HTML逆向生成Markdown -- Part 2
HTML逆向生成Markdown – Part 2
在前文的结尾,我们已经将HTML文本处理为一个个虚拟DOM节点(JSON对象)了。
为了方便之后的处理,新增加了两个表示结束标签的节点,以方便构建DOM树。
1const result = [
2 {
3 tag: 'h2',
4 type: 42, // 不要在意`type`属性,这是自定义的,42代表`h2`元素对应数字
5 position: 1
6 },
7 {
8 tag: 'textNode',
9 type: 1,
10 position: 3,
11 content: '逆向解析HTMl'
12 },
13 {
14 tag: 'h2',
15 type: 42,
16 position: 2
17 },
18 {
19 tag: 'p',
20 type: 6,
21 position: 1
22 },
23 {
24 tag: 'a',
25 type: 2,
26 position: 1,
27 attr: {
28 href: 'https://www.baidu.com'
29 }
30 },
31 {
32 tag: 'textNode',
33 type: 1,
34 position: 3,
35 content: 'Markdown'
36 },
37 {
38 tag: 'a',
39 type: 2,
40 position: 2
41 },
42 {
43 tag: 'p',
44 type: 6,
45 position: 2
46 },
47]
构建虚拟DOM树
我们已经用position
属性标识了开始/结尾标签和文本节点,我们知道在开始和结束标签之间的节点都属于该节点的子节点。
以此类推,就表示出一颗DOM树了。
以上文的节点数组为输入我们来尝试构建一个虚拟DOM树。
- 第一个是h2标签且为开始标签
1[
2 {
3 tag: 'h2',
4 type: 42
5 }
6]
- 第二个是文本节点
1[
2 {
3 tag: 'h2',
4 type: 42,
5 child: [
6 {
7 tag: 'textNode',
8 type: 1,
9 content: '逆向解析HTMl'
10 }
11 ]
12 }
13]
- 第三个是h2的结束标签,结束标签不会改变树的结构。结束标签表示之后的节点都不是该节点的子节点。(在代码层面上来说就是回退到父节点上,之后在添加节点就是添加到父节点的子节点数组中)
1[
2 {
3 tag: 'h2',
4 type: 42,
5 child: [
6 {
7 tag: 'textNode',
8 type: 1,
9 content: '逆向解析HTMl'
10 }
11 ]
12 }
13]
- 第四个是p的开始标签。因为h2已经结束了,所以p被添加到根节点上。
1[
2 {
3 tag: 'h2',
4 type: 42,
5 child: [
6 {
7 tag: 'textNode',
8 type: 1,
9 content: '逆向解析HTMl'
10 }
11 ]
12 },
13 {
14 tag: 'p',
15 type: 6
16 }
17]
- 第五个是a的开始标签,因为上一个是p的开始标签,所以a被添加到p的子节点中
1[
2 {
3 tag: 'h2',
4 type: 42,
5 child: [
6 {
7 tag: 'textNode',
8 type: 1,
9 content: '逆向解析HTMl'
10 }
11 ]
12 },
13 {
14 tag: 'p',
15 type: 6,
16 child: [
17 {
18 tag: 'a',
19 type: 2,
20 attr: {
21 href: 'https://www.baidu.com'
22 }
23 }
24 ]
25 }
26]
- 第六个是文本节点,同理被添加到a的子节点中。
1[
2 {
3 tag: 'h2',
4 type: 42,
5 child: [
6 {
7 tag: 'textNode',
8 type: 1,
9 content: '逆向解析HTMl'
10 }
11 ]
12 },
13 {
14 tag: 'p',
15 type: 6,
16 child: [
17 {
18 tag: 'a',
19 type: 2,
20 attr: {
21 href: 'https://www.baidu.com'
22 },
23 child: [
24 {
25 tag: 'textNode',
26 type: 1,
27 position: 3,
28 content: 'Markdown'
29 }
30 ]
31 }
32 ]
33 }
34]
- 之后的两个都是结束标签,树结构也不会发生变化。
最终,我们得到的是这样一个DOM树结构:
1const result = [
2 {
3 tag: 'h2',
4 type: 42,
5 child: [
6 {
7 tag: 'textNode',
8 type: 1,
9 content: '逆向解析HTMl'
10 }
11 ]
12 },
13 {
14 tag: 'p',
15 type: 6,
16 child: [
17 {
18 tag: 'a',
19 type: 2,
20 attr: {
21 href: 'https://www.baidu.com'
22 },
23 child: [
24 {
25 tag: 'textNode',
26 type: 1,
27 position: 3,
28 content: 'Markdown'
29 }
30 ]
31 }
32 ]
33 }
34]
到这一步,我们已经将HTML文本转化成了虚拟DOM树。最后也是最关键的一步,就是分析DOM树,根据MD规则生成MD文本了。 可以说之前的三个步骤都是为了最后一步服务的。