in Sources/Markdown/Parser/BlockDirectiveParser.swift [592:657]
func convertToRawMarkup(ranges: inout RangeTracker,
parent: ParseContainer?,
options: ParseOptions) -> [RawMarkup] {
switch self {
case let .root(children):
let rawChildren = children.flatMap {
$0.convertToRawMarkup(ranges: &ranges, parent: self, options: options)
}
return [.document(parsedRange: ranges.totalRange, rawChildren)]
case let .lineRun(lines, _):
// Get the maximum number of initial indentation characters to remove from the start
// of each of these `lines` from the first sibling under `parent` (which could be `self`).
let indentationColumnCount = indentationAdjustment(under: parent)
// Trim up to that number of whitespace characters off.
// We need to keep track of what we removed because cmark will report different source locations than what we
// had in the source. We'll adjust those when we get them back.
let trimmedIndentationAndLines = lines.map { line -> (line: TrimmedLine,
indentation: TrimmedLine.Lex?) in
var trimmedLine = line
let trimmedWhitespace = trimmedLine.lexWhitespace(maxLength: indentationColumnCount)
return (trimmedLine, trimmedWhitespace)
}
// Build the logical block of text that cmark will see.
let logicalText = trimmedIndentationAndLines
.map { $0.line.text }
.joined(separator: "\n")
// Ask cmark to parse it. Now we have a Markdown `Document` consisting
// of the contents of this line run.
let parsedSubdocument = MarkupParser.parseString(logicalText, source: lines.first?.source, options: options)
// Now, we'll adjust the columns of all of the source positions as
// needed to offset that indentation trimming we did above.
// Note that the child identifiers under this document will start at
// 0, so we will need to adjust those as well, because child identifiers
// start at 0 from the `root`.
var columnAdjuster = RangeAdjuster(startLine: lines.first?.lineNumber ?? 1,
ranges: ranges,
trimmedIndentationPerLine: trimmedIndentationAndLines.map { $0.indentation })
for child in parsedSubdocument.children {
columnAdjuster.visit(child)
}
// Write back the adjusted ranges.
ranges = columnAdjuster.ranges
return parsedSubdocument.children.map { $0.raw.markup }
case let .blockDirective(pendingBlockDirective, children):
let range = pendingBlockDirective.atLocation..<pendingBlockDirective.endLocation
ranges.add(range)
let children = children.flatMap {
$0.convertToRawMarkup(ranges: &ranges, parent: self, options: options)
}
return [.blockDirective(name: String(pendingBlockDirective.name),
nameLocation: pendingBlockDirective.atLocation,
argumentText: DirectiveArgumentText(segments: pendingBlockDirective.argumentsText.map {
let untrimmedText = String($0.text.base[$0.text.base.startIndex..<$0.text.endIndex])
return DirectiveArgumentText.LineSegment(untrimmedText: untrimmedText, lineStartIndex: untrimmedText.startIndex, parseIndex: $0.text.startIndex, range: $0.range)
}),
parsedRange: pendingBlockDirective.atLocation..<pendingBlockDirective.endLocation,
children)]
}
}