UNPKG

nornj

Version:

A powerful template engine that can works with React, JSX enhancement or alternative tools.

2,031 lines (1,740 loc) 104 kB
/*! * NornJ template engine v5.3.5 * (c) Joe_Sky * Released under the MIT License. */ var nj = function nj() { return nj['taggedTmpl' + (nj.outputH ? 'H' : '')].apply(null, arguments); }; nj.preAsts = {}; nj.asts = {}; nj.templates = {}; nj.errorTitle = '[NornJ]'; nj.tmplRule = {}; nj.outputH = false; nj.global = typeof self !== 'undefined' ? self : global; nj.textTag = 'nj-text'; nj.textMode = false; nj.noWsTag = 'nj-noWs'; nj.noWsMode = false; nj.fixTagName = true; function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; }; } else { _typeof = function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } 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 _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } var nativeArrayPush = Array.prototype.push, nativeArraySlice = Array.prototype.slice, hasOwnProperty = Object.prototype.hasOwnProperty, toString = Object.prototype.toString; var errorTitle = nj.errorTitle; var defineProp = Object.defineProperty; var defineProps = Object.defineProperties; // Internal function for creating a toString-based type tester. function _tagTester(name) { return function (obj) { return toString.call(obj) === '[object ' + name + ']'; }; } //Reference by underscore var isNumber = _tagTester('Number'); var isString = _tagTester('String'); var isMap = _tagTester('Map'); var isWeakMap = _tagTester('WeakMap'); var isSet = _tagTester('Set'); var isWeakSet = _tagTester('WeakSet'); //Push one by one to array function arrayPush(arr1, arr2) { nativeArrayPush.apply(arr1, arr2); return arr1; } function arraySlice(arrLike, start, end) { return nativeArraySlice.call(arrLike, start, end); } function isArray(obj) { return Array.isArray(obj); } function isObject(obj) { var type = _typeof(obj); return !isArray(obj) && (type === 'function' || type === 'object' && !!obj); } function _getProperty(key) { return function (obj) { return obj == null ? void 0 : obj[key]; }; } var _getLength = _getProperty('length'); function isArrayLike(obj) { var length = _getLength(obj); return typeof length == 'number' && length >= 0; } function _iteratorLoop(obj, func, isMap) { var size = obj.size; var i = 0; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = obj[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var item = _step.value; var ret = void 0; if (isMap) { var _item = _slicedToArray(item, 2), k = _item[0], v = _item[1]; ret = func.call(obj, v, k, i, size); } else { ret = func.call(obj, item, i, size); } if (ret === false) { break; } i++; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator["return"] != null) { _iterator["return"](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } function each(obj, func, isArr) { if (!obj) { return; } if (isArr == null) { isArr = isArrayLike(obj); } if (isArr) { for (var i = 0, l = obj.length; i < l; i++) { var ret = func.call(obj, obj[i], i, l); if (ret === false) { break; } } } else if (isSet(obj) || isWeakSet(obj)) { _iteratorLoop(obj, func); } else if (isMap(obj) || isWeakMap(obj)) { _iteratorLoop(obj, func, true); } else { var keys = Object.keys(obj), _l = keys.length; for (var _i = 0; _i < _l; _i++) { var k = keys[_i], _ret = func.call(obj, obj[k], k, _i, _l); if (_ret === false) { break; } } } } var REGEX_TRIM_RIGHT = /(\n|\r)?[\s\xA0]+$/; function trimRight(str) { return str.replace(REGEX_TRIM_RIGHT, function (all, s1) { return s1 ? '\n' : ''; }); } function noop() {} function throwIf(val, msg, type) { if (!val) { switch (type) { case 'ex': throw Error(errorTitle + 'Extension tag "' + msg + '" is undefined, please check it has been registered.'); default: throw Error(errorTitle + (msg || val)); } } } function warn(msg, type) { switch (type) { case 'f': msg = 'A filter called "' + msg + '" is undefined.'; break; } console.warn(errorTitle + msg); } function error(msg) { console.error(errorTitle + msg); } //create light weight object function obj() { return Object.create(null); } var REGEX_QUOT_D = /["]+/g, REGEX_QUOT_S = /[']+/g; function clearQuot(value, clearDouble) { if (value == null) { return; } var regex; if (clearDouble == null) { var charF = value[0]; if (charF === "'") { regex = REGEX_QUOT_S; } else if (charF === '"') { regex = REGEX_QUOT_D; } } else if (clearDouble) { regex = REGEX_QUOT_D; } else { regex = REGEX_QUOT_S; } if (regex) { value = value.replace(regex, ''); } return value; } function camelCase(str) { if (str.indexOf('-') > -1) { str = str.replace(/-\w/g, function (letter) { return letter.substr(1).toUpperCase(); }); } return str; } //Reference by babel-external-helpers var assign = Object.assign || function (target) { for (var i = 1, args = arguments; i < args.length; i++) { var source = args[i]; for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function upperFirst(str) { return str[0].toUpperCase() + str.substr(1); } function lowerFirst(str) { return str[0].toLowerCase() + str.substr(1); } function capitalize(str) { return upperFirst(str); } function as(value) { return value; } assign(nj, { defineProp: defineProp, defineProps: defineProps, arrayPush: arrayPush, arraySlice: arraySlice, isArray: isArray, isObject: isObject, isNumber: isNumber, isString: isString, isArrayLike: isArrayLike, isMap: isMap, isWeakMap: isWeakMap, isSet: isSet, isWeakSet: isWeakSet, each: each, noop: noop, throwIf: throwIf, warn: warn, obj: obj, camelCase: camelCase, assign: assign, upperFirst: upperFirst, lowerFirst: lowerFirst, capitalize: capitalize, as: as }); var tools = /*#__PURE__*/Object.freeze({ __proto__: null, defineProp: defineProp, defineProps: defineProps, isNumber: isNumber, isString: isString, isMap: isMap, isWeakMap: isWeakMap, isSet: isSet, isWeakSet: isWeakSet, arrayPush: arrayPush, arraySlice: arraySlice, isArray: isArray, isObject: isObject, isArrayLike: isArrayLike, each: each, trimRight: trimRight, noop: noop, throwIf: throwIf, warn: warn, error: error, obj: obj, clearQuot: clearQuot, camelCase: camelCase, assign: assign, upperFirst: upperFirst, lowerFirst: lowerFirst, capitalize: capitalize, as: as }); function _createRegExp(reg, mode) { return new RegExp(reg, mode); } //Clear the repeated characters function _clearRepeat(str) { var ret = '', i = 0, _char; var l = str.length; for (; i < l; i++) { _char = str[i]; if (ret.indexOf(_char) < 0) { ret += _char; } } return ret; } function _replace$(str) { return str.replace(/\$/g, '\\$'); } function _replaceMinus(str) { return str.replace(/-/g, '\\-'); } function _replaceMulti(str) { return str.replace(/\*/g, '\\*'); } function createTmplRule() { var rules = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var isGlobal = arguments.length > 1 ? arguments[1] : undefined; var _nj$tmplRule = nj.tmplRule, _nj$tmplRule$startRul = _nj$tmplRule.startRule, startRule = _nj$tmplRule$startRul === void 0 ? '{{' : _nj$tmplRule$startRul, _nj$tmplRule$endRule = _nj$tmplRule.endRule, endRule = _nj$tmplRule$endRule === void 0 ? '}}' : _nj$tmplRule$endRule, _nj$tmplRule$extensio = _nj$tmplRule.extensionRule, extensionRule = _nj$tmplRule$extensio === void 0 ? 'n-' : _nj$tmplRule$extensio, _nj$tmplRule$propRule = _nj$tmplRule.propRule, propRule = _nj$tmplRule$propRule === void 0 ? 'p-' : _nj$tmplRule$propRule, _nj$tmplRule$strPropR = _nj$tmplRule.strPropRule, strPropRule = _nj$tmplRule$strPropR === void 0 ? 's' : _nj$tmplRule$strPropR, _nj$tmplRule$template = _nj$tmplRule.templateRule, templateRule = _nj$tmplRule$template === void 0 ? 'template' : _nj$tmplRule$template, _nj$tmplRule$tagSpRul = _nj$tmplRule.tagSpRule, tagSpRule = _nj$tmplRule$tagSpRul === void 0 ? '#$@' : _nj$tmplRule$tagSpRul, _nj$tmplRule$commentR = _nj$tmplRule.commentRule, commentRule = _nj$tmplRule$commentR === void 0 ? '-' : _nj$tmplRule$commentR; var start = rules.start, end = rules.end, extension = rules.extension, prop = rules.prop, strProp = rules.strProp, template = rules.template, tagSp = rules.tagSp, comment = rules.comment, rawStart = rules.rawStart, rawEnd = rules.rawEnd; if (start) { startRule = start; } if (end) { endRule = end; } if (extension) { extensionRule = extension; } if (prop) { propRule = prop; } if (strProp) { strPropRule = strProp; } if (template) { templateRule = template; } if (tagSp) { tagSpRule = tagSp; } if (comment != null) { commentRule = comment; } var firstChar = rawStart != null ? rawStart : startRule[0], lastChar = rawEnd != null ? rawEnd : endRule[endRule.length - 1], extensionRules = _replaceMinus(_clearRepeat(extensionRule + propRule + strPropRule + tagSpRule)), escapeExtensionRule = _replace$(extensionRule), escapePropRule = _replace$(propRule), escapeStrPropRule = _replace$(strPropRule), startRuleR = firstChar + startRule, endRuleR = endRule + lastChar, varContent = '[\\s\\S]+?', varContentS = '\\.\\.\\.' + varContent, braceParamStr = _replaceMulti(startRuleR + varContent + endRuleR + '|' + startRule + varContent + endRule), escapeStartRule = _replaceMulti(startRule), escapeEndRule = _replaceMulti(endRule), escapeStartRuleR = _replaceMulti(startRuleR), escapeEndRuleR = _replaceMulti(endRuleR); var tmplRules = { startRule: startRule, endRule: endRule, extensionRule: extensionRule, propRule: propRule, strPropRule: strPropRule, templateRule: templateRule, tagSpRule: tagSpRule, commentRule: commentRule, firstChar: firstChar, lastChar: lastChar, braceParamStr: braceParamStr, xmlOpenTag: _createRegExp('^<([a-z' + firstChar + extensionRules + '][^\\s>]*)[^>]*>$', 'i'), openTagParams: _createRegExp('[\\s]+(((' + escapeStartRuleR + '(' + varContent + ')' + escapeEndRuleR + ')|(' + escapeStartRule + '(' + varContent + ')' + escapeEndRule + '))|[^\\s=>]+)(=((\'[^\']+\')|("[^"]+")|([^"\'\\s]+)))?', 'g'), directives: _createRegExp('[\\s]+(((' + escapeStartRuleR + '(' + varContent + ')' + escapeEndRuleR + ')|(' + escapeStartRule + '(' + varContent + ')' + escapeEndRule + '))|((:?)(' + escapeExtensionRule + ')?([^\\s=>]+)))(=((\'[^\']+\')|("[^"]+")|([^"\'\\s>]+)))?', 'g'), braceParam: _createRegExp(braceParamStr, 'i'), braceParamG: _createRegExp(braceParamStr, 'ig'), spreadProp: _createRegExp('[\\s]+(' + escapeStartRuleR + '[\\s]*(' + varContentS + ')' + escapeEndRuleR + ')|(' + escapeStartRule + '[\\s]*(' + varContentS + ')' + escapeEndRule + ')', 'g'), replaceSplit: _createRegExp(braceParamStr), replaceParam: _createRegExp('((' + escapeStartRuleR + ')(' + varContent + ')' + escapeEndRuleR + ')|((' + escapeStartRule + ')(' + varContent + ')' + escapeEndRule + ')', 'g'), checkElem: _createRegExp('([^<>]+)|(<([a-z/!' + firstChar + extensionRules + '][^\\s<>]*)([^<>]*)>|<)([^<]*)', 'ig'), extension: _createRegExp('^' + escapeExtensionRule + '([^\\s]+)', 'i'), exAll: _createRegExp('^([/]?)(' + escapeExtensionRule + '|' + escapeStrPropRule + escapePropRule + '|' + escapePropRule + ')([^\\s]+)', 'i'), include: _createRegExp('<' + escapeExtensionRule + 'include([^>]*)>', 'ig'), incompleteStart: _createRegExp(startRule + '((?!' + escapeEndRule + ')[\\s\\S])*$'), incompleteStartR: _createRegExp(escapeStartRuleR + '((?!' + escapeEndRuleR + ')[\\s\\S])*$'), incompleteEnd: _createRegExp('^[\\s\\S]*?' + escapeEndRule), incompleteEndR: _createRegExp('^[\\s\\S]*?' + escapeEndRuleR) }; if (isGlobal) { //Reset the regexs to global list assign(nj.tmplRule, tmplRules); } else { return tmplRules; } } //Set global template rules createTmplRule({}, true); assign(nj, { createTmplRule: createTmplRule }); function config(configs) { var delimiters = configs.delimiters, includeParser = configs.includeParser, createElement = configs.createElement, outputH = configs.outputH, textMode = configs.textMode, noWsMode = configs.noWsMode, fixTagName = configs.fixTagName; if (delimiters) { createTmplRule(delimiters, true); } if (includeParser) { nj.includeParser = includeParser; } if (createElement) { nj.createElement = createElement; } if (outputH != null) { nj.outputH = outputH; } if (textMode != null) { nj.textMode = textMode; } if (noWsMode != null) { nj.noWsMode = noWsMode; } if (fixTagName != null) { nj.fixTagName = fixTagName; } } assign(nj, { config: config }); var ESCAPE_LOOKUP = { '&': '&amp;', '>': '&gt;', '<': '&lt;', '"': '&quot;', "'": '&#x27;' // eslint-disable-line }; var REGEX_ESCAPE = /[&><"']/g; function escape(str) { if (str == null) { return ''; } else if (!str.replace) { return str; } return str.replace(REGEX_ESCAPE, function (match) { return ESCAPE_LOOKUP[match]; }); } var UNESCAPE_LOOKUP = { nbsp: "\xA0", ensp: "\u2002", emsp: "\u2003", thinsp: "\u2009", zwnj: "\u200C", zwj: "\u200D", lt: '<', gt: '>', amp: '&', quot: '"', '#x27': "'" // eslint-disable-line }; var REGEX_UNESCAPE = new RegExp('&(' + Object.keys(UNESCAPE_LOOKUP).join('|') + ');', 'g'); function unescape(str) { if (str == null) { return ''; } else if (!str.replace) { return str; } return str.replace(REGEX_UNESCAPE, function (all, match) { return UNESCAPE_LOOKUP[match]; }); } assign(nj, { escape: escape, unescape: unescape }); var REGEX_NUM = /^(-?([0-9]+[.]?[0-9]+)|[0-9])$/; //提取style内参数 function styleProps(obj) { //If the parameter is a style object,then direct return. if (isObject(obj) || isArray(obj) || isNumber(obj)) { return obj; } //参数为字符串 var pattern = /([^\s:]+)[\s]?:[\s]?([^;]+)[;]?/g; var matchArr, ret; while (matchArr = pattern.exec(obj)) { var key = matchArr[1]; var value = matchArr[2]; if (!ret) { ret = {}; } //Convert to lowercase when style name is all capital. if (/^[A-Z-]+$/.test(key)) { key = key.toLowerCase(); } //将连字符转为驼峰命名 key = camelCase(key); ret[key] = REGEX_NUM.test(value) ? Number(value) : value; } return ret; } //Get value from multiple datas function getData(prop, data, hasSource) { var value, obj; if (!data) { data = this.data; } for (var i = 0, l = data.length; i < l; i++) { obj = data[i]; if (obj) { value = obj[prop]; if (value !== undefined) { if (hasSource) { return { source: obj, value: value, prop: prop, _njSrc: true }; } return value; } } } } function getAccessorData(fn, context) { if (fn == null) { return fn; } if (fn._njTmpl) { //模板函数 return fn.call(context); } else { //普通函数 return fn.call(context.$this, context); } } function getElement(name, global, nameO, context, subName) { var element; if (!context.icp) { element = global.cp[name]; } else { element = getData(nameO, context.icp); if (!element) { element = global.cp[name]; } } if (subName != null && element) { element = element[subName]; } return element ? element : nameO; } function getElementRefer(refer, name, global, nameO, context) { return refer != null ? isString(refer) ? getElement(refer.toLowerCase(), global, refer, context) : refer : getElement(name, global, nameO, context); } function getElementName(refer, name) { return refer != null && refer !== '' ? refer : name; } function addArgs(props, dataRefer) { var args = props.args; if (args) { for (var i = args.length; i--;) { dataRefer.unshift(args[i]); } } } //Rebuild local variables in the new context function newContext(context, params) { if (!params) { return context; } return assign({}, context, { data: params.data ? arrayPush(params.data, context.data) : context.data, parent: params.newParent ? context : context.parent, index: params.index != null ? params.index : context.index, item: params.item != null ? params.item : context.item }); } //修正属性名 function fixPropName(name) { switch (name) { case 'class': name = 'className'; break; case 'for': name = 'htmlFor'; break; } return name; } //合并字符串属性 function assignStrProps(target) { var ret = ''; for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { params[_key - 1] = arguments[_key]; } var retObj = assign.apply(tools, [target].concat(params)); for (var k in retObj) { var v = retObj[k]; ret += ' ' + k + (k !== v ? '="' + v + '"' : ' '); } return ret; } //创建扩展标签子节点函数 function exRet(global, context, fn) { return function (param) { return fn(global, context, param); }; } function _getLocalComponents(localConfigs) { var icp; if (localConfigs && localConfigs.components) { icp = localConfigs.components; if (!isArray(icp)) { icp = [icp]; } } return icp; } //构建可运行的模板函数 function tmplWrap(configs, main) { return function (param1, param2) { var ctx = this, data = arraySlice(arguments); return main(configs, ctx && ctx._njCtx ? assign({}, ctx, { data: arrayPush(data, ctx.data) }) : { data: data, getData: getData, get $this() { return this.data[this.data.length - 1]; }, d: getData, icp: _getLocalComponents(param1 && param1._njParam ? param2 : param1), _njCtx: true }); }; } function levelSpace(context) { if (context.level == null) { return ''; } var ret = ''; for (var i = 0; i < context.level; i++) { ret += ' '; } return ret; } function firstNewline(context) { return context.index == null ? '' : context.index == 0 ? '' : '\n'; } function createElementApply(p) { return nj.createElement.apply(null, p); } function callFilter(filter) { return filter.source ? filter.value.bind(filter.source) : filter; } //创建模板函数 function template(fns, tmplKey) { var configs = { tmplKey: tmplKey, us: fns.useString, x: nj.extensions, f: nj.filters, np: noop, tf: throwIf, wn: warn, n: newContext, c: getAccessorData, sp: styleProps, r: exRet, e: getElement, er: getElementRefer, en: getElementName, aa: addArgs, an: assign, g: nj.global, cf: callFilter }; if (!configs.us) { configs.h = nj.createElement; configs.H = createElementApply; configs.cp = nj.components; } else { configs.ans = assignStrProps; configs.es = nj.escape; configs.ls = levelSpace; configs.fl = firstNewline; } each(fns, function (v, k) { if (k === 'main') { //将每个主函数构建为可运行的模板函数 configs[k] = tmplWrap(configs, v); defineProps(configs[k], { _njTmpl: { value: true } }); configs['_' + k] = v; } else if (k.indexOf('fn') === 0) { //扩展标签函数 configs[k] = v; } }, false); return configs; } /** * React(or other such as Preact) components. */ /** * Properties of React(or other such as Preact) components. */ var Template; (function (_Template) {})(Template || (Template = {})); var ExtensionPrefixConfig; (function (ExtensionPrefixConfig) { ExtensionPrefixConfig["onlyLowerCase"] = "onlyLowerCase"; ExtensionPrefixConfig["onlyUpperCase"] = "onlyUpperCase"; ExtensionPrefixConfig["free"] = "free"; })(ExtensionPrefixConfig || (ExtensionPrefixConfig = {})); var extensions = { "if": function _if(value, options) { if (value && value._njOpts) { options = value; value = options.props.condition; } if (value === 'false') { value = false; } var ret; var props = options.props; if (value) { ret = (props && props.then || options.children)(); } else if (props) { var elseFn = props['else']; if (props.elseifs) { var l = props.elseifs.length; each(props.elseifs, function (elseif, i) { if (elseif.value) { ret = elseif.fn(); return false; } else if (i === l - 1) { if (elseFn) { ret = elseFn(); } } }, true); } else { if (elseFn) { ret = elseFn(); } } } if (options.useString && ret == null) { return ''; } return ret; }, then: function then(options) { return options.tagProps.then = options.children; }, "else": function _else(options) { return options.tagProps['else'] = options.children; }, elseif: function elseif(value, options) { if (value && value._njOpts) { options = value; value = options.props.condition || options.props.value; } var _options = options, tagProps = _options.tagProps; if (!tagProps.elseifs) { tagProps.elseifs = []; } tagProps.elseifs.push({ value: value, fn: options.children }); }, "switch": function _switch(value, options) { if (value && value._njOpts) { options = value; value = options.props.value; } var ret; var props = options.props, elseifs = props.elseifs || [{}], l = elseifs.length; each(elseifs, function (elseif, i) { if (value === elseif.value) { ret = elseif.fn(); return false; } else if (i === l - 1) { if (props['else']) { ret = props['else'](); } } }, true); return ret; }, each: function each$1(list, options) { if (list && list._njOpts) { options = list; list = options.props.of; } var useString = options.useString, props = options.props; var ret; if (list) { if (useString) { ret = ''; } else { ret = []; } var isArrayLike$1 = isArrayLike(list); var isArrayLoop = isArrayLike$1 || isSet(list) || isWeakSet(list); each(list, function (item, index, len, lenObj) { var param = { data: [item], index: isArrayLoop ? index : len, item: item, newParent: true }; var _len = isArrayLoop ? len : lenObj; var extra = { '@first': param.index === 0, '@last': param.index === _len - 1 }; if (!isArrayLoop) { extra['@key'] = index; } param.data.push(extra); var retI = options.children(param); if (useString) { ret += retI; } else { ret.push(retI); } }, isArrayLike$1); //Return null when not use string and result is empty. if (!useString && !ret.length) { ret = null; } if ((!ret || !ret.length) && props && props['else']) { ret = props['else'](); } } else { if (props && props['else']) { ret = props['else'](); } if (useString && ret == null) { ret = ''; } } return ret; }, //Parameter prop: function prop(name, options) { var ret = options.value(); //Get parameter value var value; if (ret !== undefined) { value = ret; } else { //Match to Similar to "checked" or "disabled" attribute. value = !options.useString ? true : name; } options.tagProps[options.outputH ? fixPropName(name) : name] = value; }, //Spread parameters spread: function spread(props, options) { var tagProps = options.tagProps; each(props, function (v, k) { tagProps[k] === undefined && (options.tagProps[k] = v); }, false); }, show: function show(options) { if (!options.value()) { var tagProps = options.tagProps, useString = options.useString; if (!tagProps.style) { tagProps.style = useString ? '' : {}; } if (useString) { tagProps.style += (tagProps.style ? ';' : '') + 'display:none'; } else if (isArray(tagProps.style)) { tagProps.style.push({ display: 'none' }); } else { tagProps.style.display = 'none'; } } }, obj: function obj(options) { return options.props; }, block: function block(options) { return options.children(); }, "with": function _with(originalData, options) { if (originalData && originalData._njOpts) { options = originalData; return options.children({ data: [options.props] }); } else { var _options2 = options, props = _options2.props; return options.children({ data: [props && props.as ? _defineProperty({}, props.as, originalData) : originalData] }); } }, arg: function arg(options) { var tagProps = options.tagProps; if (!tagProps.args) { tagProps.args = []; } tagProps.args.push(options.value()); }, css: function css(options) { return options.props.style; } }; function _config(params, extra) { var ret = { onlyGlobal: false, useString: false, newContext: true, isSubTag: false, isDirective: false, isBindable: false, useExpressionInProps: false, hasName: true, noTagName: false, hasTagProps: true, hasTmplCtx: true, hasOutputH: false }; if (params) { ret = assign(ret, params); } if (extra) { ret = assign(ret, extra); } return ret; } var _defaultCfg = { onlyGlobal: true, newContext: false, hasName: false, hasTagProps: false, hasTmplCtx: false }; var _defaultCfgExpInProps = _config(_defaultCfg, { useExpressionInProps: true }); //Extension default config var extensionConfig = { "if": _config(_defaultCfgExpInProps), "else": _config(_defaultCfgExpInProps, { isSubTag: true, hasTagProps: true }), "switch": _config(_defaultCfgExpInProps, { needPrefix: ExtensionPrefixConfig.onlyLowerCase }), each: _config(_defaultCfgExpInProps, { newContext: { item: 'item', index: 'index', data: { first: ['@first', 'first'], last: ['@last', 'last'], $key: ['@key', 'key'] } } }), prop: _config(_defaultCfg, { isDirective: true, needPrefix: true, hasTagProps: true }), obj: _config(_defaultCfg, { needPrefix: true }), "with": _config(_defaultCfg, { newContext: { getDataFromProps: true } }), style: { needPrefix: true } }; extensionConfig.then = _config(extensionConfig['else']); extensionConfig.elseif = _config(extensionConfig['else']); extensionConfig.spread = _config(extensionConfig.prop); extensionConfig.block = _config(extensionConfig.obj); extensionConfig.arg = _config(extensionConfig.prop); extensionConfig.show = _config(extensionConfig.prop, { useExpressionInProps: true, noTagName: true, hasOutputH: true }); extensionConfig.css = _config(extensionConfig.obj); //Extension alias extensions['for'] = extensions.each; extensionConfig['for'] = _config(extensionConfig.each); extensions['case'] = extensions.elseif; extensionConfig['case'] = _config(extensionConfig.elseif); extensions.empty = extensions['default'] = extensions['else']; extensionConfig.empty = _config(extensionConfig['else']); extensionConfig['default'] = _config(extensionConfig['else']); extensions.strProp = extensions.prop; extensionConfig.strProp = _config(extensionConfig.prop, { useString: true }); extensions.strArg = extensions.arg; extensionConfig.strArg = _config(extensionConfig.strProp); extensions.pre = extensions.block; extensionConfig.pre = _config(extensionConfig.block); function registerExtension(name, extension, options, mergeConfig) { var params = name; if (!isObject(name)) { params = {}; params[name] = { extension: extension, options: options }; } each(params, function (v, name) { if (v) { var _extension = v.extension, _options3 = v.options; if (_extension) { extensions[name] = _extension; } else if (!mergeConfig) { extensions[name] = v; } if (mergeConfig) { if (!extensionConfig[name]) { extensionConfig[name] = _config(); } if (isObject(_options3)) { assign(extensionConfig[name], _options3); } else { extensionConfig[name] = _config(); } } else { extensionConfig[name] = _config(_options3); } } }, false); } assign(nj, { extensions: extensions, extensionConfig: extensionConfig, registerExtension: registerExtension }); var REGEX_DIGITS_RE = /(\d{3})(?=\d)/g; //Global filter list var filters = { //Get properties '.': function _(obj, prop, callFn) { if (obj == null) { return obj; } if (obj._njSrc) { return { source: obj.value, value: obj.value[prop], prop: prop, parent: obj, _njSrc: true }; } else if (callFn) { return { source: obj, value: obj[prop], prop: prop, _njSrc: true }; } return obj[prop]; }, //Call function _: function _(fn, args) { if (fn == null) { return fn; } if (fn._njSrc) { var _fn = fn.source[fn.prop]; return _fn != null ? _fn.apply(fn.source, args) : _fn; } return fn.apply(null, args); }, //Get accessor properties '#': function _(obj, prop, options) { if (obj == null) { return obj; } return getAccessorData(obj[prop], options.context); }, '**': function _(val1, val2) { var ret = Math.pow(val1, val2); return isNaN(ret) ? 0 : ret; }, '%%': function _(val1, val2) { var ret = Math.floor(val1 / val2); return isNaN(ret) ? 0 : ret; }, //Ternary operator '?:': function _(val, val1, val2) { return val ? val1 : val2; }, '!': function _(val) { return !val; }, //Convert to int "int": function int(val) { var radix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; var ret = parseInt(val, radix); return isNaN(ret) ? 0 : ret; }, //Convert to float "float": function float(val, bit) { var ret = parseFloat(val); return isNaN(ret) ? 0 : bit != null ? ret.toFixed(bit) : ret; }, //Convert to boolean bool: function bool(val) { if (val === 'false') { return false; } return Boolean(val); }, reg: function reg(pattern, flags) { return new RegExp(pattern, flags); }, //Transform css string to object css: function css(cssText) { return styleProps(cssText); }, //Generate array by two positive integers,closed interval rOpe: _getArrayByNum(1), //Generate array by two positive integers,right open interval rLt: _getArrayByNum(0), //Compare two number or letter '<=>': function _(val1, val2) { if (val1 > val2) { return 1; } else if (val1 == val2) { return 0; } else { return -1; } }, upperFirst: function upperFirst$1(str) { return upperFirst(str); }, lowerFirst: function lowerFirst$1(str) { return lowerFirst(str); }, camelCase: function camelCase$1(str) { return camelCase(str); }, isObject: function isObject$1(val) { return isObject(val); }, isNumber: function isNumber$1(val) { return isNumber(val); }, isString: function isString$1(val) { return isString(val); }, isArrayLike: function isArrayLike$1(val) { return isArrayLike(val); }, currency: function currency(value, decimals, symbol, placeholder) { if (!(value - parseFloat(value) >= 0)) { return placeholder != null ? placeholder : filterConfig.currency.placeholder; } value = parseFloat(value); symbol = decimals != null && isString(decimals) ? decimals : symbol; symbol = symbol != null && isString(symbol) ? symbol : filterConfig.currency.symbol; decimals = decimals != null && isNumber(decimals) ? decimals : 2; var stringified = Math.abs(value).toFixed(decimals); var _int = decimals ? stringified.slice(0, -1 - decimals) : stringified; var i = _int.length % 3; var head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : ''; var _float = decimals ? stringified.slice(-1 - decimals) : ''; var sign = value < 0 ? '-' : ''; return sign + symbol + head + _int.slice(i).replace(REGEX_DIGITS_RE, '$1,') + _float; } }; function _getArrayByNum(isContainEnd) { return function (val1, val2) { return Object.keys(Array.apply(null, { length: val2 - val1 + isContainEnd })).map(function (item) { return +item + val1; }); }; } function _config$1(params, extra) { var ret = { onlyGlobal: false, hasOptions: false, isOperator: false, hasLevel: false, hasTmplCtx: true, alias: null }; if (params) { ret = assign(ret, params); } if (extra) { ret = assign(ret, extra); } return ret; } var _defaultCfg$1 = { onlyGlobal: true, hasOptions: false }; //Filter default config var filterConfig = { '.': _config$1(_defaultCfg$1), _: _config$1({ onlyGlobal: true }), '#': _config$1({ onlyGlobal: true, hasOptions: true, hasLevel: true }), '**': _config$1(_defaultCfg$1), '%%': _config$1(_defaultCfg$1), '?:': _config$1(_defaultCfg$1), '!': _config$1(_defaultCfg$1), "int": _config$1(_defaultCfg$1), "float": _config$1(_defaultCfg$1), bool: _config$1(_defaultCfg$1), reg: _config$1(_defaultCfg$1), css: _config$1(_defaultCfg$1), rOpe: _config$1(_defaultCfg$1), rLt: _config$1(_defaultCfg$1), '<=>': _config$1(_defaultCfg$1), upperFirst: _config$1(_defaultCfg$1), lowerFirst: _config$1(_defaultCfg$1), camelCase: _config$1(_defaultCfg$1), isObject: _config$1(_defaultCfg$1), isNumber: _config$1(_defaultCfg$1), isString: _config$1(_defaultCfg$1), isArrayLike: _config$1(_defaultCfg$1), currency: _config$1(_defaultCfg$1, { symbol: '$', placeholder: '' }) }; filters.capitalize = filters.upperFirst; filterConfig.capitalize = _config$1(filterConfig.upperFirst); function registerFilter(name, filter, options, mergeConfig) { var params = name; if (!isObject(name)) { params = {}; params[name] = { filter: filter, options: options }; } each(params, function (v, name) { if (v) { var _filter = v.filter, _options = v.options; if (_options) { if (_options.isOperator) { var createRegexOperators = nj.createRegexOperators; if (createRegexOperators) { createRegexOperators(name); } } var alias = _options.alias; if (alias) { var createFilterAlias = nj.createFilterAlias; if (createFilterAlias) { createFilterAlias(name, alias); } name = alias; } } if (_filter) { filters[name] = _filter; } else if (!mergeConfig) { filters[name] = v; } if (mergeConfig) { if (!filterConfig[name]) { filterConfig[name] = _config$1(); } if (isObject(_options)) { assign(filterConfig[name], _options); } else { filterConfig[name] = _config$1(); } } else { filterConfig[name] = _config$1(_options); } } }, false); } assign(nj, { filters: filters, filterConfig: filterConfig, registerFilter: registerFilter }); var components = {}; var componentConfig = new Map(); function registerComponent(name, component, options) { var params = name, ret; if (!isObject(name)) { params = {}; params[name] = { component: component, options: options }; } each(params, function (v, k, i) { var comp; if (v != null) { var _component = v.component, _options = v.options; var _name = k.toLowerCase(); comp = _component ? _component : v; components[_name] = comp; componentConfig.set(comp, _options); } if (i == 0) { ret = comp; } else { if (i == 1) { ret = [ret]; } ret.push(comp); } }, false); return ret; } function getComponentConfig(name) { return componentConfig.get(isString(name) ? components[name] || name : name); } function copyComponentConfig(component, from) { componentConfig.set(component, componentConfig.get(from)); return component; } assign(nj, { components: components, componentConfig: componentConfig, registerComponent: registerComponent, getComponentConfig: getComponentConfig, copyComponentConfig: copyComponentConfig }); var REGEX_JS_PROP = /('[^']*')|("[^"]*")|(-?[0-9][0-9]*(\.\d+)?)|true|false|null|undefined|Object|Array|Math|Date|JSON|(([a-zA-Z_$#@])([a-zA-Z_$\d]*))/; var REGEX_REPLACE_CHAR = /_njQs(\d+)_/g; var REGEX_REPLACE_SET = /_njSet_/; function _replaceStr(prop, innerQuotes) { return prop.replace(REGEX_REPLACE_CHAR, function (all, g1) { return innerQuotes[g1]; }); } function _compiledProp(prop, innerBrackets, innerQuotes, source) { var ret = obj(); if (prop.indexOf('|') >= 0) { var filters = []; var filtersTmp; filtersTmp = prop.split('|'); prop = filtersTmp[0].trim(); //Extract property filtersTmp = filtersTmp.slice(1); each(filtersTmp, function (filter) { filter = filter.trim(); if (filter === '') { return; } var retF = _getFilterParam(filter), filterObj = obj(), filterName = retF[0].trim(); //Get filter name if (filterName) { var paramsF = retF[1]; //Get filter param //Multiple params are separated by commas. if (paramsF != null) { var params = []; each(innerBrackets[paramsF].split(','), function (p) { if (p !== '') { params[params.length] = _compiledProp(p.trim(), innerBrackets, innerQuotes); } }, true); filterObj.params = params; } filterObj.name = filterName; filters.push(filterObj); } }, true); ret.filters = filters; } //替换字符串值 prop = _replaceStr(prop, innerQuotes); //Extract the parent data path if (prop.indexOf('../') === 0) { var n = 0; prop = prop.replace(/\.\.\//g, function () { n++; return ''; }); ret.parentNum = n; } //Extract the js property if (prop !== '') { var matchProp = REGEX_JS_PROP.exec(prop); var hasAccessor = matchProp[6] === '#'; ret.name = hasAccessor ? matchProp[7] : matchProp[0]; if (!matchProp[5]) { //Sign the parameter is a basic type value. ret.isBasicType = true; } if (hasAccessor) { ret.isAccessor = true; } ret.name = ret.name.replace(REGEX_REPLACE_SET, function () { ret.hasSet = true; return ''; }); } else { ret.isEmpty = true; } return ret; } //Get filter param function _getFilterParam(obj) { return obj.split("'bracket_"); } //Extract replace parameters var REGEX_LT_GT = /_nj(L|G)t_/g; var LT_GT_LOOKUP = { _njLt_: '<', _njGt_: '>' }; var REGEX_QUOTE = /"[^"]*"|'[^']*'/g; var REGEX_OPERATORS_ESCAPE = /\*|\||\/|\.|\?|\+/g; var SP_FILTER_LOOKUP = { '||': 'or', '..': 'rOpe', '..<': 'rLt' }; var REGEX_SP_FILTER; function createFilterAlias(name, alias) { if (name && alias) { SP_FILTER_LOOKUP[name] = alias; } REGEX_SP_FILTER = new RegExp('[\\s]+((' + Object.keys(SP_FILTER_LOOKUP).map(function (o) { return o.replace(REGEX_OPERATORS_ESCAPE, function (match) { return '\\' + match; }); }).join('|') + ')[\\s]+)', 'g'); } createFilterAlias(); var FN_FILTER_LOOKUP = { ')': ')_(', ']': ']_(' }; var REGEX_FN_FILTER = /(\)|\]|\.([^\s'"._#()|]+))[\s]*\(/g; var REGEX_SPACE_S_FILTER = /([(,|])[\s]+/g; var REGEX_PROP_FILTER = /\.([a-zA-Z_$#@][a-zA-Z_$\d]*)/g; var REGEX_ARRPROP_FILTER = /([^\s([,])(\[)/g; var ARR_OBJ_FILTER_LOOKUP = { '[': 'list(', ']': ')', '{': 'obj(', '}': ')' }; var REGEX_ARR_OBJ_FILTER = /\[|\]|\{|\}/g; //const REGEX_OBJKEY_FILTER = /([(,][\s]*)([^\s:,'"()|]+):/g; var REGEX_SET_FILTER = /^[\s]*set[\s]+|([(,])[\s]*set[\s]+/g; var REGEX_BRACKET_FILTER = /^[\s]*([(]+)|([(,])[\s]*([(]+)/g; var NOT_OPERATORS = ['../']; var REGEX_NEGATIVE = /-[0-9]/; var BEGIN_CHARS = ['', '(', '[', ',']; var OPERATORS = ['+=', '+', '-[0-9]', '-', '**', '*', '%%', '%', '===', '!==', '==', '!=', '<=>', '<=', '>=', '=', '..<', '<', '>', '&&', '||', '?:', '?', ':', '../', '..', '/']; var REGEX_OPERATORS; function createRegexOperators(operator) { if (operator) { var insertIndex = 0; OPERATORS.forEach(function (o, i) { if (o.indexOf(operator) >= 0) { insertIndex = i + 1; } }); OPERATORS.splice(insertIndex, 0, operator); } REGEX_OPERATORS = new RegExp(OPERATORS.map(function (o) { return o.replace(REGEX_OPERATORS_ESCAPE, function (match) { return '\\' + match; }); }).join('|'), 'g'); } createRegexOperators(); function _getProp(matchArr, innerQuotes, i, addSet) { var prop = matchArr[2].trim(); var item = [matchArr[0], matchArr[1], null, true]; if (i > 0) { item[3] = false; //Sign not contain all of placehorder } if (addSet) { prop = 'set ' + prop; } //替换特殊过滤器名称并且为简化过滤器补全"|"符 prop = prop.replace(REGEX_LT_GT, function (match) { return LT_GT_LOOKUP[match]; }).replace(REGEX_QUOTE, function (match) { innerQuotes.push(match); return '_njQs' + (innerQuotes.length - 1) + '_'; }).replace(REGEX_OPERATORS, function (match, index) { if (REGEX_NEGATIVE.test(match)) { if (index > 0 && BEGIN_CHARS.indexOf(prop[index - 1].trim()) < 0) { //Example: 123-456 return match.split('-').join(' - '); } else { //Example: -123+456 return match; } } else { return NOT_OPERATORS.indexOf(match) < 0 ? " ".concat(match, " ") : match; } }).replace(REGEX_SP_FILTER, function (all, g1, match) { return ' ' + SP_FILTER_LOOKUP[match] + ' '; }).replace(REGEX_PROP_FILTER, function (all, g1) { var startWithHash = g1[0] === '#'; if (startWithHash) { g1 = g1.substr(1); } var lastCharIndex = g1.length - 1, endWithUnderline = lastCharIndex > 0 && g1[lastCharIndex] === '_'; return (startWithHash ? '#' : '.') + "('" + (endWithUnderline ? g1.substr(0, lastCharIndex) : g1) + "')" + (endWithUnderline ? '_' : ''); }).replace(REGEX_ARRPROP_FILTER, function (all, g1, g2) { return g1 + '.('; }).replace(REGEX_ARR_OBJ_FILTER, function (match) { return ARR_OBJ_FILTER_LOOKUP[match]; }).replace(REGEX_SET_FILTER, function (all, g1) { return (g1 ? g1 : '') + '_njSet_'; }).replace(REGEX_BRACKET_FILTER, function (all, g1, g2, g3) { return (g2 ? g2 : '') + (g2 ? g3 : g1).replace(/[(]/g, 'bracket('); }) //.replace(REGEX_OBJKEY_FILTER, (all, g1, g2) => g1 + ' \'' + g2 + '\' : ') .replace(REGEX_SPACE_S_FILTER, function (all, match) { return match; }).replace(REGEX_FN_FILTER, function (all, match, g1) { return !g1 ? FN_FILTER_LOOKUP[match] : ".('" + g1 + "')_("; }); item[2] = prop.trim(); return item; } function _getReplaceParam(obj, tmplRule, innerQuotes, hasColon, addSet) { var pattern = tmplRule.replaceParam; var matchArr, ret, i = 0; if (!hasColon) { while (matchArr = pattern.exec(obj)) { if (!ret) { ret = []; } var startRuleR = matchArr[2]; ret.push(_getProp([matchArr[0], startRuleR ? startRuleR : matchArr[5], startRuleR ? matchArr[3] : matchArr[6]], innerQuotes, i, addSet)); i++; } } else { matchArr = [obj, tmplRule.startRule, obj]; ret = [_getProp(matchArr, innerQuotes, i, addSet)]; } return ret; } var REGEX_INNER_BRACKET = /\(([^()]*)\)/g; var REGEX_FIX_OPERATOR_1 = /([!]+)((-?[0-9][0-9]*(\.\d+)?|[^\s,|'=]+)('bracket_\d+)?([._#]'bracket_\d+)*)/g; var REGEX_FIX_OPERATOR = /[\s]+([^\s(),|"']+)[\s]+((-?[0-9][0-9]*(\.\d+)?|[^\s,|']+)('bracket_\d+)?([._#]'bracket_\d+)*)/g; var REGEX_SPACE_FILTER = /[(,]/g; var REGEX_FIX_FILTER = /(\|)?(((\.+|_|#+)'bracket_)|[\s]+([^\s._#|]+[\s]*'bracket_))/g; function _fixOperator(prop, innerBrackets) { prop = prop.replace(REGEX_FIX_OPERATOR_1, function () { var args = arguments; innerBrackets.push(_fixFilter(args[2])); return args[1] + "'bracket_" + (innerBrackets.length - 1); }); return _fixFilter(prop.replace(REGEX_FIX_OPERATOR, function () { var args = arguments; innerBrackets.push(_fixFilter(args[2])); return ' ' + args[1] + "'bracket_" + (innerBrackets.length - 1); })); } function _fixFilter(prop) { return (' ' + prop).replace(REGEX_SPACE_FILTER, function (all) { return all + ' '; }).replace(REGEX_FIX_FILTER, function (all, g1, g2, g3, g4, g5) { return g1 ? all : ' | ' + (g3 ? g3 : g5); }).trim(); } function _replaceInnerBrackets(prop, innerBrackets) { var propR = prop.replace(REGEX_INNER_BRACKET, function (all, s1) { innerBrackets.push(_fixOperator(s1, innerBrackets)); return "'bracket_" + (innerBrackets.length - 1); }); if (propR !== prop) { return _replaceInnerBrackets(propR, innerBrackets); } else { return _fixOperator(propR, innerBrackets); } } //Get compiled parameter function compiledParam(value, tmplRule, hasColon, onlyKey, addSet) { var ret = obj(), isStr = isString(value); var strs = isStr ? !hasColon ? value.split(tmplRule.replaceSplit) : ['', ''] : [value], props = null, isAll = false; //此处指替换符是否占满整个属性值;若无替换符时为false if (isStr) { //替换插值变量以外的文本中的换行符 strs = strs.map(function (str) { return str.replace(/\n/g, '_njNl_').replace(/\r/g, ''); }); } //If have placehorder if (strs.length > 1) { var innerQuotes = []; var params = _getReplaceParam(value, tmplRule, innerQuotes, hasColon, addSet); props = []; each(params, function (param) { var retP = obj(), innerBrackets = []; isAll = param[3] ? param[0] === value : false; //If there are several curly braces in one property value, "isAll" must be false. var prop = _replaceInnerBrackets(param[2], innerBrackets); retP.prop = _compiledProp(prop, innerBrackets, innerQuotes); //To determine whether it is necessary to escape retP.escape = param[1] !== tmplRule.firstChar + tmplRule.startRule; props.push(retP); }, true); } ret.props = props; ret.strs = strs; ret.isAll = isAll; ret.onlyKey = onlyKey; return ret; } assign(nj, { createFilterAlias: createFilterAlias, createRegexOperators: createRegexOperators }); function getXmlOpenTag(obj, tmplRule) { return tmplRule.xmlOpenTag.exec(obj); } //验证xml self close tag var REGEX_XML_SELF_CLOSE_TAG = /^<[^>]+\/>$/i; function isXmlSelfCloseTag(obj) { return REGEX_XML_SELF_CLOSE_TAG.test(obj); } //Verify self close tag name var OMITTED_CLOSE_TAGS = { area: true, base: true, br: true, col: true, embed: true, hr: true, img: true, input: true, keygen: true, link: true, meta: true, param: true, source: true, track: true, wbr: true }; function verifySelfCloseTag(tagName) { return OMITTED_CLOSE_TAGS[tagName.toLowerCase()]; } //Extract parameters inside the xml open tag function getOpenTagParams(tag, tmplRule) { var pattern = tmplRule.openTagParams; var matchArr, ret; while (matchArr = pattern.exec(tag)) { var key = matchArr[1]; if (key === '/') { //If match to the last of "/", then continue the loop. continue; } if (!ret) { ret = []; } var value = matchArr[8], onlyKey = false; var onlyBrace = m