@shotstack/shotstack-canvas 1.6.6 → 1.7.1
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/dist/entry.node.cjs +127 -114
- package/dist/entry.node.d.cts +122 -103
- package/dist/entry.node.d.ts +122 -103
- package/dist/entry.node.js +135 -114
- package/dist/entry.web.d.ts +121 -102
- package/dist/entry.web.js +135 -114
- package/package.json +4 -4
package/dist/entry.web.d.ts
CHANGED
|
@@ -1,105 +1,124 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
1
2
|
import { components } from '@shotstack/schemas';
|
|
2
3
|
|
|
3
|
-
declare const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
4
|
+
declare const CanvasRichTextAssetSchema: z.ZodObject<{
|
|
5
|
+
type: z.ZodLiteral<"rich-text">;
|
|
6
|
+
text: z.ZodDefault<z.ZodString>;
|
|
7
|
+
width: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
8
|
+
height: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
9
|
+
font: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
normal: "normal";
|
|
12
|
+
italic: "italic";
|
|
13
|
+
oblique: "oblique";
|
|
14
|
+
}>>;
|
|
15
|
+
family: z.ZodDefault<z.ZodString>;
|
|
16
|
+
size: z.ZodDefault<z.ZodNumber>;
|
|
17
|
+
weight: z.ZodDefault<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
18
|
+
color: z.ZodDefault<z.ZodString>;
|
|
19
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
20
|
+
background: z.ZodOptional<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>>;
|
|
22
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
23
|
+
letterSpacing: z.ZodDefault<z.ZodNumber>;
|
|
24
|
+
lineHeight: z.ZodDefault<z.ZodNumber>;
|
|
25
|
+
textTransform: z.ZodDefault<z.ZodEnum<{
|
|
26
|
+
none: "none";
|
|
27
|
+
uppercase: "uppercase";
|
|
28
|
+
lowercase: "lowercase";
|
|
29
|
+
capitalize: "capitalize";
|
|
30
|
+
}>>;
|
|
31
|
+
textDecoration: z.ZodDefault<z.ZodEnum<{
|
|
32
|
+
none: "none";
|
|
33
|
+
underline: "underline";
|
|
34
|
+
"line-through": "line-through";
|
|
35
|
+
}>>;
|
|
36
|
+
gradient: z.ZodOptional<z.ZodObject<{
|
|
37
|
+
type: z.ZodDefault<z.ZodEnum<{
|
|
38
|
+
linear: "linear";
|
|
39
|
+
radial: "radial";
|
|
40
|
+
}>>;
|
|
41
|
+
angle: z.ZodDefault<z.ZodNumber>;
|
|
42
|
+
stops: z.ZodArray<z.ZodObject<{
|
|
43
|
+
offset: z.ZodNumber;
|
|
44
|
+
color: z.ZodString;
|
|
45
|
+
}, z.core.$strip>>;
|
|
46
|
+
}, z.core.$strip>>;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
stroke: z.ZodOptional<z.ZodObject<{
|
|
49
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
50
|
+
color: z.ZodDefault<z.ZodString>;
|
|
51
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
52
|
+
}, z.core.$strip>>;
|
|
53
|
+
shadow: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
offsetX: z.ZodDefault<z.ZodNumber>;
|
|
55
|
+
offsetY: z.ZodDefault<z.ZodNumber>;
|
|
56
|
+
blur: z.ZodDefault<z.ZodNumber>;
|
|
57
|
+
color: z.ZodDefault<z.ZodString>;
|
|
58
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
59
|
+
}, z.core.$strip>>;
|
|
60
|
+
background: z.ZodOptional<z.ZodObject<{
|
|
61
|
+
borderRadius: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
62
|
+
color: z.ZodOptional<z.ZodString>;
|
|
63
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
64
|
+
}, z.core.$strip>>;
|
|
65
|
+
border: z.ZodOptional<z.ZodObject<{
|
|
66
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
67
|
+
color: z.ZodDefault<z.ZodString>;
|
|
68
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
69
|
+
radius: z.ZodDefault<z.ZodNumber>;
|
|
70
|
+
}, z.core.$strip>>;
|
|
71
|
+
padding: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
|
|
72
|
+
top: z.ZodDefault<z.ZodNumber>;
|
|
73
|
+
right: z.ZodDefault<z.ZodNumber>;
|
|
74
|
+
bottom: z.ZodDefault<z.ZodNumber>;
|
|
75
|
+
left: z.ZodDefault<z.ZodNumber>;
|
|
76
|
+
}, z.core.$strip>]>>;
|
|
77
|
+
align: z.ZodOptional<z.ZodObject<{
|
|
78
|
+
horizontal: z.ZodDefault<z.ZodEnum<{
|
|
79
|
+
center: "center";
|
|
80
|
+
right: "right";
|
|
81
|
+
left: "left";
|
|
82
|
+
}>>;
|
|
83
|
+
vertical: z.ZodDefault<z.ZodEnum<{
|
|
84
|
+
top: "top";
|
|
85
|
+
bottom: "bottom";
|
|
86
|
+
middle: "middle";
|
|
87
|
+
}>>;
|
|
88
|
+
}, z.core.$strip>>;
|
|
89
|
+
animation: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
preset: z.ZodEnum<{
|
|
91
|
+
typewriter: "typewriter";
|
|
92
|
+
fadeIn: "fadeIn";
|
|
93
|
+
slideIn: "slideIn";
|
|
94
|
+
shift: "shift";
|
|
95
|
+
ascend: "ascend";
|
|
96
|
+
movingLetters: "movingLetters";
|
|
97
|
+
}>;
|
|
98
|
+
speed: z.ZodDefault<z.ZodNumber>;
|
|
99
|
+
duration: z.ZodOptional<z.ZodNumber>;
|
|
100
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
101
|
+
character: "character";
|
|
102
|
+
word: "word";
|
|
103
|
+
}>>;
|
|
104
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
105
|
+
right: "right";
|
|
106
|
+
left: "left";
|
|
107
|
+
up: "up";
|
|
108
|
+
down: "down";
|
|
109
|
+
}>>;
|
|
110
|
+
}, z.core.$strip>>;
|
|
111
|
+
customFonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
112
|
+
src: z.ZodString;
|
|
113
|
+
family: z.ZodString;
|
|
114
|
+
weight: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
115
|
+
style: z.ZodOptional<z.ZodString>;
|
|
116
|
+
originalFamily: z.ZodOptional<z.ZodString>;
|
|
117
|
+
}, z.core.$strip>>>;
|
|
118
|
+
}, z.core.$strict>;
|
|
119
|
+
type CanvasRichTextAsset = z.infer<typeof CanvasRichTextAssetSchema>;
|
|
26
120
|
|
|
27
121
|
type ShotstackRichTextAsset = components["schemas"]["RichTextAsset"];
|
|
28
|
-
type RichTextValidated = Required<{
|
|
29
|
-
type: "rich-text";
|
|
30
|
-
text: string;
|
|
31
|
-
width?: number;
|
|
32
|
-
height?: number;
|
|
33
|
-
font?: {
|
|
34
|
-
family: string;
|
|
35
|
-
size: number;
|
|
36
|
-
weight: string | number;
|
|
37
|
-
color: string;
|
|
38
|
-
opacity: number;
|
|
39
|
-
background?: string;
|
|
40
|
-
};
|
|
41
|
-
style?: {
|
|
42
|
-
letterSpacing: number;
|
|
43
|
-
lineHeight: number;
|
|
44
|
-
textTransform: "none" | "uppercase" | "lowercase" | "capitalize";
|
|
45
|
-
textDecoration: "none" | "underline" | "line-through";
|
|
46
|
-
gradient?: {
|
|
47
|
-
type: "linear" | "radial";
|
|
48
|
-
angle: number;
|
|
49
|
-
stops: {
|
|
50
|
-
offset: number;
|
|
51
|
-
color: string;
|
|
52
|
-
}[];
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
stroke?: {
|
|
56
|
-
width: number;
|
|
57
|
-
color: string;
|
|
58
|
-
opacity: number;
|
|
59
|
-
};
|
|
60
|
-
shadow?: {
|
|
61
|
-
offsetX: number;
|
|
62
|
-
offsetY: number;
|
|
63
|
-
blur: number;
|
|
64
|
-
color: string;
|
|
65
|
-
opacity: number;
|
|
66
|
-
};
|
|
67
|
-
background?: {
|
|
68
|
-
color?: string;
|
|
69
|
-
opacity: number;
|
|
70
|
-
};
|
|
71
|
-
border?: {
|
|
72
|
-
width: number;
|
|
73
|
-
color: string;
|
|
74
|
-
opacity: number;
|
|
75
|
-
radius: number;
|
|
76
|
-
};
|
|
77
|
-
padding?: number | {
|
|
78
|
-
top: number;
|
|
79
|
-
right: number;
|
|
80
|
-
bottom: number;
|
|
81
|
-
left: number;
|
|
82
|
-
};
|
|
83
|
-
align?: {
|
|
84
|
-
horizontal: "left" | "center" | "right";
|
|
85
|
-
vertical: "top" | "middle" | "bottom";
|
|
86
|
-
};
|
|
87
|
-
animation?: {
|
|
88
|
-
preset: typeof CANVAS_CONFIG.ANIMATION_TYPES[number];
|
|
89
|
-
speed: number;
|
|
90
|
-
duration?: number;
|
|
91
|
-
style?: "character" | "word";
|
|
92
|
-
direction?: "left" | "right" | "up" | "down";
|
|
93
|
-
};
|
|
94
|
-
customFonts?: {
|
|
95
|
-
src: string;
|
|
96
|
-
family: string;
|
|
97
|
-
weight?: string | number;
|
|
98
|
-
style?: string;
|
|
99
|
-
originalFamily?: string;
|
|
100
|
-
}[];
|
|
101
|
-
}>;
|
|
102
|
-
|
|
103
122
|
type RGBA = {
|
|
104
123
|
r: number;
|
|
105
124
|
g: number;
|
|
@@ -221,7 +240,7 @@ type Renderer = {
|
|
|
221
240
|
render(ops: DrawOp[]): Promise<void>;
|
|
222
241
|
toPNG?: () => Promise<Buffer>;
|
|
223
242
|
};
|
|
224
|
-
type ValidAsset =
|
|
243
|
+
type ValidAsset = CanvasRichTextAsset;
|
|
225
244
|
declare const isShadowFill: (op: DrawOp) => op is Extract<DrawOp, {
|
|
226
245
|
op: "FillPath";
|
|
227
246
|
}> & {
|
|
@@ -241,7 +260,7 @@ declare function createTextEngine(opts?: {
|
|
|
241
260
|
wasmBaseURL?: string;
|
|
242
261
|
}): Promise<{
|
|
243
262
|
validate(input: unknown): {
|
|
244
|
-
value:
|
|
263
|
+
value: CanvasRichTextAsset;
|
|
245
264
|
};
|
|
246
265
|
registerFontFromUrl(url: string, desc: {
|
|
247
266
|
family: string;
|
|
@@ -251,11 +270,11 @@ declare function createTextEngine(opts?: {
|
|
|
251
270
|
family: string;
|
|
252
271
|
weight?: string | number;
|
|
253
272
|
}): Promise<void>;
|
|
254
|
-
renderFrame(asset:
|
|
273
|
+
renderFrame(asset: CanvasRichTextAsset, tSeconds: number, clipDuration?: number): Promise<DrawOp[]>;
|
|
255
274
|
createRenderer(canvas: HTMLCanvasElement | OffscreenCanvas): {
|
|
256
275
|
render(ops: DrawOp[]): Promise<void>;
|
|
257
276
|
};
|
|
258
277
|
destroy(): void;
|
|
259
278
|
}>;
|
|
260
279
|
|
|
261
|
-
export { type DrawOp, type EngineInit, type Glyph, type GradientSpec, type RGBA, type Renderer, type ShapedLine, type ShotstackRichTextAsset, type ValidAsset, createTextEngine, isGlyphFill, isShadowFill };
|
|
280
|
+
export { type CanvasRichTextAsset, CanvasRichTextAssetSchema, type DrawOp, type EngineInit, type Glyph, type GradientSpec, type RGBA, type Renderer, type ShapedLine, type ShotstackRichTextAsset, type ValidAsset, createTextEngine, isGlyphFill, isShadowFill };
|
package/dist/entry.web.js
CHANGED
|
@@ -2,8 +2,18 @@ import {
|
|
|
2
2
|
__publicField
|
|
3
3
|
} from "./chunk-HYGMWVDX.js";
|
|
4
4
|
|
|
5
|
-
// src/schema/
|
|
6
|
-
import
|
|
5
|
+
// src/schema/zod-schema.ts
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import {
|
|
8
|
+
richTextAssetSchema,
|
|
9
|
+
richTextFontSchema,
|
|
10
|
+
richTextStyleSchema,
|
|
11
|
+
richTextStrokeSchema,
|
|
12
|
+
richTextShadowSchema,
|
|
13
|
+
richTextBackgroundSchema,
|
|
14
|
+
richTextAlignmentSchema,
|
|
15
|
+
richTextAnimationSchema
|
|
16
|
+
} from "@shotstack/schemas/zod";
|
|
7
17
|
|
|
8
18
|
// src/config/canvas-constants.ts
|
|
9
19
|
var CANVAS_CONFIG = {
|
|
@@ -37,110 +47,127 @@ var CANVAS_CONFIG = {
|
|
|
37
47
|
]
|
|
38
48
|
};
|
|
39
49
|
|
|
40
|
-
// src/schema/
|
|
50
|
+
// src/schema/zod-schema.ts
|
|
41
51
|
var HEX6 = /^#[A-Fa-f0-9]{6}$/;
|
|
42
|
-
var
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
).min(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
opacity: Joi.number().min(0).max(1).default(1)
|
|
63
|
-
}).unknown(false);
|
|
64
|
-
var fontSchema = Joi.object({
|
|
65
|
-
family: Joi.string().default(CANVAS_CONFIG.DEFAULTS.fontFamily),
|
|
66
|
-
size: Joi.number().min(CANVAS_CONFIG.LIMITS.minFontSize).max(CANVAS_CONFIG.LIMITS.maxFontSize).default(CANVAS_CONFIG.DEFAULTS.fontSize),
|
|
67
|
-
weight: Joi.alternatives().try(Joi.string(), Joi.number()).default("400"),
|
|
68
|
-
color: Joi.string().pattern(HEX6).default(CANVAS_CONFIG.DEFAULTS.color),
|
|
69
|
-
opacity: Joi.number().min(0).max(1).default(1),
|
|
70
|
-
background: Joi.string().pattern(HEX6).optional()
|
|
71
|
-
}).unknown(false);
|
|
72
|
-
var styleSchema = Joi.object({
|
|
73
|
-
letterSpacing: Joi.number().default(0),
|
|
74
|
-
lineHeight: Joi.number().min(0).max(10).default(1.2),
|
|
75
|
-
textTransform: Joi.string().valid("none", "uppercase", "lowercase", "capitalize").default("none"),
|
|
76
|
-
textDecoration: Joi.string().valid("none", "underline", "line-through").default("none"),
|
|
77
|
-
gradient: gradientSchema.optional()
|
|
78
|
-
}).unknown(false);
|
|
79
|
-
var alignmentSchema = Joi.object({
|
|
80
|
-
horizontal: Joi.string().valid("left", "center", "right").default(CANVAS_CONFIG.DEFAULTS.textAlign),
|
|
81
|
-
vertical: Joi.string().valid("top", "middle", "bottom").default("middle")
|
|
82
|
-
}).unknown(false);
|
|
83
|
-
var animationSchema = Joi.object({
|
|
84
|
-
preset: Joi.string().valid(...CANVAS_CONFIG.ANIMATION_TYPES),
|
|
85
|
-
speed: Joi.number().min(0.1).max(10).default(1),
|
|
86
|
-
duration: Joi.number().min(CANVAS_CONFIG.LIMITS.minDuration).max(CANVAS_CONFIG.LIMITS.maxDuration).optional(),
|
|
87
|
-
style: Joi.string().valid("character", "word").optional().when("preset", {
|
|
88
|
-
is: Joi.valid("typewriter", "shift", "fadeIn", "slideIn"),
|
|
89
|
-
then: Joi.optional(),
|
|
90
|
-
otherwise: Joi.forbidden()
|
|
91
|
-
}),
|
|
92
|
-
direction: Joi.string().optional().when("preset", {
|
|
93
|
-
switch: [
|
|
94
|
-
{ is: "ascend", then: Joi.valid("up", "down") },
|
|
95
|
-
{ is: "shift", then: Joi.valid("left", "right", "up", "down") },
|
|
96
|
-
{ is: "slideIn", then: Joi.valid("left", "right", "up", "down") },
|
|
97
|
-
{ is: "movingLetters", then: Joi.valid("left", "right", "up", "down") }
|
|
98
|
-
],
|
|
99
|
-
otherwise: Joi.forbidden()
|
|
52
|
+
var customFontSchema = z.object({
|
|
53
|
+
src: z.string().url(),
|
|
54
|
+
family: z.string(),
|
|
55
|
+
weight: z.union([z.string(), z.number()]).optional(),
|
|
56
|
+
style: z.string().optional(),
|
|
57
|
+
originalFamily: z.string().optional()
|
|
58
|
+
});
|
|
59
|
+
var borderSchema = z.object({
|
|
60
|
+
width: z.number().min(0).default(0),
|
|
61
|
+
color: z.string().regex(HEX6).default("#000000"),
|
|
62
|
+
opacity: z.number().min(0).max(1).default(1),
|
|
63
|
+
radius: z.number().min(0).default(0)
|
|
64
|
+
});
|
|
65
|
+
var paddingSchema = z.union([
|
|
66
|
+
z.number().min(0),
|
|
67
|
+
z.object({
|
|
68
|
+
top: z.number().min(0).default(0),
|
|
69
|
+
right: z.number().min(0).default(0),
|
|
70
|
+
bottom: z.number().min(0).default(0),
|
|
71
|
+
left: z.number().min(0).default(0)
|
|
100
72
|
})
|
|
101
|
-
|
|
102
|
-
var
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
73
|
+
]);
|
|
74
|
+
var canvasFontSchema = richTextFontSchema.extend({
|
|
75
|
+
family: z.string().default(CANVAS_CONFIG.DEFAULTS.fontFamily),
|
|
76
|
+
size: z.number().int().min(CANVAS_CONFIG.LIMITS.minFontSize).max(CANVAS_CONFIG.LIMITS.maxFontSize).default(CANVAS_CONFIG.DEFAULTS.fontSize),
|
|
77
|
+
weight: z.union([z.string(), z.number()]).default("400"),
|
|
78
|
+
color: z.string().regex(HEX6).default(CANVAS_CONFIG.DEFAULTS.color),
|
|
79
|
+
opacity: z.number().min(0).max(1).default(1),
|
|
80
|
+
background: z.string().regex(HEX6).optional()
|
|
81
|
+
});
|
|
82
|
+
var canvasGradientSchema = z.object({
|
|
83
|
+
type: z.enum(["linear", "radial"]).default("linear"),
|
|
84
|
+
angle: z.number().min(0).max(360).default(0),
|
|
85
|
+
stops: z.array(z.object({
|
|
86
|
+
offset: z.number().min(0).max(1),
|
|
87
|
+
color: z.string().regex(HEX6)
|
|
88
|
+
})).min(2)
|
|
89
|
+
});
|
|
90
|
+
var canvasStyleSchema = richTextStyleSchema.extend({
|
|
91
|
+
letterSpacing: z.number().default(0),
|
|
92
|
+
lineHeight: z.number().min(0).max(10).default(1.2),
|
|
93
|
+
textTransform: z.enum(["none", "uppercase", "lowercase", "capitalize"]).default("none"),
|
|
94
|
+
textDecoration: z.enum(["none", "underline", "line-through"]).default("none"),
|
|
95
|
+
gradient: canvasGradientSchema.optional()
|
|
96
|
+
});
|
|
97
|
+
var canvasStrokeSchema = richTextStrokeSchema.extend({
|
|
98
|
+
width: z.number().min(0).default(0),
|
|
99
|
+
color: z.string().regex(HEX6).default("#000000"),
|
|
100
|
+
opacity: z.number().min(0).max(1).default(1)
|
|
101
|
+
});
|
|
102
|
+
var canvasShadowSchema = richTextShadowSchema.extend({
|
|
103
|
+
offsetX: z.number().default(0),
|
|
104
|
+
offsetY: z.number().default(0),
|
|
105
|
+
blur: z.number().min(0).default(0),
|
|
106
|
+
color: z.string().regex(HEX6).default("#000000"),
|
|
107
|
+
opacity: z.number().min(0).max(1).default(0.5)
|
|
108
|
+
});
|
|
109
|
+
var canvasBackgroundSchema = richTextBackgroundSchema.extend({
|
|
110
|
+
color: z.string().regex(HEX6).optional(),
|
|
111
|
+
opacity: z.number().min(0).max(1).default(1)
|
|
112
|
+
});
|
|
113
|
+
var canvasAlignmentSchema = richTextAlignmentSchema.extend({
|
|
114
|
+
horizontal: z.enum(["left", "center", "right"]).default(CANVAS_CONFIG.DEFAULTS.textAlign),
|
|
115
|
+
vertical: z.enum(["top", "middle", "bottom"]).default("middle")
|
|
116
|
+
});
|
|
117
|
+
var canvasAnimationSchema = richTextAnimationSchema.extend({
|
|
118
|
+
preset: z.enum(CANVAS_CONFIG.ANIMATION_TYPES),
|
|
119
|
+
speed: z.number().min(0.1).max(10).default(1),
|
|
120
|
+
duration: z.number().min(CANVAS_CONFIG.LIMITS.minDuration).max(CANVAS_CONFIG.LIMITS.maxDuration).optional(),
|
|
121
|
+
style: z.enum(["character", "word"]).optional(),
|
|
122
|
+
direction: z.enum(["left", "right", "up", "down"]).optional()
|
|
123
|
+
}).superRefine((data, ctx) => {
|
|
124
|
+
const presetsWithStyle = ["typewriter", "shift", "fadeIn", "slideIn"];
|
|
125
|
+
if (data.style && !presetsWithStyle.includes(data.preset)) {
|
|
126
|
+
ctx.addIssue({
|
|
127
|
+
code: z.ZodIssueCode.custom,
|
|
128
|
+
message: `style is not allowed for preset "${data.preset}"`,
|
|
129
|
+
path: ["style"]
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const directionRules = {
|
|
133
|
+
ascend: ["up", "down"],
|
|
134
|
+
shift: ["left", "right", "up", "down"],
|
|
135
|
+
slideIn: ["left", "right", "up", "down"],
|
|
136
|
+
movingLetters: ["left", "right", "up", "down"]
|
|
137
|
+
};
|
|
138
|
+
if (data.direction) {
|
|
139
|
+
const allowedDirections = directionRules[data.preset];
|
|
140
|
+
if (!allowedDirections) {
|
|
141
|
+
ctx.addIssue({
|
|
142
|
+
code: z.ZodIssueCode.custom,
|
|
143
|
+
message: `direction is not allowed for preset "${data.preset}"`,
|
|
144
|
+
path: ["direction"]
|
|
145
|
+
});
|
|
146
|
+
} else if (!allowedDirections.includes(data.direction)) {
|
|
147
|
+
ctx.addIssue({
|
|
148
|
+
code: z.ZodIssueCode.custom,
|
|
149
|
+
message: `direction "${data.direction}" is not valid for preset "${data.preset}"`,
|
|
150
|
+
path: ["direction"]
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
var CanvasRichTextAssetSchema = richTextAssetSchema.extend({
|
|
156
|
+
type: z.literal("rich-text"),
|
|
157
|
+
text: z.string().max(CANVAS_CONFIG.LIMITS.maxTextLength).default(""),
|
|
158
|
+
width: z.number().int().min(CANVAS_CONFIG.LIMITS.minWidth).max(CANVAS_CONFIG.LIMITS.maxWidth).default(CANVAS_CONFIG.DEFAULTS.width).optional(),
|
|
159
|
+
height: z.number().int().min(CANVAS_CONFIG.LIMITS.minHeight).max(CANVAS_CONFIG.LIMITS.maxHeight).default(CANVAS_CONFIG.DEFAULTS.height).optional(),
|
|
160
|
+
font: canvasFontSchema.optional(),
|
|
161
|
+
style: canvasStyleSchema.optional(),
|
|
162
|
+
stroke: canvasStrokeSchema.optional(),
|
|
163
|
+
shadow: canvasShadowSchema.optional(),
|
|
164
|
+
background: canvasBackgroundSchema.optional(),
|
|
138
165
|
border: borderSchema.optional(),
|
|
139
166
|
padding: paddingSchema.optional(),
|
|
140
|
-
align:
|
|
141
|
-
animation:
|
|
142
|
-
customFonts:
|
|
143
|
-
}).
|
|
167
|
+
align: canvasAlignmentSchema.optional(),
|
|
168
|
+
animation: canvasAnimationSchema.optional(),
|
|
169
|
+
customFonts: z.array(customFontSchema).optional()
|
|
170
|
+
}).strict();
|
|
144
171
|
|
|
145
172
|
// src/wasm/hb-loader.ts
|
|
146
173
|
var hbSingleton = null;
|
|
@@ -2133,19 +2160,12 @@ async function createTextEngine(opts = {}) {
|
|
|
2133
2160
|
}
|
|
2134
2161
|
return {
|
|
2135
2162
|
validate(input) {
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
});
|
|
2141
|
-
if (error) throw error;
|
|
2142
|
-
return { value };
|
|
2143
|
-
} catch (err) {
|
|
2144
|
-
if (err instanceof Error) {
|
|
2145
|
-
throw new Error(`Validation failed: ${err.message}`);
|
|
2146
|
-
}
|
|
2147
|
-
throw new Error(`Validation failed: ${String(err)}`);
|
|
2163
|
+
const result = CanvasRichTextAssetSchema.safeParse(input);
|
|
2164
|
+
if (!result.success) {
|
|
2165
|
+
const messages = result.error.issues.map((i) => i.message).join(". ");
|
|
2166
|
+
throw new Error(`Validation failed: ${messages}`);
|
|
2148
2167
|
}
|
|
2168
|
+
return { value: result.data };
|
|
2149
2169
|
},
|
|
2150
2170
|
async registerFontFromUrl(url, desc) {
|
|
2151
2171
|
try {
|
|
@@ -2321,6 +2341,7 @@ async function createTextEngine(opts = {}) {
|
|
|
2321
2341
|
};
|
|
2322
2342
|
}
|
|
2323
2343
|
export {
|
|
2344
|
+
CanvasRichTextAssetSchema,
|
|
2324
2345
|
createTextEngine,
|
|
2325
2346
|
isGlyphFill2 as isGlyphFill,
|
|
2326
2347
|
isShadowFill2 as isShadowFill
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shotstack/shotstack-canvas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Text layout & animation engine (HarfBuzz) for Node & Web - fully self-contained.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/entry.node.cjs",
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
},
|
|
43
43
|
"sideEffects": false,
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@shotstack/schemas": "^1.0
|
|
45
|
+
"@shotstack/schemas": "^1.3.0",
|
|
46
46
|
"canvas": "npm:@napi-rs/canvas@^0.1.54",
|
|
47
47
|
"ffmpeg-static": "^5.2.0",
|
|
48
48
|
"fontkit": "^2.0.4",
|
|
49
49
|
"harfbuzzjs": "0.4.12",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
50
|
+
"opentype.js": "^1.3.4",
|
|
51
|
+
"zod": "^4.2.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/fluent-ffmpeg": "2.1.27",
|