import { Fragment, type ReactNode } from "react"; import "./ai.css"; /** Shown whenever the learner has switched the course's mentor rules off. */ export function MentorBanner({ on, available }: { on: boolean; available: boolean }) { if (on || !available) return null; return

Mentor mode off: I'll give full answers

; } export function Field({ label, hint, children }: { label: string; hint?: string; children: ReactNode }) { return ( ); } export function PageHead({ chap, title, children }: { chap?: ReactNode; title: string; children?: ReactNode }) { return (
{chap ?

{chap}

: null}

{title}

{children ?
{children}
: null}
); } function inline(text: string, key: string): ReactNode[] { const out: ReactNode[] = []; const re = /(`[^`]+`|\*\*[^*]+\*\*)/g; let last = 0; let m: RegExpExecArray | null; let i = 0; while ((m = re.exec(text))) { if (m.index > last) out.push(text.slice(last, m.index)); const tok = m[0]; out.push(tok.startsWith("`") ? {tok.slice(1, -1)} : {tok.slice(2, -2)}); last = m.index + tok.length; } if (last < text.length) out.push(text.slice(last)); return out; } /** A small, safe Markdown subset for assistant answers: paragraphs, lists, headings, fenced code, `code`, **bold**. */ export function Markdown({ text }: { text: string }) { const blocks: ReactNode[] = []; const lines = text.replace(/\r\n/g, "\n").split("\n"); let i = 0; let k = 0; while (i < lines.length) { const line = lines[i]!; if (/^\s*```/.test(line)) { const code: string[] = []; i++; while (i < lines.length && !/^\s*```/.test(lines[i]!)) code.push(lines[i++]!); i++; blocks.push(
{code.join("\n")}
); } else if (/^\s*([-*]|\d+\.)\s+/.test(line)) { const ordered = /^\s*\d+\./.test(line); const items: string[] = []; while (i < lines.length && /^\s*([-*]|\d+\.)\s+/.test(lines[i]!)) items.push(lines[i++]!.replace(/^\s*([-*]|\d+\.)\s+/, "")); const kids = items.map((it, j) =>
  • {inline(it, `${k}-${j}`)}
  • ); blocks.push(ordered ?
      {kids}
    : ); } else if (/^#{1,6}\s/.test(line)) { blocks.push(

    {inline(line.replace(/^#+\s*/, ""), String(k))}

    ); i++; } else if (!line.trim()) i++; else { const para: string[] = []; while (i < lines.length && lines[i]!.trim() && !/^\s*(```|[-*]\s|\d+\.\s|#{1,6}\s)/.test(lines[i]!)) para.push(lines[i++]!); blocks.push(

    {para.map((p, j) => {j ?
    : null}{inline(p, `${k}-${j}`)}
    )}

    ); } } return
    {blocks}
    ; }