@jxsuite/compiler 0.9.0 → 0.10.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/dist/compiler.js +10 -10
- package/package.json +3 -3
- package/src/compile-cli.js +10 -0
- package/src/compiler.js +27 -32
- package/src/site/content-loader.js +4 -5
- package/src/site/site-build.js +4 -4
- package/src/targets/compile-client.js +17 -29
- package/src/targets/compile-server.js +7 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jxsuite/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Jx static HTML compiler, island detector, and site builder",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@apidevtools/json-schema-ref-parser": "^15.3.5",
|
|
40
|
-
"@jxsuite/parser": "^0.
|
|
41
|
-
"@jxsuite/runtime": "^0.
|
|
40
|
+
"@jxsuite/parser": "^0.10.0",
|
|
41
|
+
"@jxsuite/runtime": "^0.10.0",
|
|
42
42
|
"remark-gfm": "^4.0.1",
|
|
43
43
|
"remark-stringify": "^11.0.0",
|
|
44
44
|
"sharp": "^0.34.5",
|
package/src/compiler.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - Server → compile-server.js (Hono server handler)
|
|
11
11
|
*
|
|
12
12
|
* Usage (CLI):
|
|
13
|
-
* bun packages/compiler/
|
|
13
|
+
* bun packages/compiler/src/compile-cli.js <source.json> [output.html]
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { readFileSync } from "node:fs";
|
|
@@ -132,35 +132,30 @@ export async function compile(sourcePath, opts = {}) {
|
|
|
132
132
|
|
|
133
133
|
// ─── CLI ──────────────────────────────────────────────────────────────────────
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
})
|
|
162
|
-
.catch((/** @type {any} */ err) => {
|
|
163
|
-
console.error(err);
|
|
164
|
-
process.exit(1);
|
|
165
|
-
});
|
|
135
|
+
/**
|
|
136
|
+
* @param {string} src
|
|
137
|
+
* @param {string} [out]
|
|
138
|
+
*/
|
|
139
|
+
export async function runCli(src, out) {
|
|
140
|
+
const [result, server] = await Promise.all([compile(src), compileServer(src)]);
|
|
141
|
+
const { writeFileSync, mkdirSync } = await import("node:fs");
|
|
142
|
+
const { dirname, join } = await import("node:path");
|
|
143
|
+
if (out) {
|
|
144
|
+
writeFileSync(out, result.html, "utf8");
|
|
145
|
+
console.error(`Written to ${out}`);
|
|
146
|
+
const outDir = dirname(out);
|
|
147
|
+
for (const f of result.files) {
|
|
148
|
+
const filePath = join(outDir, f.path);
|
|
149
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
150
|
+
writeFileSync(filePath, f.content, "utf8");
|
|
151
|
+
console.error(`Written to ${filePath}`);
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
process.stdout.write(result.html);
|
|
155
|
+
}
|
|
156
|
+
if (server && out) {
|
|
157
|
+
const serverOut = out.replace(/(\.[^.]+)?$/, "-server.js");
|
|
158
|
+
writeFileSync(serverOut, /** @type {string} */ (server), "utf8");
|
|
159
|
+
console.error(`Server handler written to ${serverOut}`);
|
|
160
|
+
}
|
|
166
161
|
}
|
|
@@ -30,12 +30,13 @@ function parseCSV(csv) {
|
|
|
30
30
|
/** @type {string[]} */
|
|
31
31
|
const lines = [];
|
|
32
32
|
|
|
33
|
-
// Split into rows respecting quoted newlines
|
|
33
|
+
// Split into rows respecting quoted newlines (preserve raw characters)
|
|
34
34
|
for (let i = 0; i < csv.length; i++) {
|
|
35
35
|
const ch = csv[i];
|
|
36
36
|
if (ch === '"') {
|
|
37
|
+
current += ch;
|
|
37
38
|
if (inQuotes && csv[i + 1] === '"') {
|
|
38
|
-
current +=
|
|
39
|
+
current += csv[i + 1];
|
|
39
40
|
i++;
|
|
40
41
|
} else {
|
|
41
42
|
inQuotes = !inQuotes;
|
|
@@ -155,7 +156,6 @@ function loadJSONEntries(filePath) {
|
|
|
155
156
|
id: item.id ?? basename(filePath, ".json") + "-" + i,
|
|
156
157
|
data: item,
|
|
157
158
|
body: null,
|
|
158
|
-
rendered: null,
|
|
159
159
|
}));
|
|
160
160
|
}
|
|
161
161
|
// Single object file — filename is the id
|
|
@@ -164,7 +164,6 @@ function loadJSONEntries(filePath) {
|
|
|
164
164
|
id: raw.id ?? basename(filePath, ".json"),
|
|
165
165
|
data: raw,
|
|
166
166
|
body: null,
|
|
167
|
-
rendered: null,
|
|
168
167
|
},
|
|
169
168
|
];
|
|
170
169
|
}
|
|
@@ -192,7 +191,7 @@ function loadCSVEntries(filePath, schema) {
|
|
|
192
191
|
}
|
|
193
192
|
// Use `id` column, `sku` column, or row index as the entry ID
|
|
194
193
|
const id = row.id ?? row.sku ?? String(i);
|
|
195
|
-
return { id, data: row, body: null
|
|
194
|
+
return { id, data: row, body: null };
|
|
196
195
|
});
|
|
197
196
|
}
|
|
198
197
|
|
package/src/site/site-build.js
CHANGED
|
@@ -173,7 +173,7 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
173
173
|
// ── 5b. Collect server entries from components (for site-wide bundling) ──
|
|
174
174
|
/** @type {{ exportName: string; src: string }[]} */
|
|
175
175
|
const siteServerEntries = [];
|
|
176
|
-
if (projectConfig.build.
|
|
176
|
+
if (projectConfig.build.adapter) {
|
|
177
177
|
for (const [, doc] of componentDefs) {
|
|
178
178
|
const entries = collectServerEntries(doc);
|
|
179
179
|
for (const entry of entries) {
|
|
@@ -268,7 +268,7 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
// ── 6c. Generate site-wide server worker ────────────────────────────────
|
|
271
|
-
if (projectConfig.build.
|
|
271
|
+
if (projectConfig.build.adapter) {
|
|
272
272
|
log("Generating site-wide server worker...");
|
|
273
273
|
|
|
274
274
|
const deduped = new Map();
|
|
@@ -277,7 +277,7 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
const workerSource = compileSiteServer([...deduped.values()], {
|
|
280
|
-
|
|
280
|
+
adapter: projectConfig.build.adapter,
|
|
281
281
|
});
|
|
282
282
|
|
|
283
283
|
if (workerSource) {
|
|
@@ -459,7 +459,7 @@ async function compilePage(
|
|
|
459
459
|
// Compile server handler if applicable (skip when provider bundles site-wide)
|
|
460
460
|
/** @type {string | null} */
|
|
461
461
|
let serverHandler = null;
|
|
462
|
-
if (!projectConfig.build.
|
|
462
|
+
if (!projectConfig.build.adapter) {
|
|
463
463
|
try {
|
|
464
464
|
const serverResult = await compileServer(route.sourcePath);
|
|
465
465
|
if (serverResult) {
|
|
@@ -342,12 +342,8 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
|
|
|
342
342
|
const value = resolveStaticValue(source.textContent, nextContext.scope);
|
|
343
343
|
inner = value == null ? "" : escapeHtml(String(value));
|
|
344
344
|
} else if (source.textContent !== undefined && needsBind) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
inner = value == null ? "" : escapeHtml(String(value));
|
|
348
|
-
} catch {
|
|
349
|
-
inner = "";
|
|
350
|
-
}
|
|
345
|
+
const value = resolveStaticValue(source.textContent, nextContext.scope);
|
|
346
|
+
inner = value == null ? "" : escapeHtml(String(value));
|
|
351
347
|
} else if (source.innerHTML) {
|
|
352
348
|
// resolveStaticValue may return null if innerHTML contains `${` from rendered content
|
|
353
349
|
// (e.g., code examples) that isn't an actual template expression. Fall back to raw value.
|
|
@@ -607,29 +603,21 @@ function emitClientModule(
|
|
|
607
603
|
if (onEntries.length > 0) {
|
|
608
604
|
lines.push("const on = {");
|
|
609
605
|
for (const [key, def] of onEntries) {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
.
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
argNames.join(", ") +
|
|
626
|
-
") => { " +
|
|
627
|
-
def.body +
|
|
628
|
-
" }; fn(" +
|
|
629
|
-
callArgs +
|
|
630
|
-
"); },",
|
|
631
|
-
);
|
|
632
|
-
}
|
|
606
|
+
const argNames = def.args ?? ["state"];
|
|
607
|
+
const callArgs = argNames
|
|
608
|
+
.map((/** @type {string} */ a) => (a === "state" ? "state" : "e"))
|
|
609
|
+
.join(", ");
|
|
610
|
+
lines.push(
|
|
611
|
+
" " +
|
|
612
|
+
key +
|
|
613
|
+
": (e) => { const fn = (" +
|
|
614
|
+
argNames.join(", ") +
|
|
615
|
+
") => { " +
|
|
616
|
+
def.body +
|
|
617
|
+
" }; fn(" +
|
|
618
|
+
callArgs +
|
|
619
|
+
"); },",
|
|
620
|
+
);
|
|
633
621
|
}
|
|
634
622
|
lines.push("};");
|
|
635
623
|
} else {
|
|
@@ -50,17 +50,17 @@ export default app
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Generate a bundled Hono server entry from pre-collected server entries across an entire site.
|
|
53
|
-
* Used when `build.
|
|
53
|
+
* Used when `build.adapter` is set in project.json. Returns null if no entries are provided.
|
|
54
54
|
*
|
|
55
55
|
* @param {{ exportName: string; src: string }[]} entries - Resolved server entries
|
|
56
56
|
* @param {object} [opts]
|
|
57
57
|
* @param {string} [opts.baseUrl] - Base path for server endpoints. Default is `'/_jx/server'`
|
|
58
|
-
* @param {string | null} [opts.
|
|
58
|
+
* @param {string | null} [opts.adapter] - Deployment adapter: `"cloudflare"`, `"node"`, `"bun"`
|
|
59
59
|
* @returns {string | null} Complete worker/server source string, or null
|
|
60
60
|
*/
|
|
61
61
|
export function compileSiteServer(entries, opts = {}) {
|
|
62
|
-
const { baseUrl = "/_jx/server",
|
|
63
|
-
if (entries.length === 0) return null;
|
|
62
|
+
const { baseUrl = "/_jx/server", adapter = null } = opts;
|
|
63
|
+
if (entries.length === 0 && !adapter) return null;
|
|
64
64
|
|
|
65
65
|
const imports = entries
|
|
66
66
|
.map(({ exportName, src }) => `import { ${exportName} } from '${src}'`)
|
|
@@ -68,8 +68,8 @@ export function compileSiteServer(entries, opts = {}) {
|
|
|
68
68
|
|
|
69
69
|
const routes = entries.map(({ exportName }) => buildRoute(exportName, baseUrl)).join("\n");
|
|
70
70
|
|
|
71
|
-
const
|
|
72
|
-
|
|
71
|
+
const adapterBlock =
|
|
72
|
+
adapter === "cloudflare" ? "\napp.all('*', (c) => c.env.ASSETS.fetch(c.req.raw))\n" : "\n";
|
|
73
73
|
|
|
74
74
|
return `// Generated by @jxsuite/compiler — do not edit manually
|
|
75
75
|
import { Hono } from 'hono'
|
|
@@ -77,7 +77,7 @@ ${imports}
|
|
|
77
77
|
|
|
78
78
|
const app = new Hono()
|
|
79
79
|
${routes}
|
|
80
|
-
${
|
|
80
|
+
${adapterBlock}
|
|
81
81
|
export default app
|
|
82
82
|
`;
|
|
83
83
|
}
|