@jxsuite/schema 1.4.0 → 1.8.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/class-schema.json +1 -0
- package/defs/children-value.schema.ts +10 -1
- package/defs/class-def.schema.ts +1 -0
- package/defs/element-def.schema.ts +1 -1
- package/defs/expression-node.schema.ts +4 -1
- package/defs/external-class-def.schema.ts +20 -2
- package/defs/field-schema.schema.ts +75 -0
- package/defs/head-entry.schema.ts +6 -1
- package/defs/image-config.schema.ts +7 -0
- package/defs/index.ts +2 -1
- package/defs/project-config.schema.ts +299 -7
- package/defs/tag-expression.schema.ts +98 -0
- package/defs/tag-name.schema.ts +13 -1
- package/package.json +7 -3
- package/project-schema.json +441 -5
- package/schema.json +289 -13
- package/schemas/document.paths.schema.json +54 -1
- package/schemas/project.core.schema.json +401 -5
- package/src/asset-paths.ts +21 -0
- package/src/extension-registry.ts +12 -0
- package/src/format-registry.ts +32 -2
- package/src/guards.ts +68 -2
- package/src/ijson.ts +205 -0
- package/src/intl.ts +155 -0
- package/src/locale.ts +429 -0
- package/src/media-type.ts +217 -0
- package/src/parse.ts +78 -1
- package/src/project-schemas.ts +358 -12
- package/src/schema.ts +85 -8
- package/types.ts +191 -4
package/types.ts
CHANGED
|
@@ -200,7 +200,11 @@ export interface JxServerFnDef {
|
|
|
200
200
|
export interface JxHeadEntry {
|
|
201
201
|
tagName: string;
|
|
202
202
|
attributes?: Record<string, string | boolean>;
|
|
203
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Element content. An **object** is a structured data block — the compiler serializes it to JSON
|
|
205
|
+
* inside the tag, which is how JSON-LD is authored (site-architecture.md §8.5).
|
|
206
|
+
*/
|
|
207
|
+
textContent?: string | Record<string, unknown>;
|
|
204
208
|
children?: (JxHeadEntry | string)[];
|
|
205
209
|
[key: string]: unknown;
|
|
206
210
|
}
|
|
@@ -212,6 +216,8 @@ export interface ImageConfig {
|
|
|
212
216
|
quality?: { webp?: number; avif?: number; jpeg?: number; png?: number };
|
|
213
217
|
sizes?: string;
|
|
214
218
|
lazyLoad?: boolean;
|
|
219
|
+
/** Wrap a multi-format image in a `<picture>` with one `<source>` per format. Default true. */
|
|
220
|
+
picture?: boolean;
|
|
215
221
|
service?: "build" | "cloudflare";
|
|
216
222
|
remoteDomains?: string[];
|
|
217
223
|
}
|
|
@@ -240,8 +246,26 @@ export interface JxStyle {
|
|
|
240
246
|
[property: string]: string | number | JxStyle | undefined;
|
|
241
247
|
}
|
|
242
248
|
|
|
249
|
+
/**
|
|
250
|
+
* A tag chosen when the element is created, from a set the schema enumerates.
|
|
251
|
+
*
|
|
252
|
+
* Both branches resolve to a `TagName`, so the candidates are readable without evaluating anything
|
|
253
|
+
* — which is what lets the compiler emit one template per candidate and `jx validate` refuse an
|
|
254
|
+
* illegal name at authoring time. See `defs/tag-expression.schema.ts` for why this is not a `${…}`
|
|
255
|
+
* template and not a third `$switch` spelling.
|
|
256
|
+
*/
|
|
257
|
+
export type JxTagExpression =
|
|
258
|
+
| { operator: "?:"; target: unknown; value: string; initial: string }
|
|
259
|
+
| { operator: "switch"; target: unknown; cases: Record<string, string>; default: string };
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* An ELEMENT's tag. The document root's and a head entry's stay `string` — see
|
|
263
|
+
* `defs/tag-expression.schema.ts`.
|
|
264
|
+
*/
|
|
265
|
+
export type JxElementTagName = string | { $expression: JxTagExpression };
|
|
266
|
+
|
|
243
267
|
export interface JxElement {
|
|
244
|
-
tagName?:
|
|
268
|
+
tagName?: JxElementTagName;
|
|
245
269
|
textContent?: string | null | JxRef;
|
|
246
270
|
innerHTML?: string;
|
|
247
271
|
/**
|
|
@@ -285,8 +309,19 @@ export interface JxMappedArray {
|
|
|
285
309
|
}
|
|
286
310
|
|
|
287
311
|
export interface JxDocument extends JxElement {
|
|
312
|
+
/**
|
|
313
|
+
* The custom element's NAME, always a literal.
|
|
314
|
+
*
|
|
315
|
+
* Narrowed from {@link JxElement.tagName} deliberately: this string becomes
|
|
316
|
+
* `customElements.define(…)`, the emitted module's file name and a CSS selector prefix, none of
|
|
317
|
+
* which can be chosen per instance. Carrying the rule in the type means `defineElement` and the
|
|
318
|
+
* compiler keep receiving a string without a positional guard anyone can forget to write.
|
|
319
|
+
*/
|
|
320
|
+
tagName?: string;
|
|
288
321
|
state?: Record<string, JxStateDefinition>;
|
|
289
322
|
$layout?: string | false;
|
|
323
|
+
/** This page's identity across languages, overriding the one its path implies (§13.5). */
|
|
324
|
+
$translationKey?: string;
|
|
290
325
|
$paths?: JxPathsDef;
|
|
291
326
|
$elements?: (JxElement | string)[];
|
|
292
327
|
$head?: JxHeadEntry[];
|
|
@@ -483,6 +518,114 @@ export type AdapterId = "static" | "cloudflare-pages" | "cloudflare-workers" | "
|
|
|
483
518
|
* Identifiers only — no secrets — so it travels with the repo and any Studio (local or cloud) can
|
|
484
519
|
* tell whether publishing is set up.
|
|
485
520
|
*/
|
|
521
|
+
/** `dist/_headers` output — the response headers only the build can know (RFC 9111, RFC 8246). */
|
|
522
|
+
/**
|
|
523
|
+
* CSP Level 3, as far as a static build can go.
|
|
524
|
+
*
|
|
525
|
+
* Off by default. Every other security header the build emits is safe to turn on for a site that
|
|
526
|
+
* has never seen one; a policy is the one that can leave a page blank, because it governs code the
|
|
527
|
+
* build cannot see — a third-party script that loads a second script, a widget that opens a frame.
|
|
528
|
+
* Turning it on is one line and one look at the browser console.
|
|
529
|
+
*/
|
|
530
|
+
export interface CspConfig {
|
|
531
|
+
/** `"report-only"` sends `Content-Security-Policy-Report-Only`. Default `"enforce"`. */
|
|
532
|
+
mode?: "enforce" | "report-only";
|
|
533
|
+
/**
|
|
534
|
+
* Replace or remove a computed directive. `false` removes it; a string replaces it wholesale, so
|
|
535
|
+
* an addition means restating the default's sources alongside the new one.
|
|
536
|
+
*/
|
|
537
|
+
directives?: Record<string, string | false>;
|
|
538
|
+
/** Where violation reports go. Emits `report-to`, `report-uri` and `Reporting-Endpoints`. */
|
|
539
|
+
reportUri?: string;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* W3C Web App Manifest. Off unless declared — a manifest is a claim that a site is meant to be
|
|
544
|
+
* installed, and most are not.
|
|
545
|
+
*/
|
|
546
|
+
export interface ManifestConfig {
|
|
547
|
+
enabled?: boolean;
|
|
548
|
+
/** Defaults to the project `name`. */
|
|
549
|
+
name?: string;
|
|
550
|
+
shortName?: string;
|
|
551
|
+
description?: string;
|
|
552
|
+
/** Defaults to `/`. */
|
|
553
|
+
startUrl?: string;
|
|
554
|
+
scope?: string;
|
|
555
|
+
display?: "fullscreen" | "standalone" | "minimal-ui" | "browser";
|
|
556
|
+
orientation?: string;
|
|
557
|
+
themeColor?: string;
|
|
558
|
+
backgroundColor?: string;
|
|
559
|
+
lang?: string;
|
|
560
|
+
dir?: "ltr" | "rtl" | "auto";
|
|
561
|
+
categories?: string[];
|
|
562
|
+
icons?: { src: string; sizes?: string; type?: string; purpose?: string }[];
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* W3C Service Worker. **Off unless declared, and turning it off means `false`, not deleting the
|
|
567
|
+
* key** — a worker is sticky, so a site that once had one must keep serving something at that URL
|
|
568
|
+
* to tell previous visitors to stop.
|
|
569
|
+
*/
|
|
570
|
+
export interface ServiceWorkerConfig {
|
|
571
|
+
enabled?: boolean;
|
|
572
|
+
/** Registration scope. Cannot exceed the worker's own path. Default `"/"`. */
|
|
573
|
+
scope?: string;
|
|
574
|
+
/** URLs fetched and cached at install time. */
|
|
575
|
+
precache?: string[];
|
|
576
|
+
/** Page served for a failed navigation. Added to `precache` if it is not already there. */
|
|
577
|
+
offlineFallback?: string;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* RFC 9116 `security.txt`. `expires` is required by §2.5.5 and an absent or past one is a build
|
|
582
|
+
* error: an expired file advertises a reporting channel while telling the reporter not to trust
|
|
583
|
+
* it.
|
|
584
|
+
*/
|
|
585
|
+
export interface SecurityTxtConfig {
|
|
586
|
+
enabled?: boolean;
|
|
587
|
+
/** At least one is required (§2.5.3): a `mailto:`, `https:` or `tel:` URI. */
|
|
588
|
+
contact?: string[];
|
|
589
|
+
/** RFC 3339 date-time; §2.5.5. */
|
|
590
|
+
expires?: string;
|
|
591
|
+
encryption?: string[];
|
|
592
|
+
acknowledgments?: string[];
|
|
593
|
+
/** BCP 47 tags, validated and canonicalized like `i18n.locales`. */
|
|
594
|
+
preferredLanguages?: string[];
|
|
595
|
+
canonical?: string;
|
|
596
|
+
policy?: string[];
|
|
597
|
+
hiring?: string[];
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export interface HeadersConfig {
|
|
601
|
+
/** Emit the file at all. Default true. */
|
|
602
|
+
enabled?: boolean;
|
|
603
|
+
/**
|
|
604
|
+
* `"auto"` marks the content-addressed image variants immutable and revalidates everything else.
|
|
605
|
+
* `"off"` emits no `Cache-Control` at all, for a host that manages caching itself.
|
|
606
|
+
*/
|
|
607
|
+
cache?: "auto" | "off";
|
|
608
|
+
security?: {
|
|
609
|
+
/** `X-Content-Type-Options: nosniff`. Default true. */
|
|
610
|
+
contentTypeOptions?: boolean;
|
|
611
|
+
/** `X-Frame-Options`, or false to omit. Default `"SAMEORIGIN"`. */
|
|
612
|
+
frameOptions?: "DENY" | "SAMEORIGIN" | false;
|
|
613
|
+
/** `Referrer-Policy`, or false to omit. Default `"strict-origin-when-cross-origin"`. */
|
|
614
|
+
referrerPolicy?: string | false;
|
|
615
|
+
/** `Permissions-Policy`, or false to omit. */
|
|
616
|
+
permissionsPolicy?: string | false;
|
|
617
|
+
/**
|
|
618
|
+
* RFC 6797. **Off by default**: a wrong `max-age` locks an apex domain to HTTPS for that long,
|
|
619
|
+
* and the mistake is not visible until a certificate lapses.
|
|
620
|
+
*/
|
|
621
|
+
hsts?: boolean | { maxAge?: number; includeSubDomains?: boolean; preload?: boolean };
|
|
622
|
+
/** CSP Level 3. Off by default — see {@link CspConfig}. */
|
|
623
|
+
csp?: boolean | "report-only" | CspConfig;
|
|
624
|
+
};
|
|
625
|
+
/** Verbatim rules, merged after the generated block. Keys are path patterns. */
|
|
626
|
+
rules?: Record<string, Record<string, string>>;
|
|
627
|
+
}
|
|
628
|
+
|
|
486
629
|
export interface DeployConfig {
|
|
487
630
|
provider: "cloudflare-pages";
|
|
488
631
|
accountId: string;
|
|
@@ -504,6 +647,7 @@ export interface ProjectConfig {
|
|
|
504
647
|
adapter?: AdapterId | (string & Record<never, never>);
|
|
505
648
|
deploy?: DeployConfig;
|
|
506
649
|
sitemap?: boolean;
|
|
650
|
+
headers?: HeadersConfig;
|
|
507
651
|
[key: string]: unknown;
|
|
508
652
|
};
|
|
509
653
|
images?: ImageConfig;
|
|
@@ -515,11 +659,39 @@ export interface ProjectConfig {
|
|
|
515
659
|
*/
|
|
516
660
|
extensions?: string[];
|
|
517
661
|
/** Redirect map: source path → destination (or destination with HTTP status). */
|
|
518
|
-
redirects?: Record<
|
|
662
|
+
redirects?: Record<
|
|
663
|
+
string,
|
|
664
|
+
string | { destination: string; status?: number } | { destination: string; rewrite: true }
|
|
665
|
+
>;
|
|
666
|
+
/** W3C Web App Manifest, emitted as `manifest.webmanifest`. */
|
|
667
|
+
manifest?: ManifestConfig;
|
|
668
|
+
/** RFC 9116, emitted as `.well-known/security.txt`. */
|
|
669
|
+
securityTxt?: SecurityTxtConfig;
|
|
670
|
+
/**
|
|
671
|
+
* W3C Service Worker, emitted as `sw.js`. Off unless declared; `false` emits a tombstone that
|
|
672
|
+
* unregisters a previously deployed worker (site-architecture.md §14.6).
|
|
673
|
+
*/
|
|
674
|
+
serviceWorker?: ServiceWorkerConfig | boolean;
|
|
675
|
+
/**
|
|
676
|
+
* Locale routing. Tags are BCP 47; a malformed one is a build error, since a locale is a URL
|
|
677
|
+
* prefix, an `hreflang` value and an `<html lang>` at once.
|
|
678
|
+
*/
|
|
679
|
+
i18n?: {
|
|
680
|
+
defaultLocale?: string;
|
|
681
|
+
locales?: string[];
|
|
682
|
+
routing?: "prefix-except-default" | "prefix-always";
|
|
683
|
+
};
|
|
519
684
|
defaults?: {
|
|
520
685
|
/** Default layout path; `null` means explicitly no layout. */
|
|
521
686
|
layout?: string | null;
|
|
522
687
|
lang?: string;
|
|
688
|
+
/** Base direction for `<html dir>`. A page's `$dir` overrides it. */
|
|
689
|
+
dir?: "ltr" | "rtl" | "auto";
|
|
690
|
+
/**
|
|
691
|
+
* Default shadow-DOM mode for components. `false` (light DOM) unless set; a component's own
|
|
692
|
+
* `$shadow` overrides it in both directions.
|
|
693
|
+
*/
|
|
694
|
+
shadow?: "open" | "closed" | false;
|
|
523
695
|
charset?: string;
|
|
524
696
|
[key: string]: unknown;
|
|
525
697
|
};
|
|
@@ -550,7 +722,7 @@ export type JxPathsDef =
|
|
|
550
722
|
* `@jxsuite/schema/guards` before use.
|
|
551
723
|
*/
|
|
552
724
|
export interface JxMutableNode {
|
|
553
|
-
tagName?:
|
|
725
|
+
tagName?: JxElementTagName;
|
|
554
726
|
textContent?: string | null | JxRef;
|
|
555
727
|
innerHTML?: string;
|
|
556
728
|
/**
|
|
@@ -639,5 +811,20 @@ export interface ContentLoaderEntry {
|
|
|
639
811
|
toc?: TocEntry[];
|
|
640
812
|
readingTime?: number;
|
|
641
813
|
wordCount?: number;
|
|
814
|
+
/**
|
|
815
|
+
* The source file's modification time, RFC 3339. The fallback a feed uses when an entry carries
|
|
816
|
+
* no authored date, and what lets the sitemap give a generated page its own `<lastmod>` rather
|
|
817
|
+
* than its template's.
|
|
818
|
+
*/
|
|
819
|
+
mtime?: string;
|
|
820
|
+
/** Authored text of a field the date-coercion pass rewrote, keyed by field name. */
|
|
821
|
+
rawDates?: Record<string, unknown>;
|
|
822
|
+
/**
|
|
823
|
+
* The locale this entry was loaded for, set only when its content type's `source` carried a
|
|
824
|
+
* `{locale}` placeholder. It is what lets a `[slug]` route under `/fr/` expand the French
|
|
825
|
+
* entries and not the English ones — without it, two translations of one post share an id and
|
|
826
|
+
* the second silently overwrites the first's route.
|
|
827
|
+
*/
|
|
828
|
+
locale?: string;
|
|
642
829
|
};
|
|
643
830
|
}
|