diff --git a/web/src/components/deer-flow/markdown.tsx b/web/src/components/deer-flow/markdown.tsx index e36319b..1e70474 100644 --- a/web/src/components/deer-flow/markdown.tsx +++ b/web/src/components/deer-flow/markdown.tsx @@ -13,6 +13,7 @@ import "katex/dist/katex.min.css"; import { Button } from "~/components/ui/button"; import { rehypeSplitWordsIntoSpans } from "~/core/rehype"; +import { autoFixMarkdown } from "~/core/utils/markdown"; import { cn } from "~/lib/utils"; import Image from "./image"; @@ -62,7 +63,9 @@ export function Markdown({ }} {...props} > - {dropMarkdownQuote(processKatexInMarkdown(children))} + {autoFixMarkdown( + dropMarkdownQuote(processKatexInMarkdown(children ?? "")) ?? "", + )} {enableCopy && typeof children === "string" && (
diff --git a/web/src/core/utils/markdown.ts b/web/src/core/utils/markdown.ts new file mode 100644 index 0000000..8b4a70f --- /dev/null +++ b/web/src/core/utils/markdown.ts @@ -0,0 +1,57 @@ +export function autoFixMarkdown(markdown: string): string { + return autoCloseTrailingLink(markdown); +} + +function autoCloseTrailingLink(markdown: string): string { + // Fix unclosed Markdown links or images + let fixedMarkdown: string = markdown; + + // Fix unclosed image syntax ![...](...) + fixedMarkdown = fixedMarkdown.replace( + /!\[([^\]]*)\]\(([^)]*)$/g, + (match: string, altText: string, url: string): string => { + return `![${altText}](${url})`; + }, + ); + + // Fix unclosed link syntax [...](...) + fixedMarkdown = fixedMarkdown.replace( + /\[([^\]]*)\]\(([^)]*)$/g, + (match: string, linkText: string, url: string): string => { + return `[${linkText}](${url})`; + }, + ); + + // Fix unclosed image syntax ![...] + fixedMarkdown = fixedMarkdown.replace( + /!\[([^\]]*)$/g, + (match: string, altText: string): string => { + return `![${altText}]`; + }, + ); + + // Fix unclosed link syntax [...] + fixedMarkdown = fixedMarkdown.replace( + /\[([^\]]*)$/g, + (match: string, linkText: string): string => { + return `[${linkText}]`; + }, + ); + + // Fix unclosed images or links missing ")" + fixedMarkdown = fixedMarkdown.replace( + /!\[([^\]]*)\]\(([^)]*)$/g, + (match: string, altText: string, url: string): string => { + return `![${altText}](${url})`; + }, + ); + + fixedMarkdown = fixedMarkdown.replace( + /\[([^\]]*)\]\(([^)]*)$/g, + (match: string, linkText: string, url: string): string => { + return `[${linkText}](${url})`; + }, + ); + + return fixedMarkdown; +}