<commit_before>`NornJ`模板可以使用纯字符串或标签模板字符串(es6)构建，并可适应多种不同使用场景。

## 目录
* [模板语法](#模板语法)
  * [插值参数](#插值参数)
  * [过滤器](#过滤器)
  * [内置过滤器](#内置过滤器)
  * [块表达式](#块表达式)
  * [内置块表达式](#内置块表达式)
    * [if](#if)
    * [else](#else)
    * [elseif](#elseif)
    * [switch](#switch)
    * [unless](#unless)
    * [each](#each)
    * [for](#for)
    * [props与prop](#props与prop)
    * [obj](#obj)
    * [tmpl](#tmpl)
* [标签模板字符串(es6)语法](#标签模板字符串(es6)语法)
  * [构建方式](#构建方式)
  * [嵌入js变量或表达式](#嵌入js变量或表达式)

# 模板语法
`NornJ`模板的结构与html非常相似，基本示例如下：
```html
<slider>
  this the test slider {{msg}}.
  <sliderItem id="test" onSliderEnd="{{event}}" />
</slider>
```

## 插值参数

在模板内可以定义插值参数，语法默认为`Mustache`语法如`{{参数名}}`，即双花括号。插值参数的作用是在模板编译后，输出html字符串或vdom对象时可用数据插入定义的参数。

* 自定义插值语法

可使用`nj.config`方法修改插值语法的默认规则(具体请看[模板全局配置](https://github.com/joe-sky/nornj/blob/master/docs/模板全局配置.md))，比如可以将双花括号改为单花括号。

> 注：在使用`nornj-react`包后，插值参数语法默认改为使用单花括号如`{参数名}`，这样做是为了在`React`中使模板语法更简练且与`JSX`语法更为接近。在本项目的文档中，`React`相关的示例默认使用单花括号，其他则默认使用双花括号。

* 在元素节点参数中定义插值参数

```html
<div id={{id}} name="{{id}} {{name}}">
```
如上例，元素属性节点中的值可以省略不写引号，但是如果属性中包含空格则必须写引号。

* 在文本节点中定义插值参数

```html
<div>{{content}}</div>
```

* 使用双花括号形式的插值参数，在模板输出html字符串时是会自动进行字符转义的，这样的目的是为了防止xss攻击等。但是也可以设置不进行转义，就须要用3个花括号的形式定义插值参数，如下所示：

```html
<div>{{{content}}}</div>
```
但是在`React`开发中，`NornJ`模板内任何形式的插值语法则都不会进行转义，因为`React`会替我们进行特殊字符转义。

* 插值参数可支持点号或数组下标语法获取属性值：
```html
<div>{{content.prop1.prop2['prop3']}}</div>
```

* 插值参数内可以包含空格：
```html
<div>{{ content[0].length }}</div>
```

* 插值参数内可放入数字、字符串等js基本类型：
```html
<div>{{'content'}} {{500.05}} {{null}} {{undefined}} {{false}}</div>
```

* 与`JSX`类似，可使用延展属性表示元素节点参数：
```js
let props = {
  foo: 1,
  bar: 2
};
let html = nj`<div {{...props}}></div'>`({ props });  //展开对象作为节点属性

console.log(html);  //输出：<div foo="1" bar="2"></div'>
```

* 定义元素节点参数的简易写法：
```js
let foo = 'bar';
let html = nj`<div {{foo}}></div'>`({ foo });  //此语法等同于"foo={{foo}}"，可省略写属性名

console.log(html);  //输出：<div foo="bar"></div'>
```

* 元素节点名称也可以设置为插值参数，如下所示：
```html
<{{element}}>this is content</{{element}}>
```
1. 元素节点名称作为插值参数时，插值参数内不可以有空格，如`{{ element }}`、`{{element|filter(' ')}}`都是错误的。
2. 另外，利用此功能可以实现`React`开发中的`高阶组件`，直接将组件类作为参数传入模板中即可，如下例：
```js
import { Component } from 'react';
import { render } from 'react-dom';

class TestComponent extends Component {
  render() {
    return nj`<div>{no}</div>`(this.props);
  }
}

render(nj`<{component} no={100} />`({
  component: TestComponent
}), document.body);
```

## 过滤器

* 在插值参数中可以使用过滤器，来对数据进行一些运算、过滤操作。语法为"{插值参数 | 过滤器1 | 过滤器2...}"，如使用多个过滤器则会按顺序依次执行，如下所示：
```js
nj.registerFilter('2x', num => num * 2);  //每个过滤器都是一个函数，使用nj.registerFilter方法注册

console.log(nj`<div>{{100 | +(50) | 2x}}</div>`());  //输出<div>300</div>
```

* 可以一次定义多个全局过滤器：
```js
nj.registerFilter({
  trim: obj => obj.trim(),
  replace: obj => obj.replace(/id/g, 'test1')
});
```

* 还可以使用局部过滤器，将过滤器函数定义为插值参数即可：
```js
nj`<div>{{1 | test}}</div>`({
  test: value => value + '_test'
});
```
<commit_msg>Updated docs<commit_after>`NornJ`模板可以使用纯字符串或标签模板字符串(es6)构建，并可适应多种不同使用场景。

## 目录
* [模板语法](#模板语法)
  * [插值参数](#插值参数)
  * [计算属性](#计算属性)
  * [过滤器](#过滤器)
  * [内置过滤器](#内置过滤器)
  * [块表达式](#块表达式)
  * [内置块表达式](#内置块表达式)
    * [if](#if)
    * [else](#else)
    * [elseif](#elseif)
    * [switch](#switch)
    * [unless](#unless)
    * [each](#each)
    * [for](#for)
    * [props与prop](#props与prop)
    * [obj](#obj)
    * [tmpl](#tmpl)
* [标签模板字符串(es6)语法](#标签模板字符串(es6)语法)
  * [构建方式](#构建方式)
  * [嵌入js变量或表达式](#嵌入js变量或表达式)

# 模板语法
`NornJ`模板的结构与html非常相似，基本示例如下：
```html
<slider>
  this the test slider {{msg}}.
  <sliderItem id="test" onSliderEnd="{{event}}" />
</slider>
```

## 插值参数

在模板内可以定义插值参数，语法默认为`Mustache`语法如`{{参数名}}`，即双花括号。插值参数的作用是在模板编译后，输出html字符串或vdom对象时可用数据插入定义的参数。

* 自定义插值语法

可使用`nj.config`方法修改插值语法的默认规则(具体请看[模板全局配置](https://github.com/joe-sky/nornj/blob/master/docs/模板全局配置.md))，比如可以将双花括号改为单花括号。

> 注：在使用`nornj-react`包后，插值参数语法默认改为使用单花括号如`{参数名}`，这样做是为了在`React`中使模板语法更简练且与`JSX`语法更为接近。在本项目的文档中，`React`相关的示例默认使用单花括号，其他则默认使用双花括号。

* 在元素节点参数中定义插值参数

```html
<div id={{id}} name="{{id}} {{name}}">
```
如上例，元素属性节点中的值可以省略不写引号，但是如果属性中包含空格则必须写引号。

* 在文本节点中定义插值参数

```html
<div>{{content}}</div>
```

* 使用双花括号形式的插值参数，在模板输出html字符串时是会自动进行字符转义的，这样的目的是为了防止xss攻击等。但是也可以设置不进行转义，就须要用3个花括号的形式定义插值参数，如下所示：

```html
<div>{{{content}}}</div>
```
但是在`React`开发中，`NornJ`模板内任何形式的插值语法则都不会进行转义，因为`React`会替我们进行特殊字符转义。

* 插值参数可支持点号或数组下标语法获取属性值：
```html
<div>{{content.prop1.prop2['prop3']}}</div>
```

* 插值参数内可以包含空格：
```html
<div>{{ content[0].length }}</div>
```

* 插值参数内可放入数字、字符串等js基本类型：
```html
<div>{{'content'}} {{500.05}} {{null}} {{undefined}} {{false}}</div>
```

* 与`JSX`类似，可使用延展属性表示元素节点参数：
```js
let props = {
  foo: 1,
  bar: 2
};
let html = nj`<div {{...props}}></div'>`({ props });  //展开对象作为节点属性

console.log(html);  //输出：<div foo="1" bar="2"></div'>
```

* 定义元素节点参数的简易写法：
```js
let foo = 'bar';
let html = nj`<div {{foo}}></div'>`({ foo });  //此语法等同于"foo={{foo}}"，可省略写属性名

console.log(html);  //输出：<div foo="bar"></div'>
```

* 元素节点名称也可以设置为插值参数，如下所示：
```html
<{{element}}>this is content</{{element}}>
```
1. 元素节点名称作为插值参数时，插值参数内不可以有空格，如`{{ element }}`、`{{element|filter(' ')}}`都是错误的。
2. 另外，利用此功能可以实现`React`开发中的`高阶组件`，直接将组件类作为参数传入模板中即可，如下例：
```js
import { Component } from 'react';
import { render } from 'react-dom';

class TestComponent extends Component {
  render() {
    return nj`<div>{no}</div>`(this.props);
  }
}

render(nj`<{component} no={100} />`({
  component: TestComponent
}), document.body);
```

## 计算属性

与`Vue`或`Mobx`的计算属性功能有些相似，`NornJ`模板中也可以使用计算属性来将一些复杂逻辑封装成一个参数。语法为在普通的插值参数前加一个`#`字符，如下例：

> 注：`NornJ`的计算属性都是只读的，并不能像`Vue`那样设置可写属性，因为在`NornJ`中也没有实现可写属性的意义。

```js
let html = nj`<div>{{#computed}}</div'>`({
  info: 'computed property.',
  computed: (ctx) => {  //每个计算属性都是一个函数，返回值即为计算结果
    return 'This is a ' + ctx.getData('info')
  }
});

console.log(html);  //输出：<div>This is a computed property.</div'>
```

* 计算属性的函数可以有一个`ctx`(即为context)参数，该参数中可以取到模板中的一些数据：

```js
let html = nj`
<div>
  <#each {{list}}>
    {{#computed}}
  </#each>
</div>`({
  id: 100,
  list: [1],
  computed: (ctx) => {
    console.log(ctx.data[0]);  //输出1
    console.log(ctx.parent.data.list);  //输出[1]
    console.log(ctx.index);  //输出0
    return ctx.getData('id');
  }
});

console.log(html);  //输出：<div>100</div'>
```

## 过滤器

* 在插值参数中可以使用过滤器，来对数据进行一些运算、过滤操作。语法为"{插值参数 | 过滤器1 | 过滤器2...}"，如使用多个过滤器则会按顺序依次执行，如下所示：
```js
nj.registerFilter('2x', num => num * 2);  //每个过滤器都是一个函数，使用nj.registerFilter方法注册

console.log(nj`<div>{{100 | +(50) | 2x}}</div>`());  //输出<div>300</div>
```

* 可以一次定义多个全局过滤器：
```js
nj.registerFilter({
  trim: obj => obj.trim(),
  replace: obj => obj.replace(/id/g, 'test1')
});
```

* 还可以使用局部过滤器，将过滤器函数定义为插值参数即可：
```js
nj`<div>{{1 | test}}</div>`({
  test: value => value + '_test'
});
```

{'fraction_non_alphanumeric': 0.2468898104265403, 'fraction_numerical': 0.012588862559241706, 'mean_word_length': 5.640117994100295, 'pattern_counts': {'":': 0, '<': 79, '<?xml version=': 0, '>': 92, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '470228', 'n_tokens_mistral': 4256, 'n_tokens_neox': 4615, 'n_words': 383}