Skip to content

Commit fa91739

Browse files
authored
Merge pull request #100 from DongyuZhao/copilot/fix-72f8db3b-ef02-4174-9cf9-ef4bf1e447be
Implement enhanced list builder with AST traversal and context-aware indentation handling
2 parents 0536404 + 65abdfb commit fa91739

File tree

8 files changed

+1052
-496
lines changed

8 files changed

+1052
-496
lines changed

Sources/CodeParserCollection/Markdown/MarkdownConstructState.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public class MarkdownConstructState: CodeConstructState {
2222
/// Stack for nested list processing
2323
public var listStack: [ListNode] = []
2424
public var currentDefinitionList: DefinitionListNode?
25+
26+
/// Enhanced list context tracking for better indentation and nesting management
27+
public var listContextStack: [ListContextInfo] = []
2528

2629
/// Indicates the last consumed line break formed a blank line (two or more consecutive newlines)
2730
public var lastWasBlankLine: Bool = false
@@ -129,3 +132,25 @@ public struct HTMLBlockTypeInfo {
129132
self.endCondition = endCondition
130133
}
131134
}
135+
136+
/// Enhanced list context information for better nesting and indentation management
137+
public struct ListContextInfo {
138+
/// The list node itself
139+
public let list: ListNode
140+
/// The parent list item that contains this list (nil for top-level lists)
141+
public let parentListItem: ListItemNode?
142+
/// The calculated indentation level for content in this list context
143+
public let contentIndent: Int
144+
/// The nesting level (1 for top-level, 2 for first nested, etc.)
145+
public let level: Int
146+
/// The marker type for compatibility checking
147+
public let markerType: String
148+
149+
public init(list: ListNode, parentListItem: ListItemNode?, contentIndent: Int, level: Int, markerType: String) {
150+
self.list = list
151+
self.parentListItem = parentListItem
152+
self.contentIndent = contentIndent
153+
self.level = level
154+
self.markerType = markerType
155+
}
156+
}

Sources/CodeParserCollection/Markdown/Nodes/MarkdownBlockBuilder.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ public class MarkdownBlockBuilder: CodeNodeBuilder {
2323
let rules: [BlockRule] = [
2424
// Open containers first (strip markers, reprocess line)
2525
.init(builder: MarkdownBlockQuoteBuilder(), phase: .openContainer, priority: 10),
26-
.init(builder: MarkdownListBuilder(), phase: .openContainer, priority: 20),
27-
.init(builder: MarkdownListItemBuilder(), phase: .openContainer, priority: 30),
26+
.init(builder: MarkdownUnifiedListBuilder(), phase: .openContainer, priority: 20),
2827

2928
// Leaf on line
3029
.init(builder: MarkdownEOFBuilder(), phase: .leafOnLine, priority: 0),
3130
.init(builder: MarkdownReferenceLinkDefinitionBuilder(), phase: .leafOnLine, priority: 5),
3231
.init(builder: MarkdownFencedCodeBlockBuilder(), phase: .leafOnLine, priority: 10),
3332
.init(builder: MarkdownATXHeadingBuilder(), phase: .leafOnLine, priority: 20),
3433
.init(builder: MarkdownThematicBreakBuilder(), phase: .leafOnLine, priority: 30),
34+
.init(builder: MarkdownSetextHeadingBuilder(), phase: .leafOnLine, priority: 32),
3535
.init(builder: MarkdownHTMLBlockBuilder(), phase: .leafOnLine, priority: 35),
3636
.init(builder: MarkdownIndentedCodeBlockBuilder(), phase: .leafOnLine, priority: 40),
3737
.init(builder: MarkdownParagraphBuilder(), phase: .leafOnLine, priority: 1000), // fallback
@@ -126,8 +126,11 @@ public class MarkdownBlockBuilder: CodeNodeBuilder {
126126
if phase == .openContainer {
127127
// Continue to next phase without returning; break out of builder loop
128128
break
129+
} else if phase == .leafOnLine {
130+
// For leafOnLine phase, allow proceeding to postParagraph phase
131+
break
129132
} else {
130-
// For leaf/post phases, we're done with this line
133+
// For postParagraph phase, we're done with this line
131134
return
132135
}
133136
}

Sources/CodeParserCollection/Markdown/Nodes/MarkdownIndentedCodeBlockBuilder.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ public class MarkdownIndentedCodeBlockBuilder: CodeNodeBuilder {
7171
if context.current.element == .paragraph {
7272
return false
7373
}
74+
75+
// Check if we're in a list item context - indented content should be treated as list continuation
76+
// rather than code block if the indentation matches list item requirements
77+
if let listItem = findContainingListItem(context.current) {
78+
// If the indentation is exactly what's needed for list item continuation,
79+
// don't create a code block - let list continuation handle it
80+
if indentationSpaces < listItem.contentIndent + 4 {
81+
return false
82+
}
83+
}
7484

7585
// If we reached end of tokens, this is just indented whitespace - not a code block
7686
guard index < context.tokens.count else {
@@ -131,4 +141,15 @@ public class MarkdownIndentedCodeBlockBuilder: CodeNodeBuilder {
131141

132142
return true
133143
}
144+
145+
private func findContainingListItem(_ node: CodeNode<MarkdownNodeElement>) -> ListItemNode? {
146+
var current: CodeNode<MarkdownNodeElement>? = node
147+
while let n = current {
148+
if let listItem = n as? ListItemNode {
149+
return listItem
150+
}
151+
current = n.parent
152+
}
153+
return nil
154+
}
134155
}

Sources/CodeParserCollection/Markdown/Nodes/MarkdownListBuilder.swift

Lines changed: 0 additions & 129 deletions
This file was deleted.

0 commit comments

Comments
 (0)