1
1
---
2
2
sidebar : auto
3
3
---
4
- # markdown-it design principles
4
+ # markdown-it 设计准则
5
5
6
- ## Data flow
6
+ ## 数据流
7
7
8
- Input data is parsed via nested chains of rules. There are 3 nested chains -
9
- ` core ` , ` block ` & ` inline ` :
8
+ 输入数据通过嵌套的规则链来解析。有三种嵌套的链 -
9
+ ` core ` , ` block ` 和 ` inline ` :
10
10
11
11
```
12
12
core
19
19
...
20
20
block.ruleX
21
21
22
- core.ruleX1 (intermediate rule that applies on block tokens, nothing yet )
22
+ core.ruleX1 (应用在块 tokens 的中间层规则,不算什么 )
23
23
...
24
24
core.ruleXX
25
25
26
- inline (applied to each block token with "inline" type )
26
+ inline (应用于内联类型的每个块 token)
27
27
inline.rule1 (text)
28
28
...
29
29
inline.ruleX
30
30
31
- core.ruleYY (applies to all tokens)
31
+ core.ruleYY (应用于所有 tokens)
32
32
... (abbreviation, footnote, typographer, linkifier)
33
33
34
34
```
35
35
36
- The result of the parsing is a * list of tokens* , that will be passed to the ` renderer ` to generate the html content.
36
+ 解析的结果是一个 * list tokens* ,它将被传递给 ` renderer ` 来生成 html 内容。
37
37
38
- These tokens can be themselves parsed again to generate more tokens (ex: a ` list token ` can be divided into multiple ` inline tokens` ).
38
+ 这些 tokens 能被自身解析来生成更多的 tokens。(例如:一个 ` list token ` 能被拆分为多个内联 tokens)。
39
39
40
- An ` env ` sandbox can be used alongside tokens to inject external variables for your parsers and renderers.
40
+ 一个 ` env ` 沙盒能被用来与 tokens 来给你的解析器和渲染器注入额外的变量。
41
41
42
- Each chain ( core / block / inline) uses an independent ` state ` object when parsing data, so that each parsing operation is independent and can be disabled on the fly.
42
+ 当解析数据时,每个链( core / block / inline)会使用一个独立的 ` state ` 对象,所以每个解析中的操作都是独立的,并且能在运行时被禁用。
43
43
44
+ ## Token 流
44
45
45
- ## Token stream
46
+ 不像传统的 AST,我们使用更加底层的数据代表 - * tokens* 。
47
+ 不同之处一目了然:
46
48
47
- Instead of traditional AST we use more low-level data representation - * tokens* .
48
- The difference is simple:
49
+ - Tokens 是一个简单的序列(数组)。
50
+ - 打开的和关闭的标签是隔离的。
51
+ - 有特殊的 token 对象,比如“内联容器(inline container)”,它有嵌套的 tokens。
52
+ - 一系列内联的标签(粗体,斜体,文本等等)
49
53
50
- - Tokens are a simple sequence (Array).
51
- - Opening and closing tags are separate.
52
- - There are special token objects, "inline containers", having nested tokens.
53
- sequences with inline markup (bold, italic, text, ...).
54
+ 参考 [ token class] ( https://github.com/markdown-it/markdown-it/blob/master/lib/token.js )
55
+ 以获得关于每个 token 内容的细节。
54
56
55
- See [ token class] ( https://github.com/markdown-it/markdown-it/blob/master/lib/token.js )
56
- for details about each token content.
57
+ 总之,一个 token 流是:
57
58
58
- In total, a token stream is:
59
+ - 在顶层 - 是成对或单个“块” tokens 的数组:
60
+ - 打开的/关闭的标题,列表,块引用,段落,...
61
+ - 代码,围栏块,水平规则,html 块,内联容器
62
+ - 每个内联 token 都有一个` .children ` 属性,带有嵌套 token 流,用于内联内容:
63
+ - 打开的/关闭的 strong 强调,em 强调,链接,代码,...
64
+ - 文字,换行符
59
65
60
- - On the top level - array of paired or single "block" tokens:
61
- - open/close for headers, lists, blockquotes, paragraphs, ...
62
- - codes, fenced blocks, horizontal rules, html blocks, inlines containers
63
- - Each inline token have a ` .children ` property with a nested token stream for inline content:
64
- - open/close for strong, em, link, code, ...
65
- - text, line breaks
66
+ 为什么不是 AST?因为我们的任务不需要它。我们遵循 KISS 原则。
67
+ 如果你愿意的话 - 你可以在没有渲染器的情况下调用解析器并转换 tokens 流到 AST。
66
68
67
- Why not AST? Because it's not needed for our tasks. We follow KISS principle.
68
- If you wish - you can call a parser without a renderer and convert the token stream
69
- to an AST.
69
+ 更多关于 tokens 的细节:
70
70
71
- More details about tokens:
71
+ - [ Renderer 源码] ( https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js )
72
+ - [ Token 源码] ( https://github.com/markdown-it/markdown-it/blob/master/lib/token.js )
73
+ - [ 在线示例] ( https://markdown-it.github.io/ ) - 输入你的文本然后点击 ` debug ` tab。
72
74
73
- - [ Renderer source] ( https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js )
74
- - [ Token source] ( https://github.com/markdown-it/markdown-it/blob/master/lib/token.js )
75
- - [ Live demo] ( https://markdown-it.github.io/ ) - type your text and click ` debug ` tab.
76
75
76
+ ## 规则(Rules)
77
77
78
- ## Rules
78
+ Rules 是用解析器的 ` state ` 对象做“有魔力的事情”的函数。一个唯一的规则会与一个或多个 ** 链 ** 相关联。例如, ` blockquote ` 标记与 ` blockquote ` , ` paragraph ` , ` heading ` 和 ` list ` 链相关联。
79
79
80
- Rules are functions, doing "magic" with parser ` state ` objects. A rule is associated with one or more * chains * and is unique. For instance, a ` blockquote ` token is associated with ` blockquote ` , ` paragraph ` , ` heading ` and ` list ` chains.
80
+ Rules 通过 [ Ruler ] ( https://markdown-it.github.io/markdown-it/#Ruler ) 实例按名称管理,并且可以被 [ MarkdownIt ] ( https://markdown-it.github.io/markdown-it/#MarkdownIt ) 方法 ` enabled ` / ` disabled ` 。
81
81
82
- Rules are managed by names via [ Ruler ] ( https://markdown-it.github.io/markdown-it/#Ruler ) instances and can be ` enabled ` / ` disabled ` from the [ MarkdownIt ] ( https://markdown-it.github.io/markdown-it/#MarkdownIt ) methods.
82
+ 你可以注意到,某些规则具有 ` validation mode ` - 在此模式下规则不能修改 token 流,只能查看 token 的结尾。
83
83
84
- You can note, that some rules have a ` validation mode ` - in this mode rules do not
85
- modify the token stream, and only look ahead for the end of a token. It's one
86
- important design principle - a token stream is "write only" on block & inline parse stages.
84
+ 这是一个重要的设计原则 - token 流在块和内联解析阶段是“只写的”。
87
85
88
- Parsers are designed to keep rules independent of each other. You can safely enable/disable them, or
89
- add new ones. There are no universal recipes for how to create new rules - design of
90
- distributed state machines with good data isolation is a tricky business. But you
91
- can investigate existing rules & plugins to see possible approaches.
86
+ 解析器旨在使规则彼此独立。你可以安全地启用/禁用它们,或者添加新的。
87
+ 关于如何创建新规则没有通用的方法 - 设计具有良好数据隔离的分布式状态机是一项棘手的业务。但是你可以调查现有规则和插件,以查看可能的方法。
92
88
93
- Also, in complex cases you can try to ask for help in tracker. Condition is very
94
- simple - it should be clear from your ticket, that you studied docs, sources,
95
- and tried to do something yourself. We never reject with help to real developpers.
89
+ 此外,在复杂的情况下,你可以尝试在跟踪器(tracker)中寻求帮助。这种情况是很简单的 - 从你的 ticket 上可以清楚地看到,你研究过文档,源码,并尝试自己做一些事情。我们绝不会拒绝真正的开发人员。
96
90
97
91
98
- ## Renderer
92
+ ## 渲染器( Renderer)
99
93
100
- After token stream is generated, it's passed to a [ renderer] ( https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js ) .
101
- It then plays all the tokens, passing each to a rule with the same name as token type.
94
+ 生成 token 流后,将其传递给 [ renderer] ( https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js ) 。
95
+ 然后它会遍历所有 token,将每个token 传递给与 token 的 type 属性同名的规则。
102
96
103
- Renderer rules are located in ` md.renderer.rules[name] ` and are simple functions
104
- with the same signature:
97
+ 渲染器规则位于 ` md.renderer.rules [name] ` ,是简单的具有相同特征的函数:
105
98
106
99
``` js
107
100
function (tokens , idx , options , env , renderer ) {
@@ -110,8 +103,8 @@ function (tokens, idx, options, env, renderer) {
110
103
}
111
104
```
112
105
113
- In many cases that allows easy output change even without parser intrusion.
114
- For example, let's replace images with vimeo links to player's iframe:
106
+ 在许多情况下,即使在没有解析器侵入的情况下,也可以轻松地进行输出更改。
107
+ 例如,让我们替换 img 和 video 链接成播放器的 iframe
115
108
116
109
``` js
117
110
var md = require (' markdown-it' )();
@@ -132,39 +125,36 @@ md.renderer.rules.image = function (tokens, idx, options, env, self) {
132
125
' </div>\n ' ;
133
126
}
134
127
135
- // pass token to default renderer.
128
+ // 传递 token 给默认的渲染器。
136
129
return defaultRender (tokens, idx, options, env, self );
137
130
};
138
131
```
139
132
140
- Here is another example, how to add ` target="_blank" ` to all links:
133
+ 这里是其他的示例,如何添加 ` target="_blank" ` 到所有链接:
141
134
142
135
``` js
143
- // Remember old renderer, if overriden, or proxy to default renderer
136
+ // 如果覆盖,或者是对默认渲染器的代理,则记住老的渲染器。
144
137
var defaultRender = md .renderer .rules .link_open || function (tokens , idx , options , env , self ) {
145
138
return self .renderToken (tokens, idx, options);
146
139
};
147
140
148
141
md .renderer .rules .link_open = function (tokens , idx , options , env , self ) {
149
- // If you are sure other plugins can't add `target` - drop check below
142
+ // 如果你确认其他的插件不能添加 `target` - 放弃以下检查:
150
143
var aIndex = tokens[idx].attrIndex (' target' );
151
144
152
145
if (aIndex < 0 ) {
153
- tokens[idx].attrPush ([' target' , ' _blank' ]); // add new attribute
146
+ tokens[idx].attrPush ([' target' , ' _blank' ]); // 添加新属性
154
147
} else {
155
- tokens[idx].attrs [aIndex][1 ] = ' _blank' ; // replace value of existing attr
148
+ tokens[idx].attrs [aIndex][1 ] = ' _blank' ; // 替换已经存在的属性值
156
149
}
157
150
158
- // pass token to default renderer.
151
+ // 传递 token 到默认的渲染器。
159
152
return defaultRender (tokens, idx, options, env, self );
160
153
};
161
154
```
162
155
163
- Note, if you need to add attributes, you can do things without renderer override.
164
- For example, you can update tokens in ` core ` chain. That is slower, than direct
165
- renderer override, but can be more simple. Let's use
166
- [ markdown-for-inline] ( https://github.com/markdown-it/markdown-it-for-inline ) plugin
167
- to do the same thing as in previous example:
156
+ 注意,如果你需要添加属性,你可以不需要覆盖渲染器来做这些事。
157
+ 例如,你能够在 ` core ` 链中更新 tokens。这比直接覆盖渲染器慢,但这更简单。让我们使用 [ markdown-for-inline] ( https://github.com/markdown-it/markdown-it-for-inline ) 插件来做同样的事情,就像之前的例子一样:
168
158
169
159
``` js
170
160
var iterator = require (' markdown-it-for-inline' );
@@ -182,23 +172,21 @@ var md = require('markdown-it')()
182
172
```
183
173
184
174
185
- You also can write your own renderer to generate other formats than HTML, such as
186
- JSON/XML... You can even use it to generate AST.
175
+ 你也能够编写你自己的渲染器来生成其他除了 HTML 的格式,像 JSON/XML... 你甚至能够使用它来生成 AST。
187
176
177
+ ## 总结
188
178
189
- ## Summary
179
+ 这在 [ 数据流 ] ( #数据流 ) 中提到过,但让我们再重复序列一次:
190
180
191
- This was mentioned in [ Data flow] ( #data-flow ) , but let's repeat sequence again:
181
+ 1 . 解析块,并使用块 token 填充顶层 token 流。
182
+ 2 . 解析内联容器上的内容,填充 ` .children ` 属性。
183
+ 3 . 渲染过程。
192
184
193
- 1 . Blocks are parsed, and top level of token stream filled with block tokens.
194
- 2 . Content on inline containers is parsed, filling ` .children ` properties.
195
- 3 . Rendering happens.
196
-
197
- And somewhere between you can apply additional transformations :) . Full content
198
- of each chain can be seen on the top of
185
+ 介于两者之间你可以应用额外的转换:)。全部内容
186
+ 可见于每个链的顶部
199
187
[ parser_core.js] ( https://github.com/markdown-it/markdown-it/blob/master/lib/parser_core.js ) ,
200
- [ parser_block.js] ( https://github.com/markdown-it/markdown-it/blob/master/lib/parser_block.js ) and
188
+ [ parser_block.js] ( https://github.com/markdown-it/markdown-it/blob/master/lib/parser_block.js ) 和
201
189
[ parser_inline.js] ( https://github.com/markdown-it/markdown-it/blob/master/lib/parser_inline.js )
202
- files.
190
+ 文件。
203
191
204
- Also you can change output directly in [ renderer] ( https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js ) for many simple cases.
192
+ 你也可以直接在 [ renderer] ( https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js ) 中更改输出,以解决许多简单的情况。
0 commit comments