@jxsuite/compiler 5.1.1 → 5.1.3
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/cli.js +224 -355
- package/dist/compiler.js +126 -257
- package/package.json +8 -8
- package/src/cli.ts +12 -14
- package/src/compiler.ts +45 -23
- package/src/shadow.ts +9 -8
- package/src/shared.ts +350 -296
- package/src/site/asset-mounts.ts +22 -12
- package/src/site/bundler.ts +38 -12
- package/src/site/client-runtime.ts +31 -17
- package/src/site/csp.ts +20 -11
- package/src/site/db-push.ts +38 -24
- package/src/site/dev-command.ts +3 -3
- package/src/site/format-host.ts +56 -45
- package/src/site/headers-emitter.ts +7 -4
- package/src/site/i18n.ts +20 -19
- package/src/site/image-cache.ts +16 -3
- package/src/site/image-optimizer.ts +19 -5
- package/src/site/image-transform.ts +56 -60
- package/src/site/img-loading.ts +11 -5
- package/src/site/layout-resolver.ts +7 -6
- package/src/site/link-relations.ts +10 -6
- package/src/site/locale-negotiation.ts +1 -1
- package/src/site/pages-discovery.ts +65 -47
- package/src/site/preview-server.ts +22 -19
- package/src/site/project-sections.ts +12 -3
- package/src/site/prototype-resolver.ts +94 -42
- package/src/site/schema-command.ts +26 -13
- package/src/site/service-worker.ts +2 -2
- package/src/site/site-build.ts +379 -262
- package/src/site/site-loader.ts +6 -3
- package/src/site/static-host.ts +3 -3
- package/src/site/validate-command.ts +64 -34
- package/src/site/well-known.ts +57 -12
- package/src/targets/compile-class.ts +17 -5
- package/src/targets/compile-client.ts +141 -106
- package/src/targets/compile-element.ts +157 -140
- package/src/targets/compile-server.ts +11 -5
- package/src/targets/compile-static.ts +57 -63
- package/src/types.ts +5 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jxsuite/compiler",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.3",
|
|
4
4
|
"description": "Jx static HTML compiler, island detector, and site builder",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -45,20 +45,20 @@
|
|
|
45
45
|
"upgrade": "bun update --latest && bun install"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@apidevtools/json-schema-ref-parser": "^16.0.
|
|
49
|
-
"@jxsuite/create": "^1.3.
|
|
50
|
-
"@jxsuite/runtime": "^4.0
|
|
48
|
+
"@apidevtools/json-schema-ref-parser": "^16.0.5",
|
|
49
|
+
"@jxsuite/create": "^1.3.14",
|
|
50
|
+
"@jxsuite/runtime": "^4.1.0",
|
|
51
51
|
"@jxsuite/schema": "^3.0.0",
|
|
52
|
-
"@jxsuite/site": "^2.0.
|
|
53
|
-
"@vue/reactivity": "3.5.
|
|
52
|
+
"@jxsuite/site": "^2.0.4",
|
|
53
|
+
"@vue/reactivity": "3.5.44",
|
|
54
54
|
"esbuild": "^0.28.2",
|
|
55
55
|
"lit-html": "^3.3.3",
|
|
56
56
|
"sharp": "^0.35.5"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@happy-dom/global-registrator": "^
|
|
59
|
+
"@happy-dom/global-registrator": "^21.0.3",
|
|
60
60
|
"@jxsuite/connector": "^0.6.2",
|
|
61
|
-
"@jxsuite/parser": "^2.0.
|
|
61
|
+
"@jxsuite/parser": "^2.0.1",
|
|
62
62
|
"@types/mdast": "^4.0.4"
|
|
63
63
|
}
|
|
64
64
|
}
|
package/src/cli.ts
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { relative, resolve } from "node:path";
|
|
12
|
+
import { errorMessage } from "@jxsuite/schema/parse";
|
|
13
|
+
import type { DbPushOptions } from "./site/db-push.ts";
|
|
12
14
|
|
|
13
15
|
// The CLI body runs inside an async function rather than via top-level await: when a test pulls this
|
|
14
16
|
// Entry in with a dynamic import(), Bun's test runtime drops the continuation after a top-level await
|
|
@@ -77,10 +79,11 @@ Options:
|
|
|
77
79
|
const dryRun = flags.has("--dry-run");
|
|
78
80
|
try {
|
|
79
81
|
const { dbPush } = await import("./site/db-push.ts");
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
82
|
+
const pushOptions: DbPushOptions = { dryRun };
|
|
83
|
+
if (connectionArg !== undefined) {
|
|
84
|
+
pushOptions.connection = connectionArg;
|
|
85
|
+
}
|
|
86
|
+
const { results, bindingsPatched, wranglerPath } = await dbPush(projectRoot, pushOptions);
|
|
84
87
|
for (const result of results) {
|
|
85
88
|
const mode = result.applied ? "applied" : "dry-run";
|
|
86
89
|
console.log(
|
|
@@ -98,8 +101,7 @@ Options:
|
|
|
98
101
|
console.log(`Updated bindings in ${relative(projectRoot, wranglerPath)}`);
|
|
99
102
|
}
|
|
100
103
|
} catch (error) {
|
|
101
|
-
|
|
102
|
-
console.error(`db push failed: ${err.message}`);
|
|
104
|
+
console.error(`db push failed: ${errorMessage(error)}`);
|
|
103
105
|
process.exit(1);
|
|
104
106
|
}
|
|
105
107
|
return;
|
|
@@ -125,8 +127,7 @@ Options:
|
|
|
125
127
|
|
|
126
128
|
console.log(`\nDone: ${result.routes} routes → ${result.files} files`);
|
|
127
129
|
} catch (error) {
|
|
128
|
-
|
|
129
|
-
console.error(`Build failed: ${err.message}`);
|
|
130
|
+
console.error(`Build failed: ${errorMessage(error)}`);
|
|
130
131
|
process.exit(1);
|
|
131
132
|
}
|
|
132
133
|
} else if (command === "dev") {
|
|
@@ -134,8 +135,7 @@ Options:
|
|
|
134
135
|
const { runDev } = await import("./site/dev-command.ts");
|
|
135
136
|
runDev(projectRoot, portArg);
|
|
136
137
|
} catch (error) {
|
|
137
|
-
|
|
138
|
-
console.error(err.message);
|
|
138
|
+
console.error(errorMessage(error));
|
|
139
139
|
process.exit(1);
|
|
140
140
|
}
|
|
141
141
|
} else if (command === "preview") {
|
|
@@ -156,8 +156,7 @@ Options:
|
|
|
156
156
|
console.log(`Wrote ${relative(projectRoot, projectSchemaPath)}`);
|
|
157
157
|
console.log(`Wrote ${relative(projectRoot, documentSchemaPath)}`);
|
|
158
158
|
} catch (error) {
|
|
159
|
-
|
|
160
|
-
console.error(`Schema generation failed: ${err.message}`);
|
|
159
|
+
console.error(`Schema generation failed: ${errorMessage(error)}`);
|
|
161
160
|
process.exit(1);
|
|
162
161
|
}
|
|
163
162
|
} else if (command === "validate") {
|
|
@@ -180,8 +179,7 @@ Options:
|
|
|
180
179
|
process.exit(1);
|
|
181
180
|
}
|
|
182
181
|
} catch (error) {
|
|
183
|
-
|
|
184
|
-
console.error(`Validation failed: ${err.message}`);
|
|
182
|
+
console.error(`Validation failed: ${errorMessage(error)}`);
|
|
185
183
|
process.exit(1);
|
|
186
184
|
}
|
|
187
185
|
} else {
|
package/src/compiler.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Jx-compiler.js — Compiler orchestrator
|
|
3
|
-
* @version 3.0.0
|
|
4
|
-
* @license MIT
|
|
5
3
|
*
|
|
6
4
|
* Routes Jx documents to the appropriate compilation target:
|
|
7
|
-
* - Fully static → compile-static.js (plain HTML/CSS, zero JS)
|
|
8
|
-
* - Custom element (-) → compile-element.js (lit-html web component)
|
|
9
|
-
* - Dynamic (standard) → compile-client.js (pre-rendered HTML + reactive bindings)
|
|
10
|
-
* - Server → compile-server.js (Hono server handler)
|
|
11
5
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
6
|
+
* - Fully static → compile-static.js (plain HTML/CSS, zero JS)
|
|
7
|
+
* - Custom element (-) → compile-element.js (lit-html web component)
|
|
8
|
+
* - Dynamic (standard) → compile-client.js (pre-rendered HTML + reactive bindings)
|
|
9
|
+
* - Server → compile-server.js (Hono server handler)
|
|
10
|
+
*
|
|
11
|
+
* Usage (CLI): `bun packages/compiler/src/compile-cli.js <source.json> [output.html]`
|
|
12
|
+
*
|
|
13
|
+
* @license MIT
|
|
14
|
+
* @version 3.0.0
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
import { readFileSync } from "node:fs";
|
|
@@ -27,7 +28,7 @@ import { compileServer } from "./targets/compile-server.ts";
|
|
|
27
28
|
import { emitElementModule } from "./targets/compile-element.ts";
|
|
28
29
|
import { compileStaticPage } from "./targets/compile-static.ts";
|
|
29
30
|
import { compileClient } from "./targets/compile-client.ts";
|
|
30
|
-
import { isClassDef } from "@jxsuite/schema/guards";
|
|
31
|
+
import { isClassDef, isString } from "@jxsuite/schema/guards";
|
|
31
32
|
import { parseJxDocument } from "@jxsuite/schema/parse";
|
|
32
33
|
import type { JxDocument, JxStyle } from "@jxsuite/schema/types";
|
|
33
34
|
import type { FormatRegistry } from "@jxsuite/schema/format-registry";
|
|
@@ -53,7 +54,17 @@ export interface CompileOptions {
|
|
|
53
54
|
* true). The site pipeline disables this and injects via the merged <head> instead.
|
|
54
55
|
*/
|
|
55
56
|
prePaintScheme?: boolean;
|
|
56
|
-
|
|
57
|
+
/**
|
|
58
|
+
* The page language the site pipeline passes alongside the other options. No compile target reads
|
|
59
|
+
* it today: the document's own `lang` is what reaches the emitted markup.
|
|
60
|
+
*/
|
|
61
|
+
lang?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The page-target options {@link compile} forwards only when its caller set them. */
|
|
65
|
+
interface PageTargetOverrides {
|
|
66
|
+
prePaintScheme?: false;
|
|
67
|
+
rewriteSrc?: (specifier: string) => string;
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
/**
|
|
@@ -78,20 +89,19 @@ export async function compile(sourcePath: string | JxDocument, opts: CompileOpti
|
|
|
78
89
|
} = opts;
|
|
79
90
|
|
|
80
91
|
let raw: JxDocument;
|
|
81
|
-
if (
|
|
92
|
+
if (isString(sourcePath)) {
|
|
82
93
|
const source = readFileSync(sourcePath, "utf8");
|
|
83
94
|
if (sourcePath.endsWith(".json")) {
|
|
84
95
|
raw = parseJxDocument(source, sourcePath);
|
|
85
96
|
} else {
|
|
86
97
|
const { extname } = await import("node:path");
|
|
87
98
|
const ext = extname(sourcePath).toLowerCase();
|
|
88
|
-
const entry = opts.formats?.byExtension
|
|
99
|
+
const entry = opts.formats?.byExtension(ext, "parse");
|
|
89
100
|
if (!entry) {
|
|
90
101
|
const { unknownFormatError } = await import("./site/format-host.ts");
|
|
91
102
|
throw unknownFormatError(sourcePath, ext);
|
|
92
103
|
}
|
|
93
|
-
|
|
94
|
-
raw = (await entry.call("parse", source)) as JxDocument;
|
|
104
|
+
raw = await entry.parseDocument(source);
|
|
95
105
|
}
|
|
96
106
|
} else {
|
|
97
107
|
raw = sourcePath;
|
|
@@ -100,11 +110,10 @@ export async function compile(sourcePath: string | JxDocument, opts: CompileOpti
|
|
|
100
110
|
// Route 0: .class.json schema-defined class → JS class module
|
|
101
111
|
if (isClassDef(raw)) {
|
|
102
112
|
const { compileClassJson } = await import("./targets/compile-class.js");
|
|
103
|
-
const jsContent = compileClassJson(raw
|
|
104
|
-
const outputPath =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
: `${raw.title}.js`;
|
|
113
|
+
const jsContent = compileClassJson(raw);
|
|
114
|
+
const outputPath = isString(sourcePath)
|
|
115
|
+
? sourcePath.replace(/\.class\.json$/, ".js")
|
|
116
|
+
: `${raw.title}.js`;
|
|
108
117
|
return { files: [{ content: jsContent, path: outputPath }], html: "" };
|
|
109
118
|
}
|
|
110
119
|
|
|
@@ -114,8 +123,7 @@ export async function compile(sourcePath: string | JxDocument, opts: CompileOpti
|
|
|
114
123
|
litHtmlSrc,
|
|
115
124
|
projectStyle,
|
|
116
125
|
reactivitySrc,
|
|
117
|
-
...(opts
|
|
118
|
-
...(opts.rewriteSrc ? { rewriteSrc: opts.rewriteSrc } : {}),
|
|
126
|
+
...pageTargetOverrides(opts),
|
|
119
127
|
title,
|
|
120
128
|
});
|
|
121
129
|
}
|
|
@@ -162,12 +170,26 @@ export async function compile(sourcePath: string | JxDocument, opts: CompileOpti
|
|
|
162
170
|
litHtmlSrc,
|
|
163
171
|
projectStyle,
|
|
164
172
|
reactivitySrc,
|
|
165
|
-
...(opts
|
|
166
|
-
...(opts.rewriteSrc ? { rewriteSrc: opts.rewriteSrc } : {}),
|
|
173
|
+
...pageTargetOverrides(opts),
|
|
167
174
|
title,
|
|
168
175
|
});
|
|
169
176
|
}
|
|
170
177
|
|
|
178
|
+
/**
|
|
179
|
+
* The `prePaintScheme` and `rewriteSrc` options a page target receives, each present only when the
|
|
180
|
+
* caller set it, so the target's own default applies otherwise.
|
|
181
|
+
*/
|
|
182
|
+
function pageTargetOverrides(opts: CompileOptions): PageTargetOverrides {
|
|
183
|
+
const overrides: PageTargetOverrides = {};
|
|
184
|
+
if (opts.prePaintScheme === false) {
|
|
185
|
+
overrides.prePaintScheme = false;
|
|
186
|
+
}
|
|
187
|
+
if (opts.rewriteSrc) {
|
|
188
|
+
overrides.rewriteSrc = opts.rewriteSrc;
|
|
189
|
+
}
|
|
190
|
+
return overrides;
|
|
191
|
+
}
|
|
192
|
+
|
|
171
193
|
// ─── CLI ──────────────────────────────────────────────────────────────────────
|
|
172
194
|
|
|
173
195
|
/**
|
package/src/shadow.ts
CHANGED
|
@@ -23,11 +23,9 @@ export type ShadowMode = "open" | "closed";
|
|
|
23
23
|
/** A value `$shadow` or `defaults.shadow` may carry. */
|
|
24
24
|
export type ShadowSetting = ShadowMode | false;
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
return undefined;
|
|
26
|
+
/** Whether a document value is one of the settings `$shadow` / `defaults.shadow` may carry. */
|
|
27
|
+
function isShadowSetting(value: unknown): value is ShadowSetting {
|
|
28
|
+
return value === false || value === "open" || value === "closed";
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
/**
|
|
@@ -44,9 +42,12 @@ export function resolveShadowMode(
|
|
|
44
42
|
doc: JxDocument | JxElement | null | undefined,
|
|
45
43
|
defaults?: ProjectConfig["defaults"],
|
|
46
44
|
): ShadowMode | null {
|
|
47
|
-
const own =
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const own = doc?.$shadow;
|
|
46
|
+
if (isShadowSetting(own)) {
|
|
47
|
+
return own === false ? null : own;
|
|
48
|
+
}
|
|
49
|
+
const projectDefault = defaults?.shadow;
|
|
50
|
+
return isShadowSetting(projectDefault) && projectDefault !== false ? projectDefault : null;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
/**
|