UNPKG

snakeskin

Version:

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

267 lines (207 loc) 5.9 kB
var callBlockNameRgxp = new RegExp(`^[^${symbols}_$][^${w}$]*|[^${w}$]+`, 'i'); Snakeskin.addDirective( 'block', { sys: true, block: true, notEmpty: true, group: [ 'template', 'inherit', 'define', 'blockInherit' ] }, function (command, commandLength) { var name = this.getFnName(command), tplName = this.tplName; if (!name) { return this.error(`invalid "${this.name}" name`); } var parts = name.split('->'); if (parts[1]) { name = parts[1].trim(); if (!tplName) { if (this.structure.parent) { this.error(`directive "outer block" can be used only within the global space`); return; } try { tplName = this.tplName = this.prepareNameDecl(parts[0]); } catch (err) { return this.error(err.message); } if (tplName in extMap) { delete extMap[tplName]; clearScopeCache(tplName); } let desc = this.preDefs[tplName] = this.preDefs[tplName] || { text: '' }; desc.startLine = this.info['line']; desc.i = this.i + 1; this.outerLink = name; this.protoStart = true; } } else if (!this.outerLink && !this.tplName) { return this.error(`directive "${this.name}" can be used only within a ${groupsList['template'].join(', ')}`); } if (!name || !tplName || callBlockNameRgxp.test(name)) { return this.error(`invalid "${this.name}" declaration`); } var scope = scopeCache[this.name][tplName] = scopeCache[this.name][tplName] || {}; var parentScope, parentTplName = extMap[tplName]; if (parentTplName) { parentScope = scopeCache[this.name][parentTplName] = scopeCache[this.name][parentTplName] || {}; } let current = scope[name]; if (!scope[name]) { current = scope[name] = { id: this.module.id, children: {} }; } if (!this.outerLink && !current.root) { let parent = parentScope && parentScope[name]; current.parent = parent; current.overridden = Boolean(parentTplName && this.parentTplName); current.root = parent ? parent.root : scope[name]; if (parent) { parent.children[tplName] = scope[name]; } } var start = this.i - this.startTemplateI; this.startDir(null, { name: name, from: this.outerLink ? this.i - this.getDiff(commandLength) : start + 1 }); var struct = this.structure, dir = String(this.name); var params, output; if (name !== command) { let ouptupCache = this.getBlockOutput(dir); if (ouptupCache) { output = command.split('=>')[1]; params = ouptupCache[name]; if (output != null) { params = ouptupCache[name] = output; } } } if (this.isAdvTest()) { if (blockCache[tplName][name]) { return this.error(`block "${name}" is already defined`); } let args = this.prepareArgs( command, dir, null, this.parentTplName, name ); if (args.params && callBlockNameRgxp.test(name)) { return this.error(`invalid "${this.name}" declaration`); } this.structure.params.args = args.params; blockCache[tplName][name] = { from: start - this.getDiff(commandLength), needPrfx: this.needPrfx, args: args, output: output }; if (args.scope) { this.scope.push(args.scope); struct.params._scope = true; } } if (this.isSimpleOutput()) { let args = blockCache[tplName][name].args; if (args.params) { let fnDecl = `__BLOCKS__.${name}`; struct.params.fn = fnDecl; this.save(/* cbws */` if (!${fnDecl}) { ${fnDecl} = function (${args.str}) { var __RESULT__ = ${this.declResult()}; ${this.declArguments()} function getTplResult(opt_clear) { var res = ${this.returnResult()}; if (opt_clear) { __RESULT__ = ${this.declResult()}; } return res; } function clearTplResult() { __RESULT__ = ${this.declResult()}; } ${args.defParams} `); if (params != null) { let str = '', vars = struct.vars; struct.vars = struct.parent.vars; params = this.getFnArgs(`(${params})`); for (let i = -1; ++i < params.length;) { str += `${this.prepareOutput(params[i], true)},` } struct.vars = vars; str = str.slice(0, -1); struct.params.params = str; } } } }, function (command, commandLength) { var params = this.structure.params, diff = this.getDiff(commandLength); var s = (this.needPrfx ? ADV_LEFT_BLOCK : '') + LEFT_BLOCK, e = RIGHT_BLOCK; if (this.outerLink === params.name) { let obj = this.preDefs[this.tplName], nl = this.lineSeparator, i = Number(obj.i); obj.text += /* cbws */` ${nl}${this.source.substring(params.from, i)} ${s}__cutLine__${e} ${s}__switchLine__ ${obj.startLine}${e} ${this.source.substring(i, this.i - diff)} ${s}__end__${e} ${nl}${this.source.substring(this.i - diff, this.i + 1)} ${s}__cutLine__${e} `; this.outerLink = null; this.tplName = null; this.protoStart = false; return; } var block = blockCache[this.tplName][params.name]; if (this.isSimpleOutput() && params.fn) { this.save(/* cbws */` return ${this.returnResult()}; }; } ${params.params != null ? this.wrap(`${params.fn}(${params.params})`) : ''} `); } if (this.isAdvTest()) { if (!block) { return this.error('invalid "block" declaration'); } let start = this.i - this.startTemplateI; block.to = start + 1; block.content = this.source .substring(this.startTemplateI) .substring(params.from, start - diff); } } );