From 137cd95c4e4476c10fc08e48c3b0b31da3a1dc54 Mon Sep 17 00:00:00 2001 From: enes Date: Tue, 24 Dec 2024 17:03:18 +0100 Subject: [PATCH] fix(viewer): allow iframe, only from custom yt directive --- src/components/Markdown/Viewer.tsx | 25 +++++++++++++++++--- src/components/Markdown/YoutubeDirective.tsx | 2 +- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/components/Markdown/Viewer.tsx b/src/components/Markdown/Viewer.tsx index f2684ca..6f4a1cb 100644 --- a/src/components/Markdown/Viewer.tsx +++ b/src/components/Markdown/Viewer.tsx @@ -2,15 +2,34 @@ import DOMPurify from 'dompurify' import { marked } from 'marked' import { createDirectives, presetDirectiveConfigs } from 'marked-directive' import { youtubeDirective } from './YoutubeDirective' +import { useMemo } from 'react' interface ViewerProps { markdown: string } export const Viewer = ({ markdown }: ViewerProps) => { - const html = marked - .use(createDirectives([...presetDirectiveConfigs, youtubeDirective])) - .parse(DOMPurify.sanitize(markdown), { async: false }) + const html = useMemo(() => { + DOMPurify.addHook('beforeSanitizeAttributes', function (node) { + if (node.nodeName && node.nodeName === 'IFRAME') { + const src = node.attributes.getNamedItem('src') + if (!(src && src.value.startsWith('https://www.youtube.com/embed/'))) { + node.remove() + } + } + }) + + return DOMPurify.sanitize( + marked + .use(createDirectives([...presetDirectiveConfigs, youtubeDirective])) + .parse(`${markdown}`, { + async: false + }), + { + ADD_TAGS: ['iframe'] + } + ) + }, [markdown]) return (
diff --git a/src/components/Markdown/YoutubeDirective.tsx b/src/components/Markdown/YoutubeDirective.tsx index bedfbe0..4908d0d 100644 --- a/src/components/Markdown/YoutubeDirective.tsx +++ b/src/components/Markdown/YoutubeDirective.tsx @@ -20,7 +20,7 @@ export const youtubeDirective: DirectiveConfig = { } if (vid) { - return `` + return `` } return false