From 8e3a8ef908bb10f7798eefca61bf9d47fac45f25 Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 5 Mar 2026 17:29:17 +0800 Subject: [PATCH] feat: pure markdown --- .../markdown-with-directive-schema.ts | 5 ++++- .../base/markdown-with-directive/index.tsx | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/web/app/components/base/markdown-with-directive/components/markdown-with-directive-schema.ts b/web/app/components/base/markdown-with-directive/components/markdown-with-directive-schema.ts index bf1822b4cf..02092407a9 100644 --- a/web/app/components/base/markdown-with-directive/components/markdown-with-directive-schema.ts +++ b/web/app/components/base/markdown-with-directive/components/markdown-with-directive-schema.ts @@ -7,7 +7,10 @@ export const withIconCardListPropsSchema = z.object(commonSchema).strict() export const withIconCardItemPropsSchema = z.object({ ...commonSchema, - icon: z.string().trim(), + icon: z.string().trim().url().refine( + value => /^https?:\/\//i.test(value), + 'icon must be a http/https URL', + ), }).strict() export const directivePropsSchemas = { diff --git a/web/app/components/base/markdown-with-directive/index.tsx b/web/app/components/base/markdown-with-directive/index.tsx index ad31a50972..2662f9356f 100644 --- a/web/app/components/base/markdown-with-directive/index.tsx +++ b/web/app/components/base/markdown-with-directive/index.tsx @@ -1,4 +1,5 @@ import type { Components } from 'react-markdown' +import DOMPurify from 'dompurify' import ReactMarkdown from 'react-markdown' import remarkDirective from 'remark-directive' import { visit } from 'unist-util-visit' @@ -169,11 +170,27 @@ type MarkdownWithDirectiveProps = { markdown: string } +function sanitizeMarkdownInput(markdown: string): string { + if (!markdown) + return '' + + if (typeof DOMPurify.sanitize === 'function') { + return DOMPurify.sanitize(markdown, { + ALLOWED_ATTR: [], + ALLOWED_TAGS: [], + }) + } + + return markdown +} + export function MarkdownWithDirective({ markdown }: MarkdownWithDirectiveProps) { - const normalizedMarkdown = normalizeDirectiveAttributeBlocks(markdown) + const sanitizedMarkdown = sanitizeMarkdownInput(markdown) + const normalizedMarkdown = normalizeDirectiveAttributeBlocks(sanitizedMarkdown) return (