Skip to content

fix: parse SVG as HTML tokens instead of deferring to markdown#114

Merged
rohal12 merged 2 commits intomainfrom
fix/113-svg-multiline-tags
Mar 24, 2026
Merged

fix: parse SVG as HTML tokens instead of deferring to markdown#114
rohal12 merged 2 commits intomainfrom
fix/113-svg-multiline-tags

Conversation

@rohal12
Copy link
Owner

@rohal12 rohal12 commented Mar 24, 2026

Summary

  • Remove the SVG special case in the tokenizer that treated <svg>…</svg> as opaque text deferred to markdown — multi-line SVG tags were HTML-escaped because micromark doesn't recognize SVG as a type 6 HTML block tag
  • Preserve original tag case in tokens so SVG camelCase elements (linearGradient, clipPath, etc.) render correctly, while keeping case-insensitive matching in the AST builder
  • Add tokenizer, AST, and DOM render tests for single-line, multi-line, and nested SVG

Test plan

  • Tokenizer: single-line <svg> produces correct HtmlTokens
  • Tokenizer: multi-line <svg> produces correct HtmlTokens
  • Tokenizer: <svg> nested inside <div> tokenizes correctly
  • AST: multi-line SVG builds correct HtmlNode tree with attributes
  • AST: nested SVG correctly parents under outer div
  • DOM: multi-line SVG renders as actual SVG element, not escaped text
  • DOM: SVG elements get correct namespace URI
  • DOM: camelCase SVG elements (linearGradient) preserve tag name
  • Full test suite: 975/975 pass
  • Type check: clean

Closes #113

🤖 Generated with Claude Code

Multi-line SVG tags were HTML-escaped because the tokenizer treated
<svg>…</svg> as opaque text, which went through micromark (CommonMark
doesn't recognize SVG as a type 6 HTML block tag). Remove the SVG
special case so <svg> is tokenized like any other HTML tag, rendering
via Preact's h() which handles SVG namespace correctly.

Also preserve original tag case in tokens (SVG needs camelCase for
elements like linearGradient, clipPath) while keeping case-insensitive
matching in the AST builder for open/close tag pairing.

Closes #113

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link

Release preview: merging this PR will publish v0.36.2 (patch bump from v0.36.1)

@github-actions
Copy link

github-actions bot commented Mar 24, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 77.53% 2609 / 3365
🔵 Statements 76.73% 2859 / 3726
🔵 Functions 67.51% 478 / 708
🔵 Branches 74.11% 1443 / 1947
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/markup/ast.ts 95% 90.78% 100% 94.25% 149-151, 160-165, 281-282
src/markup/render.tsx 90.17% 81.25% 94.11% 92.85% 72, 82, 120, 196-197, 208, 229, 230, 234-235
src/markup/tokenizer.ts 86.17% 85.44% 100% 86.13% 159-160, 203, 223-225, 259-263, 289-290, 294, 366-368, 394-396, 416, 422-424, 435, 441-443, 466-468, 492-494, 518-520, 544-546, 569-571, 614, 662-663
Generated in workflow #184 for commit 2227a63 by the Vitest Coverage Report Action

SVG children rendered via renderNodes() went through markdown, which
wraps content in <p> tags — breaking SVG namespace and producing
zero-dimension elements. Add SvgContext to skip markdown for all
descendants inside <svg>, using renderInlineNodes() instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rohal12 rohal12 merged commit a5e683a into main Mar 24, 2026
5 checks passed
@rohal12 rohal12 deleted the fix/113-svg-multiline-tags branch March 24, 2026 11:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SVG with multi-line tags renders as escaped plaintext

1 participant