???????
????????????????????????????????????????????????????棬???????????ж??????????????????????????д?????????????????????????? swig ???? nunjucks ?????????????????????????檔
?????????????????????????????????????????????????????????????Σ????????????????????????????????к???????????????????????????? vue??angular ??Щ???????? dom base ????? swig nunjucks ejs??Щ???????? string base ??????????????????????????????????? Template =parse=> Ast =render=>String??
????????????????????棬????о??????????????????????????????а????????????????????????????????????????????????????У???????Щ????????????????????????????????
???????????
?????????????棬????????????????????????????????????????????????? ast???????????????????????? ast ?????? html??
???????????? ast ??????????????????
??????????????abstract syntax tree??????д?AST??????????????syntax tree??????????????????????????????????????????????????????????????????????????е?????????????????“????”???????????????????????????????г??????????????磬????????????????????У???????????????????????????if-condition-then????????????????????????????????????????????
????????????????????????????????? tag ???????????????for??if else??set??raw???????????????????????????????????????????????????? tag???????? filter ????????????
???????? AST
???????????????????????????????????????????????????????????
????<div>
????{% if test > 1 %}
????{{ test }}
????{% endif %}
????</div>
???????????div ??????????????????????????????鼶??? if ????? if ???????????????????????????????? ?????????? json ????????????????? ast ?????????
[
{
type: 1??
text: '<div>'
}??
{
type: 2??
tag: 'if'??
item: 'test > 1'??
children: [{
type: 3??
item: 'test'
}]
}??
{
type: 1??
text: '</div>'
}
]
??????????????????????????????????????????鼶????????????????????????????????????????????????????????ɡ???????????????????????????????????鼶?????????????????????{%????{{???????????????????????????
????...
????const matches = str.match(/{{|{%/);
????const isBlock = matches[0] === '{%';
????const endIndex = matches.index;
????...
?????????????δ??????????????????????{{????{%λ?????
????????????????????????????λ???????y??λ?????????????????????????????????????????????????<div>???
????????? div ??????????????????????????????????????{%??????????endIndex?????????????????????????????????????? slice ????????
????// 2 ?? {% ?????
????str = str.slice(endIndex + 2);
??????????????????????????????????{%?????????????????%}?????????????
????const expression = str.slice(0?? str.indexOf('%}'))
????????? if test > 1 ???????????????????????????/^ifs+([sS]+)$/???????????????????? if ??????????????test > 1??????????飬?????????????????????if ??鼶??????
??????? if ????鼶??????????????????????????? {% endif %} ???????н?????????? if ?????????????????????????????????children?????????????????????
????????????????????????????????{%???{{??λ??????????????????????{{??λ?ú????ж?}}??λ???????????????????test ???????????? push ?? if ?????????б??С?
?????????????????????????????????????????{% endif %}???????????????y??????????????浽 if ?????????б????????????????????????
?????????????????????£?
const root = [];
let parent;
function parse(str){
const matches = str.match(/{{|{%/);
const isBlock = matches[0] === '{%';
const endIndex = matches.index;
const chars = str.slice(0?? matches ? endIndex : str.length);
if(chars.length) {
...??????????
}
if(!matches) return;
str = str.slice(endIndex + 2);
const leftStart = matches[0];
const rightEnd = isBlock ? '%}' : '}}';
const rightEndIndex = str.indexOf(rightEnd);
const expression = str.slice(0?? rightEndIndex)
if(isBlock) {
...?????鼶??? el
parent = el;
} else {
...??????????? el
}
(parent ? parent.children : root).push(el);
parse(str.slice(rightEndIndex + 2));
}
?????????????????????????????????????????????????????{% {{ test }}????????{%??????????б??? else ???? elseif ????????????????????????? if ???????????????????????????????????????????????
??????? html
?????????? ast ?????? html ???????????????????????????????????????????ɡ?
???????磬??????????????html += el.text???ɡ??????if??????ж???????????????test > 1?????????????????????????????eval???????????new Function???eval ???а??????????????????????????new Function?????????????????????????????new Function??????
??????????????????£?
function computedExpression(obj?? expression) {
const methodBody = `return (${expression})`;
const funcString = obj ? `with(__obj__){ ${methodBody} }` : methodBody;
const func = new Function('__obj__'?? funcString);
try {
let result = func(obj);
return (result === undefined || result === null) ? '' : result;
} catch (e) {
return '';
}
}
??????? with ?????????? function ????е???????????????
????with({ a: '123' }) {
????console.log(a); // 123
????}
??????? with ????????д??????????????????? js ???????????????????????????????????????????????????????? vue ?е? render function ????? with ??????????????? nunjucks ??????? with ???????????????????????????? nunjucks ????????У???????????淶???????????????????????? with ????????д{(diào){ test ? 'good' : 'bad' }}???????? nunjucks ????д???{{ 'good' if test else 'bad' }}??
????anyway?????и???eɡ?
??????????????
??????? ast ????? html ?????????????????????????????????????? for ????????????? for ??????????????????????????????????????????顣
??????????????? ast ?????????????????processAst(ast?? scope)?????????? scope ??
{
list: [
{ subs: [1?? 2?? 3] }??
{ subs: [4?? 5?? 6] }
]
}
??????? processAst ???????????
function processAst(ast?? scope) {
...
if(ast.for) {
const list = scope[ast.item]; // ast.item ??????б?? key ??????????? list
list.forEach(item => {
processAst(ast.children?? Object.assign({}?? scope?? {
[ast.key]: item??  // ast.key ???? for key in list ?е? key
}))
})
}
...
}
??????????????飬???????????????????????
????Filter ???????
??????????湦??????????????????????????????????????????????????????????????????? filter ???????? filter ????÷???????????? {{ test | filter1 | filter2 }}??????????????£????????????ο??? vue ?????????????????????????
???????????????
????{{ test | filter1 | filter2 }}
????????? AST ????????????????е?test | filter1 | filter2???????????????????? filter1 ?? filter2 ???????????????????????????????Щ filter ???????? ast ???? filters ?????У????????????????????ó????????
????????????????????????????????? AST ????????????????????????????????? vue ?????????????????????????????
????_$f('filter2'?? _$f('filter1'?? test))
??????????????????????????????????????????????????? filter ????????????????????£?
const filterRE = /(?:|s*w+s*)+$/;
const filterSplitRE = /s*|s*/;
function processFilter(expr?? escape) {
let result = expr;
const matches = expr.match(filterRE);
if (matches) {
const arr = matches[0].trim().split(filterSplitRE);
result = expr.slice(0?? matches.index);
// add filter method wrapping
utils.forEach(arr?? name => {
if (!name) {
return;
}
// do not escape if has safe filter
if (name === 'safe') {
escape = false;
return;
}
result = `_$f('${name}'?? ${result})`;
});
}
return escape ? `_$f('escape'?? ${result})` : result;
}
???????滹???????? safe ??????????? safe ??? filter ?????? escape ?????????????? filter ?? variable ??????_$f('filter2'?? _$f('filter1'?? test))??????????????????? computedExpression ?????????Щ???????
function processFilter(filterName?? str) {
const filter = filters[filterName] || globalFilters[filterName];
if (!filter) {
throw new Error(`unknown filter ${filterName}`);
}
return filter(str);
}
function computedExpression(obj?? expression) {
const methodBody = `return (${expression})`;
const funcString = obj ? `with(_$o){ ${methodBody} }` : methodBody;
const func = new Function('_$o'?? '_$f'?? funcString);
try {
const result = func(obj?? processFilter);
return (result === undefined || result === null) ? '' : result;
} catch (e) {
// only catch the not defined error
if (e.message.indexOf('is not defined') >= 0) {
return '';
} else {
throw e;
}
}
}
?????????????????? new Function ??????????????? filter ??????????????? filter ?? variable ????????????????
?????????AST ??????AST ?? html ?????????????????? Filter ?????????????????????ɡ?
???????????????????????????????https://github.com/whxaxes/mus
?????????????????????????е??????????·???? star ??