MarkdownParser is the main class for converting markdown text into a structured abstract syntax tree (AST). It uses cmark-gfm under the hood and supports GitHub Flavored Markdown extensions including tables, task lists, and strikethrough.
Initialization
Creates a new markdown parser instance.
let parser = MarkdownParser()
Methods
parse()
Parses markdown text into a complete document AST.
public func parse(_ markdown: String) -> ParseResult
The markdown text to parse
Contains the parsed document nodes and math context mappingArray of root-level block nodes representing the document structure
Dictionary mapping math replacement identifiers to their original LaTeX content
Example
let parser = MarkdownParser()
let result = parser.parse("# Hello World\n\nThis is **bold** text.")
print(result.document) // [.heading(level: 1, ...), .paragraph(...)]
parseIncremental()
Performs incremental parsing by reusing previously parsed blocks when possible. This is optimized for real-time editing scenarios where only the end of the document changes.
public func parseIncremental(
previousMarkdown: String,
newMarkdown: String,
previousBlocks: [MarkdownBlockNode],
previousRanges: [RootBlockRange]? = nil
) -> IncrementalParseResult?
The previous version of the markdown text
The new version of the markdown text (must be longer than previous)
previousBlocks
[MarkdownBlockNode]
required
The previously parsed block nodes from the previous markdown
previousRanges
[RootBlockRange]?
default:"nil"
Optional cached ranges from previous parsing. If nil, they will be computed.
Returns nil if incremental parsing is not applicable, otherwise returns the incremental resultNumber of blocks from the previous parse that remain unchanged
Parse result for the changed portion of the document
Updated block ranges for all blocks in the new document
Example
let parser = MarkdownParser()
let initialText = "# Title\n\nParagraph 1"
let initialResult = parser.parse(initialText)
let newText = "# Title\n\nParagraph 1\n\nParagraph 2"
if let incrementalResult = parser.parseIncremental(
previousMarkdown: initialText,
newMarkdown: newText,
previousBlocks: initialResult.document
) {
// Reuse first N blocks, append tail
let updatedBlocks = Array(initialResult.document.prefix(incrementalResult.stablePrefixBlockCount))
+ incrementalResult.tailResult.document
}
parseBlockRange()
Computes the source range of each root-level block in the markdown document without performing full parsing.
public func parseBlockRange(_ markdown: String) -> [RootBlockRange]
The markdown text to analyze
Array of range information for each root blockThe type of the block node
Starting position in the source text
Ending position in the source text
Number of blocks this root node will produce after transformation
Example
let parser = MarkdownParser()
let ranges = parser.parseBlockRange("# Heading\n\nParagraph")
for range in ranges {
print("Block type: \(range.type), outputs \(range.outputBlockCount) blocks")
}
Types
ParseResult
public struct ParseResult {
public let document: [MarkdownBlockNode]
public let mathContext: [Int: String]
}
The result of parsing markdown text.
IncrementalParseResult
public struct IncrementalParseResult {
public let stablePrefixBlockCount: Int
public let tailResult: ParseResult
public let blockRanges: [RootBlockRange]
}
The result of incremental parsing.
RootBlockRange
public struct RootBlockRange {
public let type: MarkdownNodeType
public let startIndex: String.Index
public let endIndex: String.Index
public let outputBlockCount: Int
}
Describes the source location and output characteristics of a root block.