diff --git a/lib/notion/getPostBlocks.js b/lib/notion/getPostBlocks.js index 6badce53a17..1d920e92f0f 100644 --- a/lib/notion/getPostBlocks.js +++ b/lib/notion/getPostBlocks.js @@ -109,6 +109,9 @@ function convertNotionBlocksToPost(id, blockMap, slice) { count++ + // === 【新增】强制修复非法 URL === + sanitizeBlockUrls(b?.value) + if (b?.value?.type === 'sync_block' && b?.value?.children) { const childBlocks = b.value.children // 移除同步块 @@ -190,3 +193,57 @@ export const fetchInBatches = async (ids, batchSize = 100) => { } return fetchedBlocks } + + +/** + * 强制修复 block 中所有可能的非法 URL 字段 + * @param {Object} blockValue - block.value + */ +function sanitizeBlockUrls(blockValue) { + if (!blockValue || typeof blockValue !== 'object') return + + const fixUrl = (url) => { + if (typeof url !== 'string') return url + + if (url.startsWith('/')) { + return url + } + + // 修复 http:xxx → http://xxx + if (url.startsWith('http:') && !url.startsWith('http://')) { + url = 'http://' + url.slice(5) + } else if (url.startsWith('https:') && !url.startsWith('https://')) { + url = 'https://' + url.slice(6) + } + + // 再次验证是否合法,否则替换为占位图 + try { + new URL(url) + return url + } catch { + console.warn('[Sanitize URL] Invalid URL replaced:', url) + return 'https://via.placeholder.com/1x1?text=Invalid+Image' + } + } + + // 1. 处理 properties.source(用于 image, embed, bookmark, file, pdf 等) + if ( + blockValue.properties?.source?.[0]?.[0] && + typeof blockValue.properties.source[0][0] === 'string' + ) { + blockValue.properties.source[0][0] = fixUrl(blockValue.properties.source[0][0]) + } + + // 2. 处理 file.url(用于 file block) + if (blockValue.file?.url && typeof blockValue.file.url === 'string') { + blockValue.file.url = fixUrl(blockValue.file.url) + } + + // 3. 处理 format.page_cover(页面封面) + if (blockValue.format?.page_cover && typeof blockValue.format.page_cover === 'string') { + blockValue.format.page_cover = fixUrl(blockValue.format.page_cover) + } + + // 4. 处理其他可能的 URL 字段(可选扩展) + // 例如:video、audio 的 source 可能也走 properties.source,已覆盖 +} \ No newline at end of file