LiuJi-Jim/raze-tpl

语言: TypeScript

git: https://github.com/LiuJi-Jim/raze-tpl

一个js模板引擎,其语法类似于Microsoft Razor
A js template engine with syntax like Microsoft Razor
README.md (中文)

TPL射线

一个js模板引擎,其语法类似于Microsoft Razor Render Engine

如何使用

安装

npm install raze-tpl

使用

var raze = require('raze-tpl');

var tpl = fs.readFileSync(filename, 'utf-8');

var render = raze({
  template: tpl
});

// or
var render = raze({
  filename: filename
});
// which will use fs.readFileSync

var result = render(data);

选项

key usage
safe true to add try/catch to variables accessing (default to true)
strip true to remove whitespace (default to false)
extname define extname when using import and extend (default to '.html')
plainObjEach true to use Object.keys() when loop on K-V objects (default to true)

测试并查看语法/功能的演示

  • node test / test.js(未在npm包中发布。仅在源代码中提供)
  • 请参阅tpls / template.html和tpls / template.out.html

语法和功能

变量输出

含蓄

<span>@some_variable[index]</span>

明确的

<span>@(some_variable[index])</span>

没有html转义

<span@(-some_variable[index])</span>

滤波

<span>@(some_variable[index] | replace(/lorem/ig, '>>$0<<')</span>

流量控制

在数组上循环

@each (value in arr) {
  <li>@value</li>
}
@each (index:value in arr) {
  <li>No.@index of arr is @value</li>
}

也适用于k-v对象

@each (value in kv) {
  <li>@value</li>
}
@each (k:v in kv) {
  <dt>@k</dt>
  <dd>@v</dd>
}

“alias foreach = each”

@foreach (i:n in arr) {
  ...
}

条件

@if (condition) {
  <span>Yes!!</span>
}

@if (condition) {
  <span>Yes!!</span>
} else {
  <span>Ooops..</span>
}

@if (condition) {
  <span>Yes!!</span>
} else if (another_condition) {
  <span>So so..</span>
} else {
  <span>Ooops..</span>
}

函数定义添加调用

定义

@func sayHello(name) {
  <span>Hello, <strong>@name</strong>!</span>
}

调用

@use sayHello('jim')

@each (person in persons) {
  @use sayHello(person.name)
}

在函数中,您可以像在javascript中一样享受闭包变量

块定义和覆盖

定义

@block pageBody {
  <span>default empty page body</span>
}

覆盖

@override (pageBody) {
  <strong>this block is what will really show at block#pageBody</strong>
}

附加

@append (pageBody) {
  <span>this will be appended to block#pageBody</span>
}

前面加上

@prepend (pageBody) {
  <span>this will be prepended to block#pageBody</span>
}

进口(实验)

@import ('_partials/header')
@import (variable_is_ok)
@import ('_components/card', {
  title: 'params is available',
  content: local_var,
  footer: scope_will_be_extended
})

布局和扩展(实验)

@extend ('layout.html')
@override (pageBody) {
  <strong>this block is what will really show at block#pageBody</strong>
}

导入和扩展仅在将filename传递给选项或传递模板和basedir时可用,因为import和extend使用相对路径。

过滤块

首先注册过滤器

raze.addFilter('textarea', function(str, width, height) {
  width = width || 200;
  height = height || 200;
  return '<textarea style="width:'+width+'px; height:'+height+'px;">' + str + '</textarea>';
});
raze.addFilter('json', function(obj) {
  return JSON.stringify(obj, null, '  ');
});

然后你可以使用这样的过滤器,你可以尝试'过滤块'

@filter textarea(400, 200) {
  @(nested | json)
}

这将产生

<textarea style="width:400px; height:200px;">
{
  &quot;value&quot;: &quot;root&quot;,
  &quot;nested&quot;: {
    &quot;value&quot;: &quot;nested-0&quot;,
    &quot;nested&quot;: {
      &quot;value&quot;: &quot;nested-1&quot;,
      &quot;nested&quot;: {
        &quot;value&quot;: &quot;nested-2&quot;,
        &quot;nested&quot;: {
          &quot;value&quot;: &quot;nested-3&quot;,
          &quot;nested&quot;: {
            &quot;value&quot;: &quot;nested-4&quot;
          }
        }
      }
    }
  }
}
</textarea>

逃避角逐

@@ -> @
@} -> }

文字块

@# everything in literal block will be echoed as plain text #@

注释

@* comments *@

故障排除

var render = raze(opts);
console.log(render.__renderFn.toString());

基准(为了好玩)

etpl
2000 tests in 3767.63ms.
530.84op/s.
1.8838ms/op.
-----------
art-template
2000 tests in 3634.60ms.
550.27op/s.
1.8173ms/op.
-----------
raze safe
2000 tests in 3643.93ms.
548.86op/s.
1.8220ms/op.
-----------
raze unsafe
2000 tests in 3259.28ms.
613.63op/s.
1.6296ms/op.
-----------

