-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
144 lines (135 loc) · 5.12 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* markdown-it-toc-better
*
* @param {Object} md - markdownit Object(库传入对象) required
* @param {Object} options - config object(配置对象) required
* @param {Array} options.includeLevel - Set directory level(设定目录级别)
* @param {Function} options.slugify - Function used to custom directory anchor href rule(自定义目录锚点href规则函数)
* @param {Function} options.getTocTree - Function used to acquire directory tree object,the function argument is a directory tree object(用于获取目录树对象的函数,函数入参为目录树对象)
* @param {Function} options.getTocHTML - Function used to acquire directory DOM,the function argument is a DOM(用于获取目录DOM的函数,函数入参为DOM对象)
*/
export default function(md,options) {
// Add anchor when generating the title
// 生成标题时加入锚点
md.renderer.rules.heading_open = function(tokens, index) {
let slugify = typeof options.slugify === "function" ? options.slugify : function (s) { return s; };
let level = tokens[index].tag;
let label = tokens[index + 1];
let link = slugify(label.content)
if (label.type === 'inline') {
return `<${level}><a id="#${link}"></a>`;
} else {
return '</h1>';
}
};
// Get the title node
// 获取标题节点
function findHeadings(tokens, option) {
let _a, _b, _c;
let headings = [];
let size = tokens.length;
let slugify = typeof option.slugify === "function" ? option.slugify : function (s) { return s; };
let includeLevel = option.includeLevel || [1, 2, 3, 4];
let index = 0;
while (index < size) {
let token = tokens[index];
let level = (_c = +((_b = (_a = token === null || token === void 0 ? void 0 : token.tag) === null || _a === void 0 ? void 0 : _a.substr) === null || _b === void 0 ? void 0 : _b.call(_a, 1, 1))) !== null && _c !== void 0 ? _c : -1;
if (token.type === "heading_open" && includeLevel.indexOf(level) !== -1) {
let content = tokens[index + 1].content;
let h = {
level: level,
content: content,
parent: null,
children: [],
link: "#" + slugify(content),
};
headings.push(h);
index += 3;
}
else {
index++;
}
}
return headings;
}
// Generate node tree
// 生成节点树
function flat2Tree(headings) {
let current = null;
let root = [];
for (let i = 0; i < headings.length; i++) {
let h = headings[i];
if (h.level === 1) {
root.push(h);
current = null;
}
if (current === null) {
current = h;
}
else {
while (h.level !== current.level + 1) {
if (h.level > current.level && current.children.length !== 0) {
current = current.children[current.children.length - 1];
}
else if (h.level <= current.level && current.parent !== null) {
current = current.parent;
}
else {
break;
}
}
if (h.level === current.level + 1) {
h.parent = current;
current.children.push(h);
current = h;
}
}
}
return root;
}
// Remove redundant branches
// 去除冗余分支
function removeUselessProperties(hsd) {
for (let i = 0; i < hsd.length; i++) {
delete hsd[i].parent;
removeUselessProperties(hsd[i].children);
}
}
// Generate directory elements
// 生成目录元素
function renderToc(tree) {
let TocContainer = document.createElement('ul')
let levelInner = 0
let tocHTML = tree.reduce((pre,cur) => {
let headerContainer = document.createElement('li')
let link = document.createElement('a')
link.href = cur.link
link.className = `leave_${cur.level} idx_${levelInner}`
levelInner ++
link.innerText = cur.content
headerContainer.append(link)
if(cur.children.length > 0){
let childrenDOM = cur.children
headerContainer.append(renderToc(childrenDOM))
pre.append(headerContainer)
}else{
pre.append(headerContainer)
}
return TocContainer
},TocContainer)
return tocHTML
}
// Generate and return the title node tree
// 生成并返回标题节点树
md.core.ruler.push("toc_desc", function (state) {
const o = options
let _a,_c;
let _b = (o === null || o === void 0) ? void 0 : (typeof o.render === 'function' ? void 0 : o.render);
let headings = findHeadings(state.tokens, o);
let tree = flat2Tree(headings);
removeUselessProperties(tree);
(_a = o === null || o === void 0 ? void 0 : (typeof o.getTocTree === 'function' ? o.getTocTree : void 0)) === null || _a === void 0 ? void 0 : _a.call(o, tree);
(_c = (o === null || o === void 0) ? void 0 : (typeof o.getTocHTML === 'function' ? o.getTocHTML : void 0)) === null || _c === void 0 ? void 0 : _b === void 0 ? _c.call(o, renderToc(tree)) :_c.call(o, _b.call(o,tree));
return true;
});
}