UNPKG

snakeskin

Version:

Компилятор блочных шаблонов c поддержкой наследования.

337 lines (262 loc) 6.37 kB
var emptyCommandParamsRgxp = /^([^\s]+?\(|\()/; Snakeskin.addDirective( 'tag', { block: true, placement: 'template', text: true, replacers: { '<': (cmd) => cmd.replace('<', 'tag '), '/<': (cmd) => cmd.replace('\/<', 'end tag') } }, function (command) { this.startDir(null, { bemRef: this.bemRef }); if (!this.tolerateWhitespace) { this.skipSpace = true; } if (this.isReady()) { if (command) { command = command.replace(emptyCommandParamsRgxp, 'div $1'); } else { command = 'div'; } let parts = splitBySpace(command), desc = this.returnTagDesc(parts[0]); let params = this.structure.params; params.tag = desc.tag; params.block = inlineTagMap[desc.tag] !== void 0 ? !inlineTagMap[desc.tag] : !desc.inline; let groups = this.splitAttrsGroup(parts.slice(1).join(' ')), dom = !this.domComment && this.renderMode === 'dom'; let str = /* cbws */` var __ATTR_TMP__ = { 'class': '' }; `; if (dom) { str += /* cbws */` $0 = __NODE__ = document.createElement('${desc.tag}'); `; } else { str += this.wrap(`'<${desc.tag}'`); } for (let i = -1; ++i < groups.length;) { let el = groups[i]; str += this.returnAttrDecl(el.attr, el.group, el.separator, true); } if (desc.id) { if (dom) { str += `__NODE__.id = '${desc.id}';`; } else { str += this.wrap(`' id="${desc.id}"'`); } } if (desc.classes.length) { str += /* cbws */` __ATTR_TMP__['class'] += (__ATTR_TMP__['class'] ? ' ' : '') + '${desc.classes.join(' ')}'; `; } if (dom) { str += /* cbws */` if (__ATTR_TMP__['class']) { __NODE__.className = __ATTR_TMP__['class']; } ${this.returnPushNodeDecl(!params.block)} `; } else { str += this.wrap(/* cbws */` (__ATTR_TMP__['class'] ? ' class="' + __ATTR_TMP__['class'] + '"' : '') + '${ !params.block && this.doctype === 'xml' ? '/' : '' }>' `); } this.append(str); } }, function () { var params = this.structure.params; this.bemRef = params.bemRef; this.prevSpace = false; if (params.block) { let str; if (!this.domComment && this.renderMode === 'dom') { str = ` __RESULT__.pop(); $0 = __RESULT__.length > 1 ? __RESULT__[__RESULT__.length - 1] : void 0; `; } else { str = this.wrap(`'</${params.tag}>'`); } this.append(str); } } ); var parentLinkRgxp = /^&/; /** * Анализировать заданную строку декларации тега * и вернуть объект-описание * * @param {string} str - исходная строка * @return {{tag: string, id: string, classes: !Array, pseudo: !Array, inline: boolean}} */ DirObj.prototype.returnTagDesc = function (str) { str = this.replaceTplVars(str, false, true); var points = [], types = [], action = ''; var tag = '', id = '', inline = false; var hasId = false; var pseudo = [], classes = []; var s = ADV_LEFT_BLOCK + LEFT_BLOCK, e = RIGHT_BLOCK; var bOpen = 0, bStart = false; var bMap = { '[': true, ']': true }; var sys = { '#': true, '.': true, ':': true }; var error = { tag: '', id: '', classes: [], pseudo: [], inline: false }; for (let i = -1; ++i < str.length;) { let el = str.charAt(i); if (bMap[el]) { if (el === '[') { bOpen++; bStart = true; } else { bOpen--; } continue; } if (bStart && el !== '.') { this.error('invalid syntax'); return error; } else { bStart = false; } if (sys[el] && (el !== '#' || !bOpen)) { if (el === '#') { if (hasId) { this.error('invalid syntax'); return error; } hasId = true; } tag = tag || 'div'; action = el; if (el === '.') { // Обработка липких ссылок if (bOpen) { if (points.length) { for (let j = points.length; j--;) { let point = points[j]; if (point) { if (point.stage < bOpen) { let tmp = classes[j], pos = point.from; if (point.val != null) { tmp = tmp.replace(parentLinkRgxp, point.val) } while (points[pos] != null) { let parent = points[pos]; tmp = tmp.replace(parentLinkRgxp, parent.val); pos = parent.from; } points.push({ stage: bOpen, val: tmp, from: j }); break; } } else { points.push({ stage: bOpen, val: classes[j], from: j }); break; } } } else { points.push({ stage: bOpen, val: null, from: null }); } } else { points.push(null); } types.push(!bOpen); classes.push(''); } else if (el === ':') { if (!inline) { inline = pseudo[pseudo.length - 1] === 'inline'; } pseudo.push(''); } continue; } switch (action) { case '#': id += el; break; case '.': classes[classes.length - 1] += el; break; case ':': pseudo[pseudo.length - 1] += el; break; default: tag += el; } } if (bOpen) { this.error('invalid syntax'); return error; } var ref = this.bemRef; for (let i = -1; ++i < classes.length;) { let el = classes[i], point = points[i]; if (point && point.val != null) { el = el.replace(parentLinkRgxp, point.val); } if (parentLinkRgxp.test(el) && ref) { el = `${s}'${ref}'${FILTER}${this.bemFilter} '${el.substring(1)}',$0${e}`; el = this.pasteDangerBlocks(this.replaceTplVars(el)); } else if (el && types[i]) { ref = this.pasteTplVarBlocks(el); } classes[i] = this.pasteTplVarBlocks(el); } this.bemRef = ref; if (!inline) { inline = pseudo[pseudo.length - 1] === 'inline'; } return { tag: this.pasteTplVarBlocks(tag), id: this.pasteTplVarBlocks(id), classes: classes, pseudo: pseudo, inline: inline }; };