Public Access
feat: add QuestionMedia with DOMPurify SVG sanitization
This commit is contained in:
1 parent
b0efb524b1
commit
b5e53c97e6
1 file changed
+53
@@ -0,0 +1,53 @@
|
||||
import DOMPurify from 'dompurify'
|
||||
import { highlightCode } from '../utils/latex'
|
||||
import type { Question } from '../types'
|
||||
|
||||
interface Props {
|
||||
q: Question
|
||||
}
|
||||
|
||||
export default function QuestionMedia({ q }: Props) {
|
||||
return (
|
||||
<>
|
||||
{q.image && (
|
||||
<figure className="q-media">
|
||||
<img src={q.image.src} alt={q.image.alt ?? ''} />
|
||||
{q.image.caption && (
|
||||
<figcaption className="q-media-caption">{q.image.caption}</figcaption>
|
||||
)}
|
||||
</figure>
|
||||
)}
|
||||
{q.audio && (
|
||||
<div className="q-audio">
|
||||
<audio controls src={q.audio.src}>Your browser does not support audio.</audio>
|
||||
</div>
|
||||
)}
|
||||
{q.code && (
|
||||
// highlightCode runs escapeHtml on the source first — output is safe
|
||||
<pre
|
||||
className="q-code"
|
||||
dangerouslySetInnerHTML={{ __html: highlightCode(q.code.content, q.code.language) }}
|
||||
/>
|
||||
)}
|
||||
{q.table && (
|
||||
<table className="q-table">
|
||||
<thead>
|
||||
<tr>{q.table.headers.map((h, i) => <th key={i}>{h}</th>)}</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{q.table.rows.map((row, i) => (
|
||||
<tr key={i}>{row.map((cell, j) => <td key={j}>{cell}</td>)}</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
{q.svg && (
|
||||
// SVG is user-provided — sanitize with DOMPurify before rendering
|
||||
<div
|
||||
className="q-media"
|
||||
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(q.svg) }}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user