mono-jsx 0.3.0 → 0.3.1

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
@@ -109,6 +109,9 @@ You'll need [tsx](https://www.npmjs.com/package/tsx) to start the app without a
109
109
  npx tsx app.tsx
110
110
  ```
111
111
 
112
+ > [!NOTE]
113
+ > Only root `<html>` element will be rendered as a `Response` object. You cannot return a `<div>` or any other element directly from the `fetch` handler. This is a limitation of the mono-jsx runtime.
114
+
112
115
  ## Using JSX
113
116
 
114
117
  mono-jsx uses [**JSX**](https://react.dev/learn/describing-the-ui) to describe the user interface, similar to React but with key differences.
@@ -336,7 +339,7 @@ function Main(this: FC<{}, { title: string }>) {
336
339
  <h1>{this.app.title}</h1>
337
340
  <h2>Changing the title</h2>
338
341
  <input
339
- onInput={(evt) => this.app.title = evt.target.value }
342
+ onInput={(evt) => this.app.title = evt.target.value}
340
343
  placeholder="Enter a new title"
341
344
  />
342
345
  </main>
@@ -604,6 +607,88 @@ export default {
604
607
  };
605
608
  ```
606
609
 
610
+ ## Using htmx
611
+
612
+ mono-jsx integrates with [htmx](https://htmx.org/) and [typed-htmx](https://github.com/Desdaemon/typed-htmx). To use htmx, add the `htmx` attribute to the root `<html>` element:
613
+
614
+ ```jsx
615
+ export default {
616
+ fetch: (req) => {
617
+ const url = new URL(req.url);
618
+
619
+ if (url.pathname === "/clicked") {
620
+ return (
621
+ <html>
622
+ <span>Clicked!</span>
623
+ </html>
624
+ );
625
+ }
626
+
627
+ return (
628
+ <html htmx>
629
+ <button hx-get="/clicked" hx-swap="outerHTML">
630
+ Click Me
631
+ </button>
632
+ </html>
633
+ );
634
+ },
635
+ };
636
+ ```
637
+
638
+ ### Adding htmx Extensions
639
+
640
+ You can add htmx [extensions](https://htmx.org/docs/#extensions) by adding the `htmx-ext-*` attribute to the root `<html>` element:
641
+
642
+ ```jsx
643
+ export default {
644
+ fetch: (req) => (
645
+ <html htmx htmx-ext-response-targets htmx-ext-ws>
646
+ <button hx-get="/clicked" hx-swap="outerHTML">
647
+ Click Me
648
+ </button>
649
+ </html>
650
+ ),
651
+ };
652
+ ```
653
+
654
+ ### Specifying htmx Version
655
+
656
+ You can specify the htmx version by setting the `htmx` attribute to a specific version:
657
+
658
+ ```jsx
659
+ export default {
660
+ fetch: (req) => (
661
+ <html htmx="2.0.4" htmx-ext-response-targets="2.0.2" htmx-ext-ws="2.0.2">
662
+ <button hx-get="/clicked" hx-swap="outerHTML">
663
+ Click Me
664
+ </button>
665
+ </html>
666
+ ),
667
+ };
668
+ ```
669
+
670
+ ### Installing htmx Manually
671
+
672
+ By default, mono-jsx installs htmx from [esm.sh](https://esm.sh/) CDN when you set the `htmx` attribute. You can also install htmx manually with your own CDN or local copy:
673
+
674
+ ```jsx
675
+ export default {
676
+ fetch: (req) => (
677
+ <html>
678
+ <head>
679
+ <script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
680
+ <script src="https://unpkg.com/htmx-ext-ws@2.0.2" integrity="sha384-vuKxTKv5TX/b3lLzDKP2U363sOAoRo5wSvzzc3LJsbaQRSBSS+3rKKHcOx5J8doU" crossorigin="anonymous"></script>
681
+ </head>
682
+ <body>
683
+ <button hx-get="/clicked" hx-swap="outerHTML">
684
+ Click Me
685
+ </button>
686
+ </body>
687
+ </html>
688
+ ),
689
+ };
690
+ ```
691
+
607
692
  ## License
608
693
 
609
694
  [MIT](LICENSE)
package/jsx-runtime.mjs CHANGED
@@ -11,12 +11,12 @@ function createState(fc, appState, context, request) {
11
11
  const computed = (fn) => {
12
12
  const deps = /* @__PURE__ */ Object.create(null);
13
13
  collectDeps = (fc2, key, value2) => deps[fc2 + ":" + key] = value2;
14
- const value = fn();
14
+ const value = fn.call(proxy);
15
15
  collectDeps = void 0;
16
16
  if (value instanceof Promise || deps.size === 0) return value;
17
17
  return [$computed, { value, deps, fn: fn.toString(), fc }, $vnode];
18
18
  };
19
- return new Proxy(/* @__PURE__ */ Object.create(null), {
19
+ const proxy = new Proxy(/* @__PURE__ */ Object.create(null), {
20
20
  get(target, key, receiver) {
21
21
  switch (key) {
22
22
  case "app":
@@ -47,6 +47,7 @@ function createState(fc, appState, context, request) {
47
47
  return Reflect.set(target, key, value, receiver);
48
48
  }
49
49
  });
50
+ return proxy;
50
51
  }
51
52
 
52
53
  // runtime/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mono-jsx",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "`<html>` as a `Response`.",
5
5
  "type": "module",
6
6
  "module": "./index.mjs",
@@ -26,8 +26,7 @@
26
26
  }
27
27
  },
28
28
  "scripts": {
29
- "prepublishOnly": "deno task build",
30
- "postinstall": "node setup.mjs"
29
+ "prepublishOnly": "deno task build"
31
30
  },
32
31
  "files": [
33
32
  "*.mjs",
package/setup.mjs CHANGED
@@ -1,8 +1,6 @@
1
1
  // setup.ts
2
2
  import { existsSync } from "node:fs";
3
3
  import { readFile, writeFile } from "node:fs/promises";
4
- import { fileURLToPath } from "node:url";
5
- import { argv } from "node:process";
6
4
  async function setup() {
7
5
  if (globalThis.Deno && existsSync("deno.jsonc")) {
8
6
  console.log("Please add the following options to your deno.jsonc file:");
@@ -41,18 +39,6 @@ async function setup() {
41
39
  await writeFile(tsConfigFilename, JSON.stringify(tsConfig, null, 2));
42
40
  console.log("\u2705 mono-jsx setup complete.");
43
41
  }
44
- function isMain() {
45
- if (import.meta.main) {
46
- return true;
47
- }
48
- if (import.meta.url.startsWith("file:")) {
49
- return argv[1] === fileURLToPath(import.meta.url);
50
- }
51
- return false;
52
- }
53
- if (isMain()) {
54
- setup();
55
- }
56
42
  export {
57
43
  setup
58
44
  };