'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 };