smartymonkey

compile smarty template with js

Usage no npm install needed!

<script type="module">
  import smartymonkey from 'https://cdn.skypack.dev/smartymonkey';
</script>

README

smartyMonkey

用js解析smarty语法的模板,达到服务端smarty与客户端共享同一套模板的目的
analysis smarty's grammar with js, then you can use smarty both on server and client
非常感谢DOT引擎,其实smartyMonkey的思路和很多写法都借鉴了DOT。
当前版本1.0

如何使用(how to use):

在服务端(node环境下)我们可以直接引用smartyMonkey模块,require('src/smartyMonkey');
该模块的导出,是一个create方法,可以创建smartyMonkey的实例
如:
var smartyMonkey = require('smartyMonkey');
var sm = smartyMonkey.create();
var tpl_fn = sm.compile(data);
var out = tpl_fn('monkey');

在客户端(浏览器环境下),smartyMonkey会暴露一个smartyMonkey对象到执行js的上下文中,一般是window,这个对象同样有一个create方法:
<script src="./smartyMonkey.js"></script>
<script>
var smartyMonkey = window.smartyMonkey
var sm = smartyMonkey.create();
var tpl_fn = sm.compile(data);
var out = tpl_fn('monkey');
</script>

小贴士(Tips):
 在实际使用过程中,如果是在客户端编译的话,那么我们肯定要把模板的源代码传到客户端,但是我们写的模板代码,会在服务端被smarty解析掉,所以,为了把模板源代码传送到客户端,我们可以使用smarty的literal标签,防止自己的smarty模板在服务端被解析掉。

目前支持的smarty语法(current support grammer):

① 输出(print)

  1. 首先,我们要写一个模板(hello.tpl):
    hello {%*test*%}{%$it%}

  2. 然后,我们调用smatyMonkey对模板进行编译,及使用:
    var smartyMonkey = require('../../src/smartyMonkey');
    var fs = require('fs');
    fs.readFile(
     './back.tpl',
     'utf-8',
     function (err, data) {
      var sm = smartyMonkey.create();
      var tpl_fn = sm.compile(data);
      var out = tpl_fn('monkey');
      console.log(out);
     }
    );

  3. 输出:
    hello monkey

② 循环(loop)

  1. 首先,我们要写一个模板(loop.tpl):
    {%foreach $loop1 as $key => $value%}
     <div>key is: {%$key%}</div>
     <div>val is: {%$value%}</div>
    {%/foreach%}

  2. 接着我们编译一下含有foreach循环的模板(index.js): var smartyMonkey = require('../../src/smartyMonkey');
    var fs = require('fs');
    fs.readFile(
     './loop.tpl',
     'utf-8',
     function (err, data) {
      sm = smartyMonkey.create();
      var tpl_fn = sm.compile(data, {varnames: ['loop1']});
      var out = tpl_fn(['h', 'e', 'l', 'l', 'o']);
      console.log(out);
     }
    );

  3. 输出:
    <div>key is: 0</div> <div>val is: h</div> <div>key is: 1</div> <div>val is: e</div> <div>key is: 2</div> <div>val is: l</div> <div>key is: 3</div> <div>val is: l</div> <div>key is: 4</div> <div>val is: o</div>

    foreach的另一种写法:

  4. 模板:
    {%foreach from=$loop1 key=key item=value name=loop1%}
     <div>key is: {%$key%}</div>
     <div>val is: {%$value%}</div>
     <div>index is: {%$smarty.foreach.loop1.index%}</div>
    {%/foreach%}

  5. 调用:
    同上

  6. 输出:
    <div>key is: 0</div> <div>val is: h</div> <div>index is: 0</div> <div>key is: 1</div> <div>val is: e</div> <div>index is: 1</div> <div>key is: 2</div> <div>val is: l</div> <div>index is: 2</div> <div>key is: 3</div> <div>val is: l</div> <div>index is: 3</div> <div>key is: 4</div> <div>val is: o</div> <div>index is: 4</div>

③ 条件语句(condition)

  1. 模板中的代码(code in template): {%if $a%}
    this is a:{%$a%}
    {%else%}
    there is no a
    {%/if%}

  2. 调用:
    .....
    var tpl_fn = sm.compile(data, {varnames: ['a']});
    var out = tpl_fn('aval');
    console.log('has a:', out);
    var out = tpl_fn();
    console.log('no a:', out);
    .....

  3. 输出:
    has a: this is a:aval
    no a: there is no a

④ 赋值(interpolate)

  1. 模板(interpolate.tpl):
    {%$b = 'test'%}
    b is :{%$b%}

    {%$a = $b%}
    a is :{%$a%}

    {%$a=$c%}
    new a is: {%$a%}

  2. 调用:
    .....
    var tpl_fn = sm.compile(data, {varnames: ['c']});
    var out = tpl_fn('cval');
    console.log(out);
    .....

  3. 输出:
    b is :test a is :test new a is: cval

⑤ 多个参数(multiple parameters)

smartyMonkey支持传入多个参数,只要compile的时候,指定第二个参数即可:

  1. 模板:
    a is {%$a%}
    b is {%$b%}
    c is {%$c%}

    2.调用:
    .....
    var tpl_fn = sm.compile(data, {varnames: ['a', 'b', 'c']});
    var out = tpl_fn('aval', [1,2,3,4], 99);
    console.log(out);
    .....
  2. 输出:
    a is avalb is 1,2,3,4c is 99

⑥ 过滤器(filter)

可以在模板中增加过滤器与过滤器所对应的函数,或语句。内置解析过滤器的只有一个count,被解析为js的.length

  1. 模板:
    a's length is: {%$a|count%} 2.调用:
    .....
    var tpl_fn = sm.compile(data, {varnames: ['a']});
    var out = tpl_fn('aval');
    console.log(out);
    .....
  2. 输出:
    a's length is: 4

注:我们可以通过扩展filter,来增加模板的功能
例:

  1. 模板:
    {%$a|encodeURIComponent%}
    2.调用:
    var sm = smartyMonkey.create({
     filterMap: {
      encodeURIComponent: function (code) {
       return 'encodeURIComponent(a)';
      }
     }
    });
  2. 输出:
    http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3DsmartyMonkey

扩展(extend):

smartyMonkey支持扩展语法与处理器,也可以覆盖默认的语法和处理器。

我们通过在create的时候添加regxs与execFns,来增加/替换 替换规则与替换函数。可以达到对语法的扩充。

例:
var smartyMonkey = require('../../src/smartyMonkey');
var fs = require('fs');
fs.readFile(
 './extend.tpl',
 utf-8',
 function (err, data) {
  var sm = smartyMonkey.create({
   regxs: {
    smComments: /{%*[\s\S]*?*%}/g
   },
   execFns: {
    smComments: function () {
     return '-----注释替换-----';
    }
   }
  });
  var tpl_fn = sm.compile(data, {varnames: ['loop1', 'a']});
  var out = tpl_fn(['h', 'e', 'l', 'l', 'o'], '19');
  console.log(out);
 }
);

输入(extend.tpl): {%test test%}

输出: -----注释替换-----