SIGN IN SIGN UP
honojs / hono UNCLAIMED

Web framework built on Web Standards

0 0 77 TypeScript

fix(jsx): normalize SVG attributes on the <svg> root element (#4893)

* fix(jsx): normalize SVG attributes on the <svg> root element

`<svg strokeWidth="1.5">` was output as-is by SSR, but the DOM renderer
converted it to `stroke-width`. This broke icon libraries that set
stroke/fill attributes on the <svg> root, and it caused SSR and DOM to
produce different HTML for the same JSX.

Background:
- Icon libraries put these attributes on the <svg> root so the child
  paths can inherit them. Example from Heroicons:
  https://github.com/tailwindlabs/heroicons/blob/master/optimized/24/outline/pencil-square.svg
- React also converts `strokeWidth` -> `stroke-width` on the root
  (checked with `react-dom/server@18.3.1` `renderToStaticMarkup`).
- The HTML spec says that when the parser sees a `<svg>` start tag, it
  inserts "a foreign element for the token, with SVG namespace". So
  the <svg> element itself is in the SVG namespace, not only its
  children:
  https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody:adjust-svg-attributes

Root cause: the factory put only the children of `<svg>` inside the
namespace provider (`svg > Provider > children`). When SSR rendered
the <svg>'s own attributes, `useContext(nameSpaceContext)` returned
the default `""` instead of `"svg"`, so `toSVGAttributeName` was
skipped.

Fix: put the <svg> element itself inside the provider too
(`Provider > svg > children`), so the <svg>'s own attributes also run
with the `"svg"` context.

The `<head>` branch of the factory is left unchanged. Its context
value `"head"` is a Hono-internal flag used to stop <title> / <meta>
/ <script> from hoisting to document metadata when they are already
inside <head>. It is not a spec namespace and is never read when
rendering <head>'s own attributes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(jsx): keep <svg> node shape and normalize at render time

Preserve the JSXNode shape for `<svg>` (tag/type/ref/cloneElement
compatibility) and switch SVG attribute normalization to also kick in
when the rendered tag itself is `svg`, instead of wrapping the node
in a namespace Provider.

Co-authored-by: Taku Amano <taku@taaas.jp>
K
kobaken committed
bfba97ca7ea3d4541a3419f1749e5a1a3e8f1727
Parent: 90d4182
Committed by GitHub <noreply@github.com> on 5/1/2026, 9:01:56 AM