mulmocast 2.20.0 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/schemas/mulmo_script.json +169 -0
- package/lib/data/animationRuntime.d.ts +5 -0
- package/lib/data/animationRuntime.js +639 -0
- package/lib/methods/mulmo_beat.d.ts +2 -7
- package/lib/methods/mulmo_beat.js +1 -12
- package/lib/methods/mulmo_beat_node.d.ts +2 -8
- package/lib/types/schema.d.ts +264 -0
- package/lib/utils/animation_config.d.ts +15 -0
- package/lib/utils/animation_config.js +17 -0
- package/lib/utils/beat_html/chart.d.ts +7 -11
- package/lib/utils/beat_html/chart.js +8 -18
- package/lib/utils/beat_html/decoration.d.ts +16 -0
- package/lib/utils/beat_html/decoration.js +55 -0
- package/lib/utils/beat_html/html_tailwind.d.ts +6 -6
- package/lib/utils/beat_html/html_tailwind.js +13 -7
- package/lib/utils/beat_html/index.js +5 -4
- package/lib/utils/beat_html/mermaid.d.ts +3 -6
- package/lib/utils/beat_html/mermaid.js +5 -10
- package/lib/utils/beat_html/slide.d.ts +13 -6
- package/lib/utils/beat_html/slide.js +8 -21
- package/lib/utils/beat_html/type.d.ts +47 -4
- package/lib/utils/context.d.ts +62 -0
- package/lib/utils/html_render.js +1 -1
- package/lib/utils/image_plugins/bg_image_css.d.ts +19 -0
- package/lib/utils/image_plugins/bg_image_css.js +75 -0
- package/lib/utils/image_plugins/bg_image_util.d.ts +0 -6
- package/lib/utils/image_plugins/bg_image_util.js +7 -69
- package/lib/utils/image_plugins/chart_html.d.ts +0 -10
- package/lib/utils/image_plugins/chart_html.js +5 -31
- package/lib/utils/image_plugins/html_tailwind.js +2 -39
- package/lib/utils/image_plugins/html_tailwind_script.d.ts +41 -0
- package/lib/utils/image_plugins/html_tailwind_script.js +111 -0
- package/lib/utils/image_plugins/slide.js +2 -5
- package/lib/utils/image_plugins/slide_branding.d.ts +7 -0
- package/lib/utils/image_plugins/slide_branding.js +10 -0
- package/package.json +2 -2
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import { ImageMediaType } from "../types/index.js";
|
|
2
|
-
|
|
3
|
-
const isAnimationObject = (animation) => {
|
|
4
|
-
return typeof animation === "object" && animation !== null && !Array.isArray(animation);
|
|
5
|
-
};
|
|
6
|
-
/** Check if a value is a valid animation config (true or non-array object) */
|
|
7
|
-
const isAnimationEnabled = (animation) => {
|
|
8
|
-
return animation === true || isAnimationObject(animation);
|
|
9
|
-
};
|
|
10
|
-
/** Check if movie mode (CDP screencast) is enabled */
|
|
11
|
-
const isMovieMode = (animation) => {
|
|
12
|
-
return isAnimationObject(animation) && animation.movie === true;
|
|
13
|
-
};
|
|
2
|
+
import { isAnimationEnabled, isAnimationObject, isMovieMode } from "../utils/animation_config.js";
|
|
14
3
|
/** Check if a beat has html_tailwind animation enabled */
|
|
15
4
|
const isAnimatedHtmlTailwind = (beat) => {
|
|
16
5
|
if (!beat.image || beat.image.type !== "html_tailwind")
|
|
@@ -7,14 +7,8 @@ export declare const MulmoBeatMethods: {
|
|
|
7
7
|
markdown?: (params: import("../types/type.js").BeatRenderParams) => string | undefined;
|
|
8
8
|
html?: (params: import("../types/type.js").BeatRenderParams) => Promise<string | undefined>;
|
|
9
9
|
};
|
|
10
|
-
isAnimationEnabled: (animation: unknown) => animation is true |
|
|
11
|
-
|
|
12
|
-
movie?: boolean;
|
|
13
|
-
};
|
|
14
|
-
isAnimationObject: (animation: unknown) => animation is {
|
|
15
|
-
fps?: number;
|
|
16
|
-
movie?: boolean;
|
|
17
|
-
};
|
|
10
|
+
isAnimationEnabled: (animation: unknown) => animation is true | import("../utils/animation_config.js").AnimationConfig;
|
|
11
|
+
isAnimationObject: (animation: unknown) => animation is import("../utils/animation_config.js").AnimationConfig;
|
|
18
12
|
isAnimatedHtmlTailwind: (beat: MulmoBeat) => boolean;
|
|
19
13
|
isPluginVideo: (beat: MulmoBeat) => boolean;
|
|
20
14
|
isMovieMode: (animation: unknown) => boolean;
|
package/lib/types/schema.d.ts
CHANGED
|
@@ -4207,6 +4207,72 @@ export declare const mulmoImageAssetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
4207
4207
|
}>>;
|
|
4208
4208
|
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
4209
4209
|
layout: z.ZodLiteral<"manifesto">;
|
|
4210
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
4211
|
+
title: z.ZodString;
|
|
4212
|
+
stepLabel: z.ZodOptional<z.ZodString>;
|
|
4213
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
4214
|
+
figure: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
4215
|
+
type: z.ZodLiteral<"chart">;
|
|
4216
|
+
chartData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
4217
|
+
title: z.ZodOptional<z.ZodString>;
|
|
4218
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
4219
|
+
type: z.ZodLiteral<"mermaid">;
|
|
4220
|
+
code: z.ZodString;
|
|
4221
|
+
title: z.ZodOptional<z.ZodString>;
|
|
4222
|
+
}, z.core.$strip>], "type">;
|
|
4223
|
+
accentColor: z.ZodOptional<z.ZodEnum<{
|
|
4224
|
+
primary: "primary";
|
|
4225
|
+
accent: "accent";
|
|
4226
|
+
success: "success";
|
|
4227
|
+
warning: "warning";
|
|
4228
|
+
danger: "danger";
|
|
4229
|
+
info: "info";
|
|
4230
|
+
highlight: "highlight";
|
|
4231
|
+
}>>;
|
|
4232
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
4233
|
+
bgColor: z.ZodOptional<z.ZodString>;
|
|
4234
|
+
bgGradient: z.ZodOptional<z.ZodString>;
|
|
4235
|
+
decorations: z.ZodOptional<z.ZodBoolean>;
|
|
4236
|
+
bgOpacity: z.ZodOptional<z.ZodNumber>;
|
|
4237
|
+
footer: z.ZodOptional<z.ZodString>;
|
|
4238
|
+
}, z.core.$strip>>;
|
|
4239
|
+
eyebrow: z.ZodOptional<z.ZodObject<{
|
|
4240
|
+
label: z.ZodString;
|
|
4241
|
+
color: z.ZodOptional<z.ZodEnum<{
|
|
4242
|
+
primary: "primary";
|
|
4243
|
+
accent: "accent";
|
|
4244
|
+
success: "success";
|
|
4245
|
+
warning: "warning";
|
|
4246
|
+
danger: "danger";
|
|
4247
|
+
info: "info";
|
|
4248
|
+
highlight: "highlight";
|
|
4249
|
+
}>>;
|
|
4250
|
+
}, z.core.$strip>>;
|
|
4251
|
+
density: z.ZodOptional<z.ZodEnum<{
|
|
4252
|
+
default: "default";
|
|
4253
|
+
compact: "compact";
|
|
4254
|
+
}>>;
|
|
4255
|
+
titleSize: z.ZodOptional<z.ZodEnum<{
|
|
4256
|
+
default: "default";
|
|
4257
|
+
small: "small";
|
|
4258
|
+
large: "large";
|
|
4259
|
+
hero: "hero";
|
|
4260
|
+
}>>;
|
|
4261
|
+
subtitleSize: z.ZodOptional<z.ZodEnum<{
|
|
4262
|
+
lead: "lead";
|
|
4263
|
+
big: "big";
|
|
4264
|
+
default: "default";
|
|
4265
|
+
}>>;
|
|
4266
|
+
intro: z.ZodOptional<z.ZodEnum<{
|
|
4267
|
+
fade: "fade";
|
|
4268
|
+
"fade-up": "fade-up";
|
|
4269
|
+
"fade-down": "fade-down";
|
|
4270
|
+
"slide-left": "slide-left";
|
|
4271
|
+
"slide-right": "slide-right";
|
|
4272
|
+
"zoom-in": "zoom-in";
|
|
4273
|
+
}>>;
|
|
4274
|
+
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
4275
|
+
layout: z.ZodLiteral<"figure">;
|
|
4210
4276
|
}, z.core.$strip>], "layout">;
|
|
4211
4277
|
reference: z.ZodOptional<z.ZodString>;
|
|
4212
4278
|
branding: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
@@ -8644,6 +8710,72 @@ export declare const mulmoBeatSchema: z.ZodObject<{
|
|
|
8644
8710
|
}>>;
|
|
8645
8711
|
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
8646
8712
|
layout: z.ZodLiteral<"manifesto">;
|
|
8713
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
8714
|
+
title: z.ZodString;
|
|
8715
|
+
stepLabel: z.ZodOptional<z.ZodString>;
|
|
8716
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
8717
|
+
figure: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
8718
|
+
type: z.ZodLiteral<"chart">;
|
|
8719
|
+
chartData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
8720
|
+
title: z.ZodOptional<z.ZodString>;
|
|
8721
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
8722
|
+
type: z.ZodLiteral<"mermaid">;
|
|
8723
|
+
code: z.ZodString;
|
|
8724
|
+
title: z.ZodOptional<z.ZodString>;
|
|
8725
|
+
}, z.core.$strip>], "type">;
|
|
8726
|
+
accentColor: z.ZodOptional<z.ZodEnum<{
|
|
8727
|
+
primary: "primary";
|
|
8728
|
+
accent: "accent";
|
|
8729
|
+
success: "success";
|
|
8730
|
+
warning: "warning";
|
|
8731
|
+
danger: "danger";
|
|
8732
|
+
info: "info";
|
|
8733
|
+
highlight: "highlight";
|
|
8734
|
+
}>>;
|
|
8735
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
8736
|
+
bgColor: z.ZodOptional<z.ZodString>;
|
|
8737
|
+
bgGradient: z.ZodOptional<z.ZodString>;
|
|
8738
|
+
decorations: z.ZodOptional<z.ZodBoolean>;
|
|
8739
|
+
bgOpacity: z.ZodOptional<z.ZodNumber>;
|
|
8740
|
+
footer: z.ZodOptional<z.ZodString>;
|
|
8741
|
+
}, z.core.$strip>>;
|
|
8742
|
+
eyebrow: z.ZodOptional<z.ZodObject<{
|
|
8743
|
+
label: z.ZodString;
|
|
8744
|
+
color: z.ZodOptional<z.ZodEnum<{
|
|
8745
|
+
primary: "primary";
|
|
8746
|
+
accent: "accent";
|
|
8747
|
+
success: "success";
|
|
8748
|
+
warning: "warning";
|
|
8749
|
+
danger: "danger";
|
|
8750
|
+
info: "info";
|
|
8751
|
+
highlight: "highlight";
|
|
8752
|
+
}>>;
|
|
8753
|
+
}, z.core.$strip>>;
|
|
8754
|
+
density: z.ZodOptional<z.ZodEnum<{
|
|
8755
|
+
default: "default";
|
|
8756
|
+
compact: "compact";
|
|
8757
|
+
}>>;
|
|
8758
|
+
titleSize: z.ZodOptional<z.ZodEnum<{
|
|
8759
|
+
default: "default";
|
|
8760
|
+
small: "small";
|
|
8761
|
+
large: "large";
|
|
8762
|
+
hero: "hero";
|
|
8763
|
+
}>>;
|
|
8764
|
+
subtitleSize: z.ZodOptional<z.ZodEnum<{
|
|
8765
|
+
lead: "lead";
|
|
8766
|
+
big: "big";
|
|
8767
|
+
default: "default";
|
|
8768
|
+
}>>;
|
|
8769
|
+
intro: z.ZodOptional<z.ZodEnum<{
|
|
8770
|
+
fade: "fade";
|
|
8771
|
+
"fade-up": "fade-up";
|
|
8772
|
+
"fade-down": "fade-down";
|
|
8773
|
+
"slide-left": "slide-left";
|
|
8774
|
+
"slide-right": "slide-right";
|
|
8775
|
+
"zoom-in": "zoom-in";
|
|
8776
|
+
}>>;
|
|
8777
|
+
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
8778
|
+
layout: z.ZodLiteral<"figure">;
|
|
8647
8779
|
}, z.core.$strip>], "layout">;
|
|
8648
8780
|
reference: z.ZodOptional<z.ZodString>;
|
|
8649
8781
|
branding: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
@@ -13927,6 +14059,72 @@ export declare const mulmoScriptSchema: z.ZodObject<{
|
|
|
13927
14059
|
}>>;
|
|
13928
14060
|
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
13929
14061
|
layout: z.ZodLiteral<"manifesto">;
|
|
14062
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
14063
|
+
title: z.ZodString;
|
|
14064
|
+
stepLabel: z.ZodOptional<z.ZodString>;
|
|
14065
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
14066
|
+
figure: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
14067
|
+
type: z.ZodLiteral<"chart">;
|
|
14068
|
+
chartData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
14069
|
+
title: z.ZodOptional<z.ZodString>;
|
|
14070
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
14071
|
+
type: z.ZodLiteral<"mermaid">;
|
|
14072
|
+
code: z.ZodString;
|
|
14073
|
+
title: z.ZodOptional<z.ZodString>;
|
|
14074
|
+
}, z.core.$strip>], "type">;
|
|
14075
|
+
accentColor: z.ZodOptional<z.ZodEnum<{
|
|
14076
|
+
primary: "primary";
|
|
14077
|
+
accent: "accent";
|
|
14078
|
+
success: "success";
|
|
14079
|
+
warning: "warning";
|
|
14080
|
+
danger: "danger";
|
|
14081
|
+
info: "info";
|
|
14082
|
+
highlight: "highlight";
|
|
14083
|
+
}>>;
|
|
14084
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
14085
|
+
bgColor: z.ZodOptional<z.ZodString>;
|
|
14086
|
+
bgGradient: z.ZodOptional<z.ZodString>;
|
|
14087
|
+
decorations: z.ZodOptional<z.ZodBoolean>;
|
|
14088
|
+
bgOpacity: z.ZodOptional<z.ZodNumber>;
|
|
14089
|
+
footer: z.ZodOptional<z.ZodString>;
|
|
14090
|
+
}, z.core.$strip>>;
|
|
14091
|
+
eyebrow: z.ZodOptional<z.ZodObject<{
|
|
14092
|
+
label: z.ZodString;
|
|
14093
|
+
color: z.ZodOptional<z.ZodEnum<{
|
|
14094
|
+
primary: "primary";
|
|
14095
|
+
accent: "accent";
|
|
14096
|
+
success: "success";
|
|
14097
|
+
warning: "warning";
|
|
14098
|
+
danger: "danger";
|
|
14099
|
+
info: "info";
|
|
14100
|
+
highlight: "highlight";
|
|
14101
|
+
}>>;
|
|
14102
|
+
}, z.core.$strip>>;
|
|
14103
|
+
density: z.ZodOptional<z.ZodEnum<{
|
|
14104
|
+
default: "default";
|
|
14105
|
+
compact: "compact";
|
|
14106
|
+
}>>;
|
|
14107
|
+
titleSize: z.ZodOptional<z.ZodEnum<{
|
|
14108
|
+
default: "default";
|
|
14109
|
+
small: "small";
|
|
14110
|
+
large: "large";
|
|
14111
|
+
hero: "hero";
|
|
14112
|
+
}>>;
|
|
14113
|
+
subtitleSize: z.ZodOptional<z.ZodEnum<{
|
|
14114
|
+
lead: "lead";
|
|
14115
|
+
big: "big";
|
|
14116
|
+
default: "default";
|
|
14117
|
+
}>>;
|
|
14118
|
+
intro: z.ZodOptional<z.ZodEnum<{
|
|
14119
|
+
fade: "fade";
|
|
14120
|
+
"fade-up": "fade-up";
|
|
14121
|
+
"fade-down": "fade-down";
|
|
14122
|
+
"slide-left": "slide-left";
|
|
14123
|
+
"slide-right": "slide-right";
|
|
14124
|
+
"zoom-in": "zoom-in";
|
|
14125
|
+
}>>;
|
|
14126
|
+
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
14127
|
+
layout: z.ZodLiteral<"figure">;
|
|
13930
14128
|
}, z.core.$strip>], "layout">;
|
|
13931
14129
|
reference: z.ZodOptional<z.ZodString>;
|
|
13932
14130
|
branding: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
@@ -18734,6 +18932,72 @@ export declare const mulmoStudioSchema: z.ZodObject<{
|
|
|
18734
18932
|
}>>;
|
|
18735
18933
|
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
18736
18934
|
layout: z.ZodLiteral<"manifesto">;
|
|
18935
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
18936
|
+
title: z.ZodString;
|
|
18937
|
+
stepLabel: z.ZodOptional<z.ZodString>;
|
|
18938
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
18939
|
+
figure: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
18940
|
+
type: z.ZodLiteral<"chart">;
|
|
18941
|
+
chartData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
18942
|
+
title: z.ZodOptional<z.ZodString>;
|
|
18943
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
18944
|
+
type: z.ZodLiteral<"mermaid">;
|
|
18945
|
+
code: z.ZodString;
|
|
18946
|
+
title: z.ZodOptional<z.ZodString>;
|
|
18947
|
+
}, z.core.$strip>], "type">;
|
|
18948
|
+
accentColor: z.ZodOptional<z.ZodEnum<{
|
|
18949
|
+
primary: "primary";
|
|
18950
|
+
accent: "accent";
|
|
18951
|
+
success: "success";
|
|
18952
|
+
warning: "warning";
|
|
18953
|
+
danger: "danger";
|
|
18954
|
+
info: "info";
|
|
18955
|
+
highlight: "highlight";
|
|
18956
|
+
}>>;
|
|
18957
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
18958
|
+
bgColor: z.ZodOptional<z.ZodString>;
|
|
18959
|
+
bgGradient: z.ZodOptional<z.ZodString>;
|
|
18960
|
+
decorations: z.ZodOptional<z.ZodBoolean>;
|
|
18961
|
+
bgOpacity: z.ZodOptional<z.ZodNumber>;
|
|
18962
|
+
footer: z.ZodOptional<z.ZodString>;
|
|
18963
|
+
}, z.core.$strip>>;
|
|
18964
|
+
eyebrow: z.ZodOptional<z.ZodObject<{
|
|
18965
|
+
label: z.ZodString;
|
|
18966
|
+
color: z.ZodOptional<z.ZodEnum<{
|
|
18967
|
+
primary: "primary";
|
|
18968
|
+
accent: "accent";
|
|
18969
|
+
success: "success";
|
|
18970
|
+
warning: "warning";
|
|
18971
|
+
danger: "danger";
|
|
18972
|
+
info: "info";
|
|
18973
|
+
highlight: "highlight";
|
|
18974
|
+
}>>;
|
|
18975
|
+
}, z.core.$strip>>;
|
|
18976
|
+
density: z.ZodOptional<z.ZodEnum<{
|
|
18977
|
+
default: "default";
|
|
18978
|
+
compact: "compact";
|
|
18979
|
+
}>>;
|
|
18980
|
+
titleSize: z.ZodOptional<z.ZodEnum<{
|
|
18981
|
+
default: "default";
|
|
18982
|
+
small: "small";
|
|
18983
|
+
large: "large";
|
|
18984
|
+
hero: "hero";
|
|
18985
|
+
}>>;
|
|
18986
|
+
subtitleSize: z.ZodOptional<z.ZodEnum<{
|
|
18987
|
+
lead: "lead";
|
|
18988
|
+
big: "big";
|
|
18989
|
+
default: "default";
|
|
18990
|
+
}>>;
|
|
18991
|
+
intro: z.ZodOptional<z.ZodEnum<{
|
|
18992
|
+
fade: "fade";
|
|
18993
|
+
"fade-up": "fade-up";
|
|
18994
|
+
"fade-down": "fade-down";
|
|
18995
|
+
"slide-left": "slide-left";
|
|
18996
|
+
"slide-right": "slide-right";
|
|
18997
|
+
"zoom-in": "zoom-in";
|
|
18998
|
+
}>>;
|
|
18999
|
+
staggerMs: z.ZodOptional<z.ZodNumber>;
|
|
19000
|
+
layout: z.ZodLiteral<"figure">;
|
|
18737
19001
|
}, z.core.$strip>], "layout">;
|
|
18738
19002
|
reference: z.ZodOptional<z.ZodString>;
|
|
18739
19003
|
branding: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading an html_tailwind `animation` value. Pure and dependency-free — the PNG render and the
|
|
3
|
+
* browser fragment path decide "is this animated, at what fps" the same way, and the browser
|
|
4
|
+
* bundle must not reach the schema module to do it.
|
|
5
|
+
*/
|
|
6
|
+
export type AnimationConfig = {
|
|
7
|
+
fps?: number;
|
|
8
|
+
movie?: boolean;
|
|
9
|
+
};
|
|
10
|
+
/** Type guard: checks if animation value is an object config like { fps: 30 } */
|
|
11
|
+
export declare const isAnimationObject: (animation: unknown) => animation is AnimationConfig;
|
|
12
|
+
/** Check if a value is a valid animation config (true or non-array object) */
|
|
13
|
+
export declare const isAnimationEnabled: (animation: unknown) => animation is true | AnimationConfig;
|
|
14
|
+
/** Check if movie mode (CDP screencast) is enabled */
|
|
15
|
+
export declare const isMovieMode: (animation: unknown) => boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading an html_tailwind `animation` value. Pure and dependency-free — the PNG render and the
|
|
3
|
+
* browser fragment path decide "is this animated, at what fps" the same way, and the browser
|
|
4
|
+
* bundle must not reach the schema module to do it.
|
|
5
|
+
*/
|
|
6
|
+
/** Type guard: checks if animation value is an object config like { fps: 30 } */
|
|
7
|
+
export const isAnimationObject = (animation) => {
|
|
8
|
+
return typeof animation === "object" && animation !== null && !Array.isArray(animation);
|
|
9
|
+
};
|
|
10
|
+
/** Check if a value is a valid animation config (true or non-array object) */
|
|
11
|
+
export const isAnimationEnabled = (animation) => {
|
|
12
|
+
return animation === true || isAnimationObject(animation);
|
|
13
|
+
};
|
|
14
|
+
/** Check if movie mode (CDP screencast) is enabled */
|
|
15
|
+
export const isMovieMode = (animation) => {
|
|
16
|
+
return isAnimationObject(animation) && animation.movie === true;
|
|
17
|
+
};
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import type { MulmoChartMedia } from "../../types/index.js";
|
|
2
|
-
import type { BeatHtmlFragment } from "./type.js";
|
|
2
|
+
import type { BeatHtmlFragment, BeatHtmlOptions } from "./type.js";
|
|
3
3
|
/**
|
|
4
|
-
* A chart beat as
|
|
4
|
+
* A chart beat as a deck `figure` slide, so it shares the `slide` beat's theme and its one
|
|
5
|
+
* host code path: `slideUtilityCss`, and the `[data-mulmo-chart]` canvas driven from the
|
|
6
|
+
* attribute rather than from an inline `<script>`, which neither runs through `innerHTML`
|
|
7
|
+
* nor survives sanitizing.
|
|
5
8
|
*
|
|
6
|
-
* The
|
|
7
|
-
* a script injected through `innerHTML` does not execute, and does not survive sanitizing
|
|
8
|
-
* either. The attribute shape matches `@mulmocast/deck`'s, so a host that already drives
|
|
9
|
-
* `[data-mulmo-chart]` for slides drives this too without a second code path.
|
|
10
|
-
*
|
|
11
|
-
* The markup itself comes from `image_plugins/chart_html.ts`, the same module the Node
|
|
12
|
-
* render path uses — a second copy of it would drift, and the two paths have to draw the
|
|
13
|
-
* same chart.
|
|
9
|
+
* The PNG path still draws from its own template, so the browser and the PNG differ in look.
|
|
14
10
|
*/
|
|
15
|
-
export declare const chartToHtml: (image: MulmoChartMedia,
|
|
11
|
+
export declare const chartToHtml: (image: MulmoChartMedia, options: BeatHtmlOptions) => BeatHtmlFragment;
|
|
@@ -1,21 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { deckSlideToHtml } from "./slide.js";
|
|
2
|
+
import { backgroundDecoration } from "./decoration.js";
|
|
2
3
|
/**
|
|
3
|
-
* A chart beat as
|
|
4
|
+
* A chart beat as a deck `figure` slide, so it shares the `slide` beat's theme and its one
|
|
5
|
+
* host code path: `slideUtilityCss`, and the `[data-mulmo-chart]` canvas driven from the
|
|
6
|
+
* attribute rather than from an inline `<script>`, which neither runs through `innerHTML`
|
|
7
|
+
* nor survives sanitizing.
|
|
4
8
|
*
|
|
5
|
-
* The
|
|
6
|
-
* a script injected through `innerHTML` does not execute, and does not survive sanitizing
|
|
7
|
-
* either. The attribute shape matches `@mulmocast/deck`'s, so a host that already drives
|
|
8
|
-
* `[data-mulmo-chart]` for slides drives this too without a second code path.
|
|
9
|
-
*
|
|
10
|
-
* The markup itself comes from `image_plugins/chart_html.ts`, the same module the Node
|
|
11
|
-
* render path uses — a second copy of it would drift, and the two paths have to draw the
|
|
12
|
-
* same chart.
|
|
9
|
+
* The PNG path still draws from its own template, so the browser and the PNG differ in look.
|
|
13
10
|
*/
|
|
14
|
-
export const chartToHtml = (image,
|
|
15
|
-
const plugins = chartPluginCdns(chartTypeOf(image.chartData));
|
|
16
|
-
return {
|
|
17
|
-
html: chartFragmentHtml(image.chartData, image.title, `${idPrefix}-chart`),
|
|
18
|
-
requires: ["chart"],
|
|
19
|
-
...(plugins.length > 0 ? { chartPlugins: plugins } : {}),
|
|
20
|
-
};
|
|
21
|
-
};
|
|
11
|
+
export const chartToHtml = (image, options) => deckSlideToHtml({ layout: "figure", title: image.title, figure: { type: "chart", chartData: image.chartData } }, undefined, options, backgroundDecoration(image, options));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ResolvedBranding, SlideBranding } from "@mulmocast/deck";
|
|
2
|
+
import type { BackgroundImage } from "../../types/index.js";
|
|
3
|
+
import type { BeatHtmlFragment, BeatHtmlOptions } from "./type.js";
|
|
4
|
+
export declare const safeMediaUrl: (url: string) => string;
|
|
5
|
+
/** A textSlide / markdown fragment with `documentCss` for the background the PNG paints on `body`. */
|
|
6
|
+
export declare const withDocumentBackground: (fragment: BeatHtmlFragment | undefined, image: {
|
|
7
|
+
backgroundImage?: BackgroundImage;
|
|
8
|
+
}, options: BeatHtmlOptions) => BeatHtmlFragment | undefined;
|
|
9
|
+
/** A chart / mermaid beat's background, as the branding layer of the figure slide deck draws it on. */
|
|
10
|
+
export declare const backgroundDecoration: (image: {
|
|
11
|
+
backgroundImage?: BackgroundImage;
|
|
12
|
+
}, options: BeatHtmlOptions) => {
|
|
13
|
+
branding?: ResolvedBranding;
|
|
14
|
+
};
|
|
15
|
+
/** A slide beat's branding, resolved as `convertBrandingToResolved` does on the Node side. */
|
|
16
|
+
export declare const slideBranding: (beatBranding: SlideBranding | null | undefined, options: BeatHtmlOptions) => ResolvedBranding | undefined;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { backgroundImageCss, backgroundImageLayout, resolveBackgroundImage } from "../image_plugins/bg_image_css.js";
|
|
2
|
+
import { pickBranding } from "../image_plugins/slide_branding.js";
|
|
3
|
+
import { mediaSrc } from "../image_plugins/media_html.js";
|
|
4
|
+
import { neutralizeStyleTerminator } from "../html_escape.js";
|
|
5
|
+
/**
|
|
6
|
+
* The decorations the PNG render adds around a beat's content — a background image, a slide's
|
|
7
|
+
* branding — resolved for the browser. The PNG path turns each image into a `data:` URI on disk;
|
|
8
|
+
* here the host says how its page reaches the file (`resolveMediaUrl`).
|
|
9
|
+
*/
|
|
10
|
+
// deck writes these urls into `style="…url('…')"` and `src="…"` unescaped, and a url from a script can carry a quote
|
|
11
|
+
// (`z.url()` accepts one). Percent-encoding leaves a url that still loads and cannot leave either context.
|
|
12
|
+
const UNSAFE_URL_CHARACTERS = /["'()\\<>\s]/g;
|
|
13
|
+
export const safeMediaUrl = (url) => url.replace(UNSAFE_URL_CHARACTERS, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`);
|
|
14
|
+
const mediaUrl = (source, options) => {
|
|
15
|
+
const url = (options.resolveMediaUrl ?? mediaSrc)(source);
|
|
16
|
+
return url === undefined ? undefined : safeMediaUrl(url);
|
|
17
|
+
};
|
|
18
|
+
const paintedBackground = (beatBackgroundImage, options) => {
|
|
19
|
+
const backgroundImage = resolveBackgroundImage(beatBackgroundImage, options.backgroundImage);
|
|
20
|
+
if (!backgroundImage)
|
|
21
|
+
return undefined;
|
|
22
|
+
const url = typeof backgroundImage === "string" ? safeMediaUrl(backgroundImage) : mediaUrl(backgroundImage.source, options);
|
|
23
|
+
return url === undefined ? undefined : { url, ...backgroundImageLayout(backgroundImage) };
|
|
24
|
+
};
|
|
25
|
+
/** A textSlide / markdown fragment with `documentCss` for the background the PNG paints on `body`. */
|
|
26
|
+
export const withDocumentBackground = (fragment, image, options) => {
|
|
27
|
+
const background = paintedBackground(image.backgroundImage, options);
|
|
28
|
+
if (!fragment || !background)
|
|
29
|
+
return fragment;
|
|
30
|
+
return { ...fragment, documentCss: neutralizeStyleTerminator(backgroundImageCss(background.url, background.size, background.opacity)) };
|
|
31
|
+
};
|
|
32
|
+
/** A chart / mermaid beat's background, as the branding layer of the figure slide deck draws it on. */
|
|
33
|
+
export const backgroundDecoration = (image, options) => {
|
|
34
|
+
const background = paintedBackground(image.backgroundImage, options);
|
|
35
|
+
return background ? { branding: { backgroundImage: { dataUrl: background.url, size: background.size, opacity: background.opacity } } } : {};
|
|
36
|
+
};
|
|
37
|
+
const resolvedLogo = (logo, options) => {
|
|
38
|
+
const dataUrl = mediaUrl(logo.source, options);
|
|
39
|
+
return dataUrl === undefined ? undefined : { dataUrl, position: logo.position, width: logo.width };
|
|
40
|
+
};
|
|
41
|
+
const resolvedBrandingBackground = (backgroundImage, options) => {
|
|
42
|
+
const dataUrl = mediaUrl(backgroundImage.source, options);
|
|
43
|
+
if (dataUrl === undefined)
|
|
44
|
+
return undefined;
|
|
45
|
+
return { dataUrl, size: backgroundImage.size ?? "cover", opacity: backgroundImage.opacity ?? 1, bgOpacity: backgroundImage.bgOpacity };
|
|
46
|
+
};
|
|
47
|
+
/** A slide beat's branding, resolved as `convertBrandingToResolved` does on the Node side. */
|
|
48
|
+
export const slideBranding = (beatBranding, options) => {
|
|
49
|
+
const branding = pickBranding(beatBranding, options.branding);
|
|
50
|
+
if (!branding)
|
|
51
|
+
return undefined;
|
|
52
|
+
const logo = branding.logo && resolvedLogo(branding.logo, options);
|
|
53
|
+
const backgroundImage = branding.backgroundImage && resolvedBrandingBackground(branding.backgroundImage, options);
|
|
54
|
+
return { ...(logo ? { logo } : {}), ...(backgroundImage ? { backgroundImage } : {}) };
|
|
55
|
+
};
|
|
@@ -4,12 +4,12 @@ import type { BeatHtmlFragment } from "./type.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* An html_tailwind beat as markup a host can inject.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* `<script>`:
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* `html` is the beat at rest — the same thing the Node dump path shows, with no generated
|
|
8
|
+
* `<script>`: a fragment injected through `innerHTML` cannot run one. The author's `script`
|
|
9
|
+
* FIELD, the swipe driver and the frame-based `animation` come back separately as
|
|
10
|
+
* `documentScript`, for a host that gives the beat a document of its own and can run them; it
|
|
11
|
+
* brings the beat to what the PNG shows (an animation's final frame). A `<script>` the author
|
|
12
|
+
* wrote inside `html` is markup, and passes through unsanitized — see below.
|
|
13
13
|
*
|
|
14
14
|
* The author's html is emitted as written. On this beat type markup IS the content — the
|
|
15
15
|
* schema also accepts `script` — so escaping it would remove the feature rather than a
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { htmlTailwindMarkup } from "../image_plugins/html_tailwind_markup.js";
|
|
2
|
+
import { htmlTailwindDocumentCss, htmlTailwindDocumentScript } from "../image_plugins/html_tailwind_script.js";
|
|
2
3
|
/**
|
|
3
4
|
* An html_tailwind beat as markup a host can inject.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
* `<script>`:
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* `html` is the beat at rest — the same thing the Node dump path shows, with no generated
|
|
7
|
+
* `<script>`: a fragment injected through `innerHTML` cannot run one. The author's `script`
|
|
8
|
+
* FIELD, the swipe driver and the frame-based `animation` come back separately as
|
|
9
|
+
* `documentScript`, for a host that gives the beat a document of its own and can run them; it
|
|
10
|
+
* brings the beat to what the PNG shows (an animation's final frame). A `<script>` the author
|
|
11
|
+
* wrote inside `html` is markup, and passes through unsanitized — see below.
|
|
11
12
|
*
|
|
12
13
|
* The author's html is emitted as written. On this beat type markup IS the content — the
|
|
13
14
|
* schema also accepts `script` — so escaping it would remove the feature rather than a
|
|
@@ -16,5 +17,10 @@ import { htmlTailwindMarkup } from "../image_plugins/html_tailwind_markup.js";
|
|
|
16
17
|
*/
|
|
17
18
|
export const htmlTailwindToHtml = (image) => {
|
|
18
19
|
const html = htmlTailwindMarkup(image);
|
|
19
|
-
|
|
20
|
+
const documentScript = htmlTailwindDocumentScript(image);
|
|
21
|
+
const documentCss = htmlTailwindDocumentCss(image);
|
|
22
|
+
// A script-only beat draws itself, so it is a fragment with empty markup rather than nothing.
|
|
23
|
+
if (!documentScript && html === "")
|
|
24
|
+
return undefined;
|
|
25
|
+
return { html, ...(documentCss ? { documentCss } : {}), ...(documentScript ? { documentScript } : {}) };
|
|
20
26
|
};
|
|
@@ -6,6 +6,7 @@ import { imageToHtml, movieToHtml } from "./media.js";
|
|
|
6
6
|
import { mermaidToHtml } from "./mermaid.js";
|
|
7
7
|
import { slideToHtml } from "./slide.js";
|
|
8
8
|
import { assertSafeElementId } from "../element_id.js";
|
|
9
|
+
import { withDocumentBackground } from "./decoration.js";
|
|
9
10
|
export { textSlideToMarkdown, textSlideToHtml } from "./text_slide.js";
|
|
10
11
|
export { markdownToHtml } from "./markdown.js";
|
|
11
12
|
/**
|
|
@@ -42,13 +43,13 @@ export const beatToHtml = (beat, options) => {
|
|
|
42
43
|
assertSafeElementId(options.idPrefix);
|
|
43
44
|
switch (image.type) {
|
|
44
45
|
case "textSlide":
|
|
45
|
-
return textSlideToHtml(image);
|
|
46
|
+
return withDocumentBackground(textSlideToHtml(image), image, options);
|
|
46
47
|
case "markdown":
|
|
47
|
-
return markdownToHtml(image, options.idPrefix);
|
|
48
|
+
return withDocumentBackground(markdownToHtml(image, options.idPrefix), image, options);
|
|
48
49
|
case "chart":
|
|
49
|
-
return chartToHtml(image, options
|
|
50
|
+
return chartToHtml(image, options);
|
|
50
51
|
case "mermaid":
|
|
51
|
-
return mermaidToHtml(image, options
|
|
52
|
+
return mermaidToHtml(image, options);
|
|
52
53
|
case "image":
|
|
53
54
|
// The only description of the picture this module can reach. A host with more should
|
|
54
55
|
// set its own alt; an <img> with none makes a screen reader read the file name.
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import type { MulmoMermaidMedia } from "../../types/index.js";
|
|
2
|
-
import type { BeatHtmlFragment } from "./type.js";
|
|
2
|
+
import type { BeatHtmlFragment, BeatHtmlOptions } from "./type.js";
|
|
3
3
|
/**
|
|
4
|
-
* A mermaid beat as
|
|
4
|
+
* A mermaid beat as a deck `figure` slide — see `chart.ts` for why deck draws it.
|
|
5
5
|
*
|
|
6
6
|
* Only `code.kind === "text"` renders. The other kinds — `url`, `path`, `base64` — are
|
|
7
7
|
* resolved by `MulmoMediaSourceMethods.getText`, which fetches and reads files, so they
|
|
8
8
|
* cannot be reached from here and `beatToHtml` returns undefined rather than inventing a
|
|
9
9
|
* placeholder. `mermaid.ts`'s own markdown dump already draws the same line.
|
|
10
|
-
*
|
|
11
|
-
* The markup comes from `image_plugins/mermaid_html.ts`, the module the Node render path
|
|
12
|
-
* uses, so the browser and the PNG draw the same diagram.
|
|
13
10
|
*/
|
|
14
|
-
export declare const mermaidToHtml: (image: MulmoMermaidMedia,
|
|
11
|
+
export declare const mermaidToHtml: (image: MulmoMermaidMedia, options: BeatHtmlOptions) => BeatHtmlFragment | undefined;
|
|
@@ -1,22 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { deckSlideToHtml } from "./slide.js";
|
|
2
|
+
import { backgroundDecoration } from "./decoration.js";
|
|
2
3
|
/**
|
|
3
|
-
* A mermaid beat as
|
|
4
|
+
* A mermaid beat as a deck `figure` slide — see `chart.ts` for why deck draws it.
|
|
4
5
|
*
|
|
5
6
|
* Only `code.kind === "text"` renders. The other kinds — `url`, `path`, `base64` — are
|
|
6
7
|
* resolved by `MulmoMediaSourceMethods.getText`, which fetches and reads files, so they
|
|
7
8
|
* cannot be reached from here and `beatToHtml` returns undefined rather than inventing a
|
|
8
9
|
* placeholder. `mermaid.ts`'s own markdown dump already draws the same line.
|
|
9
|
-
*
|
|
10
|
-
* The markup comes from `image_plugins/mermaid_html.ts`, the module the Node render path
|
|
11
|
-
* uses, so the browser and the PNG draw the same diagram.
|
|
12
10
|
*/
|
|
13
|
-
export const mermaidToHtml = (image,
|
|
11
|
+
export const mermaidToHtml = (image, options) => {
|
|
14
12
|
if (image.code.kind !== "text")
|
|
15
13
|
return undefined;
|
|
16
14
|
const appendix = image.appendix?.join("\n") ?? "";
|
|
17
15
|
const code = `${image.code.text}\n${appendix}`.trim();
|
|
18
|
-
return {
|
|
19
|
-
html: mermaidHtml(code, `${idPrefix}-mermaid`, image.title || "Diagram"),
|
|
20
|
-
requires: ["mermaid"],
|
|
21
|
-
};
|
|
16
|
+
return deckSlideToHtml({ layout: "figure", title: image.title || "Diagram", figure: { type: "mermaid", code } }, undefined, options, backgroundDecoration(image, options));
|
|
22
17
|
};
|