@jxsuite/schema 1.1.0 → 1.2.0
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/defs/project-config.schema.ts +7 -1
- package/package.json +2 -1
- package/project-schema.json +2 -1
- package/schema.json +1 -1
- package/schemas/document.paths.schema.json +1 -1
- package/schemas/project.core.schema.json +20 -77
- package/schemas/project.fields.schema.json +1 -1
- package/src/asset-paths.ts +42 -0
- package/src/extension-registry.ts +5 -0
- package/src/format-registry.ts +5 -2
- package/src/schema.ts +28 -1
|
@@ -54,9 +54,15 @@ export const projectConfigSchema = {
|
|
|
54
54
|
additionalProperties: { type: "string" },
|
|
55
55
|
description:
|
|
56
56
|
"Named media breakpoints following CSS @custom-media convention. " +
|
|
57
|
-
"Available in all component style objects."
|
|
57
|
+
"Available in all component style objects. Declaring a pure color-scheme " +
|
|
58
|
+
'query (e.g. "--dark": "(prefers-color-scheme: dark)") additionally opts the ' +
|
|
59
|
+
"site into the forced-scheme contract: @--dark style blocks are dual-emitted " +
|
|
60
|
+
"so a data-color-scheme attribute on <html> overrides the OS preference, " +
|
|
61
|
+
"color-scheme is declared on :root, and a pre-paint script restores the " +
|
|
62
|
+
"visitor's persisted choice (spec §9.5).",
|
|
58
63
|
examples: [
|
|
59
64
|
{
|
|
65
|
+
"--dark": "(prefers-color-scheme: dark)",
|
|
60
66
|
"--lg": "(min-width: 1024px)",
|
|
61
67
|
"--md": "(min-width: 768px)",
|
|
62
68
|
"--sm": "(min-width: 640px)",
|
package/package.json
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"description": "JSON Schema 2020-12 meta-schema generator for Jx documents",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": "./src/schema.ts",
|
|
12
|
+
"./asset-paths": "./src/asset-paths.ts",
|
|
12
13
|
"./extension-registry": "./src/extension-registry.ts",
|
|
13
14
|
"./format-registry": "./src/format-registry.ts",
|
|
14
15
|
"./project-schemas": "./src/project-schemas.ts",
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
"upgrade": "bunx npm-check-updates -u && bun install"
|
|
50
51
|
},
|
|
51
52
|
"type": "module",
|
|
52
|
-
"version": "1.
|
|
53
|
+
"version": "1.2.0",
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"json-schema-to-ts": "^3.1.1"
|
|
55
56
|
}
|
package/project-schema.json
CHANGED
|
@@ -131,9 +131,10 @@
|
|
|
131
131
|
"additionalProperties": {
|
|
132
132
|
"type": "string"
|
|
133
133
|
},
|
|
134
|
-
"description": "Named media breakpoints following CSS @custom-media convention. Available in all component style objects.",
|
|
134
|
+
"description": "Named media breakpoints following CSS @custom-media convention. Available in all component style objects. Declaring a pure color-scheme query (e.g. \"--dark\": \"(prefers-color-scheme: dark)\") additionally opts the site into the forced-scheme contract: @--dark style blocks are dual-emitted so a data-color-scheme attribute on <html> overrides the OS preference, color-scheme is declared on :root, and a pre-paint script restores the visitor's persisted choice (spec §9.5).",
|
|
135
135
|
"examples": [
|
|
136
136
|
{
|
|
137
|
+
"--dark": "(prefers-color-scheme: dark)",
|
|
137
138
|
"--lg": "(min-width: 1024px)",
|
|
138
139
|
"--md": "(min-width: 768px)",
|
|
139
140
|
"--sm": "(min-width: 640px)"
|
package/schema.json
CHANGED
|
@@ -22034,7 +22034,7 @@
|
|
|
22034
22034
|
"additionalProperties": {
|
|
22035
22035
|
"type": "string"
|
|
22036
22036
|
},
|
|
22037
|
-
"description": "Named media breakpoints following CSS @custom-media convention. Keys use the CSS custom property -- prefix.",
|
|
22037
|
+
"description": "Named media breakpoints following CSS @custom-media convention. Keys use the CSS custom property -- prefix. Pure color-scheme queries (e.g. \"--dark\": \"(prefers-color-scheme: dark)\") are dual-emitted so a data-color-scheme attribute on the root element forces the scheme regardless of the OS preference (spec §9.5).",
|
|
22038
22038
|
"examples": [
|
|
22039
22039
|
{
|
|
22040
22040
|
"--dark": "(prefers-color-scheme: dark)",
|
|
@@ -41,10 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"service": {
|
|
43
43
|
"description": "How images are optimized: \"build\" runs Sharp at build time; \"cloudflare\" emits /cdn-cgi/image transform URLs served by Cloudflare Image Transformations (requires the feature to be enabled on the serving zone).",
|
|
44
|
-
"enum": [
|
|
45
|
-
"build",
|
|
46
|
-
"cloudflare"
|
|
47
|
-
],
|
|
44
|
+
"enum": ["build", "cloudflare"],
|
|
48
45
|
"type": "string"
|
|
49
46
|
},
|
|
50
47
|
"sizes": {
|
|
@@ -88,20 +85,11 @@
|
|
|
88
85
|
"type": "array"
|
|
89
86
|
},
|
|
90
87
|
"type": {
|
|
91
|
-
"enum": [
|
|
92
|
-
"string",
|
|
93
|
-
"number",
|
|
94
|
-
"integer",
|
|
95
|
-
"boolean",
|
|
96
|
-
"array",
|
|
97
|
-
"object"
|
|
98
|
-
],
|
|
88
|
+
"enum": ["string", "number", "integer", "boolean", "array", "object"],
|
|
99
89
|
"type": "string"
|
|
100
90
|
}
|
|
101
91
|
},
|
|
102
|
-
"required": [
|
|
103
|
-
"type"
|
|
104
|
-
],
|
|
92
|
+
"required": ["type"],
|
|
105
93
|
"type": "object"
|
|
106
94
|
},
|
|
107
95
|
"RelationshipRef": {
|
|
@@ -115,9 +103,7 @@
|
|
|
115
103
|
"type": "string"
|
|
116
104
|
}
|
|
117
105
|
},
|
|
118
|
-
"required": [
|
|
119
|
-
"$ref"
|
|
120
|
-
],
|
|
106
|
+
"required": ["$ref"],
|
|
121
107
|
"type": "object"
|
|
122
108
|
}
|
|
123
109
|
},
|
|
@@ -140,9 +126,7 @@
|
|
|
140
126
|
"type": "string"
|
|
141
127
|
}
|
|
142
128
|
},
|
|
143
|
-
"required": [
|
|
144
|
-
"$ref"
|
|
145
|
-
],
|
|
129
|
+
"required": ["$ref"],
|
|
146
130
|
"type": "object"
|
|
147
131
|
},
|
|
148
132
|
{
|
|
@@ -192,9 +176,10 @@
|
|
|
192
176
|
"additionalProperties": {
|
|
193
177
|
"type": "string"
|
|
194
178
|
},
|
|
195
|
-
"description": "Named media breakpoints following CSS @custom-media convention. Available in all component style objects.",
|
|
179
|
+
"description": "Named media breakpoints following CSS @custom-media convention. Available in all component style objects. Declaring a pure color-scheme query (e.g. \"--dark\": \"(prefers-color-scheme: dark)\") additionally opts the site into the forced-scheme contract: @--dark style blocks are dual-emitted so a data-color-scheme attribute on <html> overrides the OS preference, color-scheme is declared on :root, and a pre-paint script restores the visitor's persisted choice (spec §9.5).",
|
|
196
180
|
"examples": [
|
|
197
181
|
{
|
|
182
|
+
"--dark": "(prefers-color-scheme: dark)",
|
|
198
183
|
"--lg": "(min-width: 1024px)",
|
|
199
184
|
"--md": "(min-width: 768px)",
|
|
200
185
|
"--sm": "(min-width: 640px)"
|
|
@@ -211,13 +196,7 @@
|
|
|
211
196
|
"properties": {
|
|
212
197
|
"adapter": {
|
|
213
198
|
"description": "Platform adapter for deployment-specific output.",
|
|
214
|
-
"enum": [
|
|
215
|
-
"static",
|
|
216
|
-
"cloudflare-pages",
|
|
217
|
-
"cloudflare-workers",
|
|
218
|
-
"node",
|
|
219
|
-
"bun"
|
|
220
|
-
],
|
|
199
|
+
"enum": ["static", "cloudflare-pages", "cloudflare-workers", "node", "bun"],
|
|
221
200
|
"type": "string"
|
|
222
201
|
},
|
|
223
202
|
"deploy": {
|
|
@@ -239,26 +218,17 @@
|
|
|
239
218
|
},
|
|
240
219
|
"provider": {
|
|
241
220
|
"description": "Hosting provider the project is connected to.",
|
|
242
|
-
"enum": [
|
|
243
|
-
"cloudflare-pages"
|
|
244
|
-
],
|
|
221
|
+
"enum": ["cloudflare-pages"],
|
|
245
222
|
"type": "string"
|
|
246
223
|
}
|
|
247
224
|
},
|
|
248
|
-
"required": [
|
|
249
|
-
"provider",
|
|
250
|
-
"accountId",
|
|
251
|
-
"projectName"
|
|
252
|
-
],
|
|
225
|
+
"required": ["provider", "accountId", "projectName"],
|
|
253
226
|
"type": "object"
|
|
254
227
|
},
|
|
255
228
|
"format": {
|
|
256
229
|
"default": "directory",
|
|
257
230
|
"description": "Reserved; currently unused. Accepted for forward compatibility with single-file output (desktop single-file mode) — the build emits per-route directories regardless.",
|
|
258
|
-
"enum": [
|
|
259
|
-
"directory",
|
|
260
|
-
"single"
|
|
261
|
-
],
|
|
231
|
+
"enum": ["directory", "single"],
|
|
262
232
|
"type": "string"
|
|
263
233
|
},
|
|
264
234
|
"outDir": {
|
|
@@ -274,11 +244,7 @@
|
|
|
274
244
|
"trailingSlash": {
|
|
275
245
|
"default": "always",
|
|
276
246
|
"description": "Trailing slash behavior for generated URLs.",
|
|
277
|
-
"enum": [
|
|
278
|
-
"always",
|
|
279
|
-
"never",
|
|
280
|
-
"ignore"
|
|
281
|
-
],
|
|
247
|
+
"enum": ["always", "never", "ignore"],
|
|
282
248
|
"type": "string"
|
|
283
249
|
}
|
|
284
250
|
},
|
|
@@ -307,9 +273,7 @@
|
|
|
307
273
|
"layout": {
|
|
308
274
|
"default": null,
|
|
309
275
|
"description": "Default layout file path applied to all pages. Set to null to render pages without a layout.",
|
|
310
|
-
"examples": [
|
|
311
|
-
"./layouts/base.json"
|
|
312
|
-
],
|
|
276
|
+
"examples": ["./layouts/base.json"],
|
|
313
277
|
"oneOf": [
|
|
314
278
|
{
|
|
315
279
|
"type": "string"
|
|
@@ -324,11 +288,7 @@
|
|
|
324
288
|
},
|
|
325
289
|
"extensions": {
|
|
326
290
|
"description": "Extension packages: bare package names (resolved project-first through the package exports map) or relative paths. Each must export jx-extension.json.",
|
|
327
|
-
"examples": [
|
|
328
|
-
[
|
|
329
|
-
"@jxsuite/parser"
|
|
330
|
-
]
|
|
331
|
-
],
|
|
291
|
+
"examples": [["@jxsuite/parser"]],
|
|
332
292
|
"items": {
|
|
333
293
|
"type": "string"
|
|
334
294
|
},
|
|
@@ -339,20 +299,12 @@
|
|
|
339
299
|
"properties": {
|
|
340
300
|
"defaultLocale": {
|
|
341
301
|
"description": "Default locale code.",
|
|
342
|
-
"examples": [
|
|
343
|
-
"en"
|
|
344
|
-
],
|
|
302
|
+
"examples": ["en"],
|
|
345
303
|
"type": "string"
|
|
346
304
|
},
|
|
347
305
|
"locales": {
|
|
348
306
|
"description": "Available locale codes.",
|
|
349
|
-
"examples": [
|
|
350
|
-
[
|
|
351
|
-
"en",
|
|
352
|
-
"fr",
|
|
353
|
-
"de"
|
|
354
|
-
]
|
|
355
|
-
],
|
|
307
|
+
"examples": [["en", "fr", "de"]],
|
|
356
308
|
"items": {
|
|
357
309
|
"type": "string"
|
|
358
310
|
},
|
|
@@ -360,10 +312,7 @@
|
|
|
360
312
|
},
|
|
361
313
|
"routing": {
|
|
362
314
|
"description": "Locale routing strategy.",
|
|
363
|
-
"enum": [
|
|
364
|
-
"prefix-except-default",
|
|
365
|
-
"prefix-always"
|
|
366
|
-
],
|
|
315
|
+
"enum": ["prefix-except-default", "prefix-always"],
|
|
367
316
|
"type": "string"
|
|
368
317
|
}
|
|
369
318
|
},
|
|
@@ -388,10 +337,7 @@
|
|
|
388
337
|
"name": {
|
|
389
338
|
"default": "Jx Site",
|
|
390
339
|
"description": "Human-readable project name.",
|
|
391
|
-
"examples": [
|
|
392
|
-
"My Portfolio",
|
|
393
|
-
"Jx Example Site"
|
|
394
|
-
],
|
|
340
|
+
"examples": ["My Portfolio", "Jx Example Site"],
|
|
395
341
|
"type": "string"
|
|
396
342
|
},
|
|
397
343
|
"redirects": {
|
|
@@ -429,13 +375,10 @@
|
|
|
429
375
|
},
|
|
430
376
|
"url": {
|
|
431
377
|
"description": "Production URL of the deployed site.",
|
|
432
|
-
"examples": [
|
|
433
|
-
"https://example.com",
|
|
434
|
-
"https://jxsuite.com"
|
|
435
|
-
],
|
|
378
|
+
"examples": ["https://example.com", "https://jxsuite.com"],
|
|
436
379
|
"type": "string"
|
|
437
380
|
}
|
|
438
381
|
},
|
|
439
382
|
"title": "Jx Project Core",
|
|
440
383
|
"type": "object"
|
|
441
|
-
}
|
|
384
|
+
}
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
],
|
|
12
12
|
"description": "Default field-schema union for section entry schemas: the core field shape plus relationship references. Per-project entry documents override this resource with the effective union. See specs/extensions.md §5.3.",
|
|
13
13
|
"title": "Jx Project Field Union"
|
|
14
|
-
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic mapping from Function-def `$src` module specifiers to bundled asset URLs. Shared
|
|
3
|
+
* between the compiler's sidecar bundler (which writes the bundle) and extension `lower()`
|
|
4
|
+
* implementations (which emit the URL into client code) so neither needs to depend on the other.
|
|
5
|
+
*
|
|
6
|
+
* The mapping is intentionally hash-free: the same specifier always yields the same URL, letting
|
|
7
|
+
* lowered defs reference bundles the compiler produces later in the build. Distinct specifiers that
|
|
8
|
+
* collide on a slug are rejected by the bundler at build time.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Prefix for npm package specifiers in `$src` (spec §12): `npm:<pkg>[/subpath]`. */
|
|
12
|
+
export const NPM_SPECIFIER_PREFIX = "npm:";
|
|
13
|
+
|
|
14
|
+
/** URL directory (under the site root) where bundled sidecars are written. */
|
|
15
|
+
export const SIDECAR_ASSET_DIR = "/assets/";
|
|
16
|
+
|
|
17
|
+
/** True when a `$src` specifier names an npm package rather than a project file. */
|
|
18
|
+
export function isNpmSpecifier(specifier: string): boolean {
|
|
19
|
+
return specifier.startsWith(NPM_SPECIFIER_PREFIX);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Map a Function-def `$src` specifier to its bundled asset URL.
|
|
24
|
+
*
|
|
25
|
+
* `npm:@jxsuite/search/client` → `/assets/jxsuite-search-client.js` `./lib/search-helpers.ts` →
|
|
26
|
+
* `/assets/lib-search-helpers.js`
|
|
27
|
+
*/
|
|
28
|
+
export function sidecarAssetPath(specifier: string): string {
|
|
29
|
+
let base = specifier;
|
|
30
|
+
if (isNpmSpecifier(base)) {
|
|
31
|
+
base = base.slice(NPM_SPECIFIER_PREFIX.length);
|
|
32
|
+
}
|
|
33
|
+
base = base
|
|
34
|
+
.replace(/^\.\//, "")
|
|
35
|
+
.replace(/\.(js|ts|mjs|mts)$/, "")
|
|
36
|
+
.replaceAll("@", "")
|
|
37
|
+
.replaceAll(/[/\\]+/g, "-")
|
|
38
|
+
.replaceAll(/[^\w.-]/g, "-")
|
|
39
|
+
.replaceAll(/-+/g, "-")
|
|
40
|
+
.replaceAll(/^-|-$/g, "");
|
|
41
|
+
return `${SIDECAR_ASSET_DIR}${base}.js`;
|
|
42
|
+
}
|
|
@@ -151,6 +151,11 @@ export class ExtensionRegistry {
|
|
|
151
151
|
return this.#classes.find((e) => e.capabilities.resolvePaths?.discriminator === key);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/** Classes declaring an `emit` capability (build-time asset emission), in declaration order. */
|
|
155
|
+
emitters(): FormatEntry[] {
|
|
156
|
+
return this.#classes.filter((e) => e.capabilities.emit !== undefined);
|
|
157
|
+
}
|
|
158
|
+
|
|
154
159
|
/** Server-mount classes, sorted by `server.order` (ascending; default 100), then name. */
|
|
155
160
|
serverMounts(): FormatEntry[] {
|
|
156
161
|
return this.#classes
|
package/src/format-registry.ts
CHANGED
|
@@ -21,14 +21,16 @@ export const FORMAT_CAPABILITIES: readonly FormatCapability[] = [
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* All well-known static capability roles across admission blocks (specs/extensions.md §8): format
|
|
24
|
-
* roles plus project-section (`projectData`, `resolvePaths`), compile-away (`lower`),
|
|
25
|
-
* (`mount`), and connector (`dialect`, `deploySchema`,
|
|
24
|
+
* roles plus project-section (`projectData`, `resolvePaths`), compile-away (`lower`), build-time
|
|
25
|
+
* asset emission (`emit`), server-mount (`mount`), and connector (`dialect`, `deploySchema`,
|
|
26
|
+
* `bindings`, `testConnection`) roles.
|
|
26
27
|
*/
|
|
27
28
|
export type ExtensionCapability =
|
|
28
29
|
| FormatCapability
|
|
29
30
|
| "projectData"
|
|
30
31
|
| "resolvePaths"
|
|
31
32
|
| "lower"
|
|
33
|
+
| "emit"
|
|
32
34
|
| "mount"
|
|
33
35
|
| "dialect"
|
|
34
36
|
| "deploySchema"
|
|
@@ -40,6 +42,7 @@ export const EXTENSION_CAPABILITIES: readonly ExtensionCapability[] = [
|
|
|
40
42
|
"projectData",
|
|
41
43
|
"resolvePaths",
|
|
42
44
|
"lower",
|
|
45
|
+
"emit",
|
|
43
46
|
"mount",
|
|
44
47
|
"dialect",
|
|
45
48
|
"deploySchema",
|
package/src/schema.ts
CHANGED
|
@@ -338,7 +338,10 @@ export async function generateSchema() {
|
|
|
338
338
|
additionalProperties: { type: "string" },
|
|
339
339
|
description:
|
|
340
340
|
"Named media breakpoints following CSS @custom-media convention. " +
|
|
341
|
-
"Keys use the CSS custom property -- prefix."
|
|
341
|
+
"Keys use the CSS custom property -- prefix. Pure color-scheme queries " +
|
|
342
|
+
'(e.g. "--dark": "(prefers-color-scheme: dark)") are dual-emitted so a ' +
|
|
343
|
+
"data-color-scheme attribute on the root element forces the scheme " +
|
|
344
|
+
"regardless of the OS preference (spec §9.5).",
|
|
342
345
|
examples: [
|
|
343
346
|
{
|
|
344
347
|
"--dark": "(prefers-color-scheme: dark)",
|
|
@@ -674,6 +677,30 @@ async function runSchemaCli() {
|
|
|
674
677
|
writeFileSync(resolve(schemaDir, "schemas", "project.fields.schema.json"), fieldsStr, "utf8");
|
|
675
678
|
writeFileSync(resolve(schemaDir, "schemas", "document.paths.schema.json"), pathsStr, "utf8");
|
|
676
679
|
writeFileSync(resolve(schemaDir, "extension-manifest.schema.json"), manifestStr, "utf8");
|
|
680
|
+
// The schemas/ fragments are oxfmt-managed (unlike packages/schema/*.json, which .oxfmtrc
|
|
681
|
+
// Ignores), so emit them formatted — otherwise every `bun run generate:schema` reintroduces
|
|
682
|
+
// Raw-stringify formatting and dirties the tree. This is a dev-hygiene step only: the JSON
|
|
683
|
+
// Above is already written and valid, and oxfmt just prettifies it (e.g. collapsing short enum
|
|
684
|
+
// Arrays onto one line). Inside a sandboxed/offline build (e.g. `nix build`) oxfmt exits
|
|
685
|
+
// Non-zero with no diagnostic output, so treat a failure as non-fatal and keep the valid JSON
|
|
686
|
+
// Rather than aborting the build over cosmetic formatting.
|
|
687
|
+
const fmt = Bun.spawnSync(
|
|
688
|
+
[
|
|
689
|
+
"bunx",
|
|
690
|
+
"oxfmt",
|
|
691
|
+
resolve(schemaDir, "schemas", "project.core.schema.json"),
|
|
692
|
+
resolve(schemaDir, "schemas", "project.fields.schema.json"),
|
|
693
|
+
resolve(schemaDir, "schemas", "document.paths.schema.json"),
|
|
694
|
+
],
|
|
695
|
+
{ cwd: schemaDir },
|
|
696
|
+
);
|
|
697
|
+
if (fmt.exitCode !== 0) {
|
|
698
|
+
const detail =
|
|
699
|
+
fmt.stderr.toString() ||
|
|
700
|
+
fmt.stdout.toString() ||
|
|
701
|
+
`exit ${fmt.exitCode ?? "null"}${fmt.signalCode ? `, signal ${fmt.signalCode}` : ""}`;
|
|
702
|
+
console.error(`Warning: skipped oxfmt reformat of generated schemas (${detail})`);
|
|
703
|
+
}
|
|
677
704
|
console.error("Generated:");
|
|
678
705
|
console.error(" schema.json (component)");
|
|
679
706
|
console.error(" project-schema.json");
|