opine/lightncandy
Opine-PHP 是一个极快 PHP 实现 handlebars (https://handlebars.node.org.cn/) 和 mustache (http://mustache.github.io/)。
Requires
- php: >=5.3.0
Requires (Dev)
- phpunit/phpunit: 4.0.17
README
handlebars (https://handlebars.node.org.cn/) 和 mustache (http://mustache.github.io/) 的极快 PHP 实现。
特性
- 无逻辑模板:mustache (http://mustache.github.com/) 或 handlebars (https://handlebars.node.org.cn/)
- 将模板编译为 纯 PHP 代码。示例
- 极快!
- 比 mustache.php 快 4~6 倍。
- 比 mustache-php 快 4~10 倍。
- 比 handlebars.php 快 10~30 倍。
- 详细性能测试报告可以在 这里 找到,去 http://zordius.github.io/HandlebarsTest/ 查看图表。
- 小巧! 单个 PHP 文件,只有 107K!
- 健壮!
- 100% 支持 mustache 规范 v1.1.2(无 lambda 模块)
- 支持几乎所有 handlebars.js 规范
- 输出与 SAME 相同,使用 handlebars.js
- 灵活!
- 许多 选项 可用于更改功能和行为。
- 上下文生成
- 从模板中分析使用过的功能(使用
LightnCandy::getContext()
获取它)。
- 从模板中分析使用过的功能(使用
- 调试
- 生成调试版模板
- 在渲染模板时找出缺失的数据。
- 生成可视觉调试的模板。
- 生成调试版模板
- 独立模板
- 编译后的PHP代码可以在不包含任何PHP库的情况下运行。在执行渲染函数时,无需包含LightnCandy。
安装
使用Composer(https://getcomposer.org.cn/)安装LightnCandy
composer require zordius/lightncandy:dev-master
或者,从GitHub下载LightnCandy
curl -LO https://github.com/zordius/lightncandy/raw/master/src/lightncandy.php
LightnCandy要求:PHP 5.3.0+。
升级通知
- 请查看 HISTORY.md 了解版本历史。
- 请查看 UPGRADE.md 了解升级通知。
用法
// THREE STEPS TO USE LIGHTNCANDY // Step 1. require the lib, compile template, and get the PHP code as string require('src/lightncandy.php'); $template = "Welcome {{name}} , You win \${{value}} dollars!!\n"; $phpStr = LightnCandy::compile($template); // compiled PHP code in $phpStr // Step 2A. (Usage 1) use LightnCandy::prepare to get rendering function // DEPRECATED , it may require PHP setting allow_url_fopen=1 , // and allow_url_fopen=1 is not secure . // When allow_url_fopen = 0, prepare() will create tmp file then include it, // you will need to add your tmp directory into open_basedir. // YOU MAY NEED TO CHANGE PHP SETTING BY THIS WAY $renderer = LightnCandy::prepare($phpStr); // Step 2B. (Usage 2) Store your render function in a file // You decide your compiled template file path and name, save it. // You can load your render function by include() later. // RECOMMENDED WAY file_put_contents($php_inc, $phpStr); $renderer = include($php_inc); // Step 3. run native PHP render function any time echo "Template is:\n$template\n\n"; echo $renderer(Array('name' => 'John', 'value' => 10000)); echo $renderer(Array('name' => 'Peter', 'value' => 1000));
输出将是
Template is:
Welcome {{name}} , You win ${{value}} dollars!!
Welcome John , You win $10000 dollars!!
Welcome Peter , You win $1000 dollars!!
编译选项
您可以通过运行 LightnCandy::compile($template, $options)
应用更多选项。
LightnCandy::compile($template, Array( 'flags' => LightnCandy::FLAG_ERROR_LOG | LightnCandy::FLAG_STANDALONE ));
默认情况下,将模板编译为PHP,这可以尽可能快地运行(标志 = FLAG_BESTPERFORMANCE
)。
FLAG_ERROR_LOG
:当发现任何模板错误时,使用error_log()。FLAG_ERROR_EXCEPTION
:当发现任何模板错误时抛出异常。FLAG_ERROR_SKIPPARTIAL
:跳过'部分未找到'错误/异常。使用此选项与mustache规范保持一致。FLAG_NOESCAPE
:不执行任何HTML转义于{{var}}。FLAG_STANDALONE
:生成独立的PHP代码,可以在不包含LightnCandy.php的情况下执行。编译后的PHP代码将包含作用域内的用户函数,因此体积较大。而且,模板的性能将慢1 ~ 10%。FLAG_JSTRUE
:当值是true或false时生成'true'或'false'(JavaScript行为)。否则,true/false将生成''。FLAG_JSOBJECT
:对于关联数组生成'[object Object]',对于数组生成以逗号分隔的值(JavaScript行为)。否则,所有PHP数组将生成''或'Array'。FLAG_THIS
:在模板中将{{this}}
解析为{{.}}
。否则,{{this}}
将被解析为普通变量。FLAG_WITH
:支持模板中的{{#with var}}
。否则,{{#with var}}
将导致模板错误。FLAG_PARENT
:支持模板中的{{../var}}
。否则,{{../var}}
将导致模板错误。FLAG_JSQUOTE
:将'
转义为'
,将`
转义为`
。否则,'
将被转义为'
,`
将不被处理。FLAG_ADVARNAME
:支持模板中{{foo.[0].[#te#st].bar}}
风格的复杂变量命名。如果您想使用"some string"
或(subexpresssion)
作为参数,请使用此标志。FLAG_NAMEDARG
:支持自定义helper的命名参数{{helper name1=val1 nam2=val2 ...}}
。FLAG_EXTHELPER
:不要将自定义helper代码包含在编译后的PHP代码中。这可以减少代码大小,但您需要在渲染时注意您的helper函数。如果您在执行渲染函数时忘记包含所需的函数,将触发undefined function
运行时错误。注意:匿名函数将始终放置在生成的代码中。FLAG_RUNTIMEPARTIAL
:将部分编译为运行时函数,这使递归部分或部分上下文更改成为可能。FLAG_SLASH
:在\
之后跳过一个分隔符。FLAG_ELSE
:支持handlebars规范中的{{else}}
或{{^}}
。否则,{{else}}
将被解析为普通变量,而{{^}}
将导致模板错误。FLAG_PROPERTY
: 支持对象实例属性访问。FLAG_METHOD
: 支持对象实例方法访问。FLAG_INSTANCE
: 与FLAG_PROPERTY
+FLAG_METHOD
相同。FLAG_SPACECTL
: 在模板中支持空间控制{{~ }}
或{{ ~}}
。否则,{{~ }}
或{{ ~}}
将导致模板错误。FLAG_SPVARS
: 支持特殊变量包括 @root, @index, @key, @first, @last。否则,使用默认解析逻辑编译这些变量名。FLAG_JS
: 模拟所有 JavaScript 字符串转换行为,等同于FLAG_JSTRUE
+FLAG_JSOBJECT
。FLAG_HANDLEBARS
: 支持所有 Handlebars 扩展(Handlebars 不支持的),等同于FLAG_THIS
+FLAG_WITH
+FLAG_PARENT
+FLAG_JSQUOTE
+FLAG_ADVARNAME
+FLAG_NAMEDARG
+FLAG_SLASH
+FLAG_ELSE
+FLAG_MUSTACHESP
+FLAG_MUSTACHEPAIN
。FLAG_HANDLEBARSJS
: 与 handlebars.js 行为一致,等同于FLAG_JS
+FLAG_HANDLEBARS
。FLAG_MUSTACHESP
: 将行更改和间距行为与 mustache 规范对齐。FLAG_MUSTACHELOOKUP
: 将递归查找行为与 mustache 规范对齐。FLAG_MUSTACHEPAIN
: 将部分缩进行为与 mustache 规范对齐。FLAG_MUSTACHESEC
: 将{{#foo}}
部分段落上下文行为与 mustache 规范对齐。FLAG_MUSTACHE
: 支持所有 mustache 规范,等同于FLAG_ERROR_SKIPPARTIAL
+FLAG_MUSTACHESP
+FLAG_MUSTACHELOOKUP
+FLAG_MUSTACHEPAIN
+FLAG_MUSTACHESEC
。FLAG_ECHO
: 编译为echo 'a', $b, 'c';
以提高性能。当模板和数据简单时,这会减慢渲染速度,但当数据量大且在模板中循环时,将提高 1% ~ 7%。FLAG_BESTPERFORMANCE
: 现在等同于FLAG_ECHO
。此标志可能根据性能测试结果在未来进行更改。FLAG_RENDER_DEBUG
: 生成调试模板以显示渲染时的错误。使用此标志时,渲染性能可能会减慢。
部分支持
LightnCandy 在编译时支持部分。您可以在 compile()
时通过 partials
选项提供部分。
LightnCandy::compile($template, Array( 'partials' => Array( 'name' => 'template: {{name}}', ), ));
您还可以通过文件提供部分。在 compile()
时,如果提供了基于 basedir
的选项,LightnCandy 将从 basedir
中搜索模板文件。默认模板文件名为 *.tmpl
,您可以使用 fileext
选项更改或添加更多模板文件扩展名。
// Loading partial from file system only when valid directory is provided by basedir option // '.' means getpwd() LightnCandy::compile($template, Array( 'basedir' => '.' )); // Multiple basedir and fileext are supported LightnCandy::compile($template, Array( 'flags' => LightnCandy::FLAG_STANDALONE, 'basedir' => Array( '/usr/local/share/handlebars/templates', '/usr/local/share/my_project/templates', '/usr/local/share/my_project/partials', ), 'fileext' => Array( '.tmpl', '.mustache', '.handlebars', ) ));
使用此设置,当您通过 {{> partial_name}}
包含部分时,LightnCandy 将按以下顺序搜索
- /usr/local/share/handlebars/templates/partial_name.tmpl
- /usr/local/share/handlebars/templates/partial_name.mustache
- /usr/local/share/handlebars/templates/partial_name.handlebars
- /usr/local/share/my_project/templates/partial_name.tmpl
- /usr/local/share/my_project/templates/partial_name.mustache
- /usr/local/share/my_project/templates/partial_name.handlebars
- /usr/local/share/my_project/partials/partial_name.tmpl
- /usr/local/share/my_project/partials/partial_name.mustache
- /usr/local/share/my_project/partials/partial_name.handlebars
默认情况下,部分使用与原始模板相同的上下文。如果您想更改部分的上下文,您可以在部分名称后添加一个额外的参数。
{{>partial_name .}} // Same as {{>partial_name}}
{{>partial_name foo}} // Change input context to foo, FLAG_RUNTIMEPARTIAL required
{{>partial_name ..}} // use {{..}} as new input context, FLAG_RUNTIMEPARTIAL required
自定义助手
自定义助手可以帮助您处理常见的模板任务,例如:提供 URL 和文本,然后生成一个链接。有关自定义助手的更多信息,您可以在此处阅读原始 handlebars.js 文档:https://handlebars.node.org.cn/expressions.html。
注意:处理单个标签 {{xxx}}
或部分 {{#yyy}} ... {{/yyy}}
的自定义助手在 LightnCandy 中绝对不同。有关创建用于处理 {{#yyy}} ... {{/yyy}}
的自定义助手的更多信息,请参阅 块自定义助手。
在 compile()
时,LightnCandy 将从生成的自定义助手名称表中查找助手。您可以使用 helpers
选项注册自定义助手(注意:FLAG_NAMEDARG
对于命名参数是必需的,FLAG_ADVARNAME
对于字符串或子表达式参数是必需的)
LightnCandy::compile($template, Array( // FLAG_NAMEDARG is required if you want to use named arguments 'flags' => LightnCandy::FLAG_HANDLEBARS 'helpers' => Array( // 1. You may pass your function name // When the function is not exist, you get compile time error // In this case, the helper name is same with function name // Template: {{my_helper_functoin ....}} 'my_helper_function', // 2. You may also provide a static call from a class // In this case, the helper name is same with provided full name // **DEPRECATED** It is not valid in handlebars.js // Template: {{myClass::myStaticMethod ....}} 'myClass::myStaticMethod', // 3. You may also provide an alias name for helper function // This help you to mapping different function to a preferred helper name // Template: {{helper_name ....}} 'helper_name' => 'my_other_helper', // 4. Alias also works well for static call of a class // This help you to mapping different function to a preferred helper name // Template: {{helper_name2 ....}} 'helper_name2' => 'myClass::func', // 5. Anonymous function should be provided with alias // The function will be included in generaed code always // Template: {{helper_name3 ....}} 'helper_name3' => function ($arg1, $arg2) { return "<a href=\"{$arg1}\">{$arg2}</a>"; } ) ));
自定义助手接口
输入参数将由LightnCandy自动处理,您无需担心变量名处理或当前上下文。您还可以使用双引号字符串作为输入。
{{{helper name}}} // This send processed {{{name}}} into the helper
{{{helper ../name}}} // This send processed {{{../name}}} into the helper
{{{helper "Test"}}} // This send the string "Test" into the helper (FLAG_ADVARNAME is required)
{{helper "Test"}} // This send the string "Test" into the helper and escape the helper result
{{{helper "Test" ../name}}} // This send string "Test" as first parameter,
// and processed {{{../name}}} as second parameter into the helper
您的自定义辅助函数将以两个参数执行。第一个是非命名参数,第二个是命名参数。
function myhelper ($args, $named) { if (count($args)) { // handle no name arguments.... } // access foo=bar from $named['foo'] ... }
在您的模板中
{{{helper name=value}}} // This send processed {{{value}}} into $named['name']
{{{helper name="value"}}} // This send the string "value" into $named['name']
{{{helper [na me]="value"}}} // You can still protect the name with [ ]
// so you get $named['na me'] as the string 'value'
{{{helper url name="value"}}} // This send processed {{{url}}} into $args[0]
// and the string "value" into $named['name']
自定义辅助函数转义
您自定义辅助函数的返回值应该是一个字符串。当您的自定义辅助函数从{{}}中执行时,返回值将被HTML转义。您可以通过{{{}}}执行您的辅助函数,然后直接输出原始辅助函数的返回值。
当您需要进行不同的转义逻辑时,您可以通过Array($responseString, $escape_flag)返回扩展信息,以下是一些自定义辅助函数返回值的示例。
// escaping is handled by lightncandy and decided by template // if the helper is in {{ }} , you get 'The U&ME Helper is ececuted!' // if the helper is in {{{ }}} , you get 'The U&ME Helper is executed!' return 'The U&ME Helper is executed!'; // Same as above because the escape_flag is DEFAULT // 0, false, null, undefined, or '' means DEFAULT return Array('The U&ME Helper is executed!'); return Array('The U&ME Helper is executed!', false); return Array('The U&ME Helper is executed!', 0); // escaping is handled by the helper, lightncandy will do nothing // No matter in {{ }} or {{{ }}} , you get 'Exact&Same output \' \" Ya!' return Array('Exact&Same output \' " Ya!', 'raw'); // force lightncandy escaping the helper result // No matter in {{ }} or {{{ }}} , you get 'Not&Same output ' " Ya!' return Array('Not&Same output \' " Ya!', 'enc'); // force lightncandy escaping the helper result in handlebars.js way // No matter in {{ }} or {{{ }}} , you get 'Not&Same output ' " Ya!' return Array('Not&Same output \' " Ya!', 'encq');
块自定义辅助函数
块自定义辅助函数必须用作一个部分,部分以{{#helper_name ...}}
开始,以{{/helper_name}}
结束。
您可以使用块自定义辅助函数
- 提供不同于
{{#if ...}}
...{{/if}}
的高级条件逻辑。 - 修改内部块的当前上下文。
- 为内部块提供不同的上下文。
您可以使用blockhelpers
选项注册块自定义辅助函数。
LightnCandy::compile($template, Array( 'blockhelpers' => Array( // The usage of blockhelpers option is similar with helpers option. 'my_helper_function', // You can use function name, class name with static method, ... // and choose preferred helper name by providing key name. ) ));
块自定义辅助函数接口
LightnCandy为您处理所有输入参数,您将收到当前上下文和解析后的参数。辅助函数的返回值将成为新上下文,然后传递到内部块。如果您没有返回任何值,或返回null,内部块将不会渲染。例如
// Only render inner block when input > 5 // {{#helper_iffivemore total_people}}More then 5 people, discount!{{/helper_iffivemore}} function helper_iffivemore($cx, $args, $named) { return $args[0] > 5 ? $cx : null; } // You can use named arguments, too // {{#helper_if value=people logic="more" tovalue=5}}Yes the logic is true{{/helper_if}} function helper_if($cx, $args, $named) { switch ($args['logic']) { case 'more': return $named['value'] > $named['tovalue'] ? $cx : null; case 'less': return $named['value'] < $named['tovalue'] ? $cx : null; case 'eq': return $named['value'] == $named['tovalue'] ? $cx : null; } } // Provide default values for name and salary // {{#helper_defaultpeople}}Hello, {{name}} ....Your salary will be {{salary}}{{/helper_defaultpeople}} function helper_defaultpeople($cx, $args, $named) { if (!isset($cx['name'])) { $cx['name'] = 'Sir'; } $cx['salary'] = isset($cx['salary']) ? '$' . $cx['salary'] : 'unknown'; return $cx; } // Provide specific context to innerblock // {{#helper_sample}}Preview Name:{{name}} , Salary:{{salary}}.{{/helper_sample}} function helper_sample($cx, $args) { return Array('name' => 'Sample Name', 'salary' => 'Sample Salary'); }
您不能在块自定义辅助函数中提供新的渲染结果,也不能处理循环。要提供不同的渲染结果,您应该使用自定义辅助函数。要处理循环,您应该使用{{#each}}
。例如
// Provide specific context to innerblock, then loop on it. // {{#helper_categories}}{{#each .}}<li><a href="?id={{id}}">{{name}}</a></li>{{/each}}{{/helper_categories}} function helper_categories($cx, $args) { return getMyCategories(); // Array('category1', 'category2', ...) }
块自定义辅助函数的任务仅在于为内部块提供不同的上下文或逻辑,除此之外没有其他任务。
Handlebars.js的自定义辅助函数
您可以使用hbhelpers
选项以Handlebars.js的方式实现辅助函数,所有匹配的单个自定义辅助函数和块自定义辅助函数都将被处理。在Handlebars.js中,块自定义辅助函数可以通过执行options->fn渲染子块,并通过将新上下文作为第一个参数发送来更改上下文。以下是一些示例来解释hbhelpers
自定义辅助函数的行为。
#mywith(上下文更改)
- LightnCandy
// LightnCandy sample, #mywith works same with #with $php = LightnCandy::compile($template, Array( 'flags' => LightnCandy::FLAG_HANDLEBARSJS, 'hbhelpers' => Array( 'mywith' => function ($context, $options) { return $options['fn']($context); } ) ));
- Handlebars.js
// Handlebars.js sample, #mywith works same with #with Handlebars.registerHelper('mywith', function(context, options) { return options.fn(context); });
#myeach(上下文更改)
- LightnCandy
// LightnCandy sample, #myeach works same with #each $php = LightnCandy::compile($template, Array( 'flags' => LightnCandy::FLAG_HANDLEBARSJS, 'hbhelpers' => Array( 'myeach' => function ($context, $options) { $ret = ''; foreach ($context as $cx) { $ret .= $options['fn']($cx); } return $ret; } ) ));
- Handlebars.js
// Handlebars.js sample, #myeach works same with #each Handlebars.registerHelper('myeach', function(context, options) { var ret = '', i, j = context.length; for (i = 0; i < j; i++) { ret = ret + options.fn(context[i]); } return ret; });
#myif(不更改上下文)
- LightnCandy
// LightnCandy sample, #myif works same with #if $php = LightnCandy::compile($template, Array( 'flags' => LightnCandy::FLAG_HANDLEBARSJS, 'hbhelpers' => Array( 'myif' => function ($conditional, $options) { if ($conditional) { return $options['fn'](); } else { return $options['inverse'](); } } ) ));
- Handlebars.js
// Handlebars.js sample, #myif works same with #if Handlebars.registerHelper('myif', function(conditional, options) { if (conditional) { return options.fn(this); } else { return options.inverse(this); } });
散列参数
- LightnCandy
$php = LightnCandy::compile($template, Array( 'flags' => LightnCandy::FLAG_HANDLEBARSJS, 'hbhelpers' => Array( 'sample' => function ($arg1, $arg2, $options) { // All hashed arguments are in $options['hash'] } ) ));
- Handlebars.js
Handlebars.registerHelper('sample', function(arg1, arg2, options) { // All hashed arguments are in options.hash });
转义
当Handlebars.js样式的自定义辅助函数用作块标签时,LightnCandy不会转义结果。当它是单个{{...}}标签时,LightnCandy将转义结果。要更改转义行为,您可以通过Array()返回扩展信息,请参阅自定义辅助函数转义以获取更多信息。
模板调试
当模板发生错误时,LightnCandy::compile()将返回false。您可以使用FLAG_ERROR_LOG
编译以查看更多错误消息,或使用FLAG_ERROR_EXCEPTION
编译以捕获异常。
当编译()时,您可以使用FLAG_RENDER_DEBUG
生成模板的调试版本。调试模板包含更多调试信息,但速度较慢(待定:性能结果),您可以将额外的LCRun3选项传递给render函数以了解更多的渲染错误(缺少数据)。例如
$template = "Hello! {{name}} is {{gender}}. Test1: {{@root.name}} Test2: {{@root.gender}} Test3: {{../test3}} Test4: {{../../test4}} Test5: {{../../.}} Test6: {{../../[test'6]}} {{#each .}} each Value: {{.}} {{/each}} {{#.}} section Value: {{.}} {{/.}} {{#if .}}IF OK!{{/if}} {{#unless .}}Unless not OK!{{/unless}} "; // compile to debug version $php = LightnCandy::compile($template, Array( 'flags' => LightnCandy::FLAG_RENDER_DEBUG | LightnCandy::FLAG_HANDLEBARSJS )); // Get the render function $renderer = LightnCandy::prepare($php); // error_log() when missing data: // LCRun3: [gender] is not exist // LCRun3: ../[test] is not exist $renderer(Array('name' => 'John'), LCRun3::DEBUG_ERROR_LOG); // Output visual debug template with ANSI color: echo $renderer(Array('name' => 'John'), LCRun3::DEBUG_TAGS_ANSI); // Output debug template with HTML comments: echo $renderer(Array('name' => 'John'), LCRun3::DEBUG_TAGS_HTML);
ANSI输出将是
以下是render函数的LCRun3调试选项列表
DEBUG_ERROR_LOG
:缺少所需数据时调用error_log()DEBUG_ERROR_EXCEPTION
:缺少所需数据时抛出异常DEBUG_TAGS
:将render函数的返回值转换为标准化mustache标签DEBUG_TAGS_ANSI
:将渲染函数的返回值转换为带有ANSI颜色的标准化mustache标签。DEBUG_TAGS_HTML
:将渲染函数的返回值转换为带有HTML注释的标准化mustache标签。
不支持的功能(目前如此)
- [NEVER]
{{foo/bar}}
风格的变量名,在官方handlebars.js文档中已弃用。 - [maybe] mustache lambda:基于输入值的运行时编译远离lightncandy的本质,目前不在计划中。
建议的Handlebars模板实践
- 避免使用
{{#with}}
。我认为{{path.to.val}}
比{{#with path.to}}{{val}}{{/with}}
更易读;当使用{{#with}}
时,您可能会在作用域变化上感到困惑。{{#with}}
仅在您需要访问同一路径下的多个变量时能节省您很少的时间,但在您需要理解并维护模板时则会花费大量时间。 - 当您不需要在值上使用HTML转义时,请使用
{{{val}}}
。它也有更好的性能。 - 如果您想显示
{{
,请使用这个:{{{"{{"}}}
,避免使用\{{
。 - 如果您想在不同的语言中重复使用模板,请避免使用自定义助手。或者,您可能需要在不同的语言中实现不同版本的助手。
- 为了获得最佳性能,您应该在开发阶段仅使用“按需编译”模式。在您进入生产阶段之前,可以对所有模板执行
LightnCandy::compile()
,保存所有生成的PHP代码,并部署这些生成的文件(您可能需要维护一个构建过程)。不要在生产中编译,这也是一个最佳的安全实践。为“按需编译”添加缓存不是最佳解决方案。如果您想基于LightnCandy构建某些库或框架,请考虑这种情况。 - 每次升级LightnCandy时,都要重新编译模板。
详细功能列表
访问https://handlebars.node.org.cn/以查看关于handlebars.js的更多功能描述。所有功能都与它一致。
- 与handlebars.js完全相同的CR/LF行为
- 与mustache规范(需要
FLAG_MUSTACHESP
)完全相同的CR/LF行为 - 与handlebars.js完全相同的“true”或“false”输出(需要
FLAG_JSTRUE
) - 与handlebars.js完全相同的"[object Object]"输出或join(',')数组输出(需要
FLAG_JSOBJECT
) - 可以在
{{ var }}
或{{{ var }}}
内部放置标题/尾部空格、制表符、CR/LF - 部分缩进行为与mustache规范相同(需要
FLAG_MUSTACHEPAIN
) - 递归变量查找到父上下文的行为与mustache规范相同(需要
FLAG_MUSTACHELOOKUP
) {{{value}}}
或{{&value}}
:原始变量- 作为“true”(需要
FLAG_JSTRUE
) - 作为“false”(需要
FLAG_TRUE
)
- 作为“true”(需要
{{value}}
:HTML转义的变量- 作为“true”(需要
FLAG_JSTRUE
) - 作为“false”(需要
FLAG_JSTRUE
)
- 作为“true”(需要
{{{path.to.value}}}
:点表示法,原始{{path.to.value}}
:点表示法,HTML转义{{.}}
:当前上下文,HTML转义{{{.}}}
:当前上下文,原始{{this}}
:当前上下文,HTML转义(需要FLAG_THIS
){{{this}}}
:当前上下文,原始(需要FLAG_THIS
){{#value}}
:部分- false、undefined和null将跳过部分
- true将以原始作用域运行部分
- 所有其他情况将以新作用域运行部分(包括0、1、-1、''、'1'、'0'、'-1'、'false'、Array等)
{{/value}}
:结束部分{{^value}}
:倒置部分- false、undefined和null将以原始作用域运行部分
- 所有其他情况都将跳过该部分(包括0,1,-1,'','1','0','-1','false',Array等)
{{! comment}}
: 注释{{!-- comment or {{ or }} --}}
: 扩展注释,可以包含}}或{{ .{{=<% %>=}}
: 设置自定义分隔符,自定义字符串不能包含=
。更多示例请参考http://mustache.github.io/mustache.5.html。{{#each var}}
: 每个循环{{#each}}
: 在{{.}}上循环{{/each}}
: 结束循环{{#if var}}
: 使用原始作用域运行if逻辑(null,false,空数组和''将跳过此块){{/if}}
: 结束if{{else}}
: 运行else逻辑,应在{{#if var}}
和{{/if}}
之间;或在{{#unless var}}
和{{/unless}}
之间;或在{{#foo}}
和{{/foo}}
之间;或在{{#each var}}
和{{/each}}
之间;或在{{#with var}}
和{{/with}}
之间。{{#unless var}}
: 使用原始作用域运行unless逻辑(null,false,空数组和''将渲染此块){{#with var}}
: 改变作用域。如果var为false,则跳过包含的部分。(需要FLAG_WITH
){{../var}}
: 父模板作用域。(需要FLAG_PARENT
){{>file}}
: 部分内容;在模板内包含另一个模板。{{>file foo}}
: 带有新上下文的部分内容(需要FLAG_RUNTIMEPARTIAL
){{@index}}
: 在{{#each}}
循环中引用数组的当前索引。(需要FLAG_SPVARS
){{@key}}
: 在{{#each}}
循环中引用对象的当前键。(需要FLAG_SPVARS
){{@root}}
: 引用根上下文。(需要FLAG_SPVARS
){{@first}}
: 当循环到第一个项目时为true。(需要FLAG_SPVARS
){{@last}}
: 当循环到最后一个项目时为true。(需要FLAG_SPVARS
){{@root.path.to.value}}
: 引用根上下文然后跟随路径。(需要FLAG_SPVARS
){{@../index}}
: 访问父循环索引。(需要FLAG_SPVARS
和FLAG_PARENT
){{@../key}}
: 访问父循环键。(需要FLAG_SPVARS
和FLAG_PARENT
){{foo.[ba.r].[#spec].0.ok}}
: 引用$CurrentConext['foo']['ba.r']['#spec'][0]['ok']。(需要FLAG_ADVARNAME
){{~any_valid_tag}}
: 空格控制,删除所有之前的空格(包括CR/LF,制表符,空格;在遇到任何非空格字符时停止)(需要FLAG_SPACECTL
){{any_valid_tag~}}
: 空格控制,删除所有之后的空格(包括CR/LF,制表符,空格;在遇到任何非空格字符时停止)(需要FLAG_SPACECTL
){{{helper var}}}
: 执行自定义辅助函数然后渲染结果{{helper var}}
: 执行自定义辅助函数然后渲染HTML转义后的结果{{helper "str"}}
: 使用字符串参数执行自定义辅助函数(需要FLAG_ADVARNAME
){{helper name1=var name2=var2}}
: 使用命名参数执行自定义辅助函数(需要FLAG_NAMEDARG
){{#helper ...}}...{{/helper}}
: 执行块自定义辅助函数{{helper (helper2 foo) bar}}
: 将自定义辅助函数作为子表达式执行(需要FLAG_ADVARNAME
)