forked from semlinker/reactjs-interview-questions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTableContentsBuilder.js
77 lines (68 loc) · 2.33 KB
/
TableContentsBuilder.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
const fs = require("fs");
const path = require("path");
const util = require('util');
const os = require('os');
const MD_FILE_PATH = path.join(__dirname, "README.md");
const TITLE_RE = /^(\d+\.\s*#{3}|#{2})\s*([^#\r\n]+)\r?\n?$/gm;
const TABLE_CONTENT_RE = /(<!--\s*TOC\s*-->)([\s\S]+)(<!--\s*\/TOC\s*-->)/g;
const readFile = util.promisify(fs.readFile);
const writeFile = util.promisify(fs.writeFile);
const contentTemplate = contents => `
| 序号. | 问题 |
| --- | --------- |
${contents.map(content =>`|${!content.root ? content.index : ""} | [${content.title}](#${content.anchor}) |`).join(os.EOL)}
`;
class TableContentsBuilder {
async buildTableContents(filePath) {
let contents = await this.loadContents(filePath);
if (!contents) return;
let contentTitles = this.parse(contents);
let tableContents = contentTemplate(contentTitles);
let updatedContents = contents.replace(TABLE_CONTENT_RE, (match, p1, p2, p3) => {
return p1 + tableContents + p3;
});
await this.saveContents(filePath, updatedContents);
}
async loadContents(filePath) {
if (!filePath) throw `${filePath} is invalid!`;
let content;
try {
if (fs.existsSync(filePath)) {
content = await readFile(filePath, {
encoding: "utf-8"
});
}
} catch (err) {
console.dir(err);
}
return content;
}
parse(contents) {
let contentTitles = [],
index = 1;
while (TITLE_RE.exec(contents) !== null) {
contentTitles.push({
root: RegExp.$1 === "##",
index: RegExp.$1 != "##" ? index++ : 0,
title: RegExp.$2,
anchor: RegExp.$2.replace(/\s+/g, '-').replace(/[\*`<>?()\\,?()]*\s*/g, '').toLowerCase()
});
}
return contentTitles;
}
async saveContents(filePath, contents) {
try {
await writeFile(filePath, contents, {
encoding: "utf-8"
});
} catch (err) {
console.error(err);
}
}
}
async function main() {
await new TableContentsBuilder().buildTableContents(MD_FILE_PATH);
}
main().then(() => {
console.log('Build Table Contents Success')
}).catch((err) => console.error)