/** * 标题行首序号:1 / 1.1 / 1.2.3 / 1. / 1) 等(不含 2024 这类四位年份) */ const HEADING_NUMBER_PREFIX_RE = /^\s*(?:(?:\d+\.)+\d+|\d{1,2}[\.\)::]|\d{1,2}(?=\s+[^\d]))[\.\)::]?\s+/; export function stripHeadingNumberPrefix(text) { return String(text || '').replace(HEADING_NUMBER_PREFIX_RE, ''); } export function hasHeadingNumberPrefix(text) { return HEADING_NUMBER_PREFIX_RE.test(String(text || '')); } function htmlToPlainText(html) { if (typeof document !== 'undefined') { const node = document.createElement('div'); node.innerHTML = String(html || ''); return (node.textContent || node.innerText || '').replace(/\u00a0/g, ' '); } return String(html || '') .replace(/<[^>]+>/g, '') .replace(/ /g, ' ') .replace(/\s+/g, ' ') .trim(); } export function headingHtmlHasNumberPrefix(html) { return hasHeadingNumberPrefix(htmlToPlainText(html)); } /** 去掉 HTML 标题内容中首个非空文本节点前的序号 */ export function stripHeadingNumberFromHtml(html) { if (typeof document === 'undefined') { const plain = htmlToPlainText(html); if (!hasHeadingNumberPrefix(plain)) { return html; } return String(html || '').replace(HEADING_NUMBER_PREFIX_RE, ''); } const div = document.createElement('div'); div.innerHTML = html || ''; const walker = document.createTreeWalker(div, NodeFilter.SHOW_TEXT, null); let node; while ((node = walker.nextNode())) { const raw = node.textContent || ''; if (!raw.trim()) { continue; } const stripped = stripHeadingNumberPrefix(raw); if (stripped !== raw) { node.textContent = stripped; } break; } return div.innerHTML; } /** 从正文列表中收集需去掉序号的 H1/H2 标题 */ export function collectHeadingNumberStripUpdates(contentList) { const list = contentList || []; const updates = []; list.forEach(function (item) { if (!item || (item.is_h1 != 1 && item.is_h2 != 1)) { return; } const original = item.content || ''; const next = stripHeadingNumberFromHtml(original); if (next !== original) { updates.push({ am_id: item.am_id, content: next, original: original }); } }); return updates; }