You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
obsidian-markdown/lexer_test.go

443 lines
12 KiB
Go

package markdown_test
import (
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap/zapcore"
"code.ndumas.com/ndumas/obsidian-markdown"
)
var wikilinkWithEscapeCharacters = []tc{
{
name: "wikilink with escaped close link",
in: `[[wiki\]\]link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\]\]link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with partial escaped close link",
in: `[[wiki\]link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\]link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with escaped open link",
in: `[[wiki\[\[link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\[\[link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with partial escaped open link",
in: `[[wiki\[link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\[link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with escaped alias",
in: `[[wiki\|link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\|link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with escaped blockref",
in: `[[wiki\#\^link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\#\^link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with partial escaped blockref",
in: `[[wiki\^link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\^link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with escaped header",
in: `[[wiki\#link]]`,
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: `wiki\#link`},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
}
var singleWikilink = []tc{
{
name: "wikilink",
in: "[[wikilink]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink|display name",
in: "[[wikilink|display name]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "display name"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink|display name|second pipe",
in: "[[wikilink|display name|second pipe]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "display name"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "second pipe"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with numeric alias|420|second pipe",
in: "[[wikilink|420|second pipe]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "420"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "second pipe"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with spaces in filename",
in: "[[wikilink spaces]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink spaces"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "#heading",
in: "[[#heading]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: ""},
{Typ: markdown.LexHeading, Val: "#"},
{Typ: markdown.LexIdent, Val: "heading"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink#heading",
in: "[[wikilink#heading]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexHeading, Val: "#"},
{Typ: markdown.LexIdent, Val: "heading"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink#heading|display name",
in: "[[wikilink#heading|display name]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexHeading, Val: "#"},
{Typ: markdown.LexIdent, Val: "heading"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "display name"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink#heading|display name|second pipe",
in: "[[wikilink#heading|display name|second pipe]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexHeading, Val: "#"},
{Typ: markdown.LexIdent, Val: "heading"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "display name"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "second pipe"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with numeric aliases#heading|420|display name",
in: "[[wikilink#heading|420|second pipe]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexHeading, Val: "#"},
{Typ: markdown.LexIdent, Val: "heading"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "420"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "second pipe"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "#^blockRef",
in: "[[#^blockRef]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: ""},
{Typ: markdown.LexBlockRef, Val: "#^"},
{Typ: markdown.LexIdent, Val: "blockRef"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink#^blockRef",
in: "[[wikilink#^blockRef]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexBlockRef, Val: "#^"},
{Typ: markdown.LexIdent, Val: "blockRef"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink#^blockRef|display name",
in: "[[wikilink#^blockRef|display name]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexBlockRef, Val: "#^"},
{Typ: markdown.LexIdent, Val: "blockRef"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "display name"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink#^blockRef|display name|second pipe",
in: "[[wikilink#^blockRef|display name|second pipe]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexBlockRef, Val: "#^"},
{Typ: markdown.LexIdent, Val: "blockRef"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "display name"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "second pipe"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
{
name: "wikilink with numeric aliases#^blockRef|420|second pipe",
in: "[[wikilink#^blockRef|420|second pipe]]",
expected: []markdown.Lexeme{
{Typ: markdown.LexOpenLink, Val: "[["},
{Typ: markdown.LexIdent, Val: "wikilink"},
{Typ: markdown.LexBlockRef, Val: "#^"},
{Typ: markdown.LexIdent, Val: "blockRef"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "420"},
{Typ: markdown.LexAlias, Val: "|"},
{Typ: markdown.LexIdent, Val: "second pipe"},
{Typ: markdown.LexCloseLink, Val: "]]"},
},
},
}
func Test_ObsidianWikilinks_TextWithEscapeCharacters(t *testing.T) {
for _, tc := range singleWikilink {
tc.name = "escape characters preceding " + tc.name
mut, test := mutateTestCase(
tc,
`foo\[\[not a link, but this is`,
"",
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: `foo\[\[not a link, but this is`},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
)
t.Run(mut.name, test)
}
for _, tc := range singleWikilink {
tc.name = "escape characters following " + tc.name
mut, test := mutateTestCase(
tc,
"",
`foo\[\[not a link, but this is`,
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: `foo\[\[not a link, but this is`},
},
)
t.Run(mut.name, test)
}
}
func Test_ObsidianWikilinks_EscapeCharacters(t *testing.T) {
for _, tc := range wikilinkWithEscapeCharacters {
mut, test := mutateTestCase(
tc,
"",
"",
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
)
t.Run(mut.name, test)
}
}
func Test_ObsidianWikilinks_LinksEndOfMultiLineInput(t *testing.T) {
for _, tc := range singleWikilink {
mut, test := mutateTestCase(
tc,
" test data please ignore.\nbling blonk more lines\nbling blong\nthis is a",
"",
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: " test data please ignore.\n"},
{Typ: markdown.LexText, Val: "bling blonk more lines\n"},
{Typ: markdown.LexText, Val: "bling blong\n"},
{Typ: markdown.LexText, Val: "this is a"},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
)
t.Run(mut.name, test)
}
}
func Test_ObsidianWikilinks_LinksStartOfMultiLineInput(t *testing.T) {
for _, tc := range singleWikilink {
mut, test := mutateTestCase(
tc,
"",
" test data please ignore.\nbling blonk more lines\nbling blong\nthis is a",
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: " test data please ignore.\n"},
{Typ: markdown.LexText, Val: "bling blonk more lines\n"},
{Typ: markdown.LexText, Val: "bling blong\n"},
{Typ: markdown.LexText, Val: "this is a"},
},
)
t.Run(mut.name, test)
}
}
func Test_ObsidianWikilinks_LinksStartOfInput(t *testing.T) {
for _, tc := range singleWikilink {
mut, test := mutateTestCase(
tc,
"",
" test data please ignore",
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: " test data please ignore"},
},
)
t.Run(mut.name, test)
}
}
func Test_ObsidianWikilinks_LinksEndOfInput(t *testing.T) {
for _, tc := range singleWikilink {
mut, test := mutateTestCase(
tc,
"this is a ",
"",
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: "this is a "},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
)
t.Run(mut.name, test)
}
}
func Test_ObsidianWikilinks_Basic(t *testing.T) {
for _, tc := range singleWikilink {
mut, test := mutateTestCase(
tc,
"",
"",
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
[]markdown.Lexeme{
{Typ: markdown.LexText, Val: ""},
},
)
t.Run(mut.name, test)
}
}
type tc struct {
name string
in string
expected []markdown.Lexeme
}
func mutateTestCase(tc tc, prefix, suffix string, expectedPrefix, expectedSuffix []markdown.Lexeme) (tc, func(t *testing.T)) {
tc.in = prefix + tc.in
tc.in = tc.in + suffix
if expectedPrefix != nil {
tc.expected = append(expectedPrefix, tc.expected...)
}
if expectedSuffix != nil {
tc.expected = append(tc.expected, expectedSuffix...)
}
return tc, func(t *testing.T) {
l := markdown.Lex("testLexer", tc.in, zapcore.WarnLevel)
defer l.L.Sync()
assert.Equal(t, tc.expected, l.Items, "token stream mismatch")
}
}