0.0.1 • Published 5 years ago
light-template v0.0.1
Light-Template
一个基于JavaScript的模版DSL
特性
- 用原生JS控制模版的渲染
- 支持子模版链接
- 支持模版调试
安装
npm
npm install light-template
browser
<script src="path/to/light-template.min.js"></script>
<script>
let { default: template } = LIGHT_TEMPLATE
</script>
示例
import template from "light-template";
//模版
let tmpl =`<p><%- data.name %><p>
<p><%= data.desc %></p>
<ul><% for(let tag of data.tags){ %>
<li><% print(tag) %></li><% } %>
</ul>`
//数据
let data = {
name: "<<Alice&Bob>>",
desc: "How do Alice and Bob prevent Truck",
tags: [
"HASH",
"MAC",
"RSA",
"Digital Signature",
"CA"
]
}
//编译
let executor = template(tmpl, { variable: "data", soureMap: true })
//执行
let result = executor.render(data)
console.log(result)
输出:
<p><<Alice&Bob>><p>
<p>How do Alice and Bob prevent Truck</p>
<ul>
<li>HASH</li>
<li>MAC</li>
<li>RSA</li>
<li>Digital Signature</li>
<li>CA</li>
</ul>
更丰富的例子参考 ➡️ 示例
语法
语法基本与 lodash.template 相同,但新增了一个链接指令.
插值指令
<%=
,顾名思义,就是插入一个值
let tmpl =`<p><%= data.greeting %><p>`
let data = { greeting: "Hello World" }
let exe = template(tmpl, { variable: "data" })
let result = exe.render(data)
console.log(result)
// output:
// <p>Hello World<p>
HTML转义指令
<%-
可用于转义HTML保留字符
let tmpl =`<p><%- data.greeting %><p>`
let data = { greeting: `<img src="xss">` }
let exe = template(tmpl, { variable: "data" })
let result = exe.render(data)
console.log(result)
// output:
// <p><img src="xss"><p>
脚本块指令
<%
%>
之间可以编写任意的JS代码,提供了一个内置的print函数,用于输出内容到最终的模版.
let tmpl =`<ul>
<%
for(let user of users){
print('<li>'+user+'</li>')
}
%>
</ul>`
let data = ["Alice","Bob"]
let result = template(tmpl, { variable: "users", soureMap: true }).render(data)
console.log(result)
// output:
// <ul>
// <li>Alice</li><li>Bob</li>
// </ul>
链接子模版
<%@
%>
之间可以指定要插入的子模版的名称,当light-template遇到链接指令时,都将要链接的模版名称传给加载器,由加载器返回模版的内容,然后进行编译. 需注意,这个名称不一定是路径名,只要可以标识一个唯一的模版即可.
let tmpls = new Map()
tmpls.set("greeting.tmpl", `Hello,<%= user.name %>`)
//模版加载器
let sourceLoader = (sourceName) => {
if (!tmpls.has(sourceName))
throw new Error("Can't find template named " + sourceName)
return tmpls.get(sourceName)
}
//入口模版
let entry = `<p><%@ greeting.tmpl %></p>` // 使用 <%@ 链接一个子模版
//编译
let exe = template(entry, { variable: "user", sourceLoader, soureMap: true })
//渲染
let result = exe.render({ name: "Alice" })
console.log(result)
// output:
// <p>Hello,Alice</p>
保留字符转义
<%
、%>
是保留字符, 如果要用作文本,使用\
转义
let tmpl ="脚本块的语法是:\\<% code \\%>" //这里有两个`\` 是因为`\`在JS中也是特殊字符,因此要加一个`\`转义
let result = template(tmpl, { variable: "data", soureMap: true }).render({})
console.log(result)
// output:
//脚本块的语法是:<% code %>
原理
将模版编译为一个JavaScript函数, 该函数接收一个data,以拼接字符串的形式生成最终的模版.
<p><%= data.greeting %><p>
⬇️
function(data){
let __p = ""
__p+="<p>"+ data.greeting +"<p>"
return __p
}
API
template
template(tmpl: string, options?: TemplateSettings): TemplateExecutor
- tmpl ,模版内容
- TemplateSettings
-
variable?: string
,指定数据对象在模版中的变量名,可通过该变量引用数据对象 -soureMap?: boolean
,是否生成sourceMap -sourceName? : string
,指定入口模版的名称,在调试的时候方便区分模版. -sourceLoader? : (soureName :string)=>string
, 模版源码加载器,当要使用子模版嵌入指令(<%@
)时须指定,该函数接收一个模版名称,返回模版内容. - TemplateExecutor
-
render(data :any)
,接收一个数据对象对模版进行渲染 -source: string
,生成的渲染函数
compile
compile(tmpl: string, settings?: TemplateSettings): string
与template的区别是,此方法仅返回渲染函数的字符串形式.
其他
with
JS中的with关键字可以将一个变量的属性作为一个作用域的上下文
let obj = { x :1 ,y:2 }
with(obj){
//可以直接使用obj的属性
z=x+y
}
如果把这一特性用在模版中,原本要<%= data.greeting %>
,而现在可直接通过 <%= greeting %>
访问数据对象.
但是,with是一个过期的特性,strict 模式中使用with会直接抛出异常, 因此舍弃了提供该功能.
0.0.1
5 years ago
0.0.0-alpha.3
5 years ago
0.0.0-alpha.4
5 years ago
0.0.0-alpha.2
5 years ago
0.0.0-alpha.1
5 years ago
0.0.0
5 years ago