@jxsuite/compiler 0.9.0 → 0.10.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/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 +60 -61
- package/src/site/context-injection.js +16 -16
- package/src/site/pages-discovery.js +12 -12
- package/src/site/site-build.js +17 -17
- package/src/site/site-loader.js +2 -2
- package/src/targets/compile-client.js +17 -29
- package/src/targets/compile-server.js +7 -7
package/src/site/site-build.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
DEFAULT_REACTIVITY_SRC,
|
|
41
41
|
DEFAULT_LIT_HTML_SRC,
|
|
42
42
|
} from "../shared.js";
|
|
43
|
-
import {
|
|
43
|
+
import { loadContentTypes, loadContentConfig, resolveContentTypeRefs } from "./content-loader.js";
|
|
44
44
|
import { resolvePrototypes } from "./prototype-resolver.js";
|
|
45
45
|
import { compileMarkdown } from "../targets/compile-markdown.js";
|
|
46
46
|
import { transformImageNodes } from "./image-transform.js";
|
|
@@ -97,20 +97,20 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
97
97
|
const staticRoutes = discoverPages(pagesDir);
|
|
98
98
|
log(` Found ${staticRoutes.length} page(s)`);
|
|
99
99
|
|
|
100
|
-
// ── 3b. Load content
|
|
101
|
-
log("Loading content
|
|
102
|
-
const
|
|
103
|
-
if (
|
|
104
|
-
log(` Loaded ${
|
|
105
|
-
// Resolve cross-
|
|
100
|
+
// ── 3b. Load content types ─────────────────────────────────────────────
|
|
101
|
+
log("Loading content types...");
|
|
102
|
+
const contentTypes = await loadContentTypes(projectRoot, projectConfig);
|
|
103
|
+
if (contentTypes.size > 0) {
|
|
104
|
+
log(` Loaded ${contentTypes.size} content type(s): ${[...contentTypes.keys()].join(", ")}`);
|
|
105
|
+
// Resolve cross-content-type $ref references
|
|
106
106
|
const contentConfig = loadContentConfig(projectRoot, projectConfig);
|
|
107
107
|
if (contentConfig) {
|
|
108
|
-
|
|
108
|
+
resolveContentTypeRefs(contentTypes, contentConfig.config);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
// ── 4. Expand dynamic routes ────────────────────────────────────────────
|
|
113
|
-
const routes = await expandDynamicRoutes(staticRoutes, projectRoot,
|
|
113
|
+
const routes = await expandDynamicRoutes(staticRoutes, projectRoot, contentTypes);
|
|
114
114
|
log(` ${routes.length} route(s) after expansion`);
|
|
115
115
|
|
|
116
116
|
let fileCount = 0;
|
|
@@ -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) {
|
|
@@ -194,7 +194,7 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
194
194
|
route,
|
|
195
195
|
projectConfig,
|
|
196
196
|
projectRoot,
|
|
197
|
-
|
|
197
|
+
contentTypes,
|
|
198
198
|
imageCache,
|
|
199
199
|
outDir,
|
|
200
200
|
componentDefs,
|
|
@@ -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) {
|
|
@@ -339,7 +339,7 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
339
339
|
* @param {any} route
|
|
340
340
|
* @param {any} projectConfig
|
|
341
341
|
* @param {string} projectRoot
|
|
342
|
-
* @param {Map<string, any[]>} [
|
|
342
|
+
* @param {Map<string, any[]>} [contentTypes]
|
|
343
343
|
* @param {import("./image-cache.js").CacheManifest | null} [imageCache]
|
|
344
344
|
* @param {string} [outDir]
|
|
345
345
|
* @returns {Promise<{ html: string; files: any[]; serverHandler: string | null; doc: any }>}
|
|
@@ -348,7 +348,7 @@ async function compilePage(
|
|
|
348
348
|
route,
|
|
349
349
|
projectConfig,
|
|
350
350
|
projectRoot,
|
|
351
|
-
|
|
351
|
+
contentTypes = new Map(),
|
|
352
352
|
imageCache = null,
|
|
353
353
|
outDir = "",
|
|
354
354
|
componentDefs = new Map(),
|
|
@@ -375,7 +375,7 @@ async function compilePage(
|
|
|
375
375
|
delete layoutDoc._pageTitle;
|
|
376
376
|
|
|
377
377
|
// Inject $site and $page context, resolve ContentCollection/ContentEntry
|
|
378
|
-
injectContext(layoutDoc, projectConfig, route,
|
|
378
|
+
injectContext(layoutDoc, projectConfig, route, contentTypes, projectRoot);
|
|
379
379
|
|
|
380
380
|
// Resolve generic $prototype entries via .class.json imports
|
|
381
381
|
await resolvePrototypes(layoutDoc, route, projectRoot);
|
|
@@ -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) {
|
package/src/site/site-loader.js
CHANGED
|
@@ -25,7 +25,7 @@ const DEFAULTS = {
|
|
|
25
25
|
$media: {},
|
|
26
26
|
style: {},
|
|
27
27
|
state: {},
|
|
28
|
-
|
|
28
|
+
contentTypes: {},
|
|
29
29
|
redirects: {},
|
|
30
30
|
images: {
|
|
31
31
|
optimize: true,
|
|
@@ -85,7 +85,7 @@ export function loadProjectConfig(projectRoot) {
|
|
|
85
85
|
if (raw.state) config.state = raw.state;
|
|
86
86
|
if (raw.redirects) config.redirects = raw.redirects;
|
|
87
87
|
if (raw.imports) config.imports = raw.imports;
|
|
88
|
-
if (raw.
|
|
88
|
+
if (raw.contentTypes) config.contentTypes = raw.contentTypes;
|
|
89
89
|
|
|
90
90
|
return {
|
|
91
91
|
config,
|
|
@@ -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
|
}
|