Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mustache模版引擎的工作原理入门 #14

Open
iscarecrow opened this issue Jan 16, 2017 · 0 comments
Open

mustache模版引擎的工作原理入门 #14

iscarecrow opened this issue Jan 16, 2017 · 0 comments

Comments

@iscarecrow
Copy link
Owner

iscarecrow commented Jan 16, 2017

上一篇underscore模板引擎的工作原理,介绍到underscore采用正则替换模板变量,输出函数,并执行获取HtmlString,但是存在的问题如下:

内容包括

  • 函数直接执行存在问题
  • mustache字符串扫描过程Scanner
  • token转换成htmlString Writer
  • xss攻击防御、报错机制、模版缓存如何处理

函数直接执行存在问题

  • xss攻击防御
  • 报错机制
  • 模版缓存

mustache如何解决这些问题

接下来我们讨论mustache是如何运行的

mustache模版方法
  • Scanner
  • Writer
  • Context
思路
  1. Scanner逐个扫描整个字符串,通过不同类型进行存储token
  2. 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&lt;h1&gt;ddddd&lt;&#x2F;h1&gt;</h3>"

var string = '<h1>dddd</h1>';

var entityMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;',
    '/': '&#x2F;',
    '`': '&#x60;',
    '=': '&#x3D;'
  };

 function escapeHtml (string) {
    return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
      return entityMap[s];
    });
  }
报错问题解析

throw,因为整个htmlString是逐个解析的,所以能够在需要报错的节点直接抛异常

  • {{ }} 报错
  • 输入template出错

参考资料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant