@caelo-cms/shared 0.10.23 → 0.10.26

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.
Files changed (137) hide show
  1. package/dist/ai-tools.d.ts +15 -70
  2. package/dist/ai-tools.d.ts.map +1 -1
  3. package/dist/ai-tools.js +14 -74
  4. package/dist/ai-tools.js.map +1 -1
  5. package/dist/base-css.d.ts +11 -0
  6. package/dist/base-css.d.ts.map +1 -1
  7. package/dist/base-css.js +13 -1
  8. package/dist/base-css.js.map +1 -1
  9. package/dist/build-page.d.ts +0 -2
  10. package/dist/build-page.d.ts.map +1 -1
  11. package/dist/build-page.js +2 -3
  12. package/dist/build-page.js.map +1 -1
  13. package/dist/content.d.ts +0 -3
  14. package/dist/content.d.ts.map +1 -1
  15. package/dist/content.js +91 -7
  16. package/dist/content.js.map +1 -1
  17. package/dist/context.d.ts +6 -0
  18. package/dist/context.d.ts.map +1 -1
  19. package/dist/design-draft-shell.d.ts +21 -0
  20. package/dist/design-draft-shell.d.ts.map +1 -0
  21. package/dist/design-draft-shell.js +81 -0
  22. package/dist/design-draft-shell.js.map +1 -0
  23. package/dist/font-assets.d.ts +89 -0
  24. package/dist/font-assets.d.ts.map +1 -0
  25. package/dist/font-assets.js +61 -0
  26. package/dist/font-assets.js.map +1 -0
  27. package/dist/genesis.d.ts +43 -3
  28. package/dist/genesis.d.ts.map +1 -1
  29. package/dist/genesis.js +72 -5
  30. package/dist/genesis.js.map +1 -1
  31. package/dist/google-models.d.ts +35 -0
  32. package/dist/google-models.d.ts.map +1 -0
  33. package/dist/google-models.js +20 -0
  34. package/dist/google-models.js.map +1 -0
  35. package/dist/index.d.ts +5 -3
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +5 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/media.d.ts +0 -3
  40. package/dist/media.d.ts.map +1 -1
  41. package/dist/media.js +0 -5
  42. package/dist/media.js.map +1 -1
  43. package/dist/plugin-preview.d.ts +44 -0
  44. package/dist/plugin-preview.d.ts.map +1 -0
  45. package/dist/plugin-preview.js +69 -0
  46. package/dist/plugin-preview.js.map +1 -0
  47. package/dist/preview-compose.d.ts +35 -15
  48. package/dist/preview-compose.d.ts.map +1 -1
  49. package/dist/preview-compose.js +95 -89
  50. package/dist/preview-compose.js.map +1 -1
  51. package/dist/responsive-images.d.ts +6 -5
  52. package/dist/responsive-images.d.ts.map +1 -1
  53. package/dist/responsive-images.js +6 -5
  54. package/dist/responsive-images.js.map +1 -1
  55. package/dist/seo.d.ts +11 -28
  56. package/dist/seo.d.ts.map +1 -1
  57. package/dist/seo.js +12 -31
  58. package/dist/seo.js.map +1 -1
  59. package/dist/structured-sets.d.ts +0 -36
  60. package/dist/structured-sets.d.ts.map +1 -1
  61. package/dist/structured-sets.js +1 -52
  62. package/dist/structured-sets.js.map +1 -1
  63. package/dist/template-engine.d.ts +18 -0
  64. package/dist/template-engine.d.ts.map +1 -1
  65. package/dist/template-engine.js +39 -2
  66. package/dist/template-engine.js.map +1 -1
  67. package/dist/theme-importers/loose.js +1 -1
  68. package/dist/theme-importers/loose.js.map +1 -1
  69. package/dist/theme-normalize.d.ts +9 -0
  70. package/dist/theme-normalize.d.ts.map +1 -1
  71. package/dist/theme-normalize.js +65 -6
  72. package/dist/theme-normalize.js.map +1 -1
  73. package/dist/theme-render.d.ts +15 -0
  74. package/dist/theme-render.d.ts.map +1 -1
  75. package/dist/theme-render.js +39 -0
  76. package/dist/theme-render.js.map +1 -1
  77. package/dist/themes.d.ts +15 -1
  78. package/dist/themes.d.ts.map +1 -1
  79. package/dist/themes.js +48 -1
  80. package/dist/themes.js.map +1 -1
  81. package/dist/url.d.ts +45 -0
  82. package/dist/url.d.ts.map +1 -0
  83. package/dist/url.js +64 -0
  84. package/dist/url.js.map +1 -0
  85. package/dist/version.d.ts +2 -2
  86. package/dist/version.js +1 -1
  87. package/package.json +2 -2
  88. package/src/__tests__/redos-hardening.test.ts +1 -1
  89. package/src/ai-tools.ts +14 -90
  90. package/src/base-css.ts +13 -1
  91. package/src/build-page.ts +3 -5
  92. package/src/content.test.ts +99 -17
  93. package/src/content.ts +95 -8
  94. package/src/context.ts +6 -0
  95. package/src/design-draft-shell.test.ts +85 -0
  96. package/src/design-draft-shell.ts +109 -0
  97. package/src/font-assets.ts +63 -0
  98. package/src/genesis.ts +76 -5
  99. package/src/google-models.ts +20 -0
  100. package/src/index.ts +5 -3
  101. package/src/media.ts +0 -6
  102. package/src/plugin-preview.test.ts +79 -0
  103. package/src/plugin-preview.ts +81 -0
  104. package/src/preview-compose-deferrals.test.ts +144 -0
  105. package/src/preview-compose.test.ts +51 -0
  106. package/src/preview-compose.ts +128 -93
  107. package/src/responsive-images.ts +6 -5
  108. package/src/seo.test.ts +8 -48
  109. package/src/seo.ts +16 -52
  110. package/src/structured-sets.ts +1 -67
  111. package/src/template-engine-data-lists.test.ts +90 -0
  112. package/src/template-engine.ts +72 -1
  113. package/src/theme-importers/loose.ts +1 -1
  114. package/src/theme-normalize.ts +70 -8
  115. package/src/theme-render.ts +36 -0
  116. package/src/theme-token-roles.test.ts +182 -0
  117. package/src/themes.ts +53 -0
  118. package/src/url.test.ts +40 -0
  119. package/src/url.ts +69 -0
  120. package/src/version.ts +1 -1
  121. package/dist/design-manifest.d.ts +0 -36
  122. package/dist/design-manifest.d.ts.map +0 -1
  123. package/dist/design-manifest.js +0 -90
  124. package/dist/design-manifest.js.map +0 -1
  125. package/dist/i18n.d.ts +0 -92
  126. package/dist/i18n.d.ts.map +0 -1
  127. package/dist/i18n.js +0 -226
  128. package/dist/i18n.js.map +0 -1
  129. package/dist/translation.d.ts +0 -127
  130. package/dist/translation.d.ts.map +0 -1
  131. package/dist/translation.js +0 -208
  132. package/dist/translation.js.map +0 -1
  133. package/src/design-manifest.ts +0 -93
  134. package/src/i18n.test.ts +0 -274
  135. package/src/i18n.ts +0 -269
  136. package/src/translation.test.ts +0 -160
  137. package/src/translation.ts +0 -295
package/src/url.ts ADDED
@@ -0,0 +1,69 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+
3
+ /**
4
+ * Slug/URL primitives shared between the static generator, the preview
5
+ * op, and the admin UI (epic #380 #384 — successor of the deleted
6
+ * i18n.ts). URL shape beyond base + slug becomes a plugin contribution
7
+ * on the URL composition point (#390).
8
+ *
9
+ * isHomeSlug / isDesignatedHomePage — the home-decision predicate.
10
+ * trimSlashes / trimTrailingSlashes — linear-scan slug hygiene.
11
+ */
12
+
13
+ /**
14
+ * Strip leading and trailing `/` characters with a single linear scan.
15
+ *
16
+ * Replaces the regex `/^\/+|\/+$/g`, whose trailing-slash branch
17
+ * backtracks O(n²) on a long run of slashes that is not at end-of-string
18
+ * (CodeQL js/polynomial-redos). This char-index walk is unconditionally
19
+ * linear and produces byte-identical output for every input.
20
+ */
21
+ export function trimSlashes(s: string): string {
22
+ let start = 0;
23
+ let end = s.length;
24
+ while (start < end && s.charCodeAt(start) === 47 /* '/' */) start += 1;
25
+ while (end > start && s.charCodeAt(end - 1) === 47 /* '/' */) end -= 1;
26
+ return s.slice(start, end);
27
+ }
28
+
29
+ /**
30
+ * Strip only trailing `/` characters with a single linear scan — the
31
+ * non-backtracking replacement for `/\/+$/` (same ReDoS class as above).
32
+ * Used for base URLs, which carry a scheme and must keep their leading
33
+ * characters.
34
+ */
35
+ export function trimTrailingSlashes(s: string): string {
36
+ let end = s.length;
37
+ while (end > 0 && s.charCodeAt(end - 1) === 47 /* '/' */) end -= 1;
38
+ return s.slice(0, end);
39
+ }
40
+
41
+ /**
42
+ * The "magic slug" sentinel test: a page whose slug is empty, `home`,
43
+ * or `index` is the site root by convention even without an explicit
44
+ * `site_defaults.home_page_id` designation. Leading/trailing slashes
45
+ * are ignored so `/home/` reads the same as `home`.
46
+ */
47
+ export function isHomeSlug(slug: string): boolean {
48
+ const s = trimSlashes(slug);
49
+ return s === "" || s === "home" || s === "index";
50
+ }
51
+
52
+ /**
53
+ * The single home-decision predicate every URL/output-path site must
54
+ * use so canonical, redirects, and the emitted file agree (0184
55
+ * explicit-homepage feature). A page is the site root when it IS the
56
+ * designated `site_defaults.home_page_id` OR carries a magic slug.
57
+ *
58
+ * @param pageId The page being resolved.
59
+ * @param slug That page's slug.
60
+ * @param designatedHomePageId `site_defaults.home_page_id`
61
+ * (null/undefined when none designated).
62
+ */
63
+ export function isDesignatedHomePage(
64
+ pageId: string,
65
+ slug: string,
66
+ designatedHomePageId: string | null | undefined,
67
+ ): boolean {
68
+ return (designatedHomePageId != null && pageId === designatedHomePageId) || isHomeSlug(slug);
69
+ }
package/src/version.ts CHANGED
@@ -22,7 +22,7 @@
22
22
  * follow standard SemVer.
23
23
  */
24
24
 
25
- export const CAELO_VERSION = "0.10.23";
25
+ export const CAELO_VERSION = "0.10.26";
26
26
 
27
27
  /**
28
28
  * Deprecated alias for back-compat — early P17 work spelled this
@@ -1,36 +0,0 @@
1
- /**
2
- * issue #165 — the Design Manifest: a generated, versioned description
3
- * of THIS site's design system (epic #149, growth-time convergence).
4
- *
5
- * The operator requirement is asymmetric: pages of the SAME site share
6
- * one visual line, while different sites are free to look nothing
7
- * alike. A global stylesheet solves the first at the cost of the
8
- * second; the per-site manifest solves both — it captures what this
9
- * site's tokens/patterns MEAN so the AI converges toward its own
10
- * design, not a Caelo default.
11
- *
12
- * Written at Genesis materialisation (or curated later via chat);
13
- * rendered as the `## Design system` system-prompt block.
14
- */
15
- import { z } from "zod";
16
- export declare const designManifestPattern: z.ZodObject<{
17
- name: z.ZodString;
18
- moduleType: z.ZodOptional<z.ZodString>;
19
- spec: z.ZodString;
20
- }, z.core.$strict>;
21
- export declare const designManifestSchema: z.ZodObject<{
22
- tokenRoles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
23
- typography: z.ZodOptional<z.ZodString>;
24
- rhythm: z.ZodOptional<z.ZodString>;
25
- patterns: z.ZodOptional<z.ZodArray<z.ZodObject<{
26
- name: z.ZodString;
27
- moduleType: z.ZodOptional<z.ZodString>;
28
- spec: z.ZodString;
29
- }, z.core.$strict>>>;
30
- imagery: z.ZodOptional<z.ZodString>;
31
- avoid: z.ZodOptional<z.ZodString>;
32
- }, z.core.$strict>;
33
- export type DesignManifest = z.infer<typeof designManifestSchema>;
34
- /** Render the `## Design system` prompt block. Null when empty. */
35
- export declare function formatDesignSystemBlock(manifest: DesignManifest | null): string | null;
36
- //# sourceMappingURL=design-manifest.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"design-manifest.d.ts","sourceRoot":"","sources":["../src/design-manifest.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,qBAAqB;;;;kBASvB,CAAC;AAEZ,eAAO,MAAM,oBAAoB;;;;;;;;;;;kBAYtB,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,mEAAmE;AACnE,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CA8CtF"}
@@ -1,90 +0,0 @@
1
- // SPDX-License-Identifier: MPL-2.0
2
- /**
3
- * issue #165 — the Design Manifest: a generated, versioned description
4
- * of THIS site's design system (epic #149, growth-time convergence).
5
- *
6
- * The operator requirement is asymmetric: pages of the SAME site share
7
- * one visual line, while different sites are free to look nothing
8
- * alike. A global stylesheet solves the first at the cost of the
9
- * second; the per-site manifest solves both — it captures what this
10
- * site's tokens/patterns MEAN so the AI converges toward its own
11
- * design, not a Caelo default.
12
- *
13
- * Written at Genesis materialisation (or curated later via chat);
14
- * rendered as the `## Design system` system-prompt block.
15
- */
16
- import { z } from "zod";
17
- export const designManifestPattern = z
18
- .object({
19
- /** Pattern name the AI reasons in ("hero", "card grid", "cta band"). */
20
- name: z.string().min(1).max(80),
21
- /** Stable module `type` implementing it — reuse target (#159 place mode). */
22
- moduleType: z.string().max(64).optional(),
23
- /** One-line spec: what makes this pattern THIS site's version of it. */
24
- spec: z.string().min(1).max(500),
25
- })
26
- .strict();
27
- export const designManifestSchema = z
28
- .object({
29
- /** `--color-primary` → "CTAs and links only" — usage semantics per var. */
30
- tokenRoles: z.record(z.string().min(3).max(64), z.string().min(1).max(300)).optional(),
31
- /** Scale ratio, casing, measure rules. */
32
- typography: z.string().min(1).max(1000).optional(),
33
- /** Section padding, container width, grid gaps. */
34
- rhythm: z.string().min(1).max(1000).optional(),
35
- patterns: z.array(designManifestPattern).max(24).optional(),
36
- imagery: z.string().min(1).max(500).optional(),
37
- avoid: z.string().min(1).max(500).optional(),
38
- })
39
- .strict();
40
- /** Render the `## Design system` prompt block. Null when empty. */
41
- export function formatDesignSystemBlock(manifest) {
42
- if (manifest === null)
43
- return null;
44
- const lines = [
45
- "## Design system",
46
- "",
47
- "THIS site's own design language — derived from the chosen design. Every module you author or restyle conforms to it unless the operator explicitly asks to break the line. Reuse the pattern's module type (place mode) before minting lookalikes.",
48
- "",
49
- ];
50
- let hasContent = false;
51
- const roles = manifest.tokenRoles ?? {};
52
- const roleEntries = Object.entries(roles);
53
- if (roleEntries.length > 0) {
54
- hasContent = true;
55
- lines.push("Token roles:");
56
- for (const [token, role] of roleEntries.slice(0, 24))
57
- lines.push(`- \`${token}\` — ${role}`);
58
- lines.push("");
59
- }
60
- if (manifest.typography) {
61
- hasContent = true;
62
- lines.push(`Typography: ${manifest.typography}`, "");
63
- }
64
- if (manifest.rhythm) {
65
- hasContent = true;
66
- lines.push(`Rhythm: ${manifest.rhythm}`, "");
67
- }
68
- if (manifest.patterns && manifest.patterns.length > 0) {
69
- hasContent = true;
70
- lines.push("Patterns:");
71
- for (const p of manifest.patterns) {
72
- lines.push(`- **${p.name}**${p.moduleType ? ` (module type \`${p.moduleType}\`)` : ""} — ${p.spec}`);
73
- }
74
- lines.push("");
75
- }
76
- if (manifest.imagery) {
77
- hasContent = true;
78
- lines.push(`Imagery: ${manifest.imagery}`, "");
79
- }
80
- if (manifest.avoid) {
81
- hasContent = true;
82
- lines.push(`Never: ${manifest.avoid}`, "");
83
- }
84
- if (!hasContent)
85
- return null;
86
- while (lines[lines.length - 1] === "")
87
- lines.pop();
88
- return lines.join("\n");
89
- }
90
- //# sourceMappingURL=design-manifest.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"design-manifest.js","sourceRoot":"","sources":["../src/design-manifest.ts"],"names":[],"mappings":"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"}
package/dist/i18n.d.ts DELETED
@@ -1,92 +0,0 @@
1
- /**
2
- * Strip leading and trailing `/` characters with a single linear scan.
3
- *
4
- * Replaces the regex `/^\/+|\/+$/g`, whose trailing-slash branch
5
- * backtracks O(n²) on a long run of slashes that is not at end-of-string
6
- * (CodeQL js/polynomial-redos). This char-index walk is unconditionally
7
- * linear and produces byte-identical output for every input.
8
- */
9
- export declare function trimSlashes(s: string): string;
10
- /**
11
- * Strip only trailing `/` characters with a single linear scan — the
12
- * non-backtracking replacement for `/\/+$/` (same ReDoS class as above).
13
- * Used for base URLs, which carry a scheme and must keep their leading
14
- * characters.
15
- */
16
- export declare function trimTrailingSlashes(s: string): string;
17
- export interface LocaleConfig {
18
- code: string;
19
- displayName: string;
20
- urlStrategy: "none" | "subdirectory" | "subdomain" | "domain";
21
- urlHost: string | null;
22
- isDefault: boolean;
23
- }
24
- /**
25
- * The "magic slug" sentinel test: a page whose slug is empty, `home`,
26
- * or `index` is the locale root by convention even without an explicit
27
- * `locales.home_page_id` designation. Leading/trailing slashes are
28
- * ignored so `/home/` reads the same as `home`.
29
- */
30
- export declare function isHomeSlug(slug: string): boolean;
31
- /**
32
- * The single home-decision predicate every URL/output-path site must
33
- * use so canonical, hreflang, redirects, and the emitted file agree
34
- * (0184 explicit-homepage feature). A page is the locale root when it
35
- * IS the locale's designated `home_page_id` OR carries a magic slug.
36
- *
37
- * @param pageId The page being resolved.
38
- * @param slug That page's slug.
39
- * @param localeHomePageId `locales.home_page_id` for the page's locale
40
- * (null/undefined when no page is designated).
41
- */
42
- export declare function pageIsLocaleHome(pageId: string, slug: string, localeHomePageId: string | null | undefined): boolean;
43
- /**
44
- * Build a public-facing URL for a (locale, slug) tuple. Pure function —
45
- * no DB access — so the static generator can call it for every page
46
- * without round-trips.
47
- *
48
- * @param locale The target locale's full config row.
49
- * @param slug Path component (e.g. "about", "blog/post-1"). No leading slash.
50
- * @param siteBaseUrl Default base URL when the strategy is `none` or
51
- * `subdirectory` (e.g. "https://example.com").
52
- * @param pageUrlStyle Page emission style (see below).
53
- * @param isHomePage Explicit homepage designation (0184 —
54
- * `locales.home_page_id`). When true this page IS the
55
- * locale root and resolves to `<base>/` regardless of
56
- * its own slug. The explicit flag WINS over the slug
57
- * sentinel below; the sentinel stays as a back-compat
58
- * fallback for callers that can't cheaply surface the
59
- * designation.
60
- * @returns Absolute URL, including scheme + host.
61
- */
62
- export declare function resolveLocaleUrl(locale: LocaleConfig, slug: string, siteBaseUrl: string, pageUrlStyle?: "directory" | "no-extension", isHomePage?: boolean): string;
63
- /**
64
- * Emit `<link rel="alternate" hreflang="…">` tags for every locale
65
- * that has a published variant of this page. The default locale also
66
- * gets an `x-default` entry per Google's i18n guidance.
67
- *
68
- * Returned as a single string suitable for splicing into <head>.
69
- */
70
- export declare function buildHreflangLinks(perLocaleUrls: ReadonlyArray<{
71
- localeCode: string;
72
- url: string;
73
- isDefault: boolean;
74
- }>): string;
75
- /**
76
- * Canonical-JSON serializer + sha256 → hex. Stable across runs because
77
- * keys are sorted. The output is used for `pages.content_hash` so that
78
- * a Mode-2 translation can detect whether its source has changed.
79
- */
80
- export declare function computeContentHash(value: unknown): Promise<string>;
81
- export interface LocaleLintWarning {
82
- code: string;
83
- message: string;
84
- }
85
- /**
86
- * Cross-row config sanity checks. Run at:
87
- * - propose-time (warnings stored on the proposal preview)
88
- * - render-time (no fail-loudly per CLAUDE.md §2 since the renderer
89
- * can still emit; surfaced in admin UI as banners)
90
- */
91
- export declare function lintLocaleConfig(locales: ReadonlyArray<LocaleConfig>, advancedUrlRouting: boolean): LocaleLintWarning[];
92
- //# sourceMappingURL=i18n.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AA6BA;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC9D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGhD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAET;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EAMnB,YAAY,GAAE,WAAW,GAAG,cAA4B,EACxD,UAAU,CAAC,EAAE,OAAO,GACnB,MAAM,CAyCR;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,aAAa,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,GACpF,MAAM,CAaR;AAUD;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAWxE;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,EACpC,kBAAkB,EAAE,OAAO,GAC1B,iBAAiB,EAAE,CAoCrB"}
package/dist/i18n.js DELETED
@@ -1,226 +0,0 @@
1
- // SPDX-License-Identifier: MPL-2.0
2
- /**
3
- * P9 — i18n primitives shared between the static generator, the
4
- * preview op, and the admin UI:
5
- *
6
- * computeContentHash(page, modules) — sha256 of canonical-JSON
7
- * content. Drives `pages.content_hash` + the translation_status
8
- * recompute path.
9
- *
10
- * resolveLocaleUrl(locale, slug, siteBaseUrl, pageUrlStyle?, isHomePage?) —
11
- * builds the public URL for a (locale, slug) tuple given the
12
- * locale's url_strategy + url_host. `isHomePage` forces the locale
13
- * root (0184 explicit designation). Used by:
14
- * - hreflang emitter
15
- * - sitemap.xml emitter (when extended for i18n)
16
- * - language-selector module
17
- *
18
- * buildHreflangLinks(currentLocale, perLocaleUrls, defaultLocaleCode) —
19
- * emits the `<link rel="alternate" hreflang=...>` markup.
20
- *
21
- * lintLocaleConfig(locales, advancedUrlRouting) — surfaces config
22
- * warnings (mixed strategies, missing url_host for subdomain/
23
- * domain, default locale using `none` alongside subdirectory
24
- * siblings, advanced strategy chosen while toggle is off).
25
- */
26
- const TEXT_ENCODER = new TextEncoder();
27
- /**
28
- * Strip leading and trailing `/` characters with a single linear scan.
29
- *
30
- * Replaces the regex `/^\/+|\/+$/g`, whose trailing-slash branch
31
- * backtracks O(n²) on a long run of slashes that is not at end-of-string
32
- * (CodeQL js/polynomial-redos). This char-index walk is unconditionally
33
- * linear and produces byte-identical output for every input.
34
- */
35
- export function trimSlashes(s) {
36
- let start = 0;
37
- let end = s.length;
38
- while (start < end && s.charCodeAt(start) === 47 /* '/' */)
39
- start += 1;
40
- while (end > start && s.charCodeAt(end - 1) === 47 /* '/' */)
41
- end -= 1;
42
- return s.slice(start, end);
43
- }
44
- /**
45
- * Strip only trailing `/` characters with a single linear scan — the
46
- * non-backtracking replacement for `/\/+$/` (same ReDoS class as above).
47
- * Used for base URLs, which carry a scheme and must keep their leading
48
- * characters.
49
- */
50
- export function trimTrailingSlashes(s) {
51
- let end = s.length;
52
- while (end > 0 && s.charCodeAt(end - 1) === 47 /* '/' */)
53
- end -= 1;
54
- return s.slice(0, end);
55
- }
56
- /**
57
- * The "magic slug" sentinel test: a page whose slug is empty, `home`,
58
- * or `index` is the locale root by convention even without an explicit
59
- * `locales.home_page_id` designation. Leading/trailing slashes are
60
- * ignored so `/home/` reads the same as `home`.
61
- */
62
- export function isHomeSlug(slug) {
63
- const s = trimSlashes(slug);
64
- return s === "" || s === "home" || s === "index";
65
- }
66
- /**
67
- * The single home-decision predicate every URL/output-path site must
68
- * use so canonical, hreflang, redirects, and the emitted file agree
69
- * (0184 explicit-homepage feature). A page is the locale root when it
70
- * IS the locale's designated `home_page_id` OR carries a magic slug.
71
- *
72
- * @param pageId The page being resolved.
73
- * @param slug That page's slug.
74
- * @param localeHomePageId `locales.home_page_id` for the page's locale
75
- * (null/undefined when no page is designated).
76
- */
77
- export function pageIsLocaleHome(pageId, slug, localeHomePageId) {
78
- return (localeHomePageId != null && pageId === localeHomePageId) || isHomeSlug(slug);
79
- }
80
- /**
81
- * Build a public-facing URL for a (locale, slug) tuple. Pure function —
82
- * no DB access — so the static generator can call it for every page
83
- * without round-trips.
84
- *
85
- * @param locale The target locale's full config row.
86
- * @param slug Path component (e.g. "about", "blog/post-1"). No leading slash.
87
- * @param siteBaseUrl Default base URL when the strategy is `none` or
88
- * `subdirectory` (e.g. "https://example.com").
89
- * @param pageUrlStyle Page emission style (see below).
90
- * @param isHomePage Explicit homepage designation (0184 —
91
- * `locales.home_page_id`). When true this page IS the
92
- * locale root and resolves to `<base>/` regardless of
93
- * its own slug. The explicit flag WINS over the slug
94
- * sentinel below; the sentinel stays as a back-compat
95
- * fallback for callers that can't cheaply surface the
96
- * designation.
97
- * @returns Absolute URL, including scheme + host.
98
- */
99
- export function resolveLocaleUrl(locale, slug, siteBaseUrl,
100
- // v0.2.85 — page emission style. 'directory' (default) builds
101
- // URLs ending in `/<slug>/`; 'no-extension' builds URLs ending
102
- // in `/<slug>` (no trailing slash) to match what the bucket
103
- // actually serves when pages are emitted as bare slugs. Home
104
- // page is always `<base>/` regardless of style.
105
- pageUrlStyle = "directory", isHomePage) {
106
- const stripped = trimSlashes(slug);
107
- // 0184 — the explicit designation wins; the slug sentinel
108
- // (""/`home`/`index`) survives as a back-compat fallback so a page the
109
- // AI never ran set_home_page on still resolves to the root. Shared
110
- // `isHomeSlug` keeps this test identical across every home-decision site.
111
- const isHome = isHomePage === true || isHomeSlug(stripped);
112
- // tail: the path component appended after `<base>/` or `<base>/<locale>/`.
113
- // 'directory' style: trailing slash for non-home so the URL points at
114
- // the directory the bucket serves index.html from.
115
- // 'no-extension' style: no trailing slash, no extension — the URL
116
- // points at the bare-slug object the bucket serves directly.
117
- const tail = isHome ? "" : pageUrlStyle === "no-extension" ? stripped : `${stripped}/`;
118
- const base = trimTrailingSlashes(siteBaseUrl);
119
- switch (locale.urlStrategy) {
120
- case "none":
121
- return tail ? `${base}/${tail}` : `${base}/`;
122
- case "subdirectory":
123
- // Default locale with strategy `subdirectory` still gets the prefix
124
- // unless the migration set strategy=none for it. The decision is
125
- // explicit per locale row, not implicit on isDefault.
126
- return tail ? `${base}/${locale.code}/${tail}` : `${base}/${locale.code}/`;
127
- case "subdomain": {
128
- if (!locale.urlHost) {
129
- throw new Error(`locale '${locale.code}' uses url_strategy='subdomain' without url_host — config invalid`);
130
- }
131
- const protocol = base.startsWith("http://") ? "http://" : "https://";
132
- return tail ? `${protocol}${locale.urlHost}/${tail}` : `${protocol}${locale.urlHost}/`;
133
- }
134
- case "domain": {
135
- if (!locale.urlHost) {
136
- throw new Error(`locale '${locale.code}' uses url_strategy='domain' without url_host — config invalid`);
137
- }
138
- const protocol = base.startsWith("http://") ? "http://" : "https://";
139
- return tail ? `${protocol}${locale.urlHost}/${tail}` : `${protocol}${locale.urlHost}/`;
140
- }
141
- }
142
- }
143
- /**
144
- * Emit `<link rel="alternate" hreflang="…">` tags for every locale
145
- * that has a published variant of this page. The default locale also
146
- * gets an `x-default` entry per Google's i18n guidance.
147
- *
148
- * Returned as a single string suitable for splicing into <head>.
149
- */
150
- export function buildHreflangLinks(perLocaleUrls) {
151
- if (perLocaleUrls.length === 0)
152
- return "";
153
- const lines = [];
154
- for (const v of perLocaleUrls) {
155
- lines.push(`<link rel="alternate" hreflang="${escapeAttr(v.localeCode)}" href="${escapeAttr(v.url)}" />`);
156
- }
157
- const def = perLocaleUrls.find((v) => v.isDefault);
158
- if (def) {
159
- lines.push(`<link rel="alternate" hreflang="x-default" href="${escapeAttr(def.url)}" />`);
160
- }
161
- return lines.join("\n");
162
- }
163
- function escapeAttr(s) {
164
- return s
165
- .replace(/&/g, "&amp;")
166
- .replace(/"/g, "&quot;")
167
- .replace(/</g, "&lt;")
168
- .replace(/>/g, "&gt;");
169
- }
170
- /**
171
- * Canonical-JSON serializer + sha256 → hex. Stable across runs because
172
- * keys are sorted. The output is used for `pages.content_hash` so that
173
- * a Mode-2 translation can detect whether its source has changed.
174
- */
175
- export async function computeContentHash(value) {
176
- const canonical = JSON.stringify(value, (_key, val) => {
177
- if (val && typeof val === "object" && !Array.isArray(val)) {
178
- const sorted = {};
179
- for (const k of Object.keys(val).sort())
180
- sorted[k] = val[k];
181
- return sorted;
182
- }
183
- return val;
184
- });
185
- const digest = await crypto.subtle.digest("SHA-256", TEXT_ENCODER.encode(canonical));
186
- return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
187
- }
188
- /**
189
- * Cross-row config sanity checks. Run at:
190
- * - propose-time (warnings stored on the proposal preview)
191
- * - render-time (no fail-loudly per CLAUDE.md §2 since the renderer
192
- * can still emit; surfaced in admin UI as banners)
193
- */
194
- export function lintLocaleConfig(locales, advancedUrlRouting) {
195
- const warnings = [];
196
- const usingAdvanced = locales.some((l) => l.urlStrategy === "subdomain" || l.urlStrategy === "domain");
197
- if (usingAdvanced && !advancedUrlRouting) {
198
- warnings.push({
199
- code: "advanced-routing-disabled",
200
- message: "one or more locales use 'subdomain' or 'domain' strategy but Advanced URL Routing is disabled — enable it under /security/locales",
201
- });
202
- }
203
- for (const l of locales) {
204
- if ((l.urlStrategy === "subdomain" || l.urlStrategy === "domain") && !l.urlHost) {
205
- warnings.push({
206
- code: "missing-url-host",
207
- message: `locale '${l.code}' uses url_strategy='${l.urlStrategy}' without url_host`,
208
- });
209
- }
210
- }
211
- // Default-locale 'none' alongside subdirectory siblings is a common
212
- // mixed config; surface it so users know the default's URL stays bare
213
- // while siblings get prefixed.
214
- const def = locales.find((l) => l.isDefault);
215
- const subdirSiblings = locales.filter((l) => !l.isDefault && l.urlStrategy === "subdirectory");
216
- if (def && def.urlStrategy === "none" && subdirSiblings.length > 0) {
217
- warnings.push({
218
- code: "mixed-default-none-subdir",
219
- message: `default locale '${def.code}' uses 'none' while ${subdirSiblings
220
- .map((l) => l.code)
221
- .join(", ")} use 'subdirectory' — this is valid but unusual; verify hreflang renders correctly`,
222
- });
223
- }
224
- return warnings;
225
- }
226
- //# sourceMappingURL=i18n.js.map
package/dist/i18n.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"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"}