Files
llmgw/internal/web/chatrender_test.go
T
Ilker ManapandClaude Opus 5.5 6b1f8b0827 Render a finished chat reply as markdown
A reply streams as text as before; once it ends, the server renders it
with the model card's rules - raw HTML dropped, dangerous links emptied,
images as links - and the page places that. Headings, lists, tables and
code blocks read as they were written.

Maths outside code is set aside before the markdown, so its underscores
and asterisks are not taken for emphasis, and marked for the page to
typeset. KaTeX no longer searches the reply for delimiters, which took
"$5 and $10" for a formula. A reply that cannot be rendered stays
plain text, with the old search.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:44:18 +02:00

50 lines
1.6 KiB
Go

package web
import (
"strings"
"testing"
)
func TestAReplyIsMarkdownWithItsMathsLeftForKaTeX(t *testing.T) {
got := string(renderReply("Here is **bold** and `code`.\n\n" +
"The sum $a_1 * b_2$ and \\(x_i^2\\), then\n\n$$\\sum_{i=1}^n i$$\n\n" +
"```go\nfmt.Println(\"$5\")\n```\n\nIt costs $5 and $10."))
for _, want := range []string{
"<strong>bold</strong>", "<code>code</code>",
// Untouched by emphasis, and marked for KaTeX with its delimiters
// taken off.
`data-display="0" data-src="$a_1 * b_2$">a_1 * b_2</span>`,
`>x_i^2</span>`, `data-display="1" data-src="$$\sum_{i=1}^n i$$">\sum_{i=1}^n i</span>`,
`<pre><code class="language-go">`,
"It costs $5 and $10.",
} {
if !strings.Contains(got, want) {
t.Errorf("missing %q in %s", want, got)
}
}
if strings.Contains(got, "llmgwmath") {
t.Errorf("a placeholder was left behind: %s", got)
}
}
func TestAReplyCannotRunAnything(t *testing.T) {
got := string(renderReply("<script>alert(1)</script>\n\n[x](javascript:alert(1))\n\n" +
"$<img src=x onerror=alert(1)>$"))
for _, bad := range []string{"<script", "javascript:", "<img"} {
if strings.Contains(got, bad) {
t.Errorf("rendered %q: %s", bad, got)
}
}
}
func TestMathsInCodeIsLeftAsCode(t *testing.T) {
got := string(renderReply("Use `$x$` literally.\n\n```sh\necho $HOME $PATH\n```\n\nBut $y_1$ is maths."))
if strings.Count(got, `class="math"`) != 1 || !strings.Contains(got, `data-src="$y_1$"`) {
t.Errorf("only the maths outside code should be marked: %s", got)
}
if !strings.Contains(got, "<code>$x$</code>") || !strings.Contains(got, "echo $HOME $PATH") {
t.Errorf("code should keep its dollars: %s", got)
}
}