@gradial/aci 0.1.20-preview.3 → 0.1.21

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 (227) hide show
  1. package/README.md +48 -108
  2. package/bin/{aci → aci-darwin-arm64} +0 -0
  3. package/bin/aci.js +99 -6
  4. package/dist/assets/index.d.ts +3 -3
  5. package/dist/assets/index.js +3 -3
  6. package/dist/astro/index.d.ts +12 -3
  7. package/dist/astro/index.js +20 -5
  8. package/dist/content/assets.d.ts +17 -0
  9. package/dist/content/assets.js +65 -0
  10. package/dist/content/index.d.ts +1 -0
  11. package/dist/content/index.js +1 -0
  12. package/dist/define-component.d.ts +1 -2
  13. package/dist/define-component.js +73 -5
  14. package/dist/dev/content-watch.d.ts +37 -0
  15. package/dist/dev/content-watch.js +154 -0
  16. package/dist/dev/index.d.ts +24 -43
  17. package/dist/dev/index.js +4 -169
  18. package/dist/index.d.ts +14 -6
  19. package/dist/index.js +8 -9
  20. package/dist/next/asset-route.js +2 -2
  21. package/dist/next/config.d.ts +2 -2
  22. package/dist/next/config.js +5 -5
  23. package/dist/next/content-watch.js +6 -1
  24. package/dist/next/index.d.ts +2 -2
  25. package/dist/next/index.js +2 -2
  26. package/dist/next/middleware.d.ts +1 -0
  27. package/dist/next/middleware.js +49 -8
  28. package/dist/next/page.d.ts +1 -1
  29. package/dist/next/page.js +14 -12
  30. package/dist/next/render.d.ts +3 -3
  31. package/dist/next/render.js +11 -9
  32. package/dist/next/server.d.ts +12 -12
  33. package/dist/next/server.js +1 -1
  34. package/dist/preview/core.d.ts +5 -0
  35. package/dist/preview/core.js +1 -1
  36. package/dist/react/Media.d.ts +24 -0
  37. package/dist/react/Media.js +30 -0
  38. package/dist/react/Picture.d.ts +12 -0
  39. package/dist/react/Picture.js +11 -0
  40. package/dist/react/VideoPlayer.d.ts +13 -0
  41. package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
  42. package/dist/react/index.d.ts +333 -3
  43. package/dist/react/index.js +89 -3
  44. package/dist/registry.d.ts +2 -2
  45. package/dist/registry.js +3 -3
  46. package/dist/types/block-ref.d.ts +26 -0
  47. package/dist/types/block-ref.js +28 -0
  48. package/dist/types/component.d.ts +36 -32
  49. package/dist/types/config.d.ts +1 -1
  50. package/dist/types/image.d.ts +33 -20
  51. package/dist/types/image.js +42 -50
  52. package/dist/types/index.d.ts +1 -0
  53. package/dist/types/index.js +1 -0
  54. package/dist/types/link.d.ts +38 -0
  55. package/dist/types/link.js +58 -0
  56. package/dist/types/media.d.ts +16 -35
  57. package/dist/types/media.js +15 -84
  58. package/dist/types/renderer.d.ts +1 -1
  59. package/dist/types/rich-text.d.ts +40 -0
  60. package/dist/types/rich-text.js +39 -0
  61. package/dist/types/video.d.ts +7 -13
  62. package/dist/types/video.js +3 -3
  63. package/package.json +29 -76
  64. package/src/cli/compile-registry.mjs +120 -63
  65. package/src/cli/validate-content.mjs +38 -75
  66. package/src/types/block-ref.ts +74 -0
  67. package/src/types/image.ts +79 -60
  68. package/templates/astro/template/.aci.yaml +28 -0
  69. package/templates/astro/template/.storybook/main.ts +79 -0
  70. package/templates/astro/template/.storybook/manager.ts +6 -0
  71. package/templates/astro/template/.storybook/preview.ts +33 -0
  72. package/templates/astro/template/astro.config.mjs +37 -0
  73. package/templates/astro/template/package.json.tmpl +41 -0
  74. package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
  75. package/templates/astro/template/src/cms/registry.ts +28 -0
  76. package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
  77. package/templates/astro/template/src/components/chrome/Header.astro +94 -0
  78. package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
  79. package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
  80. package/templates/astro/template/src/components/elements/Button.astro +51 -0
  81. package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
  82. package/templates/astro/template/src/components/elements/Container.astro +11 -0
  83. package/templates/astro/template/src/components/elements/Icon.astro +31 -0
  84. package/templates/astro/template/src/components/elements/Logo.astro +29 -0
  85. package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
  86. package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
  87. package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
  88. package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
  89. package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
  90. package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
  91. package/templates/astro/template/src/design-system/styles.css +399 -0
  92. package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
  93. package/templates/astro/template/src/design-system/tokens/components.css +69 -0
  94. package/templates/astro/template/src/design-system/tokens/index.css +6 -0
  95. package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
  96. package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
  97. package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
  98. package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
  99. package/templates/astro/template/src/env.d.ts +1 -0
  100. package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
  101. package/templates/astro/template/src/fixtures/composition.ts +31 -0
  102. package/templates/astro/template/src/fixtures/index.ts +17 -0
  103. package/templates/astro/template/src/fixtures/sections.ts +39 -0
  104. package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
  105. package/templates/astro/template/src/pages/[...slug].astro +61 -0
  106. package/templates/astro/template/src/render/RenderPage.astro +66 -0
  107. package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
  108. package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
  109. package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
  110. package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
  111. package/templates/astro/template/tsconfig.json +11 -0
  112. package/templates/common/.agents/AGENTS.md +37 -0
  113. package/templates/common/.agents/skills/aci/SKILL.md +162 -0
  114. package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
  115. package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
  116. package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
  117. package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
  118. package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
  119. package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
  120. package/templates/common/.agents/skills/migration/SKILL.md +160 -0
  121. package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
  122. package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
  123. package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
  124. package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
  125. package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
  126. package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
  127. package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
  128. package/templates/common/.content/config/site.json +192 -0
  129. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
  130. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
  131. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
  132. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
  133. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
  134. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
  135. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
  136. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
  137. package/templates/common/.content/fragments/navbar/_index.json +25 -0
  138. package/templates/common/.content/fragments/site-footer/_index.json +62 -0
  139. package/templates/common/.content/pages/about/_index.json +51 -0
  140. package/templates/common/.content/pages/home/_index.json +112 -0
  141. package/templates/common/.content/schemas/site.schema.json +123 -0
  142. package/templates/common/README.md.tmpl +45 -0
  143. package/templates/common/contracts/components/button.contract.ts +19 -0
  144. package/templates/common/contracts/components/container.contract.ts +19 -0
  145. package/templates/common/contracts/components/featureCard.contract.ts +15 -0
  146. package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
  147. package/templates/common/contracts/components/homeHero.contract.ts +36 -0
  148. package/templates/common/contracts/components/index.ts +21 -0
  149. package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
  150. package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
  151. package/templates/common/contracts/components/statsBar.contract.ts +19 -0
  152. package/templates/common/design-system/styles.css +346 -0
  153. package/templates/common/design-system/tokens/colors.css +110 -0
  154. package/templates/common/design-system/tokens/components.css +86 -0
  155. package/templates/common/design-system/tokens/index.css +6 -0
  156. package/templates/common/design-system/tokens/radii.css +5 -0
  157. package/templates/common/design-system/tokens/shadows.css +9 -0
  158. package/templates/common/design-system/tokens/spacing.css +26 -0
  159. package/templates/common/design-system/tokens/typography.css +32 -0
  160. package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
  161. package/templates/common/public/assets/Dwire-model.png +0 -0
  162. package/templates/common/public/assets/bare-metal-logo.png +0 -0
  163. package/templates/common/public/assets/meridian-logo.svg +8 -0
  164. package/templates/common/public/assets/seattle.avif +0 -0
  165. package/templates/nextjs/template/.aci.yaml +26 -0
  166. package/templates/nextjs/template/.storybook/main.ts +13 -0
  167. package/templates/nextjs/template/.storybook/preview.ts +34 -0
  168. package/templates/nextjs/template/eslint.config.mjs +36 -0
  169. package/templates/nextjs/template/next-env.d.ts +6 -0
  170. package/templates/nextjs/template/next.config.ts +8 -0
  171. package/templates/nextjs/template/package.json.tmpl +46 -0
  172. package/templates/nextjs/template/postcss.config.mjs +7 -0
  173. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
  174. package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
  175. package/templates/nextjs/template/src/app/layout.tsx +29 -0
  176. package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
  177. package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
  178. package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
  179. package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
  180. package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
  181. package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
  182. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
  183. package/templates/nextjs/template/src/cms/registry.ts +28 -0
  184. package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
  185. package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
  186. package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
  187. package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
  188. package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
  189. package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
  190. package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
  191. package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
  192. package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
  193. package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
  194. package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
  195. package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
  196. package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
  197. package/templates/nextjs/template/src/middleware.ts +4 -0
  198. package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
  199. package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
  200. package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
  201. package/templates/nextjs/template/tsconfig.json +23 -0
  202. package/templates/nextjs/template/vercel.json +6 -0
  203. package/dist/content/contract.d.ts +0 -83
  204. package/dist/content/contract.js +0 -104
  205. package/dist/content/tailwind-validator.d.ts +0 -6
  206. package/dist/content/tailwind-validator.js +0 -31
  207. package/dist/content/validation.d.ts +0 -108
  208. package/dist/content/validation.js +0 -183
  209. package/dist/react/GradialMedia.d.ts +0 -24
  210. package/dist/react/GradialMedia.js +0 -31
  211. package/dist/react/GradialPicture.d.ts +0 -14
  212. package/dist/react/GradialPicture.js +0 -30
  213. package/dist/react/GradialVideoPlayer.d.ts +0 -13
  214. package/dist/sveltekit/index.d.ts +0 -25
  215. package/dist/sveltekit/index.js +0 -66
  216. package/dist/sveltekit/preview.d.ts +0 -5
  217. package/dist/sveltekit/preview.js +0 -33
  218. package/src/types/component.ts +0 -49
  219. package/src/types/config.ts +0 -37
  220. package/src/types/data.ts +0 -47
  221. package/src/types/index.ts +0 -10
  222. package/src/types/layout.ts +0 -29
  223. package/src/types/media.ts +0 -125
  224. package/src/types/page.ts +0 -47
  225. package/src/types/render-mode.ts +0 -10
  226. package/src/types/renderer.ts +0 -83
  227. package/src/types/video.ts +0 -66
