diff --git a/frontend/src/routes/study/topics/[id]/questions/[qid]/edit/+page.svelte b/frontend/src/routes/study/topics/[id]/questions/[qid]/edit/+page.svelte
index 17ba13d..54c739e 100644
--- a/frontend/src/routes/study/topics/[id]/questions/[qid]/edit/+page.svelte
+++ b/frontend/src/routes/study/topics/[id]/questions/[qid]/edit/+page.svelte
@@ -12,12 +12,26 @@
import { api } from '$lib/api';
import { addToast } from '$lib/stores/toast';
import { ArrowLeft, Save, Trash2, AlertCircle, Sparkles, GitCompare, ArrowRight, CheckCircle2, XCircle } from 'lucide-svelte';
+ import { marked } from 'marked';
+ import DOMPurify from 'dompurify';
import Button from '$lib/components/ui/Button.svelte';
import Card from '$lib/components/ui/Card.svelte';
import Skeleton from '$lib/components/ui/Skeleton.svelte';
import TextInput from '$lib/components/ui/TextInput.svelte';
import Textarea from '$lib/components/ui/Textarea.svelte';
+ // AI 풀이 markdown 렌더링 (DocumentViewer 와 동일 패턴)
+ marked.use({ mangle: false, headerIds: false });
+ function renderMd(text) {
+ if (!text) return '';
+ return DOMPurify.sanitize(marked(text), {
+ USE_PROFILES: { html: true },
+ FORBID_TAGS: ['style', 'script'],
+ FORBID_ATTR: ['onerror', 'onclick'],
+ ALLOW_UNKNOWN_PROTOCOLS: false,
+ });
+ }
+
let topicId = $derived(Number($page.params.id));
let questionId = $derived(Number($page.params.qid));
@@ -289,7 +303,9 @@
{/if}
{#if aiOpen && aiBody}
-
{aiBody}
+
+ {@html renderMd(aiBody)}
+
{#if aiEvidence?.length}
참고 근거 {aiEvidence.length}건
diff --git a/frontend/src/routes/study/topics/[id]/review/+page.svelte b/frontend/src/routes/study/topics/[id]/review/+page.svelte
index 4e94cd3..2d5a4a1 100644
--- a/frontend/src/routes/study/topics/[id]/review/+page.svelte
+++ b/frontend/src/routes/study/topics/[id]/review/+page.svelte
@@ -12,11 +12,25 @@
import { api } from '$lib/api';
import { addToast } from '$lib/stores/toast';
import { ArrowLeft, Play, CheckCircle2, XCircle, RotateCcw, Sparkles, AlertCircle, GitCompare, ArrowRight } from 'lucide-svelte';
+ import { marked } from 'marked';
+ import DOMPurify from 'dompurify';
import Button from '$lib/components/ui/Button.svelte';
import Card from '$lib/components/ui/Card.svelte';
import Skeleton from '$lib/components/ui/Skeleton.svelte';
import TextInput from '$lib/components/ui/TextInput.svelte';
+ // AI 풀이 markdown 렌더링 (DocumentViewer 와 동일 패턴)
+ marked.use({ mangle: false, headerIds: false });
+ function renderMd(text) {
+ if (!text) return '';
+ return DOMPurify.sanitize(marked(text), {
+ USE_PROFILES: { html: true },
+ FORBID_TAGS: ['style', 'script'],
+ FORBID_ATTR: ['onerror', 'onclick'],
+ ALLOW_UNKNOWN_PROTOCOLS: false,
+ });
+ }
+
let topicId = $derived(Number($page.params.id));
let topicName = $state('');
@@ -357,7 +371,9 @@
{aiExplError}
{/if}
{#if aiExpl?.ai_explanation}
- {aiExpl.ai_explanation}
+
+ {@html renderMd(aiExpl.ai_explanation)}
+
{/if}
{#if aiExpl?.evidence?.length}