fix(ast): keep the SVG schema for raw HTML inside an MDX <svg> element - #283
Open
gtritchie wants to merge 5 commits into
Open
fix(ast): keep the SVG schema for raw HTML inside an MDX <svg> element#283gtritchie wants to merge 5 commits into
gtritchie wants to merge 5 commits into
Conversation
With `rawHtml`, `reparse_children_into` serialized and reparsed an MDX JSX element's children with `in_svg = false` and an HTML `<template>` fragment context, so raw HTML under a JSX element named `svg` lost the SVG attribute schema: `fill-rule` stayed an unknown `fill-rule` property instead of `fillRule`, and a hast `fillRule` property serialized unconverted and came back lowercased as `fillrule`. Thread the namespace context through the emitter. Parsed elements still derive it from their own namespace; a stitched MDX node inherits its parent's, and an MDX element named `svg` puts its children in SVG content, matching the serializer's `in_svg || tag == "svg"` switch. The reparse then both serializes with the SVG schema and parses in an `<svg>` fragment context. Fixes bruits#249
The SVG context threaded through the raw-HTML reparse was sticky through every SVG-namespace element, so an MDX node stitched back under `<foreignObject>` (or `<desc>`/`<title>`) reparsed its own raw children in SVG content. The parser treats those elements as HTML integration points and reads their children as HTML, which is also how `emit` already chooses the schema for the element's direct children. Stop SVG content at an HTML integration point for parsed elements, copied arena elements, and MDX elements named after one. Stickiness through `<foreignObject>` remains a serializer-only rule in `render.rs`. Refs bruits#249
html5ever parses <math> subtrees in the MathML namespace, not the HTML context; the helper ignores MathML's integration points only because the reparse context tracks SVG content alone.
GitHub's merge of main (bruits#282) spliced the two new bruits#192 tests inside the bruits#249 test body, leaving the mdxToJs describe block unclosed so the file failed to parse. Re-add the test's closing line; the file is now main plus the bruits#249 test.
Merging this PR will not alter performance
Comparing Footnotes
|
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.
Fixes #249.
Problem
With
rawHtml,reparse_children_intoserialized an MDX JSX element's children within_svg = falseand reparsed them in an HTML<template>fragment context. Raw HTML under a JSX element namedsvgtherefore lost the SVG attribute schema:<path fill-rule="evenodd"/>came back with an unknownfill-ruleproperty instead offillRule, and a hastfillRuleproperty was serialized unconverted and read back lowercased asfillrule.Fix
EmitTask::Emit/EmitArenanow carry the namespace context the node sits in. Parsed elements keep deriving their schema from their own namespace; a stitched MDX node inherits its parent's; an MDX element namedsvgputs its children in SVG content, matching the serializer'sin_svg || tag == "svg"switch.reparse_children_intothen serializes with the SVG schema and parses in the existingHtmlSpace::Svgcontext. This also covers JSX nested inside a JSX<svg>and JSX stitched back under raw<svg>…</svg>.Unlike the serializer, the reparse exits SVG content at the HTML integration points (
foreignObject,desc,title), which is how html5ever already treats those elements' direct children.Behaviour notes
Raw HTML inside a JSX
<svg>now parses the same way as raw HTML inside a real<svg>: non-breakout HTML elements (td,label,input, …) land in the SVG namespace, void elements are not void, and<script>/<style>are not raw text. The last of these already corrupts<in script text under a real<svg>on main (hast-util-to-html and rehype-raw behave the same) — tracked in #284. Raw MathML under a JSX<math>still parses in HTML content (<mspace/>does not self-close) — the same class of problem, tracked in #285.Tests
Rust (
from_html.rs): raw child of an MDX<svg>; hast element withfillRuleunder an MDX<svg>; JSX nested in a JSX<svg>; JSX under raw<svg>; non-svgJSX keeps the HTML schema; ordinary HTML under a JSX<svg>breaks out; JSX under raw and JSX<foreignObject>exits SVG content. JS (compile.test.ts):mdxToJswith an mdast plugin injecting anhtmlnode under<svg>assertsfillRule/strokeWidth. All failed before the fix.