-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Labels
Description
上一篇underscore模板引擎的工作原理,介绍到underscore采用正则替换模板变量,输出函数,并执行获取HtmlString,但是存在的问题如下:
内容包括
- 函数直接执行存在问题
- mustache字符串扫描过程
Scanner - token转换成htmlString
Writer - xss攻击防御、报错机制、模版缓存如何处理
函数直接执行存在问题
- xss攻击防御
- 报错机制
- 模版缓存
mustache如何解决这些问题
接下来我们讨论mustache是如何运行的
mustache模版方法
- Scanner
- Writer
- Context
思路
- Scanner逐个扫描整个字符串,通过不同类型进行存储token
- Write将token按类型进行渲染
Scanner扫描
scanner的扫描方法,整个字符串从左往右。输入输出如下,调用parseTemplate
input = '12{{title}}'3;
// parseTemplate, token [type,content,字符串起始位置,字符串结束位置]
output = [
['text',1, 0,1],
['text',2, 1,2],
['name','title',2,11],
['text',3,11,12]
]
// squashTokens 合并
output = [
['text',12,0,2],
['name','title',2,11],
['text',11,12]
]扫描机制
- scan
- scanUntil
- eos (input)
// 1.扫描字符串text
var openingTagRe = /\{\{\s*/
var input = '12{{title}}3';
var value = scanner.scanUntil(openingTagRe)
// 扫描到{{, 获取12(text type), value循环.
var output = '{{title}}3'
// 2.去除开始符号{{
input = '{{title}}3'
output = 'title}}3'
// 3.匹配变量name
var closingTagRe = /\s*\}\}/
var input = 'title}}3'
var x = scanner.scanUntil(closingTagRe)
// 扫描到}}, 获取title(name type)
var output = '}}3'
// 4.去除结束符号}}
input = '}}3'
output = '3'
// 5.循环1步骤
var input = 3
var output = '';Writer 数据写入
renderTokens分发不同type的渲染
此处根据token类型( #、^、>、&、name、text),使用renderTokens填写变量
// loop squashTokens render
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
// 类型 #、^、>、&、name、text
symbol = token[0];
value = render(symbol)
buffer +=value
}
// buffer就是最终要渲染的字符串======== to be continued =========
缓存问题解析
Context
- lookup
- push
xss防御问题解析 escape
- mustache.escape
var title = "<h1>dddd</h1>"
var input = "<h3>12{{title}}</h3>";
var output = "<h3>12<h1>ddddd</h1></h3>"
var string = '<h1>dddd</h1>';
var entityMap = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
'`': '`',
'=': '='
};
function escapeHtml (string) {
return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
return entityMap[s];
});
}报错问题解析
throw,因为整个htmlString是逐个解析的,所以能够在需要报错的节点直接抛异常
- {{ }} 报错
- 输入template出错