diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index bf8408c2..9631949c 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -327,3 +327,98 @@ body::after { .score-bar-gradient-low { background: linear-gradient(90deg, #585860, #3a3a40); } + +/* Markdown rendered inside AI responses */ +.prose h1, +.prose h2, +.prose h3, +.prose h4 { + color: var(--text-primary); + font-weight: 700; + line-height: 1.35; +} + +.prose h1 { + margin: 1rem 0 0.5rem; + font-size: 1.05rem; +} + +.prose h2 { + margin: 0.9rem 0 0.45rem; + font-size: 0.98rem; +} + +.prose h3 { + margin: 0.8rem 0 0.4rem; + font-size: 0.92rem; +} + +.prose h4 { + margin: 0.7rem 0 0.35rem; + font-size: 0.86rem; +} + +.prose p { + color: var(--text-secondary); +} + +.prose code { + border: 1px solid var(--border-subtle); + border-radius: 6px; + background: var(--surface-2); + padding: 0.1rem 0.3rem; + color: var(--accent-cyan); + font-size: 0.9em; +} + +.prose pre { + overflow-x: auto; + border: 1px solid var(--border-subtle); + border-radius: 12px; + background: var(--surface-1); + padding: 0.75rem; +} + +.prose pre code { + border: 0; + background: transparent; + padding: 0; + color: var(--text-secondary); +} + +.markdown-table-wrap { + margin: 0.75rem 0; + max-width: 100%; + overflow-x: auto; + border: 1px solid var(--border-subtle); + border-radius: 12px; +} + +.markdown-table-wrap table { + width: 100%; + min-width: 520px; + border-collapse: collapse; + font-size: 0.78rem; +} + +.markdown-table-wrap th, +.markdown-table-wrap td { + border-bottom: 1px solid var(--border-subtle); + padding: 0.55rem 0.65rem; + text-align: left; + vertical-align: top; +} + +.markdown-table-wrap th { + background: var(--surface-2); + color: var(--text-primary); + font-weight: 700; +} + +.markdown-table-wrap td { + color: var(--text-secondary); +} + +.markdown-table-wrap tr:last-child td { + border-bottom: 0; +} diff --git a/frontend/src/lib/markdown.ts b/frontend/src/lib/markdown.ts index 8dd486fa..ae8a5791 100644 --- a/frontend/src/lib/markdown.ts +++ b/frontend/src/lib/markdown.ts @@ -1,34 +1,120 @@ -export function markdownToHtml(md: string): string { - return md +function escapeHtml(value: string): string { + return value .replace(/&/g, "&") .replace(//g, ">") - .replace(/^## (.+)$/gm, "

$1

") - .replace(/^### (.+)$/gm, "

$1

") - .replace(/\*\*(.+?)\*\*/g, "$1") - .replace(/^- (.+)$/gm, "
  • $1
  • ") - .replace(/(
  • .*<\/li>\n?)+/g, (m) => ``) - .replace(/\n{2,}/g, "

    ") - .replace(/^(?!<[hulo])/gm, "

    ") - .replace(/(?])$/gm, "

    ") - .replace(/

    <\/p>/g, "") - .replace(/

    ()/g, "$1") - .replace(/(<\/h[23]>)<\/p>/g, "$1") - .replace(/

    (