import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { ExternalLink, Download, X } from 'lucide-react' import Markdown from 'react-markdown' import remarkGfm from 'remark-gfm' import remarkBreaks from 'remark-breaks' import rehypeSanitize from 'rehype-sanitize' import { openFile as openFileUrl } from '../../utils/fileDownload' import type { FileManagerState } from './useFileManager' import { triggerDownload } from './FileManager.helpers' /** * Inline preview for uploaded Markdown files (#1345). Fetches the file's text via * the signed preview URL and renders it with react-markdown. Output is sanitized * with rehype-sanitize — these are UNTRUSTED uploads, unlike collab notes — and * react-markdown v10 already drops raw HTML, so no script can execute. */ export function MarkdownPreviewModal(S: FileManagerState) { const { previewFile, setPreviewFile, previewFileUrl, toast, t } = S const [text, setText] = useState('') const [err, setErr] = useState(false) useEffect(() => { if (!previewFileUrl) return let cancelled = false setErr(false) setText('') fetch(previewFileUrl, { credentials: 'include' }) .then(r => (r.ok ? r.text() : Promise.reject(new Error('load failed')))) .then(body => { if (!cancelled) setText(body) }) .catch(() => { if (!cancelled) setErr(true) }) return () => { cancelled = true } }, [previewFileUrl]) return createPortal(
setPreviewFile(null)} >
e.stopPropagation()} >
{previewFile.original_name}
{err ?

{t('files.openError')}

: {text}}
, document.body ) }