@mehm8128/rehype-toc 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +35 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,54 +3,56 @@ import { visit } from "unist-util-visit";
|
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
const rehypeCollapsibleToc = () => {
|
|
5
5
|
return (tree) => {
|
|
6
|
-
const
|
|
6
|
+
const rootUlElement = {
|
|
7
7
|
type: "element",
|
|
8
8
|
tagName: "ol",
|
|
9
9
|
properties: {},
|
|
10
10
|
children: []
|
|
11
11
|
};
|
|
12
12
|
visit(tree, "element", (node) => {
|
|
13
|
-
visitorCallback(node,
|
|
13
|
+
visitorCallback(node, rootUlElement);
|
|
14
14
|
});
|
|
15
|
-
const detailsElement = createCollapsibleToc(
|
|
15
|
+
const detailsElement = createCollapsibleToc(rootUlElement);
|
|
16
16
|
tree.children.unshift(detailsElement);
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
|
-
const visitorCallback = (node,
|
|
19
|
+
const visitorCallback = (node, rootUlElement) => {
|
|
20
20
|
if (!/^h[2-6]$/.test(node.tagName)) return;
|
|
21
21
|
const headingLevel = getHeadingLevelFromElement(node);
|
|
22
22
|
const liElement = createListItemElement(node);
|
|
23
|
-
const
|
|
23
|
+
const rootUlElementChildren = assertElementNodeList(rootUlElement.children);
|
|
24
24
|
if (headingLevel === 2) {
|
|
25
|
-
|
|
25
|
+
rootUlElement.children.push(liElement);
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
sameLevelOlElement.children.push(liElement);
|
|
28
|
+
const sameLevelUlElement = searchSameLevelUlElement(rootUlElementChildren, headingLevel);
|
|
29
|
+
if (sameLevelUlElement) {
|
|
30
|
+
sameLevelUlElement.children.push(liElement);
|
|
32
31
|
return;
|
|
33
32
|
}
|
|
34
|
-
const deepestLiElement = getDeepestLiElement(
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
deepestLiElement.children.push(
|
|
33
|
+
const deepestLiElement = getDeepestLiElement(rootUlElementChildren);
|
|
34
|
+
const newUlElement = createUlElement();
|
|
35
|
+
newUlElement.children.push(liElement);
|
|
36
|
+
deepestLiElement.children.push(newUlElement);
|
|
38
37
|
};
|
|
39
38
|
/**
|
|
40
39
|
* 引数のolに入っている一番新しいliの中で、levelと同じ見出しレベルのli要素を返す
|
|
41
40
|
*/
|
|
42
|
-
const
|
|
43
|
-
const rootLiElement = assertElementNode(
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
const searchSameLevelUlElement = (rootUlElement, level) => {
|
|
42
|
+
const rootLiElement = assertElementNode(rootUlElement[rootUlElement.length - 1]);
|
|
43
|
+
const headingAnchorElement = assertElementNode(rootLiElement.children[0]);
|
|
44
|
+
const headingTextElement = assertElementText(headingAnchorElement.children[0]);
|
|
45
|
+
const rootElementHeadingLevel = getHeadingLevelFromText(headingTextElement);
|
|
46
|
+
if (rootElementHeadingLevel === level) return rootLiElement;
|
|
47
|
+
const childUlElement = assertElementNodeList(rootLiElement.children)[1];
|
|
48
|
+
if (childUlElement === void 0) return;
|
|
49
|
+
return searchSameLevelUlElement(assertElementNodeList(childUlElement.children), level);
|
|
48
50
|
};
|
|
49
51
|
/**
|
|
50
52
|
* 引数のolに入っている一番新しいliの中で、一番深いli要素を取得する
|
|
51
53
|
*/
|
|
52
|
-
const getDeepestLiElement = (
|
|
53
|
-
const rootLiElement = assertElementNode(
|
|
54
|
+
const getDeepestLiElement = (rootUlElement) => {
|
|
55
|
+
const rootLiElement = assertElementNode(rootUlElement[rootUlElement.length - 1]);
|
|
54
56
|
const olElement = assertElementNodeList(rootLiElement.children)[1];
|
|
55
57
|
if (!olElement) return rootLiElement;
|
|
56
58
|
return getDeepestLiElement(assertElementNodeList(olElement.children));
|
|
@@ -59,7 +61,11 @@ const getHeadingLevelFromElement = (headingElement) => {
|
|
|
59
61
|
const headingLevel = Number(headingElement.tagName.charAt(1));
|
|
60
62
|
return headingLevel;
|
|
61
63
|
};
|
|
62
|
-
const
|
|
64
|
+
const getHeadingLevelFromText = (headingElement) => {
|
|
65
|
+
const headingLevel = Number(headingElement.value.charAt(1));
|
|
66
|
+
return headingLevel;
|
|
67
|
+
};
|
|
68
|
+
const createUlElement = () => {
|
|
63
69
|
return {
|
|
64
70
|
type: "element",
|
|
65
71
|
tagName: "ol",
|
|
@@ -88,7 +94,7 @@ const createListItemElement = (node) => {
|
|
|
88
94
|
children: [anchorElement]
|
|
89
95
|
};
|
|
90
96
|
};
|
|
91
|
-
const createCollapsibleToc = (
|
|
97
|
+
const createCollapsibleToc = (rootUlElement) => {
|
|
92
98
|
const summaryElement = {
|
|
93
99
|
type: "element",
|
|
94
100
|
tagName: "summary",
|
|
@@ -102,7 +108,7 @@ const createCollapsibleToc = (rootOlElement) => {
|
|
|
102
108
|
type: "element",
|
|
103
109
|
tagName: "details",
|
|
104
110
|
properties: {},
|
|
105
|
-
children: [summaryElement,
|
|
111
|
+
children: [summaryElement, rootUlElement]
|
|
106
112
|
};
|
|
107
113
|
return detailsElement;
|
|
108
114
|
};
|
|
@@ -114,6 +120,10 @@ const assertElementNodeList = (nodeList) => {
|
|
|
114
120
|
if (nodeList.some((node) => node.type !== "element")) throw new Error("Elementノードではありません");
|
|
115
121
|
return nodeList;
|
|
116
122
|
};
|
|
123
|
+
const assertElementText = (node) => {
|
|
124
|
+
if (node.type !== "text") throw new Error("Textノードではありません");
|
|
125
|
+
return node;
|
|
126
|
+
};
|
|
117
127
|
|
|
118
128
|
//#endregion
|
|
119
129
|
export { rehypeCollapsibleToc };
|