compileHTMLToJSX is a deterministic, regex-based compiler that converts an HTML fragment into valid JSX. It applies a fixed sequence of transforms — no AI, no heuristics.
The entry point is:
Transform sequence
1
Strip document wrappers
<!DOCTYPE>, <html>, <head>, and <body> tags are stripped so only the body fragment remains. This runs first so all subsequent transforms work on a clean fragment.2
Pre-process: Material Symbols and `<pre>` blocks
Two patterns are fixed before attribute rewriting because the regex compiler cannot handle them inline safely.Material Symbols / Icons — Stitch emits icon names as both a
data-icon attribute and as text content. The Material Symbols font renders the icon purely via the class name; if the text content is present, the icon name appears as literal text instead of a glyph. The pre-processor strips the text child from any <span> whose class contains material-symbols-* or material-icons*:<pre><code> blocks — Raw { and } characters inside <pre> blocks are valid HTML but invalid JSX (JSX treats them as expression delimiters). The pre-processor replaces them with HTML entities that render identically in the browser:3
Transform opening tags
Every opening tag is rewritten: attributes are renamed, event handlers are camelCased, inline styles are converted to objects, and void elements are self-closed.See the detailed attribute tables below.
4
Convert HTML comments to JSX comments
HTML comments are converted to JSX expression comments:
5
Wrap in a fragment if multiple root elements
If the compiled output has more than one root element, a React fragment wrapper is added:
Attribute renaming
All standard HTML attributes that have a different name in JSX are renamed via a static lookup table.Full ATTR_MAP table
Full ATTR_MAP table
data-* attributes are not remapped — React passes all data-* props through unchanged.
Event handler camelCasing
HTML event handler attributes are renamed to their React camelCase equivalents and wrapped in an arrow function:Full EVENT_MAP table
Full EVENT_MAP table
Void element self-closing
Void elements cannot have children and must be self-closed in JSX. The following elements are always emitted with/>:
Inline style conversion
CSSstyle strings are converted to JavaScript objects. The converter handles complex values including url(), calc(), and var() using a balanced-bracket parser — not a naive split on ;.
Conversion rules:
- CSS property names are converted to camelCase (
background-color→backgroundColor) - Pure integer values are emitted as number literals (no quotes)
- All other values are emitted as quoted strings
- Double quotes inside values are escaped
data-alt promotion
Stitch sometimes uses data-alt on <img> elements instead of the standard alt attribute. The compiler promotes it to a proper alt:
alt and data-alt are present, data-alt wins (it overwrites the earlier attribute in the ordered map).
data-icon removal
The data-icon attribute is a Stitch artifact used to store the icon name for Material Symbols elements. Because the icon name is already the text content of the element (and the pre-processor strips that text to prevent it from rendering), data-icon serves no purpose in JSX and is dropped:
Fragment wrapping for multiple root elements
When the compiled output has more than one top-level element, it cannot be returned from a React component without a wrapper. The compiler detects this automatically and wraps the output in a<>...</> fragment:
requiresClientDirective
After compilation, the converter checks whether the component’s JSX requires a 'use client' directive in Next.js. The check is a set of regex tests:
'use client'; prepended if it contains:
- Any event handler prop (
onClick,onChange,onSubmit,onInput,onFocus,onBlur) - Any React hook (
useState,useEffect,useRef,useContext,useReducer) - Any
<button>element — buttons are always interactive and always require the client boundary
requiresClientDirective only applies to Next.js App Router projects. Vite components can use hooks and event handlers freely without any directive.Before-and-after example
A realistic Stitch component going through the full compiler:class→className(three elements)stylestring → JS object (two elements)data-alt→alt<img>→ self-closedonclick→onClickwrapped in arrow function- Material Symbols text child stripped;
data-icondropped - Since the component contains a
<button>,requiresClientDirectivereturnstrueand'use client';is prepended to the file