Skip to content

Commit 94a6715

Browse files
committed
docs: zh-cn translation for static analyze features
1 parent 3492ff6 commit 94a6715

File tree

3 files changed

+303
-6
lines changed

3 files changed

+303
-6
lines changed

docs/source/tutorials/static-analysis.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ title: Static Template Analysis
44

55
{% since %}v10.20.0{% endsince %}
66

7+
{% note warn Experimental %}
8+
Note that this is an experimental feature and future APIs are subject to change. And internal structures returned can be changed w/o a major version bump.
9+
{% endnote %}
10+
711
{% note info Sync and Async %}
8-
There are synchronous and asynchronous versions of each of the methods demonstrated on this page. See the [Liquid API](liquid-api) for a complete reference.
12+
There are synchronous and asynchronous versions of each of the methods demonstrated on this page. See the [Liquid API][liquid-api] for a complete reference.
913
{% endnote %}
1014

1115
## Variables
@@ -17,7 +21,7 @@ import { Liquid } from 'liquidjs'
1721

1822
const engine = new Liquid()
1923

20-
const template = engine.parse(`\
24+
const template = engine.parse(`
2125
<p>
2226
{% assign title = user.title | capitalize %}
2327
{{ title }} {{ user.first_name | default: user.name }} {{ user.last_name }}
@@ -129,15 +133,15 @@ By default, LiquidJS will try to load and analyze any included and rendered temp
129133
```javascript
130134
import { Liquid } from 'liquidjs'
131135

132-
const footer = `\
136+
const footer = `
133137
<footer>
134138
<p>&copy; {{ "now" | date: "%Y" }} {{ site_name }}</p>
135139
<p>{{ site_description }}</p>
136140
</footer>`
137141

138142
const engine = new Liquid({ templates: { footer } })
139143

140-
const template = engine.parse(`\
144+
const template = engine.parse(`
141145
<body>
142146
<h1>Hi, {{ you | default: 'World' }}!</h1>
143147
{% assign some = 'thing' %}
@@ -171,7 +175,7 @@ If an `{% include %}` tag uses a dynamic template name (one that can't be determ
171175

172176
### Advanced Usage
173177

174-
The examples so far all use convenience methods of the `Liquid` class, intended to cover the most common use cases. Instead, you can work with [analysis results](static-analysis-interface) directly, which expose the row, column and file name for every occurrence of each variable.
178+
The examples so far all use convenience methods of the `Liquid` class, intended to cover the most common use cases. Instead, you can work with [analysis results][static-analysis-interface] directly, which expose the row, column and file name for every occurrence of each variable.
175179

176180
This is an example of an object returned from `Liquid.analyze()`, passing it the template from the [Partial Template](#partial-templates) section above.
177181

@@ -238,7 +242,7 @@ The [`blockScope()`](/api/interfaces/Template.html#blockScope) method is respons
238242

239243
Whether a tag is an inline tag or a block tag, if it accepts arguments it should implement [`arguments()`](/api/interfaces/Template.html#arguments), which is responsible for returning the tag's arguments as a sequence of [`Value`](/api/classes/Value.html) instances or tokens of type [`ValueToken`](/api/types/ValueToken.html).
240244

241-
This example demonstrates these methods for a block tag. See LiquidJS's [built-in tags](built-in) for more examples.
245+
This example demonstrates these methods for a block tag. See LiquidJS's [built-in tags][built-in] for more examples.
242246

243247
```javascript
244248
import { Liquid, Tag, Hash } from 'liquidjs'
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
---
2+
title: 静态模板分析
3+
---
4+
5+
{% since %}v10.20.0{% endsince %}
6+
7+
{% note warn 实验性功能 %}
8+
这是一个实验性功能,未来的 API 可能会发生变化,返回的内部结构也可能在不进行主要版本更新的情况下更改。
9+
{% endnote %}
10+
11+
{% note info 同步与异步 %}
12+
本文中的每种方法都提供了同步和异步版本。请参阅 [Liquid API][liquid-api] 了解完整的参考信息。
13+
{% endnote %}
14+
15+
## 变量
16+
17+
可以使用 `Liquid.variables(template)` 方法获取模板中使用的变量名称。它会返回一个字符串数组,每个字符串代表一个不同的变量,不包括其属性。
18+
19+
```javascript
20+
import { Liquid } from 'liquidjs'
21+
22+
const engine = new Liquid()
23+
24+
const template = engine.parse(`
25+
<p>
26+
{% assign title = user.title | capitalize %}
27+
{{ title }} {{ user.first_name | default: user.name }} {{ user.last_name }}
28+
{% if user.address %}
29+
{{ user.address.line1 }}
30+
{% else %}
31+
{{ user.email_addresses[0] }}
32+
{% for email in user.email_addresses %}
33+
- {{ email }}
34+
{% endfor %}
35+
{% endif %}
36+
{{ a[b.c].d }}
37+
<p>
38+
`)
39+
40+
console.log(engine.variablesSync(template))
41+
```
42+
43+
**输出**
44+
45+
```javascript
46+
[ 'user', 'title', 'email', 'a', 'b' ]
47+
```
48+
49+
可以看到,标签和过滤器参数中的变量也会包含在内,例如示例中的嵌套变量 `b`
50+
另外,可以使用 `Liquid.fullVariables(template)` 方法获取包含其属性的完整变量列表。
51+
52+
```javascript
53+
// 上例继续
54+
engine.fullVariables(template).then(console.log)
55+
```
56+
57+
**输出**
58+
59+
```javascript
60+
[
61+
'user.title',
62+
'user.first_name',
63+
'user.name',
64+
'user.last_name',
65+
'user.address',
66+
'user.address.line1',
67+
'user.email_addresses[0]',
68+
'user.email_addresses',
69+
'title',
70+
'email',
71+
'a[b.c].d',
72+
'b.c'
73+
]
74+
```
75+
76+
或者,使用 `Liquid.variableSegments(template)` 获取每个变量路径的字符串和数字数组。
77+
78+
```javascript
79+
// 上例继续
80+
engine.variableSegments(template).then(console.log)
81+
```
82+
83+
**输出**
84+
85+
```javascript
86+
[
87+
[ 'user', 'title' ],
88+
[ 'user', 'first_name' ],
89+
[ 'user', 'name' ],
90+
[ 'user', 'last_name' ],
91+
[ 'user', 'address' ],
92+
[ 'user', 'address', 'line1' ],
93+
[ 'user', 'email_addresses', 0 ],
94+
[ 'user', 'email_addresses' ],
95+
[ 'title' ],
96+
[ 'email' ],
97+
[ 'a', [ 'b', 'c' ], 'd' ],
98+
[ 'b', 'c' ]
99+
]
100+
```
101+
102+
### 全局变量
103+
104+
注意在上述示例中,`title``email` 被包含在结果中。通常你可能希望排除 `{% assign %}` 标签中定义的变量名,以及由 `{% for %}` 标签引入的临时变量。
105+
106+
为了获取 _全局_ 变量(即由应用开发者提供,而不是模板作者定义的变量)的名称,可以使用 `globalVariables``globalFullVariables``globalVariableSegments` 方法(及其同步版本)。
107+
108+
```javascript
109+
// 上例继续
110+
engine.globalVariableSegments(template).then(console.log)
111+
```
112+
113+
**输出**
114+
115+
```javascript
116+
[
117+
[ 'user', 'title' ],
118+
[ 'user', 'first_name' ],
119+
[ 'user', 'name' ],
120+
[ 'user', 'last_name' ],
121+
[ 'user', 'address' ],
122+
[ 'user', 'address', 'line1' ],
123+
[ 'user', 'email_addresses', 0 ],
124+
[ 'user', 'email_addresses' ],
125+
[ 'a', [ 'b', 'c' ], 'd' ],
126+
[ 'b', 'c' ]
127+
]
128+
```
129+
130+
### 部分模板
131+
132+
默认情况下,LiquidJS 还会尝试加载和分析任何被包含和渲染的模板。
133+
134+
```javascript
135+
import { Liquid } from 'liquidjs'
136+
137+
const footer = `
138+
<footer>
139+
<p>&copy; {{ "now" | date: "%Y" }} {{ site_name }}</p>
140+
<p>{{ site_description }}</p>
141+
</footer>`
142+
143+
const engine = new Liquid({ templates: { footer } })
144+
145+
const template = engine.parse(`
146+
<body>
147+
<h1>Hi, {{ you | default: 'World' }}!</h1>
148+
{% assign some = 'thing' %}
149+
{% include 'footer' %}
150+
</body>
151+
`)
152+
153+
engine.globalVariables(template).then(console.log)
154+
```
155+
156+
**输出**
157+
158+
```javascript
159+
[ 'you', 'site_name', 'site_description' ]
160+
```
161+
162+
可以通过将 `partials` 选项设置为 `false` 来禁用部分模板的分析。
163+
164+
```javascript
165+
// 上例继续
166+
engine.globalVariables(template, { partials: false }).then(console.log)
167+
```
168+
169+
**输出**
170+
171+
```javascript
172+
[ 'you' ]
173+
```
174+
175+
如果 `{% include %}` 标签使用了动态模板名称(无法在渲染模板之前确定的模板名称),即使 `partials` 设置为 `true`,也会被忽略。
176+
177+
### 高级用法
178+
179+
上述示例使用的是 `Liquid` 类的便捷方法,适用于最常见的使用场景。
180+
如果需要更详细的信息,可以直接处理 [分析结果][static-analysis-interface],其中每个变量的每次出现都会记录行、列和文件名等信息。
181+
182+
此处是对 [部分模板](#部分模板) 中模板进行 `Liquid.analyze()` 调用后返回的对象示例。
183+
184+
```javascript
185+
{
186+
variables: {
187+
you: [
188+
[String (Variable): 'you'] {
189+
segments: [ 'you' ],
190+
location: { row: 2, col: 14, file: undefined }
191+
}
192+
],
193+
site_name: [
194+
[String (Variable): 'site_name'] {
195+
segments: [ 'site_name' ],
196+
location: { row: 2, col: 41, file: 'footer' }
197+
}
198+
],
199+
site_description: [
200+
[String (Variable): 'site_description'] {
201+
segments: [ 'site_description' ],
202+
location: { row: 3, col: 9, file: 'footer' }
203+
}
204+
]
205+
},
206+
globals: {
207+
you: [
208+
[String (Variable): 'you'] {
209+
segments: [ 'you' ],
210+
location: { row: 2, col: 14, file: undefined }
211+
}
212+
],
213+
site_name: [
214+
[String (Variable): 'site_name'] {
215+
segments: [ 'site_name' ],
216+
location: { row: 2, col: 41, file: 'footer' }
217+
}
218+
],
219+
site_description: [
220+
[String (Variable): 'site_description'] {
221+
segments: [ 'site_description' ],
222+
location: { row: 3, col: 9, file: 'footer' }
223+
}
224+
]
225+
},
226+
locals: {
227+
some: [
228+
[String (Variable): 'some'] {
229+
segments: [ 'some' ],
230+
location: { row: 3, col: 13, file: undefined }
231+
}
232+
]
233+
}
234+
}
235+
```
236+
237+
### 自定义标签的分析
238+
239+
为了在静态分析中包含自定义标签的结果,这些标签必须实现 [Template 接口]( /api/interfaces/Template.html) 中定义的一些附加方法。LiquidJS 会使用这些方法返回的信息来遍历模板并报告变量使用情况。
240+
241+
并非所有方法都是必须的,这取决于标签的类型。如果标签是一个块标签,具有起始标签、结束标签以及内容,那么它需要实现 [`children()`](/api/interfaces/Template.html#children) 方法。`children()` 需要返回一个生成器,这是为了像 `render()` 一样既可以同步也可以异步调用。该方法应返回当前标签的子节点,例如 HTML 内容、输出语句和标签。
242+
243+
[`blockScope()`](/api/interfaces/Template.html#blockScope) 方法用于告知 LiquidJS 在标签块的持续时间内哪些名称会处于作用域中。这些名称可能依赖于标签的参数,也可能是固定的,例如 `{% for %}` 标签生成的 `forloop`
244+
245+
无论标签是行内标签还是块标签,如果它接受参数,则应实现 [`arguments()`](/api/interfaces/Template.html#arguments) 方法,该方法负责将标签的参数作为 [`Value`](/api/classes/Value.html) 实例或类型为 [`ValueToken`](/api/types/ValueToken.html) 的标记序列返回。
246+
247+
以下示例展示了块标签如何实现这些方法。有关更多示例,请参见 LiquidJS 的[内置标签][built-in]
248+
249+
```javascript
250+
import { Liquid, Tag, Hash } from 'liquidjs'
251+
252+
class ExampleTag extends Tag {
253+
args
254+
templates
255+
256+
constructor (token, remainTokens, liquid, parser) {
257+
super(token, remainTokens, liquid)
258+
this.args = new Hash(token.tokenizer)
259+
this.templates = []
260+
261+
const stream = parser.parseStream(remainTokens)
262+
.on('tag:endexample', () => { stream.stop() })
263+
.on('template', (tpl) => this.templates.push(tpl))
264+
.on('end', () => { throw new Error(`tag ${token.getText()} not closed`) })
265+
266+
stream.start()
267+
}
268+
269+
* render (ctx, emitter) {
270+
const scope = (yield this.args.render(ctx))
271+
ctx.push(scope)
272+
yield this.liquid.renderer.renderTemplates(this.templates, ctx, emitter)
273+
ctx.pop()
274+
}
275+
276+
* children () {
277+
return this.templates
278+
}
279+
280+
* arguments () {
281+
yield * Object.values(this.args.hash).filter((el) => el !== undefined)
282+
}
283+
284+
blockScope () {
285+
return Object.keys(this.args.hash)
286+
}
287+
}
288+
```
289+
290+
[liquid-api]: /api/classes/Liquid.html
291+
[static-analysis-interface]: /api/interfaces/StaticAnalysis.html
292+
[built-in]: https://github.com/harttle/liquidjs/tree/master/src/tags

docs/themes/navy/languages/zh-cn.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ sidebar:
5252
operators: 运算符
5353
truth: 真和假
5454
dos: DoS
55+
static_analysis: 静态分析
5556

5657
miscellaneous: 其他
5758
migration9: '迁移到 LiquidJS 9'

0 commit comments

Comments
 (0)