@gradial/aci 0.1.1 → 0.1.2
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/README.md +46 -1
- package/bin/aci +0 -0
- package/bin/aci.js +139 -27
- package/dist/assets/index.d.ts +2 -0
- package/dist/assets/index.js +2 -0
- package/dist/astro/index.js +4 -4
- package/dist/block-ref.d.ts +34 -0
- package/dist/block-ref.js +34 -0
- package/dist/define-component.d.ts +1 -0
- package/dist/define-component.js +1 -0
- package/dist/define-layout.d.ts +1 -0
- package/dist/define-layout.js +1 -0
- package/dist/dev/index.d.ts +6 -0
- package/dist/dev/index.js +66 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -1
- package/dist/next/asset-route.d.ts +9 -0
- package/dist/next/asset-route.js +15 -0
- package/dist/next/config.d.ts +2 -10
- package/dist/next/config.js +5 -2
- package/dist/next/server.d.ts +4 -0
- package/dist/next/server.js +53 -0
- package/dist/providers/s3.d.ts +2 -0
- package/dist/providers/s3.js +13 -1
- package/dist/react/GradialMedia.d.ts +24 -0
- package/dist/react/GradialMedia.js +31 -0
- package/dist/react/GradialPicture.d.ts +14 -0
- package/dist/react/GradialPicture.js +30 -0
- package/dist/react/GradialVideoPlayer.d.ts +13 -0
- package/dist/react/GradialVideoPlayer.js +28 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +3 -0
- package/dist/sveltekit/index.js +6 -1
- package/dist/types/component.d.ts +8 -3
- package/dist/types/image.d.ts +2 -2
- package/dist/types/image.js +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/media.d.ts +69 -0
- package/dist/types/media.js +86 -0
- package/dist/types/video.d.ts +70 -0
- package/dist/types/video.js +22 -0
- package/package.json +13 -9
- package/src/cli/compile-registry.mjs +142 -1
- package/src/cli/validate-content.mjs +98 -0
- package/src/cli/css-stub-loader.mjs +0 -27
- package/src/cli/generate-registry.mjs +0 -72
package/dist/providers/s3.js
CHANGED
|
@@ -2,7 +2,7 @@ import crypto from 'node:crypto';
|
|
|
2
2
|
import { FragmentNotFoundError, PageNotFoundError } from '../content/provider.js';
|
|
3
3
|
import { normalizeRoute } from '../content/routes.js';
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
5
|
-
// S3 content provider — reads compiled
|
|
5
|
+
// S3 content provider — reads compiled content files from S3
|
|
6
6
|
// ---------------------------------------------------------------------------
|
|
7
7
|
export class S3ContentProvider {
|
|
8
8
|
config;
|
|
@@ -49,6 +49,9 @@ export class S3ContentProvider {
|
|
|
49
49
|
this.#manifest ??= this.getJSON('manifest.json');
|
|
50
50
|
return await this.#manifest;
|
|
51
51
|
}
|
|
52
|
+
async fetchRaw(key) {
|
|
53
|
+
return await getS3Raw(key, this.config);
|
|
54
|
+
}
|
|
52
55
|
async getJSON(key) {
|
|
53
56
|
return await getS3JSON(joinKey(this.config.keyPrefix, key), this.config);
|
|
54
57
|
}
|
|
@@ -69,6 +72,15 @@ export async function getS3JSON(key, config) {
|
|
|
69
72
|
}
|
|
70
73
|
return (await res.json());
|
|
71
74
|
}
|
|
75
|
+
export async function getS3Raw(key, config) {
|
|
76
|
+
const url = s3ObjectURL(config, key);
|
|
77
|
+
const signedHeaders = signedS3Headers('GET', url, config);
|
|
78
|
+
return await fetch(url, {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
headers: signedHeaders,
|
|
81
|
+
cache: 'no-store'
|
|
82
|
+
});
|
|
83
|
+
}
|
|
72
84
|
// ---------------------------------------------------------------------------
|
|
73
85
|
// Internal helpers
|
|
74
86
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CSSProperties, type ImgHTMLAttributes, type VideoHTMLAttributes } from 'react';
|
|
2
|
+
import type { GradialAsset } from '../types/media.js';
|
|
3
|
+
export interface GradialMediaProps {
|
|
4
|
+
/** The compiler-resolved asset to render. */
|
|
5
|
+
asset: GradialAsset;
|
|
6
|
+
/** CSS class applied to the rendered element. */
|
|
7
|
+
className?: string;
|
|
8
|
+
/** Inline styles applied to the rendered element. */
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
/** Loading strategy for images. Defaults to 'lazy'. */
|
|
11
|
+
loading?: 'eager' | 'lazy';
|
|
12
|
+
/** Additional image attributes (only applied when asset is an image). */
|
|
13
|
+
imgProps?: Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'alt'>;
|
|
14
|
+
/** Additional video attributes (only applied when asset is a video). */
|
|
15
|
+
videoProps?: Omit<VideoHTMLAttributes<HTMLVideoElement>, 'src' | 'poster' | 'width' | 'height'>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Polymorphic media component — renders a GradialAsset as the appropriate
|
|
19
|
+
* HTML element based on $type.
|
|
20
|
+
*
|
|
21
|
+
* - gradial.image → <picture> or <img> via GradialPicture
|
|
22
|
+
* - gradial.video → <video> via GradialVideoPlayer
|
|
23
|
+
*/
|
|
24
|
+
export declare function GradialMedia({ asset, className, style, loading, imgProps, videoProps, }: GradialMediaProps): import("react").FunctionComponentElement<import("./GradialPicture.js").GradialPictureProps> | import("react").FunctionComponentElement<import("./GradialVideoPlayer.js").GradialVideoPlayerProps> | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import { GradialPicture } from './GradialPicture.js';
|
|
3
|
+
import { GradialVideoPlayer } from './GradialVideoPlayer.js';
|
|
4
|
+
/**
|
|
5
|
+
* Polymorphic media component — renders a GradialAsset as the appropriate
|
|
6
|
+
* HTML element based on $type.
|
|
7
|
+
*
|
|
8
|
+
* - gradial.image → <picture> or <img> via GradialPicture
|
|
9
|
+
* - gradial.video → <video> via GradialVideoPlayer
|
|
10
|
+
*/
|
|
11
|
+
export function GradialMedia({ asset, className, style, loading = 'lazy', imgProps, videoProps, }) {
|
|
12
|
+
switch (asset.$type) {
|
|
13
|
+
case 'gradial.image':
|
|
14
|
+
return createElement(GradialPicture, {
|
|
15
|
+
image: asset,
|
|
16
|
+
className,
|
|
17
|
+
style,
|
|
18
|
+
loading,
|
|
19
|
+
...imgProps,
|
|
20
|
+
});
|
|
21
|
+
case 'gradial.video':
|
|
22
|
+
return createElement(GradialVideoPlayer, {
|
|
23
|
+
video: asset,
|
|
24
|
+
className,
|
|
25
|
+
style,
|
|
26
|
+
...videoProps,
|
|
27
|
+
});
|
|
28
|
+
default:
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ImgHTMLAttributes } from 'react';
|
|
2
|
+
import type { GradialImage } from '../types/image.js';
|
|
3
|
+
export interface GradialPictureProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'alt'> {
|
|
4
|
+
image: GradialImage;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Renders a GradialImage as a <picture> element with responsive <source> entries,
|
|
8
|
+
* or a plain <img> when no art-directed sources exist.
|
|
9
|
+
*
|
|
10
|
+
* The compiler output determines the rendering:
|
|
11
|
+
* - sources[] populated → <picture> with <source> elements (art direction / format variants)
|
|
12
|
+
* - sources[] empty → <img> with fallback src
|
|
13
|
+
*/
|
|
14
|
+
export declare function GradialPicture({ image, ...attrs }: GradialPictureProps): import("react").DetailedReactHTMLElement<import("react").HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a GradialImage as a <picture> element with responsive <source> entries,
|
|
4
|
+
* or a plain <img> when no art-directed sources exist.
|
|
5
|
+
*
|
|
6
|
+
* The compiler output determines the rendering:
|
|
7
|
+
* - sources[] populated → <picture> with <source> elements (art direction / format variants)
|
|
8
|
+
* - sources[] empty → <img> with fallback src
|
|
9
|
+
*/
|
|
10
|
+
export function GradialPicture({ image, ...attrs }) {
|
|
11
|
+
const img = createElement('img', {
|
|
12
|
+
src: image.fallback.src,
|
|
13
|
+
alt: image.alt,
|
|
14
|
+
width: image.fallback.width > 0 ? image.fallback.width : undefined,
|
|
15
|
+
height: image.fallback.height > 0 ? image.fallback.height : undefined,
|
|
16
|
+
loading: 'lazy',
|
|
17
|
+
decoding: 'async',
|
|
18
|
+
...attrs,
|
|
19
|
+
});
|
|
20
|
+
if (!image.sources?.length) {
|
|
21
|
+
return img;
|
|
22
|
+
}
|
|
23
|
+
return createElement('picture', null, ...image.sources.map((source, index) => createElement('source', {
|
|
24
|
+
key: index,
|
|
25
|
+
media: source.media,
|
|
26
|
+
type: source.type,
|
|
27
|
+
srcSet: source.srcset,
|
|
28
|
+
sizes: source.sizes,
|
|
29
|
+
})), img);
|
|
30
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type VideoHTMLAttributes } from 'react';
|
|
2
|
+
import type { GradialVideo } from '../types/video.js';
|
|
3
|
+
export interface GradialVideoPlayerProps extends Omit<VideoHTMLAttributes<HTMLVideoElement>, 'src' | 'poster' | 'width' | 'height'> {
|
|
4
|
+
video: GradialVideo;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Renders a GradialVideo as a <video> element.
|
|
8
|
+
*
|
|
9
|
+
* - Uses poster.fallback.src for the poster attribute (single URL — browser limitation).
|
|
10
|
+
* - Includes <source> elements for format variants when available.
|
|
11
|
+
* - Falls back to src attribute on <video> when no source variants exist.
|
|
12
|
+
*/
|
|
13
|
+
export declare function GradialVideoPlayer({ video, ...attrs }: GradialVideoPlayerProps): import("react").DetailedReactHTMLElement<Record<string, unknown>, HTMLElement>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a GradialVideo as a <video> element.
|
|
4
|
+
*
|
|
5
|
+
* - Uses poster.fallback.src for the poster attribute (single URL — browser limitation).
|
|
6
|
+
* - Includes <source> elements for format variants when available.
|
|
7
|
+
* - Falls back to src attribute on <video> when no source variants exist.
|
|
8
|
+
*/
|
|
9
|
+
export function GradialVideoPlayer({ video, ...attrs }) {
|
|
10
|
+
const posterSrc = video.poster?.fallback.src;
|
|
11
|
+
const hasSources = video.sources && video.sources.length > 0;
|
|
12
|
+
const videoAttrs = {
|
|
13
|
+
poster: posterSrc,
|
|
14
|
+
width: video.width > 0 ? video.width : undefined,
|
|
15
|
+
height: video.height > 0 ? video.height : undefined,
|
|
16
|
+
...attrs,
|
|
17
|
+
};
|
|
18
|
+
// If no format variants, put src directly on <video>
|
|
19
|
+
if (!hasSources) {
|
|
20
|
+
videoAttrs.src = video.src;
|
|
21
|
+
}
|
|
22
|
+
const children = (video.sources ?? []).map((source, index) => createElement('source', {
|
|
23
|
+
key: index,
|
|
24
|
+
src: source.src,
|
|
25
|
+
type: source.type,
|
|
26
|
+
}));
|
|
27
|
+
return createElement('video', videoAttrs, ...children);
|
|
28
|
+
}
|
package/dist/sveltekit/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { gradialContentWatchPlugin, devRefreshPort, devRefreshScriptTag, } from '../dev/index.js';
|
|
1
|
+
import { gradialContentWatchPlugin, gradialDamAssetPlugin, devRefreshPort, devRefreshScriptTag, } from '../dev/index.js';
|
|
2
2
|
// ---------------------------------------------------------------------------
|
|
3
3
|
// Entries helper — for SvelteKit SSG prerendering
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
@@ -32,9 +32,14 @@ export async function gradialEntries() {
|
|
|
32
32
|
// ---------------------------------------------------------------------------
|
|
33
33
|
export function gradialSvelteKit(options = {}) {
|
|
34
34
|
const watchPlugin = gradialContentWatchPlugin(options);
|
|
35
|
+
const damAssetPlugin = gradialDamAssetPlugin(options);
|
|
35
36
|
return {
|
|
36
37
|
...watchPlugin,
|
|
37
38
|
name: 'gradial-sveltekit',
|
|
39
|
+
configureServer(server) {
|
|
40
|
+
damAssetPlugin.configureServer?.(server);
|
|
41
|
+
watchPlugin.configureServer?.(server);
|
|
42
|
+
},
|
|
38
43
|
transformIndexHtml(html) {
|
|
39
44
|
if (process.env.NODE_ENV === 'production') {
|
|
40
45
|
return html;
|
|
@@ -19,8 +19,12 @@ type CmsComponentFn<TProps = any> = ((props: TProps) => import('react').ReactEle
|
|
|
19
19
|
type InferContentProps<TSchema> = TSchema extends z.ZodType<infer T> ? T : Record<string, unknown>;
|
|
20
20
|
export interface ComponentDefinition<TSchema = unknown> {
|
|
21
21
|
name: string;
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* The React component that renders this CMS block.
|
|
24
|
+
* Accepts at least the schema-derived props, but may accept additional
|
|
25
|
+
* composition params (className, etc.) passed by parent sections.
|
|
26
|
+
*/
|
|
27
|
+
component?: CmsComponentFn<any>;
|
|
24
28
|
schema: TSchema;
|
|
25
29
|
renderModes?: ComponentRenderModes;
|
|
26
30
|
render?: ComponentRenderModes;
|
|
@@ -31,7 +35,7 @@ export interface ComponentDefinition<TSchema = unknown> {
|
|
|
31
35
|
}
|
|
32
36
|
export interface ComponentContract<TSchema = unknown> {
|
|
33
37
|
name: string;
|
|
34
|
-
component?: CmsComponentFn<
|
|
38
|
+
component?: CmsComponentFn<any>;
|
|
35
39
|
schema: TSchema;
|
|
36
40
|
renderModes: ComponentRenderModes;
|
|
37
41
|
render: ComponentRenderModes;
|
|
@@ -40,4 +44,5 @@ export interface ComponentContract<TSchema = unknown> {
|
|
|
40
44
|
vary?: VaryDimension[];
|
|
41
45
|
imageSlots?: Record<string, ImageSlotContract>;
|
|
42
46
|
}
|
|
47
|
+
export type InferComponentProps<TContract> = TContract extends ComponentContract<infer TSchema> ? InferContentProps<TSchema> : Record<string, unknown>;
|
|
43
48
|
export type { CmsComponentFn, InferContentProps };
|
package/dist/types/image.d.ts
CHANGED
|
@@ -40,12 +40,12 @@ export declare const GradialImageSchema: z.ZodObject<{
|
|
|
40
40
|
height: z.ZodNumber;
|
|
41
41
|
type: z.ZodString;
|
|
42
42
|
}, z.core.$strip>;
|
|
43
|
-
sources: z.ZodArray<z.ZodObject<{
|
|
43
|
+
sources: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
44
44
|
media: z.ZodOptional<z.ZodString>;
|
|
45
45
|
type: z.ZodString;
|
|
46
46
|
srcset: z.ZodString;
|
|
47
47
|
sizes: z.ZodOptional<z.ZodString>;
|
|
48
|
-
}, z.core.$strip
|
|
48
|
+
}, z.core.$strip>>>>;
|
|
49
49
|
}, z.core.$strip>;
|
|
50
50
|
export type ImageHTMLAttributes = Record<string, string | number | boolean | undefined | null>;
|
|
51
51
|
export declare function renderImageHTML(image: GradialImage, attrs?: ImageHTMLAttributes): string;
|
package/dist/types/image.js
CHANGED
|
@@ -15,7 +15,7 @@ export const GradialImageSchema = z.object({
|
|
|
15
15
|
type: z.string().min(1),
|
|
16
16
|
srcset: z.string().min(1),
|
|
17
17
|
sizes: z.string().optional(),
|
|
18
|
-
})),
|
|
18
|
+
})).nullable().default([]),
|
|
19
19
|
});
|
|
20
20
|
export function renderImageHTML(image, attrs = {}) {
|
|
21
21
|
const imgAttrs = renderAttrs({
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type GradialImage } from './image.js';
|
|
3
|
+
import { type GradialVideo } from './video.js';
|
|
4
|
+
/** Discriminated union of all compiler-resolved asset types. */
|
|
5
|
+
export type GradialAsset = GradialImage | GradialVideo;
|
|
6
|
+
export declare const GradialAssetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
7
|
+
$type: z.ZodLiteral<"gradial.image">;
|
|
8
|
+
assetId: z.ZodString;
|
|
9
|
+
versionId: z.ZodString;
|
|
10
|
+
alt: z.ZodString;
|
|
11
|
+
fallback: z.ZodObject<{
|
|
12
|
+
src: z.ZodString;
|
|
13
|
+
width: z.ZodNumber;
|
|
14
|
+
height: z.ZodNumber;
|
|
15
|
+
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>>>>;
|
|
23
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
24
|
+
$type: z.ZodLiteral<"gradial.video">;
|
|
25
|
+
assetId: z.ZodString;
|
|
26
|
+
versionId: z.ZodString;
|
|
27
|
+
alt: z.ZodString;
|
|
28
|
+
src: z.ZodString;
|
|
29
|
+
type: z.ZodString;
|
|
30
|
+
width: z.ZodNumber;
|
|
31
|
+
height: z.ZodNumber;
|
|
32
|
+
poster: z.ZodOptional<z.ZodObject<{
|
|
33
|
+
$type: z.ZodLiteral<"gradial.image">;
|
|
34
|
+
assetId: z.ZodString;
|
|
35
|
+
versionId: z.ZodString;
|
|
36
|
+
alt: z.ZodString;
|
|
37
|
+
fallback: z.ZodObject<{
|
|
38
|
+
src: z.ZodString;
|
|
39
|
+
width: z.ZodNumber;
|
|
40
|
+
height: z.ZodNumber;
|
|
41
|
+
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>>>>;
|
|
49
|
+
}, z.core.$strip>>;
|
|
50
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
51
|
+
src: z.ZodString;
|
|
52
|
+
type: z.ZodString;
|
|
53
|
+
}, z.core.$strip>>>;
|
|
54
|
+
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;
|
|
@@ -0,0 +1,86 @@
|
|
|
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, '&')
|
|
83
|
+
.replace(/"/g, '"')
|
|
84
|
+
.replace(/</g, '<')
|
|
85
|
+
.replace(/>/g, '>');
|
|
86
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type GradialImage } from './image.js';
|
|
3
|
+
export interface VideoSource {
|
|
4
|
+
src: string;
|
|
5
|
+
type: string;
|
|
6
|
+
}
|
|
7
|
+
export interface GradialVideo {
|
|
8
|
+
/** Discriminator — always 'gradial.video'. */
|
|
9
|
+
$type: 'gradial.video';
|
|
10
|
+
/** DAM asset identifier. */
|
|
11
|
+
assetId: string;
|
|
12
|
+
/** DAM version identifier. */
|
|
13
|
+
versionId: string;
|
|
14
|
+
/** Accessible description of the video content. */
|
|
15
|
+
alt: string;
|
|
16
|
+
/** Primary video URL (compiler-resolved). */
|
|
17
|
+
src: string;
|
|
18
|
+
/** Primary video MIME type (e.g. 'video/mp4'). */
|
|
19
|
+
type: string;
|
|
20
|
+
/** Intrinsic width in pixels. */
|
|
21
|
+
width: number;
|
|
22
|
+
/** Intrinsic height in pixels. */
|
|
23
|
+
height: number;
|
|
24
|
+
/**
|
|
25
|
+
* Poster frame — a full GradialImage with responsive srcset.
|
|
26
|
+
* The compiler extracts or generates this from the video asset.
|
|
27
|
+
*/
|
|
28
|
+
poster?: GradialImage;
|
|
29
|
+
/** Format variants (e.g. mp4 + webm). Maps to <video><source> elements. */
|
|
30
|
+
sources?: VideoSource[];
|
|
31
|
+
/** Duration in seconds (if known). */
|
|
32
|
+
duration?: number;
|
|
33
|
+
}
|
|
34
|
+
export declare const VideoSourceSchema: z.ZodObject<{
|
|
35
|
+
src: z.ZodString;
|
|
36
|
+
type: z.ZodString;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export declare const GradialVideoSchema: z.ZodObject<{
|
|
39
|
+
$type: z.ZodLiteral<"gradial.video">;
|
|
40
|
+
assetId: z.ZodString;
|
|
41
|
+
versionId: z.ZodString;
|
|
42
|
+
alt: z.ZodString;
|
|
43
|
+
src: z.ZodString;
|
|
44
|
+
type: z.ZodString;
|
|
45
|
+
width: z.ZodNumber;
|
|
46
|
+
height: z.ZodNumber;
|
|
47
|
+
poster: z.ZodOptional<z.ZodObject<{
|
|
48
|
+
$type: z.ZodLiteral<"gradial.image">;
|
|
49
|
+
assetId: z.ZodString;
|
|
50
|
+
versionId: z.ZodString;
|
|
51
|
+
alt: z.ZodString;
|
|
52
|
+
fallback: z.ZodObject<{
|
|
53
|
+
src: z.ZodString;
|
|
54
|
+
width: z.ZodNumber;
|
|
55
|
+
height: z.ZodNumber;
|
|
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>>>>;
|
|
64
|
+
}, z.core.$strip>>;
|
|
65
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
66
|
+
src: z.ZodString;
|
|
67
|
+
type: z.ZodString;
|
|
68
|
+
}, z.core.$strip>>>;
|
|
69
|
+
duration: z.ZodOptional<z.ZodNumber>;
|
|
70
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { GradialImageSchema } from './image.js';
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Zod schema
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
export const VideoSourceSchema = z.object({
|
|
7
|
+
src: z.string().min(1),
|
|
8
|
+
type: z.string().min(1),
|
|
9
|
+
});
|
|
10
|
+
export const GradialVideoSchema = z.object({
|
|
11
|
+
$type: z.literal('gradial.video'),
|
|
12
|
+
assetId: z.string().min(1),
|
|
13
|
+
versionId: z.string().min(1),
|
|
14
|
+
alt: z.string(),
|
|
15
|
+
src: z.string().min(1),
|
|
16
|
+
type: z.string().min(1),
|
|
17
|
+
width: z.number().int().nonnegative(),
|
|
18
|
+
height: z.number().int().nonnegative(),
|
|
19
|
+
poster: GradialImageSchema.optional(),
|
|
20
|
+
sources: z.array(VideoSourceSchema).optional(),
|
|
21
|
+
duration: z.number().nonnegative().optional(),
|
|
22
|
+
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradial/aci",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"bin/aci.js",
|
|
10
|
+
"bin/aci",
|
|
10
11
|
"src/cli/*.mjs",
|
|
11
12
|
"README.md"
|
|
12
13
|
],
|
|
@@ -57,13 +58,18 @@
|
|
|
57
58
|
"types": "./dist/assets/index.d.ts",
|
|
58
59
|
"import": "./dist/assets/index.js"
|
|
59
60
|
},
|
|
61
|
+
"./react": {
|
|
62
|
+
"types": "./dist/react/index.d.ts",
|
|
63
|
+
"import": "./dist/react/index.js"
|
|
64
|
+
},
|
|
60
65
|
"./astro": {
|
|
61
66
|
"types": "./dist/astro/index.d.ts",
|
|
62
67
|
"import": "./dist/astro/index.js"
|
|
63
68
|
},
|
|
64
69
|
"./next": {
|
|
65
70
|
"types": "./dist/next/index.d.ts",
|
|
66
|
-
"import": "./dist/next/index.js"
|
|
71
|
+
"import": "./dist/next/index.js",
|
|
72
|
+
"default": "./dist/next/index.js"
|
|
67
73
|
},
|
|
68
74
|
"./next/server": {
|
|
69
75
|
"types": "./dist/next/server.d.ts",
|
|
@@ -79,6 +85,10 @@
|
|
|
79
85
|
"types": "./dist/next/dev-refresh.d.ts",
|
|
80
86
|
"import": "./dist/next/dev-refresh.js"
|
|
81
87
|
},
|
|
88
|
+
"./next/asset-route": {
|
|
89
|
+
"types": "./dist/next/asset-route.d.ts",
|
|
90
|
+
"import": "./dist/next/asset-route.js"
|
|
91
|
+
},
|
|
82
92
|
"./sveltekit": {
|
|
83
93
|
"types": "./dist/sveltekit/index.d.ts",
|
|
84
94
|
"import": "./dist/sveltekit/index.js"
|
|
@@ -93,6 +103,7 @@
|
|
|
93
103
|
},
|
|
94
104
|
"scripts": {
|
|
95
105
|
"build": "tsc -p tsconfig.json",
|
|
106
|
+
"build:cli": "cd ../.. && ./scripts/build-cli.sh",
|
|
96
107
|
"compile-registry": "tsx src/cli/compile-registry.mjs",
|
|
97
108
|
"prepack": "npm run build"
|
|
98
109
|
},
|
|
@@ -116,13 +127,6 @@
|
|
|
116
127
|
"optional": true
|
|
117
128
|
}
|
|
118
129
|
},
|
|
119
|
-
"optionalDependencies": {
|
|
120
|
-
"@gradial/cli-darwin-arm64": "0.1.0",
|
|
121
|
-
"@gradial/cli-darwin-x64": "0.1.0",
|
|
122
|
-
"@gradial/cli-linux-x64": "0.1.0",
|
|
123
|
-
"@gradial/cli-linux-arm64": "0.1.0",
|
|
124
|
-
"@gradial/cli-win32-x64": "0.1.0"
|
|
125
|
-
},
|
|
126
130
|
"devDependencies": {
|
|
127
131
|
"@vercel/edge-config": "^1.4.3",
|
|
128
132
|
"@types/node": "^24.10.1",
|