nornj
Version:
A powerful template engine that can works with React, JSX enhancement or alternative tools.
480 lines (380 loc) • 16.3 kB
JavaScript
;
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.compileStringTmpl = compileStringTmpl;
var _core = _interopRequireDefault(require("../core"));
var tools = _interopRequireWildcard(require("../utils/tools"));
var tranElem = _interopRequireWildcard(require("../transforms/transformElement"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
var preAsts = _core["default"].preAsts;
var SPLIT_FLAG = '_njParam';
var TEXT_CONTENT = ['style', 'script', 'textarea', 'xmp', _core["default"].textTag];
var OMITTED_CLOSE_TAGS = tranElem.OMITTED_CLOSE_TAGS; //Compile string template
function compileStringTmpl(tmpl) {
var tmplKey = tmpl.toString(); //Get unique key
var ret = preAsts[tmplKey];
var outputH = this.outputH,
tmplRule = this.tmplRule,
onlyParse = this.onlyParse,
fileName = this.fileName,
isExpression = this.isExpression,
isCss = this.isCss;
if (!ret) {
//If the cache already has template data, direct return the template.
var isStr = tools.isString(tmpl),
xmls = isStr ? [tmpl] : tmpl,
l = xmls.length;
var fullXml = '',
isInBrace = false; //Connection xml string
tools.each(xmls, function (xml, i) {
var split = '';
if (i == 0) {
if (isExpression) {
xml = (outputH ? tmplRule.firstChar : '') + tmplRule.startRule + ' ' + xml;
} else if (isCss) {
xml = '<' + tmplRule.extensionRule + 'css style="' + xml;
}
}
if (i < l - 1) {
var last = xml.length - 1,
lastChar = xml[last],
lastChar3 = xml.substr(last - 2),
isAccessor = lastChar === '#',
isSpread = lastChar3 === '...';
if (isInBrace) {
isInBrace = !tmplRule['incompleteEnd' + (isInBrace === 'isR' ? 'R' : '')].test(xml);
}
if (!isInBrace) {
if (tmplRule.incompleteStartR.test(xml)) {
isInBrace = 'isR';
} else {
isInBrace = tmplRule.incompleteStart.test(xml);
}
}
if (isAccessor) {
xml = xml.substr(0, last);
} else if (isSpread) {
xml = xml.substr(0, last - 2);
}
split = (isAccessor ? '#' : isSpread ? '...' : '') + SPLIT_FLAG + i;
if (!isInBrace) {
split = tmplRule.startRule + split + tmplRule.endRule;
}
}
if (i == l - 1) {
if (isExpression) {
xml += ' ' + tmplRule.endRule + (outputH ? tmplRule.lastChar : '');
} else if (isCss) {
xml += '" />';
}
}
fullXml += xml + split;
}, true); //Merge all include tags
var includeParser = _core["default"].includeParser;
if (includeParser) {
fullXml = includeParser(fullXml, fileName, tmplRule);
}
fullXml = _formatAll(fullXml, tmplRule);
if (!outputH) {
if (_core["default"].textMode) {
fullXml = '<' + _core["default"].textTag + '>' + fullXml + '</' + _core["default"].textTag + '>';
}
if (_core["default"].noWsMode) {
fullXml = '<' + _core["default"].noWsTag + '>' + fullXml + '</' + _core["default"].noWsTag + '>';
}
} //Resolve string to element
ret = _checkStringElem(fullXml, tmplRule, outputH);
tools.defineProp(ret, '_njParamCount', {
value: l - 1
}); //Save to the cache
preAsts[tmplKey] = ret;
}
var tmplFn;
if (!onlyParse) {
var params;
var args = arguments,
paramCount = ret._njParamCount;
if (paramCount > 0) {
params = {};
tools.defineProp(params, '_njParam', {
value: true
});
for (var i = 0; i < paramCount; i++) {
params[SPLIT_FLAG + i] = args[i + 1];
}
}
tmplFn = params ? function () {
return tmplMainFn.apply(this, tools.arrayPush([params], arguments));
} : function () {
return tmplMainFn.apply(this, arguments);
};
tools.defineProps(tmplFn, {
_njTmpl: {
value: ret
},
_njTmplKey: {
value: tmplKey
}
});
var tmplMainFn = _core["default"]['compile' + (outputH ? 'H' : '')](tmplFn, tmplKey, null, null, tmplRule);
} else {
tmplFn = {
_njTmpl: ret,
_njTmplKey: tmplKey
};
}
return tmplFn;
}
function _createCurrent(elemName, parent) {
var current = {
elem: [],
elemName: elemName,
parent: parent
};
parent.elem.push(current.elem);
return current;
}
function _setTextAfter(textAfter, current) {
textAfter && textAfter !== '' && _setText(textAfter, current.elem);
} //Resolve string to element
function _checkStringElem(xml, tmplRule, outputH) {
var root = [],
pattern = tmplRule.checkElem;
var current = {
elem: root,
elemName: 'root',
parent: null
},
parent = null,
matchArr,
inTextContent,
omittedCloseElem = null;
while (matchArr = pattern.exec(xml)) {
var textBefore = matchArr[1],
elem = matchArr[2],
elemName = matchArr[3],
elemParams = matchArr[4];
var textAfter = matchArr[5]; //处理上一次循环中的可省略闭合标签
if (omittedCloseElem) {
var _omittedCloseElem = omittedCloseElem,
_omittedCloseElem2 = _slicedToArray(_omittedCloseElem, 4),
_elem = _omittedCloseElem2[0],
_elemName = _omittedCloseElem2[1],
_elemParams = _omittedCloseElem2[2],
_textAfter = _omittedCloseElem2[3];
var isEx = elem ? tranElem.isExAll(elemName, tmplRule) : false;
if (isEx && !isEx[1] && (tranElem.isPropS(elemName, tmplRule) || tranElem.isStrPropS(elemName, tmplRule) || tranElem.isParamsEx(isEx[3]) || tranElem.exCompileConfig(isEx[3]).isDirective)) {
parent = current;
current = _createCurrent(_elemName, parent);
_setElem(_elem, _elemName, _elemParams, current.elem, null, tmplRule, outputH);
} else {
_setSelfCloseElem(_elem, _elemName, _elemParams, current.elem, tmplRule, outputH);
}
_setTextAfter(_textAfter, current);
omittedCloseElem = null;
} //Text before tag
if (textBefore && textBefore !== '') {
_setText(textBefore, current.elem);
} //Element tag
if (elem) {
if (elem !== '<') {
if (elem.indexOf('<!') === 0) {
//一些特殊标签当做文本处理
_setText(elem, current.elem);
} else {
var _isEx = tranElem.isExAll(elemName, tmplRule);
if (elemName[0] === '/') {
//Close tag
if (elemName.substr(1).toLowerCase() === inTextContent) {
//取消纯文本子节点标记
inTextContent = null;
}
if (_isEx || !inTextContent) {
var cName = current.elemName;
if (cName.indexOf(SPLIT_FLAG) < 0 ? elemName === '/' + cName : elemName.indexOf(SPLIT_FLAG) > -1 || elemName === '//') {
//如果开始标签包含SPLIT_FLAG,则只要结束标签包含SPLIT_FLAG就认为该标签已关闭
current = current.parent;
}
} else {
_setText(elem, current.elem);
}
} else if (elem[elem.length - 2] === '/') {
//Self close tag
if (_isEx || !inTextContent) {
_setSelfCloseElem(elem, elemName, elemParams, current.elem, tmplRule, outputH);
} else {
_setText(elem, current.elem);
}
} else {
//Open tag
if (_isEx || !inTextContent) {
if (!inTextContent && OMITTED_CLOSE_TAGS[elemName.toLowerCase()]) {
//img等可不闭合标签
omittedCloseElem = [elem, elemName, elemParams, textAfter];
} else {
var elemNameL = elemName.toLowerCase();
if (TEXT_CONTENT.indexOf(elemNameL) > -1) {
//标记该标签为纯文本子节点
inTextContent = elemNameL;
}
parent = current;
current = _createCurrent(elemName, parent);
_setElem(elem, elemName, elemParams, current.elem, null, tmplRule, outputH);
}
} else {
_setText(elem, current.elem);
}
}
}
} else {
//单独的"<"和后面的文本拼合在一起
if (textAfter == null) {
textAfter = '';
}
textAfter = elem + textAfter;
}
} //Text after tag
!omittedCloseElem && _setTextAfter(textAfter, current);
} //处理最后一次循环中遗留的可省略闭合标签
if (omittedCloseElem) {
var _omittedCloseElem3 = omittedCloseElem,
_omittedCloseElem4 = _slicedToArray(_omittedCloseElem3, 4),
_elem2 = _omittedCloseElem4[0],
_elemName2 = _omittedCloseElem4[1],
_elemParams2 = _omittedCloseElem4[2],
_textAfter2 = _omittedCloseElem4[3];
_setSelfCloseElem(_elem2, _elemName2, _elemParams2, current.elem, tmplRule, outputH);
_setTextAfter(_textAfter2, current);
}
return root;
}
var LT_GT_LOOKUP = {
'<': '_njLt_',
'>': '_njGt_'
};
var REGEX_LT_GT = />|</g;
function _formatAll(str, tmplRule) {
var commentRule = tmplRule.commentRule;
return str.replace(new RegExp('<!--' + commentRule + '[\\s\\S]*?' + commentRule + '-->', 'g'), '').replace(new RegExp('([\\s]+:[^\\s=>]+=((\'[^\']+\')|("[^"]+")))|(' + tmplRule.braceParamStr + ')', 'g'), function (all, g1, g2, g3, g4, g5) {
return (g1 ? g1 : g5).replace(REGEX_LT_GT, function (match) {
return LT_GT_LOOKUP[match];
});
});
}
function _transformToEx(isStr, elemName, elemParams, tmplRule) {
return tmplRule.extensionRule + (isStr ? 'strProp' : 'prop') + ' ' + tmplRule.startRule + "'" + elemName.substr((isStr ? tmplRule.strPropRule.length : 0) + tmplRule.propRule.length) + "'" + tmplRule.endRule + elemParams;
} //Set element node
function _setElem(elem, elemName, elemParams, elemArr, bySelfClose, tmplRule, outputH) {
var ret, paramsEx;
var fixedExTagName = tranElem.fixExTagName(elemName, tmplRule);
if (fixedExTagName) {
elemName = fixedExTagName;
}
if (tranElem.isEx(elemName, tmplRule, true)) {
ret = elem.substring(1, elem.length - 1);
if (fixedExTagName) {
ret = tmplRule.extensionRule + tools.lowerFirst(ret);
}
var retS = _getSplitParams(ret, tmplRule, outputH);
ret = retS.elem;
paramsEx = retS.params;
} else if (tranElem.isStrPropS(elemName, tmplRule)) {
ret = _transformToEx(true, elemName, elemParams, tmplRule);
} else if (tranElem.isPropS(elemName, tmplRule)) {
ret = _transformToEx(false, elemName, elemParams, tmplRule);
} else {
var _retS = _getSplitParams(elem, tmplRule, outputH);
ret = _retS.elem;
paramsEx = _retS.params;
}
if (bySelfClose) {
var retC = [ret];
if (paramsEx) {
retC.push(paramsEx);
}
elemArr.push(retC);
} else {
elemArr.push(ret);
if (paramsEx) {
elemArr.push(paramsEx);
}
}
}
var REGEX_EX_ATTR = /([^\s-$.]+)(([$.][^\s-$.]+)*)((-[^\s-$.]+([$.][^\s-$.]+)*)*)/; //Extract split parameters
function _getSplitParams(elem, tmplRule, outputH) {
var extensionRule = tmplRule.extensionRule,
startRule = tmplRule.startRule,
endRule = tmplRule.endRule,
firstChar = tmplRule.firstChar,
lastChar = tmplRule.lastChar,
spreadProp = tmplRule.spreadProp,
directives = tmplRule.directives;
var paramsEx; //Replace the parameter like "{...props}".
elem = elem.replace(spreadProp, function (all, g1, propR, g3, prop) {
if (propR) {
prop = propR;
}
if (!paramsEx) {
paramsEx = [extensionRule + 'props'];
}
paramsEx.push([extensionRule + 'spread ' + (propR ? firstChar : '') + startRule + prop.replace(/\.\.\./, '') + endRule + (propR ? lastChar : '') + '/']);
return ' ';
}); //Replace the parameter like "#show={false}".
elem = elem.replace(directives, function (all, g1, g2, g3, g4, g5, g6, key, hasColon, hasEx, name, hasEqual, value) {
if (hasEx == null) {
return all;
}
if (!paramsEx) {
paramsEx = [extensionRule + 'props'];
}
var args, modifiers;
name = name.replace(REGEX_EX_ATTR, function (all, name, modifier, g3, arg) {
if (arg) {
args = arg.substr(1).split('-').map(function (item) {
var argStr;
var modifierStr = '';
var strs = item.split(/[$.]/);
strs.forEach(function (str, i) {
if (i == 0) {
argStr = "name:'".concat(str, "'") + (i < strs.length - 1 ? ',' : '');
} else {
modifierStr += "'".concat(str, "'") + (i < strs.length - 1 ? ',' : '');
}
});
return '{' + argStr + (modifierStr != '' ? 'modifiers:[' + modifierStr + ']' : '') + '}';
});
}
if (modifier) {
modifiers = modifier.substr(1).split(/[$.]/).map(function (item) {
return "'".concat(item, "'");
});
}
return name;
});
var exPreAst = [extensionRule + name + ' _njIsDirective' + (args ? ' arguments="' + firstChar + startRule + '[' + args.join(',') + ']' + endRule + lastChar + '"' : '') + (modifiers ? ' modifiers="' + startRule + '[' + modifiers.join(',') + ']' + endRule + '"' : '') + (hasEqual ? '' : ' /')];
hasEqual && exPreAst.push((hasColon ? (outputH ? firstChar : '') + startRule + ' ' : '') + tools.clearQuot(value) + (hasColon ? ' ' + endRule + (outputH ? lastChar : '') : ''));
paramsEx.push(exPreAst);
return ' ';
});
return {
elem: elem,
params: paramsEx
};
} //Set self close element node
function _setSelfCloseElem(elem, elemName, elemParams, elemArr, tmplRule, outputH) {
if (/\/$/.test(elemName)) {
elemName = elemName.substr(0, elemName.length - 1);
}
_setElem(elem, elemName, elemParams, elemArr, true, tmplRule, outputH);
} //Set text node
function _setText(text, elemArr) {
elemArr.push(text);
}