import crypto from 'node:crypto'; import fs from 'node:fs'; import path from 'node:path'; import { preparePublishedPlatformBrand } from './mindspace-page-tag.mjs'; const INLINE_SCRIPT_PATTERN = /]*\bsrc\b)[^>]*>([\s\S]*?)<\/script>/gi; export function collectInlineScriptHashes(html) { const hashes = []; const seen = new Set(); for (const match of String(html ?? '').matchAll(INLINE_SCRIPT_PATTERN)) { const hash = crypto.createHash('sha256').update(match[1] ?? '').digest('base64'); if (seen.has(hash)) continue; seen.add(hash); hashes.push(hash); } return hashes; } export async function handleMindSpaceLongImageDownload({ query, filePath, pageUrl = null, res, isLongImageDownloadRequest, longImagePathForHtml, renderLongImage, } = {}) { if (!isLongImageDownloadRequest?.(query)) return false; const longImagePath = longImagePathForHtml(filePath); try { await renderLongImage(pageUrl ? { url: pageUrl, outputPath: longImagePath } : { htmlPath: filePath, outputPath: longImagePath }); res.set('Cache-Control', 'no-store'); res.download(longImagePath, path.basename(longImagePath), (err) => { if (err && !res.headersSent) res.status(404).json({ message: '长图文件不存在' }); }); } catch (error) { res .status(500) .type('text/plain; charset=utf-8') .send(`长图生成失败:${error?.message || '未知错误'}`); } return true; } export function decorateMindSpacePublishedHtml({ html, embed = false, context, htmlFilePath = '', fileExists = fs.existsSync, userAgent = '', preparePublicationHtmlForEmbed, injectOgTags, injectWechatShareBridge, injectPublicFileShareButton, publishedPageCsp, isWechatUserAgent, } = {}) { let nextHtml = html; let allowEmbedFrame = false; if (embed) { nextHtml = preparePublicationHtmlForEmbed(nextHtml); allowEmbedFrame = true; } try { nextHtml = preparePublishedPlatformBrand(nextHtml); nextHtml = injectOgTags(nextHtml, { origin: context.origin, pageUrl: context.pageUrl, pageDirUrl: context.pageDirUrl, fallbackImageUrl: context.fallbackImageUrl, htmlFilePath, fileExists, }); const wechatShare = !embed && isWechatUserAgent(userAgent || ''); if (wechatShare) { nextHtml = injectWechatShareBridge(nextHtml, { pageUrl: context.pageUrl }); } const shareInjection = !embed ? injectPublicFileShareButton(nextHtml) : { html: nextHtml, scriptHashes: [] }; nextHtml = shareInjection.html; const scriptHashes = collectInlineScriptHashes(nextHtml); return { html: nextHtml, csp: publishedPageCsp(nextHtml, { embed, wechatShare, scriptHashes, }), allowEmbedFrame, }; } catch { return { html: nextHtml, csp: publishedPageCsp(nextHtml, { embed }), allowEmbedFrame, }; } }