", "quoted"}},
{"link", "see [xAI](https://x.ai)", []string{`href="https://x.ai"`, "xAI"}},
{"fenced code", "```go\nfmt.Println()\n```", []string{"", "", "| ", "a", " | ", "1"}},
{"image as link", "", []string{`href="https://x.ai/logo.png"`, "logo"}},
{"autolink bare url", "visit https://x.ai now", []string{`href="https://x.ai"`}},
}
for _, c := range rich {
t.Run("rich/"+c.name, func(t *testing.T) {
got, formatted := markdownToHTML(c.in)
if !formatted {
t.Fatalf("markdownToHTML(%q) formatted=false, want true (got %q)", c.in, got)
}
for _, sub := range c.contains {
if !strings.Contains(got, sub) {
t.Fatalf("markdownToHTML(%q) = %q, missing %q", c.in, got, sub)
}
}
})
}
// Plain text (even multi-line or with stray punctuation) carries no
// formatting, so the bot sends only the bare body.
plain := []string{
"just a sentence",
"line one\nline two",
"a < b & c > d",
"2 * 3 * 4",
"snake_case_name",
"файл_имя_тут",
"text with ! bang",
`path c:\users`,
"",
}
for _, in := range plain {
t.Run("plain", func(t *testing.T) {
if got, formatted := markdownToHTML(in); formatted {
t.Fatalf("markdownToHTML(%q) formatted=true, want false (got %q)", in, got)
}
})
}
}
func TestMarkdownNeverEmitsUnsafeScheme(t *testing.T) {
for _, bad := range []string{
"[a](javascript:x)", "[a](data:text/html,x)", "[a](vbscript:x)", "[a](file:///etc)",
"[a](JaVaScRiPt:x)", "[a](java\tscript:x)",
} {
if html, _ := markdownToHTML(bad); strings.Contains(html, "href=") {
t.Fatalf("emitted a link for unsafe scheme: %q -> %q", bad, html)
}
}
}
func TestMarkdownOversizeFallsBackToPlain(t *testing.T) {
// A formatted reply whose HTML exceeds maxFormattedBytes must return ("", false)
// so the bot sends only the plain body.
big := strings.Repeat("- item\n", 8000)
if html, formatted := markdownToHTML(big); formatted || html != "" {
t.Fatalf("oversize formatted output should fall back to plain: formatted=%v len=%d", formatted, len(html))
}
// Implausibly large input is rejected outright.
huge := strings.Repeat("a", maxInputBytes+1)
if html, formatted := markdownToHTML(huge); formatted || html != "" {
t.Fatalf("oversize input should fall back to plain: formatted=%v len=%d", formatted, len(html))
}
}
func TestMarkdownAdversarialNoPanicNoInjection(t *testing.T) {
inputs := []string{
strings.Repeat("[", 20000) + "x",
"x" + strings.Repeat("](https://a)", 20000),
strings.Repeat("*", 5000) + "x" + strings.Repeat("*", 5000),
strings.Repeat("> ", 5000) + "deep",
strings.Repeat(" ", 50) + "- nested",
strings.Repeat("`", 4000) + "code",
"| " + strings.Repeat("a |", 2000) + "\n| " + strings.Repeat("- |", 2000) + "\n| x |",
"\n**``**\n[x](\"> |