honox 0.0.0 → 0.0.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.
@@ -0,0 +1,129 @@
1
+ import fs from "fs/promises";
2
+ import _generate from "@babel/generator";
3
+ const generate = _generate.default ?? _generate;
4
+ import { parse } from "@babel/parser";
5
+ import _traverse from "@babel/traverse";
6
+ const traverse = _traverse.default ?? _traverse;
7
+ import {
8
+ identifier,
9
+ jsxAttribute,
10
+ jsxClosingElement,
11
+ jsxElement,
12
+ jsxIdentifier,
13
+ jsxOpeningElement,
14
+ stringLiteral,
15
+ callExpression,
16
+ variableDeclarator,
17
+ variableDeclaration,
18
+ functionExpression,
19
+ blockStatement,
20
+ returnStatement,
21
+ jsxSpreadAttribute,
22
+ jsxExpressionContainer,
23
+ exportDefaultDeclaration,
24
+ conditionalExpression,
25
+ memberExpression
26
+ } from "@babel/types";
27
+ import { COMPONENT_NAME, DATA_SERIALIZED_PROPS } from "../constants.js";
28
+ function addSSRCheck(funcName, componentName, isAsync = false) {
29
+ const isSSR = memberExpression(
30
+ memberExpression(identifier("import"), identifier("meta")),
31
+ identifier("env.SSR")
32
+ );
33
+ const serializedProps = callExpression(identifier("JSON.stringify"), [identifier("props")]);
34
+ const ssrElement = jsxElement(
35
+ jsxOpeningElement(
36
+ jsxIdentifier("honox-island"),
37
+ [
38
+ jsxAttribute(jsxIdentifier(COMPONENT_NAME), stringLiteral(componentName)),
39
+ jsxAttribute(jsxIdentifier(DATA_SERIALIZED_PROPS), jsxExpressionContainer(serializedProps))
40
+ ],
41
+ false
42
+ ),
43
+ jsxClosingElement(jsxIdentifier("honox-island")),
44
+ [
45
+ jsxElement(
46
+ jsxOpeningElement(
47
+ jsxIdentifier(funcName),
48
+ [jsxSpreadAttribute(identifier("props"))],
49
+ false
50
+ ),
51
+ jsxClosingElement(jsxIdentifier(funcName)),
52
+ []
53
+ )
54
+ ]
55
+ );
56
+ const clientElement = jsxElement(
57
+ jsxOpeningElement(jsxIdentifier(funcName), [jsxSpreadAttribute(identifier("props"))], false),
58
+ jsxClosingElement(jsxIdentifier(funcName)),
59
+ []
60
+ );
61
+ const returnStmt = returnStatement(conditionalExpression(isSSR, ssrElement, clientElement));
62
+ const functionExpr = functionExpression(null, [identifier("props")], blockStatement([returnStmt]));
63
+ if (isAsync) {
64
+ functionExpr.async = true;
65
+ }
66
+ return functionExpr;
67
+ }
68
+ const transformJsxTags = (contents, componentName) => {
69
+ const ast = parse(contents, {
70
+ sourceType: "module",
71
+ plugins: ["typescript", "jsx"]
72
+ });
73
+ if (ast) {
74
+ traverse(ast, {
75
+ ExportDefaultDeclaration(path) {
76
+ if (path.node.declaration.type === "FunctionDeclaration") {
77
+ const functionId = path.node.declaration.id;
78
+ if (!functionId) {
79
+ return;
80
+ }
81
+ const isAsync = path.node.declaration.async;
82
+ const originalFunctionId = identifier(functionId.name + "Original");
83
+ const originalFunction = functionExpression(
84
+ null,
85
+ path.node.declaration.params,
86
+ path.node.declaration.body
87
+ );
88
+ if (isAsync) {
89
+ originalFunction.async = true;
90
+ }
91
+ path.insertBefore(
92
+ variableDeclaration("const", [variableDeclarator(originalFunctionId, originalFunction)])
93
+ );
94
+ const wrappedFunction = addSSRCheck(originalFunctionId.name, componentName, isAsync);
95
+ const wrappedFunctionId = identifier("Wrapped" + functionId.name);
96
+ path.replaceWith(
97
+ variableDeclaration("const", [variableDeclarator(wrappedFunctionId, wrappedFunction)])
98
+ );
99
+ path.insertAfter(exportDefaultDeclaration(wrappedFunctionId));
100
+ }
101
+ }
102
+ });
103
+ const { code } = generate(ast);
104
+ return code;
105
+ }
106
+ };
107
+ function islandComponents() {
108
+ return {
109
+ name: "transform-island-components",
110
+ async load(id) {
111
+ const match = id.match(/\/islands\/(.+?\.tsx)$/);
112
+ if (match) {
113
+ const componentName = match[1];
114
+ const contents = await fs.readFile(id, "utf-8");
115
+ const code = transformJsxTags(contents, componentName);
116
+ if (code) {
117
+ return {
118
+ code,
119
+ map: null
120
+ };
121
+ }
122
+ }
123
+ }
124
+ };
125
+ }
126
+ export {
127
+ islandComponents,
128
+ transformJsxTags
129
+ };
@@ -0,0 +1,8 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ type RemoveElementsOptions = {
4
+ attributes: string[];
5
+ };
6
+ declare function removeElementsPlugin(options: RemoveElementsOptions): Plugin;
7
+
8
+ export { removeElementsPlugin };
@@ -0,0 +1,52 @@
1
+ import _generate from "@babel/generator";
2
+ import { parse } from "@babel/parser";
3
+ import _traverse from "@babel/traverse";
4
+ import { HAS_ISLANDS_ID } from "../constants";
5
+ const traverse = _traverse.default ?? _traverse;
6
+ const generate = _generate.default ?? _generate;
7
+ function injectHasIslands() {
8
+ return {
9
+ name: "inject-has-islands",
10
+ transform(code, id) {
11
+ if (id.endsWith(".tsx") || id.endsWith(".jsx")) {
12
+ let hasIslandsImport = false;
13
+ const ast = parse(code, {
14
+ sourceType: "module",
15
+ plugins: ["jsx"]
16
+ });
17
+ traverse(ast, {
18
+ ImportDeclaration(path) {
19
+ if (path.node.source.value.includes("islands/")) {
20
+ hasIslandsImport = true;
21
+ }
22
+ }
23
+ });
24
+ if (hasIslandsImport) {
25
+ const hasIslandsNode = {
26
+ type: "ExportNamedDeclaration",
27
+ declaration: {
28
+ type: "VariableDeclaration",
29
+ declarations: [
30
+ {
31
+ type: "VariableDeclarator",
32
+ id: { type: "Identifier", name: HAS_ISLANDS_ID },
33
+ init: { type: "BooleanLiteral", value: true }
34
+ }
35
+ ],
36
+ kind: "const"
37
+ }
38
+ };
39
+ ast.program.body.push(hasIslandsNode);
40
+ }
41
+ const output = generate(ast, {}, code);
42
+ return {
43
+ code: output.code,
44
+ map: output.map
45
+ };
46
+ }
47
+ }
48
+ };
49
+ }
50
+ export {
51
+ injectHasIslands
52
+ };
package/package.json CHANGED
@@ -1,6 +1,121 @@
1
1
  {
2
2
  "name": "honox",
3
- "version": "0.0.0",
4
- "main": "index.js",
5
- "license": "MIT"
6
- }
3
+ "version": "0.0.2",
4
+ "main": "dist/index.js",
5
+ "type": "module",
6
+ "scripts": {
7
+ "test": "bun typecheck && bun test:unit && bun test:integration && bun test:e2e",
8
+ "test:unit": "vitest --run test/unit",
9
+ "test:integration": "bun test:integration:api && bun test:integration:hono-jsx",
10
+ "test:integration:hono-jsx": "vitest run -c ./test/hono-jsx/vitest.config.ts ./test/hono-jsx/integration.test.ts",
11
+ "test:integration:hono-jsx:watch": "vitest -c ./test/hono-jsx/vitest.config.ts ./test/hono-jsx/integration.test.ts",
12
+ "test:integration:api": "vitest run -c ./test/api/vitest.config.ts ./test/api/integration.test.ts",
13
+ "test:e2e": "playwright test -c ./test/hono-jsx/playwright.config.ts ./test/hono-jsx/e2e.test.ts",
14
+ "typecheck": "tsc --noEmit",
15
+ "build": "tsup && publint",
16
+ "watch": "tsup --watch",
17
+ "lint": "eslint --ext js,ts src test",
18
+ "lint:fix": "eslint --ext js,ts src test --fix",
19
+ "format": "prettier --check \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\"",
20
+ "format:fix": "prettier --write \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\"",
21
+ "prerelease": "bun run test && bun run build",
22
+ "release": "np"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js"
31
+ },
32
+ "./types": {
33
+ "types": "./dist/types.d.ts",
34
+ "import": "./dist/types.js"
35
+ },
36
+ "./factory": {
37
+ "types": "./dist/factory/index.d.ts",
38
+ "import": "./dist/factory/index.js"
39
+ },
40
+ "./server": {
41
+ "types": "./dist/server/index.d.ts",
42
+ "import": "./dist/server/index.js"
43
+ },
44
+ "./client": {
45
+ "types": "./dist/client/index.d.ts",
46
+ "import": "./dist/client/index.js"
47
+ },
48
+ "./utils/*": {
49
+ "types": "./dist/utils/*.d.ts",
50
+ "import": "./dist/utils/*.js"
51
+ },
52
+ "./vite": {
53
+ "types": "./dist/vite/index.d.ts",
54
+ "import": "./dist/vite/index.js"
55
+ }
56
+ },
57
+ "typesVersions": {
58
+ "*": {
59
+ "types": [
60
+ "./dist/types"
61
+ ],
62
+ "factory": [
63
+ "./dist/factory"
64
+ ],
65
+ "server": [
66
+ "./dist/server"
67
+ ],
68
+ "client": [
69
+ "./dist/client"
70
+ ],
71
+ "utils/*": [
72
+ "./dist/utils/*"
73
+ ],
74
+ "vite": [
75
+ "./dist/vite"
76
+ ]
77
+ }
78
+ },
79
+ "author": "Yusuke Wada <yusuke@kamawada.com> (https://github.com/yusukebe)",
80
+ "license": "MIT",
81
+ "repository": {
82
+ "type": "git",
83
+ "url": "https://github.com/honojs/honox.git"
84
+ },
85
+ "publishConfig": {
86
+ "registry": "https://registry.npmjs.org",
87
+ "access": "public"
88
+ },
89
+ "homepage": "https://hono.dev",
90
+ "dependencies": {
91
+ "@babel/generator": "^7.23.6",
92
+ "@babel/parser": "^7.23.6",
93
+ "@babel/traverse": "^7.23.6",
94
+ "@babel/types": "^7.23.6",
95
+ "@hono/vite-dev-server": "^0.5.0"
96
+ },
97
+ "devDependencies": {
98
+ "@hono/eslint-config": "^0.0.4",
99
+ "@mdx-js/rollup": "^3.0.0",
100
+ "@playwright/test": "^1.41.0",
101
+ "@types/babel__generator": "^7",
102
+ "@types/babel__traverse": "^7",
103
+ "@types/node": "^20.10.5",
104
+ "eslint": "^8.56.0",
105
+ "glob": "^10.3.10",
106
+ "hono": "4.0.0-rc.4",
107
+ "np": "7.7.0",
108
+ "prettier": "^3.1.1",
109
+ "publint": "^0.2.7",
110
+ "tsup": "^8.0.1",
111
+ "typescript": "^5.3.3",
112
+ "vite": "^5.0.12",
113
+ "vitest": "^1.2.1"
114
+ },
115
+ "engines": {
116
+ "node": ">=18.14.1"
117
+ },
118
+ "optionalDependencies": {
119
+ "@rollup/rollup-linux-x64-gnu": "^4.9.6"
120
+ }
121
+ }