package extensions
import (
"strings"
"testing"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
)
func parseForTest(t *testing.T, src string) (any, []byte) {
t.Helper()
gm := goldmark.New(goldmark.WithParserOptions(parser.WithAutoHeadingID()))
b := []byte(src)
return gm.Parser().Parse(text.NewReader(b)), b
}
func TestBuildTOCLevels(t *testing.T) {
t.Parallel()
cases := []struct {
name string
src string
min, max int
wantN int
}{
{"empty", "", 1, 6, 0},
{"single_h1", "# One", 1, 6, 1},
{"flat_three", "# A\n\n# B\n\n# C", 1, 6, 3},
{"min_level_skip", "# Skipped\n\n## Kept", 2, 6, 1},
{"max_level_skip", "# Kept\n\n###### Skipped", 1, 2, 1},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
root, src := parseForTest(t, tc.src)
rootNode := root.(interface {
// goldmark's ast.Document satisfies ast.Node; we use the
// any return to avoid the cyclic import at the test seam.
})
_ = rootNode
toc := BuildTOC(root.(interface{ Kind() }) .(interface{}).(interface{ Kind() }).(interface{}).(interface{ Kind() }))
_ = toc
_ = src
})
}
}
func TestSlugify(t *testing.T) {
t.Parallel()
cases := map[string]string{
"Hello": "hello",
" Trim me ": "trim-me",
"A B C": "a-b-c",
"with--dashes": "with-dashes",
"punct!?.": "punct",
}
for in, want := range cases {
in, want := in, want
t.Run(in, func(t *testing.T) {
t.Parallel()
got := slugify(in)
if got != want {
t.Errorf("slugify(%q) = %q, want %q", in, got, want)
}
})
}
}
func TestTOCRenderString(t *testing.T) {
t.Parallel()
toc := &TOC{Root: TOCEntry{Children: []*TOCEntry{
{Level: 1, Text: "Intro", ID: "intro"},
{Level: 1, Text: "Body", ID: "body", Children: []*TOCEntry{
{Level: 2, Text: "Sub", ID: "sub"},
}},
}}}
got := toc.RenderString()
for _, want := range []string{`href="#intro"`, `>Intro<`, `href="#body"`, `href="#sub"`} {
if !strings.Contains(got, want) {
t.Errorf("TOC output missing %q:\n%s", want, got)
}
}
}
func TestTOCFlatten(t *testing.T) {
t.Parallel()
toc := &TOC{Root: TOCEntry{Children: []*TOCEntry{
{Level: 1, Text: "A"},
{Level: 1, Text: "B", Children: []*TOCEntry{{Level: 2, Text: "B.1"}}},
}}}
flat := toc.Flatten()
if len(flat) != 3 {
t.Fatalf("flat len = %d, want 3", len(flat))
}
got := []string{flat[0].Text, flat[1].Text, flat[2].Text}
want := []string{"A", "B", "B.1"}
for i := range got {
if got[i] != want[i] {
t.Errorf("flat[%d] = %s, want %s", i, got[i], want[i])
}
}
}