b2e5b1d420
hermes-bots/plugin.js was 16,193 lines of hand-written JSX compiler output
— it imported { jsx, jsxs } from 'react/jsx-runtime' and called them
directly. Because the file was .js, eslint (scoped to plugins/**/*.{ts,tsx})
and tsc (allowJs: false) both skipped it entirely, so none of the design
system, import-fence, or type rules that govern the rest of the app ever
reached the largest UI surface we ship on by default.
Converting it back to JSX is an inverse-compile, not a rewrite, so it is
done by script rather than by hand:
- scripts/codemod/dejsx.mjs rewrites jsx()/jsxs() calls into JSX elements.
735 conversions, none skipped. Comments between children become
{/* … */} containers, since a bare // in children position is text.
- scripts/codemod/verify.mjs proves the result. It recompiles the .tsx
through esbuild — an implementation independent of the codemod — and
compares it to the original after normalizing away esbuild's own
rewrites (quote style, void 0, numeric format, string/template folding,
export hoisting) and alpha-renaming every binding per scope. Output:
IDENTICAL across 333,711 normalized characters.
Two rewrite classes are semantics-preserving but not byte-identical, so
they are named and counted rather than hidden: 12 spread-children folds
(JSX has no spread-children syntax; children={[...xs]} can only be written
{xs}, which React flattens identically and which is the idiom the whole
ecosystem writes) and 1 redundant key prop (passed both in props and as
the third argument; React's jsx runtime never copies key into props).
No behavior change. 16,193 lines become 16,050 of real TSX.