mulmocast 2.1.28 → 2.1.30
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 +77 -0
- package/assets/html/tailwind.html +33 -0
- package/lib/cli/commands/tool/index.js +11 -1
- package/lib/cli/commands/tool/info/builder.d.ts +6 -0
- package/lib/cli/commands/tool/info/builder.js +13 -0
- package/lib/cli/commands/tool/info/handler.d.ts +6 -0
- package/lib/cli/commands/tool/info/handler.js +219 -0
- package/lib/cli/commands/tool/info/index.d.ts +4 -0
- package/lib/cli/commands/tool/info/index.js +4 -0
- package/lib/data/index.d.ts +1 -0
- package/lib/data/index.js +1 -0
- package/lib/data/markdownStyles.d.ts +14 -0
- package/lib/data/markdownStyles.js +998 -0
- package/lib/types/schema.d.ts +72 -5
- package/lib/types/schema.js +22 -1
- package/lib/types/type.d.ts +4 -1
- package/lib/utils/context.d.ts +24 -2
- package/lib/utils/html_render.js +13 -5
- package/lib/utils/image_plugins/chart.js +2 -5
- package/lib/utils/image_plugins/markdown.js +60 -12
- package/lib/utils/image_plugins/markdown_layout.d.ts +6 -0
- package/lib/utils/image_plugins/markdown_layout.js +127 -0
- package/lib/utils/image_plugins/mermaid.d.ts +1 -0
- package/lib/utils/image_plugins/mermaid.js +16 -13
- package/lib/utils/image_plugins/text_slide.js +3 -2
- package/lib/utils/image_plugins/utils.d.ts +2 -0
- package/lib/utils/image_plugins/utils.js +13 -0
- package/package.json +1 -1
- package/scripts/test/test_all_markdown_styles.json +809 -0
- package/scripts/test/test_markdown_layout.json +152 -0
- package/scripts/test/test_markdown_mermaid.json +58 -0
- package/scripts/test/test_markdown_styles.json +53 -0
- package/scripts/test/test_text_slide_style.json +70 -0
- package/scripts/test/test_vertexai.json +4 -1
- package/scripts/test/test_vertexai.json~ +21 -0
- package/scripts/test/zenn_combined_example.json +39 -0
- package/scripts/test/zenn_layout_samples.json +92 -0
- package/scripts/test/zenn_markdown_demo.json +79 -0
package/lib/types/schema.d.ts
CHANGED
|
@@ -179,9 +179,31 @@ export declare const mediaSourceMermaidSchema: z.ZodDiscriminatedUnion<[z.ZodObj
|
|
|
179
179
|
kind: z.ZodLiteral<"path">;
|
|
180
180
|
path: z.ZodString;
|
|
181
181
|
}, z.core.$strict>], "kind">;
|
|
182
|
+
export declare const row2Schema: z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
183
|
+
export declare const grid2x2Schema: z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
184
|
+
export declare const markdownLayoutSchema: z.ZodIntersection<z.ZodObject<{
|
|
185
|
+
header: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
186
|
+
"sidebar-left": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
187
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodObject<{
|
|
188
|
+
"row-2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
189
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
190
|
+
"2x2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
191
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
192
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
193
|
+
}, z.core.$strip>]>>;
|
|
182
194
|
export declare const mulmoMarkdownMediaSchema: z.ZodObject<{
|
|
183
195
|
type: z.ZodLiteral<"markdown">;
|
|
184
|
-
markdown: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]
|
|
196
|
+
markdown: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodIntersection<z.ZodObject<{
|
|
197
|
+
header: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
198
|
+
"sidebar-left": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
199
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodObject<{
|
|
200
|
+
"row-2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
201
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
202
|
+
"2x2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
203
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
204
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
205
|
+
}, z.core.$strip>]>>]>;
|
|
206
|
+
style: z.ZodOptional<z.ZodString>;
|
|
185
207
|
}, z.core.$strict>;
|
|
186
208
|
export declare const mulmoImageMediaSchema: z.ZodObject<{
|
|
187
209
|
type: z.ZodLiteral<"image">;
|
|
@@ -203,6 +225,7 @@ export declare const mulmoTextSlideMediaSchema: z.ZodObject<{
|
|
|
203
225
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
204
226
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
205
227
|
}, z.core.$strip>;
|
|
228
|
+
style: z.ZodOptional<z.ZodString>;
|
|
206
229
|
}, z.core.$strict>;
|
|
207
230
|
export declare const captionSplitSchema: z.ZodDefault<z.ZodEnum<{
|
|
208
231
|
none: "none";
|
|
@@ -270,7 +293,17 @@ export declare const mulmoVisionMediaSchema: z.ZodObject<{
|
|
|
270
293
|
}, z.core.$strict>;
|
|
271
294
|
export declare const mulmoImageAssetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
272
295
|
type: z.ZodLiteral<"markdown">;
|
|
273
|
-
markdown: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]
|
|
296
|
+
markdown: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodIntersection<z.ZodObject<{
|
|
297
|
+
header: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
298
|
+
"sidebar-left": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
299
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodObject<{
|
|
300
|
+
"row-2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
301
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
302
|
+
"2x2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
303
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
304
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
305
|
+
}, z.core.$strip>]>>]>;
|
|
306
|
+
style: z.ZodOptional<z.ZodString>;
|
|
274
307
|
}, z.core.$strict>, z.ZodObject<{
|
|
275
308
|
type: z.ZodLiteral<"web">;
|
|
276
309
|
url: z.ZodURL;
|
|
@@ -329,6 +362,7 @@ export declare const mulmoImageAssetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
329
362
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
330
363
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
331
364
|
}, z.core.$strip>;
|
|
365
|
+
style: z.ZodOptional<z.ZodString>;
|
|
332
366
|
}, z.core.$strict>, z.ZodObject<{
|
|
333
367
|
type: z.ZodLiteral<"chart">;
|
|
334
368
|
title: z.ZodString;
|
|
@@ -796,7 +830,17 @@ export declare const mulmoBeatSchema: z.ZodObject<{
|
|
|
796
830
|
description: z.ZodOptional<z.ZodString>;
|
|
797
831
|
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
798
832
|
type: z.ZodLiteral<"markdown">;
|
|
799
|
-
markdown: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]
|
|
833
|
+
markdown: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodIntersection<z.ZodObject<{
|
|
834
|
+
header: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
835
|
+
"sidebar-left": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
836
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodObject<{
|
|
837
|
+
"row-2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
838
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
839
|
+
"2x2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
840
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
841
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
842
|
+
}, z.core.$strip>]>>]>;
|
|
843
|
+
style: z.ZodOptional<z.ZodString>;
|
|
800
844
|
}, z.core.$strict>, z.ZodObject<{
|
|
801
845
|
type: z.ZodLiteral<"web">;
|
|
802
846
|
url: z.ZodURL;
|
|
@@ -855,6 +899,7 @@ export declare const mulmoBeatSchema: z.ZodObject<{
|
|
|
855
899
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
856
900
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
857
901
|
}, z.core.$strip>;
|
|
902
|
+
style: z.ZodOptional<z.ZodString>;
|
|
858
903
|
}, z.core.$strict>, z.ZodObject<{
|
|
859
904
|
type: z.ZodLiteral<"chart">;
|
|
860
905
|
title: z.ZodString;
|
|
@@ -1980,7 +2025,17 @@ export declare const mulmoScriptSchema: z.ZodObject<{
|
|
|
1980
2025
|
description: z.ZodOptional<z.ZodString>;
|
|
1981
2026
|
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
1982
2027
|
type: z.ZodLiteral<"markdown">;
|
|
1983
|
-
markdown: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]
|
|
2028
|
+
markdown: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodIntersection<z.ZodObject<{
|
|
2029
|
+
header: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
2030
|
+
"sidebar-left": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
2031
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodObject<{
|
|
2032
|
+
"row-2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
2033
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
2034
|
+
"2x2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
2035
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
2036
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
2037
|
+
}, z.core.$strip>]>>]>;
|
|
2038
|
+
style: z.ZodOptional<z.ZodString>;
|
|
1984
2039
|
}, z.core.$strict>, z.ZodObject<{
|
|
1985
2040
|
type: z.ZodLiteral<"web">;
|
|
1986
2041
|
url: z.ZodURL;
|
|
@@ -2039,6 +2094,7 @@ export declare const mulmoScriptSchema: z.ZodObject<{
|
|
|
2039
2094
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
2040
2095
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2041
2096
|
}, z.core.$strip>;
|
|
2097
|
+
style: z.ZodOptional<z.ZodString>;
|
|
2042
2098
|
}, z.core.$strict>, z.ZodObject<{
|
|
2043
2099
|
type: z.ZodLiteral<"chart">;
|
|
2044
2100
|
title: z.ZodString;
|
|
@@ -2868,7 +2924,17 @@ export declare const mulmoStudioSchema: z.ZodObject<{
|
|
|
2868
2924
|
description: z.ZodOptional<z.ZodString>;
|
|
2869
2925
|
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
2870
2926
|
type: z.ZodLiteral<"markdown">;
|
|
2871
|
-
markdown: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]
|
|
2927
|
+
markdown: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodIntersection<z.ZodObject<{
|
|
2928
|
+
header: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
2929
|
+
"sidebar-left": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
2930
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodObject<{
|
|
2931
|
+
"row-2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
2932
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
2933
|
+
"2x2": z.ZodTuple<[z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>], null>;
|
|
2934
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
2935
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
2936
|
+
}, z.core.$strip>]>>]>;
|
|
2937
|
+
style: z.ZodOptional<z.ZodString>;
|
|
2872
2938
|
}, z.core.$strict>, z.ZodObject<{
|
|
2873
2939
|
type: z.ZodLiteral<"web">;
|
|
2874
2940
|
url: z.ZodURL;
|
|
@@ -2927,6 +2993,7 @@ export declare const mulmoStudioSchema: z.ZodObject<{
|
|
|
2927
2993
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
2928
2994
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2929
2995
|
}, z.core.$strip>;
|
|
2996
|
+
style: z.ZodOptional<z.ZodString>;
|
|
2930
2997
|
}, z.core.$strict>, z.ZodObject<{
|
|
2931
2998
|
type: z.ZodLiteral<"chart">;
|
|
2932
2999
|
title: z.ZodString;
|
package/lib/types/schema.js
CHANGED
|
@@ -75,10 +75,30 @@ export const mediaSourceMermaidSchema = z.discriminatedUnion("kind", [
|
|
|
75
75
|
]);
|
|
76
76
|
// String is easier for AI, string array is easier for human
|
|
77
77
|
const stringOrStringArray = z.union([z.string(), z.array(z.string())]);
|
|
78
|
+
export const row2Schema = z.tuple([
|
|
79
|
+
stringOrStringArray, // left
|
|
80
|
+
stringOrStringArray, // right
|
|
81
|
+
]);
|
|
82
|
+
export const grid2x2Schema = z.tuple([
|
|
83
|
+
stringOrStringArray, // top-left
|
|
84
|
+
stringOrStringArray, // top-right
|
|
85
|
+
stringOrStringArray, // bottom-left
|
|
86
|
+
stringOrStringArray, // bottom-right
|
|
87
|
+
]);
|
|
88
|
+
// Frame: optional header and sidebar
|
|
89
|
+
const layoutFrameSchema = z.object({
|
|
90
|
+
header: stringOrStringArray.optional(),
|
|
91
|
+
"sidebar-left": stringOrStringArray.optional(),
|
|
92
|
+
});
|
|
93
|
+
// Main: exactly one of row-2, 2x2, or content
|
|
94
|
+
const layoutMainSchema = z.union([z.object({ "row-2": row2Schema }), z.object({ "2x2": grid2x2Schema }), z.object({ content: stringOrStringArray })]);
|
|
95
|
+
// Combine frame + main (loose validation - extra properties not rejected at schema level)
|
|
96
|
+
export const markdownLayoutSchema = layoutFrameSchema.and(layoutMainSchema);
|
|
78
97
|
export const mulmoMarkdownMediaSchema = z
|
|
79
98
|
.object({
|
|
80
99
|
type: z.literal("markdown"),
|
|
81
|
-
markdown: stringOrStringArray,
|
|
100
|
+
markdown: z.union([stringOrStringArray, markdownLayoutSchema]),
|
|
101
|
+
style: z.string().optional(),
|
|
82
102
|
})
|
|
83
103
|
.strict();
|
|
84
104
|
const mulmoWebMediaSchema = z
|
|
@@ -119,6 +139,7 @@ export const mulmoTextSlideMediaSchema = z
|
|
|
119
139
|
subtitle: z.string().optional(),
|
|
120
140
|
bullets: z.array(z.string()).optional(),
|
|
121
141
|
}),
|
|
142
|
+
style: z.string().optional(),
|
|
122
143
|
})
|
|
123
144
|
.strict();
|
|
124
145
|
export const captionSplitSchema = z.enum(["none", "estimate"]).default("none");
|
package/lib/types/type.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CallbackFunction } from "graphai";
|
|
2
|
-
import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualArraySchema, mulmoStudioMultiLingualDataSchema, mulmoStudioMultiLingualFileSchema, speakerDictionarySchema, speakerSchema, mulmoSpeechParamsSchema, mulmoImageParamsSchema, mulmoImageParamsImagesValueSchema, mulmoImageParamsImagesSchema, mulmoFillOptionSchema, mulmoTransitionSchema, mulmoVideoFilterSchema, mulmoMovieParamsSchema, mulmoSoundEffectParamsSchema, mulmoLipSyncParamsSchema, textSlideParamsSchema, speechOptionsSchema, speakerDataSchema, mulmoCanvasDimensionSchema, mulmoPromptTemplateSchema, mulmoPromptTemplateFileSchema, text2ImageProviderSchema, text2HtmlImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoImageAssetSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema, mediaSourceMermaidSchema, mulmoSessionStateSchema, mulmoOpenAIImageModelSchema, mulmoGoogleImageModelSchema, mulmoGoogleMovieModelSchema, mulmoReplicateMovieModelSchema, mulmoImagePromptMediaSchema } from "./schema.js";
|
|
2
|
+
import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualArraySchema, mulmoStudioMultiLingualDataSchema, mulmoStudioMultiLingualFileSchema, speakerDictionarySchema, speakerSchema, mulmoSpeechParamsSchema, mulmoImageParamsSchema, mulmoImageParamsImagesValueSchema, mulmoImageParamsImagesSchema, mulmoFillOptionSchema, mulmoTransitionSchema, mulmoVideoFilterSchema, mulmoMovieParamsSchema, mulmoSoundEffectParamsSchema, mulmoLipSyncParamsSchema, textSlideParamsSchema, speechOptionsSchema, speakerDataSchema, mulmoCanvasDimensionSchema, mulmoPromptTemplateSchema, mulmoPromptTemplateFileSchema, text2ImageProviderSchema, text2HtmlImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoImageAssetSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema, mediaSourceMermaidSchema, mulmoSessionStateSchema, mulmoOpenAIImageModelSchema, mulmoGoogleImageModelSchema, mulmoGoogleMovieModelSchema, mulmoReplicateMovieModelSchema, mulmoImagePromptMediaSchema, markdownLayoutSchema, row2Schema, grid2x2Schema } from "./schema.js";
|
|
3
3
|
import { pdf_modes, pdf_sizes, storyToScriptGenerateMode } from "./const.js";
|
|
4
4
|
import type { LLM } from "./provider2agent.js";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -46,6 +46,9 @@ export type MulmoGoogleImageModel = z.infer<typeof mulmoGoogleImageModelSchema>;
|
|
|
46
46
|
export type MulmoGoogleMovieModel = z.infer<typeof mulmoGoogleMovieModelSchema>;
|
|
47
47
|
export type MulmoReplicateMovieModel = z.infer<typeof mulmoReplicateMovieModelSchema>;
|
|
48
48
|
export type MulmoImagePromptMedia = z.infer<typeof mulmoImagePromptMediaSchema>;
|
|
49
|
+
export type MulmoMarkdownLayout = z.infer<typeof markdownLayoutSchema>;
|
|
50
|
+
export type MulmoRow2 = z.infer<typeof row2Schema>;
|
|
51
|
+
export type MulmoGrid2x2 = z.infer<typeof grid2x2Schema>;
|
|
49
52
|
export type MulmoImageAsset = z.infer<typeof mulmoImageAssetSchema>;
|
|
50
53
|
export type MulmoTextSlideMedia = z.infer<typeof mulmoTextSlideMediaSchema>;
|
|
51
54
|
export type MulmoMarkdownMedia = z.infer<typeof mulmoMarkdownMediaSchema>;
|
package/lib/utils/context.d.ts
CHANGED
|
@@ -274,7 +274,17 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
|
|
|
274
274
|
};
|
|
275
275
|
} | {
|
|
276
276
|
type: "markdown";
|
|
277
|
-
markdown: string | string[]
|
|
277
|
+
markdown: string | string[] | ({
|
|
278
|
+
header?: string | string[] | undefined;
|
|
279
|
+
"sidebar-left"?: string | string[] | undefined;
|
|
280
|
+
} & ({
|
|
281
|
+
"row-2": [string | string[], string | string[]];
|
|
282
|
+
} | {
|
|
283
|
+
"2x2": [string | string[], string | string[], string | string[], string | string[]];
|
|
284
|
+
} | {
|
|
285
|
+
content: string | string[];
|
|
286
|
+
}));
|
|
287
|
+
style?: string | undefined;
|
|
278
288
|
} | {
|
|
279
289
|
type: "web";
|
|
280
290
|
url: string;
|
|
@@ -321,6 +331,7 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
|
|
|
321
331
|
subtitle?: string | undefined;
|
|
322
332
|
bullets?: string[] | undefined;
|
|
323
333
|
};
|
|
334
|
+
style?: string | undefined;
|
|
324
335
|
} | {
|
|
325
336
|
type: "chart";
|
|
326
337
|
title: string;
|
|
@@ -930,7 +941,17 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
930
941
|
};
|
|
931
942
|
} | {
|
|
932
943
|
type: "markdown";
|
|
933
|
-
markdown: string | string[]
|
|
944
|
+
markdown: string | string[] | ({
|
|
945
|
+
header?: string | string[] | undefined;
|
|
946
|
+
"sidebar-left"?: string | string[] | undefined;
|
|
947
|
+
} & ({
|
|
948
|
+
"row-2": [string | string[], string | string[]];
|
|
949
|
+
} | {
|
|
950
|
+
"2x2": [string | string[], string | string[], string | string[], string | string[]];
|
|
951
|
+
} | {
|
|
952
|
+
content: string | string[];
|
|
953
|
+
}));
|
|
954
|
+
style?: string | undefined;
|
|
934
955
|
} | {
|
|
935
956
|
type: "web";
|
|
936
957
|
url: string;
|
|
@@ -977,6 +998,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
977
998
|
subtitle?: string | undefined;
|
|
978
999
|
bullets?: string[] | undefined;
|
|
979
1000
|
};
|
|
1001
|
+
style?: string | undefined;
|
|
980
1002
|
} | {
|
|
981
1003
|
type: "chart";
|
|
982
1004
|
title: string;
|
package/lib/utils/html_render.js
CHANGED
|
@@ -8,15 +8,23 @@ export const renderHTMLToImage = async (html, outputPath, width, height, isMerma
|
|
|
8
8
|
});
|
|
9
9
|
const page = await browser.newPage();
|
|
10
10
|
// Set the page content to the HTML generated from the Markdown
|
|
11
|
-
|
|
11
|
+
// Use networkidle0 only for external images, otherwise use domcontentloaded for faster rendering
|
|
12
|
+
const hasExternalImages = html.includes("<img") && /src=["']https?:\/\//.test(html);
|
|
13
|
+
const waitUntil = hasExternalImages ? "networkidle0" : "domcontentloaded";
|
|
14
|
+
await page.setContent(html, { waitUntil, timeout: 30000 });
|
|
12
15
|
// Adjust page settings if needed (like width, height, etc.)
|
|
13
16
|
await page.setViewport({ width, height });
|
|
14
|
-
// height:100% ensures background fills viewport;
|
|
15
|
-
await page.addStyleTag({ content: "html
|
|
17
|
+
// height:100% ensures background fills viewport; only reset html, let body styles come from custom CSS
|
|
18
|
+
await page.addStyleTag({ content: "html{height:100%;margin:0;padding:0;overflow:hidden}" });
|
|
16
19
|
if (isMermaid) {
|
|
20
|
+
// Wait for mermaid library to load from CDN
|
|
21
|
+
await page.waitForFunction(() => typeof window.mermaid !== "undefined", { timeout: 20000 });
|
|
22
|
+
// Wait until all mermaid elements have SVG rendered
|
|
17
23
|
await page.waitForFunction(() => {
|
|
18
|
-
const
|
|
19
|
-
|
|
24
|
+
const elements = document.querySelectorAll(".mermaid");
|
|
25
|
+
if (elements.length === 0)
|
|
26
|
+
return true;
|
|
27
|
+
return Array.from(elements).every((el) => el.querySelector("svg") !== null);
|
|
20
28
|
}, { timeout: 20000 });
|
|
21
29
|
}
|
|
22
30
|
// Wait for Chart.js to finish rendering if this is a chart
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getHTMLFile } from "../file.js";
|
|
2
2
|
import { renderHTMLToImage, interpolate } from "../html_render.js";
|
|
3
|
-
import { parrotingImagePath } from "./utils.js";
|
|
4
|
-
import nodeProcess from "node:process";
|
|
3
|
+
import { parrotingImagePath, generateUniqueId } from "./utils.js";
|
|
5
4
|
export const imageType = "chart";
|
|
6
5
|
const processChart = async (params) => {
|
|
7
6
|
const { beat, imagePath, canvasSize, textSlideStyle } = params;
|
|
@@ -28,9 +27,7 @@ const dumpHtml = async (params) => {
|
|
|
28
27
|
return;
|
|
29
28
|
const chartData = JSON.stringify(beat.image.chartData, null, 2);
|
|
30
29
|
const title = beat.image.title || "Chart";
|
|
31
|
-
|
|
32
|
-
// eslint-disable-next-line sonarjs/pseudo-random
|
|
33
|
-
const chartId = nodeProcess.env.NODE_ENV === "test" ? "id" : `chart-${Math.random().toString(36).substr(2, 9)}`;
|
|
30
|
+
const chartId = generateUniqueId("chart");
|
|
34
31
|
return `
|
|
35
32
|
<div class="chart-container mb-6">
|
|
36
33
|
<h3 class="text-xl font-semibold mb-4">${title}</h3>
|
|
@@ -1,24 +1,72 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { getHTMLFile } from "../file.js";
|
|
2
|
+
import { renderHTMLToImage, interpolate } from "../html_render.js";
|
|
3
|
+
import { parrotingImagePath, resolveStyle } from "./utils.js";
|
|
4
|
+
import { generateLayoutHtml, layoutToMarkdown, toMarkdownString, parseMarkdown } from "./markdown_layout.js";
|
|
5
|
+
import { isObject } from "graphai";
|
|
4
6
|
export const imageType = "markdown";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
// Type guard for object (data) format
|
|
8
|
+
const isMarkdownLayout = (md) => {
|
|
9
|
+
return isObject(md) && !Array.isArray(md);
|
|
10
|
+
};
|
|
11
|
+
// Generate markdown in order: header → sidebar-left → content
|
|
12
|
+
const dumpMarkdown = (params) => {
|
|
13
|
+
const { beat } = params;
|
|
7
14
|
if (!beat.image || beat.image.type !== imageType)
|
|
8
15
|
return;
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
const md = beat.image.markdown;
|
|
17
|
+
// text | text[] format
|
|
18
|
+
if (!isMarkdownLayout(md)) {
|
|
19
|
+
return toMarkdownString(md);
|
|
20
|
+
}
|
|
21
|
+
// object (data) format
|
|
22
|
+
return layoutToMarkdown(md);
|
|
12
23
|
};
|
|
13
|
-
|
|
24
|
+
// Generate full HTML for rendering
|
|
25
|
+
const generateHtml = async (params) => {
|
|
14
26
|
const { beat } = params;
|
|
27
|
+
if (!beat.image || beat.image.type !== imageType)
|
|
28
|
+
return "";
|
|
29
|
+
const md = beat.image.markdown;
|
|
30
|
+
const style = resolveStyle(beat.image.style, params.textSlideStyle);
|
|
31
|
+
if (isMarkdownLayout(md)) {
|
|
32
|
+
const htmlBody = await generateLayoutHtml(md);
|
|
33
|
+
const template = getHTMLFile("tailwind");
|
|
34
|
+
return interpolate(template, {
|
|
35
|
+
title: "Markdown Layout",
|
|
36
|
+
html_body: htmlBody,
|
|
37
|
+
custom_style: style,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const markdown = dumpMarkdown(params) ?? "";
|
|
41
|
+
const body = await parseMarkdown(markdown);
|
|
42
|
+
return `<html><head><style>${style}</style></head><body>${body}</body></html>`;
|
|
43
|
+
};
|
|
44
|
+
// Check if markdown content contains mermaid code blocks
|
|
45
|
+
const containsMermaid = (md) => {
|
|
46
|
+
const text = isMarkdownLayout(md) ? layoutToMarkdown(md) : toMarkdownString(md);
|
|
47
|
+
return text.includes("```mermaid");
|
|
48
|
+
};
|
|
49
|
+
const processMarkdown = async (params) => {
|
|
50
|
+
const { beat, imagePath, canvasSize } = params;
|
|
15
51
|
if (!beat.image || beat.image.type !== imageType)
|
|
16
52
|
return;
|
|
17
|
-
|
|
53
|
+
const html = await generateHtml(params);
|
|
54
|
+
const hasMermaid = containsMermaid(beat.image.markdown);
|
|
55
|
+
await renderHTMLToImage(html, imagePath, canvasSize.width, canvasSize.height, hasMermaid);
|
|
56
|
+
return imagePath;
|
|
18
57
|
};
|
|
19
58
|
const dumpHtml = async (params) => {
|
|
20
|
-
const
|
|
21
|
-
|
|
59
|
+
const { beat } = params;
|
|
60
|
+
if (!beat.image || beat.image.type !== imageType)
|
|
61
|
+
return "";
|
|
62
|
+
const md = beat.image.markdown;
|
|
63
|
+
if (isMarkdownLayout(md)) {
|
|
64
|
+
return await generateLayoutHtml(md);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const markdown = dumpMarkdown(params);
|
|
68
|
+
return await parseMarkdown(markdown ?? "");
|
|
69
|
+
}
|
|
22
70
|
};
|
|
23
71
|
export const process = processMarkdown;
|
|
24
72
|
export const path = parrotingImagePath;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type MulmoMarkdownLayout } from "../../types/type.js";
|
|
2
|
+
declare const toMarkdownString: (content: string | string[]) => string;
|
|
3
|
+
declare const parseMarkdown: (content: string | string[]) => Promise<string>;
|
|
4
|
+
export declare const generateLayoutHtml: (md: MulmoMarkdownLayout) => Promise<string>;
|
|
5
|
+
export declare const layoutToMarkdown: (md: MulmoMarkdownLayout) => string;
|
|
6
|
+
export { toMarkdownString, parseMarkdown };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { marked } from "marked";
|
|
2
|
+
import { generateMermaidHtml } from "./mermaid.js";
|
|
3
|
+
// Regex to match mermaid code blocks
|
|
4
|
+
const mermaidBlockRegex = /```mermaid\n([\s\S]*?)```/g;
|
|
5
|
+
// Convert string or string array to markdown string
|
|
6
|
+
const toMarkdownString = (content) => {
|
|
7
|
+
if (Array.isArray(content)) {
|
|
8
|
+
return content.join("\n");
|
|
9
|
+
}
|
|
10
|
+
return content;
|
|
11
|
+
};
|
|
12
|
+
// Replace mermaid code blocks with rendered HTML
|
|
13
|
+
const convertMermaidBlocks = (text) => {
|
|
14
|
+
return text.replace(mermaidBlockRegex, (_match, code) => {
|
|
15
|
+
return generateMermaidHtml(code.trim());
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
// Parse markdown content to HTML (with mermaid support)
|
|
19
|
+
const parseMarkdown = async (content) => {
|
|
20
|
+
const text = toMarkdownString(content);
|
|
21
|
+
const textWithMermaidHtml = convertMermaidBlocks(text);
|
|
22
|
+
return await marked.parse(textWithMermaidHtml);
|
|
23
|
+
};
|
|
24
|
+
// Generate header HTML
|
|
25
|
+
const generateHeaderHtml = async (data) => {
|
|
26
|
+
const headerHtml = await parseMarkdown(data);
|
|
27
|
+
return `
|
|
28
|
+
<div class="shrink-0 px-8 py-4 border-b border-gray-200 bg-gray-50">
|
|
29
|
+
<div class="prose prose-lg max-w-none">${headerHtml}</div>
|
|
30
|
+
</div>
|
|
31
|
+
`;
|
|
32
|
+
};
|
|
33
|
+
// Generate sidebar HTML
|
|
34
|
+
const generateSidebarHtml = async (data) => {
|
|
35
|
+
const sidebarHtml = await parseMarkdown(data);
|
|
36
|
+
return `
|
|
37
|
+
<div class="shrink-0 w-56 px-4 py-4 border-r border-gray-200 bg-gray-100 overflow-auto">
|
|
38
|
+
<div class="prose prose-sm max-w-none">${sidebarHtml}</div>
|
|
39
|
+
</div>
|
|
40
|
+
`;
|
|
41
|
+
};
|
|
42
|
+
// Generate row-2 layout HTML (two columns)
|
|
43
|
+
const generateRow2Html = async (data) => {
|
|
44
|
+
const [left, right] = data;
|
|
45
|
+
const leftHtml = await parseMarkdown(left);
|
|
46
|
+
const rightHtml = await parseMarkdown(right);
|
|
47
|
+
return `
|
|
48
|
+
<div class="h-full flex gap-6">
|
|
49
|
+
<div class="flex-1 overflow-auto">
|
|
50
|
+
<div class="prose max-w-none">${leftHtml}</div>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="flex-1 overflow-auto">
|
|
53
|
+
<div class="prose max-w-none">${rightHtml}</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
`;
|
|
57
|
+
};
|
|
58
|
+
// Generate 2x2 grid layout HTML
|
|
59
|
+
const generate2x2Html = async (data) => {
|
|
60
|
+
const [tl, tr, bl, br] = data;
|
|
61
|
+
const [tlHtml, trHtml, blHtml, brHtml] = await Promise.all([parseMarkdown(tl), parseMarkdown(tr), parseMarkdown(bl), parseMarkdown(br)]);
|
|
62
|
+
return `
|
|
63
|
+
<div class="h-full grid grid-cols-2 grid-rows-2 gap-4">
|
|
64
|
+
<div class="overflow-auto p-4 bg-gray-50 rounded-lg">
|
|
65
|
+
<div class="prose prose-sm max-w-none">${tlHtml}</div>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="overflow-auto p-4 bg-gray-50 rounded-lg">
|
|
68
|
+
<div class="prose prose-sm max-w-none">${trHtml}</div>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="overflow-auto p-4 bg-gray-50 rounded-lg">
|
|
71
|
+
<div class="prose prose-sm max-w-none">${blHtml}</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="overflow-auto p-4 bg-gray-50 rounded-lg">
|
|
74
|
+
<div class="prose prose-sm max-w-none">${brHtml}</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
`;
|
|
78
|
+
};
|
|
79
|
+
// Generate content HTML (single column)
|
|
80
|
+
const generateContentHtml = async (data) => {
|
|
81
|
+
const contentHtml = await parseMarkdown(data);
|
|
82
|
+
return `<div class="prose max-w-none">${contentHtml}</div>`;
|
|
83
|
+
};
|
|
84
|
+
// Generate Tailwind HTML for layout
|
|
85
|
+
export const generateLayoutHtml = async (md) => {
|
|
86
|
+
const parts = ['<div class="w-full h-full flex flex-col overflow-hidden">'];
|
|
87
|
+
if (md.header) {
|
|
88
|
+
parts.push(await generateHeaderHtml(md.header));
|
|
89
|
+
}
|
|
90
|
+
parts.push('<div class="flex-1 flex min-h-0 overflow-hidden">');
|
|
91
|
+
if (md["sidebar-left"]) {
|
|
92
|
+
parts.push(await generateSidebarHtml(md["sidebar-left"]));
|
|
93
|
+
}
|
|
94
|
+
parts.push('<div class="flex-1 p-6 overflow-auto">');
|
|
95
|
+
if ("row-2" in md) {
|
|
96
|
+
parts.push(await generateRow2Html(md["row-2"]));
|
|
97
|
+
}
|
|
98
|
+
else if ("2x2" in md) {
|
|
99
|
+
parts.push(await generate2x2Html(md["2x2"]));
|
|
100
|
+
}
|
|
101
|
+
else if ("content" in md) {
|
|
102
|
+
parts.push(await generateContentHtml(md.content));
|
|
103
|
+
}
|
|
104
|
+
parts.push("</div>", "</div>", "</div>");
|
|
105
|
+
return parts.join("");
|
|
106
|
+
};
|
|
107
|
+
// Convert layout to plain markdown string
|
|
108
|
+
export const layoutToMarkdown = (md) => {
|
|
109
|
+
const parts = [];
|
|
110
|
+
if (md.header) {
|
|
111
|
+
parts.push(toMarkdownString(md.header));
|
|
112
|
+
}
|
|
113
|
+
if (md["sidebar-left"]) {
|
|
114
|
+
parts.push(toMarkdownString(md["sidebar-left"]));
|
|
115
|
+
}
|
|
116
|
+
if ("row-2" in md) {
|
|
117
|
+
parts.push(...md["row-2"].map(toMarkdownString));
|
|
118
|
+
}
|
|
119
|
+
else if ("2x2" in md) {
|
|
120
|
+
parts.push(...md["2x2"].map(toMarkdownString));
|
|
121
|
+
}
|
|
122
|
+
else if ("content" in md) {
|
|
123
|
+
parts.push(toMarkdownString(md.content));
|
|
124
|
+
}
|
|
125
|
+
return parts.join("\n\n");
|
|
126
|
+
};
|
|
127
|
+
export { toMarkdownString, parseMarkdown };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ImageProcessorParams } from "../../types/index.js";
|
|
2
2
|
export declare const imageType = "mermaid";
|
|
3
|
+
export declare const generateMermaidHtml: (code: string, title?: string) => string;
|
|
3
4
|
export declare const process: (params: ImageProcessorParams) => Promise<string | undefined>;
|
|
4
5
|
export declare const path: (params: ImageProcessorParams) => string;
|
|
5
6
|
export declare const markdown: (params: ImageProcessorParams) => string | undefined;
|
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import { MulmoMediaSourceMethods } from "../../methods/index.js";
|
|
2
2
|
import { getHTMLFile } from "../file.js";
|
|
3
3
|
import { renderHTMLToImage, interpolate } from "../html_render.js";
|
|
4
|
-
import { parrotingImagePath } from "./utils.js";
|
|
5
|
-
import nodeProcess from "node:process";
|
|
4
|
+
import { parrotingImagePath, generateUniqueId } from "./utils.js";
|
|
6
5
|
export const imageType = "mermaid";
|
|
6
|
+
// Generate mermaid HTML from code string (shared utility)
|
|
7
|
+
export const generateMermaidHtml = (code, title) => {
|
|
8
|
+
const diagramId = generateUniqueId("mermaid");
|
|
9
|
+
const titleHtml = title ? `<h3 class="text-xl font-semibold mb-4">${title}</h3>` : "";
|
|
10
|
+
return `
|
|
11
|
+
<div class="mermaid-container mb-6">
|
|
12
|
+
${titleHtml}
|
|
13
|
+
<div class="flex justify-center">
|
|
14
|
+
<div id="${diagramId}" class="mermaid">
|
|
15
|
+
${code.trim()}
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>`;
|
|
19
|
+
};
|
|
7
20
|
const processMermaid = async (params) => {
|
|
8
21
|
const { beat, imagePath, canvasSize, context, textSlideStyle } = params;
|
|
9
22
|
if (!beat?.image || beat.image.type !== imageType)
|
|
@@ -38,17 +51,7 @@ const dumpHtml = async (params) => {
|
|
|
38
51
|
const title = beat.image.title || "Diagram";
|
|
39
52
|
const appendix = beat.image.appendix?.join("\n") || "";
|
|
40
53
|
const fullCode = `${diagramCode}\n${appendix}`.trim();
|
|
41
|
-
|
|
42
|
-
const diagramId = nodeProcess.env.NODE_ENV === "test" ? "id" : `mermaid-${Math.random().toString(36).substr(2, 9)}`;
|
|
43
|
-
return `
|
|
44
|
-
<div class="mermaid-container mb-6">
|
|
45
|
-
<h3 class="text-xl font-semibold mb-4">${title}</h3>
|
|
46
|
-
<div class="flex justify-center">
|
|
47
|
-
<div id="${diagramId}" class="mermaid">
|
|
48
|
-
${fullCode}
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
</div>`;
|
|
54
|
+
return generateMermaidHtml(fullCode, title);
|
|
52
55
|
};
|
|
53
56
|
export const process = processMermaid;
|
|
54
57
|
export const path = parrotingImagePath;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { renderMarkdownToImage } from "../html_render.js";
|
|
2
|
-
import { parrotingImagePath } from "./utils.js";
|
|
2
|
+
import { parrotingImagePath, resolveStyle } from "./utils.js";
|
|
3
3
|
import { marked } from "marked";
|
|
4
4
|
export const imageType = "textSlide";
|
|
5
5
|
const processTextSlide = async (params) => {
|
|
@@ -7,6 +7,7 @@ const processTextSlide = async (params) => {
|
|
|
7
7
|
if (!beat.image || beat.image.type !== imageType)
|
|
8
8
|
return;
|
|
9
9
|
const slide = beat.image.slide;
|
|
10
|
+
const style = resolveStyle(beat.image.style, textSlideStyle);
|
|
10
11
|
const markdown = dumpMarkdown(params) ?? "";
|
|
11
12
|
const topMargin = (() => {
|
|
12
13
|
if (slide.bullets?.length && slide.bullets.length > 0) {
|
|
@@ -15,7 +16,7 @@ const processTextSlide = async (params) => {
|
|
|
15
16
|
const marginTop = slide.subtitle ? canvasSize.height * 0.4 : canvasSize.height * 0.45;
|
|
16
17
|
return `body {margin-top: ${marginTop}px;}`;
|
|
17
18
|
})();
|
|
18
|
-
await renderMarkdownToImage(markdown,
|
|
19
|
+
await renderMarkdownToImage(markdown, style + topMargin, imagePath, canvasSize.width, canvasSize.height);
|
|
19
20
|
return imagePath;
|
|
20
21
|
};
|
|
21
22
|
const dumpMarkdown = (params) => {
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { ImageProcessorParams } from "../../types/index.js";
|
|
2
2
|
export declare const parrotingImagePath: (params: ImageProcessorParams) => string;
|
|
3
|
+
export declare const resolveStyle: (styleName: string | undefined, fallbackStyle: string) => string;
|
|
4
|
+
export declare const generateUniqueId: (prefix: string) => string;
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
import { getMarkdownStyle } from "../../data/markdownStyles.js";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import nodeProcess from "node:process";
|
|
1
4
|
export const parrotingImagePath = (params) => {
|
|
2
5
|
return params.imagePath;
|
|
3
6
|
};
|
|
7
|
+
export const resolveStyle = (styleName, fallbackStyle) => {
|
|
8
|
+
const customStyle = styleName ? getMarkdownStyle(styleName) : undefined;
|
|
9
|
+
return customStyle ? customStyle.css : fallbackStyle;
|
|
10
|
+
};
|
|
11
|
+
export const generateUniqueId = (prefix) => {
|
|
12
|
+
if (nodeProcess.env.NODE_ENV === "test") {
|
|
13
|
+
return "id";
|
|
14
|
+
}
|
|
15
|
+
return `${prefix}-${randomUUID().slice(0, 8)}`;
|
|
16
|
+
};
|