// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: MIT package markdown import "testing" // gfmCorpus holds the cases of the GitHub Flavored Markdown extensions: // tables, strikethrough and task lists. var gfmCorpus = []struct { name string input string want string }{ // Tables, in the multi-line shape the GFM specification prints. {"table basic", "| foo | bar |\n| --- | --- |\n| baz | bim |", "\n\n\n\n\n\n\n\n\n\n\n\n\n
foobar
bazbim
\n"}, {"table without boundary pipes", "foo | bar\n--- | ---\nbaz | bim", "\n\n\n\n\n\n\n\n\n\n\n\n\n
foobar
bazbim
\n"}, {"table alignment", "| a | b | c | d |\n| :- | :-: | -: | - |", "\n\n\n\n\n\n\n\n\n
abcd
\n"}, {"table without body", "| abc | def |\n| --- | --- |", "\n\n\n\n\n\n\n
abcdef
\n"}, {"table excess cell ignored", "| a | b |\n| --- | --- |\n| c | d | e |", "\n\n\n\n\n\n\n\n\n\n\n\n\n
ab
cd
\n"}, {"table missing cell empty", "| a | b |\n| --- | --- |\n| c |", "\n\n\n\n\n\n\n\n\n\n\n\n\n
ab
c
\n"}, {"table count mismatch stays paragraph", "| a | b |\n| --- |\n| c |", "

| a | b |\n| --- |\n| c |

\n"}, {"table escaped pipe", "| a \\| b | c |\n| --- | --- |", "\n\n\n\n\n\n\n
a | bc
\n"}, {"table cells hold inline", "| *a* | `b` |\n| --- | --- |", "\n\n\n\n\n\n\n
ab
\n"}, {"table code span escaped pipe", "| f\\|oo |\n| --- |\n| b `\\|` az |", "\n\n\n\n\n\n\n\n\n\n\n
f|oo
b | az
\n"}, {"table breaks at blank", "| a |\n| --- |\n| b |\n\nparagraph", "\n\n\n\n\n\n\n\n\n\n\n
a
b
\n

paragraph

\n"}, {"table interrupted by heading", "| a |\n| --- |\n| b |\n# h", "\n\n\n\n\n\n\n\n\n\n\n
a
b
\n

h

\n"}, {"table interrupts paragraph", "a | b\n--- | ---", "\n\n\n\n\n\n\n
ab
\n"}, {"table splits paragraph", "foo\na | b\n--- | ---", "

foo

\n\n\n\n\n\n\n\n
ab
\n"}, {"setext without pipes stays", "abc\n---", "

abc

\n"}, // Strikethrough. {"strikethrough double tilde", "~~foo~~", "

foo

\n"}, {"strikethrough single tilde", "~foo~", "

foo

\n"}, {"strikethrough unmatched pair", "~~foo~", "

~foo

\n"}, {"strikethrough intraword", "foo~~bar~~baz", "

foobarbaz

\n"}, {"tilde spaced stays literal", "a ~ b", "

a ~ b

\n"}, // Task lists. {"task checked", "- [x] foo", "\n"}, {"task unchecked", "- [ ] foo", "\n"}, {"task uppercase x", "- [X] foo", "\n"}, {"task needs a space", "- [x]foo", "\n"}, {"task list of two", "- [x] foo\n- [ ] bar", "\n"}, {"task nested", "- [x] foo\n - [ ] bar", "\n"}, {"task in loose list", "- [x] foo\n\n- [ ] bar", "\n"}, } func TestGFMCorpus(t *testing.T) { for _, tc := range gfmCorpus { t.Run(tc.name, func(t *testing.T) { got := string(RenderHTML([]byte(tc.input))) if got != tc.want { t.Errorf("input %q\ngot: %q\nwant: %q", tc.input, got, tc.want) } }) } }