@inglorious/vite-plugin-jsx 1.0.0

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.
@@ -0,0 +1,3 @@
1
+ [?9001h[?1004h[?25l]0;C:\WINDOWS\system32\cmd.exe [?25h[?25l
2
+ > @inglorious/vite-plugin-jsx@1.0.0 lint C:\Users\anton\Projects\ic\inglorious-forge\packages\vite-plugin-jsx
3
+ > eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0[?25h[?9001l[?1004l
@@ -0,0 +1,57 @@
1
+ [?9001h[?1004h[?25l]0;C:\WINDOWS\system32\cmd.exe [?25h[?25l
2
+ > @inglorious/vite-plugin-jsx@0.1.0 test C:\Users\anton\Projects\ic\inglorious-forge\packages\vite-plugin-jsx
3
+ > vitest run[?25h]0;node (vitest)
4
+ [?25l RUN  v2.1.9 C:/Users/anton/Projects/ic/inglorious-forge/packages/vite-plugin-jsx[?25h]0;node (vitest 3)]0;node (vitest 1)]0;node (vitest 2)]0;node (vitest 5)]0;node (vitest 6)]0;node (vitest 7)]0;node (vitest 4)]0;node (vitest 9)]0;node (vitest 8)]0;node (vitest 10)]0;node (vitest 11)[?25l · moves api parameter to the end if it is not the last one
5
+ · does not change parameters if api is already the last argument
6
+ · moves api parameter to the end when it is in the middle
7
+ · does not inject api if no capitalized component is used
8
+ · does not inject api if component is not inside a 'render' method
9
+ · throws an error when trying to inject api with a rest parameter present
10
+ · injects api argument when component is nested inside a Fragment
11
+ · injects api argument when component is nested inside standard elements
12
+  ✓ moves api parameter to the end if it is not the last one
13
+ ✓ does not change parameters if api is already the last argument
14
+ ✓ moves api parameter to the end when it is in the middle
15
+ ✓ does not inject api if no capitalized component is used
16
+ ✓ does not inject api if component is not inside a 'render' method
17
+ ✓ throws an error when trying to inject api with a rest parameter present
18
+ ✓ injects api argument when component is nested inside a Fragment
19
+ ✓ injects api argument when component is nested inside standard elements
20
+  ✓ src/index.test.js (29) 737ms
21
+ ✓ vite-plugin-jsx (29) 736ms
22
+ ✓ transforms basic JSX elements 411ms
23
+ ✓ injects the html import only when JSX is present
24
+ ✓ transforms className to class
25
+ ✓ handles event listeners (@event syntax)
26
+ ✓ handles boolean attributes
27
+ ✓ distinguishes between properties (.) and attributes
28
+ ✓ handles fragments
29
+ ✓ handles nested expressions and elements
30
+ ✓ transforms Array.map to repeat directive
31
+ ✓ transforms Array.map with key to keyed repeat directive
32
+ ✓ transforms ternary operators to when directive
33
+ ✓ transforms logical AND to when directive
34
+ ✓ merges imports if @inglorious/web is already imported
35
+ ✓ throws error for missing event handler expression
36
+ ✓ throws error for string literal event handler
37
+ ✓ does not generate closing tag for void elements
38
+ ✓ handles SVG self-closing tags correctly
39
+ ✓ expands self-closing non-void HTML tags
40
+ ✓ ignores empty expressions and comments
41
+ ✓ transforms capitalized components to api.render calls
42
+ ✓ injects api argument into render function if missing when using components
43
+ ✓ moves api parameter to the end if it is not the last one
44
+ ✓ does not change parameters if api is already the last argument
45
+ ✓ moves api parameter to the end when it is in the middle
46
+ ✓ does not inject api if no capitalized component is used
47
+ ✓ does not inject api if component is not inside a 'render' method
48
+ ✓ throws an error when trying to inject api with a rest parameter present
49
+ ✓ injects api argument when component is nested inside a Fragment
50
+ ✓ injects api argument when component is nested inside standard elements
51
+ 
52
+  Test Files  1 passed (1)
53
+  Tests  29 passed (29)
54
+  Start at  20:22:47
55
+  Duration  4.54s (transform 214ms, setup 0ms, collect 1.40s, tests 737ms, environment 0ms, prepare 1.08s)
56
+ 
57
+ 
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @inglorious/vite-plugin-jsx
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Add JSX support
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright © 2025 Inglorious Coderz Srl.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,370 @@
1
+ # 🩸 @inglorious/vite-plugin-jsx
2
+
3
+ > **JSX without React. Deterministic UI for Inglorious Web.**
4
+
5
+ `@inglorious/vite-plugin-jsx` is a Vite plugin that compiles standard JSX / TSX into highly-optimized `lit-html` templates for **[@inglorious/web](https://www.npmjs.com/package/@inglorious/web)**.
6
+
7
+ It gives you React-familiar syntax **without** React's runtime, hooks, lifecycle, or reactivity model.
8
+
9
+ > New to Inglorious Web? Check out the [main documentation](https://www.npmjs.com/package/@inglorious/web) first.
10
+
11
+ ---
12
+
13
+ ## ✨ Features
14
+
15
+ - Standard JSX & TSX syntax
16
+ - Zero runtime overhead
17
+ - Compiles directly to `lit-html`
18
+ - Deterministic rendering model
19
+ - No hooks, no effects, no lifecycles
20
+ - First-class SVG support
21
+ - Automatic optimization of:
22
+ - conditionals → `when()`
23
+ - lists → `repeat()`
24
+ - Smart attribute & property binding
25
+ - Full TypeScript support
26
+
27
+ ---
28
+
29
+ ## 📦 Installation
30
+
31
+ ```bash
32
+ npm install -D @inglorious/vite-plugin-jsx
33
+ ```
34
+
35
+ ---
36
+
37
+ ## ⚡ Usage
38
+
39
+ ### `vite.config.ts`
40
+
41
+ ```ts
42
+ import { defineConfig } from "vite"
43
+ import { jsx } from "@inglorious/vite-plugin-jsx"
44
+
45
+ export default defineConfig({
46
+ plugins: [jsx()],
47
+ })
48
+ ```
49
+
50
+ That’s it.
51
+
52
+ You can now write JSX/TSX in your Inglorious project.
53
+
54
+ ---
55
+
56
+ ## 🧬 What It Compiles To
57
+
58
+ ### JSX Input
59
+
60
+ ```jsx
61
+ function render(entity, api) {
62
+ return (
63
+ <div className="card">
64
+ {entity.visible && <h2>{entity.title}</h2>}
65
+
66
+ {entity.items.map((item) => (
67
+ <p key={item.id} onClick={() => api.select(item)}>
68
+ {item.name}
69
+ </p>
70
+ ))}
71
+ </div>
72
+ )
73
+ }
74
+ ```
75
+
76
+ ### Compiled Output
77
+
78
+ ```js
79
+ function render(entity, api) {
80
+ return html`
81
+ <div class="card">
82
+ ${when(entity.visible, () => html`<h2>${entity.title}</h2>`)}
83
+ ${repeat(
84
+ entity.items,
85
+ (item) => item.id,
86
+ (item) => html`<p @click=${() => api.select(item)}>${item.name}</p>`,
87
+ )}
88
+ </div>
89
+ `
90
+ }
91
+ ```
92
+
93
+ ---
94
+
95
+ ## 📚 Common Patterns
96
+
97
+ ### Handling Events
98
+
99
+ ```jsx
100
+ export const button = {
101
+ render(entity, api) {
102
+ return (
103
+ <button onClick={() => api.notify(`#${entity.id}:click`)}>
104
+ {entity.label}
105
+ </button>
106
+ )
107
+ },
108
+ }
109
+ ```
110
+
111
+ ### Conditional Rendering
112
+
113
+ ```jsx
114
+ export const panel = {
115
+ render(entity, api) {
116
+ return (
117
+ <div>
118
+ {entity.isLoading && <Spinner />}
119
+ {entity.error ? (
120
+ <ErrorMessage text={entity.error} />
121
+ ) : (
122
+ <Content data={entity.data} />
123
+ )}
124
+ </div>
125
+ )
126
+ },
127
+ }
128
+ ```
129
+
130
+ ### Lists with Keys
131
+
132
+ ```jsx
133
+ export const todoList = {
134
+ render(entity, api) {
135
+ return (
136
+ <ul>
137
+ {entity.todos.map((todo) => (
138
+ <TodoItem key={todo.id} {...todo} />
139
+ ))}
140
+ </ul>
141
+ )
142
+ },
143
+ }
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 📘 TypeScript Support
149
+
150
+ The plugin works with `.tsx` files out of the box. For proper type checking:
151
+
152
+ ```ts
153
+ // tsconfig.json
154
+ {
155
+ "compilerOptions": {
156
+ "jsx": "preserve", // Let Vite handle JSX transformation
157
+ "jsxImportSource": undefined // Prevent automatic React imports
158
+ }
159
+ }
160
+ ```
161
+
162
+ For entity types with JSX renders:
163
+
164
+ ```ts
165
+ import { html } from "@inglorious/web"
166
+
167
+ type CounterEntity = {
168
+ type: "counter"
169
+ value: number
170
+ }
171
+
172
+ export const counter = {
173
+ render(entity: CounterEntity, api) {
174
+ return (
175
+ <div className="counter">
176
+ <span>Count: {entity.value}</span>
177
+ </div>
178
+ )
179
+ }
180
+ }
181
+ ```
182
+
183
+ ---
184
+
185
+ ## 🧠 Design Philosophy
186
+
187
+ This plugin is **purely compile-time**.
188
+
189
+ It does **not** introduce:
190
+
191
+ - state
192
+ - hooks
193
+ - lifecycles
194
+ - effects
195
+ - subscriptions
196
+ - partial reactivity
197
+
198
+ JSX is treated as **syntax**, not as a runtime system.
199
+
200
+ The execution model of **@inglorious/web** remains untouched:
201
+
202
+ > store change → full deterministic render → diff → commit
203
+
204
+ ---
205
+
206
+ ## 🔁 JSX Rules & Semantics
207
+
208
+ ### Event handlers
209
+
210
+ ```jsx
211
+ <button onClick={save} />
212
+ ```
213
+
214
+
215
+
216
+ ```html
217
+ <button @click="${save}"></button>
218
+ ```
219
+
220
+ ---
221
+
222
+ ### Property vs Attribute Binding
223
+
224
+ ```jsx
225
+ // Properties (use . prefix for custom elements and form controls)
226
+ <input value={x} /> // → .value=${x}
227
+ <my-element data={x} /> // → .data=${x}
228
+
229
+ // Attributes (standard HTML, kebab-case, or specific attributes)
230
+ <input id={x} /> // → id=${x}
231
+ <div data-id={x} /> // → data-id=${x}
232
+ <div class={x} /> // → class=${x}
233
+ ```
234
+
235
+ ---
236
+
237
+ ### Conditionals
238
+
239
+ ```jsx
240
+ {
241
+ cond && <A />
242
+ }
243
+ {
244
+ cond ? <A /> : <B />
245
+ }
246
+ ```
247
+
248
+ → compiled to `when()`
249
+
250
+ ---
251
+
252
+ ### Lists
253
+
254
+ ```jsx
255
+ items.map((i) => <Row key={i.id} />)
256
+ ```
257
+
258
+ → compiled to `repeat()`
259
+
260
+ Keys are extracted automatically.
261
+
262
+ ---
263
+
264
+ ### Fragments
265
+
266
+ ```jsx
267
+ <>
268
+ <A />
269
+ <B />
270
+ </>
271
+ ```
272
+
273
+ Fully supported.
274
+
275
+ ---
276
+
277
+ ### SVG
278
+
279
+ Nested SVG trees are handled correctly, including `foreignObject`.
280
+
281
+ ---
282
+
283
+ ### Engine Components
284
+
285
+ Capitalized tags are treated as **Engine Components** and compiled to `api.render()` calls.
286
+
287
+ ```jsx
288
+ export const app = {
289
+ render() {
290
+ // ☝️ Plugin auto-injects 'api' if you use components!
291
+ return <Form id="f1" />
292
+ },
293
+ }
294
+ ```
295
+
296
+ → `api.render("form", { id: "f1" })`
297
+
298
+ > 💡 **Smart injection**: The plugin automatically adds the `api` parameter to your render function when you use Engine Components in JSX. You don't need to add it manually!
299
+
300
+ #### ⚠️ Important Constraint
301
+
302
+ These engine components must:
303
+
304
+ - **not** contain children
305
+ - **not** represent DOM
306
+ - **not** try to be React
307
+
308
+ They are **render boundaries** for your engine.
309
+
310
+ ```jsx
311
+ // ❌ DON'T DO THIS - Engine components don't support children
312
+ export const form = {
313
+ render(entity, api) {
314
+ return (
315
+ <Form id="f1">
316
+ <Field />
317
+ </Form>
318
+ )
319
+ },
320
+ }
321
+
322
+ // ✅ DO THIS - Compose at the entity level instead
323
+ export const form = {
324
+ render(entity, api) {
325
+ return html`<form>${api.render("field", { formId: entity.id })}</form>`
326
+ },
327
+ }
328
+ ```
329
+
330
+ ---
331
+
332
+ ## 🧪 Why This Exists
333
+
334
+ React's runtime model is heavy, implicit, and hard to reason about at scale.
335
+
336
+ Inglorious Web is built on different principles:
337
+
338
+ - **Explicit data flow** - All state lives in the store
339
+ - **Deterministic rendering** - Same state always produces same output
340
+ - **Full-tree updates** - No dependency tracking, no hidden subscriptions
341
+ - **Predictable performance** - lit-html diffs everything, every time
342
+
343
+ This plugin lets you keep the ergonomics of JSX **without compromising the architecture**.
344
+
345
+ ---
346
+
347
+ ## 🧯 What This Plugin Does NOT Support (by design)
348
+
349
+ This plugin intentionally does **not** support:
350
+
351
+ - React hooks (useState, useEffect, etc.)
352
+ - Component-local state
353
+ - Lifecycle methods
354
+ - Context API
355
+ - Portals
356
+ - Fine-grained reactivity
357
+
358
+ **Why?** These features conflict with Inglorious Web's deterministic rendering model.
359
+
360
+ If you need these patterns, consider whether your state should live in the store instead, or use React directly.
361
+
362
+ ---
363
+
364
+ ## License
365
+
366
+ **MIT License - Free and open source**
367
+
368
+ Created by [Matteo Antony Mistretta](https://github.com/IngloriousCoderz)
369
+
370
+ You're free to use, modify, and distribute this software. See [LICENSE](./LICENSE) for details.
@@ -0,0 +1 @@
1
+ export { default } from "@inglorious/eslint-config/base"
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@inglorious/vite-plugin-jsx",
3
+ "version": "1.0.0",
4
+ "description": "A Vite plugin that transforms JSX into lit-html syntax.",
5
+ "author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./src/index.js",
9
+ "homepage": "https://github.com/IngloriousCoderz/inglorious-forge/tree/main/packages/vite-plugin-jsx#readme",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/IngloriousCoderz/inglorious-forge.git",
13
+ "directory": "packages/vite-plugin-jsx"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/IngloriousCoderz/inglorious-forge/issues"
17
+ },
18
+ "keywords": [
19
+ "vite",
20
+ "vite-plugin",
21
+ "inglorious",
22
+ "jsx",
23
+ "lit-html"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "dependencies": {
29
+ "@babel/core": "^7.28.5",
30
+ "@babel/plugin-syntax-jsx": "^7.28.6",
31
+ "@babel/plugin-syntax-typescript": "^7.28.6"
32
+ },
33
+ "devDependencies": {
34
+ "vitest": "^2.0.4",
35
+ "@inglorious/eslint-config": "1.1.1"
36
+ },
37
+ "engines": {
38
+ "node": ">= 22"
39
+ },
40
+ "scripts": {
41
+ "format": "prettier --write '**/*.{js,jsx}'",
42
+ "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
43
+ "test:watch": "vitest",
44
+ "test": "vitest run"
45
+ }
46
+ }
@@ -0,0 +1,177 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`vite-plugin-jsx > distinguishes between properties (.) and attributes 1`] = `
4
+ "import { html } from "@inglorious/web";
5
+ const App = () => html\`<my-element id=\${id} class=\${cls} aria-label=\${label} data-test=\${test} .someProp=\${value} .complexData=\${obj}></my-element>\`;"
6
+ `;
7
+
8
+ exports[`vite-plugin-jsx > does not change parameters if api is already the last argument 1`] = `
9
+ "import { html } from "@inglorious/web";
10
+ export const app = {
11
+ render(entity, api) {
12
+ return api.render("form");
13
+ }
14
+ };"
15
+ `;
16
+
17
+ exports[`vite-plugin-jsx > does not generate closing tag for void elements 1`] = `
18
+ "import { html } from "@inglorious/web";
19
+ html\`<img src="image.png" />\`;"
20
+ `;
21
+
22
+ exports[`vite-plugin-jsx > does not inject api if component is not inside a 'render' method 1`] = `
23
+ "import { html } from "@inglorious/web";
24
+ export const app = {
25
+ notRender() {
26
+ return api.render("form");
27
+ }
28
+ };"
29
+ `;
30
+
31
+ exports[`vite-plugin-jsx > does not inject api if no capitalized component is used 1`] = `
32
+ "import { html } from "@inglorious/web";
33
+ export const app = {
34
+ render(entity) {
35
+ return html\`<div>\${entity.name}</div>\`;
36
+ }
37
+ };"
38
+ `;
39
+
40
+ exports[`vite-plugin-jsx > expands self-closing non-void HTML tags 1`] = `
41
+ "import { html } from "@inglorious/web";
42
+ html\`<div class="empty"></div>\`;"
43
+ `;
44
+
45
+ exports[`vite-plugin-jsx > handles SVG self-closing tags correctly 1`] = `
46
+ "import { html } from "@inglorious/web";
47
+ const Icon = () => html\`<svg> \${html\`<path d="M0 0h10v10H0z" />\`} \${html\`<circle cx="5" cy="5" r="5" />\`} </svg>\`;"
48
+ `;
49
+
50
+ exports[`vite-plugin-jsx > handles boolean attributes 1`] = `
51
+ "import { html } from "@inglorious/web";
52
+ html\`<input disabled checked readonly />\`;"
53
+ `;
54
+
55
+ exports[`vite-plugin-jsx > handles event listeners (@event syntax) 1`] = `
56
+ "import { html } from "@inglorious/web";
57
+ html\`<button @click=\${handleClick} @mouseover=\${() => {}}>Click</button>\`;"
58
+ `;
59
+
60
+ exports[`vite-plugin-jsx > handles fragments 1`] = `
61
+ "import { html } from "@inglorious/web";
62
+ const List = () => html\` \${html\`<li>A</li>\`} \${html\`<li>B</li>\`} \`;"
63
+ `;
64
+
65
+ exports[`vite-plugin-jsx > handles nested expressions and elements 1`] = `
66
+ "import { html, when } from "@inglorious/web";
67
+ const App = () => html\`<div>\${when(show, () => html\`<span>Visible</span>\`, () => null)}</div>\`;"
68
+ `;
69
+
70
+ exports[`vite-plugin-jsx > ignores empty expressions and comments 1`] = `
71
+ "import { html } from "@inglorious/web";
72
+ const App = () => html\`<div> \${html\`<span>Content</span>\`} </div>\`;"
73
+ `;
74
+
75
+ exports[`vite-plugin-jsx > injects api argument into render function if missing when using components 1`] = `
76
+ "import { html } from "@inglorious/web";
77
+ export const app = {
78
+ render(api) {
79
+ return api.render("form");
80
+ }
81
+ };"
82
+ `;
83
+
84
+ exports[`vite-plugin-jsx > injects api argument when component is nested inside a Fragment 1`] = `
85
+ "import { html } from "@inglorious/web";
86
+ export const app = {
87
+ render(api) {
88
+ return html\` \${api.render("form")} \`;
89
+ }
90
+ };"
91
+ `;
92
+
93
+ exports[`vite-plugin-jsx > injects api argument when component is nested inside standard elements 1`] = `
94
+ "import { html } from "@inglorious/web";
95
+ export const app = {
96
+ render(api) {
97
+ return html\`<div> \${api.render("form")} </div>\`;
98
+ }
99
+ };"
100
+ `;
101
+
102
+ exports[`vite-plugin-jsx > merges imports if @inglorious/web is already imported 1`] = `
103
+ "import { html, when } from "@inglorious/web";
104
+ const App = ({
105
+ show
106
+ }) => html\`<div>\${when(show, () => api.render("a"), () => api.render("b"))}</div>\`;"
107
+ `;
108
+
109
+ exports[`vite-plugin-jsx > moves api parameter to the end if it is not the last one 1`] = `
110
+ "import { html } from "@inglorious/web";
111
+ export const app = {
112
+ render(entity, api) {
113
+ return api.render("form");
114
+ }
115
+ };"
116
+ `;
117
+
118
+ exports[`vite-plugin-jsx > moves api parameter to the end when it is in the middle 1`] = `
119
+ "import { html } from "@inglorious/web";
120
+ export const app = {
121
+ render(entity, options, api) {
122
+ return api.render("form");
123
+ }
124
+ };"
125
+ `;
126
+
127
+ exports[`vite-plugin-jsx > transforms Array.map to repeat directive 1`] = `
128
+ "import { html } from "@inglorious/web";
129
+ const List = ({
130
+ items
131
+ }) => html\`<ul> \${items.map(item => html\`<li>\${item}</li>\`)} </ul>\`;"
132
+ `;
133
+
134
+ exports[`vite-plugin-jsx > transforms Array.map with key to keyed repeat directive 1`] = `
135
+ "import { html } from "@inglorious/web";
136
+ const List = ({
137
+ items
138
+ }) => html\`<ul> \${items.map(item => html\`<li .key=\${item.id}>\${item.name}</li>\`)} </ul>\`;"
139
+ `;
140
+
141
+ exports[`vite-plugin-jsx > transforms basic JSX elements 1`] = `
142
+ "import { html } from "@inglorious/web";
143
+ export const App = () => html\`<div>Hello World</div>\`;"
144
+ `;
145
+
146
+ exports[`vite-plugin-jsx > transforms capitalized components to api.render calls 1`] = `
147
+ "import { html } from "@inglorious/web";
148
+ export const app = {
149
+ render(api) {
150
+ return html\`\${api.render("form", {
151
+ id: "f1",
152
+ title: "My Form"
153
+ })}\${api.render("list", {
154
+ items: []
155
+ })}\${api.render("footer")}\`;
156
+ }
157
+ };"
158
+ `;
159
+
160
+ exports[`vite-plugin-jsx > transforms className to class 1`] = `
161
+ "import { html } from "@inglorious/web";
162
+ html\`<div class="container">Content</div>\`;"
163
+ `;
164
+
165
+ exports[`vite-plugin-jsx > transforms logical AND to when directive 1`] = `
166
+ "import { html, when } from "@inglorious/web";
167
+ const App = ({
168
+ show
169
+ }) => html\`<div>\${when(show, () => api.render("modal"))}</div>\`;"
170
+ `;
171
+
172
+ exports[`vite-plugin-jsx > transforms ternary operators to when directive 1`] = `
173
+ "import { html, when } from "@inglorious/web";
174
+ const App = ({
175
+ isLoggedIn
176
+ }) => html\`<div>\${when(isLoggedIn, () => api.render("user"), () => api.render("login"))}</div>\`;"
177
+ `;