├── examples ├── expr.tpl.html ├── test.tpl.html ├── modules │ └── a │ │ ├── a.tpl │ │ └── b │ │ ├── c │ │ ├── c.tpl │ │ └── d │ │ │ ├── d.tpl.html │ │ │ ├── d.tpl │ │ │ └── d.tpl.js │ │ └── b.tpl ├── assign.tpl.html ├── expr.tpl ├── data.tpl.html ├── assign.tpl ├── data.json ├── condition.tpl ├── condition.tpl.html ├── variable.tpl ├── test.tpl.js ├── loop.tpl.html ├── function.tpl.html ├── loop.tpl ├── function.tpl ├── expr.tpl.js ├── assign.tpl.js ├── condition.tpl.js ├── function.tpl.js └── loop.tpl.js ├── .fecsignore ├── .gitignore ├── .npmignore ├── .fecsrc ├── config.js.example ├── package.json ├── lib ├── compiler.js ├── func.js ├── parser │ ├── literal.jison │ ├── index.jison │ └── literal.js ├── renderer │ ├── expr.js │ ├── assign.js │ ├── if.js │ ├── module.js │ ├── index.js │ ├── loop.js │ ├── function.js │ └── literal.js ├── func.src.js ├── utils.js └── phpfunc.js ├── LICENSE ├── README.md ├── bin └── smarty4js-cli └── index.js /examples/expr.tpl.html: -------------------------------------------------------------------------------- 1 | 33ab... -------------------------------------------------------------------------------- /examples/test.tpl.html: -------------------------------------------------------------------------------- 1 | <{$a = 2}><{$a|testphp}> -------------------------------------------------------------------------------- /.fecsignore: -------------------------------------------------------------------------------- 1 | lib/parser 2 | examples 3 | test 4 | node_modules -------------------------------------------------------------------------------- /examples/modules/a/a.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | {%$a="this is a page"%} 4 | 5 | {%$a%} -------------------------------------------------------------------------------- /examples/assign.tpl.html: -------------------------------------------------------------------------------- 1 | 1[1,2,3,[1,2],4,5]test assign{"b":{"c":{"d":1}}}1[1,[9,8],3]81048576 -------------------------------------------------------------------------------- /examples/modules/a/b/c/c.tpl: -------------------------------------------------------------------------------- 1 | 2 | {%include file="../../a.tpl"%} 3 | 4 | {%$c="this is c page"%} 5 | 6 | {%$c%} -------------------------------------------------------------------------------- /examples/modules/a/b/c/d/d.tpl.html: -------------------------------------------------------------------------------- 1 | this is a pagethis is b page {%$a.b.c%}this is a pagethis is c pagethis is d page -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | test 4 | examples/test.tpl 5 | examples/test.js 6 | .rvmrc 7 | npm-debug.log 8 | .idea 9 | -------------------------------------------------------------------------------- /examples/modules/a/b/c/d/d.tpl: -------------------------------------------------------------------------------- 1 | {%include file="../../b.tpl"%} 2 | {%include file="../c.tpl"%} 3 | 4 | {%$d="this is d page"%} 5 | 6 | {%$d%} -------------------------------------------------------------------------------- /examples/modules/a/b/b.tpl: -------------------------------------------------------------------------------- 1 | {%include file="../../a/a.tpl"%} 2 | 3 | {%$b = 'this is b page'%} 4 | 5 | {%$b%} 6 | 7 | {%literal%} 8 | {%$a.b.c%} 9 | {%/literal%} -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | ._.DS_Store 4 | test 5 | examples 6 | .gitignore 7 | .rvmrc 8 | Makefile 9 | *.example 10 | .fecsignore 11 | .fecsrc 12 | config.js.example 13 | npm-debug.log 14 | -------------------------------------------------------------------------------- /examples/expr.tpl: -------------------------------------------------------------------------------- 1 | 2 | {%1 + 2%} 3 | 4 | {%$x = 1%} 5 | {%$y = 2%} 6 | {%$x + $y%} 7 | 8 | {%$foo = 'abcdef'%} 9 | {%$count = 6%} 10 | {%$factor = 2%} 11 | {%$foo|truncate:"`$count / $factor - 1`"%} 12 | 13 | {%*support all logic expression and operation expression or mix*%} -------------------------------------------------------------------------------- /examples/data.tpl.html: -------------------------------------------------------------------------------- 1 | { "name": "smarty4Js", "peoples": [ { "city": "beijing", "name": "Johnson", "age": 22 }, { "city": "hangzhou", "name": "Tom", "age": 27 }, { "city": "shanghai", "name": "Green", "age": 25 } ], "info": { "location": { "city": "beijing", "street": "shangdi 10 street..." } }} -------------------------------------------------------------------------------- /.fecsrc: -------------------------------------------------------------------------------- 1 | { 2 | "eslint": { 3 | "env": { 4 | "node": true, 5 | "browser": false 6 | }, 7 | 8 | "globals": { 9 | "__h": true, 10 | "__f": true, 11 | "__da": true 12 | }, 13 | 14 | "rules": { 15 | "no-console": 0, 16 | "fecs-camelcase": [2, { "ignore": ["/_/"]}] 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /config.js.example: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = { 4 | config: { 5 | 'left_delimiter': '{%', // default 6 | 'right_delimiter': '%}', // default 7 | 'isAmd': false, 8 | 'isCmd': false, 9 | 'globalVar': '_smartyTpl' 10 | }, 11 | plugins: { // add php function 12 | testphp: function (str) { 13 | return str + '--demo--'; 14 | } 15 | }, 16 | funcs: { // add smarty function 17 | 18 | } 19 | }; -------------------------------------------------------------------------------- /examples/assign.tpl: -------------------------------------------------------------------------------- 1 | {%$test = 1%} 2 | {%$test%} 3 | 4 | {%$arr = [1,2,3,[1,2],4,5]%} 5 | {%json_encode($arr)%} 6 | 7 | {%assign var=testAssign value='test assign'%} 8 | {%$testAssign%} 9 | 10 | {%$a.b['c'].d = 1%} 11 | {%json_encode($a)%} 12 | {%$a.b.c.d%} 13 | 14 | {%assign var=foo value=[1,[9,8],3]%} 15 | {%json_encode($foo)%} 16 | 17 | {%$num = 5%} 18 | {%$aa = {%$num%} + 3%} 19 | {%$aa%} 20 | 21 | {%$x = 4%} 22 | {%$y = 10%} 23 | {%$ret = pow($x, $y)%} 24 | {%$ret%} 25 | -------------------------------------------------------------------------------- /examples/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smarty4Js", 3 | "peoples": [ 4 | { 5 | "city": "beijing", 6 | "name": "Johnson", 7 | "age": 22 8 | }, 9 | { 10 | "city": "hangzhou", 11 | "name": "Tom", 12 | "age": 27 13 | }, 14 | { 15 | "city": "shanghai", 16 | "name": "Green", 17 | "age": 25 18 | } 19 | ], 20 | "info": { 21 | "location": { 22 | "city": "beijing", 23 | "street": "shangdi 10 street..." 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /examples/condition.tpl: -------------------------------------------------------------------------------- 1 | 2 | {%$a = 1%} 3 | 4 | {%if $a gt 0%} 5 |
true
6 | {%else%} 7 |false
8 | {%/if%} 9 | 10 | {%foreach range(0, 100) as $num%} 11 | {%if $num % 4 eq 0%} 12 | {%$num%}--4--, 13 | {%else%} 14 | {%if $num % 5 == 0%} 15 | {%$num%}--5--, 16 | {%else if $num % 3 == 0%} 17 | {%$num%}--3--, 18 | {%else%} 19 | -- 20 | {%/if%} 21 | {%/if%} 22 | {%/foreach%} 23 | 24 | {%if !isset($ssssss)%} 25 | yes!! 26 | {%else%} 27 | no!! 28 | {%/if%} 29 | 30 | {%foreach $peoples as $item%} 31 | {%if $item@first%} 32 | {%$item.name%} 33 | {%else%} 34 | -- 35 | {%/if%} 36 | {%/foreach%} -------------------------------------------------------------------------------- /examples/condition.tpl.html: -------------------------------------------------------------------------------- 1 |true
0--4--, -- -- 3--3--, 4--4--, 5--5--, 6--3--, -- 8--4--, 9--3--, 10--5--, -- 12--4--, -- -- 15--5--, 16--4--, -- 18--3--, -- 20--4--, 21--3--, -- -- 24--4--, 25--5--, -- 27--3--, 28--4--, -- 30--5--, -- 32--4--, 33--3--, -- 35--5--, 36--4--, -- -- 39--3--, 40--4--, -- 42--3--, -- 44--4--, 45--5--, -- -- 48--4--, -- 50--5--, 51--3--, 52--4--, -- 54--3--, 55--5--, 56--4--, 57--3--, -- -- 60--4--, -- -- 63--3--, 64--4--, 65--5--, 66--3--, -- 68--4--, 69--3--, 70--5--, -- 72--4--, -- -- 75--5--, 76--4--, -- 78--3--, -- 80--4--, 81--3--, -- -- 84--4--, 85--5--, -- 87--3--, 88--4--, -- 90--5--, -- 92--4--, 93--3--, -- 95--5--, 96--4--, -- -- 99--3--, 100--4--, no!!Johnson -- -- -------------------------------------------------------------------------------- /examples/variable.tpl: -------------------------------------------------------------------------------- 1 | {%*smarty comments*%} 2 | 3 | hello, {%$name|upper%}. 4 | welecom to {%$peoples[1].name|cat: "'s home"%}, 5 | this is in {%$peoples[1]->city%} 6 | 7 | {%$info.location.street%} 8 | 9 | {%$tmp = 'location'%} 10 | {%$info.{%$tmp%}.street%} 11 | 12 | {%$tmp1 = 'hello, {%$info.location.street%}'%} 13 | {%$tmp1%} 14 | 15 | {%$info['location']->city|upper%} 16 | 17 | {%$abcdefghijk = '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'%} 18 | {%$s1 = 'cde'%} 19 | {%$s2 = 'ghi'%} 20 | {%$ab{%$s1%}f{%$s2%}jk%} 21 | 22 | {%$tmpa = 2%} 23 | {%$tmpb = 10%} 24 | {%"-----testtesttesttes~~`$tmpa + $tmpb`~~ttesttesttesttesttest-----"%} 25 | 26 | {%time()%} 27 | 28 | {%$num = 5%} 29 | {%$num + 20%} 30 | 31 | {%$smarty.ldelim%} 32 | 33 | {%$arr = [1,2,3,4, 'a' => [1,2,3,4, 'aa' => 'aaa'], [1,2,3]]%} 34 | {%json_encode($arr)%} -------------------------------------------------------------------------------- /examples/test.tpl.js: -------------------------------------------------------------------------------- 1 | (function(){var __ret={render:function(__tn, __da){if(typeof __tn=="object"){__da=__tn;__tn=undefined;}if(typeof __tn=="string"){__da=__da||{};} 2 | var __h="",__cap={},__ext={},__assign,__sec={},__for={},smarty={foreach:{},capture:{},ldelim:"{%",rdelim:"%}"},__dre=/^\d+(\.\d+)?$/g,__nre=/[\.\(\)\[\]\{\}\+\-\*\?\|\^\$]/g, 3 | __v=function(){var __va=Array.prototype.slice.call(arguments);for(var __vi=0,__vl=__va.length;__vi<__vl;__vi++){var __vd=__va[__vi];if(__vd!=undefined&&""+__vd!="NaN"){if(typeof __vd=="function"){return __vd();}else{return __vd;}}}return "";}; 4 | __h+="<{$a = 2}><{$a|testphp}>"; 5 | if(__tn){return __func["__fn__"+__tn](__da);} 6 | return __h;}}; 7 | if (typeof exports=="object" && typeof module=="object"){exports=module.exports=__ret;} 8 | else if (typeof define=="function" && define.amd){define(__ret);} 9 | else {return __ret;}})(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smarty4js", 3 | "description": "A JavaScript Template Engine Most Like Smarty", 4 | "version": "0.1.8", 5 | "keywords": [ 6 | "smarty", 7 | "smartyjs", 8 | "template", 9 | "tpl", 10 | "smarty js", 11 | "smarty.js", 12 | "smarty4Js", 13 | "parser", 14 | "preprocessor", 15 | "smarty compiler", 16 | "compile smarty" 17 | ], 18 | "contributors": [ 19 | { 20 | "name": "johnson", 21 | "email": "zoumiaojiang@gmail.com" 22 | } 23 | ], 24 | "bugs": { 25 | "url": "https://github.com/ecomfe/smarty4js/issues" 26 | }, 27 | "bin": { 28 | "smarty4js": "./bin/smarty4js-cli" 29 | }, 30 | "main": "index", 31 | "devDependencies": { 32 | "jison": "~0.4.15" 33 | }, 34 | "repository": "git://github.com/ecomfe/smarty4js" 35 | } 36 | -------------------------------------------------------------------------------- /lib/compiler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Compiler of Smarty4Js 3 | * @author johnson [zoumiaojiang@gmail.com] 4 | * @date 2014-11-13 5 | */ 6 | 7 | var utils = require('./utils'); 8 | 9 | /** 10 | * constructor 11 | */ 12 | function Compiler() { 13 | this.init.apply(this, arguments); 14 | } 15 | 16 | /** 17 | * init Compiler 18 | * @param {Object} engine a template engine object 19 | */ 20 | Compiler.prototype.init = function (engine) { 21 | this.engine = engine; 22 | }; 23 | 24 | /** 25 | * render of compiler 26 | * @param {Object} data data of render 27 | * @return {string} html code 28 | */ 29 | Compiler.prototype.render = function (data) { 30 | var jsTpl = this.getJsTpl(); 31 | return (new Function('return ' + jsTpl)()).render(data || {}); 32 | }; 33 | 34 | /** 35 | * get js template 36 | * @param {number} type js template style 37 | * @return {string} js code 38 | */ 39 | Compiler.prototype.getJsTpl = function (type) { 40 | return this.engine.renderer.parser(type); 41 | }; 42 | 43 | module.exports = Compiler; 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2015, Zou,Miaojiang(zoumiaojiang@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the 'Software'), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/loop.tpl.html: -------------------------------------------------------------------------------- 1 | 1 * 1 = 1, 1 * 2 = 2, 1 * 3 = 3, 1 * 4 = 4, 1 * 5 = 5, 1 * 6 = 6, 1 * 7 = 7, 1 * 8 = 8, 1 * 9 = 9, 2 * 1 = 2, 2 * 2 = 4, 2 * 3 = 6, 2 * 4 = 8, 2 * 5 = 10, 2 * 6 = 12, 2 * 7 = 14, 2 * 8 = 16, 2 * 9 = 18, 3 * 1 = 3, 3 * 2 = 6, 3 * 3 = 9, 3 * 4 = 12, 3 * 5 = 15, 3 * 6 = 18, 3 * 7 = 21, 3 * 8 = 24, 3 * 9 = 27, 4 * 1 = 4, 4 * 2 = 8, 4 * 3 = 12, 4 * 4 = 16, 4 * 5 = 20, 4 * 6 = 24, 4 * 7 = 28, 4 * 8 = 32, 4 * 9 = 36, 5 * 1 = 5, 5 * 2 = 10, 5 * 3 = 15, 5 * 4 = 20, 5 * 5 = 25, 5 * 6 = 30, 5 * 7 = 35, 5 * 8 = 40, 5 * 9 = 45, 6 * 1 = 6, 6 * 2 = 12, 6 * 3 = 18, 6 * 4 = 24, 6 * 5 = 30, 6 * 6 = 36, 6 * 7 = 42, 6 * 8 = 48, 6 * 9 = 54, 7 * 1 = 7, 7 * 2 = 14, 7 * 3 = 21, 7 * 4 = 28, 7 * 5 = 35, 7 * 6 = 42, 7 * 7 = 49, 7 * 8 = 56, 7 * 9 = 63, 8 * 1 = 8, 8 * 2 = 16, 8 * 3 = 24, 8 * 4 = 32, 8 * 5 = 40, 8 * 6 = 48, 8 * 7 = 56, 8 * 8 = 64, 8 * 9 = 72, 9 * 1 = 9, 9 * 2 = 18, 9 * 3 = 27, 9 * 4 = 36, 9 * 5 = 45, 9 * 6 = 54, 9 * 7 = 63, 9 * 8 = 72, 9 * 9 = 81, Johnson, 22, beijing, 3 -- 0 ++Tom, 27, hangzhou, 3 -- 1 ++Green, 25, shanghai, 3 -- 2 ++Johnson, 22, beijing, 3 -- 0Tom, 27, hangzhou, 3 -- 1Green, 25, shanghai, 3 -- 230, 1, 2, 3, 4, 5, 6, 7, 8, 9, name:Johnson name:Tom name:Green19, 17, 15, 13, 11, 9, 7, test foreachelse, 12345 ... xxx -------------------------------------------------------------------------------- /examples/modules/a/b/c/d/d.tpl.js: -------------------------------------------------------------------------------- 1 | (function(root){var __ret={render:function(__tn, __da){if(typeof __tn=="object"){__da=__tn;__tn=undefined;}if(typeof __tn=="string"){__da=__da||{};} 2 | var __h="",__cap={},__ext={},__assign,__sec={},__for={},smarty={foreach:{},capture:{},ldelim:"{%",rdelim:"%}"},__dre=/^\d+(\.\d+)?$/g,__nre=/[\.\(\)\[\]\{\}\+\-\*\?\|\^\$]/g, 3 | __v=function(){var __va=Array.prototype.slice.call(arguments);for(var __vi=0,__vl=__va.length;__vi<__vl;__vi++){var __vd=__va[__vi];if(__vd!=undefined&&""+__vd!="NaN"){if(typeof __vd=="function"){return __vd();}else{return __vd;}}}};var __ic2315={};var __ic2318={};__assign="this is a page";__da.a=__assign; 4 | __h+=__v(__ic2318.a,__ic2315.a,__da.a);__assign="this is b page";__da.b=__assign; 5 | __h+=__v(__ic2315.b,__da.b); 6 | __h+=" {%$a.b.c%}";var __ic2321={};var __ic2324={};__assign="this is a page";__da.a=__assign; 7 | __h+=__v(__ic2324.a,__ic2321.a,__da.a);__assign="this is c page";__da.c=__assign; 8 | __h+=__v(__ic2321.c,__da.c);__assign="this is d page";__da.d=__assign; 9 | __h+=__v(__da.d); 10 | if(__tn){return __func["__fn__"+__tn](__da);} 11 | return __h;}}; 12 | if (typeof exports=="object" && typeof module=="object"){exports=module.exports=__ret;} 13 | if (typeof define=="function" && define.amd){define(__ret);} 14 | root._smartyTpl=__ret; 15 | return __ret;})(this); -------------------------------------------------------------------------------- /examples/function.tpl.html: -------------------------------------------------------------------------------- 1 | 123asdsakljdlk---asdasdas---asd;aslkd1 * 1 = 1, 1 * 2 = 2, 1 * 3 = 3, 1 * 4 = 4, 1 * 5 = 5, 1 * 6 = 6, 1 * 7 = 7, 1 * 8 = 8, 1 * 9 = 9, 2 * 1 = 2, 2 * 2 = 4, 2 * 3 = 6, 2 * 4 = 8, 2 * 5 = 10, 2 * 6 = 12, 2 * 7 = 14, 2 * 8 = 16, 2 * 9 = 18, 3 * 1 = 3, 3 * 2 = 6, 3 * 3 = 9, 3 * 4 = 12, 3 * 5 = 15, 3 * 6 = 18, 3 * 7 = 21, 3 * 8 = 24, 3 * 9 = 27, 4 * 1 = 4, 4 * 2 = 8, 4 * 3 = 12, 4 * 4 = 16, 4 * 5 = 20, 4 * 6 = 24, 4 * 7 = 28, 4 * 8 = 32, 4 * 9 = 36, 5 * 1 = 5, 5 * 2 = 10, 5 * 3 = 15, 5 * 4 = 20, 5 * 5 = 25, 5 * 6 = 30, 5 * 7 = 35, 5 * 8 = 40, 5 * 9 = 45, 6 * 1 = 6, 6 * 2 = 12, 6 * 3 = 18, 6 * 4 = 24, 6 * 5 = 30, 6 * 6 = 36, 6 * 7 = 42, 6 * 8 = 48, 6 * 9 = 54, 7 * 1 = 7, 7 * 2 = 14, 7 * 3 = 21, 7 * 4 = 28, 7 * 5 = 35, 7 * 6 = 42, 7 * 7 = 49, 7 * 8 = 56, 7 * 9 = 63, 8 * 1 = 8, 8 * 2 = 16, 8 * 3 = 24, 8 * 4 = 32, 8 * 5 = 40, 8 * 6 = 48, 8 * 7 = 56, 8 * 8 = 64, 8 * 9 = 72, 9 * 1 = 9, 9 * 2 = 18, 9 * 3 = 27, 9 * 4 = 36, 9 * 5 = 45, 9 * 6 = 54, 9 * 7 = 63, 9 * 8 = 72, 9 * 9 = 81, I say just hello, world, {* when { is left_delimiter, } is right_delimiter *}{literal} function javascriptFunction() { alert('xxx'); // comments }{/literal} {%xxxxxx, write anything here...%} -------------------------------------------------------------------------------- /examples/loop.tpl: -------------------------------------------------------------------------------- 1 | {%for $i = 1 to 9%} 2 | {%for $j = 1 to 9%} 3 | {%$i%} * {%$j%} = {%$i * $j%}, 4 | {%/for%} 5 | {%/for%} 6 | 7 | {%foreach $peoples as $item%} 8 | {%$item.name%}, 9 | {%$item.age%}, 10 | {%$item.city%}, 11 | {%$item@total%} -- 12 | {%$smarty.foreach.index%} ++ 13 | {%/foreach%} 14 | 15 | {%foreach from=$peoples name=getPeopleInfo item=$item key=aaa%} 16 | {%$item.name%}, 17 | {%$item.age%}, 18 | {%$item.city%}, 19 | {%$smarty.foreach.total%} -- 20 | {%$aaa%} 21 | {%/foreach%} 22 | {%$smarty.foreach.getPeopleInfo.total%} 23 | 24 | {%$num = 0%} 25 | {%while $num lt 10%} 26 | {%$num%}, 27 | {%$num++%} 28 | {%/while%} 29 | 30 | {%section name=n loop=$peoples%} 31 | name:{%$peoples[n].name%} 32 | {%/section%} 33 | 34 | {%$smarty.section%} 35 | 36 | 37 | {%section name=sss loop=20 max=7 step=-2%} 38 | {%$smarty.section.sss.index%}, 39 | {%/section%} 40 | 41 | 42 | {%$b = 'test foreachelse'%} 43 | {%foreach $aaa as $item%} 44 | {%$item%}, 45 | 46 | {%foreachelse%} 47 | {%$b%}, 48 | {%foreach from=[1,2,3,4,5] item=a name=testforeachelseinner%} 49 | {%$a%} 50 | {%/foreach%} 51 | ... 52 | {%/foreach%} 53 | 54 | 55 | {%section name=sectionelsetest loop=$undefineddata%} 56 | ... 57 | {%sectionelse%} 58 | xxx 59 | {%/section%} 60 | -------------------------------------------------------------------------------- /examples/function.tpl: -------------------------------------------------------------------------------- 1 | {%$myOptions = [ 2 | '11' => 'aaa', 3 | '22' => 'bbb', 4 | '33' => 'ccc' 5 | ]%} 6 | {%$mySelect = 22%} 7 | {%html_options name=foo options=$myOptions selected=$mySelect%} 8 | 9 | {%function name=funca p=11%} 10 | {%$p%} 11 | {%/function%} 12 | {%funca p=123%} 13 | 14 | {%function name=a%} 15 | {%$funca%} 16 | {%/function%} 17 | 18 | {%$bbbb = "asdsakljdlk---{%a funca='asdasdas'%}---asd;aslkd"%} 19 | {%$bbbb%} 20 | 21 | 22 | {%function name=testAssign%} 23 | {%for $i = 1 to $funca%} 24 | {%for $j = 1 to $funcb%} 25 | {%$i%} * {%$j%} = {%$i * $j%}, 26 | {%/for%} 27 | {%/for%} 28 | {%/function%} 29 | 30 | {%call testAssign funca=9 funcb=9 assign=testFuncAssign%} 31 | {%$testFuncAssign%} 32 | 33 | 34 | {%capture append="foo"%} 35 | hello 36 | {%/capture%} 37 | I say just 38 | {%capture append="foo"%} 39 | world 40 | {%/capture%} 41 | 42 | {%foreach $foo as $text%} 43 | {%$text%}, 44 | {%/foreach%} 45 | 46 | 47 | {* when { is left_delimiter, } is right_delimiter *} 48 | {literal} 49 | function javascriptFunction() { 50 | alert('xxx'); 51 | // comments 52 | } 53 | {/literal} 54 | 55 | {%* when {% is left_delimiter, %} is right_delimiter *%} 56 | 57 | {%literal%} 58 | {%xxxxxx, write anything here...%} 59 | {%/literal%} 60 | 61 | {%*all function used like smarty grammar*%} -------------------------------------------------------------------------------- /examples/expr.tpl.js: -------------------------------------------------------------------------------- 1 | (function(){var __ret={render:function(__tn, __da){if(typeof __tn=="object"){__da=__tn;__tn=undefined;}if(typeof __tn=="string"){__da=__da||{};}var __f={truncate:function (str, num, s) { 2 | str = '' + str; 3 | return num >= str.length ? str : str.substr(0, ((num >= 0) ? num : 80)) + (s ? '' + s : '...'); 4 | }}; 5 | var __h="",__cap={},__ext={},__assign,__sec={},__for={},smarty={foreach:{},capture:{},ldelim:"{%",rdelim:"%}"},__dre=/^\d+(\.\d+)?$/g,__nre=/[\.\(\)\[\]\{\}\+\-\*\?\|\^\$]/g, 6 | __v=function(){var __va=Array.prototype.slice.call(arguments);for(var __vi=0,__vl=__va.length;__vi<__vl;__vi++){var __vd=__va[__vi];if(__vd!=undefined&&""+__vd!="NaN"){if(typeof __vd=="function"){return __vd();}else{return __vd;}}}}; 7 | __h+=((__dre.test(""+1)?parseFloat(""+1,10):1)+(__dre.test(""+2)?parseFloat(""+2,10):2));__assign=1;__da.x=__assign;__assign=2;__da.y=__assign; 8 | __h+=((__dre.test(""+__v(__da.x))?parseFloat(""+__v(__da.x),10):__v(__da.x))+(__dre.test(""+__v(__da.y))?parseFloat(""+__v(__da.y),10):__v(__da.y)));__assign="abcdef";__da.foo=__assign;__assign=6;__da.count=__assign;__assign=2;__da.factor=__assign; 9 | __h+=__f.truncate(__v(__da.foo),""+((__v(__da.count)/__v(__da.factor))-1)); 10 | if(__tn){return __func["__fn__"+__tn](__da);} 11 | return __h;}}; 12 | if (typeof exports=="object" && typeof module=="object"){exports=module.exports=__ret;} 13 | else if (typeof define=="function" && define.amd){define(__ret);} 14 | return __ret;})(); -------------------------------------------------------------------------------- /lib/func.js: -------------------------------------------------------------------------------- 1 | module.exports={html_image:function(e){var a=e.height?' height="'+e.height+'"':"";var t=e.width?' width="'+e.width+'"':"";var r=e.border?' border="'+e.border+'"':"";var o=e.alt?' alt="'+e.alt+'"':"";return'true
";} 34 | else{ 35 | __h+="false
";}var __fc2337__d=__f.range(0,100),__fc2337fi=0,__fc2337__={},__fc2337={}; 36 | for(var __fc2337k in __fc2337__d){if(__fc2337__d.hasOwnProperty(__fc2337k)){ 37 | __fc2337__=smarty.foreach={index:__fc2337fi,key:__fc2337k.replace("__a",""),total:__f.count(__fc2337__d),first:__fc2337fi==0?1:"",last:(__fc2337fi==__f.count(__fc2337__d)-1)?1:"",show:(__fc2337__d[__fc2337k])?true:false}; 38 | __fc2337["num"]=__fc2337__d[__fc2337k]; 39 | if(((__v(__fc2337.num,__da.num)%4)==0)){ 40 | __h+=__v(__fc2337.num,__da.num); 41 | __h+="--4--, ";} 42 | else{ 43 | if(((__v(__fc2337.num,__da.num)%5)==0)){ 44 | __h+=__v(__fc2337.num,__da.num); 45 | __h+="--5--, ";} 46 | else if(((__v(__fc2337.num,__da.num)%3)==0)){ 47 | __h+=__v(__fc2337.num,__da.num); 48 | __h+="--3--, ";} 49 | else{ 50 | __h+=" -- ";}}__fc2337fi++;}} 51 | if(!__f.isset(__v(__da.ssssss))){ 52 | __h+=" yes!!";} 53 | else{ 54 | __h+=" no!!";}var __fc2338__d=__v(__da.peoples),__fc2338fi=0,__fc2338__={},__fc2338={}; 55 | for(var __fc2338k in __fc2338__d){if(__fc2338__d.hasOwnProperty(__fc2338k)){ 56 | __fc2338__=smarty.foreach={index:__fc2338fi,key:__fc2338k.replace("__a",""),total:__f.count(__fc2338__d),first:__fc2338fi==0?1:"",last:(__fc2338fi==__f.count(__fc2338__d)-1)?1:"",show:(__fc2338__d[__fc2338k])?true:false}; 57 | __fc2338["item"]=__fc2338__d[__fc2338k]; 58 | if(__fc2338__.first){ 59 | __h+=__v(__v(__fc2338["item"],{}).name,__v(__da["item"],{}).name);} 60 | else{ 61 | __h+=" -- ";}__fc2338fi++;}} 62 | if(__tn){return __func["__fn__"+__tn](__da);} 63 | return __h;}}; 64 | if (typeof exports=="object" && typeof module=="object"){exports=module.exports=__ret;} 65 | else if (typeof define=="function" && define.amd){define(__ret);} 66 | else {return __ret;}})(); -------------------------------------------------------------------------------- /lib/renderer/assign.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file render of assign_stmt 3 | * @author johnson [zoumiaojiang@gmail.com] 4 | */ 5 | 6 | var utils = require('../utils'); 7 | 8 | module.exports = function (Renderer) { 9 | 10 | utils.mixin(Renderer.prototype, { 11 | 12 | /** 13 | * render assign 14 | * {%$some_var = anything%} 15 | * @param {Object} node ast node 16 | * @return {string} render result 17 | */ 18 | _assign: function (node) { 19 | var me = this; 20 | var key = node.key; 21 | var ret = me._getOriginVar(key); 22 | 23 | /** 24 | * add scope for assign var 25 | * @param {string} str pre-render result 26 | * @return {string} render result 27 | */ 28 | function addScope(str) { // TODO: now all assign to smarty global context... 29 | 30 | // a tmp assign var 31 | var tmps = '__assign=' + me._getExpr(node.value) + ';'; 32 | var scope; 33 | 34 | // scope = me.ctxScope[0]; 35 | for (var ctxi = me.ctxScope.length - 1; ctxi >= 0; ctxi--) { 36 | scope = me.ctxScope[ctxi]; 37 | var tmpa = ret.replace(/__SCOPE/g, scope).split('.'); 38 | var kf = tmpa[0]; 39 | for (var index = 0, jl = tmpa.length; index < jl; index++) { 40 | var item = tmpa[index]; 41 | if (index !== 0 && index !== jl - 1 && item) { 42 | var spli = ((item.indexOf('[') > -1) ? '' : '.'); 43 | var tmp = kf + spli + item; 44 | tmps += tmp + '=' + tmp + '?' + tmp + ':{};'; 45 | kf += spli + item; 46 | } 47 | } 48 | 49 | if (ctxi === 0) { 50 | tmps += ret.replace(/__SCOPE/g, scope).replace(/\.\[/g, '[') + '='; 51 | } 52 | } 53 | return tmps += '__assign;'; 54 | } 55 | 56 | return addScope(ret); 57 | }, 58 | 59 | /** 60 | * assign function 61 | * {%assign var=xxx value=xxx%} 62 | * @param {Object} node ast node 63 | * @return {string} render string 64 | */ 65 | _assignFunc: function (node) { 66 | var me = this; 67 | var attrs = node.attrs; 68 | var varKey; 69 | var varVal; 70 | var ret = ''; 71 | if (attrs) { 72 | attrs.forEach(function (attr) { 73 | var key = attr.key; 74 | var val = attr.value; 75 | if (key.value === 'var') { 76 | if (val.type === 'STR') { 77 | varKey = '__da.' + val.value; 78 | } 79 | else { 80 | throw new Error('Assign Type Error!'); 81 | } 82 | } 83 | 84 | if (key.value === 'value') { 85 | varVal = me._getExpr(val); 86 | } 87 | }); 88 | 89 | if (varKey && varVal) { 90 | ret += varKey + '=' + varVal + ';'; 91 | } 92 | } 93 | return ret; 94 | } 95 | }); 96 | }; 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Smarty4Js (Smarty For JavaScript) 2 | ====================================== 3 | 4 | ## What? 5 | 6 | - JavaScript template engine 7 | - Supports Smarty template syntax 8 | - Used in Node.js 9 | - Simple and powerful way to create and render a template 10 | 11 | ## Why? 12 | 13 | - Powerful 14 | - Don't want to have two or more templates in your project 15 | - Deep love for Smarty 16 | 17 | ## When? 18 | 19 | - When your synchronous templates is Smarty, and your Ajax templates will use the same template 20 | - When you want to write Smarty templates with JavaScript anywhere 21 | - When you want to put a lot of logic in JavaScript templates 22 | - When you like Smarty very much 23 | 24 | ## How? 25 | 26 | - Single 27 | - With Grunt 28 | - With Gulp 29 | - With EDP 30 | - With all Node.js web subject 31 | 32 | 33 | ### Usage 34 | 35 | #### Install 36 | ```bash 37 | npm install -g smarty4js 38 | ``` 39 | 40 | #### Syntax 41 | ``` 42 | Most of Smarty syntax is supported. 43 | ``` 44 | 45 | #### Command line 46 | ```bash 47 | // get tpl.js 48 | smarty4Js compile a.tpl [b.tpl ...] [-c|--config=confPath -o|--output=outputPath] 49 | -c | --config: Use user-define config file 50 | -o | --output: Specify a destination directory 51 | 52 | // get tpl.html 53 | smarty4Js render a.tpl [b.tpl ...] -d|--data=jsonFilePath [-c|--config=confPath -o|--output=outputPath] 54 | -d | --data : JSON data file path to render 55 | -c | --config: Use user-defined config file 56 | -o | --output: Specify a destination directory 57 | 58 | // show current version 59 | smarty4Js -v|--version 60 | 61 | ``` 62 | 63 | - if `render`, return html(`demo.tpl.html`), if `compile`, return jsTpl(`demo.tpl.js`) 64 | - jsTpl is a closure. It has a `render` method that you can use: 65 | 66 | ```Javascript 67 | 68 | // amd and cmd 69 | var template = require('demo.tpl'); 70 | template.render(data); 71 | 72 | // you can also use