@@ -12,31 +12,25 @@ import (
12
12
)
13
13
14
14
type inlineParser struct {
15
- start []byte
16
- end []byte
15
+ trigger []byte
16
+ endBytesSingleDollar []byte
17
+ endBytesDoubleDollar []byte
18
+ endBytesBracket []byte
17
19
}
18
20
19
21
var defaultInlineDollarParser = & inlineParser {
20
- start : []byte {'$' },
21
- end : []byte {'$' },
22
- }
23
-
24
- var defaultDualDollarParser = & inlineParser {
25
- start : []byte {'$' , '$' },
26
- end : []byte {'$' , '$' },
22
+ trigger : []byte {'$' },
23
+ endBytesSingleDollar : []byte {'$' },
24
+ endBytesDoubleDollar : []byte {'$' , '$' },
27
25
}
28
26
29
27
func NewInlineDollarParser () parser.InlineParser {
30
28
return defaultInlineDollarParser
31
29
}
32
30
33
- func NewInlineDualDollarParser () parser.InlineParser {
34
- return defaultDualDollarParser
35
- }
36
-
37
31
var defaultInlineBracketParser = & inlineParser {
38
- start : []byte {'\\' , '(' },
39
- end : []byte {'\\' , ')' },
32
+ trigger : []byte {'\\' , '(' },
33
+ endBytesBracket : []byte {'\\' , ')' },
40
34
}
41
35
42
36
func NewInlineBracketParser () parser.InlineParser {
@@ -45,7 +39,7 @@ func NewInlineBracketParser() parser.InlineParser {
45
39
46
40
// Trigger triggers this parser on $ or \
47
41
func (parser * inlineParser ) Trigger () []byte {
48
- return parser .start
42
+ return parser .trigger
49
43
}
50
44
51
45
func isPunctuation (b byte ) bool {
@@ -64,33 +58,60 @@ func isAlphanumeric(b byte) bool {
64
58
func (parser * inlineParser ) Parse (parent ast.Node , block text.Reader , pc parser.Context ) ast.Node {
65
59
line , _ := block .PeekLine ()
66
60
67
- if ! bytes .HasPrefix (line , parser .start ) {
61
+ if ! bytes .HasPrefix (line , parser .trigger ) {
68
62
// We'll catch this one on the next time round
69
63
return nil
70
64
}
71
65
72
- precedingCharacter := block .PrecendingCharacter ()
73
- if precedingCharacter < 256 && (isAlphanumeric (byte (precedingCharacter )) || isPunctuation (byte (precedingCharacter ))) {
74
- // need to exclude things like `a$` from being considered a start
75
- return nil
66
+ var startMarkLen int
67
+ var stopMark []byte
68
+ checkSurrounding := true
69
+ if line [0 ] == '$' {
70
+ startMarkLen = 1
71
+ stopMark = parser .endBytesSingleDollar
72
+ if len (line ) > 1 {
73
+ if line [1 ] == '$' {
74
+ startMarkLen = 2
75
+ stopMark = parser .endBytesDoubleDollar
76
+ } else if line [1 ] == '`' {
77
+ pos := 1
78
+ for ; pos < len (line ) && line [pos ] == '`' ; pos ++ {
79
+ }
80
+ startMarkLen = pos
81
+ stopMark = bytes .Repeat ([]byte {'`' }, pos )
82
+ stopMark [len (stopMark )- 1 ] = '$'
83
+ checkSurrounding = false
84
+ }
85
+ }
86
+ } else {
87
+ startMarkLen = 2
88
+ stopMark = parser .endBytesBracket
89
+ }
90
+
91
+ if checkSurrounding {
92
+ precedingCharacter := block .PrecendingCharacter ()
93
+ if precedingCharacter < 256 && (isAlphanumeric (byte (precedingCharacter )) || isPunctuation (byte (precedingCharacter ))) {
94
+ // need to exclude things like `a$` from being considered a start
95
+ return nil
96
+ }
76
97
}
77
98
78
99
// move the opener marker point at the start of the text
79
- opener := len ( parser . start )
100
+ opener := startMarkLen
80
101
81
102
// Now look for an ending line
82
103
depth := 0
83
104
ender := - 1
84
105
for i := opener ; i < len (line ); i ++ {
85
- if depth == 0 && bytes .HasPrefix (line [i :], parser . end ) {
106
+ if depth == 0 && bytes .HasPrefix (line [i :], stopMark ) {
86
107
succeedingCharacter := byte (0 )
87
- if i + len (parser . end ) < len (line ) {
88
- succeedingCharacter = line [i + len (parser . end )]
108
+ if i + len (stopMark ) < len (line ) {
109
+ succeedingCharacter = line [i + len (stopMark )]
89
110
}
90
111
// check valid ending character
91
112
isValidEndingChar := isPunctuation (succeedingCharacter ) || isBracket (succeedingCharacter ) ||
92
113
succeedingCharacter == ' ' || succeedingCharacter == '\n' || succeedingCharacter == 0
93
- if ! isValidEndingChar {
114
+ if checkSurrounding && ! isValidEndingChar {
94
115
break
95
116
}
96
117
ender = i
@@ -112,21 +133,12 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser.
112
133
113
134
block .Advance (opener )
114
135
_ , pos := block .Position ()
115
- var node ast.Node
116
- if parser == defaultDualDollarParser {
117
- node = NewInlineBlock ()
118
- } else {
119
- node = NewInline ()
120
- }
136
+ node := NewInline ()
137
+
121
138
segment := pos .WithStop (pos .Start + ender - opener )
122
139
node .AppendChild (node , ast .NewRawTextSegment (segment ))
123
- block .Advance (ender - opener + len (parser .end ))
124
-
125
- if parser == defaultDualDollarParser {
126
- trimBlock (& (node .(* InlineBlock )).Inline , block )
127
- } else {
128
- trimBlock (node .(* Inline ), block )
129
- }
140
+ block .Advance (ender - opener + len (stopMark ))
141
+ trimBlock (node , block )
130
142
return node
131
143
}
132
144
0 commit comments