181 lines
3.9 KiB
JavaScript
Executable File
181 lines
3.9 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
||
|
||
'use strict';
|
||
|
||
|
||
|
||
const fs = require('fs');
|
||
|
||
const path = require('path');
|
||
|
||
|
||
|
||
function parseArgs(argv) {
|
||
|
||
const args = { input: '', out: '', stdout: false, append: false, requireChineseName: false, json: false, markdown: false };
|
||
|
||
for (let i = 2; i < argv.length; i++) {
|
||
|
||
const a = argv[i];
|
||
|
||
if (a === '--input' || a === '-i') args.input = argv[++i] || '';
|
||
|
||
else if (a === '--out' || a === '-o') args.out = argv[++i] || '';
|
||
|
||
else if (a === '--stdout') args.stdout = true;
|
||
|
||
else if (a === '--append') args.append = true;
|
||
|
||
else if (a === '--require-chinese-name') args.requireChineseName = true;
|
||
|
||
else if (a === '--json') args.json = true;
|
||
|
||
else if (a === '--markdown') args.markdown = true;
|
||
|
||
else if (a === '--help' || a === '-h') args.help = true;
|
||
|
||
else throw new Error(`未知参数:${a}`);
|
||
|
||
}
|
||
|
||
return args;
|
||
|
||
}
|
||
|
||
|
||
|
||
function usage() {
|
||
|
||
return `用法:
|
||
|
||
node scripts/write_markdown_utf8.js --input 草稿.md --out 最终项目总结.md --require-chinese-name --markdown
|
||
|
||
node scripts/write_markdown_utf8.js --out 阶段报告.md --require-chinese-name --markdown < 草稿.md
|
||
|
||
|
||
|
||
说明:使用 UTF-8 写入 Markdown,避免 Windows PowerShell / cmd 默认编码导致中文变成问号。使用 --require-chinese-name 可强制输出 Markdown 文件名包含中文。`;
|
||
|
||
}
|
||
|
||
|
||
|
||
function readAllStdin() {
|
||
|
||
try { return fs.readFileSync(0, 'utf8'); } catch { return ''; }
|
||
|
||
}
|
||
|
||
|
||
|
||
function ensureParent(file) {
|
||
|
||
const dir = path.dirname(path.resolve(file));
|
||
|
||
fs.mkdirSync(dir, { recursive: true });
|
||
|
||
}
|
||
|
||
|
||
|
||
function hasChinese(text) {
|
||
|
||
return /[\u4e00-\u9fff]/.test(String(text || ''));
|
||
|
||
}
|
||
|
||
|
||
|
||
function hasReplacementQuestionMarks(text) {
|
||
|
||
const replacementRunPattern = new RegExp('\\?{3,}', 'g');
|
||
|
||
const runs = text.match(replacementRunPattern) || [];
|
||
|
||
const questionCharCount = runs.reduce((n, item) => n + item.length, 0);
|
||
|
||
const hasChinese = /[\u4e00-\u9fff]/.test(text);
|
||
|
||
return questionCharCount >= 8 && !hasChinese;
|
||
|
||
}
|
||
|
||
|
||
|
||
function main() {
|
||
|
||
const args = parseArgs(process.argv);
|
||
|
||
if (args.help || (!args.out && !args.stdout)) {
|
||
|
||
console.log(usage());
|
||
|
||
process.exit(args.help ? 0 : 1);
|
||
|
||
}
|
||
|
||
const input = (args.input ? fs.readFileSync(args.input, 'utf8') : readAllStdin()).replace(/^\uFEFF/, '');
|
||
|
||
if (!input) throw new Error('缺少要写入的 Markdown 内容');
|
||
|
||
if (hasReplacementQuestionMarks(input)) {
|
||
|
||
throw new Error('输入内容疑似已经发生中文编码损坏:检测到大量问号且没有中文字符;请从原始结论重新生成后再写入。');
|
||
|
||
}
|
||
|
||
if (args.stdout) process.stdout.write(input, 'utf8');
|
||
|
||
if (args.out) {
|
||
|
||
if (args.requireChineseName && !hasChinese(path.basename(args.out))) throw new Error(`输出 Markdown 文件名必须包含中文:${args.out}`);
|
||
|
||
ensureParent(args.out);
|
||
|
||
if (args.append) fs.appendFileSync(args.out, input, 'utf8');
|
||
|
||
else fs.writeFileSync(args.out, input, 'utf8');
|
||
|
||
}
|
||
|
||
const result = { out: args.out || '', bytes: Buffer.byteLength(input, 'utf8'), encoding: 'utf8', chineseFileName: args.out ? hasChinese(path.basename(args.out)) : true, ok: true };
|
||
|
||
if (args.json) console.log(JSON.stringify(result, null, 2));
|
||
|
||
if (args.markdown) {
|
||
|
||
console.log('# Markdown UTF-8 写入结果');
|
||
|
||
console.log('');
|
||
|
||
console.log(`- 输出文件:${result.out || 'stdout'}`);
|
||
|
||
console.log(`- 编码:${result.encoding}`);
|
||
|
||
console.log(`- 中文文件名:${result.chineseFileName ? '是' : '否'}`);
|
||
|
||
console.log(`- 字节数:${result.bytes}`);
|
||
|
||
console.log('- 状态:写入完成,中文应正常显示');
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
try {
|
||
|
||
main();
|
||
|
||
} catch (err) {
|
||
|
||
console.error(err.message || String(err));
|
||
|
||
console.error(usage());
|
||
|
||
process.exit(1);
|
||
|
||
}
|
||
|