You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+21-1Lines changed: 21 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -99,7 +99,7 @@ The React runtime shares the same template semantics as `jsx`, except it returns
99
99
100
100
-`style` accepts either a string or an object. Object values handle CSS custom properties (`--token`) automatically.
101
101
-`class` and `className` both work and can be strings or arrays.
102
-
- Event handlers use the `on<Event>` naming convention (e.g. `onClick`).
102
+
- Event handlers use the `on<Event>` naming convention (e.g. `onClick`), support capture-phase variants via `on<Event>Capture`, and allow custom events with the `on:custom-event` syntax (descriptor objects with `{ handler, once, capture }` are also accepted).
103
103
-`ref` supports callback refs as well as mutable `{ current }` objects.
104
104
-`dangerouslySetInnerHTML` expects an object with an `__html` field, mirroring React.
105
105
@@ -286,6 +286,26 @@ import { reactJsx as nodeReactJsx } from '@knighted/jsx/node/react/lite'
286
286
287
287
Each lite subpath ships the same API as its standard counterpart but is pre-minified and scoped to just that runtime (DOM, React, Node DOM, or Node React). Swap them in when you want the smallest possible bundles; otherwise the default exports keep working as-is.
288
288
289
+
## Common gotchas
290
+
291
+
### DocumentFragment reuse (DOM helper)
292
+
293
+
`jsx` returns actual DOM nodes, so fragments compile down to real `DocumentFragment` instances. The browser treats those fragments as one-time transport containers: append them to a parent, and the fragment empties itself as it moves its children. Unlike VDOM libraries (React, Preact, Solid), we do not clone fragments on your behalf, so storing a fragment and reusing it later will not work the way a React developer might expect.
When you need multiple copies, call the template again, wrap it in a helper (`const makeHeader = () => jsx`<...>`; makeHeader()`), or clone the fragment before reusing it (`footer.append(header.cloneNode(true))`). Components that return fragments are unaffected because every invocation produces a fresh fragment.
308
+
289
309
## Limitations
290
310
291
311
- Requires a DOM-like environment (it throws when `document` is missing).
Copy file name to clipboardExpand all lines: docs/cli.md
+8-3Lines changed: 8 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ npx @knighted/jsx init
10
10
11
11
What it does by default:
12
12
13
-
- Installs `@oxc-parser/binding-wasm32-wasi` plus runtime helpers (`@napi-rs/wasm-runtime`, `@emnapi/runtime`, `@emnapi/core`).
13
+
- Installs `@oxc-parser/binding-wasm32-wasi`that matches the library's bundled `oxc-parser` version plus runtime helpers (`@napi-rs/wasm-runtime`, `@emnapi/runtime`, `@emnapi/core`).
14
14
- Records the binding in `optionalDependencies` so the version is visible in your project.
15
15
- Verifies the binding can be imported and reports the resolved path.
16
16
- Skips loader config changes (prompted only when you opt in).
- The default binding install always matches the `oxc-parser` version bundled with `@knighted/jsx`; use `--wasm-version`, `--wasm-package`, or `WASM_BINDING_PACKAGE` when you intentionally need a different build.
49
54
- The command uses `npm pack` internally to pull the WASM binding even when it is marked for `cpu: ["wasm32"]`.
50
55
- Loader configuration is opt-in and requires a prompt. No config files are modified unless you request help.
51
56
- If verification fails, rerun with `--verbose` to see the resolved binding path and error details.
Copy file name to clipboardExpand all lines: docs/how-it-compares.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,21 +11,21 @@ Use this quick matrix to see how `@knighted/jsx` stacks up against other tagged-
11
11
| SSR / Node |`@knighted/jsx/node` bootstraps `linkedom`/`jsdom` automatically; fixtures cover Next.js, Lit + React hybrids, and plain Node usage. | Depends on the hyperscript target/framework to provide SSR. | Provides DOM-focused SSR utilities but no automatic shims or React interop. |
12
12
| TypeScript support | First-class typings for DOM + React runtimes, loader options, and Node helpers. | Community types only for the tag factory. | Minimal typings; templates rely on generic DOM types. |
13
13
| Component interoperability | Mix DOM helpers, React components, Lit roots, and loader-transformed calls in one file. | Primarily a JSX stand-in for Preact or hyperscript. | Focused on DOM updates, pairs with `uhtml/async` or low-level renderers. |
14
-
| Approx. size | DOM: ~8.8 kB raw / ~2.3 kB min+gzip. Lite DOM: ~5.7 kB raw / ~2.5 kB min+gzip.|~1 kB min+gzip. |~7 kB min+gzip. |
14
+
| Approx. size | DOM: ~14.3 kB raw / ~3.3 kB min+gzip. Lite DOM: ~7.8 kB raw / ~3.3 kB min+gzip. |~1 kB min+gzip. |~7 kB min+gzip. |
15
15
16
16
> `htm` and `uhtml` remain excellent when you only need lightweight hyperscript or DOM templating. `@knighted/jsx` trades a slightly larger runtime for full JSX semantics, React parity, loaders, and SSR tooling.
17
17
18
18
> [!NOTE]
19
-
> `@knighted/jsx` sizes were measured by gzipping `dist/jsx.js` (default runtime) and `dist/lite/index.js` from the latest build. The lite build is raw-smaller, but its minified output uses fewer repeated tokens, so gzip has a little less to compress (hence the slightly higher min+gzip size).
19
+
> `@knighted/jsx` sizes were measured by gzipping `dist/jsx.js` (default runtime) and `dist/lite/index.js` from the latest build. The lite build stays raw-smaller, while gzip now lands within a few bytes of the default runtime because all helpers live in one bundle.
20
20
21
21
## Detailed size breakdown
22
22
23
-
| Entry point | Raw size (bytes) | Min+gzip size (bytes) | Lite raw size (bytes) | Lite min+gzip size (bytes) | Notes|
| DOM runtime (`@knighted/jsx`) |9,054 (`dist/jsx.js`) |2,291|5,790 (`dist/lite/index.js`) |2,512| Lite bundle packs everything into one file, so gzip sees fewer repeated tokens despite the smaller raw payload. |
26
-
| React runtime (`@knighted/jsx/react`) | 5,133 (`dist/react/react-jsx.js`) | 1,445| 4,146 (`dist/lite/react/index.js`) |1,885|Same trade-off as DOM: raw-lite wins, gzip-lite is slightly larger because it inlines all helpers.|
27
-
| Node DOM entry (`@knighted/jsx/node`) |9,197 combined (`dist/jsx.js` + `dist/node/bootstrap.js` via dynamic import) | ≈3,205|6,954 (`dist/lite/node/index.js`) | 3,007| Lite bundle already includes the bootstrap shim, so both raw and gzipped footprints shrink end-to-end.|
28
-
| Node React entry (`@knighted/jsx/node/react`) | 7,559 combined (`dist/react/react-jsx.js` + `dist/node/bootstrap.js`) | ≈2,359| 4,146 (`dist/lite/node/react/index.js`) |1,885| Lite variant bundles React + bootstrap, cutting both raw and gzipped sizes.|
23
+
| Entry point | Raw size (bytes) | Min+gzip size (bytes) | Lite raw size (bytes) | Lite min+gzip size (bytes) | Notes |
| DOM runtime (`@knighted/jsx`) |14,580 (`dist/jsx.js`) |3,384|7,959 (`dist/lite/index.js`) |3,351| Lite bundle packs everything into one file, so gzip results now sit within a few bytes of the default runtime. |
26
+
| React runtime (`@knighted/jsx/react`) | 5,166 (`dist/react/react-jsx.js`) | 1,454| 4,556 (`dist/lite/react/index.js`) |2,076|Lite React remains raw-smaller but pays a small gzip premium because it inlines helper code. |
27
+
| Node DOM entry (`@knighted/jsx/node`) |17,006 combined (`dist/jsx.js` + `dist/node/bootstrap.js` via dynamic import) | ≈4,298|9,131 (`dist/lite/node/index.js`) | 3,847| Lite bundle already includes the bootstrap shim, so both raw and gzipped footprints shrink end-to-end. |
28
+
| Node React entry (`@knighted/jsx/node/react`) | 7,592 combined (`dist/react/react-jsx.js` + `dist/node/bootstrap.js`) | ≈2,368| 4,556 (`dist/lite/node/react/index.js`) |2,076| Lite variant bundles React + bootstrap, cutting both raw and gzipped sizes. |
29
29
30
30
> [!TIP]
31
31
> Numbers were captured using `gzip -c <file> | wc -c`. “Combined” entries include every file the non-lite entry loads at runtime so you can compare end-to-end costs.
Copy file name to clipboardExpand all lines: docs/next-steps.md
+4-13Lines changed: 4 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,16 +2,7 @@
2
2
3
3
A few focused improvements will give @knighted/jsx a more polished, batteries-included feel across editors, runtimes, and testing workflows.
4
4
5
-
## 1. Type-level ergonomics
6
-
7
-
- Provide opt-in helper wrappers (for example `jsx.el<'button'>`) that return concrete `HTMLElement` types, plus richer React intrinsic typing for `reactJsx` so attribute completion matches native elements.
8
-
- Clearly explain how to mix these helpers with existing components to keep type safety predictable across DOM and React runtimes.
9
-
10
-
## 2. Starter templates
11
-
12
-
- Publish StackBlitz/CodeSandbox starters (DOM only, React, Lit + React) and link them from the docs so newcomers can experiment without cloning the repo.
13
-
- Include scripts that demonstrate the CDN-only workflow alongside bundler-driven builds.
14
-
15
-
## 3. Runtime diagnostics
16
-
17
-
- Add a development flag that logs friendly warnings for common pitfalls (missing `key`, passing plain strings instead of nodes, etc.) to shorten the feedback loop while prototyping.
5
+
1.**Type-level ergonomics** – Explore opt-in helpers like `jsx.el<'button'>` (or richer intrinsic maps) so DOM nodes return concrete element types, and tighten the React intrinsic typing to match native attributes. Document how these helpers compose with existing components so the DX stays predictable.
6
+
2.**Starter templates** – Ship StackBlitz/CodeSandbox starters (DOM-only, React, Lit + React) that highlight CDN flows and bundler builds. Link them in the README/docs so developers can experiment without cloning the repo.
7
+
3.**Runtime diagnostics** – Add an optional dev flag that surfaces friendly warnings for common pitfalls (missing `key`, fragment reuse, string refs, etc.) to shorten debugging cycles without bloating production bundles.
8
+
4.**Bundle-size trims** – Audit shared helpers/metadata for duplication, experiment with feature flags (opt-out of advanced descriptors), and run esbuild/rollup analyzers to find dead code so the next releases can claw back some of the new bytes.
0 commit comments