diff --git a/lexer.go b/lexer.go index eed8059..29b14fd 100644 --- a/lexer.go +++ b/lexer.go @@ -31,11 +31,12 @@ const ( ) const ( - OpenLink = "[[" - CloseLink = "]]" - Alias = "|" - Heading = "#" - BlockRef = "#^" + OpenLink = "[[" + CloseLink = "]]" + Alias = "|" + Heading = "#" + BlockRef = "#^" + EscapeChar = `\` ) func Lex(name, input string, level zapcore.Level) *Lexer { diff --git a/lexer_test.go b/lexer_test.go index 7f46a58..3191418 100644 --- a/lexer_test.go +++ b/lexer_test.go @@ -9,7 +9,19 @@ import ( "code.ndumas.com/ndumas/obsidian-markdown" ) -var SingleWikilink = []tc{ +var wikilinkWithEscapeCharacters = []tc{ + { + name: "wikilink", + 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]]", @@ -197,8 +209,25 @@ var SingleWikilink = []tc{ }, } +func Test_ObsidianWikilinks_LinksWithEscapeCharacters(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 { + for _, tc := range singleWikilink { mut, test := mutateTestCase( tc, " test data please ignore.\nbling blonk more lines\nbling blong\nthis is a", @@ -219,7 +248,7 @@ func Test_ObsidianWikilinks_LinksEndOfMultiLineInput(t *testing.T) { } func Test_ObsidianWikilinks_LinksStartOfMultiLineInput(t *testing.T) { - for _, tc := range SingleWikilink { + for _, tc := range singleWikilink { mut, test := mutateTestCase( tc, "", @@ -240,7 +269,7 @@ func Test_ObsidianWikilinks_LinksStartOfMultiLineInput(t *testing.T) { } func Test_ObsidianWikilinks_LinksStartOfInput(t *testing.T) { - for _, tc := range SingleWikilink { + for _, tc := range singleWikilink { mut, test := mutateTestCase( tc, "", @@ -258,7 +287,7 @@ func Test_ObsidianWikilinks_LinksStartOfInput(t *testing.T) { } func Test_ObsidianWikilinks_LinksEndOfInput(t *testing.T) { - for _, tc := range SingleWikilink { + for _, tc := range singleWikilink { mut, test := mutateTestCase( tc, "this is a ", @@ -276,7 +305,7 @@ func Test_ObsidianWikilinks_LinksEndOfInput(t *testing.T) { func Test_ObsidianWikilinks_Basic(t *testing.T) { - for _, tc := range SingleWikilink { + for _, tc := range singleWikilink { mut, test := mutateTestCase( tc, "", diff --git a/states.go b/states.go index 29a27d4..a8566e9 100644 --- a/states.go +++ b/states.go @@ -26,15 +26,19 @@ func isBlockRef(s string) bool { return strings.HasPrefix(s, BlockRef) } +func isEscape(s string) bool { + return strings.HasPrefix(s, EscapeChar) +} + func lexIdent(l *Lexer) stateFn { + L := l.L.Named("lexIdent") for { - L := l.L.Named("lexIdent") s := l.input[l.GetPos():] L.Debug("stepping through lexIdent") - if s[0] == '\\' { // i think this will handle escape characters? - break - } switch { + case isEscape(s): + l.next() + continue case isCloseLink(s): L.Debug("found CloseLink") l.emit(LexIdent) @@ -85,10 +89,17 @@ func lexAlias(l *Lexer) stateFn { func lexText(l *Lexer) stateFn { L := l.L.Named("lexText") for { - if isOpenLink(l.input[l.GetPos():]) { + s := l.input[l.GetPos():] + L.Debug("stepping through lexText") + switch { + case isEscape(s): + l.next() + continue + case isOpenLink(s): L.Debug("found openLink") l.emit(LexText) return lexOpenLink + } r := l.next() switch {