feat: add online FAQ/KB sync without old bridge

This commit is contained in:
wangliang
2026-10-23 11:29:43 +08:00
parent f526696f93
commit 81b49c9350
24 changed files with 1793 additions and 5 deletions
+72
View File
@@ -0,0 +1,72 @@
'use strict';
const fs = require('fs');
function escapeRe(value) {
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function normalizeQuestion(value) {
return String(value || '').toLowerCase().replace(/[^\p{L}\p{N}]+/gu, ' ').trim();
}
// 用官网 FAQ 更新本地 markdown:保留 frontmatter、章节标题和 Q 顺序,
// 只替换已有问题的答案,新问题追加到文件末尾。
function updateMarkdownFile(filePath, questions) {
if (!fs.existsSync(filePath)) return { changed: false, reason: 'file_missing', added: 0, updated: 0 };
let content = fs.readFileSync(filePath, 'utf8');
const bodyStart = (content.match(/^---\n[\s\S]*?\n---\n/) || [''])[0].length;
const body = content.slice(bodyStart);
const existing = new Map();
let currentQ = null;
let answer = [];
const flush = () => {
if (currentQ) existing.set(normalizeQuestion(currentQ), { question: currentQ, answer: answer.join('\n').trim() });
};
for (const line of body.split('\n')) {
const q = line.match(/^###\s+Q:\s*(.*)$/);
if (q) {
flush();
currentQ = q[1].trim();
answer = [];
} else if (currentQ) {
answer.push(line);
}
}
flush();
let changed = false;
let added = 0;
let updated = 0;
const additions = [];
for (const item of questions) {
if (!item.q || !item.a) continue;
const key = normalizeQuestion(item.q);
if (existing.has(key)) {
const prev = existing.get(key);
if (prev.answer !== item.a) {
const re = new RegExp(`(### Q: ${escapeRe(prev.question)}\\n)([\\s\\S]*?)(?=\\n### Q:|$)`, 'm');
if (re.test(content)) {
content = content.replace(re, (_m, prefix) => `${prefix}${item.a}\n`);
prev.answer = item.a;
changed = true;
updated += 1;
}
}
} else {
existing.set(key, { question: item.q, answer: item.a });
additions.push(`### Q: ${item.q}\n${item.a}\n`);
added += 1;
changed = true;
}
}
if (additions.length) {
content = content.replace(/\s+$/, '') + '\n\n' + additions.join('\n');
}
if (changed) fs.writeFileSync(filePath, content, 'utf8');
return { changed, added, updated };
}
module.exports = { updateMarkdownFile };