Repository navigation
Render a supported subset of inline HTML tags instead of dropping them - #181
Open
Vincent Peng (vincent-peng) wants to merge 3 commits into
Open
Vincent Peng (vincent-peng) wants to merge 3 commits into
Vincent Peng (vincent-peng) wants to merge 3 commits into
Conversation
Inline raw-HTML nodes (InlineHTML) were previously dropped during inline conversion because they don't conform to InlineConvertible. This adds an AST-level InlineHTMLRewriter that maps a supported formatting subset onto equivalent Markdown nodes or InlineAttributes carriers before conversion: - <br> -> line break, <wbr> -> zero-width space - <b>/<strong> -> strong, <i>/<em> -> emphasis - <s>/<del>/<strike> -> strikethrough - <u>/<ins>, <mark>, <sub>/<sup> -> InlineAttributes, now rendered by a new InlineConvertible conformance (underline, highlight, baseline offset) - <code>/<kbd>/<samp>/<tt> -> inline code - <a href> -> link HTML comments are dropped. Unmatched, unsupported, or malformed tags keep their source as literal text so documents degrade gracefully. An open tag with no matching close applies to the rest of the inline container, which keeps mid-stream documents sensible while a tag is still arriving. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Follow-ups from review: - Bound tag-matching recursion at 64 pairs of nesting; deeper input emits literally instead of recursing quadratically / overflowing the stack. - Convert HTMLBlock nodes (standalone-line tags, cmark block type 7) to literal paragraphs so their text is never silently dropped. - Replace the href regex with a quote-aware scanner: matches only on a whitespace boundary (no data-href/xlink:href false positives), skips quoted attribute values, and accepts case-insensitive HREF. - Decode common named/numeric entities in href values (&, ", …). - Flatten InlineAttributes inside <a> to their children so the link still forms; split underline/highlight/sub/sup runs around non-recurring children (Link, Image) instead of going fully literal. - Use InlineCode.code when flattening nested inline code inside <code>. - Accept the full cmark whitespace set inside tags; map </br> to a line break like browsers do. - Require a key boundary in the InlineAttributes enabled-key regex. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- visitHTMLBlock now drops comment/PI/declaration blocks instead of surfacing them as visible text, matching inline comment handling. - Images inside <b>/<i>/<s> wrappers split the run so Image nodes reach paragraph level where ImageBlockRewriter can hoist them — previously an image inside a bold tag was silently dropped at conversion. - Link/Image/InlineAttributes children are filtered back to RecurringInlineMarkup (text-preserved fallback) so rewritten content stays within swift-markdown's structural rules. - Depth-cap fallback path now drops comments consistently. - enabledKey regex requires a word boundary after 'true'; README lists <strike> and clarifies comment handling. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Vincent Peng (vincent-peng)
requested review from
a team
and
a balanced review from Copilot
October 8, 2026 13:42
Contributor
Author
|
Independent verification: PASS (verified against the real artifact by an agent that did not write the code, on detached worktree
|
Vincent Peng (vincent-peng)
added a commit
to vincent-peng/SwiftStreamingMarkdown
that referenced
this pull request
Oct 8, 2026
This was referenced Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
InlineHTMLnodes had noInlineConvertibleconformance, so the entire node — including text inside formatting tags — was dropped during conversion (a <kbd>Ctrl</kbd>rendered asa). This adds anInlineHTMLRewriterpost-parse pass (same seam as the existing speculative rewriters) that maps a focused, GitHub-relevant inline subset onto existing AST nodes:<br>,</br>LineBreak<b>/<strong>Strong<i>/<em>Emphasis<s>/<del>/<strike>Strikethrough<u>/<ins>InlineAttributes)<mark>InlineAttributes)<sub>/<sup>InlineAttributes+MDFont.scaled)<code>/<kbd>/<samp>/<tt>InlineCode<a href="…">Link(quote-aware attribute scan; entity-decoded;data:rejected;data-hrefnot matched)<wbr><!-- … -->Design notes:
ImageBlockRewriter; formatting wrappers split aroundImagenodes so paragraph-level image extraction still works.Link,Image,InlineAttributes) degrade non-recurring children to plain text to respect swift-markdown structural invariants.HTMLBlocknodes become literal-source paragraphs; comments, declarations (<!…>), and processing instructions (<?…>) are dropped.InlineAttributes.convertrenders underline/highlight/subscript/superscript via the existing attributed-string pipeline;MDFont.scaled(by:)works on UIKit and AppKit.Resolves #177
Validation
make lint— 0 violations (strict)make test— full suite passes (150 package tests + 9ParagraphViewtests), including a newInlineHTMLRewriterTestssuite (28 tests) exercising the full parse → rewrite → renderable → attributed-string path: every supported tag, comments/declarations, unsupported/unknown/unclosed tags, nested formatting, links andhrefedge cases (quoted/unquoted/uppercase/data-href/entities), image-in-wrapper splitting, nested-link degradation, deep-nesting bounds, and documents with no HTML (no-op passthrough).make build-sample— builds cleanOSS readiness
README's supported-syntax list updated.