diff --git a/client/src/utils/articlePptSlides.ts b/client/src/utils/articlePptSlides.ts index 4026aca..aa2c93c 100644 --- a/client/src/utils/articlePptSlides.ts +++ b/client/src/utils/articlePptSlides.ts @@ -47,6 +47,16 @@ export type PptSlide = PptTitleSlide | PptSectionSlide const PPT_SLIDE_BOTTOM = 5.1 const SECTION_HEADER_HEIGHT = 0.85 const IMAGE_PLACEHOLDER_GLOBAL_RE = /\[图片(?::[^\]]*)?\]/g +const IMAGE_FILENAME_SUFFIX_RE = + /\s+[\w\u4e00-\u9fa5.-]+\.(jpg|jpeg|png|gif|webp|svg|bmp)\s*$/i + +function stripTrailingImageFilenames(text: string): string { + let result = text + while (IMAGE_FILENAME_SUFFIX_RE.test(result)) { + result = result.replace(IMAGE_FILENAME_SUFFIX_RE, '') + } + return result +} let markdownParser: MarkdownIt | null = null @@ -82,9 +92,11 @@ function renderInlineText(inlineToken: Token): string { return renderTokenChildren(inlineToken.children) } -/** 移除 inline 渲染产生的 [图片: ...] 占位片段 */ +/** 移除 inline 渲染产生的 [图片: ...] 占位片段与段尾图片文件名 */ export function stripImagePlaceholders(text: string): string { - return text.replace(IMAGE_PLACEHOLDER_GLOBAL_RE, '').replace(/\s+/g, ' ').trim() + let result = text.replace(IMAGE_PLACEHOLDER_GLOBAL_RE, '') + result = stripTrailingImageFilenames(result) + return result.replace(/\s+/g, ' ').trim() } function getImgSrc(el: Element): string { @@ -454,7 +466,9 @@ export function dedupeImageCaptionBlocks(blocks: ContentBlock[]): ContentBlock[] const prev = result[result.length - 1] if (block.type === 'paragraph') { - const text = block.text.trim() + const text = stripImagePlaceholders(block.text) + if (!text) continue + const next = blocks[i + 1] if (prev?.type === 'image' && isImageCaptionLike(text, prev)) { @@ -463,12 +477,15 @@ export function dedupeImageCaptionBlocks(blocks: ContentBlock[]): ContentBlock[] if (next?.type === 'image' && isImageCaptionLike(text, next)) { continue } - result.push(block) + result.push(text === block.text ? block : { ...block, text }) continue } - if (block.type === 'list' && prev?.type === 'image') { - const items = block.items.filter((item) => !isImageCaptionLike(item, prev)) + if (block.type === 'list') { + const items = block.items + .map((item) => stripImagePlaceholders(item)) + .filter(Boolean) + .filter((item) => !(prev?.type === 'image' && isImageCaptionLike(item, prev))) if (items.length) { result.push({ ...block, items }) }