opine/lightncandy

Opine-PHP 是一个极快 PHP 实现 handlebars (https://handlebars.node.org.cn/) 和 mustache (http://mustache.github.io/)。

v1.0.0 2014-11-24 19:10 UTC

This package is not auto-updated.

Last update: 2024-09-24 02:42:20 UTC


README

handlebars (https://handlebars.node.org.cn/) 和 mustache (http://mustache.github.io/) 的极快 PHP 实现。

Travis CI 状态:单元测试 回归测试

Scrutinizer CI 状态:代码覆盖率

Packagist 上的包:最新稳定版本 许可证 HHVM 状态

特性

  • 无逻辑模板:mustache (http://mustache.github.com/) 或 handlebars (https://handlebars.node.org.cn/)
  • 将模板编译为 纯 PHP 代码。示例
  • 极快!
  • 小巧! 单个 PHP 文件,只有 107K!
  • 健壮!
  • 灵活!
    • 许多 选项 可用于更改功能和行为。
  • 上下文生成
    • 从模板中分析使用过的功能(使用 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+。

升级通知

用法

// 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&amp;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&amp;Same output &#039; &quot; 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&amp;Same output &#x27; &quot; Ya!'
return Array('Not&Same output \' " Ya!', 'encq');

块自定义辅助函数

块自定义辅助函数必须用作一个部分,部分以{{#helper_name ...}}开始,以{{/helper_name}}结束。

您可以使用块自定义辅助函数

  1. 提供不同于{{#if ...}} ... {{/if}}的高级条件逻辑。
  2. 修改内部块的当前上下文。
  3. 为内部块提供不同的上下文。

您可以使用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
  • {{value}}:HTML转义的变量
    • 作为“true”(需要FLAG_JSTRUE
    • 作为“false”(需要FLAG_JSTRUE
  • {{{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_SPVARSFLAG_PARENT
  • {{@../key}} : 访问父循环键。(需要FLAG_SPVARSFLAG_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