一个极其快速的 PHP 实现的 handlebars (http://handlebarsjs.com/) 和 mustache (http://mustache.GitHub.io/),
一个极其快速的 PHP 实现的 handlebars (http://handlebarsjs.com/) 和 mustache (http://mustache.GitHub.io/),
⚡ An extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).
CI status: tested PHP: 7.1, 7.2, 7.3, 7.4, 8.0, 8.1
LightnCandy::getContext() to get it) .Use Composer ( https://getcomposer.org/ ) to install LightnCandy:
composer require zordius/lightncandy:dev-masterUPGRADE NOTICE
You can apply more options by running LightnCandy::compile($template, $options):
LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_ERROR_LOG | LightnCandy::FLAG_STANDALONEPHP
));Default is to compile the template as PHP, which can be run as fast as possible (flags = FLAG_BESTPERFORMANCE).
Error Handling
JavaScript Compatibility
Mustache Compatibility
FLAG_MUSTACHELOOKUP : align recursive lookup up behaviors with mustache specification. And, the rendering performance will be worse.FLAG_MUSTACHELAMBDA : support simple lambda logic as mustache specification. And, the rendering performance will be worse.FLAG_NOHBHELPERS : Do not compile handlebars.js builtin helpers. With this option, {{#with}}, {{#if}}, {{#unless}}, {{#each}} means normal section, and {{#with foo}}, {{#if foo}}, {{#unless foo}}, {{#each foo}} will cause compile error.FLAG_MUSTACHESECTION : align section context behaviors with mustache.js.FLAG_MUSTACHE : support all mustache specification but performance drop, same with FLAG_ERROR_SKIPPARTIAL + FLAG_MUSTACHELOOKUP + FLAG_MUSTACHELAMBDA + FLAG_NOHBHELPERS + FLAG_RUNTIMEPARTIAL + FLAG_JSTRUE + FLAG_JSOBJECT.Handlebars Compatibility
FLAG_RAWBLOCK: support {{{{raw_block}}}}any_char_or_{{foo}}_as_raw_string{{{{/raw_block}}}}.FLAG_HANDLEBARSLAMBDA : support lambda logic as handlebars.js specification. And, the rendering performance will be worse.FLAG_SPVARS : support special variables include @root, @index, @key, @first, @last. Otherwise, compile these variable names with default parsing logic.FLAG_HANDLEBARS : support most handlebars extensions and also keep performance good, same with FLAG_THIS + FLAG_PARENT + FLAG_HBESCAPE + FLAG_ADVARNAME + FLAG_NAMEDARG + FLAG_SPVARS + FLAG_SLASH + FLAG_ELSE + FLAG_RAWBLOCK.FLAG_HANDLEBARSJS : support most handlebars.js + javascript behaviors and also keep performance good, same with FLAG_JS + FLAG_HANDLEBARS.FLAG_HANDLEBARSJS_FULL : enable all supported handlebars.js behaviors but performance drop, same with FLAG_HANDLEBARSJS + FLAG_INSTANCE + FLAG_RUNTIMEPARTIAL + FLAG_MUSTACHELOOKUP + FLAG_HANDLEBARSLAMBDA.Handlebars Options
FLAG_IGNORESTANDALONE : prevent standalone detection on {{#foo}}, {{/foo}} or {{^}}, the behavior is same with handlebars.js ignoreStandalone compile time option.FLAG_STRINGPARAMS : pass variable name as string to helpers, the behavior is same with handlebars.js stringParams compile time option.FLAG_KNOWNHELPERSONLY: Only pass current context to lambda, the behavior is same with handlebars.js knownHelpersOnly compile time option.FLAG_PREVENTINDENT : align partial indent behavior with mustache specification. This is same with handlebars.js preventIndent copmile time option.PHP
#mywith (context change)
// LightnCandy sample, #mywith works same with #with
$php = LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_HANDLEBARSJS,
'helpers' => array(
'mywith' => function ($context, $options) {
return $options['fn']($context);
}
)
));// Handlebars.js sample, #mywith works same with #with
Handlebars.registerHelper('mywith', function(context, options) {
return options.fn(context);
});#myeach (context change)
// LightnCandy sample, #myeach works same with #each
$php = LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_HANDLEBARSJS,
'helpers' => array(
'myeach' => function ($context, $options) {
$ret = '';
foreach ($context as $cx) {
$ret .= $options['fn']($cx);
}
return $ret;
}
)
));// Handlebars.js sample, #myeach works same with #each
Handlebars.registerHelper('myeach', function(context, options) {
var ret = '', i, j = context.length;
for (i = 0; i LightnCandy::FLAG_HANDLEBARSJS,
'helpers' => array(
'myif' => function ($conditional, $options) {
if ($conditional) {
return $options['fn']();
} else {
return $options['inverse']();
}
}
)
));// 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);
}
});You can use isset($options['fn']) to detect your custom helper is a block or not; you can also use isset($options['inverse']) to detect the existence of {{else}}.
Data variables and context
You can get special data variables from $options['data']. Using $options['_this'] to receive current context.
$php = LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_HANDLEBARSJS,
'helpers' => array(
'getRoot' => function ($options) {
print_r($options['_this']); // dump current context
return $options['data']['root']; // same as {{@root}}
}
)
));Handlebars.registerHelper('getRoot', function(options) {
console.log(this); // dump current context
return options.data.root; // same as {{@root}}
});Private variables
You can inject private variables into inner block when you execute child block with second parameter. The example code showed similar behavior with {{#each}} which sets index for child block and can be accessed with {{@index}}.
$php = LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_HANDLEBARSJS,
'helpers' => array(
'list' => function ($context, $options) {
$out = '';
$data = $options['data'];
foreach ($context as $idx => $cx) {
$data['index'] = $idx;
$out .= $options['fn']($cx, array('data' => $data));
}
return $out;
}
)
));Handlebars.registerHelper('list', function(context, options) {
var out = '';
var data = options.data ? Handlebars.createFrame(options.data) : undefined;
for (var i=0; i=}}` to change delimiters to `` , but the change will not affect included partials.
If you want to change default delimiters for a template and all included partials, you may `compile()` it with `delimiters` option:
```php
LightnCandy::compile('I wanna use as delimiters!', array(
'delimiters' => array('')
));When template error happened, LightnCandy::compile() will return false. You may compile with FLAG_ERROR_LOG to see more error message, or compile with FLAG_ERROR_EXCEPTION to catch the exception.
You may generate debug version of templates with FLAG_RENDER_DEBUG when compile() . The debug template contained more debug information and slower (TBD: performance result) , you may pass extra LightnCandy\Runtime options into render function to know more rendering error (missing data). For example:
$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
$phpStr = LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_RENDER_DEBUG | LightnCandy::FLAG_HANDLEBARSJS
));
// Save the compiled PHP code into a php file
file_put_contents('render.php', '');
// Get the render function from the php file
$renderer = include('render.php');
// error_log() when missing data:
// LightnCandy\Runtime: [gender] is not exist
// LightnCandy\Runtime: ../[test] is not exist
$renderer(array('name' => 'John'), array('debug' => LightnCandy\Runtime::DEBUG_ERROR_LOG));
// Output visual debug template with ANSI color:
echo $renderer(array('name' => 'John'), array('debug' => LightnCandy\Runtime::DEBUG_TAGS_ANSI));
// Output debug template with HTML comments:
echo $renderer(array('name' => 'John'), array('debug' => LightnCandy\Runtime::DEBUG_TAGS_HTML));
…
php
$php = LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_HANDLEBARSJS,
'prepartial' => function ($context, $template, $name) {
return "$template";
}
));You may also extend LightnCandy\Partial by override the prePartial() static method to turn your preprocess into a built-in feature.
If you want to do extra tasks inside render function or add more comment, you may use renderex when compile() . For example, this sample embed the compil
暂无开放 Issues,或尚未同步最近议题。