package md_test import ( "testing" "gno.land/p/moul/md" ) func TestHelpers(t *testing.T) { tests := []struct { name string function func() string expected string }{ {"Bold", func() string { return md.Bold("foo") }, "**foo**"}, {"Italic", func() string { return md.Italic("foo") }, "*foo*"}, {"Strikethrough", func() string { return md.Strikethrough("foo") }, "~~foo~~"}, {"H1", func() string { return md.H1("foo") }, "# foo\n"}, {"HorizontalRule", md.HorizontalRule, "---\n"}, {"InlineCode", func() string { return md.InlineCode("foo") }, "`foo`"}, {"CodeBlock", func() string { return md.CodeBlock("foo") }, "```\nfoo\n```\n"}, {"LanguageCodeBlock", func() string { return md.LanguageCodeBlock("go", "foo") }, "```go\nfoo\n```\n"}, {"Link", func() string { return md.Link("foo", "http://example.com") }, "[foo](http://example.com)"}, {"UserLink", func() string { return md.UserLink("moul") }, "[@moul](/u/moul)"}, {"Image", func() string { return md.Image("foo", "http://example.com") }, "![foo](http://example.com)"}, {"InlineImageWithLink", func() string { return md.InlineImageWithLink("alt", "http://img.example.com/x.png", "http://link.example.com") }, "[![alt](http://img.example.com/x.png)](http://link.example.com)"}, {"FootnoteDefinition", func() string { return md.FootnoteDefinition("foo", "bar") }, "[^foo]:\n bar\n"}, {"LinkReferenceDefinition", func() string { return md.LinkReferenceDefinition("foo", "http://example.com", "") }, "\n\n[foo]: http://example.com\n\n"}, {"Paragraph", func() string { return md.Paragraph("foo") }, "foo\n\n"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.function() if result != tt.expected { t.Errorf("%s() = %q, want %q", tt.name, result, tt.expected) } }) } } func TestLists(t *testing.T) { t.Run("BulletList", func(t *testing.T) { items := []string{"foo", "bar"} expected := "- foo\n- bar\n" result := md.BulletList(items) if result != expected { t.Errorf("BulletList(%q) = %q, want %q", items, result, expected) } }) t.Run("OrderedList", func(t *testing.T) { items := []string{"foo", "bar"} expected := "1. foo\n2. bar\n" result := md.OrderedList(items) if result != expected { t.Errorf("OrderedList(%q) = %q, want %q", items, result, expected) } }) t.Run("TodoList", func(t *testing.T) { items := []string{"foo", "bar\nmore bar"} done := []bool{true, false} expected := "- [x] foo\n- [ ] bar\n more bar\n" result := md.TodoList(items, done) if result != expected { t.Errorf("TodoList(%q, %q) = %q, want %q", items, done, result, expected) } }) } func TestUserLink(t *testing.T) { tests := []struct { name string input string expected string }{ {"username", "moul", "[@moul](/u/moul)"}, // "g1blah" data part is too short for a bech32 address (min 6 // chars after "1"); UserLink validates as a username instead. {"short g1-prefixed string treated as username", "g1blah", "[@g1blah](/u/g1blah)"}, // "user_name" is a valid username (charset includes _ and -); // the validator returns it verbatim, so no markdown escape of _. {"username with underscore", "user_name", "[@user_name](/u/user_name)"}, // "g1abc123" has a 6-char data part — valid bech32 shape. {"address with 6-char data", "g1abc123", "[g1abc123](/u/g1abc123)"}, // invalid identifier (spaces, uppercase, etc.) → empty. {"rejected: spaces", "hello world", ""}, {"rejected: uppercase first char", "Alice", ""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := md.UserLink(tt.input) if result != tt.expected { t.Errorf("UserLink(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } func TestNested(t *testing.T) { t.Run("Nested Single Level", func(t *testing.T) { content := "- foo\n- bar" expected := " - foo\n - bar" result := md.Nested(content, " ") if result != expected { t.Errorf("Nested(%q) = %q, want %q", content, result, expected) } }) t.Run("Nested Double Level", func(t *testing.T) { content := " - foo\n - bar" expected := " - foo\n - bar" result := md.Nested(content, " ") if result != expected { t.Errorf("Nested(%q) = %q, want %q", content, result, expected) } }) } func TestColumns(t *testing.T) { tests := []struct { name string input []string padded bool expected string }{ { name: "no columns", input: []string{}, padded: false, expected: "", }, { name: "no columns padded", input: []string{}, padded: true, expected: "", }, { name: "one column", input: []string{"Column 1"}, padded: false, expected: ` Column 1 `, }, { name: "one column padded", input: []string{"Column 1"}, padded: true, expected: ` Column 1 `, }, { name: "two columns", input: []string{"Column 1", "Column 2"}, padded: false, expected: ` Column 1 Column 2 `, }, { name: "two columns padded", input: []string{"Column 1", "Column 2"}, padded: true, expected: ` Column 1 Column 2 `, }, { name: "four columns", input: []string{"A", "B", "C", "D"}, padded: false, expected: ` A B C D `, }, { name: "four columns padded", input: []string{"A", "B", "C", "D"}, padded: true, expected: ` A B C D `, }, { name: "more than four columns", input: []string{"1", "2", "3", "4", "5"}, padded: false, expected: ` 1 2 3 4 5 `, }, { name: "more than four columns padded", input: []string{"1", "2", "3", "4", "5"}, padded: true, expected: ` 1 2 3 4 5 `, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := md.Columns(tt.input, tt.padded) if result != tt.expected { t.Errorf("Columns(%v, %v) =\n%q\nwant:\n%q", tt.input, tt.padded, result, tt.expected) } }) } } func TestColumnsN(t *testing.T) { tests := []struct { name string content []string colsPerRow int padded bool expected string }{ { name: "empty input", content: []string{}, colsPerRow: 2, padded: false, expected: "", }, { name: "colsPerRow <= 0", content: []string{"A", "B", "C"}, colsPerRow: 0, padded: false, expected: ` A B C `, }, { name: "exact full row, no padding", content: []string{"A", "B"}, colsPerRow: 2, padded: false, expected: ` A B `, }, { name: "partial last row, no padding", content: []string{"A", "B", "C"}, colsPerRow: 2, padded: false, expected: ` A B C `, }, { name: "partial last row, with padding", content: []string{"A", "B", "C"}, colsPerRow: 2, padded: true, expected: ` A B C `, }, { name: "padded with more empty cells", content: []string{"X"}, colsPerRow: 3, padded: true, expected: ` X `, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := md.ColumnsN(tt.content, tt.colsPerRow, tt.padded) if result != tt.expected { t.Errorf("ColumnsN(%v, %d, %v) =\n%q\nwant:\n%q", tt.content, tt.colsPerRow, tt.padded, result, tt.expected) } }) } }