Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions DiscordMarkdownParser/Sources/DiscordMarkdownParser/AST.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public enum AST {
public let children: [ASTNode]
public let sourceLocation: SourceLocation?

/// Heading level (1-6)
/// Heading level (1-3)
public let level: Int

public init(
Expand Down Expand Up @@ -177,18 +177,23 @@ public enum AST {

/// Starting number for ordered lists
public let startNumber: Int?

/// Nesting level
public let level: Int

/// List items
public let items: [ASTNode]

public init(
isOrdered: Bool,
startNumber: Int? = nil,
level: Int,
items: [ASTNode],
sourceLocation: SourceLocation? = nil
) {
self.isOrdered = isOrdered
self.startNumber = startNumber
self.level = level
self.items = items
self.sourceLocation = sourceLocation
self.children = items
Expand All @@ -200,8 +205,12 @@ public enum AST {
public let nodeType: ASTNodeType = .listItem
public let children: [ASTNode]
public let sourceLocation: SourceLocation?

/// Number of the item in the ordered list
public let listNumber: Int?

public init(children: [ASTNode], sourceLocation: SourceLocation? = nil) {
public init(itemNumber: Int? = nil, children: [ASTNode], sourceLocation: SourceLocation? = nil) {
self.listNumber = itemNumber
self.children = children
self.sourceLocation = sourceLocation
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,22 +428,29 @@ public final class BlockParser {

// MARK: - List Parsers

private func parseList() throws -> AST.ListNode {
private func parseList(_ indentationLevel: Int = 0) throws -> AST.ListNode {
let startLocation = tokenStream.current.location
let firstMarker = tokenStream.current.content

let isOrdered = firstMarker.last == "." || firstMarker.last == ")"
let isOrdered = firstMarker.last == "."
let startNumber = isOrdered ? Int(firstMarker.dropLast()) : nil
let delimiter = isOrdered ? firstMarker.last : nil
let bulletChar = isOrdered ? nil : firstMarker.first

var items: [ASTNode] = []

var whitespaceCount = 0
var itemNumber = startNumber
while !tokenStream.isAtEnd && tokenStream.check(.listMarker) {
let level = whitespaceCount / 2
if whitespaceCount != 0 && level < indentationLevel {
print(tokenStream.current.content)
break
}
let marker = tokenStream.current.content

// Check if this marker matches the list type
let markerIsOrdered = marker.last == "." || marker.last == ")"
let markerIsOrdered = marker.last == "."
if markerIsOrdered != isOrdered {
break
}
Expand All @@ -459,21 +466,31 @@ public final class BlockParser {
}

// Parse list item
let item = try parseListItem()
var item: ASTNode
if whitespaceCount > 0 && level != indentationLevel {
item = try parseList(indentationLevel == level ? indentationLevel : indentationLevel + 1)
} else {
item = try parseListItem(itemNumber)
}
items.append(item)

if isOrdered {
itemNumber! += 1
}

skipWhitespaceAndNewlines()
whitespaceCount = skipWhitespaceAndNewlines()
}

return AST.ListNode(
isOrdered: isOrdered,
startNumber: startNumber,
level: indentationLevel,
items: items,
sourceLocation: startLocation
)
}

private func parseListItem() throws -> AST.ListItemNode {
private func parseListItem(_ itemNumber: Int?) throws -> AST.ListItemNode {
let startLocation = tokenStream.current.location

// Consume list marker
Expand Down Expand Up @@ -525,7 +542,7 @@ public final class BlockParser {
}
}

return AST.ListItemNode(children: children, sourceLocation: startLocation)
return AST.ListItemNode(itemNumber: itemNumber, children: children, sourceLocation: startLocation)
}

private func isNextListItem() -> Bool {
Expand Down Expand Up @@ -859,9 +876,14 @@ public final class BlockParser {
}
}

private func skipWhitespaceAndNewlines() {
private func skipWhitespaceAndNewlines() -> Int {
var count: Int = 0
while tokenStream.check(.whitespace) || tokenStream.check(.newline) {
if tokenStream.check(.whitespace) {
count += tokenStream.current.length
}
tokenStream.advance()
}
return count
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public enum CommonMarkUtils {
// Must be followed by . or )
guard index < trimmed.endIndex else { return nil }
let delimiter = trimmed[index]
guard delimiter == "." || delimiter == ")" else { return nil }
guard delimiter == "." else { return nil }

index = trimmed.index(after: index)

Expand Down Expand Up @@ -242,7 +242,7 @@ public struct ListMarkerInfo: Sendable, Equatable {
/// The number for ordered lists
public let number: Int?

/// The delimiter for ordered lists ('.' or ')')
/// The delimiter for ordered lists ('.')
public let delimiter: Character?

/// The width of the marker in characters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ public final class DiscordMarkdownParser: Sendable {
return AST.ListNode(
isOrdered: list.isOrdered,
startNumber: list.startNumber,
level: list.level,
items: processedItems,
sourceLocation: list.sourceLocation
)
Expand All @@ -279,6 +280,7 @@ public final class DiscordMarkdownParser: Sendable {
)

return AST.ListItemNode(
itemNumber: listItem.listNumber,
children: processedChildren,
sourceLocation: listItem.sourceLocation
)
Expand Down Expand Up @@ -480,6 +482,7 @@ public final class DiscordMarkdownParser: Sendable {
case .listItem:
if let listItemNode = originalNode as? AST.ListItemNode {
return AST.ListItemNode(
itemNumber: listItemNode.listNumber,
children: children,
sourceLocation: listItemNode.sourceLocation
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ public final class MarkdownTokenizer {
let startLocation = currentLocation
var content = ""

while !isAtEnd && currentChar == "#" && content.count < 6 {
while !isAtEnd && currentChar == "#" && content.count < 3 {
content.append(currentChar)
advance()
}
Expand Down
Loading
Loading