Download the PHP package opine/lightncandy without Composer
On this page you can find all versions of the php package opine/lightncandy. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download opine/lightncandy
More information about opine/lightncandy
Files in opine/lightncandy
Package lightncandy
Short Description Opine-PHP form of an extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).
License MIT
Homepage https://github.com/zordius/lightncandy
Informations about the package lightncandy
LightnCandy
An extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).
Features
- Logicless template: mustache ( http://mustache.github.com/ ) or handlebars ( http://handlebarsjs.com/ ) .
- Compile template to pure PHP code. Examples:
- Template A generated PHP A
- Template B generated PHP B
- FAST!
- Runs 4~6 times faster than mustache.php.
- Runs 4~10 times faster than mustache-php.
- Runs 10~30 times faster than handlebars.php.
- Detail performance test reports can be found here, go http://zordius.github.io/HandlebarsTest/ to see charts.
- SMALL! single PHP file, only 107K!
- ROBUST!
- 100% support mustache spec v1.1.2 (without lambda module)
- Supports almost all handlebars.js spec
- Output SAME with handlebars.js
- FLEXIBLE!
- Lot of options to change features and behaviors.
- Context generation
- Analyze used features from your template (use
LightnCandy::getContext()
to get it) .
- Analyze used features from your template (use
- Debug
- Generate debug version template
- Find out missing data when rendering template.
- Generate visually debug template.
- Generate debug version template
- Standalone Template
- The compiled PHP code can run without any PHP library. You do not need to include LightnCandy when execute rendering function.
Installation
Use Composer ( https://getcomposer.org/ ) to install LightnCandy:
Or, download LightnCandy from github:
LightnCandy requirement: PHP 5.3.0+ .
UPGRADE NOTICE
- Please check HISTORY.md for versions history.
- Please check UPGRADE.md for upgrade notice.
Usage
The output will be:
Compile Options
You can apply more options by running LightnCandy::compile($template, $options)
:
Default is to compile the template as PHP, which can be run as fast as possible (flags = FLAG_BESTPERFORMANCE
).
FLAG_ERROR_LOG
: error_log() when found any template errorFLAG_ERROR_EXCEPTION
: throw exception when found any template errorFLAG_ERROR_SKIPPARTIAL
: skip 'partial not found' error/exception. Use this to align with mustache specification.FLAG_NOESCAPE
: do not do any HTML escape on {{var}}.FLAG_STANDALONE
: generate stand-alone PHP codes, which can be execute without including LightnCandy.php. The compiled PHP code will contain scoped user function, somehow larger. And, the performance of the template will slow 1 ~ 10%.FLAG_JSTRUE
: generate 'true' or 'false' when value is true or false (JavaScript behavior). Otherwise, true/false will generate ''.FLAG_JSOBJECT
: generate '[object Object]' for associated array, generate ',' separated values for array (JavaScript behavior). Otherwise, all PHP array will generate '' or 'Array'.FLAG_THIS
: resolve{{this}}
as{{.}}
in template. Otherwise,{{this}}
will be resolved as normal variable.FLAG_WITH
: support{{#with var}}
in template. Otherwise,{{#with var}}
will cause template error.FLAG_PARENT
: support{{../var}}
in template. Otherwise,{{../var}}
will cause template error.FLAG_JSQUOTE
: escape'
to'
,`
to`
. Otherwise,'
will be escaped to'
,`
will not be touched.FLAG_ADVARNAME
: support{{foo.[0].[#te#st].bar}}
style advanced variable naming in template. Use this flag if you wanna use"some string"
or(subexpresssion)
as argument.FLAG_NAMEDARG
: support named arguments for custom helper{{helper name1=val1 nam2=val2 ...}}
.FLAG_EXTHELPER
: do not including custom helper codes into compiled PHP codes. This reduces the code size, but you need to take care of your helper functions when rendering. If you forget to include required functions when execute rendering function,undefined function
runtime error will be triggered. NOTE: Anonymous functions will always be placed into generated codes.FLAG_RUNTIMEPARTIAL
: compile partial as runtime function, This enables recursive partials or context change for partials.FLAG_SLASH
: Skip a delimiter when it behind\
.FLAG_ELSE
: support{{else}}
or{{^}}
as handlebars specification. Otherwise,{{else}}
will be resolved as normal variable , and {{^}} will cause template error.FLAG_PROPERTY
: support object instance attribute access.FLAG_METHOD
: support object instance method access.FLAG_INSTANCE
: same withFLAG_PROPERTY
+FLAG_METHOD
FLAG_SPACECTL
: support space control{{~ }}
or{{ ~}}
in template. Otherwise,{{~ }}
or{{ ~}}
will cause template error.FLAG_SPVARS
: support special variables include @root, @index, @key, @first, @last. Otherwise, compile these variable names with default parsing logic.FLAG_JS
: simulate all JavaScript string conversion behavior, same withFLAG_JSTRUE
+FLAG_JSOBJECT
.FLAG_HANDLEBARS
: support all handlebars extensions (which mustache do not supports) , same withFLAG_THIS
+FLAG_WITH
+FLAG_PARENT
+FLAG_JSQUOTE
+FLAG_ADVARNAME
+FLAG_NAMEDARG
+FLAG_SLASH
+FLAG_ELSE
+FLAG_MUSTACHESP
+FLAG_MUSTACHEPAIN
.FLAG_HANDLEBARSJS
: align with handlebars.js behaviors, same withFLAG_JS
+FLAG_HANDLEBARS
.FLAG_MUSTACHESP
: align line change and spacing behaviors with mustache specification.FLAG_MUSTACHELOOKUP
: align recursive lookup up behaviors with mustache specification.FLAG_MUSTACHEPAIN
: align partial indent behavior with mustache specification.FLAG_MUSTACHESEC
: align section{{#foo}}
context behavior with mustache specification.FLAG_MUSTACHE
: support all mustache specification, same withFLAG_ERROR_SKIPPARTIAL
+FLAG_MUSTACHESP
+FLAG_MUSTACHELOOKUP
+FLAG_MUSTACHEPAIN
+FLAG_MUSTACHESEC
.FLAG_ECHO
: compile toecho 'a', $b, 'c';
to improve performance. This will slow down rendering when the template and data are simple, but will improve 1% ~ 7% when the data is big and looping in the template.FLAG_BESTPERFORMANCE
: same withFLAG_ECHO
now. This flag may be changed base on performance testing result in the future.FLAG_RENDER_DEBUG
: generate debug template to show error when rendering. With this flag, the performance of rendering may be slowed.
Partial Support
LightnCandy supports partial when compile time. You can provide partials by partials
option when compile()
:
You can also provide partials by files. When compile()
, LightnCandy will search template files from basedir
in the option if you provided one or more. Default template file name is *.tmpl
, you can change or add more template file extensions with fileext
option.
With this setting, when you include a partial by {{> partial_name}}
, LightnCandy will search in this order:
- /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
By default, partial uses the same context with original template. If you want to change context for the partial, you may add one more argument after the partial name:
Custom Helper
Custom helper can help you deal with common template tasks, for example: provide URL and text then generate a link. To know more about custom helper, you can read original handlebars.js document here: http://handlebarsjs.com/expressions.html .
NOTICE: custom helpers to handle single tag {{xxx}}
or a section {{#yyy}} ... {{/yyy}}
are absolutely different in LightnCandy. To know more about creating custom helpers to handle {{#yyy}} ... {{/yyy}}
, please refer to Block Custom Helper.
When compile()
, LightnCandy will lookup helpers from generated custom helper name table. You can register custom helpers with helpers
option (NOTICE: FLAG_NAMEDARG
is required for named arguments, FLAG_ADVARNAME
is required for string or subexpression arguments):
Custom Helper Interface
The input arguments are processed by LightnCandy automatically, you do not need to worry about variable name processing or current context. You can also use double quoted string as input:
Your custom helper function will be executed with two arguments. The first one is noname arguments, the second one is named arguments:
In your template:
Custom Helper Escaping
The return value of your custom helper should be a string. When your custom helper be executed from {{ }} , the return value will be HTML escaped. You may execute your helper by {{{ }}} , then the original helper return value will be outputted directly.
When you need to do different escaping logic, you can return extended information by Array($responseString, $escape_flag) , here are some custom helper return value cases:
Block Custom Helper
Block custom helper must be used as a section, the section is started with {{#helper_name ...}}
and ended with {{/helper_name}}
.
You may use block custom helper to:
- Provide advanced condition logic which is different from
{{#if ...}}
...{{/if}}
. - Modify current context for the inner block.
- Provide different context to the inner block.
You can register block custom helpers with blockhelpers
option:
Block Custom Helper Interface
LightnCandy handled all input arguments for you, you will receive current context and parsed arguments. The return value of helper function will become new context then be passed into inner block. If you do not return any value, or return null, the inner block will not be rendered. For example:
You cannot provide new rendered result, nor handle loop in your block custom helper. To provide different rendering result, you should use custom helper. To handle loop, you should use {{#each}}
. For example:
The mission of a block custom helper is only focus on providing different context or logic to inner block, nothing else.
Handlebars.js' Custom Helper
You can implement helpers more like Handlebars.js way with hbhelpers
option, all matched single custom helper and block custom helper will be handled. In Handlebars.js, a block custom helper can rendener child block by executing options->fn, and change context by send new context as first parameter. Here are some examples to explain the behavior of hbhelpers
custom helper:
#mywith (context change)
-
LightnCandy
- Handlebars.js
#myeach (context change)
-
LightnCandy
- Handlebars.js
#myif (no context change)
-
LightnCandy
- Handlebars.js
Hashed arguments
-
LightnCandy
- Handlebars.js
Escaping
When a Handlebars.js style custom helper be used as block tags, LightnCandy will not escape the result. When it is a single {{...}} tag, LightnCandy will escape the result. To change the escape behavior, you can return extended information by Array(), please read Custom Helper Escaping for more.
Template Debugging
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 LCRun3 options into render function to know more rendering error (missing data). For example:
The ANSI output will be:
Here are the list of LCRun3 debug options for render function:
DEBUG_ERROR_LOG
: error_log() when missing required dataDEBUG_ERROR_EXCEPTION
: throw exception when missing required dataDEBUG_TAGS
: turn the return value of render function into normalized mustache tagsDEBUG_TAGS_ANSI
: turn the return value of render function into normalized mustache tags with ANSI colorDEBUG_TAGS_HTML
: turn the return value of render function into normalized mustache tags with HTML comments
Unsupported Feature (so far)
- [NEVER]
{{foo/bar}}
style variable name, it is deprecated in official handlebars.js document. - [maybe] mustache lambda : runtime time compile based on input value is far from lightncandy nature, not in the plan now.
Suggested Handlebars Template Practices
- Prevent to use
{{#with}}
. I think{{path.to.val}}
is more readable then{{#with path.to}}{{val}}{{/with}}
; when using{{#with}}
you will confusing on scope changing.{{#with}}
only save you very little time when you access many variables under same path, but cost you a lot time when you need to understand then maintain a template. - use
{{{val}}}
when you do not require HTML escaped output on the value. It is better performance, too. - If you wanna display
{{
, use this:{{{"{{"}}}
, prevent using\{{
. - Prevent to use custom helper if you want to reuse your template in different language. Or, you may need to implement different versions of helper in different languages.
- For best performance, you should only use 'compile on demand' pattern when you are in development stage. Before you go to production, you can
LightnCandy::compile()
on all your templates, save all generated PHP codes, and deploy these generated files (You may need to maintain a build process for this) . DO NOT COMPILE ON PRODUCTION , it also a best practice for security. Adding cache for 'compile on demand' is not the best solution. If you want to build some library or framework based on LightnCandy, think about this scenario. - Recompile your templates when you upgrade LightnCandy every time.
Detail Feature list
Go http://handlebarsjs.com/ to see more feature description about handlebars.js. All features align with it.
- Exact same CR/LF behavior with handlebars.js
- Exact same CR/LF bahavior with mustache spec (require
FLAG_MUSTACHESP
) - Exact same 'true' or 'false' output with handlebars.js (require
FLAG_JSTRUE
) - Exact same '[object Object]' output or join(',' array) output with handlebars.js (require
FLAG_JSOBJECT
) - Can place heading/tailing space, tab, CR/LF inside
{{ var }}
or{{{ var }}}
- Indent behavior of the partial same with mustache spec (require
FLAG_MUSTACHEPAIN
) - Recursive variable lookup to parent context behavior same with mustache spec (require
FLAG_MUSTACHELOOKUP
) {{{value}}}
or{{&value}}
: raw variable- true as 'true' (require
FLAG_JSTRUE
) - false as 'false' (require
FLAG_TRUE
)
- true as 'true' (require
{{value}}
: HTML escaped variable- true as 'true' (require
FLAG_JSTRUE
) - false as 'false' (require
FLAG_JSTRUE
)
- true as 'true' (require
{{{path.to.value}}}
: dot notation, raw{{path.to.value}}
: dot notation, HTML escaped{{.}}
: current context, HTML escaped{{{.}}}
: current context, raw{{this}}
: current context, HTML escaped (requireFLAG_THIS
){{{this}}}
: current context, raw (requireFLAG_THIS
){{#value}}
: section- false, undefined and null will skip the section
- true will run the section with original scope
- All others will run the section with new scope (includes 0, 1, -1, '', '1', '0', '-1', 'false', Array, ...)
{{/value}}
: end section{{^value}}
: inverted section- false, undefined and null will run the section with original scope
- All others will skip the section (includes 0, 1, -1, '', '1', '0', '-1', 'false', Array, ...)
{{! comment}}
: comment{{!-- comment or {{ or }} --}}
: extended comment that can contain }} or {{ .{{=<% %>=}}
: set delimiter to custom string , the custom string can not contain=
. Check http://mustache.github.io/mustache.5.html for more example.{{#each var}}
: each loop{{#each}}
: each loop on {{.}}{{/each}}
: end loop{{#if var}}
: run if logic with original scope (null, false, empty Array and '' will skip this block){{/if}}
: end if{{else}}
: run else logic, should between{{#if var}}
and{{/if}}
; or between{{#unless var}}
and{{/unless}}
; or between{{#foo}}
and{{/foo}}
; or between{{#each var}}
and{{/each}}
; or between{{#with var}}
and{{/with}}
.{{#unless var}}
: run unless logic with original scope (null, false, empty Array and '' will render this block){{#with var}}
: change context scope. If the var is false, skip included section. (requireFLAG_WITH
){{../var}}
: parent template scope. (requireFLAG_PARENT
){{>file}}
: partial; include another template inside a template.{{>file foo}}
: partial with new context (requireFLAG_RUNTIMEPARTIAL
){{@index}}
: references to current index in a{{#each}}
loop on an array. (requireFLAG_SPVARS
){{@key}}
: references to current key in a{{#each}}
loop on an object. (requireFLAG_SPVARS
){{@root}}
: references to root context. (requireFLAG_SPVARS
){{@first}}
: true when looping at first item. (requireFLAG_SPVARS
){{@last}}
: true when looping at last item. (requireFLAG_SPVARS
){{@root.path.to.value}}
: references to root context then follow the path. (requireFLAG_SPVARS
){{@../index}}
: access to parent loop index. (requireFLAG_SPVARS
andFLAG_PARENT
){{@../key}}
: access to parent loop key. (requireFLAG_SPVARS
andFLAG_PARENT
){{foo.[ba.r].[#spec].0.ok}}
: references to $CurrentConext['foo']['ba.r']['#spec'][0]['ok'] . (requireFLAG_ADVARNAME
){{~any_valid_tag}}
: Space control, remove all previous spacing (includes CR/LF, tab, space; stop on any none spacing character) (requireFLAG_SPACECTL
){{any_valid_tag~}}
: Space control, remove all next spacing (includes CR/LF, tab, space; stop on any none spacing character) (requireFLAG_SPACECTL
){{{helper var}}}
: Execute custom helper then render the result{{helper var}}
: Execute custom helper then render the HTML escaped result{{helper "str"}}
: Execute custom helper with string arguments (requireFLAG_ADVARNAME
){{helper name1=var name2=var2}}
: Execute custom helper with named arguments (requireFLAG_NAMEDARG
){{#helper ...}}...{{/helper}}
: Execute block custom helper{{helper (helper2 foo) bar}}
: Execute custom helpers as subexpression (requireFLAG_ADVARNAME
)