Skip to content
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,14 @@ The renderer targets the subset of CommonMark + GitHub-flavored Markdown that LL
- [x] Inline LaTeX math via `\( … \)`
- [x] Display LaTeX math via `$$ … $$`
- [x] Inline citation pills
- [x] Inline HTML formatting tags — `<br>`, `<b>`/`<strong>`, `<i>`/`<em>`, `<s>`/`<del>`/`<strike>`, `<u>`/`<ins>`, `<mark>`, `<sub>`/`<sup>`, `<code>`/`<kbd>`/`<samp>`/`<tt>`, `<a href>`, `<wbr>` (comments are dropped; unsupported or unmatched tags render as literal text)
- [x] Highlight (`==text==`)

### Not yet supported

- [ ] Footnotes (`[^1]`)
- [ ] Highlight (`==text==`), superscript (`^x^`), subscript (`~x~`)
- [ ] Raw HTML (`<details>`, `<kbd>`, `<aside>`, …) — kept inline as text
- [ ] Superscript (`^x^`), subscript (`~x~`)
- [ ] Block-level raw HTML (`<details>`, `<aside>`, …) — kept inline as text
- [ ] GitHub alerts (`> [!NOTE]`) — rendered as plain block quotes
- [ ] Container directives (`::: warning … :::`) and admonitions (`!!! note`)
- [ ] Mermaid / PlantUML diagrams — rendered as fenced code
Expand Down
45 changes: 45 additions & 0 deletions Sources/MarkdownText/Inline/Markdown+InlineConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,51 @@ extension Markdown.InlineCode: InlineConvertible {
}
}

extension Markdown.InlineAttributes: InlineConvertible {

/// Attribute keys this renderer understands inside `attributes`. Produced by
/// `InlineHTMLRewriter` for tags that have no dedicated Markdown node
/// (`<u>`/`<ins>`, `<mark>`, `<sub>`, `<sup>`).
private static let enabledKeyRegex = try? Regex(#"(?:^|[,{}\s])([a-zA-Z]+)\s*:\s*true\b"#)

private var enabledKeys: Set<String> {
guard let regex = Self.enabledKeyRegex else { return [] }
var keys = Set<String>()
for match in attributes.matches(of: regex) {
if let key = match.output[1].substring {
keys.insert(String(key))
}
}
return keys
}

func convert(attributeContainer: NSAttributeContainer, config: MarkdownRenderConfig) -> NSMutableAttributedString {
var container = attributeContainer
let font = attributeContainer[.font] as? MDFont ?? config.paragraphStyle.textFonts.normal
let keys = enabledKeys
if keys.contains("subscript") {
container[.font] = font.scaled(by: 0.75)
container[.baselineOffset] = -font.pointSize * 0.2
}
if keys.contains("superscript") {
container[.font] = font.scaled(by: 0.75)
container[.baselineOffset] = font.pointSize * 0.35
}
if keys.contains("underline") {
container[.underlineStyle] = NSUnderlineStyle.single.rawValue
container[.underlineColor] = container[.foregroundColor]
}
if keys.contains("highlight") {
container[.backgroundColor] = MDColor.systemYellow.withAlphaComponent(0.45)
}
let str = NSMutableAttributedString()
self.inlineConvertibleChildren.forEach { convertible in
str.append(convertible.convert(attributeContainer: container, config: config))
}
return str
}
}

extension Markdown.Table.Cell: InlineConvertible {

func convert(attributeContainer: NSAttributeContainer, config: MarkdownRenderConfig) -> NSMutableAttributedString {
Expand Down
18 changes: 18 additions & 0 deletions Sources/MarkdownText/Parser/MarkdownParserImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ public final class MarkdownParserImpl: MarkdownParser {
PartialTableMarkupPostParsingRewriter()
]

private let inlineHTMLRewriter = InlineHTMLMarkupPostParsingRewriter()

private let delimiterRewriter = InlineDelimiterMarkupPostParsingRewriter()

private let imageBlockRewriter = ImageBlockMarkupPostParsingRewriter()

private let latexPreprocessor: LaTexPreProcessor
Expand All @@ -39,6 +43,20 @@ public final class MarkdownParserImpl: MarkdownParser {
}
}

if let rewrittenDoc = inlineHTMLRewriter.rewriteIfApplicable(document: result.document) {
result = MarkdownParseResult(
document: rewrittenDoc,
speculativeRewritten: result.speculativeRewritten
)
}

if let rewrittenDoc = delimiterRewriter.rewriteIfApplicable(document: result.document) {
result = MarkdownParseResult(
document: rewrittenDoc,
speculativeRewritten: result.speculativeRewritten
)
}

if option.imageSupport {
if let rewrittenDoc = imageBlockRewriter.rewriteIfApplicable(document: result.document) {
result = MarkdownParseResult(
Expand Down
Loading