This repository has been archived by the owner on Feb 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gen.js
105 lines (86 loc) · 2.36 KB
/
gen.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
const fs = require("fs");
const pinyin = require("pinyin");
const RAW_FILE = "raw";
const HTML_TMPL = "index.tmpl.html";
const HTML_OUTPUT = "index.html";
const TMPL_MARK = "__CONTENT__";
const PART_DELIM = "---";
const LINES_PER_SECTION = 4;
const LINE_ENDING = "\n";
const REG_BREAK = /[。;]/;
const MAX_LINE_WIDTH = 16;
//=== helpers
// wrap
const wrap = (tag, inner) => `<${tag}>${inner}</${tag}>`;
const mapAndConcat = (arr, fn) => arr.map(fn).join("");
const addPinyin = (str) =>
wrap(
"ruby",
mapAndConcat(pinyin(str), (py, i) =>
[str[i], wrap("rp", "("), wrap("rt", py), wrap("rp", ")")].join("")
)
);
const withPinyin = (str) => str.replace(/[^,。;]+?(?=[,。;])/g, addPinyin);
const last = (arr) => arr[arr.length - 1];
// break str within max length
const br = (str, maxLen) => {
const breakIndice = [0];
let pi = last(breakIndice);
let tmp = str.search(REG_BREAK);
while (tmp >= 0) {
i = pi + tmp + 1;
const len = i - last(breakIndice);
if (len > maxLen) {
if (pi === last(breakIndice)) {
breakIndice.push(i);
} else {
breakIndice.push(pi);
}
}
pi = i;
tmp = str.substring(pi).search(REG_BREAK);
}
breakIndice.push(str.length);
return breakIndice
.slice(1, breakIndice.length)
.map((cur, i) => str.substring(breakIndice[i], cur));
};
const addBrAndPinyin = (str) =>
br(str, MAX_LINE_WIDTH).map(withPinyin).join("<br>");
//--- helpers end
const data = fs
.readFileSync(RAW_FILE, { encoding: "utf-8" })
.trim()
.split(PART_DELIM)
.map((part) =>
part
.trim()
.split(LINE_ENDING)
.reduce((prev, cur, i) => {
if (i % LINES_PER_SECTION === 0) {
prev.push({
title: cur,
lines: [],
});
} else {
prev[Math.floor(i / LINES_PER_SECTION)].lines.push(cur);
}
return prev;
}, [])
);
const content = mapAndConcat(data, (part) =>
wrap(
"article",
mapAndConcat(part, (chapter) =>
wrap(
"section",
wrap("h3", chapter.title) +
mapAndConcat(chapter.lines, (line) => wrap("p", addBrAndPinyin(line)))
)
)
)
);
const template = fs.readFileSync(HTML_TMPL, { encoding: "utf-8" });
const htmlContent = template.replace(TMPL_MARK, wrap("main", content));
fs.writeFileSync(HTML_OUTPUT, htmlContent);
console.log("done");