mulmocast 2.1.29 → 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/types/schema.d.ts +67 -5
- package/lib/types/schema.js +21 -1
- package/lib/types/type.d.ts +4 -1
- package/lib/utils/context.d.ts +22 -2
- package/lib/utils/html_render.js +11 -3
- package/lib/utils/image_plugins/chart.js +2 -5
- package/lib/utils/image_plugins/markdown.js +60 -17
- 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_markdown_layout.json +152 -0
- package/scripts/test/test_markdown_mermaid.json +58 -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/README.md
CHANGED
|
@@ -343,6 +343,50 @@ To force regeneration, delete the old files — including temporary files — un
|
|
|
343
343
|
|
|
344
344
|
If you modify the text or instruction fields in a MulmoScript, mulmo will automatically detect the changes and regenerate the corresponding audio content upon re-run.
|
|
345
345
|
|
|
346
|
+
## Markdown Slide Styles
|
|
347
|
+
|
|
348
|
+
MulmoCast includes 100 pre-designed CSS styles for markdown slides, organized in 10 categories:
|
|
349
|
+
|
|
350
|
+
| Category | Description | Example Styles |
|
|
351
|
+
|----------|-------------|----------------|
|
|
352
|
+
| business | Professional corporate designs | corporate-blue, executive-gray, finance-green |
|
|
353
|
+
| tech | Technology and developer themes | cyber-neon, matrix-green, terminal-dark |
|
|
354
|
+
| creative | Artistic and expressive styles | artistic-splash, watercolor-soft, graffiti |
|
|
355
|
+
| minimalist | Clean and simple designs | clean-white, zen-beige, nordic-light |
|
|
356
|
+
| nature | Nature-inspired themes | forest-green, ocean-blue, sunset-orange |
|
|
357
|
+
| dark | Dark mode and elegant themes | charcoal-elegant, midnight-blue, obsidian |
|
|
358
|
+
| colorful | Vibrant and bold colors | vibrant-pink, candy-colors, aurora |
|
|
359
|
+
| vintage | Retro and classic styles | retro-70s, art-deco, typewriter |
|
|
360
|
+
| japanese | Japanese aesthetic designs | washi-paper, sakura-pink, zen-garden |
|
|
361
|
+
| geometric | Pattern-based designs | hexagon-pattern, isometric, bauhaus |
|
|
362
|
+
|
|
363
|
+
### Usage
|
|
364
|
+
|
|
365
|
+
Add the `style` property to a markdown beat:
|
|
366
|
+
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"beats": [
|
|
370
|
+
{
|
|
371
|
+
"text": "Corporate presentation slide",
|
|
372
|
+
"image": {
|
|
373
|
+
"type": "markdown",
|
|
374
|
+
"markdown": "# Quarterly Report\n\n## Key Highlights\n\n- Revenue up 15%\n- New market expansion\n- Team growth",
|
|
375
|
+
"style": "corporate-blue"
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Discover Available Styles
|
|
383
|
+
|
|
384
|
+
Use the `mulmo tool info` command to see all available styles:
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
mulmo tool info styles
|
|
388
|
+
```
|
|
389
|
+
|
|
346
390
|
## MulmoScript Format
|
|
347
391
|
|
|
348
392
|
MulmoScript is a JSON format to define podcast or video scripts:
|
|
@@ -569,6 +613,7 @@ Commands:
|
|
|
569
613
|
mulmo tool complete <file> Complete partial MulmoScript with defaults
|
|
570
614
|
mulmo tool prompt Dump prompt from template
|
|
571
615
|
mulmo tool schema Dump mulmocast schema
|
|
616
|
+
mulmo tool info [category] Show available options (styles, bgm, voices, etc.)
|
|
572
617
|
|
|
573
618
|
Options:
|
|
574
619
|
--version Show version number [boolean]
|
|
@@ -686,6 +731,38 @@ Examples:
|
|
|
686
731
|
mulmo tool complete input.json -t children_book
|
|
687
732
|
```
|
|
688
733
|
|
|
734
|
+
```
|
|
735
|
+
mulmo tool info [category]
|
|
736
|
+
|
|
737
|
+
Show available options for MulmoScript configuration
|
|
738
|
+
|
|
739
|
+
Positionals:
|
|
740
|
+
category Category to show info for
|
|
741
|
+
[string] [choices: "styles", "bgm", "templates", "voices", "images", "movies", "llm"]
|
|
742
|
+
|
|
743
|
+
Options:
|
|
744
|
+
--version Show version number [boolean]
|
|
745
|
+
-v, --verbose verbose log [boolean] [required] [default: false]
|
|
746
|
+
-h, --help Show help [boolean]
|
|
747
|
+
-F, --format Output format [string] [choices: "text", "json", "yaml"]
|
|
748
|
+
|
|
749
|
+
Examples:
|
|
750
|
+
# Show all available categories
|
|
751
|
+
mulmo tool info
|
|
752
|
+
|
|
753
|
+
# List all 100 markdown styles
|
|
754
|
+
mulmo tool info styles
|
|
755
|
+
|
|
756
|
+
# List available BGM assets
|
|
757
|
+
mulmo tool info bgm
|
|
758
|
+
|
|
759
|
+
# List TTS providers and voices
|
|
760
|
+
mulmo tool info voices
|
|
761
|
+
|
|
762
|
+
# Output as JSON for programmatic use
|
|
763
|
+
mulmo tool info styles --format json
|
|
764
|
+
```
|
|
765
|
+
|
|
689
766
|
|
|
690
767
|
|
|
691
768
|
## Contributing
|
|
@@ -7,6 +7,39 @@
|
|
|
7
7
|
<title>${title}</title>
|
|
8
8
|
<!-- Tailwind CSS CDN -->
|
|
9
9
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
10
|
+
<!-- Mermaid CDN for embedded diagrams -->
|
|
11
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
12
|
+
<script>
|
|
13
|
+
mermaid.initialize({
|
|
14
|
+
startOnLoad: true,
|
|
15
|
+
theme: 'default',
|
|
16
|
+
flowchart: { useMaxWidth: true }
|
|
17
|
+
});
|
|
18
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
19
|
+
const mermaidElements = document.querySelectorAll(".mermaid");
|
|
20
|
+
if (mermaidElements.length > 0) {
|
|
21
|
+
mermaid.init(undefined, ".mermaid");
|
|
22
|
+
mermaidElements.forEach(el => el.dataset.ready = "true");
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
</script>
|
|
26
|
+
<style>
|
|
27
|
+
/* Mermaid diagram styling */
|
|
28
|
+
.mermaid {
|
|
29
|
+
display: flex;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
align-items: center;
|
|
32
|
+
width: 100%;
|
|
33
|
+
min-height: 100px;
|
|
34
|
+
}
|
|
35
|
+
.mermaid svg {
|
|
36
|
+
max-width: 100%;
|
|
37
|
+
max-height: 100%;
|
|
38
|
+
width: auto;
|
|
39
|
+
height: auto;
|
|
40
|
+
}
|
|
41
|
+
${custom_style}
|
|
42
|
+
</style>
|
|
10
43
|
</head>
|
|
11
44
|
<body class="bg-white text-gray-800 h-full flex flex-col">
|
|
12
45
|
${html_body}
|
package/lib/types/schema.d.ts
CHANGED
|
@@ -179,9 +179,30 @@ 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>]>>]>;
|
|
185
206
|
style: z.ZodOptional<z.ZodString>;
|
|
186
207
|
}, z.core.$strict>;
|
|
187
208
|
export declare const mulmoImageMediaSchema: z.ZodObject<{
|
|
@@ -204,6 +225,7 @@ export declare const mulmoTextSlideMediaSchema: z.ZodObject<{
|
|
|
204
225
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
205
226
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
206
227
|
}, z.core.$strip>;
|
|
228
|
+
style: z.ZodOptional<z.ZodString>;
|
|
207
229
|
}, z.core.$strict>;
|
|
208
230
|
export declare const captionSplitSchema: z.ZodDefault<z.ZodEnum<{
|
|
209
231
|
none: "none";
|
|
@@ -271,7 +293,16 @@ export declare const mulmoVisionMediaSchema: z.ZodObject<{
|
|
|
271
293
|
}, z.core.$strict>;
|
|
272
294
|
export declare const mulmoImageAssetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
273
295
|
type: z.ZodLiteral<"markdown">;
|
|
274
|
-
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>]>>]>;
|
|
275
306
|
style: z.ZodOptional<z.ZodString>;
|
|
276
307
|
}, z.core.$strict>, z.ZodObject<{
|
|
277
308
|
type: z.ZodLiteral<"web">;
|
|
@@ -331,6 +362,7 @@ export declare const mulmoImageAssetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
331
362
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
332
363
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
333
364
|
}, z.core.$strip>;
|
|
365
|
+
style: z.ZodOptional<z.ZodString>;
|
|
334
366
|
}, z.core.$strict>, z.ZodObject<{
|
|
335
367
|
type: z.ZodLiteral<"chart">;
|
|
336
368
|
title: z.ZodString;
|
|
@@ -798,7 +830,16 @@ export declare const mulmoBeatSchema: z.ZodObject<{
|
|
|
798
830
|
description: z.ZodOptional<z.ZodString>;
|
|
799
831
|
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
800
832
|
type: z.ZodLiteral<"markdown">;
|
|
801
|
-
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>]>>]>;
|
|
802
843
|
style: z.ZodOptional<z.ZodString>;
|
|
803
844
|
}, z.core.$strict>, z.ZodObject<{
|
|
804
845
|
type: z.ZodLiteral<"web">;
|
|
@@ -858,6 +899,7 @@ export declare const mulmoBeatSchema: z.ZodObject<{
|
|
|
858
899
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
859
900
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
860
901
|
}, z.core.$strip>;
|
|
902
|
+
style: z.ZodOptional<z.ZodString>;
|
|
861
903
|
}, z.core.$strict>, z.ZodObject<{
|
|
862
904
|
type: z.ZodLiteral<"chart">;
|
|
863
905
|
title: z.ZodString;
|
|
@@ -1983,7 +2025,16 @@ export declare const mulmoScriptSchema: z.ZodObject<{
|
|
|
1983
2025
|
description: z.ZodOptional<z.ZodString>;
|
|
1984
2026
|
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
1985
2027
|
type: z.ZodLiteral<"markdown">;
|
|
1986
|
-
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>]>>]>;
|
|
1987
2038
|
style: z.ZodOptional<z.ZodString>;
|
|
1988
2039
|
}, z.core.$strict>, z.ZodObject<{
|
|
1989
2040
|
type: z.ZodLiteral<"web">;
|
|
@@ -2043,6 +2094,7 @@ export declare const mulmoScriptSchema: z.ZodObject<{
|
|
|
2043
2094
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
2044
2095
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2045
2096
|
}, z.core.$strip>;
|
|
2097
|
+
style: z.ZodOptional<z.ZodString>;
|
|
2046
2098
|
}, z.core.$strict>, z.ZodObject<{
|
|
2047
2099
|
type: z.ZodLiteral<"chart">;
|
|
2048
2100
|
title: z.ZodString;
|
|
@@ -2872,7 +2924,16 @@ export declare const mulmoStudioSchema: z.ZodObject<{
|
|
|
2872
2924
|
description: z.ZodOptional<z.ZodString>;
|
|
2873
2925
|
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
2874
2926
|
type: z.ZodLiteral<"markdown">;
|
|
2875
|
-
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>]>>]>;
|
|
2876
2937
|
style: z.ZodOptional<z.ZodString>;
|
|
2877
2938
|
}, z.core.$strict>, z.ZodObject<{
|
|
2878
2939
|
type: z.ZodLiteral<"web">;
|
|
@@ -2932,6 +2993,7 @@ export declare const mulmoStudioSchema: z.ZodObject<{
|
|
|
2932
2993
|
subtitle: z.ZodOptional<z.ZodString>;
|
|
2933
2994
|
bullets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2934
2995
|
}, z.core.$strip>;
|
|
2996
|
+
style: z.ZodOptional<z.ZodString>;
|
|
2935
2997
|
}, z.core.$strict>, z.ZodObject<{
|
|
2936
2998
|
type: z.ZodLiteral<"chart">;
|
|
2937
2999
|
title: z.ZodString;
|
package/lib/types/schema.js
CHANGED
|
@@ -75,10 +75,29 @@ 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]),
|
|
82
101
|
style: z.string().optional(),
|
|
83
102
|
})
|
|
84
103
|
.strict();
|
|
@@ -120,6 +139,7 @@ export const mulmoTextSlideMediaSchema = z
|
|
|
120
139
|
subtitle: z.string().optional(),
|
|
121
140
|
bullets: z.array(z.string()).optional(),
|
|
122
141
|
}),
|
|
142
|
+
style: z.string().optional(),
|
|
123
143
|
})
|
|
124
144
|
.strict();
|
|
125
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,16 @@ 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
|
+
}));
|
|
278
287
|
style?: string | undefined;
|
|
279
288
|
} | {
|
|
280
289
|
type: "web";
|
|
@@ -322,6 +331,7 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
|
|
|
322
331
|
subtitle?: string | undefined;
|
|
323
332
|
bullets?: string[] | undefined;
|
|
324
333
|
};
|
|
334
|
+
style?: string | undefined;
|
|
325
335
|
} | {
|
|
326
336
|
type: "chart";
|
|
327
337
|
title: string;
|
|
@@ -931,7 +941,16 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
931
941
|
};
|
|
932
942
|
} | {
|
|
933
943
|
type: "markdown";
|
|
934
|
-
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
|
+
}));
|
|
935
954
|
style?: string | undefined;
|
|
936
955
|
} | {
|
|
937
956
|
type: "web";
|
|
@@ -979,6 +998,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
979
998
|
subtitle?: string | undefined;
|
|
980
999
|
bullets?: string[] | undefined;
|
|
981
1000
|
};
|
|
1001
|
+
style?: string | undefined;
|
|
982
1002
|
} | {
|
|
983
1003
|
type: "chart";
|
|
984
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
17
|
// height:100% ensures background fills viewport; only reset html, let body styles come from custom CSS
|
|
15
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,29 +1,72 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
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";
|
|
5
6
|
export const imageType = "markdown";
|
|
6
|
-
|
|
7
|
-
|
|
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;
|
|
8
14
|
if (!beat.image || beat.image.type !== imageType)
|
|
9
15
|
return;
|
|
10
|
-
const
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return
|
|
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);
|
|
17
23
|
};
|
|
18
|
-
|
|
24
|
+
// Generate full HTML for rendering
|
|
25
|
+
const generateHtml = async (params) => {
|
|
19
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;
|
|
20
51
|
if (!beat.image || beat.image.type !== imageType)
|
|
21
52
|
return;
|
|
22
|
-
|
|
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;
|
|
23
57
|
};
|
|
24
58
|
const dumpHtml = async (params) => {
|
|
25
|
-
const
|
|
26
|
-
|
|
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
|
+
}
|
|
27
70
|
};
|
|
28
71
|
export const process = processMarkdown;
|
|
29
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 };
|