@@ -1,23 +1,25 @@
1
1
  import { z } from 'zod';
2
2
  export interface ImageSource {
3
+ /** Derivative URL. */
3
4
  src: string;
5
+ /** Intrinsic width in pixels. */
4
6
  width: number;
7
+ /** Intrinsic height in pixels. */
5
8
  height: number;
9
+ /** MIME type hint, e.g. image/webp. */
6
10
  type: string;
7
11
  }
8
- export interface PictureSource {
9
- media?: string;
10
- type: string;
11
- srcset: string;
12
- sizes?: string;
13
- }
14
- export interface GradialImage {
12
+ export interface Image {
13
+ /** Discriminator — always 'gradial.image'. */
15
14
  $type: 'gradial.image';
15
+ /** DAM asset identifier. */
16
16
  assetId: string;
17
+ /** DAM version identifier. */
17
18
  versionId: string;
19
+ /** Accessible description of the image content. */
18
20
  alt: string;
19
- fallback: ImageSource;
20
- sources: PictureSource[] | null;
21
+ /** Responsive derivative variants produced for the asset slot. */
22
+ sources: ImageSource[];
21
23
  }
22
24
  export interface ImageSlotContract {
23
25
  outputs: SlotOutput[];
@@ -29,23 +31,34 @@ export interface SlotOutput {
29
31
  widths: number[];
30
32
  media?: string;
31
33
  }
32
- export declare const GradialImageSchema: z.ZodObject<{
34
+ export declare const ImageSourceSchema: z.ZodObject<{
35
+ src: z.ZodString;
36
+ width: z.ZodNumber;
37
+ height: z.ZodNumber;
38
+ type: z.ZodString;
39
+ }, z.core.$strip>;
40
+ export declare const ImageSchema: z.ZodObject<{
33
41
  $type: z.ZodLiteral<"gradial.image">;
34
42
  assetId: z.ZodString;
35
43
  versionId: z.ZodString;
36
44
  alt: z.ZodString;
37
- fallback: z.ZodObject<{
45
+ sources: z.ZodArray<z.ZodObject<{
38
46
  src: z.ZodString;
39
47
  width: z.ZodNumber;
40
48
  height: z.ZodNumber;
41
49
  type: z.ZodString;
42
- }, z.core.$strip>;
43
- sources: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodObject<{
44
- media: z.ZodOptional<z.ZodString>;
45
- type: z.ZodString;
46
- srcset: z.ZodString;
47
- sizes: z.ZodOptional<z.ZodString>;
48
- }, z.core.$strip>>>>;
50
+ }, z.core.$strip>>;
49
51
  }, z.core.$strip>;
50
- export type ImageHTMLAttributes = Record<string, string | number | boolean | undefined | null>;
51
- export declare function renderImageHTML(image: GradialImage, attrs?: ImageHTMLAttributes): string;
52
+ export type ImageAttrs = Record<string, unknown>;
53
+ /**
54
+ * Picks the primary variant from an image's sources.
55
+ * Uses the largest width; ties fall back to the first entry.
56
+ */
57
+ export declare function primaryImageSource(image: Image): ImageSource;
58
+ /**
59
+ * Computes the full set of <img> attributes for an Image.
60
+ *
61
+ * Framework components (React <Picture>, Astro <img>, Svelte <img>) call this
62
+ * and spread the result into their native element. No HTML string serialization.
63
+ */
64
+ export declare function imageAttrs(image: Image, overrides?: ImageAttrs): ImageAttrs;
@@ -1,58 +1,50 @@
1
1
  import { z } from 'zod';
2
- export const GradialImageSchema = z.object({
2
+ // ---------------------------------------------------------------------------
3
+ // Zod schema
4
+ // ---------------------------------------------------------------------------
5
+ export const ImageSourceSchema = z.object({
6
+ src: z.string().min(1),
7
+ width: z.number().int().nonnegative(),
8
+ height: z.number().int().nonnegative(),
9
+ type: z.string().min(1),
10
+ });
11
+ export const ImageSchema = z.object({
3
12
  $type: z.literal('gradial.image'),
4
13
  assetId: z.string().min(1),
5
14
  versionId: z.string().min(1),
6
15
  alt: z.string(),
7
- fallback: z.object({
8
- src: z.string().min(1),
9
- width: z.number().int().nonnegative(),
10
- height: z.number().int().nonnegative(),
11
- type: z.string().min(1),
12
- }),
13
- sources: z.array(z.object({
14
- media: z.string().optional(),
15
- type: z.string().min(1),
16
- srcset: z.string().min(1),
17
- sizes: z.string().optional(),
18
- })).nullable().default([]),
16
+ sources: z.array(ImageSourceSchema).min(1),
19
17
  });
20
- export function renderImageHTML(image, attrs = {}) {
21
- const imgAttrs = renderAttrs({
22
- ...attrs,
23
- src: image.fallback.src,
24
- alt: image.alt,
25
- width: image.fallback.width > 0 ? image.fallback.width : undefined,
26
- height: image.fallback.height > 0 ? image.fallback.height : undefined,
27
- });
28
- const img = `<img${imgAttrs}>`;
29
- if (!image.sources?.length) {
30
- return img;
31
- }
32
- const sources = image.sources.map((source) => `<source${renderAttrs({
33
- media: source.media,
34
- type: source.type,
35
- srcset: source.srcset,
36
- sizes: source.sizes,
37
- })}>`).join('');
38
- return `<picture>${sources}${img}</picture>`;
39
- }
40
- function renderAttrs(attrs) {
41
- const rendered = Object.entries(attrs)
42
- .filter(([, value]) => value !== undefined && value !== null && value !== false)
43
- .map(([name, value]) => value === true ? escapeName(name) : `${escapeName(name)}="${escapeAttr(String(value))}"`);
44
- if (!rendered.length) {
45
- return '';
46
- }
47
- return ' ' + rendered.join(' ');
18
+ /**
19
+ * Picks the primary variant from an image's sources.
20
+ * Uses the largest width; ties fall back to the first entry.
21
+ */
22
+ export function primaryImageSource(image) {
23
+ return image.sources.reduce((largest, source) => source.width > largest.width ? source : largest, image.sources[0]);
48
24
  }
49
- function escapeName(name) {
50
- return name.replace(/[^A-Za-z0-9_:-]/g, '');
51
- }
52
- function escapeAttr(value) {
53
- return value
54
- .replace(/&/g, '&amp;')
55
- .replace(/"/g, '&quot;')
56
- .replace(/</g, '&lt;')
57
- .replace(/>/g, '&gt;');
25
+ /**
26
+ * Computes the full set of <img> attributes for an Image.
27
+ *
28
+ * Framework components (React <Picture>, Astro <img>, Svelte <img>) call this
29
+ * and spread the result into their native element. No HTML string serialization.
30
+ */
31
+ export function imageAttrs(image, overrides = {}) {
32
+ const primary = primaryImageSource(image);
33
+ const srcset = image.sources
34
+ .map((s) => `${s.src} ${s.width}w`)
35
+ .join(', ');
36
+ const sizes = image.sources
37
+ .map((s) => `(max-width: ${s.width}px) ${s.width}px`)
38
+ .join(', ');
39
+ return {
40
+ src: primary.src,
41
+ alt: image.alt,
42
+ width: primary.width > 0 ? primary.width : undefined,
43
+ height: primary.height > 0 ? primary.height : undefined,
44
+ srcSet: srcset || undefined,
45
+ sizes: sizes || undefined,
46
+ loading: 'lazy',
47
+ decoding: 'async',
48
+ ...overrides,
49
+ };
58
50
  }
@@ -3,6 +3,7 @@ export * from './component.js';
3
3
  export * from './data.js';
4
4
  export * from './layout.js';
5
5
  export * from './page.js';
6
+ export * from './rich-text.js';
6
7
  export * from './renderer.js';
7
8
  export * from './render-mode.js';
8
9
  export * from './image.js';
@@ -3,6 +3,7 @@ export * from './component.js';
3
3
  export * from './data.js';
4
4
  export * from './layout.js';
5
5
  export * from './page.js';
6
+ export * from './rich-text.js';
6
7
  export * from './renderer.js';
7
8
  export * from './render-mode.js';
8
9
  export * from './image.js';
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ export type LinkTarget = '_self' | '_blank' | '_parent' | '_top';
3
+ export interface Link {
4
+ href: string;
5
+ target?: LinkTarget;
6
+ title?: string;
7
+ rel?: string;
8
+ }
9
+ export declare const LinkSchema: z.ZodObject<{
10
+ href: z.ZodString;
11
+ target: z.ZodOptional<z.ZodEnum<{
12
+ _self: "_self";
13
+ _blank: "_blank";
14
+ _parent: "_parent";
15
+ _top: "_top";
16
+ }>>;
17
+ title: z.ZodOptional<z.ZodString>;
18
+ rel: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strip>;
20
+ export interface LinkResolverContext {
21
+ /** Resolved path for an aci:page:{slug} reference, if found. */
22
+ resolvePageSlug?: (slug: string) => string | undefined;
23
+ }
24
+ export declare function resolveLink(reference: string | Link, ctx?: LinkResolverContext): Link;
25
+ /**
26
+ * Resolve a Link object to its final href string.
27
+ * An optional resolver can perform async or domain-specific resolution.
28
+ */
29
+ export declare function resolveHref(link: Link, resolver?: (link: Link) => string | Promise<string>): string | Promise<string>;
30
+ /**
31
+ * Throw if the href uses an unsafe protocol (javascript:, data:, vbscript:).
32
+ */
33
+ export declare function assertSafeHref(href: string): void;
34
+ /**
35
+ * Normalize the rel attribute for a Link.
36
+ * Adds noopener noreferrer for target="_blank" automatically.
37
+ */
38
+ export declare function normalizeLinkRel(link: Link): string | undefined;
@@ -0,0 +1,58 @@
1
+ import { z } from 'zod';
2
+ // ---------------------------------------------------------------------------
3
+ // Zod schema
4
+ // ---------------------------------------------------------------------------
5
+ export const LinkSchema = z.object({
6
+ href: z.string().min(1),
7
+ target: z.enum(['_self', '_blank', '_parent', '_top']).optional(),
8
+ title: z.string().optional(),
9
+ rel: z.string().optional(),
10
+ });
11
+ export function resolveLink(reference, ctx = {}) {
12
+ if (typeof reference !== 'string')
13
+ return reference;
14
+ if (reference.startsWith('aci:external:')) {
15
+ return { href: reference.slice('aci:external:'.length), target: '_blank' };
16
+ }
17
+ if (reference.startsWith('aci:page:')) {
18
+ const slug = reference.slice('aci:page:'.length);
19
+ const path = ctx.resolvePageSlug?.(slug);
20
+ return { href: path ?? `/${slug}` };
21
+ }
22
+ return { href: reference };
23
+ }
24
+ /**
25
+ * Resolve a Link object to its final href string.
26
+ * An optional resolver can perform async or domain-specific resolution.
27
+ */
28
+ export function resolveHref(link, resolver) {
29
+ if (resolver) {
30
+ return resolver(link);
31
+ }
32
+ return link.href;
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // Shared helpers — consumed by React, Astro, and Svelte components
36
+ // ---------------------------------------------------------------------------
37
+ /**
38
+ * Throw if the href uses an unsafe protocol (javascript:, data:, vbscript:).
39
+ */
40
+ export function assertSafeHref(href) {
41
+ const protocol = href.split(':')[0].toLowerCase();
42
+ if (protocol === 'javascript' || protocol === 'data' || protocol === 'vbscript') {
43
+ throw new Error(`unsafe Link protocol: ${protocol}`);
44
+ }
45
+ }
46
+ /**
47
+ * Normalize the rel attribute for a Link.
48
+ * Adds noopener noreferrer for target="_blank" automatically.
49
+ */
50
+ export function normalizeLinkRel(link) {
51
+ if (link.target !== '_blank') {
52
+ return link.rel;
53
+ }
54
+ const rel = new Set((link.rel ?? '').split(/\s+/).filter(Boolean));
55
+ rel.add('noopener');
56
+ rel.add('noreferrer');
57
+ return [...rel].join(' ');
58
+ }
@@ -1,25 +1,20 @@
1
1
  import { z } from 'zod';
2
- import { type GradialImage } from './image.js';
3
- import { type GradialVideo } from './video.js';
2
+ import { type Image } from './image.js';
3
+ import { type Video } from './video.js';
4
4
  /** Discriminated union of all compiler-resolved asset types. */
5
- export type GradialAsset = GradialImage | GradialVideo;
6
- export declare const GradialAssetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
5
+ export type Asset = Image | Video;
6
+ /** Zod schema for a resolved asset value. */
7
+ export declare const AssetSchema: z.ZodUnion<readonly [z.ZodObject<{
7
8
  $type: z.ZodLiteral<"gradial.image">;
8
9
  assetId: z.ZodString;
9
10
  versionId: z.ZodString;
10
11
  alt: z.ZodString;
11
- fallback: z.ZodObject<{
12
+ sources: z.ZodArray<z.ZodObject<{
12
13
  src: z.ZodString;
13
14
  width: z.ZodNumber;
14
15
  height: z.ZodNumber;
15
16
  type: z.ZodString;
16
- }, z.core.$strip>;
17
- sources: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodObject<{
18
- media: z.ZodOptional<z.ZodString>;
19
- type: z.ZodString;
20
- srcset: z.ZodString;
21
- sizes: z.ZodOptional<z.ZodString>;
22
- }, z.core.$strip>>>>;
17
+ }, z.core.$strip>>;
23
18
  }, z.core.$strip>, z.ZodObject<{
24
19
  $type: z.ZodLiteral<"gradial.video">;
25
20
  assetId: z.ZodString;
@@ -34,36 +29,22 @@ export declare const GradialAssetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
34
29
  assetId: z.ZodString;
35
30
  versionId: z.ZodString;
36
31
  alt: z.ZodString;
37
- fallback: z.ZodObject<{
32
+ sources: z.ZodArray<z.ZodObject<{
38
33
  src: z.ZodString;
39
34
  width: z.ZodNumber;
40
35
  height: z.ZodNumber;
41
36
  type: z.ZodString;
42
- }, z.core.$strip>;
43
- sources: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodObject<{
44
- media: z.ZodOptional<z.ZodString>;
45
- type: z.ZodString;
46
- srcset: z.ZodString;
47
- sizes: z.ZodOptional<z.ZodString>;
48
- }, z.core.$strip>>>>;
37
+ }, z.core.$strip>>;
49
38
  }, z.core.$strip>>;
50
39
  sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
51
40
  src: z.ZodString;
52
41
  type: z.ZodString;
53
42
  }, z.core.$strip>>>;
54
43
  duration: z.ZodOptional<z.ZodNumber>;
55
- }, z.core.$strip>], "$type">;
56
- export declare function isGradialImage(value: unknown): value is GradialImage;
57
- export declare function isGradialVideo(value: unknown): value is GradialVideo;
58
- export declare function isGradialAsset(value: unknown): value is GradialAsset;
59
- /**
60
- * Renders a GradialVideo to an HTML string.
61
- * Uses poster.fallback.src for the poster attribute.
62
- * Includes <source> elements for format variants.
63
- */
64
- export declare function renderVideoHTML(video: GradialVideo, attrs?: Record<string, string | number | boolean | undefined | null>): string;
65
- /**
66
- * Renders any GradialAsset to an HTML string.
67
- * Delegates to renderImageHTML or renderVideoHTML based on $type.
68
- */
69
- export declare function renderAssetHTML(asset: GradialAsset, attrs?: Record<string, string | number | boolean | undefined | null>): string;
44
+ }, z.core.$strip>]>;
45
+ /** Runtime guard: value is a resolved asset. */
46
+ export declare function isAsset(value: unknown): value is Asset;
47
+ /** Runtime guard: value is a resolved image asset. */
48
+ export declare function isImage(value: unknown): value is Image;
49
+ /** Runtime guard: value is a resolved video asset. */
50
+ export declare function isVideo(value: unknown): value is Video;
@@ -1,86 +1,17 @@
1
1
  import { z } from 'zod';
2
- import { GradialImageSchema, renderImageHTML } from './image.js';
3
- import { GradialVideoSchema } from './video.js';
4
- // ---------------------------------------------------------------------------
5
- // Zod schema discriminated on $type
6
- // ---------------------------------------------------------------------------
7
- export const GradialAssetSchema = z.discriminatedUnion('$type', [
8
- GradialImageSchema,
9
- GradialVideoSchema,
10
- ]);
11
- // ---------------------------------------------------------------------------
12
- // Type guards
13
- // ---------------------------------------------------------------------------
14
- export function isGradialImage(value) {
15
- return (typeof value === 'object' &&
16
- value !== null &&
17
- value.$type === 'gradial.image');
18
- }
19
- export function isGradialVideo(value) {
20
- return (typeof value === 'object' &&
21
- value !== null &&
22
- value.$type === 'gradial.video');
23
- }
24
- export function isGradialAsset(value) {
25
- return isGradialImage(value) || isGradialVideo(value);
26
- }
27
- // ---------------------------------------------------------------------------
28
- // HTML string renderers (framework-agnostic)
29
- // ---------------------------------------------------------------------------
30
- /**
31
- * Renders a GradialVideo to an HTML string.
32
- * Uses poster.fallback.src for the poster attribute.
33
- * Includes <source> elements for format variants.
34
- */
35
- export function renderVideoHTML(video, attrs = {}) {
36
- const posterSrc = video.poster?.fallback.src;
37
- const attrPairs = [
38
- ...Object.entries(attrs),
39
- ['src', video.sources?.length ? undefined : video.src],
40
- ['poster', posterSrc],
41
- ['width', video.width > 0 ? video.width : undefined],
42
- ['height', video.height > 0 ? video.height : undefined],
43
- ];
44
- const attrString = renderAttrs(attrPairs);
45
- const sources = (video.sources ?? [])
46
- .map((s) => `<source${renderAttrs([['src', s.src], ['type', s.type]])}>`)
47
- .join('');
48
- // If no format variants, src is on the <video> element itself
49
- if (!sources) {
50
- return `<video${attrString}></video>`;
51
- }
52
- return `<video${attrString}>${sources}</video>`;
53
- }
54
- /**
55
- * Renders any GradialAsset to an HTML string.
56
- * Delegates to renderImageHTML or renderVideoHTML based on $type.
57
- */
58
- export function renderAssetHTML(asset, attrs = {}) {
59
- if (asset.$type === 'gradial.image') {
60
- return renderImageHTML(asset, attrs);
61
- }
62
- return renderVideoHTML(asset, attrs);
63
- }
64
- // ---------------------------------------------------------------------------
65
- // Internal helpers
66
- // ---------------------------------------------------------------------------
67
- function renderAttrs(pairs) {
68
- const rendered = pairs
69
- .filter(([, value]) => value !== undefined && value !== null && value !== false)
70
- .map(([name, value]) => value === true
71
- ? escapeName(name)
72
- : `${escapeName(name)}="${escapeAttr(String(value))}"`);
73
- if (!rendered.length)
74
- return '';
75
- return ' ' + rendered.join(' ');
76
- }
77
- function escapeName(name) {
78
- return name.replace(/[^A-Za-z0-9_:-]/g, '');
79
- }
80
- function escapeAttr(value) {
81
- return value
82
- .replace(/&/g, '&amp;')
83
- .replace(/"/g, '&quot;')
84
- .replace(/</g, '&lt;')
85
- .replace(/>/g, '&gt;');
2
+ import { ImageSchema } from './image.js';
3
+ import { VideoSchema } from './video.js';
4
+ /** Zod schema for a resolved asset value. */
5
+ export const AssetSchema = z.union([ImageSchema, VideoSchema]);
6
+ /** Runtime guard: value is a resolved asset. */
7
+ export function isAsset(value) {
8
+ return ImageSchema.safeParse(value).success || VideoSchema.safeParse(value).success;
9
+ }
10
+ /** Runtime guard: value is a resolved image asset. */
11
+ export function isImage(value) {
12
+ return ImageSchema.safeParse(value).success;
13
+ }
14
+ /** Runtime guard: value is a resolved video asset. */
15
+ export function isVideo(value) {
16
+ return VideoSchema.safeParse(value).success;
86
17
  }
@@ -7,7 +7,7 @@ export interface RenderCapabilities {
7
7
  clientIslands: boolean;
8
8
  fragmentRender: boolean;
9
9
  }
10
- export interface GradialRenderer {
10
+ export interface Renderer {
11
11
  renderPage(request: RenderPageRequest): Promise<RenderPageResult>;
12
12
  renderFragment?(request: RenderFragmentRequest): Promise<RenderResult>;
13
13
  renderIsland?(request: RenderIslandRequest): Promise<RenderResult>;
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ export type InlineContent = {
3
+ type: 'text';
4
+ text: string;
5
+ } | {
6
+ type: 'span';
7
+ content: InlineContent[];
8
+ variant?: string;
9
+ } | {
10
+ type: 'strong';
11
+ content: InlineContent[];
12
+ } | {
13
+ type: 'em';
14
+ content: InlineContent[];
15
+ } | {
16
+ type: 'link';
17
+ href: string;
18
+ content: InlineContent[];
19
+ };
20
+ export type Heading = {
21
+ type: 'heading';
22
+ level: 1 | 2 | 3 | 4 | 5 | 6;
23
+ content: InlineContent[];
24
+ variant?: string;
25
+ };
26
+ export type RichTextValue = {
27
+ format: 'html';
28
+ html: string;
29
+ } | {
30
+ format: 'markdown';
31
+ markdown: string;
32
+ };
33
+ export declare const InlineContentSchema: z.ZodType<InlineContent>;
34
+ export declare const HeadingSchema: z.ZodObject<{
35
+ type: z.ZodLiteral<"heading">;
36
+ level: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>, z.ZodLiteral<5>, z.ZodLiteral<6>]>;
37
+ content: z.ZodArray<z.ZodType<InlineContent, unknown, z.core.$ZodTypeInternals<InlineContent, unknown>>>;
38
+ variant: z.ZodOptional<z.ZodString>;
39
+ }, z.core.$strip>;
40
+ export declare const RichTextValueSchema: z.ZodType<RichTextValue>;
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ export const InlineContentSchema = z.lazy(() => z.object({
3
+ type: z.literal('text'),
4
+ text: z.string(),
5
+ }).or(z.object({
6
+ type: z.literal('span'),
7
+ content: z.array(InlineContentSchema),
8
+ variant: z.string().optional(),
9
+ })).or(z.object({
10
+ type: z.literal('strong'),
11
+ content: z.array(InlineContentSchema),
12
+ })).or(z.object({
13
+ type: z.literal('em'),
14
+ content: z.array(InlineContentSchema),
15
+ })).or(z.object({
16
+ type: z.literal('link'),
17
+ href: z.string().min(1),
18
+ content: z.array(InlineContentSchema),
19
+ })));
20
+ export const HeadingSchema = z.object({
21
+ type: z.literal('heading'),
22
+ level: z.union([
23
+ z.literal(1),
24
+ z.literal(2),
25
+ z.literal(3),
26
+ z.literal(4),
27
+ z.literal(5),
28
+ z.literal(6),
29
+ ]),
30
+ content: z.array(InlineContentSchema),
31
+ variant: z.string().optional(),
32
+ });
33
+ export const RichTextValueSchema = z.object({
34
+ format: z.literal('html'),
35
+ html: z.string(),
36
+ }).or(z.object({
37
+ format: z.literal('markdown'),
38
+ markdown: z.string(),
39
+ }));
@@ -1,10 +1,10 @@
1
1
  import { z } from 'zod';
2
- import { type GradialImage } from './image.js';
2
+ import { type Image } from './image.js';
3
3
  export interface VideoSource {
4
4
  src: string;
5
5
  type: string;
6
6
  }
7
- export interface GradialVideo {
7
+ export interface Video {
8
8
  /** Discriminator — always 'gradial.video'. */
9
9
  $type: 'gradial.video';
10
10
  /** DAM asset identifier. */
@@ -22,10 +22,10 @@ export interface GradialVideo {
22
22
  /** Intrinsic height in pixels. */
23
23
  height: number;
24
24
  /**
25
- * Poster frame — a full GradialImage with responsive srcset.
25
+ * Poster frame — a full Image with responsive srcset.
26
26
  * The compiler extracts or generates this from the video asset.
27
27
  */
28
- poster?: GradialImage;
28
+ poster?: Image;
29
29
  /** Format variants (e.g. mp4 + webm). Maps to <video><source> elements. */
30
30
  sources?: VideoSource[];
31
31
  /** Duration in seconds (if known). */
@@ -35,7 +35,7 @@ export declare const VideoSourceSchema: z.ZodObject<{
35
35
  src: z.ZodString;
36
36
  type: z.ZodString;
37
37
  }, z.core.$strip>;
38
- export declare const GradialVideoSchema: z.ZodObject<{
38
+ export declare const VideoSchema: z.ZodObject<{
39
39
  $type: z.ZodLiteral<"gradial.video">;
40
40
  assetId: z.ZodString;
41
41
  versionId: z.ZodString;
@@ -49,18 +49,12 @@ export declare const GradialVideoSchema: z.ZodObject<{
49
49
  assetId: z.ZodString;
50
50
  versionId: z.ZodString;
51
51
  alt: z.ZodString;
52
- fallback: z.ZodObject<{
52
+ sources: z.ZodArray<z.ZodObject<{
53
53
  src: z.ZodString;
54
54
  width: z.ZodNumber;
55
55
  height: z.ZodNumber;
56
56
  type: z.ZodString;
57
- }, z.core.$strip>;
58
- sources: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodObject<{
59
- media: z.ZodOptional<z.ZodString>;
60
- type: z.ZodString;
61
- srcset: z.ZodString;
62
- sizes: z.ZodOptional<z.ZodString>;
63
- }, z.core.$strip>>>>;
57
+ }, z.core.$strip>>;
64
58
  }, z.core.$strip>>;
65
59
  sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
66
60
  src: z.ZodString;
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { GradialImageSchema } from './image.js';
2
+ import { ImageSchema } from './image.js';
3
3
  // ---------------------------------------------------------------------------
4
4
  // Zod schema
5
5
  // ---------------------------------------------------------------------------
@@ -7,7 +7,7 @@ export const VideoSourceSchema = z.object({
7
7
  src: z.string().min(1),
8
8
  type: z.string().min(1),
9
9
  });
10
- export const GradialVideoSchema = z.object({
10
+ export const VideoSchema = z.object({
11
11
  $type: z.literal('gradial.video'),
12
12
  assetId: z.string().min(1),
13
13
  versionId: z.string().min(1),
@@ -16,7 +16,7 @@ export const GradialVideoSchema = z.object({
16
16
  type: z.string().min(1),
17
17
  width: z.number().int().nonnegative(),
18
18
  height: z.number().int().nonnegative(),
19
- poster: GradialImageSchema.optional(),
19
+ poster: ImageSchema.optional(),
20
20
  sources: z.array(VideoSourceSchema).optional(),
21
21
  duration: z.number().nonnegative().optional(),
22
22
  });