docs: website for LiquidJS

This commit is contained in:
harttle
2020-03-28 17:21:07 +08:00
parent 0633dbeabb
commit 3e42d6b1b0
422 changed files with 14509 additions and 50335 deletions
+54
View File
@@ -0,0 +1,54 @@
---
title: 缓存
---
在典型的网站项目中,同一个模板文件可能会反复地用不同数据去渲染。在生产环境下模板文件的内容不太会发生变化(除非重新部署了服务),因此可以把从磁盘读取的文件内容和解析得到的模板结构(AST)缓存下来重复使用来节省渲染时间。
LiquidJS 在这一方面比较灵活,提供了多种不同的方式来达到提升性能的目的。
## 手动缓存
[.parse()][parse], [.parseFile()][parseFile], [.parseFileSync()][parseFileSync] API 可以用来把字符串或文件解析成模板。得到的模板可以用不同的数据去重复地渲染得到不同的 HTML。
从字符串解析:
```javascript
var tpl = engine.parse('{{name | capitalize}}');
engine.renderSync(tpl, {name: 'alice'}) // 'Alice'
engine.renderSync(tpl, {name: 'bob'}) // 'Bob'
```
从文件解析:
```javascript
var tpl = engine.parseFileSync('hello'); // contents of `hello.liquid`: {{name}}
engine.renderSync(tpl, {name: 'alice'}) // 'Alice'
engine.renderSync(tpl, {name: 'bob'}) // 'Bob'
```
上述代码中字符串或文件只被解析了一次,可以反复利用去渲染不同的数据。有很多模板文件时可以把 `tpl` 变量存在 `Map` 中,后续再 `.render()` 时直接从 Map 中拿出解析好的模板去渲染。
## `cache` 选项
如果你只用 `.renderFile()``.renderFileSync()` 也可以直接设置 [cache][cache] 选项,LiquidJS 会帮你缓存。
```javascript
var { Liquid } = require('liquidjs');
var engine = new Liquid({
cache: true
});
// LiquidJS 将会解析 hello.liquid 然后用 {name: 'alice'} 渲染它
engine.renderFileSync('hello', {name: 'alice'})
// LiquidJS 会找到上次 hello.liquid 解析的结果模板,再用 {name: 'bob'} 渲染它
engine.renderFileSync('hello', {name: 'bob'})
```
[parse]: ../../api/classes/liquid_.liquid.html#parse
[parseFile]: ../../api/classes/liquid_.liquid.html#parseFile
[parseFileSync]: ../../api/classes/liquid_.liquid.html#parseFileSync
[renderFile]: ../../api/classes/liquid_.liquid.html#renderFile
[renderFileSync]: ../../api/classes/liquid_.liquid.html#renderFilesync
@@ -0,0 +1,39 @@
---
title: 贡献指南
---
## 发起 Pull Request
**代码风格**LiquidJS 采用 [standard](https://github.com/standard/eslint-config-standard) 和 [@typescript-eslint/recommended](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.json) 规则,提交前确保可以通过风格检查:
```bash
npm run lint
```
**测试**:确保你改动之后测试仍然可以通过:
```bash
npm test
```
**提交消息**:请遵守 [Angular 提交消息规范](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits),尤其注意 [type 标识](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#type)semantic-release 机器人依赖这个标识自动发布。
## Star on Github 👉 [![harttle/liquidjs](https://img.shields.io/github/stars/harttle/liquidjs?style=flat-square)][liquidjs]
这是支持我们最简单的方式:通过提升排名来让更多人了解,让它得到更好的改进。
## 成为赞助者!
LiquidJS 是开源的、免费的,并且 **没有** 商业支持,也 **没有** 任何广告。如果你喜欢 LiquidJS 或你的公司在使用 LiquidJS,请考虑通过 [Open Collective][oc] 或 [Patreon][pt] 赞助,作为感谢你的名字和头像(或 Logo)会展示在这里和 [Github README][liquidjs]。
<object type="image/svg+xml" data="https://opencollective.com/liquidjs/tiers/backer.svg?avatarHeight=72"></object>
[![Become a Patron!](../../icon/[email protected])](https://www.patreon.com/bePatron?u=32321060)
[oc]: https://opencollective.com/liquidjs/
[pt]: https://www.patreon.com/harttle
[shopify/liquid]: https://shopify.github.io/liquid/
[caniuse-promises]: http://caniuse.com/#feat=promises
[pp]: https://github.com/taylorhakes/promise-polyfill
[tutorial]: https://shopify.github.io/liquid/basics/introduction/
[liquidjs]: https://github.com/harttle/liquidjs
@@ -0,0 +1,29 @@
---
title: 迁移到 LiquidJS 9
---
LiquidJS 9 有一些基础性的改进,包括一些缺陷修复、新特性、性能提升,也有一些不兼容的变更。
## 新特性
* 同步渲染:新增了 renderSync, parseAndRenderSync, renderFileSync API
* 新的工具:Expression 和 Tokenizer
## 修复
* 布尔逻辑运算顺序,见 [#130](https://github.com/harttle/liquidjs/issues/130)
* `break``continue` 会忽略它们之前的代码,见 [#123](https://github.com/harttle/liquidjs/issues/123)
* React.js 示例无法正确 yarn install,见 [#145](https://github.com/harttle/liquidjs/issues/145)
* 有时没有正确地等待 Promise 类型的 Drops。
## 性能
* 目标平台提升到 Node.js 8 引起的性能提升(去掉了一些 Polyfill),见 [#137](https://github.com/harttle/liquidjs/issues/137)
* 内存使用降低了 57.5%,见 [#202](https://github.com/harttle/liquidjs/pull/202)
* 渲染性能提升了 100.3%,见 [#205](https://github.com/harttle/liquidjs/pull/205)。
## 不兼容的变更
* LiquidJS 不再有默认导出了,以后要使用 `import {Liquid} from 'liquidjs'` 语法。使用 UMD 包里的 `window.Liquid` 也需要改为 `window.liquidjs.Liquid`
* 移除了重复的静态方法 `Liquid.evalValue`,统一使用示例方法 `liquid.evalValue`
* 支持的最低目标平台为 Node.js 8,CJS 包(Node.js 下的主入口)不再支持 Node.js &leq; 6 了,ESMdist/liquid.esm.js)和 UMDdist/liquid.js, dist/liquid.min.js)包不受影响。
+21
View File
@@ -0,0 +1,21 @@
---
title: 运算符
---
LiquidJS 运算符非常简单也很特别,只支持两类运算符:
* 比较运算符:`==`, `!=`, `>`, `<`, `>=`, `<=`
* 逻辑运算符:`or`, `and`, `contains`
因此普通的数学运算是不支持的,比如 `{% raw %}{{a + b}}{% endraw %}`。它的替代方案是过滤器 `{% raw %}{{ a | plus: b}}{% endraw %}`。事实上 `+` 在 LiquidJS 中是一个合法的变量名。
## 优先级
1. 比较运算符。所有比较运算符具有同样的优先级,且高于逻辑运算符。
2. 逻辑运算符。所有逻辑运算符具有同样的有衔接。
## 结合性
逻辑运算符是又结合的,所以连续的逻辑运算时计算顺序是从右向左,参考 [Shopify][operator-order] 的文档。
[operator-order]: https://help.shopify.com/en/themes/liquid/basics/operators#order-of-operations
+75
View File
@@ -0,0 +1,75 @@
---
title: 概述
---
LiquidJS 是一个简单的、安全的、兼容 Shopify 的、纯 JavaScript 编写的模板引擎。这个项目的目的是为 JavaScript 社区提供一个 Liquid 模板引擎的实现。
## 在 Node.js 里使用
通过 NPM 安装:
```bash
npm install --save liquidjs
```
```javascript
var { Liquid } = require('liquidjs');
var engine = new Liquid();
engine
.parseAndRender('{{name | capitalize}}', {name: 'alice'})
.then(console.log); // 输出 'Alice'
```
{% note info 示例 %} 这里有一个 LiquidJS 在 Node.js 里使用的例子:<a href="https://github.com/harttle/liquidjs/blob/master/demo/nodejs/" target="_blank">liquidjs/demo/nodejs/</a>.{% endnote %}
LiquidJS 的类型定义也导出并发布到了 NPM 包里,写 TypeScript 的项目可以直接这样使用:
```typescript
import { Liquid } from 'liquidjs';
const engine = new Liquid();
engine
.parseAndRender('{{name | capitalize}}', {name: 'alice'})
.then(console.log); // 输出 'Alice'
```
{% note info 示例 %} 这里有一个 LiquidJS 在 TypeScript 下的例子:<a href="https://github.com/harttle/liquidjs/blob/master/demo/typescript/" target="_blank">liquidjs/demo/typescript/</a>.{% endnote %}
## 在浏览器里使用
LiquidJS 预先构建了 UMD 打包(包括压缩版和未压缩版),可以通过 NPM 包来使用:
```html
<script src="//unpkg.com/liquidjs/dist/liquid.min.js"></script> <!--生产环境-->
<script src="//unpkg.com/liquidjs/dist/liquid.js"></script> <!--开发环境t-->
```
或者直接引用 jsDelivr CDN 上的版本:
```html
<script src="https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.min.js"></script> <!--生产环境-->
<script src="https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.js"></script> <!--开发环境t-->
```
{% note info 示例 %} 这里有一个 jsFiddle 上的在线例子:<a href="https://jsfiddle.net/x43eb0z6/" target="_blank">jsfiddle.net/x43eb0z6</a>,其源码也可以在 <a href="https://github.com/harttle/liquidjs/blob/master/demo/browser/" target="_blank">liquidjs/demo/browser/</a> 找到。{% endnote %}
{% note warn 兼容性 %} 在类似 IE 和 Android UC 这样的浏览器中,你可能需要引入 <a href="https://github.com/taylorhakes/promise-polyfill" target="_blank">Promise polyfill</a>,参看 <a href="http://caniuse.com/#feat=promises" target="_blank">caniuse 的统计</a>。 {% endnote %}
## 在命令行里使用
你还可以在命令行里使用 LiquidJS:
```bash
echo '{{"hello" | capitalize}}' | npx liquidjs
```
模板来自标准输入,数据则来自参数,这个参数可以是一个 JSON 文件的路径,也可以是一个 JSON 字符串:
```bash
echo 'Hello, {{ name }}.' | npx liquidjs '{"name": "Snake"}'
```
## 其他
[@stevenanthonyrevo](https://github.com/stevenanthonyrevo) 还提供了一个 ReactJS demo,请参考 [liquidjs/demo/reactjs/](https://github.com/harttle/liquidjs/blob/master/demo/reactjs/)。
@@ -0,0 +1,56 @@
---
title: 引用和继承
---
## 引用模板片段
对于如下两个模板文件:
```
// 文件:color.liquid
color: '{{ color }}' shape: '{{ shape }}'
// 文件:theme.liquid
{% assign shape = 'circle' %}
{% include 'color' %}
{% include 'color' with 'red' %}
{% include 'color', color: 'yellow', shape: 'square' %}
```
输出为:
```
color: '' shape: 'circle'
color: 'red' shape: 'circle'
color: 'yellow' shape: 'square'
```
## 布局模板(模板继承)
对于如下两个模板文件:
```
// 文件:default-layout.liquid
Header
{% block content %}My default content{% endblock %}
Footer
// 文件:page.liquid
{% layout "default-layout" %}
{% block content %}My page content{% endblock %}
```
渲染 `page.liquid` 将会输出:
```
Header
My page content
Footer
```
{% note tip Block %}
<ul>
<li>布局文件(父模板)中可以定义多个 block</li>
<li>只有一个 block 时,block 名字可以省略。</li>
</ul>
{% endnote %}
+49
View File
@@ -0,0 +1,49 @@
---
title: 插件
---
一组标签和过滤器可以封装为一个 **插件**,通常发包到 NPM 来方便使用。本文介绍如何创建和使用插件。
## 编写插件
LiquidJS 插件就是一个简单的函数,它的第一个参数是 [Liquid 类][liquid],其中的 `this` 是它被注册到的 Liquid 实例。可以通过 `this` 来调用 Liquid API,比如 [注册标签和过滤器][register]。
现在我们来写一个插件并在其中注册一个过滤器,来把输入字符串转换为大写:
```javascript
/**
* Inside the plugin function, `this` refers to the Liquid instance.
*
* @param Liquid: provides facilities to implement tags and filters.
*/
module.exports = function (Liquid) {
this.registerFilter('upup', x => x.toUpperCase());
}
```
把上述代码保存为 `upup.js`
## 使用插件
把插件传递给 `.plugin()` 方法即可注册插件,例如:
```javascript
const engine = new Liquid()
engine.plugin(require('./upup.js'));
engine.parseAndRender('{{ "foo" | upup }}').then(console.log)
```
上述代码将会输出 `"FOO"`
## 插件列表
由于本仓库只包含 [Shopify/liquid](https://github.com/Shopify/liquid/) 核心仓库的标签和插件(参考 <https://github.com/harttle/liquidjs#differences-and-limitations>),Shopify 平台上特有的插件只能通过插件来使用。
这里是一个插件列表,欢迎添加你的插件(点击右上角编辑按钮):
* Sections 标签(开发中): https://github.com/harttle/liquidjs-section-tags
* 颜色过滤器: https://github.com/harttle/liquidjs-color-filters
[liquid]: ../../api/classes/liquid_.liquid.html
[register]: ./register-filters-tags.html
@@ -0,0 +1,39 @@
---
title: 注册标签和过滤器
---
## 注册标签
```javascript
// 使用方式: {% upper name%}
engine.registerTag('upper', {
parse: function(tagToken, remainTokens) {
this.str = tagToken.args; // name
},
render: async function(scope, hash) {
var str = await this.liquid.evalValue(this.str, scope); // 'alice'
return str.toUpperCase() // 'Alice'
}
});
```
* `parse`: 从 `remainTokens` 中读取后续的标签/输出/HTML,直到找到你期望的结束标签。
* `render`: 把 scope 数据和此前解析得到的 Token 结合,输出 HTML 字符串。
查看已有的标签实现:<https://github.com/harttle/liquidjs/tree/master/src/builtin/tags>
## 注册过滤器
```javascript
// 使用方式: {{ name | upper }}
engine.registerFilter('upper', v => v.toUpperCase())
```
过滤器的参数将会传递给上面注册的过滤器函数,从第二个参数开始(第一个参数是过滤器左侧的输入),例如:
```javascript
// Usage: {{ 1 | add: 2, 3 }}
engine.registerFilter('add', (initial, arg1, arg2) => initial + arg1 + arg2)
```
查看已有的过滤器实现:<https://github.com/harttle/liquidjs/tree/master/src/builtin/filters>
+113
View File
@@ -0,0 +1,113 @@
---
title: 渲染文件
---
一个典型的项目会有一个目录下都是模板,最方便的方式就是设置 LiquidJS 的 [root][root] 然后调用 [.renderFile()][renderFile] 或 [.renderFileSync()][renderFileSync] 来渲染其中的一个模板文件。
## 渲染一个文件
例如你有如下的目录结构:
```
.
├── index.js
└── views/
├── hello.liquid
└── world.liquid
```
其中 `hello.liquid` 内容为:
```liquid
name: {{name}}
```
`index.js` 中可以这样渲染 `hello.liquid`:
```javascript
var engine = new Liquid({
root: path.resolve(__dirname, 'views/'), // 设置模板查找目录
extname: '.liquid' // 添加后缀,默认为 "" 表示不添加后缀
});
// 将会读取并渲染 `views/hello.liquid`
engine.renderFile("hello", {name: 'alice'}).then(console.log)
```
执行 `node index.js` 你将会得到类似这样的输出:
```
name: alice
```
## 模板查找
传递给 [.renderFile()][renderFile], [.parseFile()][parseFile] [.renderFileSync()][renderFileSync], [.parseFileSync()][parseFileSync] 这些 API 的模板名,
以及传递给 [include][include], [layout][layout] 这些标签的模板名,将会根据 [root][root] 选项来查找。
`root` 可以设置为 `string` 类型的路径(见上面的例子), 也可以设置为一个字符串数组表示路径列表,这时 LiquidJS 将会按顺序去查找。例如:
```javascript
var engine = new Liquid({
root: ['views/', 'views/partials/'],
extname: '.liquid'
});
```
{% note tip 相对路径 %}<code>root</code> 中使用相对路径将会被解释为相对于 <code>cwd()</code>(当前工作目录)。{% endnote %}
当模板中引入子模板时(`{% raw %}{% render "foo" %}{% endraw %}`),或者调用 `.renderFile('foo')` 时,LiquidJS 会依次查看如下几个文件,并渲染第一个存在的文件:
- `cwd()`/views/foo.liquid
- `cwd()`/views/partials/foo.liquid
如果上述文件都不存在,将会抛出一个 `ENOENT` 错误。
{% note info 示例 %} 在 Node.js 示例中展示了怎么渲染一个文件 <a href="https://github.com/harttle/liquidjs/blob/master/demo/nodejs/" target="_blank">liquidjs/demo/nodejs/</a>。{% endnote %}
在浏览器中使用 LiquidJS 时,比如当前路径为 <https://example.com/bar/index.html>,只会去 `root` 数组中的第一个路径下获取,也就是这个文件:
- <https://example.com/bar/foo.liquid>
如果获取失败(比如得到一个 404/500 错误)或网络错误,将会抛出一个 `ENOENT` 错误。
{% note info 示例 %} 在这个示例中展示了如何从网络获取并渲染一个模板文件 <a href="https://github.com/harttle/liquidjs/blob/master/demo/browser/" target="_blank">liquidjs/demo/browser/</a>。{% endnote %}
## 文件系统接口
LiquidJS 定义了一个文件系统接口([src/fs/ifs.ts][ifs]),在 Node.js 下的默认实现是 [src/fs/node.ts][fs-node],在浏览器打包文件中的默认实现是 [src/fs/browser.ts][fs-browser]。
你可以通过创建 `Liquid` 时的 [fs][fs] 参数来指定一个自定义实现来指定如何读取模板文件。比如从数据库里读取:
```javascript
const engine = new Liquid({
fs: {
readFileSync (file) {
return db.model('Template').findByIdSync(file).text
},
await readFile (file) {
const template = await db.model('Template').findById(file)
return template.text
},
existsSync () {
return true
},
await exists () {
return true
},
resolve(root, file, ext) {
return file
}
}
});
```
[fs]: ../../api/interfaces/liquid_options_.liquidoptions.html#Optional-fs
[ifs]: https://github.com/harttle/liquidjs/blob/master/src/fs/ifs.ts
[fs-node]: https://github.com/harttle/liquidjs/blob/master/src/fs/node.ts
[fs-browser]: https://github.com/harttle/liquidjs/blob/master/src/fs/browser.ts
[layout]: https://help.shopify.com/en/themes/liquid/tags/theme-tags#layout
[include]: https://help.shopify.com/themes/liquid/tags/theme-tags#include
[renderFile]: ../../api/classes/liquid_.liquid.html#renderFile
[renderFileSync]: ../../api/classes/liquid_.liquid.html#renderFilesync
[parseFile]: ../../api/classes/liquid_.liquid.html#parseFile
[parseFileSync]: ../../api/classes/liquid_.liquid.html#parseFileSync
[root]: ../../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
+52
View File
@@ -0,0 +1,52 @@
---
title: 基本语法
---
LiquidJS 语法相对简单。LiquidJS 中有两种标记:
- **标签**。标签由标签名和参数构成,由 `{%raw%}{%{%endraw%}``%}` 包裹。
- **输出**。输出由一个值和一组可选的过滤器构成,由 `{%raw%}{{{%endraw%}``}}` 包裹。
## 输出
**输出** 用于转换和输出变量到 HTMl。下面的模板将会把 `username` 的值插入到 input 的 `value`
```liquid
<input type="text" name="user" value="{{username}}">
```
*输出* 里的值可以在输出之前经过若干个 **过滤器** 的转换。比如在变量后面追加一个字符串:
```liquid
{{ username | append: ", welcome to LiquidJS!" }}
```
过滤器可以级联,用起来像管道一样:
```liquid
{{ username | append: ", welcome to LiquidJS!" | capitalize }}
```
[这里](../filters/overview.html) 是 LiquidJS 支持的完整的过滤器列表。
## 标签
**标签** 用于控制模板渲染过程,操作模板变量,和其他模板交互等。例如 `assign` 可以用来定义一个模板中可以使用的变量:
```liquid
{% assign foo = "FOO" %}
```
一般标签成对地出现,一个开始标签和一个对应的结束标签,比如:
```liquid
{% if foo == "FOO" %}
Variable `foo` equals "FOO"
{% else %}
Variable `foo` not equals "FOO"
{% endif %}
```
[这里](../tags/overview.html) 是 LiquidJS 支持的完整的标签列表。
[shopify/liquid]: https://github.com/Shopify/liquid
@@ -0,0 +1,27 @@
---
title: 真和假
---
虽然我们希望 [Liquid][sl] 是平台无关的,但 JavaScript 版本和 [Ruby 版本][ruby] 仍然有[很多区别][diff],真值就是其中之一。
## 真值表
根据 [Shopify 的文档](https://shopify.github.io/liquid/basics/truthy-and-falsy/)Ruby 版本除了 `false``nil` 之外的所有值都是真,但 JavaScript 有完全不同的类型系统,比如我们有 `undefined` 类型,以及不区分 `integer``float`,因此有些不同:
value | truthy | falsy
--- | --- | ---
`true` | ✔️ |
`false` | | ✔️
`null` | | ✔️
`undefined` | | ✔️
`string` | ✔️ |
`empty string` | ✔️ |
`0` | ✔️ |
`integer` | ✔️ |
`float` | ✔️ |
`array` | ✔️ |
`empty array` | ✔️ |
[ruby]: https://shopify.github.io/liquid
[sl]: https://www.npmjs.com/package/liquidjs
[diff]: https://github.com/harttle/liquidjs#differences-and-limitations
@@ -0,0 +1,72 @@
---
title: 在 Express.js 里使用
---
LiquidJS 可以用来作为 [Express 的模板引擎](https://expressjs.com/en/resources/template-engines.html)。可以把 Liquid 设置到 [view engine][express-views] 选项上即可:
```javascript
var { Liquid } = require('liquidjs');
var engine = new Liquid();
// 注册为 liquid 文件的模板引擎
app.engine('liquid', engine.express());
app.set('views', './views'); // 指定模板目录
app.set('view engine', 'liquid'); // 把 liquid 文件设为默认模板
```
{% note info 示例 %} 这是一个在 Express.js 中使用 LiquidJS 的例子:<a href="https://github.com/harttle/liquidjs/blob/master/demo/express/" target="_blank">liquidjs/demo/express/</a>.{% endnote %}
## 模板查找
LiquidJS 仍然会去 [root][root] 指定的目录查找(参考 [Render A Template File][render-a-file]),也会去 Express.js 的 [`views`][express-views] 选项指定的目录里(上述例子中是 `./views`)去查找。例如你有这样的目录结构:
```
.
├── views1/
│ └── hello.liquid
└── views2/
└── world.liquid
```
LiquidJS 的模板 root 设置到了 `views1`Express.js 的 views 设置到了 `views2`
```javascript
var { Liquid } = require('liquidjs');
var engine = new Liquid({
root: './views1/'
});
app.engine('liquid', engine.express());
app.set('views', './views2');
app.set('view engine', 'liquid');
```
`hello.liquid``world.liquid` 两个文件都可以找到并且成功渲染:
```javascript
res.render('hello')
res.render('world')
```
## 缓存
直接把 [cache 选项][cache] 设为 `true` 即可开启模板缓存,参考 [缓存][Caching] 一文。推荐在生产环境中开启缓存,可以用如下代码:
```javascript
var { Liquid } = require('liquidjs');
var engine = new Liquid({
cache: process.env.NODE_ENV === 'production'
});
```
`cache` 还可以是一个数字表示最大缓存的模板数量,也可以是一个自定义的缓存实现,详情请参考 [cache 选项][cache]。
[cache]: ../../api/interfaces/liquid_options_.liquidoptions.html#Optional-cache
[express-views]: http://expressjs.com/en/guide/using-template-engines.html
[parseFile]: ../../api/classes/liquid_.liquid.html#parseFile
[parseFileSync]: ../../api/classes/liquid_.liquid.html#parseFileSync
[layout]: https://help.shopify.com/en/themes/liquid/tags/theme-tags#layout
[include]: https://help.shopify.com/themes/liquid/tags/theme-tags#include
[root]: ../../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
[render-a-file]: ./render-a-file.html
[Caching]: ./caching.html
@@ -0,0 +1,56 @@
---
title: 空白字符控制
---
为了让源代码缩进好看,我们会加很多空白字符比如把不会产生输出的标签也单独一行。LiquidJS 提供了空白字符控制机制,可以避免这些多余的空白字符输出到 HTML 中。
## 通过标记的方式
默认所有标签和输出的行,都会在行尾产生一个换行(`\n`),如果有缩进的话还会产生很多前导空格。例如:
```liquid
{% author = "harttle" %}
{{ author }}
```
将会输出(注意前面的空行):
```
harttle
```
可以在标签和输出的标记里面加横线(`{% raw %}{{-{% endraw %}`, `-}}`, `{% raw %}{%-{% endraw %}`, `-%}`)来移除左侧/右侧的空白。例如:
```liquid
{% assign author = "harttle" -%}
{{ author }}
```
将会输出:
```
harttle
```
这个例子中 `-%}` 移除了 `assign` 标签右侧的空白。
## 通过选项
此外 LiquidJS 还提供了一系列选项来帮助扫代码式地移除空白:
* `trimTagLeft`
* `trimTagRight`
* `trimValueRight`
* `trimValueRight`
[LiquidJS][liquidjs] 默认 **不会** 移除任何空白字符,也就是说上面几个选项的默认值都为 `false`。这几个选项的详情请参考 [LiquidJS 选项][options]。
## 贪婪模式
上述几个设置默认情况下会跨越换行(`\n`),如果你希望保留上下空行可以把 [greedy 选项][liquidjs] 关掉,这样遇到 `\n` 就会停止。为了和 [shopify/liquid][shopify/liquid] 一致该选项默认是打开的。
[shopify/liquid]: https://github.com/Shopify/liquid
[liquidjs]: https://github.com/harttle/liquidjs
[options]: ../../api/interfaces/liquid_options_.liquidoptions.html
[greedy]: ../../api/interfaces/liquid_options_.liquidoptions.html#Optional-greedy