Security News
pnpm 10.0.0 Blocks Lifecycle Scripts by Default
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.
ETPL是一个灵活、具有强大复用能力的高性能Javascript模板引擎,适用于WEB前端应用中视图的生成,特别是SPA(Single Page APP)类型的应用。
ETPL是一个灵活、具有强大复用能力的高性能的模板引擎,适用于WEB前端应用中视图的生成,特别是SPA(Single Page APP)类型的应用。
ETPL可以在CommonJS/AMD
的模块定义环境中使用,也可以直接在页面下通过<script src=
的方式引用。CommonJS/AMD
环境下需要通过如下代码得到ETPL的模块。
var etpl = require( 'etpl' );
得到ETPL模块对象后,首先对模板源代码进行编译,就能够得到模板编译后的function
。
var render = etpl.compile( 'Hello ${name}!' );
然后执行这个function
,传入数据对象,就能得到模板执行的结果了。
var text = render( {name: 'etpl'} );
编写模板和数据前,如果对执行结果有疑虑,就去ETPL的homepage试试看吧。
ETPL的指令标签默认为HTML注释的形式,在指令标签内允许声明 指令起始
、指令结束
和注释
。
指令起始
的语法形式为: 。其中, command-value 的具体语法形式详情请参见各指令相关章节。
<!-- target: targetName -->
<!-- if: ${number} > 0 -->
<!-- for: ${persons} as ${person}, ${index} -->
指令结束
的语法形式为: 。
<!-- /if -->
<!-- /for -->
<!-- /target -->
注释
的语法形式为: ,注释指令在render时将不输出。
<!-- // just add some message -->
如果不期望使用HTML注释形式的指令标签,可以通过config API可以配置指令标签的形式:
etpl.config({
commandOpen: '<%',
commandClose: '%>'
});
/*
配置指令标签的形式为“<% ... %>”,然后指令标签可以像下面一样声明:
<% if: ${number} > 0 %>
greater than zero
<% /if %>
*/
为了减少开发者的工作量,部分指令标签支持自动结束
,模板开发者无需手工编写指令结束
。比如:当遇见target指令起始时,ETPL自动认为上一个target已经结束。
具体指令的自动结束
支持,请参考相应指令相关章节。
target
是ETPL的基本单元,其含义是 一个模版片段 。target
可用于render,也可用于被其他target
所import或use。
如果仅仅编写的是一个模板片段,可以省略target
的声明。这样的编写方式与其他模板引擎类似,ETPL将默认生成匿名target,但模板片段将不可复用(不可被import或use,不可指定母版)。
匿名target应位于模板源码起始。下面例子中,位于其他target后的模板片段Bye
将没有任何作用。
<!-- use: hello(name=${name}) -->
<!-- target: hello -->
Hello ${name}!
<!-- /target -->
Bye
target的语法形式为:
target: target-name
target: target-name(master=master-name)
target声明可以为其指定相应的母版。母版功能请参考模板复用章节。
target支持自动结束,当遇见 target 或 master 时自动结束。
<!-- target: hello -->
Hello <strong>ETPL</strong>!
<!-- target: bye -->
Bye <strong>ETPL</strong>!
通过var
指令可以在模板内部声明一个变量。声明的变量在整个target
内有效。
var的语法形式为:
var: var-name=expression
expression
中可以使用静态或动态数据。
<!-- var: age = 18 -->
<!-- var: age = ${person.age} -->
<!-- var: name = 'etpl' -->
var无需编写指令结束
,其将在指令起始
后立即自动结束。
绝大多数模板引擎都支持变量替换功能。ETPL变量替换的语法为:
${variable-name}
${variable-name|filter-name}
${variable-name|filter-name(arguments)}
${variable-name|filter1|filter2(arguments)|filter3|...}
variable-name支持.
形式的property access。
编写模板时可以指定filter,默认使用html filter进行HTML转义。如果想要保留变量的原形式,需要手工指定使用名称为raw的filter,或者通过config API配置引擎的defaultFilter参数。
${myVariable|raw}
etpl.config({
defaultFilter: ''
});
ETPL默认支持3种filters,可以通过引擎的addFilter
方法自定义扩展filter。
变量替换支持多filter处理。filter之间以类似管道的方式,前一个filter的输出做为后一个filter的输入,向后传递。
${myVariable|html|url}
filter支持参数传递,参数可以使用动态数据。
<!-- // 假设存在扩展filter: comma -->
${myVariable|comma(3)}
${myVariable|comma(${commaLength})}
${myVariable|comma(${commaLength}+1)}
在变量替换中,引擎会默认将数据toString后传递给filter,以保证filter输入输出的类型一致性。如果filter期望接受的是原始数据,模板开发者需要通过前缀的*
指定。
<!-- // 假设存在扩展filter: dateFormat -->
${*myDate|dateFormat('yyyy-MM-dd')}
除了在变量替换中可以使用filter进行处理,ETPL还可以通过filter
指令,使用指定的filter对一个模板内容块进行过滤处理。
filter的语法形式为:
filter: filter-name
filter: filter-name(arguments)
下面的例子假定使用者实现了一个markdown的filter
<!-- filter: markdown(${useExtra}, true) -->
## markdown document
This is the content, also I can use `${variables}`
<!-- /filter -->
filter指令不支持自动结束,必须手工编写指令结束
。
<!-- /filter -->
ETPL支持多种形式的模板复用方式,帮助模板开发者减少模板编写的重复劳动和维护成本。
通过import指令,可以在当前位置插入指定target的源码。
import的语法形式为:
import: target-name
<!-- target: hello -->
Hello <strong>${name}</strong>!
<!-- target: main -->
<div class="main"><!-- import: hello --></div>
import无需编写指令结束
,其将在指令起始
后立即自动结束。
通过master
指令可以声明一个母版,母版中通过contentplaceholder
指令声明可被替换的部分。
target
声明时通过 master=master-name 指定一个母版,就可以继承于这个母版的片段,并且通过content
指令,替换母版中contentplaceholder
指令声明部分的内容。指定母版的target中只允许包含content
指令声明的片段。
母版功能支持多层母版,master
声明时也可以通过 master=master-name 指定一个母版。母板中的contentplaceholder
不会再传递下去,即contentplaceholder
只在一层有效。
master的语法形式为:
master: master-name
master: master-name(master=master-name)
contentplaceholder的语法形式为:
contentplaceholder: content-name
content的语法形式为:
content: content-name
<!-- master: myMaster -->
<div class="title"><!-- contentplaceholder: title -->title<!-- /contentplaceholder --></div>
<div class="main"><!-- contentplaceholder: main --></div>
<!-- master: myMaster-has-sidebar(master=myMaster) -->
<!-- content: title -->
title for has sidebar
<!-- content: main -->
<div class="sidebar"><!-- contentplaceholder: sidebar --></div>
<div class="article"><!-- contentplaceholder: article --></div>
<!-- target: myTarget(master=myMaster) -->
<!-- content: title -->
Building WebKit from Xcode
<!-- content: main -->
<p>To build from within Xcode, you can use the WebKit workspace. </p>
<!-- target: myTarget-has-sidebar(master=myMaster-has-sidebar) -->
<!-- content: sidebar -->
<ul class="navigator">...</ul>
<!-- content: article -->
<p>To build from within Xcode, you can use the WebKit workspace. </p>
master支持自动结束,当遇见 target 或 master 时自动结束。
contentplaceholder支持自动结束,当遇见 contentplaceholder 或 target 或 master 时,在指令标签起始
后自动结束。
content支持自动结束,当遇见 content 或 target 或 master 时自动结束。
通过use
指令,可以调用指定target
,在当前位置插入其render后的结果。允许使用静态或动态数据指定数据项。
use的语法形式为:
use: target-name
use: target-name(data-name=expression, data-name=expression)
<!-- target: info -->
name: ${name}
<!-- if: ${email} -->
email: ${email}
<!-- /if -->
<!-- target: main -->
<div class="main"><!-- use: info(name=${person.name}, email=${person.email}) --></div>
use无需编写指令结束
,其将在指令起始
后立即自动结束。
ETPL提供了分支的支持,相关指令有if
、elif
、else
。
if的语法形式为:
if: conditional-expression
elif的语法形式为:
elif: conditional-expression
else的语法形式为:
else
conditional-expression中可以使用动态数据,通过${variable}
的形式,可以使用模板render的data。${variable}
支持.
的property accessor。
if指令不支持自动结束,必须手工编写指令结束<!-- /if -->
。
<!-- if: ${number} > 0 -->
larger than zero
<!-- elif: ${number} == 0 -->
zero
<!-- else -->
invalid
<!-- /if -->
if指令不支持自动结束,必须手工编写指令结束
。
<!-- /if -->
通过for指令的支持,可以实现对Array和Object的遍历。Array为正序遍历,Object为不保证顺序的forin。
for的语法形式为:
for: ${variable} as ${item-variable}
for: ${variable} as ${item-variable}, ${index-variable}
for: ${variable} as ${item-variable}, ${key-variable}
其中,${variable}
为想要遍历的对象,支持.
形式的property access。在遍历过程中,声明的${item-variable}
和${index-variable}
,分别代表数据项和索引(遍历Object时为键名)。
<ul>
<!-- for: ${persons} as ${person}, ${index} -->
<li>${index}: ${person.name}
<!-- /for -->
</ul>
for指令不支持自动结束,必须手工编写指令结束
。
<!-- /for -->
ETPL初始化时自动创建一个默认的引擎实例,并将其暴露。大多数应用场景可直接使用默认的引擎实例。
var etpl = require( 'etpl' );
为默认引擎添加过滤器。过滤函数的第一个参数为过滤源字符串,其后的参数可由模板开发者传入。过滤函数必须返回string。
{string}
name - 过滤器名称{Function}
filter - 过滤函数etpl.addFilter( 'markdown', function ( source, useExtra ) {
// ......
} );
使用默认引擎编译模板。返回第一个target编译后的renderer函数。
{string}
source - 模板源代码var helloRenderer = etpl.compile( 'Hello ${name}!' );
helloRenderer( {name: 'ETPL'} ); // Hello ETPL!
对默认引擎进行配置,配置参数将合并到引擎现有的参数中。
{Object}
options - 配置参数对象{string}
options.commandOpen - 命令语法起始串,默认值为 <!--{string}
options.commandClose - 命令语法结束串,默认值为 -->{string}
options.defaultFilter - 默认变量替换的filter,默认值为 html{boolean}
options.strip - 是否清除命令标签前后的空白字符,默认值为 false{string}
options.namingConflict - target或master名字冲突时的处理策略,值可以是error
| ignore
| override
,分别代表抛出错误
、保留现有目标,忽略新目标
、覆盖现有目标
。默认值为 erroretplEngine.config( {
defaultFilter: ''
} );
从默认引擎中,根据target名称获取模板内容。
{string}
name - target名称etpl.compile( '<!-- target: hello -->Hello ${name}!' );
etpl.get( 'hello' ); // Hello ${name}!
从默认引擎中,根据target名称获取编译后的renderer函数。
{string}
name - target名称etpl.compile( '<!-- target: hello -->Hello ${name}!' );
var helloRenderer = etpl.getRenderer( 'hello' );
helloRenderer( {name: 'ETPL'} ); // Hello ETPL!
同compile
方法。该方法的存在是为了兼容老版本的模板引擎api,不建议使用。
使用默认引擎执行模板渲染,返回渲染后的字符串。
{string}
name - target名称{Object}
data - 模板数据。可以是plain object,也可以是带有 {string}get({string}name) 方法的对象etpl.compile( '<!-- target: hello -->Hello ${name}!' );
etpl.render( 'hello', {name: 'ETPL'} ); // Hello ETPL!
不同的引擎实例可有效避免target命名冲突的问题。
下面的代码可以初始化一个新的引擎实例。
var etpl = require( 'etpl' );
var etplEngine = new etpl.Engine();
引擎实例的初始化允许传入引擎参数。支持的引擎参数见下面的config
方法。
var etpl = require( 'etpl' );
var etplEngine = new etpl.Engine({
commandOpen: '<%',
commandClose: '%>'
});
添加过滤器。过滤函数的第一个参数为过滤源字符串,其后的参数可由模板开发者传入。过滤函数必须返回string。
{string}
name - 过滤器名称{Function}
filter - 过滤函数etplEngine.addFilter( 'markdown', function ( source, useExtra ) {
// ......
} );
编译模板。返回第一个target编译后的renderer函数。
{string}
source - 模板源代码var helloRenderer = etplEngine.compile( 'Hello ${name}!' );
helloRenderer( {name: 'ETPL'} ); // Hello ETPL!
对引擎进行配置,配置参数将合并到引擎现有的参数中。
{Object}
options - 配置参数对象{string}
options.commandOpen - 命令语法起始串,默认值为 <!--{string}
options.commandClose - 命令语法结束串,默认值为 -->{string}
options.defaultFilter - 默认变量替换的filter,默认值为 html{boolean}
options.strip - 是否清除命令标签前后的空白字符,默认值为 false{string}
options.namingConflict - target或master名字冲突时的处理策略,值可以是error
| ignore
| override
,分别代表抛出错误
、保留现有目标,忽略新目标
、覆盖现有目标
。默认值为 erroretplEngine.config( {
defaultFilter: ''
} );
根据target名称获取模板内容。
{string}
name - target名称etplEngine.compile( '<!-- target: hello -->Hello ${name}!' );
etplEngine.get( 'hello' ); // Hello ${name}!
根据target名称获取编译后的renderer函数。
{string}
name - target名称etplEngine.compile( '<!-- target: hello -->Hello ${name}!' );
var helloRenderer = etplEngine.getRenderer( 'hello' );
helloRenderer( {name: 'ETPL'} ); // Hello ETPL!
执行模板渲染,返回渲染后的字符串。
{string}
name - target名称{Object}
data - 模板数据。可以是plain object,也可以是带有 {string}get({string}name) 方法的对象etplEngine.compile( '<!-- target: hello -->Hello ${name}!' );
etplEngine.render( 'hello', {name: 'ETPL'} ); // Hello ETPL!
ETPL的前身是ER框架自带的简易模板引擎,其基本与前身保持兼容。但由于一些考虑因素,存在以下一些不兼容的地方。
出于代码体积和使用频度的考虑,ETPL删除了merge
API。如果想要该API,请在自己的应用中加入如下代码:
/**
* 执行模板渲染,并将渲染后的字符串作为innerHTML填充到HTML元素中。
* 兼容老版本的模板引擎api
*
* @param {HTMLElement} element 渲染字符串填充的HTML元素
* @param {string} name target名称
* @param {Object=} data 模板数据
*/
etpl.merge = function ( element, name, data ) {
if ( element ) {
element.innerHTML = this.render( name, data );
}
};
FAQs
ETPL是一个强复用、灵活、高性能的JavaScript模板引擎,适用于浏览器端或Node环境中视图的生成。
The npm package etpl receives a total of 17 weekly downloads. As such, etpl popularity was classified as not popular.
We found that etpl demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
Research
Security News
Socket researchers have discovered multiple malicious npm packages targeting Solana private keys, abusing Gmail to exfiltrate the data and drain Solana wallets.