灵感来自

  • ASPNET /剃刀
  • magicdawn /剃刀TMPL
  • AUI / artTemplate
  • ecomfe / empl

本文使用googletrans自动翻译,仅供参考, 原文来自github.com

en_README.md

raze-tpl

A js template engine with syntax like Microsoft Razor Render Engine

how to use

install

npm install raze-tpl

use

var raze = require('raze-tpl');

var tpl = fs.readFileSync(filename, 'utf-8');

var render = raze({
  template: tpl
});

// or
var render = raze({
  filename: filename
});
// which will use fs.readFileSync

var result = render(data);

options

key usage
safe true to add try/catch to variables accessing (default to true)
strip true to remove whitespace (default to false)
extname define extname when using import and extend (default to '.html')
plainObjEach true to use Object.keys() when loop on K-V objects (default to true)

test and see the demo of syntax/features

  • node test/test.js (not published in npm package. only available in source code)
  • see tpls/template.html and tpls/template.out.html

syntax and features

variable outputing

implicit

<span>@some_variable[index]</span>

explicit

<span>@(some_variable[index])</span>

no html escaping

<span@(-some_variable[index])</span>

filtering

<span>@(some_variable[index] | replace(/lorem/ig, '>>$0<<')</span>

flow control

loop on array

@each (value in arr) {
  <li>@value</li>
}
@each (index:value in arr) {
  <li>No.@index of arr is @value</li>
}

also available on k-v objects

@each (value in kv) {
  <li>@value</li>
}
@each (k:v in kv) {
  <dt>@k</dt>
  <dd>@v</dd>
}

"alias foreach=each"

@foreach (i:n in arr) {
  ...
}

conditions

@if (condition) {
  <span>Yes!!</span>
}

@if (condition) {
  <span>Yes!!</span>
} else {
  <span>Ooops..</span>
}

@if (condition) {
  <span>Yes!!</span>
} else if (another_condition) {
  <span>So so..</span>
} else {
  <span>Ooops..</span>
}

function definition add calling

definition

@func sayHello(name) {
  <span>Hello, <strong>@name</strong>!</span>
}

calling

@use sayHello('jim')

@each (person in persons) {
  @use sayHello(person.name)
}

in functions you can enjoy closure variables just like what you have in javascript

block definition and overriding

definition

@block pageBody {
  <span>default empty page body</span>
}

overriding

@override (pageBody) {
  <strong>this block is what will really show at block#pageBody</strong>
}

appending

@append (pageBody) {
  <span>this will be appended to block#pageBody</span>
}

prepending

@prepend (pageBody) {
  <span>this will be prepended to block#pageBody</span>
}

importing (experimental)

@import ('_partials/header')
@import (variable_is_ok)
@import ('_components/card', {
  title: 'params is available',
  content: local_var,
  footer: scope_will_be_extended
})

layout and extending (experimental)

@extend ('layout.html')
@override (pageBody) {
  <strong>this block is what will really show at block#pageBody</strong>
}

import and extend only available when passing filename to options or or passing both template and basedir, because import and extend are using relative path.

filter blocks

register filters first

raze.addFilter('textarea', function(str, width, height) {
  width = width || 200;
  height = height || 200;
  return '<textarea style="width:'+width+'px; height:'+height+'px;">' + str + '</textarea>';
});
raze.addFilter('json', function(obj) {
  return JSON.stringify(obj, null, '  ');
});

and then you can use such filters and you can try 'filter block'

@filter textarea(400, 200) {
  @(nested | json)
}

which will generate

<textarea style="width:400px; height:200px;">
{
  &quot;value&quot;: &quot;root&quot;,
  &quot;nested&quot;: {
    &quot;value&quot;: &quot;nested-0&quot;,
    &quot;nested&quot;: {
      &quot;value&quot;: &quot;nested-1&quot;,
      &quot;nested&quot;: {
        &quot;value&quot;: &quot;nested-2&quot;,
        &quot;nested&quot;: {
          &quot;value&quot;: &quot;nested-3&quot;,
          &quot;nested&quot;: {
            &quot;value&quot;: &quot;nested-4&quot;
          }
        }
      }
    }
  }
}
</textarea>

miscellaneous

escape chars

@@ -> @
@} -> }

literal blocks

@# everything in literal block will be echoed as plain text #@

comments

@* comments *@

trouble shooting

var render = raze(opts);
console.log(render.__renderFn.toString());

benchmark (for fun)

etpl
2000 tests in 3767.63ms.
530.84op/s.
1.8838ms/op.
-----------
art-template
2000 tests in 3634.60ms.
550.27op/s.
1.8173ms/op.
-----------
raze safe
2000 tests in 3643.93ms.
548.86op/s.
1.8220ms/op.
-----------
raze unsafe
2000 tests in 3259.28ms.
613.63op/s.
1.6296ms/op.
-----------

inspired by