-
Notifications
You must be signed in to change notification settings - Fork 1
/
convert.js
148 lines (130 loc) · 3.9 KB
/
convert.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
145
146
147
148
const fs = require('fs');
const readline = require('readline');
const path = require('path');
const iconvLite = require('iconv-lite');
/**
* 获取配置项
*/
function readConfig() {
const configs = require('./config');
return configs;
}
/**
* 转换编码为 utf-8
* @param {Object} configs 配置项
*/
function decodeFile(configs) {
const { sourceRequest, sourceEncodeType, title } = configs;
const filePath = path.join(__dirname, sourceRequest);
let tempData = fs.readFileSync(filePath);
tempData = iconvLite.decode(tempData, sourceEncodeType);
fs.writeFileSync(`${title}temp.txt`, tempData);
}
/**
* 读取源文件并进行处理
* @param {Object} configs 配置项
* @param {Function} callback 文件读取结束回调
*/
function txtParse(configs, callback) {
const { title, chapterReg } = configs;
const chapterRegObj = new RegExp(chapterReg);
const tempFilePath = path.join(__dirname, `${title}temp.txt`);
const input = fs.createReadStream(tempFilePath);
const chapterList = [];
const contentList = [];
const readLine = readline.createInterface({ input });
console.log('=================== 开始文件读取 ==================');
let chapterContent = [];
readLine.on('line', (line) => {
if (chapterRegObj.test(line)) {
chapterList.push(line);
if (chapterList.length > 1 && chapterContent.length) {
contentList.push(chapterContent);
}
chapterContent = [];
} else if (!line.trim()) {
// pass
} else {
chapterContent.push(line);
}
});
readLine.on('close', () => {
chapterContent.length && contentList.push(chapterContent);
console.log('=================== 文件读取结束 ==================');
console.log(`识别章节数 ------> ${chapterList.length}`);
callback(configs, chapterList, contentList);
});
}
/**
* 转换为 HTML 并输出
* @param {Object} configs 配置项
* @param {Array} chapterList 章节列表
* @param {Array} contentList 内容列表
*/
function txt2html(configs, chapterList, contentList) {
console.log('=================== 开始生成 HTML 文件 ==================');
const { title, target } = configs;
// 获取样式文件
const styleFilePath = path.join(__dirname, './style.css');
const style = fs.readFileSync(styleFilePath);
let html = `
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh" xml:lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>${title}</title>
<style type="text/css">
${style}
</style>
</head>
<body>
`;
for (let i = 0; i < chapterList.length; i++) {
html += `<h2>${chapterList[i].trim()}</h2>`
contentList[i].forEach(item => {
html += `<p>${item}</p>`;
});
html += '<div class="pagebreak"></div>';
}
html += `
</body>
</html>
`;
const outputFilePath = path.join(__dirname, './kindleBooks', target);
fs.writeFileSync(outputFilePath, html);
console.log('=================== HTML 文件生成结束 ==================');
}
/**
* 清理临时文件
* @param {Object} configs 配置项
*/
function clearTemp(configs) {
const file = `${configs.title}temp.txt`;
// 检查当前目录中是否存在该文件
fs.access(file, fs.constants.F_OK, (err) => {
if (!err) { // 存在
// 删除该文件
fs.unlinkSync(file);
}
});
}
/**
* 主函数
*/
function run() {
console.log('=================== 开始转换 ==================');
if (!fs.existsSync('kindleBooks')) {
fs.mkdirSync('kindleBooks');
}
// 获取配置项
const configs = readConfig();
// 输出临时文件,编码为 utf-8
decodeFile(configs);
// 转换
txtParse(configs, txt2html);
// 清理不必要的临时资源
clearTemp(configs);
console.log('=================== 转换结束 ==================');
}
// 开始执行
run();