]*>([\s\S]*?)<\/strong>/gi, '$1')
.replace(/]*>([\s\S]*?)<\/b>/gi, '$1')
.replace(/<[^>]+>/g, '')
.replace(/\n{3,}/g, '\n\n')
.trim();
}
function stripLegacyReadOriginalFooter(content) {
return String(content ?? '')
.replace(/]*>\s*阅读原文[::][\s\S]*?<\/p>/gi, '')
.trim();
}
export function isNewsHotspotFormat(html) {
const source = String(html ?? '');
if (isDailyNewsFormat(source)) return false;
if (/news-hotspot|今日新闻热点/u.test(source)) return true;
if (!/class="card"/.test(source)) return false;
return /
]*>/.test(source)
&& (/',
`
`,
'',
].join('');
}
function resolveSidecarThumbnailPaths(publishDir, htmlRelativePath) {
if (!publishDir || !htmlRelativePath) return [];
const htmlPath = path.join(publishDir, htmlRelativePath);
const pngPath = htmlPath.replace(/\.html$/i, '.thumbnail.png');
const svgPath = htmlPath.replace(/\.html$/i, '.thumbnail.svg');
if (fs.existsSync(pngPath)) return [pngPath];
if (fs.existsSync(svgPath)) return [svgPath];
return [];
}
function collectPageImageCandidatesFromHtml(html, { publishDir = '', htmlRelativePath = '' } = {}) {
const source = String(html ?? '');
const refs = [];
const coverPath = extractMindspaceCoverPath(source);
if (coverPath) refs.push(coverPath);
for (const match of source.matchAll(/background-image:\s*url\(["']?([^"')]+)["']?\)/gi)) {
refs.push(match[1]);
}
for (const match of source.matchAll(/
]+src=["']([^"']+)["']/gi)) {
refs.push(match[1]);
}
const seen = new Set();
const resolved = [];
for (const ref of refs) {
const normalized = normalizeImageRef(ref);
if (!normalized || seen.has(normalized)) continue;
seen.add(normalized);
resolved.push({
ref: normalized,
absPath: resolveImageFilePath(normalized, publishDir, htmlRelativePath),
});
}
return resolved;
}
export function collectPageImageCandidates(html, { publishDir = '', htmlRelativePath = '' } = {}) {
const resolved = collectPageImageCandidatesFromHtml(html, { publishDir, htmlRelativePath });
if (
htmlRelativePath
&& publishDir
&& !resolveHeroImagePath(html, { publishDir, htmlRelativePath })
) {
const seen = new Set(resolved.map((item) => item.ref));
for (const sidecarPath of resolveSidecarThumbnailPaths(publishDir, htmlRelativePath)) {
const ref = path.basename(sidecarPath);
if (seen.has(ref)) continue;
seen.add(ref);
resolved.push({ ref, absPath: sidecarPath });
}
}
return resolved;
}
function countBodyImages(html) {
return collectPageImageCandidates(html).length;
}
function extractBodyHtml(source) {
const match = String(source ?? '').match(/]*>([\s\S]*?)<\/body>/i);
return match ? match[1] : String(source ?? '');
}
function stripMindspaceDeliveryChrome(source) {
let body = extractBodyHtml(source);
body = body.replace(/