/* Tutor prose. Deliberately almost no markup: the prompt allows **bold** and nothing else. Two behaviours carry over from the artifact because they do real work: - a line that is mostly Korean and short is set larger, so an example sentence reads as an example rather than as prose; - a line opening with ✓ or ✗ is a marked answer, and gets the colour. */ import { Fragment } from "react"; const KOREAN = /[가-힣]/g; const PUNCT = /[\s.,!?·…"'“”()[\]:;~-]/g; /** Mostly-Korean and short enough to be an example, not a sentence of prose. */ function isKoreanLine(line: string): boolean { const bare = line.replace(PUNCT, ""); if (!bare || bare.length > 60) return false; const korean = (bare.match(KOREAN) ?? []).length; return korean / bare.length > 0.55; } /** **bold** is the only inline markup the prompt permits. */ function inline(text: string) { return text.split(/(\*\*[^*]+\*\*)/g).map((part, i) => part.startsWith("**") && part.endsWith("**") && part.length > 4 ? ( {part.slice(2, -2)} ) : ( {part} ), ); } export function MessageBody({ text }: { text: string }) { const lines = text.split("\n"); return ( <> {lines.map((line, i) => { const trimmed = line.trim(); if (!trimmed) return
; const mark = trimmed.startsWith("✓") ? "ok" : trimmed.startsWith("✗") ? "no" : null; const rest = mark ? trimmed.slice(1).trimStart() : trimmed; return (

{mark && {mark === "ok" ? "✓" : "✗"}} {inline(rest)}

); })} ); }