honox 0.1.1 → 0.1.2
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 +1 -1
- package/dist/client/client.d.ts +5 -1
- package/dist/client/client.js +12 -1
- package/dist/client/runtime.d.ts +5 -0
- package/dist/client/runtime.js +81 -0
- package/dist/constants.d.ts +2 -1
- package/dist/constants.js +2 -0
- package/dist/server/components/script.d.ts +1 -0
- package/dist/server/components/script.js +9 -2
- package/dist/server/server.js +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/utils/file.js +1 -1
- package/dist/vite/island-components.js +29 -2
- package/package.json +2 -2
package/README.md
CHANGED
package/dist/client/client.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { Hydrate, CreateElement } from '../types.js';
|
|
1
|
+
import { Hydrate, CreateElement, CreateChildren } from '../types.js';
|
|
2
2
|
|
|
3
3
|
type ClientOptions = {
|
|
4
4
|
hydrate?: Hydrate;
|
|
5
5
|
createElement?: CreateElement;
|
|
6
|
+
/**
|
|
7
|
+
* Create "children" attribute of a component from a list of child nodes
|
|
8
|
+
*/
|
|
9
|
+
createChildren?: CreateChildren;
|
|
6
10
|
ISLAND_FILES?: Record<string, () => Promise<unknown>>;
|
|
7
11
|
island_root?: string;
|
|
8
12
|
};
|
package/dist/client/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { render } from "hono/jsx/dom";
|
|
2
2
|
import { jsx as jsxFn } from "hono/jsx/dom/jsx-runtime";
|
|
3
|
-
import { COMPONENT_NAME, DATA_SERIALIZED_PROPS } from "../constants.js";
|
|
3
|
+
import { COMPONENT_NAME, DATA_HONO_TEMPLATE, DATA_SERIALIZED_PROPS } from "../constants.js";
|
|
4
4
|
const createClient = async (options) => {
|
|
5
5
|
const FILES = options?.ISLAND_FILES ?? import.meta.glob("/app/islands/**/[a-zA-Z0-9[-]+.(tsx|ts)");
|
|
6
6
|
const root = options?.island_root ?? "/app/islands/";
|
|
@@ -17,6 +17,17 @@ const createClient = async (options) => {
|
|
|
17
17
|
const props = JSON.parse(serializedProps ?? "{}");
|
|
18
18
|
const hydrate = options?.hydrate ?? render;
|
|
19
19
|
const createElement = options?.createElement ?? jsxFn;
|
|
20
|
+
const maybeTemplate = element.childNodes[element.childNodes.length - 1];
|
|
21
|
+
if (maybeTemplate?.nodeName === "TEMPLATE" && maybeTemplate?.attributes.getNamedItem(DATA_HONO_TEMPLATE) !== null) {
|
|
22
|
+
let createChildren = options?.createChildren;
|
|
23
|
+
if (!createChildren) {
|
|
24
|
+
const { buildCreateChildrenFn } = await import("./runtime");
|
|
25
|
+
createChildren = buildCreateChildrenFn(createElement);
|
|
26
|
+
}
|
|
27
|
+
props.children = await createChildren(
|
|
28
|
+
maybeTemplate.content.childNodes
|
|
29
|
+
);
|
|
30
|
+
}
|
|
20
31
|
const newElem = await createElement(Component, props);
|
|
21
32
|
await hydrate(newElem, element);
|
|
22
33
|
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Suspense, use } from "hono/jsx/dom";
|
|
2
|
+
const buildCreateChildrenFn = (createElement) => {
|
|
3
|
+
const createChildren = async (childNodes) => {
|
|
4
|
+
const children = [];
|
|
5
|
+
for (let i = 0; i < childNodes.length; i++) {
|
|
6
|
+
const child = childNodes[i];
|
|
7
|
+
if (child.nodeType === 8) {
|
|
8
|
+
continue;
|
|
9
|
+
} else if (child.nodeType === 3) {
|
|
10
|
+
children.push(child.textContent);
|
|
11
|
+
} else if (child.nodeName === "TEMPLATE" && child.id.match(/(?:H|E):\d+/)) {
|
|
12
|
+
const placeholderElement = document.createElement("hono-placeholder");
|
|
13
|
+
placeholderElement.style.display = "none";
|
|
14
|
+
let resolve;
|
|
15
|
+
const promise = new Promise((r) => resolve = r);
|
|
16
|
+
child.replaceWith = (node) => {
|
|
17
|
+
createChildren(node.childNodes).then(resolve);
|
|
18
|
+
placeholderElement.remove();
|
|
19
|
+
};
|
|
20
|
+
let fallback = [];
|
|
21
|
+
for (
|
|
22
|
+
// equivalent to i++
|
|
23
|
+
placeholderElement.appendChild(child);
|
|
24
|
+
i < childNodes.length;
|
|
25
|
+
i++
|
|
26
|
+
) {
|
|
27
|
+
const child2 = childNodes[i];
|
|
28
|
+
if (child2.nodeType === 8) {
|
|
29
|
+
placeholderElement.appendChild(child2);
|
|
30
|
+
i--;
|
|
31
|
+
break;
|
|
32
|
+
} else if (child2.nodeType === 3) {
|
|
33
|
+
fallback.push(child2.textContent);
|
|
34
|
+
} else {
|
|
35
|
+
fallback.push(
|
|
36
|
+
await createElement(child2.nodeName, {
|
|
37
|
+
children: await createChildren(child2.childNodes)
|
|
38
|
+
})
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const fallbackTemplates = document.querySelectorAll(
|
|
43
|
+
`[data-hono-target="${child.id}"]`
|
|
44
|
+
);
|
|
45
|
+
if (fallbackTemplates.length > 0) {
|
|
46
|
+
const fallbackTemplate = fallbackTemplates[fallbackTemplates.length - 1];
|
|
47
|
+
fallback = await createChildren(fallbackTemplate.content.childNodes);
|
|
48
|
+
}
|
|
49
|
+
if (fallback.length === 0 && child.id.startsWith("E:")) {
|
|
50
|
+
let resolve2;
|
|
51
|
+
const promise2 = new Promise((r) => resolve2 = r);
|
|
52
|
+
fallback = await createElement(Suspense, {
|
|
53
|
+
fallback: [],
|
|
54
|
+
children: [await createElement(() => use(promise2), {})]
|
|
55
|
+
});
|
|
56
|
+
placeholderElement.insertBefore = (node) => {
|
|
57
|
+
createChildren(node.childNodes).then(resolve2);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
document.body.appendChild(placeholderElement);
|
|
61
|
+
children.push(
|
|
62
|
+
await createElement(Suspense, {
|
|
63
|
+
fallback,
|
|
64
|
+
children: [await createElement(() => use(promise), {})]
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
} else {
|
|
68
|
+
children.push(
|
|
69
|
+
await createElement(child.nodeName, {
|
|
70
|
+
children: await createChildren(child.childNodes)
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return children;
|
|
76
|
+
};
|
|
77
|
+
return createChildren;
|
|
78
|
+
};
|
|
79
|
+
export {
|
|
80
|
+
buildCreateChildrenFn
|
|
81
|
+
};
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
declare const COMPONENT_NAME = "component-name";
|
|
2
2
|
declare const DATA_SERIALIZED_PROPS = "data-serialized-props";
|
|
3
|
+
declare const DATA_HONO_TEMPLATE = "data-hono-template";
|
|
3
4
|
declare const IMPORTING_ISLANDS_ID: "__importing_islands";
|
|
4
5
|
|
|
5
|
-
export { COMPONENT_NAME, DATA_SERIALIZED_PROPS, IMPORTING_ISLANDS_ID };
|
|
6
|
+
export { COMPONENT_NAME, DATA_HONO_TEMPLATE, DATA_SERIALIZED_PROPS, IMPORTING_ISLANDS_ID };
|
package/dist/constants.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const COMPONENT_NAME = "component-name";
|
|
2
2
|
const DATA_SERIALIZED_PROPS = "data-serialized-props";
|
|
3
|
+
const DATA_HONO_TEMPLATE = "data-hono-template";
|
|
3
4
|
const IMPORTING_ISLANDS_ID = "__importing_islands";
|
|
4
5
|
export {
|
|
5
6
|
COMPONENT_NAME,
|
|
7
|
+
DATA_HONO_TEMPLATE,
|
|
6
8
|
DATA_SERIALIZED_PROPS,
|
|
7
9
|
IMPORTING_ISLANDS_ID
|
|
8
10
|
};
|
|
@@ -18,12 +18,19 @@ const Script = async (options) => {
|
|
|
18
18
|
if (manifest) {
|
|
19
19
|
const scriptInManifest = manifest[src.replace(/^\//, "")];
|
|
20
20
|
if (scriptInManifest) {
|
|
21
|
-
return /* @__PURE__ */ jsx(HasIslands, { children: /* @__PURE__ */ jsx(
|
|
21
|
+
return /* @__PURE__ */ jsx(HasIslands, { children: /* @__PURE__ */ jsx(
|
|
22
|
+
"script",
|
|
23
|
+
{
|
|
24
|
+
type: "module",
|
|
25
|
+
async: !!options.async,
|
|
26
|
+
src: `/${scriptInManifest.file}`
|
|
27
|
+
}
|
|
28
|
+
) });
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
31
|
return /* @__PURE__ */ jsx(Fragment, {});
|
|
25
32
|
} else {
|
|
26
|
-
return /* @__PURE__ */ jsx("script", { type: "module", src });
|
|
33
|
+
return /* @__PURE__ */ jsx("script", { type: "module", async: !!options.async, src });
|
|
27
34
|
}
|
|
28
35
|
};
|
|
29
36
|
export {
|
package/dist/server/server.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** JSX */
|
|
2
2
|
type CreateElement = (type: any, props: any) => Node | Promise<Node>;
|
|
3
3
|
type Hydrate = (children: Node, parent: Element) => void | Promise<void>;
|
|
4
|
+
type CreateChildren = (childNodes: NodeListOf<ChildNode>) => Node[] | Promise<Node[]>;
|
|
4
5
|
|
|
5
|
-
export type { CreateElement, Hydrate };
|
|
6
|
+
export type { CreateChildren, CreateElement, Hydrate };
|
package/dist/utils/file.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const filePathToPath = (filePath) => {
|
|
2
|
-
filePath = filePath.replace(/\.tsx?$/g, "").replace(/\.mdx$/g, "").replace(/^\/?index
|
|
2
|
+
filePath = filePath.replace(/\.tsx?$/g, "").replace(/\.mdx$/g, "").replace(/^\/?index$/, "/").replace(/\/index$/, "").replace(/\[\.{3}.+\]/, "*").replace(/\[(.+?)\]/g, ":$1");
|
|
3
3
|
return /^\//.test(filePath) ? filePath : "/" + filePath;
|
|
4
4
|
};
|
|
5
5
|
const groupByDirectory = (files) => {
|
|
@@ -24,13 +24,25 @@ import {
|
|
|
24
24
|
conditionalExpression,
|
|
25
25
|
memberExpression
|
|
26
26
|
} from "@babel/types";
|
|
27
|
-
import { COMPONENT_NAME, DATA_SERIALIZED_PROPS } from "../constants.js";
|
|
27
|
+
import { COMPONENT_NAME, DATA_HONO_TEMPLATE, DATA_SERIALIZED_PROPS } from "../constants.js";
|
|
28
28
|
function addSSRCheck(funcName, componentName, isAsync = false) {
|
|
29
29
|
const isSSR = memberExpression(
|
|
30
30
|
memberExpression(identifier("import"), identifier("meta")),
|
|
31
31
|
identifier("env.SSR")
|
|
32
32
|
);
|
|
33
|
-
const serializedProps = callExpression(identifier("JSON.stringify"), [
|
|
33
|
+
const serializedProps = callExpression(identifier("JSON.stringify"), [
|
|
34
|
+
callExpression(memberExpression(identifier("Object"), identifier("fromEntries")), [
|
|
35
|
+
callExpression(
|
|
36
|
+
memberExpression(
|
|
37
|
+
callExpression(memberExpression(identifier("Object"), identifier("entries")), [
|
|
38
|
+
identifier("props")
|
|
39
|
+
]),
|
|
40
|
+
identifier("filter")
|
|
41
|
+
),
|
|
42
|
+
[identifier('([key]) => key !== "children"')]
|
|
43
|
+
)
|
|
44
|
+
])
|
|
45
|
+
]);
|
|
34
46
|
const ssrElement = jsxElement(
|
|
35
47
|
jsxOpeningElement(
|
|
36
48
|
jsxIdentifier("honox-island"),
|
|
@@ -50,6 +62,21 @@ function addSSRCheck(funcName, componentName, isAsync = false) {
|
|
|
50
62
|
),
|
|
51
63
|
jsxClosingElement(jsxIdentifier(funcName)),
|
|
52
64
|
[]
|
|
65
|
+
),
|
|
66
|
+
jsxExpressionContainer(
|
|
67
|
+
conditionalExpression(
|
|
68
|
+
memberExpression(identifier("props"), identifier("children")),
|
|
69
|
+
jsxElement(
|
|
70
|
+
jsxOpeningElement(
|
|
71
|
+
jsxIdentifier("template"),
|
|
72
|
+
[jsxAttribute(jsxIdentifier(DATA_HONO_TEMPLATE), stringLiteral(""))],
|
|
73
|
+
false
|
|
74
|
+
),
|
|
75
|
+
jsxClosingElement(jsxIdentifier("template")),
|
|
76
|
+
[jsxExpressionContainer(memberExpression(identifier("props"), identifier("children")))]
|
|
77
|
+
),
|
|
78
|
+
identifier("null")
|
|
79
|
+
)
|
|
53
80
|
)
|
|
54
81
|
]
|
|
55
82
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "honox",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"@types/node": "^20.10.5",
|
|
114
114
|
"eslint": "^8.56.0",
|
|
115
115
|
"glob": "^10.3.10",
|
|
116
|
-
"hono": "^4.0.
|
|
116
|
+
"hono": "^4.0.3",
|
|
117
117
|
"np": "7.7.0",
|
|
118
118
|
"prettier": "^3.1.1",
|
|
119
119
|
"publint": "^0.2.7",
|