mono-jsx 0.1.3 β†’ 0.3.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.
package/README.md CHANGED
@@ -2,32 +2,34 @@
2
2
 
3
3
  ![`<html>` as a `Response`](./.github/og-image.png)
4
4
 
5
- mono-jsx is a JSX runtime that renders `<html>` element to a `Response` object in JavaScript runtimes like Node.js, Deno, Bun, Cloudflare Workers, etc.
5
+ mono-jsx is a JSX runtime that renders `<html>` element to `Response` object in JavaScript runtimes like Node.js, Deno, Bun, Cloudflare Workers, etc.
6
6
 
7
7
  - πŸš€ No build step needed
8
8
  - πŸ¦‹ Lightweight (8KB gzipped), zero dependencies
9
9
  - πŸ”« Minimal state runtime
10
- - 🚨 Complete Web API Typescript definitions
10
+ - 🚨 Complete Web API TypeScript definitions
11
11
  - ⏳ Streaming rendering
12
12
  - 🌎 Universal, works in Node.js, Deno, Bun, Cloudflare Workers, etc.
13
13
 
14
14
  ## Installation
15
15
 
16
- mono-jsx supports all modern JavaScript runtimes including Node.js, Deno, Bun, Cloudflare Workers, etc.
17
- You can install it via `npm i`, `deno add`, or `bun add`.
16
+ mono-jsx supports all modern JavaScript runtimes including Node.js, Deno, Bun, and Cloudflare Workers.
17
+ You can install it via `npm`, `deno`, or `bun`:
18
18
 
19
19
  ```bash
20
20
  # Node.js, Cloudflare Workers, or other node-compatible runtimes
21
21
  npm i mono-jsx
22
+
22
23
  # Deno
23
24
  deno add npm:mono-jsx
25
+
24
26
  # Bun
25
27
  bun add mono-jsx
26
28
  ```
27
29
 
28
30
  ## Setup JSX Runtime
29
31
 
30
- To use mono-jsx as JSX runtime, add the following configuration to your `tsconfig.json`(`deno.json` for Deno):
32
+ To use mono-jsx as your JSX runtime, add the following configuration to your `tsconfig.json` (or `deno.json` for Deno):
31
33
 
32
34
  ```jsonc
33
35
  {
@@ -38,30 +40,31 @@ To use mono-jsx as JSX runtime, add the following configuration to your `tsconfi
38
40
  }
39
41
  ```
40
42
 
41
- Alternatively, you can also use pragma directive in your JSX file.
43
+ Alternatively, you can use a pragma directive in your JSX file:
42
44
 
43
45
  ```js
44
46
  /** @jsxImportSource mono-jsx */
45
47
  ```
46
48
 
47
- You can also run `mono-jsx setup` to automatically add the configuration to your `tsconfig.json` or `deno.json`.
49
+ You can also run `mono-jsx setup` to automatically add the configuration to your project:
48
50
 
49
51
  ```bash
50
52
  # Node.js, Cloudflare Workers, or other node-compatible runtimes
51
53
  npx mono-jsx setup
54
+
52
55
  # Deno
53
- deno run npm:mono-jsx setup
56
+ deno run -A npm:mono-jsx setup
57
+
54
58
  # Bun
55
59
  bunx mono-jsx setup
56
60
  ```
57
61
 
58
62
  ## Usage
59
63
 
60
- mono-jsx allows you to return an `<html>` JSX element as a `Response` object in the `fetch` handler.
64
+ mono-jsx allows you to return an `<html>` JSX element as a `Response` object in the `fetch` handler:
61
65
 
62
66
  ```tsx
63
67
  // app.tsx
