import parser to support nested tags

This commit is contained in:
harttle
2016-06-17 03:38:03 +08:00
parent a842284628
commit 8b9e9f759a
13 changed files with 340 additions and 161 deletions
+30 -33
View File
@@ -2,30 +2,35 @@ const lexical = require('./lexical.js');
const syntax = require('./syntax.js');
const error = require('./error.js');
module.exports = function(Filter, Tag) {
function render(tokens, scope) {
function stringify(val) {
if (typeof val === 'string') return val;
return JSON.stringify(val);
}
function isTruthy(val) {
if (val instanceof Array) return !!val.length;
return !!val;
}
function factory(Filter, Tag) {
function renderTemplates(templates, scope) {
var html = '';
while (tokens.length) {
var token = tokens.shift();
switch (token.type) {
case 'html':
html += token.value;
break;
case 'output':
html += evalFilter(token.value, scope);
break;
case 'tag':
html += renderTag(token, tokens, scope);
break;
default:
error(`unexpected type: ${token.type}`, token);
var template;
while (template = templates.shift()) {
if (template.type === 'tag') {
html += template.render(scope);
} else if (template.type === 'html') {
html += template.value;
} else if (template.type === 'output') {
var val = evalFilter(template.value, scope);
html += stringify(val);
}
}
return html;
}
function evalExp(exp, scope) {
if(!scope) error('unable to evalExp: scope undefined');
if (!scope) error('unable to evalExp: scope undefined');
var operatorREs = lexical.operators;
for (var i = 0; i < operatorREs.length; i++) {
var operatorRE = operatorREs[i];
@@ -41,8 +46,8 @@ module.exports = function(Filter, Tag) {
return evalFilter(exp, scope);
}
function evalFilter(str, scope){
if(!scope) error('unable to evalFilter: scope undefined');
function evalFilter(str, scope) {
if (!scope) error('unable to evalFilter: scope undefined');
var filters = str.split('|');
var val = scope.get(filters.shift());
return filters
@@ -50,20 +55,12 @@ module.exports = function(Filter, Tag) {
.reduce((v, filter) => filter.render(v, scope), val);
}
function renderTag(token, tokens, scope) {
var tag = Tag.construct(token),
subTokens = [];
if (tag.needClose) {
var curToken, endToken = 'end' + tag.token.name;
while ((curToken = tokens.shift()) && curToken.value !== endToken) {
subTokens.push(curToken);
}
if (!curToken) error(`${token.value} not closed`);
}
return tag.render(subTokens, scope);
}
return {
render, renderTag, evalFilter, evalExp
renderTemplates, evalFilter, evalExp
};
};
factory.isTruthy = isTruthy;
factory.stringify = stringify;
module.exports = factory;