fix(viewer): allow iframe, only from custom yt directive

This commit is contained in:
enes 2024-12-24 17:03:18 +01:00
parent a6ed390fad
commit 137cd95c4e
2 changed files with 23 additions and 4 deletions

View File

@ -2,15 +2,34 @@ import DOMPurify from 'dompurify'
import { marked } from 'marked' import { marked } from 'marked'
import { createDirectives, presetDirectiveConfigs } from 'marked-directive' import { createDirectives, presetDirectiveConfigs } from 'marked-directive'
import { youtubeDirective } from './YoutubeDirective' import { youtubeDirective } from './YoutubeDirective'
import { useMemo } from 'react'
interface ViewerProps { interface ViewerProps {
markdown: string markdown: string
} }
export const Viewer = ({ markdown }: ViewerProps) => { export const Viewer = ({ markdown }: ViewerProps) => {
const html = marked 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])) .use(createDirectives([...presetDirectiveConfigs, youtubeDirective]))
.parse(DOMPurify.sanitize(markdown), { async: false }) .parse(`${markdown}`, {
async: false
}),
{
ADD_TAGS: ['iframe']
}
)
}, [markdown])
return ( return (
<div className='viewer' dangerouslySetInnerHTML={{ __html: html }}></div> <div className='viewer' dangerouslySetInnerHTML={{ __html: html }}></div>

View File

@ -20,7 +20,7 @@ export const youtubeDirective: DirectiveConfig = {
} }
if (vid) { if (vid) {
return `<iframe width="560" height="315" src="https://www.youtube.com/embed/${vid}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>` return `<iframe title="Video embed" width="560" height="315" src="https://www.youtube.com/embed/${vid}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>`
} }
return false return false