64
-
65
68
  export default {
66
69
  fetch: (req) => (
67
70
  <html>
@@ -71,24 +74,23 @@ export default {
71
74
  };
72
75
  ```
73
76
 
74
- For Deno/Bun users, you can run the `app.tsx` directly.
77
+ For Deno/Bun users, you can run the `app.tsx` directly:
75
78
 
76
79
  ```bash
77
80
  deno serve app.tsx
78
81
  bun run app.tsx
79
82
  ```
80
83
 
81
- If you are building a web app with [Cloudflare Workers](https://developers.cloudflare.com/workers/wrangler/commands/#dev), use `wrangler dev` command to start the app in local development mode.
84
+ If you're building a web app with [Cloudflare Workers](https://developers.cloudflare.com/workers/wrangler/commands/#dev), use `wrangler dev` to start local development:
82
85
 
83
86
  ```bash
84
87
  npx wrangler dev app.tsx
85
88
  ```
86
89
 
87
- **Node.js does not support JSX syntax and declarative fetch server**, we recommend using mono-jsx with [srvx](https://srvx.h3.dev/).
90
+ **Node.js doesn't support JSX syntax or declarative fetch servers**, so we recommend using mono-jsx with [srvx](https://srvx.h3.dev/):
88
91
 
89
92
  ```tsx
90
93
  // app.tsx
91
-
92
94
  import { serve } from "srvx";
93
95
 
94
96
  serve({
@@ -101,7 +103,7 @@ serve({
101
103
  });
102
104
  ```
103
105
 
104
- and you will need [tsx](https://www.npmjs.com/package/tsx) to start the app without a build step.
106
+ You'll need [tsx](https://www.npmjs.com/package/tsx) to start the app without a build step:
105
107
 
106
108
  ```bash
107
109
  npx tsx app.tsx
@@ -109,27 +111,33 @@ npx tsx app.tsx
109
111
 
110
112
  ## Using JSX
111
113
 
112
- mono-jsx uses [**JSX**](https://react.dev/learn/describing-the-ui) to describe the user interface, similar to React but with some differences.
114
+ mono-jsx uses [**JSX**](https://react.dev/learn/describing-the-ui) to describe the user interface, similar to React but with key differences.
113
115
 
114
116
  ### Using Standard HTML Property Names
115
117
 
116
- mono-jsx adopts standard HTML property names, avoiding React's custom property naming conventions.
118
+ mono-jsx adopts standard HTML property names, avoiding React's custom naming conventions:
117
119
 
118
- - `className` becomes `class`
119
- - `htmlFor` becomes `for`
120
- - `onChange` becomes `onInput`
120
+ - `className` β†’ `class`
121
+ - `htmlFor` β†’ `for`
122
+ - `onChange` β†’ `onInput`
121
123
 
122
- ### Composition `class`
124
+ ### Composition with `class`
123
125
 
124
- mono-jsx allows you to compose the `class` property using an array of strings, objects, or expressions.
126
+ mono-jsx allows you to compose the `class` property using arrays of strings, objects, or expressions:
125
127
 
126
128
  ```jsx
127
- <div class={["container box", isActive && "active", { hover: isHover }]} />;
129
+ <div
130
+ class={[
131
+ "container box",
132
+ isActive && "active",
133
+ { hover: isHover },
134
+ ]}
135
+ />;
128
136
  ```
129
137
 
130
- ### Using Pseudo Classes and Media Queries in the `style` Property
138
+ ### Using Pseudo Classes and Media Queries in `style`
131
139
 
132
- mono-jsx allows you to use [pseudo classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes), [pseudo elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements), [media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries/Using_media_queries), and [css nesting](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting) in the `style` property.
140
+ mono-jsx supports [pseudo classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes), [pseudo elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements), [media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries/Using_media_queries), and [CSS nesting](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting) in the `style` property:
133
141
 
134
142
  ```jsx
135
143
  <a
@@ -148,14 +156,16 @@ mono-jsx allows you to use [pseudo classes](https://developer.mozilla.org/en-US/
148
156
 
149
157
  ### `<slot>` Element
150
158
 
151
- mono-jsx uses [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) element to render the slotted content (Equivalent to React's `children` property). Plus, you also can add the `name` attribute to define a named slot.
159
+ mono-jsx uses [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) elements to render slotted content (equivalent to React's `children` property). You can also add the `name` attribute to define named slots:
152
160
 
153
161
  ```jsx
154
162
  function Container() {
155
163
  return (
156
164
  <div class="container">
157
- <slot /> {/* <h1>Hello world!</h1> */}
158
- <slot name="desc" /> {/* <p>This is a description.</p> */}
165
+ {/* Default slot */}
166
+ <slot />
167
+ {/* Named slot */}
168
+ <slot name="desc" />
159
169
  </div>
160
170
  );
161
171
  }
@@ -163,7 +173,9 @@ function Container() {
163
173
  function App() {
164
174
  return (
165
175
  <Container>
176
+ {/* This goes to the named slot */}
166
177
  <p slot="desc">This is a description.</p>
178
+ {/* This goes to the default slot */}
167
179
  <h1>Hello world!</h1>
168
180
  </Container>
169
181
  );
@@ -172,7 +184,7 @@ function App() {
172
184
 
173
185
  ### `html` Tag Function
174
186
 
175
- mono-jsx doesn't support the `dangerouslySetInnerHTML` property, instead, it provides a `html` tag function to render raw HTML in JSX.
187
+ mono-jsx provides an `html` tag function to render raw HTML in JSX instead of React's `dangerouslySetInnerHTML`:
176
188
 
177
189
  ```jsx
178
190
  function App() {
@@ -180,8 +192,7 @@ function App() {
180
192
  }
181
193
  ```
182
194
 
183
- The `html` tag function is a global function injected by mono-jsx, you can use it in any JSX expression without importing it.
184
- You also can use the `css` and `js`, that are just aliases of the `html` tag function, to render CSS and JavaScript code.
195
+ The `html` tag function is globally available without importing. You can also use `css` and `js` tag functions for CSS and JavaScript:
185
196
 
186
197
  ```jsx
187
198
  function App() {
@@ -195,31 +206,38 @@ function App() {
195
206
  ```
196
207
 
197
208
  > [!WARNING]
198
- > the `html` tag function is **unsafe** that can cause [**XSS**](https://en.wikipedia.org/wiki/Cross-site_scripting) vulnerabilities.
209
+ > The `html` tag function is **unsafe** and can cause [**XSS**](https://en.wikipedia.org/wiki/Cross-site_scripting) vulnerabilities.
199
210
 
200
211
  ### Event Handlers
201
212
 
202
- mono-jsx allows you to write event handlers directly in the JSX code, like React.
213
+ mono-jsx lets you write event handlers directly in JSX, similar to React:
203
214
 
204
215
  ```jsx
205
216
  function Button() {
206
- return <button onClick={(evt) => alert("BOOM!")}>Click Me</button>;
217
+ return (
218
+ <button onClick={(evt) => alert("BOOM!")}>
219
+ Click Me
220
+ </button>
221
+ );
207
222
  }
208
223
  ```
209
224
 
210
225
  > [!NOTE]
211
- > the event handler would never be called in server-side. It will be serialized to a string and sent to the client-side. **This means you should NOT use any server-side variables or functions in the event handler.**
226
+ > Event handlers are never called on the server-side. They're serialized to strings and sent to the client. **This means you should NOT use server-side variables or functions in event handlers.**
212
227
 
213
228
  ```tsx
229
+ import { doSomething } from "some-library";
230
+
214
231
  function Button(this: FC, props: { role: string }) {
215
232
  let message = "BOOM!";
216
- console.log(message); // only print message in server-side
233
+ console.log(message); // only executes on server-side
217
234
  return (
218
235
  <button
219
236
  role={props.role}
220
237
  onClick={(evt) => {
221
238
  alert(message); // ❌ `message` is a server-side variable
222
239
  console.log(props.role); // ❌ `props` is a server-side variable
240
+ doSomething(); // ❌ `doSomething` is imported on the server-side
223
241
  Deno.exit(0); // ❌ `Deno` is unavailable in the browser
224
242
  document.title = "BOOM!"; // βœ… `document` is a browser API
225
243
  console.log(evt.target); // βœ… `evt` is the event object
@@ -232,7 +250,7 @@ function Button(this: FC, props: { role: string }) {
232
250
  }
233
251
  ```
234
252
 
235
- Plus, mono-jsx supports the `mount` event that will be triggered when the element is mounted in the client-side.
253
+ Additionally, mono-jsx supports the `mount` event for when elements are mounted in the client-side DOM:
236
254
 
237
255
  ```jsx
238
256
  function App() {
@@ -244,14 +262,14 @@ function App() {
244
262
  }
245
263
  ```
246
264
 
247
- mono-jsx also accepts a function as the `action` property for `form` elements, which will be called when the form is submitted.
265
+ mono-jsx also accepts functions for the `action` property on `form` elements, which will be called on form submission:
248
266
 
249
267
  ```tsx
250
268
  function App() {
251
269
  return (
252
270
  <form
253
- action={(data: FormData, evt) => {
254
- evt.defaultPrevented // true
271
+ action={(data: FormData, event: SubmitEvent) => {
272
+ event.preventDefault(); // true
255
273
  console.log(data.get("name"));
256
274
  }}
257
275
  >
@@ -262,23 +280,28 @@ function App() {
262
280
  }
263
281
  ```
264
282
 
265
- ## Using State
283
+ ## Reactive
284
+
285
+ mono-jsx provides a minimal state runtime for updating the view based on client-side state changes:
286
+
287
+ ### Using State
266
288
 
267
- mono-jsx provides a minimal state runtime that allows you to update view based on state changes in client-side.
289
+ You can use `this` to define state in your components. The view will automatically update when the state changes:
268
290
 
269
291
  ```tsx
270
292
  function Counter(
271
293
  this: FC<{ count: number }>,
272
294
  props: { initialCount?: number },
273
295
  ) {
296
+ // Initialize state
274
297
  this.count = props.initialCount ?? 0;
298
+
275
299
  return (
276
300
  <div>
277
- {/* use the state */}
301
+ {/* render state */}
278
302
  <span>{this.count}</span>
279
- {/* use computed state */}
280
- <span>doubled: {this.computed(() => 2 * this.count)}</span>
281
- {/* update the state in event handlers */}
303
+
304
+ {/* Update state to trigger re-render */}
282
305
  <button onClick={() => this.count--}>-</button>
283
306
  <button onClick={() => this.count++}>+</button>
284
307
  </div>
@@ -286,11 +309,77 @@ function Counter(
286
309
  }
287
310
  ```
288
311
 
289
- > [!WARNING]
290
- > The state cannot be used in an arrow function component, you should use a `function` declaration instead.
312
+ ### Using App State
291
313
 
292
- ```jsx
293
- // ❌ `this.count++` won't update the view, please use a function declaration instead
314
+ You can define app state by adding `appState` prop to the root `<html>` element. The app state is available in all components via `this.app.<stateKey>`. Changes to the app state will trigger re-renders in all components that use it:
315
+
316
+ ```tsx
317
+ function Header(this: FC<{}, { title: string }>) {
318
+ return (
319
+ <header>
320
+ <h1>{this.app.title}</h1>
321
+ </header>
322
+ );
323
+ }
324
+
325
+ function Footer(this: FC<{}, { title: string }>) {
326
+ return (
327
+ <footer>
328
+ <p>(c) 2025 {this.app.title}</p>
329
+ </footer>
330
+ );
331
+ }
332
+
333
+ function Main(this: FC<{}, { title: string }>) {
334
+ return (
335
+ <main>
336
+ <h1>{this.app.title}</h1>
337
+ <h2>Changing the title</h2>
338
+ <input
339
+ onInput={(evt) => this.app.title = evt.target.value }
340
+ placeholder="Enter a new title"
341
+ />
342
+ </main>
343
+ );
344
+ }
345
+
346
+ export default {
347
+ fetch: (req) => (
348
+ <html appState={{ title: "Welcome to mono-jsx!" }}>
349
+ <Header />
350
+ <Main />
351
+ <Footer />
352
+ </html>
353
+ ),
354
+ };
355
+ ```
356
+
357
+ ### Using Computed State
358
+
359
+ You can use `this.computed` to create computed state based on state. The computed state will automatically update when the state changes:
360
+
361
+ ```tsx
362
+ function App(this: FC<{ input: string }>) {
363
+ this.input = "Welcome to mono-jsx!";
364
+ return (
365
+ <div>
366
+ <h1>{this.computed(() => this.input + "!")}</h1>
367
+
368
+ <form action={(fd) => this.input = fd.get("input") as string}>
369
+ <input type="text" name="input" value={this.input} />
370
+ <button type="submit">Submit</button>
371
+ </form>
372
+ </div>
373
+ );
374
+ }
375
+ ```
376
+
377
+ ### Limitation of States
378
+
379
+ 1\. States cannot be used in arrow function components.
380
+
381
+ ```tsx
382
+ // ❌ Won't work - state updates won't refresh the view
294
383
  const App = () => {
295
384
  this.count = 0;
296
385
  return (
@@ -300,40 +389,87 @@ const App = () => {
300
389
  </div>
301
390
  );
302
391
  };
392
+
393
+ // βœ… Works correctly
394
+ function App(this: FC) {
395
+ this.count = 0;
396
+ return (
397
+ <div>
398
+ <span>{this.count}</span>
399
+ <button onClick={() => this.count++}>+</button>
400
+ </div>
401
+ );
402
+ }
403
+ ```
404
+
405
+ 2\. States cannot be computed outside of the `this.computed` method.
406
+
407
+ ```tsx
408
+ // ❌ Won't work - state updates won't refresh the view
409
+ function App(this: FC<{ message: string }>) {
410
+ this.message = "Welcome to mono-jsx!";
411
+ return (
412
+ <div>
413
+ <h1 title={this.message + "!"}>{this.message + "!"}</h1>
414
+ <button onClick={() => this.message = "Clicked"}>
415
+ Click Me
416
+ </button>
417
+ </div>
418
+ );
419
+ }
420
+
421
+ // βœ… Works correctly
422
+ function App(this: FC) {
423
+ this.message = "Welcome to mono-jsx!";
424
+ return (
425
+ <div>
426
+ <h1 title={this.computed(() => this.message + "!")}>{this.computed(() => this.message + "!")}</h1>
427
+ <button onClick={() => this.message = "Clicked"}>
428
+ Click Me
429
+ </button>
430
+ </div>
431
+ );
432
+ }
303
433
  ```
304
434
 
305
435
  ## Built-in Elements
306
436
 
307
- mono-jsx provides some built-in elements to help you build your app.
437
+ mono-jsx provides built-in elements to help you build reactive UIs.
308
438
 
309
439
  ### `<toggle>` element
310
440
 
311
- `<toggle>` element allows you to toggle the visibility of the slotted content.
441
+ The `<toggle>` element conditionally renders content based on a boolean value:
312
442
 
313
443
  ```tsx
314
444
  function App(this: FC<{ show: boolean }>) {
315
445
  this.show = false;
446
+
447
+ function toggle() {
448
+ this.show = !this.show;
449
+ }
450
+
316
451
  return (
317
452
  <div>
318
453
  <toggle value={this.show}>
319
454
  <h1>Welcome to mono-jsx!</h1>
320
455
  </toggle>
321
- <button onClick={toggle}>{this.computed(() => this.show ? "Hide" : "Show")}</button>
456
+
457
+ <button onClick={toggle}>
458
+ {this.computed(() => this.show ? "Hide" : "Show")}
459
+ </button>
322
460
  </div>
323
461
  );
324
- function toggle() {
325
- this.show = !this.show;
326
- }
327
462
  }
328
463
  ```
329
464
 
330
465
  ### `<switch>` element
331
466
 
332
- `<switch>` element allows you to switch the slotted content based on the `value` property. You need to define the `slot` attribute in the slotted content to match the `value`, otherwise, the default slots will be rendered.
467
+ The `<switch>` element renders different content based on a value. Elements with matching `slot` attributes are displayed when their value matches, otherwise default content is shown:
333
468
 
334
469
  ```tsx
335
470
  function App(this: FC<{ lang: "en" | "zh" | "emoji" }>) {
336
471
  this.lang = "en";
472
+
337
473
  return (
338
474
  <div>
339
475
  <switch value={this.lang}>
@@ -341,6 +477,7 @@ function App(this: FC<{ lang: "en" | "zh" | "emoji" }>) {
341
477
  <h1 slot="zh">δ½ ε₯½οΌŒδΈ–η•ŒοΌ</h1>
342
478
  <h1>βœ‹πŸŒŽβ—οΈ</h1>
343
479
  </switch>
480
+
344
481
  <button onClick={() => this.lang = "en"}>English</button>
345
482
  <button onClick={() => this.lang = "zh"}>δΈ­ζ–‡</button>
346
483
  <button onClick={() => this.lang = "emoji"}>Emoji</button>
@@ -351,10 +488,10 @@ function App(this: FC<{ lang: "en" | "zh" | "emoji" }>) {
351
488
 
352
489
  ## Streaming Rendering
353
490
 
354
- mono-jsx renders your `<html>` as a readable stream, that allows async function components are rendered asynchronously. You can set a `placeholder` attribute to show a loading state while the async component is loading.
491
+ mono-jsx renders your `<html>` as a readable stream, allowing async components to render asynchronously. You can use `placeholder` to display a loading state while waiting for async components to render:
355
492
 
356
493
  ```jsx
357
- async function Sleep(ms) {
494
+ async function Sleep({ ms }) {
358
495
  await new Promise((resolve) => setTimeout(resolve, ms));
359
496
  return <slot />;
360
497
  }
@@ -363,6 +500,7 @@ export default {
363
500
  fetch: (req) => (
364
501
  <html>
365
502
  <h1>Welcome to mono-jsx!</h1>
503
+
366
504
  <Sleep ms={1000} placeholder={<p>Sleeping...</p>}>
367
505
  <p>After 1 second</p>
368
506
  </Sleep>
@@ -371,10 +509,10 @@ export default {
371
509
  };
372
510
  ```
373
511
 
374
- You can also set `rendering` attribute to "eager" to render the async component eagerly, which means the async component will be rendered as a sync function component and the `placeholder` will be ignored.
512
+ You can set the `rendering` attribute to `"eager"` to force synchronous rendering (the `placeholder` will be ignored):
375
513
 
376
514
  ```jsx
377
- async function Sleep(ms) {
515
+ async function Sleep({ ms }) {
378
516
  await new Promise((resolve) => setTimeout(resolve, ms));
379
517
  return <slot />;
380
518
  }
@@ -383,6 +521,7 @@ export default {
383
521
  fetch: (req) => (
384
522
  <html>
385
523
  <h1>Welcome to mono-jsx!</h1>
524
+
386
525
  <Sleep ms={1000} rendering="eager">
387
526
  <p>After 1 second</p>
388
527
  </Sleep>
@@ -391,9 +530,37 @@ export default {
391
530
  };
392
531
  ```
393
532
 
533
+ ## Using Context
534
+
535
+ You can use the `context` property in `this` to access context values in your components. The context is defined on the root `<html>` element:
536
+
537
+ ```tsx
538
+ function Dash(this: FC<{}, {}, { auth: { uuid: string; name: string } }>) {
539
+ const { auth } = this.context;
540
+ return (
541
+ <div>
542
+ <h1>Welcome back, {auth.name}!</h1>
543
+ <p>Your UUID is {auth.uuid}</p>
544
+ </div>
545
+ );
546
+ }
547
+
548
+ export default {
549
+ fetch: async (req) => {
550
+ const auth = await doAuth(req);
551
+ return (
552
+ <html context={{ auth }} request={req}>
553
+ {!auth && <p>Please Login</p>}
554
+ {auth && <Dash />}
555
+ </html>
556
+ );
557
+ },
558
+ };
559
+ ```
560
+
394
561
  ## Accessing Request Info
395
562
 
396
- You can access the request info in a function component by using the `request` property in the `this` context. And you must pass the `request` object to the root `<html>` element to make it work.
563
+ You can access request information in components via the `request` property in `this` which is set on the root `<html>` element:
397
564
 
398
565
  ```tsx
399
566
  function RequestInfo(this: FC) {
@@ -419,7 +586,7 @@ export default {
419
586
 
420
587
  ## Customizing Response
421
588
 
422
- You can add `status` or `headers` attribute to the `<html>` element to customize the response.
589
+ Add `status` or `headers` attributes to the root `<html>` element to customize the response:
423
590
 
424
591
  ```jsx
425
592
  export default {
package/bin/mono-jsx CHANGED
@@ -1,34 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { readFile, writeFile } from "node:fs/promises";
4
3
  import process from "node:process";
4
+ import { setup } from "../setup.mjs";
5
5
 
6
6
  switch (process.argv[2]) {
7
7
  case "setup":
8
- setup().then(() => {
9
- console.log("βœ… JSX runtime setup complete.");
10
- });
8
+ setup()
11
9
  break;
12
10
  default:
13
11
  process.exit(0);
14
12
  }
15
-
16
- async function setup() {
17
- let tsConfigPath = globalThis.Deno ? "deno.json" : "tsconfig.json";
18
- let tsConfig = Object.create(null);
19
- try {
20
- const json = await readFile(tsConfigPath, "utf8");
21
- tsConfig = JSON.parse(json);
22
- } catch {
23
- // ignore
24
- }
25
- tsConfig.compilerOptions = {
26
- ...tsConfig.compilerOptions,
27
- jsx: "react-jsx",
28
- jsxImportSource: "mono-jsx",
29
- };
30
- if (!globalThis.Deno) {
31
- tsConfig.compilerOptions.alllowJs = true
32
- }
33
- await writeFile(tsConfigPath, JSON.stringify(tsConfig, null, 2));
34
- }