fix: truncate article titles to safe UTF-8 budget

This commit is contained in:
Longtail committed 2026-10-31 18:38:41 +08:00
1 parent 24a73b19c0
commit 7ab0bc3485
7 files changed
+115 -15

No files matched your search

+22 -3
View File
@@ -153,12 +153,31 @@
return output.join('\n').trim();
}
function shortTitle(title, budget = 75) {
const size = ch => {
const code = ch.codePointAt(0);
return code <= 0x7f ? 1 : code <= 0x7ff ? 2 : code <= 0xffff ? 3 : 4;
};
// A generated prefix plus "..." (up to 78 bytes) is already safe.
const total = Array.from(title).reduce((sum, ch) => sum + size(ch), 0);
if (total <= budget || (title.endsWith('...') && total <= budget + 3)) return title;
let prefix = '', used = 0;
for (const ch of title) {
const bytes = size(ch);
if (used + bytes > budget) break;
prefix += ch;
used += bytes;
}
return prefix + '...';
}
function compile(markdown, mdPath, fileMap, titleOverride) {
let body = String(markdown).replace(/^\uFEFF/, '').replace(/\r\n?/g, '\n');
const firstHeading = body.match(/^\s*#\s+([^\n]+)\n?/);
const title = String(titleOverride || firstHeading?.[1] || mdPath.split('/').pop().replace(/\.md$/i, '')).trim();
const originalTitle = String(titleOverride || firstHeading?.[1] || mdPath.split('/').pop().replace(/\.md$/i, '')).trim();
const title = shortTitle(originalTitle);
if (firstHeading) body = body.slice(firstHeading[0].length).trim();
if (!title || Array.from(title).length > 80) throw new Error('标题为空或超过 80 字,请修改 Markdown 标题后重试。');
if (!title) throw new Error('标题为空,请修改 Markdown 标题后重试。');
if (!body.trim()) throw new Error('正文为空。');
const warnings = [];
if (/<\/?[a-z][^>]*>/i.test(body)) warnings.push('存在 HTML,将作为文字保留;请检查排版。');
@@ -531,7 +550,7 @@
$('diagnostics').onclick = () => downloadJSON({ ...summary(), logs }, 'dww11-import-diagnostics.json');
win.addEventListener('pagehide', releasePreviews, { once: true });
}
return { VERSION, normalizePath, imagePath, readLink, markdownToBBCode, compile, prepareFiles, preparePackage, parseAid, attachmentId, verifyEditorImages, mount };
return { VERSION, shortTitle, normalizePath, imagePath, readLink, markdownToBBCode, compile, prepareFiles, preparePackage, parseAid, attachmentId, verifyEditorImages, mount };
});
// Extracted from dww11-wechat-oneclick.user.js v1.0.9; package source is authoritative.
+22 -3
View File
@@ -153,12 +153,31 @@
return output.join('\n').trim();
}
function shortTitle(title, budget = 75) {
const size = ch => {
const code = ch.codePointAt(0);
return code <= 0x7f ? 1 : code <= 0x7ff ? 2 : code <= 0xffff ? 3 : 4;
};
// A generated prefix plus "..." (up to 78 bytes) is already safe.
const total = Array.from(title).reduce((sum, ch) => sum + size(ch), 0);
if (total <= budget || (title.endsWith('...') && total <= budget + 3)) return title;
let prefix = '', used = 0;
for (const ch of title) {
const bytes = size(ch);
if (used + bytes > budget) break;
prefix += ch;
used += bytes;
}
return prefix + '...';
}
function compile(markdown, mdPath, fileMap, titleOverride) {
let body = String(markdown).replace(/^\uFEFF/, '').replace(/\r\n?/g, '\n');
const firstHeading = body.match(/^\s*#\s+([^\n]+)\n?/);
const title = String(titleOverride || firstHeading?.[1] || mdPath.split('/').pop().replace(/\.md$/i, '')).trim();
const originalTitle = String(titleOverride || firstHeading?.[1] || mdPath.split('/').pop().replace(/\.md$/i, '')).trim();
const title = shortTitle(originalTitle);
if (firstHeading) body = body.slice(firstHeading[0].length).trim();
if (!title || Array.from(title).length > 80) throw new Error('标题为空或超过 80 字,请修改 Markdown 标题后重试。');
if (!title) throw new Error('标题为空,请修改 Markdown 标题后重试。');
if (!body.trim()) throw new Error('正文为空。');
const warnings = [];
if (/<\/?[a-z][^>]*>/i.test(body)) warnings.push('存在 HTML,将作为文字保留;请检查排版。');
@@ -531,5 +550,5 @@
$('diagnostics').onclick = () => downloadJSON({ ...summary(), logs }, 'dww11-import-diagnostics.json');
win.addEventListener('pagehide', releasePreviews, { once: true });
}
return { VERSION, normalizePath, imagePath, readLink, markdownToBBCode, compile, prepareFiles, preparePackage, parseAid, attachmentId, verifyEditorImages, mount };
return { VERSION, shortTitle, normalizePath, imagePath, readLink, markdownToBBCode, compile, prepareFiles, preparePackage, parseAid, attachmentId, verifyEditorImages, mount };
});