UNPKG

snakeskin

Version:

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

274 lines (215 loc) 5.82 kB
(() => { Snakeskin.addDirective( 'attr', { placement: 'template', notEmpty: true, text: true }, function (command) { this.startInlineDir(); if (this.isReady()) { let str = '', groups = this.splitAttrsGroup(command); for (let i = -1; ++i < groups.length;) { let el = groups[i]; str += this.returnAttrDecl( el.attr, el.group, el.separator ); } this.append(str); } } ); var escapeEqRgxp = /===|==|([\\]+)=/g, escapeOrRgxp = /\|\||([\\]+)\|/g; var unEscapeEqRgxp = /__SNAKESKIN_EQ__(\d+)_(\d+)_/g, unEscapeOrRgxp = /__SNAKESKIN_OR__(\d+)_(\d+)_/g; function escapeEq(sstr, $1) { if ($1 && $1.length % 2 === 0) { return sstr; } return `__SNAKESKIN_EQ__${sstr.split('=').length}_${$1.length}_`; } function escapeOr(sstr, $1) { if ($1 && $1.length % 2 === 0) { return sstr; } return `__SNAKESKIN_OR__${sstr.split('|').length}_${$1.length}_`; } function unEscapeEq(ignore, $1, $2) { return new Array(Number($2)).join('\\') + new Array(Number($1)).join('='); } function unEscapeOr(ignore, $1, $2) { return new Array(Number($2)).join('\\') + new Array(Number($1)).join('|'); } /** * Вернуть строку декларации XML атрибутов * * @param {string} str - исходная строка * @param {?string=} [opt_group] - название группы * @param {?string=} [opt_separator='-'] - разделитель группы * @param {?boolean=} [opt_classLink=false] - если true, то значения для атрибута class * будут сохраняться во временную переменную * * @return {string} */ DirObj.prototype.returnAttrDecl = function (str, opt_group, opt_separator, opt_classLink) { var rAttr = this.attr, rEscape = this.attrEscape; this.attr = true; this.attrEscape = true; opt_group = opt_group || ''; opt_separator = opt_separator || '-'; str = str .replace(escapeHTMLRgxp, escapeHTML) .replace(escapeOrRgxp, escapeOr); var parts = str.split('|'), res = '', ref = this.bemRef; var s = ADV_LEFT_BLOCK + LEFT_BLOCK, e = RIGHT_BLOCK; for (let i = -1; ++i < parts.length;) { parts[i] = parts[i] .replace(unEscapeOrRgxp, unEscapeOr) .replace(escapeEqRgxp, escapeEq); let arg = parts[i].split('='), empty = arg.length !== 2; if (empty) { if (this.doctype === 'xml') { arg[1] = arg[0]; empty = false; } else { arg[1] = ''; } } arg[0] = arg[0].trim().replace(unEscapeEqRgxp, unEscapeEq); arg[1] = arg[1].trim().replace(unEscapeEqRgxp, unEscapeEq); res += /* cbws */` var __ATTR_STR__ = \'\', __ATTR_J__ = 0; `; if (opt_group) { arg[0] = opt_group + opt_separator + arg[0]; } else { arg[0] = arg[0].charAt(0) === '-' ? `data-${arg[0].slice(1)}` : arg[0]; } arg[0] = `'${this.pasteTplVarBlocks(arg[0])}'`; let vals = splitBySpace(arg[1]); for (let j = -1; ++j < vals.length;) { let val = vals[j].trim(); if (parentLinkRgxp.test(val) && ref) { val = `${s}'${ref}'${FILTER}${this.bemFilter} '${val.substring('&amp;'.length)}',$0${e}`; val = this.pasteDangerBlocks(this.replaceTplVars(val)); } val = `'${this.pasteTplVarBlocks(val)}'`; res += /* cbws */` if ((${val}) != null && (${val}) !== '') { __ATTR_STR__ += __ATTR_J__ ? ' ' + ${val} : ${val}; __ATTR_J__++; } `; } res += `if ((${arg[0]}) != null && (${arg[0]}) != '') {`; let tmp = /* cbws */` if (__NODE__) { __NODE__.setAttribute(${arg[0]}, ${empty} ? ${arg[0]} : __ATTR_STR__ ); } else { ${this.wrap(`' ' + ${arg[0]} + (${empty} ? '' : '="' + __ATTR_STR__ + '"')`)} } `; if (opt_classLink) { res += /* cbws */` if (__ATTR_TMP__[(${arg[0]})] != null) { __ATTR_TMP__[(${arg[0]})] += __ATTR_STR__; } else { ${tmp} } `; } else { res += tmp; } res += '}'; } this.attr = rAttr; this.attrEscape = rEscape; return res; }; /** * Разбить строку декларации атрибута на группы * * @param {string} str - исходная строка * @return {!Array} */ DirObj.prototype.splitAttrsGroup = function (str) { var rAttr = this.attr, rEscape = this.attrEscape; this.attr = true; this.attrEscape = true; str = this.replaceTplVars(str, false, true); var groups = []; var group = '', attr = '', sep = ''; var pOpen = 0; var separator = { '-': true, ':': true, '_': true }; for (let i = -1; ++i < str.length;) { let el = str.charAt(i), next = str.charAt(i + 1); if (!pOpen) { if (separator[el] && next === '(') { pOpen++; i++; sep = el; continue; } if (el === '(') { pOpen++; sep = ''; continue; } } if (pOpen) { if (el === '(') { pOpen++; } else if (el === ')') { pOpen--; if (!pOpen) { groups.push({ group: Snakeskin.Filters.html(group, true).trim(), separator: sep, attr: attr.trim() }); group = ''; attr = ''; sep = ''; i++; continue; } } } if (!pOpen) { group += el; } else { attr += el; } } if (group && !attr) { groups.push({ group: null, separator: null, attr: group.trim() }); } this.attr = rAttr; this.attrEscape = rEscape; return groups; }; })();