5
5
package math
6
6
7
7
import (
8
+ "bytes"
9
+
8
10
"github.com/yuin/goldmark/ast"
9
11
"github.com/yuin/goldmark/parser"
10
12
"github.com/yuin/goldmark/text"
@@ -15,13 +17,6 @@ type blockParser struct {
15
17
parseDollars bool
16
18
}
17
19
18
- type blockData struct {
19
- dollars bool
20
- indent int
21
- }
22
-
23
- var blockInfoKey = parser .NewContextKey ()
24
-
25
20
// NewBlockParser creates a new math BlockParser
26
21
func NewBlockParser (parseDollarBlocks bool ) parser.BlockParser {
27
22
return & blockParser {
@@ -31,7 +26,7 @@ func NewBlockParser(parseDollarBlocks bool) parser.BlockParser {
31
26
32
27
// Open parses the current line and returns a result of parsing.
33
28
func (b * blockParser ) Open (parent ast.Node , reader text.Reader , pc parser.Context ) (ast.Node , parser.State ) {
34
- line , _ := reader .PeekLine ()
29
+ line , segment := reader .PeekLine ()
35
30
pos := pc .BlockOffset ()
36
31
if pos == - 1 || len (line [pos :]) < 2 {
37
32
return nil , parser .NoChildren
@@ -44,33 +39,57 @@ func (b *blockParser) Open(parent ast.Node, reader text.Reader, pc parser.Contex
44
39
return nil , parser .NoChildren
45
40
}
46
41
47
- pc .Set (blockInfoKey , & blockData {dollars : dollars , indent : pos })
48
- node := NewBlock ()
42
+ node := NewBlock (dollars , pos )
43
+
44
+ // Now we need to check if the ending block is on the segment...
45
+ endBytes := []byte {'\\' , ']' }
46
+ if dollars {
47
+ endBytes = []byte {'$' , '$' }
48
+ }
49
+ idx := bytes .Index (line [pos + 2 :], endBytes )
50
+ if idx >= 0 {
51
+ segment .Stop = segment .Start + idx + 2
52
+ reader .Advance (segment .Len () - 1 )
53
+ segment .Start += 2
54
+ node .Lines ().Append (segment )
55
+ node .Closed = true
56
+ return node , parser .Close | parser .NoChildren
57
+ }
58
+
59
+ reader .Advance (segment .Len () - 1 )
60
+ segment .Start += 2
61
+ node .Lines ().Append (segment )
49
62
return node , parser .NoChildren
50
63
}
51
64
52
65
// Continue parses the current line and returns a result of parsing.
53
66
func (b * blockParser ) Continue (node ast.Node , reader text.Reader , pc parser.Context ) parser.State {
67
+ block := node .(* Block )
68
+ if block .Closed {
69
+ return parser .Close
70
+ }
71
+
54
72
line , segment := reader .PeekLine ()
55
- data := pc .Get (blockInfoKey ).(* blockData )
56
73
w , pos := util .IndentWidth (line , 0 )
57
74
if w < 4 {
58
- if data . dollars {
75
+ if block . Dollars {
59
76
i := pos
60
77
for ; i < len (line ) && line [i ] == '$' ; i ++ {
61
78
}
62
79
length := i - pos
63
80
if length >= 2 && util .IsBlank (line [i :]) {
64
81
reader .Advance (segment .Stop - segment .Start - segment .Padding )
82
+ block .Closed = true
65
83
return parser .Close
66
84
}
67
85
} else if len (line [pos :]) > 1 && line [pos ] == '\\' && line [pos + 1 ] == ']' && util .IsBlank (line [pos + 2 :]) {
68
86
reader .Advance (segment .Stop - segment .Start - segment .Padding )
87
+ block .Closed = true
69
88
return parser .Close
70
89
}
71
90
}
72
91
73
- pos , padding := util .IndentPosition (line , 0 , data . indent )
92
+ pos , padding := util .IndentPosition (line , 0 , block . Indent )
74
93
seg := text .NewSegmentPadding (segment .Start + pos , segment .Stop , padding )
75
94
node .Lines ().Append (seg )
76
95
reader .AdvanceAndSetPadding (segment .Stop - segment .Start - pos - 1 , padding )
@@ -79,7 +98,7 @@ func (b *blockParser) Continue(node ast.Node, reader text.Reader, pc parser.Cont
79
98
80
99
// Close will be called when the parser returns Close.
81
100
func (b * blockParser ) Close (node ast.Node , reader text.Reader , pc parser.Context ) {
82
- pc . Set ( blockInfoKey , nil )
101
+ // noop
83
102
}
84
103
85
104
// CanInterruptParagraph returns true if the parser can interrupt paragraphs,
0 commit comments