package parser import ( "bytes" "os" "path/filepath" "testing" ) func TestDiscoverSlideFiles_SortsByPrefixAndIgnoresNonMarkdown(t *testing.T) { dir := t.TempDir() writeFiles(t, dir, map[string]string{ "020-second.md": "body", "010-first.md": "body", "030-third.md": "body", "README.txt": "not a slide", "assets/img.png": "binary", }) got, err := discoverSlideFiles(dir) if err != nil { t.Fatalf("discoverSlideFiles() error = %v", err) } want := []string{"010-first.md", "020-second.md", "030-third.md"} if !equalStrings(got, want) { t.Errorf("discoverSlideFiles() = %v, want %v", got, want) } } func TestDiscoverSlideFiles_SortsNumericallyAcrossDigitCounts(t *testing.T) { dir := t.TempDir() writeFiles(t, dir, map[string]string{ "10-b.md": "body", "9-a.md": "body", "1000-d.md": "body", "999-c.md": "body", }) got, err := discoverSlideFiles(dir) if err != nil { t.Fatalf("discoverSlideFiles() error = %v", err) } want := []string{"9-a.md", "10-b.md", "999-c.md", "1000-d.md"} if !equalStrings(got, want) { t.Errorf("discoverSlideFiles() = %v, want %v", got, want) } } func TestParseDir_RespectsSkip(t *testing.T) { dir := t.TempDir() writeFiles(t, dir, map[string]string{ "010-intro.md": "---\ntitle: Intro\n---\n# Intro\n", "020-hidden.md": "---\ntitle: Hidden\nskip: true\n---\n# Hidden\n", "030-outro.md": "---\ntitle: Outro\n---\n# Outro\n", }) slides, err := ParseDir(dir) if err != nil { t.Fatalf("ParseDir() error = %v", err) } if len(slides) != 2 { t.Fatalf("len(slides) = %d, want 2", len(slides)) } if slides[0].Title != "Intro" || slides[1].Title != "Outro" { t.Errorf("slides = %+v, want Intro then Outro (Hidden skipped)", slides) } } func TestParseDir_OrderAndFields(t *testing.T) { dir := t.TempDir() writeFiles(t, dir, map[string]string{ "020-second.md": "---\ntitle: Second\nclass: center\nnotes: speak here\n---\n# Second\n", "010-first.md": "---\ntitle: First\n---\n# First\n", }) slides, err := ParseDir(dir) if err != nil { t.Fatalf("ParseDir() error = %v", err) } if len(slides) != 2 { t.Fatalf("len(slides) = %d, want 2", len(slides)) } if slides[0].Filename != "010-first.md" || slides[1].Filename != "020-second.md" { t.Fatalf("slides in wrong order: %+v", slides) } if slides[1].Class != "center" || slides[1].Notes != "speak here" { t.Errorf("slides[1] = %+v, want Class=center Notes=\"speak here\"", slides[1]) } } func TestParseDir_Incremental(t *testing.T) { dir := t.TempDir() writeFiles(t, dir, map[string]string{ "010-a.md": "---\nincremental: true\n---\n# A\n", "020-b.md": "# B\n", }) slides, err := ParseDir(dir) if err != nil { t.Fatalf("ParseDir() error = %v", err) } if !slides[0].Incremental { t.Errorf("slides[0].Incremental = false, want true") } if slides[1].Incremental { t.Errorf("slides[1].Incremental = true, want false") } } func TestParseDir_NewSlideMarkerSplitsOneFileIntoMultipleSlides(t *testing.T) { dir := t.TempDir() writeFiles(t, dir, map[string]string{ "010-combo.md": "---\ntitle: Combo\nclass: center\n---\n# One\n\n\n\n# Two\n", "020-after.md": "# Three\n", }) slides, err := ParseDir(dir) if err != nil { t.Fatalf("ParseDir() error = %v", err) } if len(slides) != 3 { t.Fatalf("len(slides) = %d, want 3: %+v", len(slides), slides) } if !bytes.Contains([]byte(slides[0].HTML), []byte("One")) { t.Errorf("slides[0].HTML = %q, want it to contain %q", slides[0].HTML, "One") } if !bytes.Contains([]byte(slides[1].HTML), []byte("Two")) { t.Errorf("slides[1].HTML = %q, want it to contain %q", slides[1].HTML, "Two") } if !bytes.Contains([]byte(slides[2].HTML), []byte("Three")) { t.Errorf("slides[2].HTML = %q, want it to contain %q", slides[2].HTML, "Three") } // Both parts of the split file share its frontmatter. if slides[0].Title != "Combo" || slides[1].Title != "Combo" { t.Errorf("slides[0..1].Title = %q, %q, want both %q", slides[0].Title, slides[1].Title, "Combo") } if slides[0].Class != "center" || slides[1].Class != "center" { t.Errorf("slides[0..1].Class = %q, %q, want both %q", slides[0].Class, slides[1].Class, "center") } } func TestParseDir_NewSlideMarkerIgnoredInsideFencedCodeBlock(t *testing.T) { dir := t.TempDir() writeFiles(t, dir, map[string]string{ "010-doc.md": "# Doc\n\n```\n\n```\n", }) slides, err := ParseDir(dir) if err != nil { t.Fatalf("ParseDir() error = %v", err) } if len(slides) != 1 { t.Fatalf("len(slides) = %d, want 1 (marker inside fence must not split): %+v", len(slides), slides) } } func writeFiles(t *testing.T, dir string, files map[string]string) { t.Helper() for name, content := range files { path := filepath.Join(dir, name) if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { t.Fatalf("MkdirAll(%s) error = %v", filepath.Dir(path), err) } if err := os.WriteFile(path, []byte(content), 0o644); err != nil { t.Fatalf("WriteFile(%s) error = %v", path, err) } } } func equalStrings(a, b []string) bool { if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true }