Files
tougao_web/src/utils/stripHeadingNumber.js
2026-07-06 09:11:20 +08:00

82 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 标题行首序号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(/&nbsp;/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;
}