@knighted/jsx 1.2.0-rc.2 → 1.2.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -20
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ const handleClick = () => {
|
|
|
56
56
|
|
|
57
57
|
const button = jsx`
|
|
58
58
|
<button className={${`counter-${count}`}} onClick={${handleClick}}>
|
|
59
|
-
Count is
|
|
59
|
+
Count is ${count}
|
|
60
60
|
</button>
|
|
61
61
|
`
|
|
62
62
|
|
|
@@ -78,7 +78,7 @@ const App = () => {
|
|
|
78
78
|
return reactJsx`
|
|
79
79
|
<section className="react-demo">
|
|
80
80
|
<h2>Hello from React</h2>
|
|
81
|
-
<p>Count is
|
|
81
|
+
<p>Count is ${count}</p>
|
|
82
82
|
<button onClick={${() => setCount(value => value + 1)}}>
|
|
83
83
|
Increment
|
|
84
84
|
</button>
|
|
@@ -147,12 +147,12 @@ import { renderToString } from 'react-dom/server'
|
|
|
147
147
|
|
|
148
148
|
const Badge = ({ label }: { label: string }) =>
|
|
149
149
|
reactJsx`
|
|
150
|
-
<button type="button">React says:
|
|
150
|
+
<button type="button">React says: ${label}</button>
|
|
151
151
|
`
|
|
152
152
|
|
|
153
153
|
const reactMarkup = renderToString(
|
|
154
154
|
reactJsx`
|
|
155
|
-
<${Badge} label=
|
|
155
|
+
<${Badge} label="Server-only" />
|
|
156
156
|
`,
|
|
157
157
|
)
|
|
158
158
|
|
|
@@ -250,7 +250,7 @@ Build the fixture locally with `npx next build test/fixtures/next-app` (or run `
|
|
|
250
250
|
|
|
251
251
|
### Interpolations
|
|
252
252
|
|
|
253
|
-
- All dynamic values are provided through standard template literal expressions (`${...}`)
|
|
253
|
+
- All dynamic values are provided through standard template literal expressions (`${...}`) and map to JSX exactly where they appear. Use JSX braces anywhere the syntax normally requires them (`className={${value}}`, spreads, etc.), but plain text children can interpolate directly, e.g. `Count is ${value}`.
|
|
254
254
|
- Every expression can be any JavaScript value: primitives, arrays/iterables, DOM nodes, functions, other `jsx` results, or custom component references.
|
|
255
255
|
- Async values (Promises) are not supported. Resolve them before passing into the template.
|
|
256
256
|
|
|
@@ -266,10 +266,12 @@ const Button = ({ children, variant = 'primary' }) => {
|
|
|
266
266
|
return el
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
+
const label = 'Tap me'
|
|
270
|
+
|
|
269
271
|
const view = jsx`
|
|
270
272
|
<section>
|
|
271
|
-
<${Button} variant=
|
|
272
|
-
|
|
273
|
+
<${Button} variant="ghost">
|
|
274
|
+
${label}
|
|
273
275
|
</${Button}>
|
|
274
276
|
</section>
|
|
275
277
|
`
|
|
@@ -336,6 +338,15 @@ npm run test
|
|
|
336
338
|
|
|
337
339
|
Tests live in `test/jsx.test.ts` and cover DOM props/events, custom components, fragments, and iterable children so you can see exactly how the template tag is meant to be used.
|
|
338
340
|
|
|
341
|
+
Need full end-to-end coverage? The Playwright suite boots the CDN demo (`examples/esm-demo.html`) and the loader-backed Rspack fixture to verify nested trees, sibling structures, and interop with Lit/React:
|
|
342
|
+
|
|
343
|
+
```sh
|
|
344
|
+
npm run test:e2e
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
> [!NOTE]
|
|
348
|
+
> The e2e script builds the library, installs the WASM parser binding, bundles the loader fixture, and then runs `playwright test`. Make sure Playwright browsers are installed locally (`npx playwright install`).
|
|
349
|
+
|
|
339
350
|
## Browser demo / Vite build
|
|
340
351
|
|
|
341
352
|
This repo ships with a ready-to-run Vite demo under `examples/browser` that bundles the library (make sure you have installed the WASM binding via the command above first). Use it for a full end-to-end verification in a real browser (the demo imports `@knighted/jsx/lite` so you can confirm the lighter entry behaves identically):
|
|
@@ -357,19 +368,6 @@ For a zero-build verification of the lite bundle, open `examples/esm-demo-lite.h
|
|
|
357
368
|
- JSX identifiers are resolved at runtime through template interpolations; you cannot reference closures directly inside the template without using `${...}`.
|
|
358
369
|
- Promises/async components are not supported.
|
|
359
370
|
|
|
360
|
-
## Performance notes vs `htm`
|
|
361
|
-
|
|
362
|
-
[`htm`](https://github.com/developit/htm) popularized tagged template literals for view rendering by tokenizing the template strings on the fly and calling a user-provided hyperscript function. This library takes a different approach: every invocation runs the native `oxc-parser` (compiled to WebAssembly) to build a real JSX AST before constructing DOM nodes.
|
|
363
|
-
|
|
364
|
-
Tradeoffs to keep in mind:
|
|
365
|
-
|
|
366
|
-
- **Parser vs tokenizer** – `htm` performs lightweight string tokenization, while `@knighted/jsx` pays a higher one-time parse cost but gains the full JSX grammar (fragments, spread children, nested namespaces) without heuristics. For large or deeply nested templates the WASM-backed parser is typically faster and more accurate than string slicing.
|
|
367
|
-
- **DOM-first rendering** – this runtime builds DOM nodes directly, so the cost after parsing is mostly attribute assignment and child insertion. `htm` usually feeds a virtual DOM/hyperscript factory (e.g., Preact’s `h`), which may add an extra abstraction layer before hitting the DOM.
|
|
368
|
-
- **Bundle size** – including the parser and WASM binding is heavier than `htm`’s ~1 kB tokenizer. If you just need hyperscript sugar, `htm` stays leaner; if you value real JSX semantics without a build step, the extra kilobytes buy you correctness and speed on complex trees.
|
|
369
|
-
- **Actual size** – as of `v1.2.0-rc.1` the default `dist/jsx.js` bundle is ~9.0 kB raw / ~2.3 kB min+gzip, while the `@knighted/jsx/lite` entry stays ~5.7 kB raw / ~2.5 kB min+gzip. `htm` weighs in at roughly 0.7 kB min+gzip, so the lite entry narrows the gap to ~1.8 kB for production payloads.
|
|
370
|
-
|
|
371
|
-
In short, `@knighted/jsx` trades a slightly larger runtime for the ability to parse genuine JSX with native performance, whereas `htm` favors minimal footprint and hyperscript integration. Pick the tool that aligns with your rendering stack and performance envelope.
|
|
372
|
-
|
|
373
371
|
## License
|
|
374
372
|
|
|
375
373
|
MIT © Knighted Code Monkey
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knighted/jsx",
|
|
3
|
-
"version": "1.2.0-rc.
|
|
3
|
+
"version": "1.2.0-rc.3",
|
|
4
4
|
"description": "Runtime JSX tagged template that renders DOM or React trees anywhere without a build step.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jsx runtime",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"prettier": "prettier -w .",
|
|
64
64
|
"test": "vitest run --coverage",
|
|
65
65
|
"test:watch": "vitest",
|
|
66
|
+
"test:e2e": "npm run build && npm run setup:wasm && npm run build:fixture && playwright test",
|
|
66
67
|
"build:fixture": "node scripts/build-rspack-fixture.mjs",
|
|
67
68
|
"demo:node-ssr": "node test/fixtures/node-ssr/render.mjs",
|
|
68
69
|
"dev": "vite dev --config vite.config.ts",
|
|
@@ -75,15 +76,17 @@
|
|
|
75
76
|
"devDependencies": {
|
|
76
77
|
"@eslint/js": "^9.39.1",
|
|
77
78
|
"@knighted/duel": "^2.1.6",
|
|
78
|
-
"@types
|
|
79
|
+
"@oxc-project/types": "^0.99.0",
|
|
80
|
+
"@playwright/test": "^1.57.0",
|
|
79
81
|
"@rspack/core": "^1.0.5",
|
|
80
82
|
"@types/jsdom": "^27.0.0",
|
|
83
|
+
"@types/node": "^22.10.1",
|
|
81
84
|
"@types/react": "^19.2.7",
|
|
82
85
|
"@types/react-dom": "^19.2.3",
|
|
83
86
|
"@vitest/coverage-v8": "^4.0.14",
|
|
84
87
|
"eslint": "^9.39.1",
|
|
85
88
|
"eslint-plugin-n": "^17.10.3",
|
|
86
|
-
"
|
|
89
|
+
"eslint-plugin-playwright": "^2.4.0",
|
|
87
90
|
"http-server": "^14.1.1",
|
|
88
91
|
"jsdom": "^27.2.0",
|
|
89
92
|
"lit": "^3.2.1",
|
|
@@ -103,9 +106,9 @@
|
|
|
103
106
|
"oxc-parser": "^0.99.0"
|
|
104
107
|
},
|
|
105
108
|
"peerDependencies": {
|
|
106
|
-
"react": ">=18",
|
|
107
109
|
"jsdom": "*",
|
|
108
|
-
"linkedom": "*"
|
|
110
|
+
"linkedom": "*",
|
|
111
|
+
"react": ">=18"
|
|
109
112
|
},
|
|
110
113
|
"peerDependenciesMeta": {
|
|
111
114
|
"react": {
|