1
1
package parser
2
2
3
3
import (
4
- "slices"
5
-
6
4
"github.com/usememos/gomark/ast"
7
5
"github.com/usememos/gomark/parser/tokenizer"
8
6
)
@@ -55,7 +53,9 @@ func ParseBlockWithParsers(tokens []*tokenizer.Token, blockParsers []BlockParser
55
53
}
56
54
}
57
55
}
58
- return mergeListItemNodes (nodes ), nil
56
+
57
+ nodes = mergeListItemNodes (nodes )
58
+ return nodes , nil
59
59
}
60
60
61
61
var defaultInlineParsers = []InlineParser {
@@ -101,81 +101,59 @@ func ParseInlineWithParsers(tokens []*tokenizer.Token, inlineParsers []InlinePar
101
101
}
102
102
103
103
func mergeListItemNodes (nodes []ast.Node ) []ast.Node {
104
- if len (nodes ) == 0 {
105
- return nodes
106
- }
107
- result := []ast.Node {}
108
- for i := 0 ; i < len (nodes ); i ++ {
109
- var prevNode , nextNode , prevResultNode ast.Node
110
- if i > 0 {
111
- prevNode = nodes [i - 1 ]
112
- }
113
- if i < len (nodes )- 1 {
114
- nextNode = nodes [i + 1 ]
115
- }
116
- if len (result ) > 0 {
117
- prevResultNode = result [len (result )- 1 ]
118
- }
119
- switch nodes [i ].(type ) {
120
- case * ast.OrderedListItem , * ast.UnorderedListItem , * ast.TaskListItem :
121
- var listKind ast.ListKind
122
- var indent int
123
- switch item := nodes [i ].(type ) {
124
- case * ast.OrderedListItem :
125
- listKind = ast .OrderedList
126
- indent = item .Indent
127
- case * ast.UnorderedListItem :
128
- listKind = ast .UnorderedList
129
- indent = item .Indent
130
- case * ast.TaskListItem :
131
- listKind = ast .DescrpitionList
132
- indent = item .Indent
104
+ var result []ast.Node
105
+ var stack []* ast.List
106
+
107
+ for _ , node := range nodes {
108
+ nodeType := node .Type ()
109
+
110
+ // Handle line breaks.
111
+ if nodeType == ast .LineBreakNode {
112
+ // If the stack is not empty and the last node is a list node, add the line break to the list.
113
+ if len (stack ) > 0 && len (result ) > 0 && result [len (result )- 1 ].Type () == ast .ListNode {
114
+ stack [len (stack )- 1 ].Children = append (stack [len (stack )- 1 ].Children , node )
115
+ } else {
116
+ result = append (result , node )
133
117
}
118
+ continue
119
+ }
134
120
135
- indent /= 2
136
- if prevResultNode == nil || prevResultNode .Type () != ast .ListNode || prevResultNode .(* ast.List ).Kind != listKind || prevResultNode .(* ast.List ).Indent > indent {
137
- prevResultNode = & ast.List {
138
- BaseBlock : ast.BaseBlock {},
139
- Kind : listKind ,
140
- Indent : indent ,
141
- Children : []ast.Node {nodes [i ]},
121
+ if ast .IsListItemNode (node ) {
122
+ itemKind , itemIndent := ast .GetListItemKindAndIndent (node )
123
+
124
+ // Create a new List node if the stack is empty or the current item should be a child of the last item.
125
+ if len (stack ) == 0 || (itemKind != stack [len (stack )- 1 ].Kind || itemIndent > stack [len (stack )- 1 ].Indent ) {
126
+ newList := & ast.List {
127
+ Kind : itemKind ,
128
+ Indent : itemIndent ,
129
+ Children : []ast.Node {node },
142
130
}
143
- result = append (result , prevResultNode )
144
- continue
145
- }
146
131
147
- listNode , ok := prevResultNode .(* ast.List )
148
- if ! ok {
149
- continue
150
- }
151
- if listNode .Indent != indent {
152
- parent := findListPossibleParent (listNode , indent )
153
- if parent == nil {
154
- parent = & ast.List {
155
- BaseBlock : ast.BaseBlock {},
156
- Kind : listKind ,
157
- Indent : indent ,
158
- }
159
- listNode .Children = append (listNode .Children , parent )
132
+ // Add the new List node to the stack or the result.
133
+ if len (stack ) > 0 && itemIndent > stack [len (stack )- 1 ].Indent {
134
+ stack [len (stack )- 1 ].Children = append (stack [len (stack )- 1 ].Children , newList )
135
+ } else {
136
+ result = append (result , newList )
160
137
}
161
- parent . Children = append (parent . Children , nodes [ i ] )
138
+ stack = append (stack , newList )
162
139
} else {
163
- listNode . Children = append ( listNode . Children , nodes [ i ])
164
- }
165
- case * ast. LineBreak :
166
- if prevResultNode != nil && prevResultNode . Type () == ast . ListNode &&
167
- // Check if the prev node is not a line break node.
168
- ( prevNode == nil || prevNode . Type () != ast . LineBreakNode ) &&
169
- // Check if the next node is a list item node.
170
- ( nextNode == nil || slices . Contains ([]ast. NodeType { ast . OrderedListItemNode , ast . UnorderedListItemNode , ast . TaskListItemNode }, nextNode . Type ())) {
171
- prevResultNode .( * ast. List ). Children = append ( prevResultNode .( * ast. List ). Children , nodes [ i ])
172
- } else {
173
- result = append ( result , nodes [ i ])
140
+ // Pop the stack until the current item should be a sibling of the last item.
141
+ for len ( stack ) > 0 && ( itemKind != stack [ len ( stack ) - 1 ]. Kind || itemIndent < stack [ len ( stack ) - 1 ]. Indent ) {
142
+ stack = stack [: len ( stack ) - 1 ]
143
+ }
144
+
145
+ // Add the current item to the last List node in the stack or the result.
146
+ if len ( stack ) > 0 {
147
+ stack [ len ( stack ) - 1 ]. Children = append ( stack [ len ( stack ) - 1 ]. Children , node )
148
+ } else {
149
+ result = append ( result , node )
150
+ }
174
151
}
175
- default :
176
- result = append (result , nodes [ i ] )
152
+ } else {
153
+ result = append (result , node )
177
154
}
178
155
}
156
+
179
157
return result
180
158
}
181
159
@@ -193,20 +171,3 @@ func mergeTextNodes(nodes []ast.Node) []ast.Node {
193
171
}
194
172
return result
195
173
}
196
-
197
- func findListPossibleParent (listNode * ast.List , indent int ) * ast.List {
198
- if listNode .Indent == indent {
199
- return listNode
200
- }
201
- if listNode .Indent < indent {
202
- return nil
203
- }
204
- if len (listNode .Children ) == 0 {
205
- return nil
206
- }
207
- lastChild := listNode .Children [len (listNode .Children )- 1 ]
208
- if lastChild .Type () != ast .ListNode {
209
- return nil
210
- }
211
- return findListPossibleParent (lastChild .(* ast.List ), indent )
212
- }
0 commit comments