佐迪乌斯 / 轻盈的
php:>=7.1.0
phpunit/phpunit : >=7
自述文件
特征
无逻辑模板:胡子( http://mustache.github.com/ )或车把( http://handlebarsjs.com/ )。 将模板编译为 纯PHP 代码。 示例: 快! 跑得比 胡子.php (Justin Hileman/bobthecow实现)。 跑得比 胡须-php (Dave Ingram实现)。 跑步速度比 把手.php . 可以找到详细的性能测试报告 在这里 ,开始 http://zordius.github.io/Handlebars测试/ 查看图表。
小! 189K中的所有PHP文件 健壮! 100%支持 胡子规范v1.1.3 。对于可选lambda模块,支持10种规格中的4种。 几乎支持所有 把手.js规范 输出 相同 具有 车把.js
灵活! 大量 选项 改变特征和行为。
上下文生成 分析模板中使用的功能(执行 LightnCondy::getContext() 获取它)。
调试 生成调试版本模板 渲染模板时查找缺少的数据。 生成可视化调试模板。
独立模板 编译后的PHP代码可以在没有任何PHP库的情况下运行。 执行渲染函数时不需要包含LightnCandy。
安装
作曲家需要zordius/lightncandy:dev-master
文件
编译选项
LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 标志_错误_记录 | LightnCandy公司 :: 标志_ TANDALONEPHP ));
标记_ USTACHELOOKUP :将递归查找行为与胡子规范对齐。 而且,渲染性能会更差。 穆斯塔切拉姆巴达旗 :支持简单的lambda逻辑作为mustache规范。 而且,渲染性能会更差。 标志_ OHBHELPERS :不要编译handlebars.js内置帮助程序。 使用此选项, {{#with}} , {{#if}} , {{除非}} , {{#each}} 指正常截面,以及 {{#带foo}} , {{#if-foo}} , {{#除非foo}} , {{每个foo}} 将导致编译错误。 标志_防撞部分 :将节上下文行为与mustache.js对齐。 FLAG_MUSTACHE标志 :支持所有胡子规格,但性能下降,与 标志_错误_终止 + 标记_ USTACHELOOKUP + 穆斯塔切拉姆巴达旗 + 标志_ OHBHELPERS + 标记_运行时间部分 + 标记_JSTRUE + 标志_JSOBJECT .
标志_本 标志_租金 标志_最佳状态 FLAG_ADVARNAME标志 标志_修改器 FLAG_SLASH(闪烁) 标记_左侧 AWBLOCK标志 :支持 {{{raw_block}}}}任意字符或{{foo}}_as_raw_string{{{/raw_block}}}} . 旗标_扶手杆SLAMBDA :支持lambda逻辑作为把手.js规范。 而且,渲染性能会更差。 旗标_ PVARS :支持特殊变量包括@root、@index、@key、@first、@last。 否则,使用默认解析逻辑编译这些变量名。 旗杆 :支持大多数车把扩展,并保持性能良好,与 标志_本 + 标志_警告 + 标志_最佳状态 + FLAG_ADVARNAME标志 + 标志_修改器 + 旗标_ PVARS + FLAG_SLASH(闪烁) + 标记_左侧 + AWBLOCK标志 . 旗标_扶手 :支持大多数handlers.js+javascript行为,同时保持良好的性能,与 标志_JS + 旗杆 . 标志_操纵杆SJS_FULL :启用所有支持的handlebars.js行为,但性能下降,与相同 旗标_扶手 + 标志_安装 + 标记_运行时间部分 + 标记_ USTACHELOOKUP + 旗标_扶手杆SLAMBDA .
标志_背景 标记_部件上下文 标志_ GNORESTANDALONE :防止在上进行独立检测 {{#foo}} , {{/foo}} 或 {{^}} ,行为与handlebars.js ignoreStandalone编译时选项相同。 标记_触发参数 :将变量名作为字符串传递给助手,行为与handlebars.js stringParams编译时选项相同。 标志_已知 :仅将当前上下文传递给lambda,行为与handlers.js knownHelpersOnly编译时选项相同。 标志_预防 :将部分缩进行为与胡子规格对齐。 这与handlebars.js preventIndent copmile时间选项相同。
部分支持
自定义助手
自定义助手示例
LightnCandy公司
//LightnCandy示例,#mywith与#with工作方式相同 $ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , “助手” => 阵列 ( “我的” => 功能 ( $ 上下文 , $ 选项 ) { 返回 $ 选项 [ “fn” ]( $ 上下文 ); } ) ));
手柄.js
//Handlebars.js示例,#mywith与#with工作方式相同 把手 . 注册表帮助程序 ( “我的” , 功能 ( 上下文 , 选项 ) { 返回 选项 . fn公司 ( 上下文 ) ; } ) ;
LightnCandy公司
//LightnCandy示例,#myeach与#each的工作原理相同 $ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , “助手” => 阵列 ( “myeach” => 功能 ( $ 上下文 , $ 选项 ) { $ 转塔 = '' ; foreach公司 ( $ 上下文 作为 $ cx公司 ) { $ 转塔 .= $ 选项 [ “fn” ]( $ cx公司 ); } 返回 $ 转塔 ; } ) ));
手柄.js
//Handlebars.js示例,#myeach与#each的工作方式相同 把手 . 注册表帮助程序 ( “myeach” , 功能 ( 上下文 , 选项 ) { 无功功率,无功功率 转塔 = '' , 我 , j个 = 上下文 . 长度 ; 对于 ( 我 = 0 ; 我 < j个 ; 我 ++ ) { 转塔 = 转塔 + 选项 . fn公司 ( 上下文 [ 我 ] ) ; } 返回 转塔 ; } ) ;
LightnCandy公司
//LightnCandy示例,#myif与#if的工作原理相同 $ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , “助手” => 阵列 ( “我的” => 功能 ( $ 有条件的 , $ 选项 ) { 如果 ( $ 有条件的 ) { 返回 $ 选项 [ “fn” ](); } 其他的 { 返回 $ 选项 [ “反向” ](); } } ) ));
手柄.js
//Handlebars.js示例,#myif与#if工作方式相同 把手 . 注册表帮助程序 ( “我的” , 功能 ( 有条件的 , 选项 ) { 如果 ( 有条件的 ) { 返回 选项 . fn公司 ( 这 ) ; } 其他的 { 返回 选项 . 反向 ( 这 ) ; } } ) ;
$ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , “助手” => 阵列 ( “获取根” => 功能 ( $ 选项 ) { 打印(r)( $ 选项 [ “_这” ]); //转储当前上下文 返回 $ 选项 [ '数据' ][ “root” ]; //与{{@root}}相同 } ) ));
手柄.js
把手 . 注册表帮助程序 ( “获取根” , 功能 ( 选项 ) { 控制台 . 日志 ( 这 ) ; //转储当前上下文 返回 选项 . 数据 . 根 ; //与…相同{{ @根 }} } ) ;
LightnCandy公司
$ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , “助手” => 阵列 ( '列表' => 功能 ( $ 上下文 , $ 选项 ) { $ 外面的 = '' ; $ 数据 = $ 选项 [ '数据' ]; foreach公司 ( $ 上下文 作为 $ 国际数据交换 => $ cx公司 ) { $ 数据 [ '索引' ] = $ 国际数据交换 ; $ 外面的 .= $ 选项 [ “fn” ]( $ cx公司 , 阵列 ( '数据' => $ 数据 )); } 返回 $ 外面的 ; } ) ));
手柄.js
把手 . 注册表帮助程序 ( '列表' , 功能 ( 上下文 , 选项 ) { 无功功率,无功功率 外面的 = '' ; 无功功率,无功功率 数据 = 选项 . 数据 ? 把手 . 创建帧 ( 选项 . 数据 ) 以下为: 未定义 ; 对于 ( 无功功率,无功功率 我 = 0 ; 我 < 上下文 . 长度 ; 我 ++ ) { 如果 ( 数据 ) { 数据 . 指数 = 我 ; } 外面的 += 选项 . fn公司 ( 上下文 [ 我 ] , { 数据 以下为: 数据 } ) ; } 返回 外面的 ; } ) ;
更改分隔符
LightnCandy公司 :: 编译 ( “我想使用<%foo%>作为分隔符!” , 阵列 ( '分隔符' => 阵列 ( '<%' , '%>' ) ));
模板调试
$ 模板 = " 你好! {{name}}是{{gender}}。 测试1:{{@root.name}} 测试2:{{@root.segender}}} 测试3:{{../Test3}} 测试4:{{../../Test4}} 测试5:{{../../.}} 测试6:{{../../[test'6]}} {{每个}} 每个值:{{}} {{/each}} {{#.}} 节值:{{}} {{/.}} {{#if.}}如果可以! {{/if}} {{#excels.}}除非不正常! {{/除非}} ”; //编译为调试版本 $ phpStr公司 = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: FLAG_RENDER_DEBUG标志 | LightnCandy公司 :: 旗标_扶手 )); //将编译后的PHP代码保存到PHP文件中 文件输出内容( '呈现.php' , '<? php' . $ phpStr公司 . '?>' ); //从php文件获取render函数 $ 渲染器 = 包括 ( '呈现.php' ); //缺少数据时出现error_log(): //LightnCandy\运行时:[gender]不存在 //LightnCandy\运行时:/ [test]不存在 $ 渲染器 ( 阵列 ( “名称” => “约翰” ), 阵列 ( “调试” => LightnCandy公司 \ 运行时 :: 调试错误日志 )); //输出ANSI颜色的可视化调试模板: 回声 $ 渲染器 ( 阵列 ( “名称” => “约翰” ), 阵列 ( “调试” => LightnCandy公司 \ 运行时 :: 调试_TAGS_ANSI )); //输出带有HTML注释的调试模板: 回声 $ 渲染器 ( 阵列 ( “名称” => “约翰” ), 阵列 ( “调试” => LightnCandy公司 \ 运行时 :: 调试_TAGS_HTML ));
调试错误日志 :error_log(),当缺少所需数据时 调试出错 :缺少所需数据时引发异常 调试标签 :将render函数的返回值转换为规范化的mustache标记 调试_TAGS_ANSI :将render函数的返回值转换为ANSI颜色的规范化胡子标记 调试_TAGS_HTML :将render函数的返回值转换为带有HTML注释的规范化mustache标记
预处理部分
$ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , '准备' => 功能 ( $ 上下文 , $ 模板 , $ 名称 ) { 返回 " <!-- 部分启动: $ 名称 --> $ 模板 <!-- 部分结束: $ 名称 --> ”; } ));
自定义渲染函数
$ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , “renderex” => “//编译于” .日期( “Y-m-d h:i:s” ) ));
功能 ( $ 在里面 ) { $ cx公司 = 阵列 (...); //编译于1999-12-31 00:00:00 返回 . . . . . }
自定义渲染运行时类
//用于调试{{{foo}}}的自定义运行库 班 我的运行时间 延伸 LightnCandy公司 \ 运行时 { 公众的 静止的 功能 未经加工的 ( $ cx公司 , $ v(v) ) { 返回 '[[调试:raw()=>' .var_导出( $ v(v) , 真的 )。 ']]' ; } } //将MyRunTime用作运行库 $ php(电话) = LightnCandy公司 :: 编译 ( $ 模板 , 阵列 ( '标志' => LightnCandy公司 :: 旗标_扶手 , “运行时” => “我的运行时间” ));
不支持的功能
{{foo/bar}} 样式变量名,在官方handlebars.js文档中已弃用,请使用此样式: {{foo.bar}} .
建议的把手模板实践
防止使用 {{#with}} .我想 {{path.to.val}} 那么可读性更强 {{#withpath.to}}{val}}{/without}}} ; 使用时 {{#with}} 你会对范围变更感到困惑。 {{#with}} 当您在同一路径下访问多个变量时,只会节省很少的时间,但当您需要理解然后维护模板时,会花费大量时间。 使用 {{val}}} 当您不需要对值进行HTML转义输出时。 这也是更好的表现。 如果要以不同语言重用模板,请防止使用自定义帮助程序。 或者,您可能需要用不同的语言实现不同版本的helper。 为了获得最佳性能,您应该只在开发阶段使用“按需编译”模式。 在投入生产之前,您可以 LightnCandy::compile() 在所有模板上,保存所有生成的PHP代码,并部署这些生成的文件(您可能需要为此维护一个构建过程)。 请勿在生产时编译 ,这也是安全的最佳实践。 为“按需编译”添加缓存并不是最佳解决方案。 如果您想基于LightnCandy构建一些库或框架,请考虑这个场景。 每次升级LightnCandy时都要重新编译模板。 坚持逃生实践 { 或 } 对于把手和lightncandy: 如果要显示原子 }} ,你可以不用任何技巧就直接使用它。 前任: {{foo}}} 如果要显示 } 在任何车把标记之后,您都可以使用: {{带“}”}}{{.}}{带}} 例如: {{foo}}{{#带“}”}}{.}}{/带}} 如果要显示原子 { ,你可以不用任何技巧就使用它。 前任: {和{{foo}} . 如果要显示 {{ ,您可以使用 {{#带“{{”}}{{.}}{/带}} 例如: {{#带“{{”}}{{.}}{/带}}{}foo}}
详细功能列表
与把手.js完全相同的CR/LF行为 与胡子规格完全相同的CR/LF行为 与handlebars.js的“true”或“false”输出完全相同(需要 标记_JSTRUE ) 与handlebars.js(require)的“[object object]”输出或join(','array)输出完全相同 标志_JSOBJECT ) 可以在内部放置标题/尾随空格、制表符、CR/LF {{var}} 或 {{var}}} 与胡子规格相同的部分的缩进行为 父上下文行为的递归变量查找与胡子规范相同(需要 标记_ USTACHELOOKUP ) {{{value}}} 或 {{值}} :原始变量 true作为“true”(需要 标记_JSTRUE ) false作为“false”(需要 标志_方向 )
{{值}} :HTML转义变量 true作为“true”(需要 标记_JSTRUE ) false作为“false”(需要 标记_JSTRUE )
{{{path.to.value}} :点表示法,原始 {{path.to.value}} :点表示法,HTML转义 {{.}} :当前上下文,HTML转义 {{{.}}} :当前上下文,原始 {{this}} :当前上下文,HTML转义(需要 标志_本 ) {{此}}} :当前上下文,原始(需要 标志_本 ) {{值}} :节 false、undefined和null将跳过该节 true将运行具有原始范围的节 所有其他人将使用新范围运行节(包括0、1、-1、“”、“1”、“0”、“-1”、“false”、Array…)
{{/value}} :端部 {{^值}} :倒置截面 false、undefined和null将运行具有原始范围的节 其他所有人都将跳过该节(包括0、1、-1、“”、“1”、“0”、“-1”、“false”、Array…)
{{!注释}} :注释 {{!--注释或{{或}}--}} :可以包含}}或{{的扩展注释。 {{=<% %>=}} :将分隔符设置为自定义字符串,则自定义字符串不能包含 = .检查 http://mustache.github.io/mustache.5.html 例如。 {{每个变量}} :每个回路 {{#each}} :{{.}}上的每个循环 {{/each}} :结束循环 {{#每个条作为|foo|}} :echo循环并将值设置为foo。 (需要 FLAG_ADVARNAME标志 ) {{#每个栏为|foomoo|}} :条上的echo循环,将值设置为foo,将索引设置为moo。 (需要 FLAG_ADVARNAME标志 ) {{#if-var}} :如果逻辑具有原始范围,则运行(null、false、空数组和“”将跳过此块) {{#iffoo-includeZero=true}} :当foo===0时,result为true(需要 标志_修改器 ) {{/if}} :结束条件 {{else}} 或 {{^}} :运行else逻辑,应介于 {{#if-var}} 和 {{/if}} ; 或介于 {{#除非var}} 和 {{/除非}} ; 或介于 {{#foo}} 和 {{/foo}} ; 或介于 {{每个变量}} 和 {{/each}} ; 或介于 {{#带var}} 和 {{/带}} .(要求 标记_左侧 ) {{#if-foo}}。。。 {{else-if-bar}}。。。 {{/if}} :如果else阻止则被链接 {{#除非var}} :run,除非具有原始范围的逻辑(null、false、空数组和“”将呈现此块) {{#除非foo}}。。。 {{else-if-bar}}。。。 {{/除非}} :链接除非其他块 {{#除非foo}}。。。 {{else除非bar}}。。。 {{/除非}} :链接除非其他块 {{#foo}}。。。 {{else栏}}。。。 {{/foo}} :自定义helper链接的else块 {{#带var}} :更改上下文范围。 如果var为false或空数组,请跳过included部分。 {{#条为|foo|}} :将上下文更改为bar并将值设置为foo。 (需要 FLAG_ADVARNAME标志 ) {{查找foo栏}} :通过作为键的bar值查找foo。 {{../var}} :父模板范围。 (需要 标志_租金 ) {{>文件}} :部分; 在模板中包含另一个模板。 {{>文件foo}} :带有新上下文的部分(需要 标记_运行时间部分 ) {{>文件foo-bar=另一个}} :partial包含与以下键值混合的新上下文(需要 标记_运行时间部分 ) {{>(助手)foo}} :包含助手提供的动态分部(按名称)(需要 标记_运行时间部分 ) {{@索引}} :对中当前索引的引用 {{#each}} 数组上的循环。 (需要 旗标_ PVARS ) {{@key}} :对中当前键的引用 {{#each}} 对象上的循环。 (需要 旗标_ PVARS ) {{@root}} :对根上下文的引用。 (要求 旗标_ PVARS ) {{@第一}} :在第一项处循环时为true。 (需要 旗标_ PVARS ) {{@last}} :在最后一项处循环时为true。 (需要 旗标_ PVARS ) {{@root.path.to.value}} :引用根上下文,然后遵循路径。 (需要 旗标_ PVARS ) {{@../index}} :访问父循环索引。 (需要 旗标_ PVARS 和 标志_警告 ) {{@../key}} :访问父循环键。 (需要 标志_虚拟机 和 标志_警告 ) {{foo.[ba.r].[#spec].0.ok}} :对$CurrentConext['foo']['ba.r'][#spec'][0]['ok']的引用。 (需要 FLAG_ADVARNAME标志 ) {{~any_valid_tag}} :空格控制,删除所有以前的空格(包括CR/LF、制表符、空格;停止在任何非空格字符上) {{any_valid_tag~}} :空格控制,删除所有下一个空格(包括CR/LF、制表符、空格;停止在任何非空格字符上) {{{helper变量}}} :执行自定义助手,然后呈现结果 {{helper变量}} :执行自定义帮助程序,然后呈现HTML转义结果 {{助手“str”}} 或 {{helper“str”}} :使用字符串参数执行自定义帮助程序(需要 FLAG_ADVARNAME标志 ) {{helper 123 null true false undefined}} :将number、true、false、null或未定义的值传递给helper {{助手名称1=var名称2=var2}} :使用命名参数执行自定义助手(需要 标志_修改器 ) {{#helper…}}。。。 {{/helper}} :执行块自定义助手 {{助手(helper2foo)栏}} :将自定义帮助程序作为子表达式执行(需要 FLAG_ADVARNAME标志 ) {{{{raw_block}}}{{will_not_parsed}}{}{{{/raw_lock}}}} :原始块(需要 AWBLOCK标志 ) {{#>foo}}块{{/foo}} :部分闭塞,提供 foo公司 部分默认内容(需要 标记_运行时间部分 ) {{#>@partial-block}} :访问分部中的分部块内容 {{#*inline“partial_name”}}。。。 {{/inline}} :内联部分,提供部分并覆盖原始部分。 {{log-foo}} :将值输出到stderr进行调试。
开发人员备注
框架集成
工具
CLI(命令行界面): https://github.com/PXLbros/LightnCandy-CLI