-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathprocessing.ts
More file actions
101 lines (90 loc) · 3.4 KB
/
processing.ts
File metadata and controls
101 lines (90 loc) · 3.4 KB
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
import { readLines } from 'https://deno.land/std@0.113.0/io/mod.ts';
import { groupBy, sortBy } from 'https://deno.land/std@0.113.0/collections/mod.ts';
interface Post {
word: string;
meaning: string;
correct: string;
wrong: string;
note: string;
category: string;
fileName: string;
}
const TABLE_HEAD = '|单词|翻译|正确发音|常见错误发音|备注|\n| ---- | ---- | ---- | ---- | ---- |\n';
const TABLE_ROW = (row: Post) => `| ${row.word} | ${row.meaning} | ${row.correct} | ${row.wrong} | ${row.note} |\n`;
const H3_TITLE = '### 单词\n';
const H4_TITLE = (index: number, name: string) => `#### ${String(index).padStart(2, '0')}.${name}\n\n`;
const README_ANNOTION_REGEX = (name: string) => `(<!--START-${name}-->\n)(.*)(<!--END-${name}-->\n)`;
const README_ANNOTION = (name: string, rep: string) => `\n<!--START-${name}-->\n${rep}\n<!--END-${name}-->\n`;
async function insertInToReadMe(path: string, replacement: string): Promise<void> {
const annotationName = 'word';
const reg = new RegExp(README_ANNOTION_REGEX(annotationName), 's');
await Deno.readTextFile(path)
.then((data) => {
if (reg.test(data)) {
return data.replace(reg, `$1${replacement}\n$3`);
}
return data + README_ANNOTION(annotationName, replacement);
})
.then((text) => Deno.writeTextFile(path, text));
}
function makeTableStr(groupData: Record<string, Post[]>): string {
let s = H3_TITLE;
let index = 1;
for (const key in groupData) {
let table = H4_TITLE(index++, key) + TABLE_HEAD;
table += flat(groupData[key], TABLE_ROW, (a, b) => b.fileName.localeCompare(a.fileName));
s += `\n${table}`;
}
return s;
}
async function parsePost(fileReader: Deno.File, fileName: string): Promise<Post> {
const obj: Record<string, string> = {};
for await (const line of readLines(fileReader)) {
if (line.startsWith('---')) {
continue;
}
const [key, value] = line.split(':').map((item) => item.trim());
obj[key] = value || '';
}
return {
word: obj.word,
meaning: obj.meaning,
correct: obj.correct,
wrong: obj.wrong,
note: obj.note,
category: obj.category,
fileName: fileName,
};
}
function flat<T>(array: T[], selector: (el: T) => string, compare?: (a: T, b: T) => number): string {
let s = '';
if (compare) {
array.sort(compare);
}
for (const t of array) {
s += selector(t);
}
return s;
}
async function run(): Promise<void> {
const arr: Post[] = [];
const allSync: Promise<void>[] = [];
for await (const dirEntry of Deno.readDir('_posts')) {
if (dirEntry.isFile) {
allSync.push(
Deno.open('_posts/' + dirEntry.name)
.then((fileReader) => parsePost(fileReader, dirEntry.name))
.then((item) => {
arr.push(item);
})
.catch((err) => console.error(err))
);
}
}
await Promise.all(allSync)
.then(() => sortBy(arr, (it) => it.fileName))
.then((sortedArr) => groupBy(sortedArr, (it: Post) => it.category))
.then((postByCategroy) => makeTableStr(postByCategroy))
.then((tableStr) => insertInToReadMe('README.md', tableStr));
}
run().catch((error) => console.log(error));