mulmocast 2.1.40 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/assets/schemas/html_prompt.json +60 -0
  3. package/assets/schemas/mulmo_script.json +283 -0
  4. package/assets/slide_themes/corporate.json +18 -0
  5. package/assets/slide_themes/creative.json +18 -0
  6. package/assets/slide_themes/dark.json +18 -0
  7. package/assets/slide_themes/minimal.json +18 -0
  8. package/assets/slide_themes/pop.json +18 -0
  9. package/assets/slide_themes/warm.json +18 -0
  10. package/assets/styles/akira_comic.json +22 -0
  11. package/assets/styles/ani.json +43 -0
  12. package/assets/styles/children_book.json +13 -0
  13. package/assets/styles/comic_strips.json +13 -0
  14. package/assets/styles/drslump_comic.json +22 -0
  15. package/assets/styles/ghibli_comic.json +22 -0
  16. package/assets/styles/ghibli_shorts.json +28 -0
  17. package/assets/styles/ghost_comic.json +29 -0
  18. package/assets/styles/leda.json +29 -0
  19. package/assets/styles/onepiece_comic.json +22 -0
  20. package/assets/styles/slide_corporate.json +30 -0
  21. package/assets/styles/slide_creative.json +30 -0
  22. package/assets/styles/slide_dark.json +30 -0
  23. package/assets/styles/slide_minimal.json +30 -0
  24. package/assets/styles/slide_pop.json +30 -0
  25. package/assets/styles/slide_warm.json +30 -0
  26. package/lib/actions/image_agents.d.ts +2 -1
  27. package/lib/actions/image_agents.js +3 -3
  28. package/lib/actions/images.d.ts +3 -1
  29. package/lib/actions/images.js +1 -0
  30. package/lib/data/index.d.ts +2 -0
  31. package/lib/data/index.js +2 -0
  32. package/lib/data/slideStyles.d.ts +206 -0
  33. package/lib/data/slideStyles.js +206 -0
  34. package/lib/data/slideThemes.d.ts +134 -0
  35. package/lib/data/slideThemes.js +134 -0
  36. package/lib/methods/mulmo_media_source.d.ts +1 -0
  37. package/lib/methods/mulmo_media_source.js +17 -3
  38. package/lib/slide/blocks.d.ts +2 -0
  39. package/lib/slide/blocks.js +54 -2
  40. package/lib/slide/index.d.ts +2 -2
  41. package/lib/slide/index.js +1 -1
  42. package/lib/slide/layouts/columns.js +4 -4
  43. package/lib/slide/layouts/comparison.js +4 -3
  44. package/lib/slide/layouts/grid.js +3 -3
  45. package/lib/slide/render.js +24 -1
  46. package/lib/slide/schema.d.ts +454 -0
  47. package/lib/slide/schema.js +19 -0
  48. package/lib/slide/utils.d.ts +12 -1
  49. package/lib/slide/utils.js +55 -2
  50. package/lib/types/schema.d.ts +448 -0
  51. package/lib/types/slide.d.ts +454 -0
  52. package/lib/types/slide.js +19 -0
  53. package/lib/types/type.d.ts +1 -0
  54. package/lib/utils/context.d.ts +182 -0
  55. package/lib/utils/html_render.js +44 -6
  56. package/lib/utils/image_plugins/slide.d.ts +14 -0
  57. package/lib/utils/image_plugins/slide.js +101 -2
  58. package/package.json +9 -2
  59. package/scripts/test/img_detector.png +0 -0
  60. package/scripts/test/img_higgs.png +0 -0
  61. package/scripts/test/img_lhc.png +0 -0
  62. package/scripts/test/test_slide_chart_mermaid.json +148 -0
  63. package/scripts/test/test_slide_image_ref.json +261 -0
  64. package/scripts/test/test_slide_image_ref_en.json +287 -0
@@ -331,6 +331,19 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
331
331
  src: string;
332
332
  alt?: string | undefined;
333
333
  fit?: "contain" | "cover" | undefined;
334
+ } | {
335
+ type: "imageRef";
336
+ ref: string;
337
+ alt?: string | undefined;
338
+ fit?: "contain" | "cover" | undefined;
339
+ } | {
340
+ type: "chart";
341
+ chartData: Record<string, unknown>;
342
+ title?: string | undefined;
343
+ } | {
344
+ type: "mermaid";
345
+ code: string;
346
+ title?: string | undefined;
334
347
  })[] | undefined;
335
348
  footer?: string | undefined;
336
349
  label?: string | undefined;
@@ -398,6 +411,19 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
398
411
  src: string;
399
412
  alt?: string | undefined;
400
413
  fit?: "contain" | "cover" | undefined;
414
+ } | {
415
+ type: "imageRef";
416
+ ref: string;
417
+ alt?: string | undefined;
418
+ fit?: "contain" | "cover" | undefined;
419
+ } | {
420
+ type: "chart";
421
+ chartData: Record<string, unknown>;
422
+ title?: string | undefined;
423
+ } | {
424
+ type: "mermaid";
425
+ code: string;
426
+ title?: string | undefined;
401
427
  })[] | undefined;
402
428
  footer?: string | undefined;
403
429
  };
@@ -441,6 +467,19 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
441
467
  src: string;
442
468
  alt?: string | undefined;
443
469
  fit?: "contain" | "cover" | undefined;
470
+ } | {
471
+ type: "imageRef";
472
+ ref: string;
473
+ alt?: string | undefined;
474
+ fit?: "contain" | "cover" | undefined;
475
+ } | {
476
+ type: "chart";
477
+ chartData: Record<string, unknown>;
478
+ title?: string | undefined;
479
+ } | {
480
+ type: "mermaid";
481
+ code: string;
482
+ title?: string | undefined;
444
483
  })[] | undefined;
445
484
  footer?: string | undefined;
446
485
  };
@@ -506,6 +545,19 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
506
545
  src: string;
507
546
  alt?: string | undefined;
508
547
  fit?: "contain" | "cover" | undefined;
548
+ } | {
549
+ type: "imageRef";
550
+ ref: string;
551
+ alt?: string | undefined;
552
+ fit?: "contain" | "cover" | undefined;
553
+ } | {
554
+ type: "chart";
555
+ chartData: Record<string, unknown>;
556
+ title?: string | undefined;
557
+ } | {
558
+ type: "mermaid";
559
+ code: string;
560
+ title?: string | undefined;
509
561
  })[] | undefined;
510
562
  }[];
511
563
  layout: "grid";
@@ -619,6 +671,19 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
619
671
  src: string;
620
672
  alt?: string | undefined;
621
673
  fit?: "contain" | "cover" | undefined;
674
+ } | {
675
+ type: "imageRef";
676
+ ref: string;
677
+ alt?: string | undefined;
678
+ fit?: "contain" | "cover" | undefined;
679
+ } | {
680
+ type: "chart";
681
+ chartData: Record<string, unknown>;
682
+ title?: string | undefined;
683
+ } | {
684
+ type: "mermaid";
685
+ code: string;
686
+ title?: string | undefined;
622
687
  })[] | undefined;
623
688
  dark?: boolean | undefined;
624
689
  ratio?: number | undefined;
@@ -665,6 +730,19 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
665
730
  src: string;
666
731
  alt?: string | undefined;
667
732
  fit?: "contain" | "cover" | undefined;
733
+ } | {
734
+ type: "imageRef";
735
+ ref: string;
736
+ alt?: string | undefined;
737
+ fit?: "contain" | "cover" | undefined;
738
+ } | {
739
+ type: "chart";
740
+ chartData: Record<string, unknown>;
741
+ title?: string | undefined;
742
+ } | {
743
+ type: "mermaid";
744
+ code: string;
745
+ title?: string | undefined;
668
746
  })[] | undefined;
669
747
  dark?: boolean | undefined;
670
748
  ratio?: number | undefined;
@@ -718,6 +796,19 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
718
796
  src: string;
719
797
  alt?: string | undefined;
720
798
  fit?: "contain" | "cover" | undefined;
799
+ } | {
800
+ type: "imageRef";
801
+ ref: string;
802
+ alt?: string | undefined;
803
+ fit?: "contain" | "cover" | undefined;
804
+ } | {
805
+ type: "chart";
806
+ chartData: Record<string, unknown>;
807
+ title?: string | undefined;
808
+ } | {
809
+ type: "mermaid";
810
+ code: string;
811
+ title?: string | undefined;
721
812
  })[] | undefined;
722
813
  accentColor?: "success" | "primary" | "accent" | "warning" | "danger" | "info" | "highlight" | undefined;
723
814
  }[];
@@ -1623,6 +1714,19 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
1623
1714
  src: string;
1624
1715
  alt?: string | undefined;
1625
1716
  fit?: "contain" | "cover" | undefined;
1717
+ } | {
1718
+ type: "imageRef";
1719
+ ref: string;
1720
+ alt?: string | undefined;
1721
+ fit?: "contain" | "cover" | undefined;
1722
+ } | {
1723
+ type: "chart";
1724
+ chartData: Record<string, unknown>;
1725
+ title?: string | undefined;
1726
+ } | {
1727
+ type: "mermaid";
1728
+ code: string;
1729
+ title?: string | undefined;
1626
1730
  })[] | undefined;
1627
1731
  footer?: string | undefined;
1628
1732
  label?: string | undefined;
@@ -1690,6 +1794,19 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
1690
1794
  src: string;
1691
1795
  alt?: string | undefined;
1692
1796
  fit?: "contain" | "cover" | undefined;
1797
+ } | {
1798
+ type: "imageRef";
1799
+ ref: string;
1800
+ alt?: string | undefined;
1801
+ fit?: "contain" | "cover" | undefined;
1802
+ } | {
1803
+ type: "chart";
1804
+ chartData: Record<string, unknown>;
1805
+ title?: string | undefined;
1806
+ } | {
1807
+ type: "mermaid";
1808
+ code: string;
1809
+ title?: string | undefined;
1693
1810
  })[] | undefined;
1694
1811
  footer?: string | undefined;
1695
1812
  };
@@ -1733,6 +1850,19 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
1733
1850
  src: string;
1734
1851
  alt?: string | undefined;
1735
1852
  fit?: "contain" | "cover" | undefined;
1853
+ } | {
1854
+ type: "imageRef";
1855
+ ref: string;
1856
+ alt?: string | undefined;
1857
+ fit?: "contain" | "cover" | undefined;
1858
+ } | {
1859
+ type: "chart";
1860
+ chartData: Record<string, unknown>;
1861
+ title?: string | undefined;
1862
+ } | {
1863
+ type: "mermaid";
1864
+ code: string;
1865
+ title?: string | undefined;
1736
1866
  })[] | undefined;
1737
1867
  footer?: string | undefined;
1738
1868
  };
@@ -1798,6 +1928,19 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
1798
1928
  src: string;
1799
1929
  alt?: string | undefined;
1800
1930
  fit?: "contain" | "cover" | undefined;
1931
+ } | {
1932
+ type: "imageRef";
1933
+ ref: string;
1934
+ alt?: string | undefined;
1935
+ fit?: "contain" | "cover" | undefined;
1936
+ } | {
1937
+ type: "chart";
1938
+ chartData: Record<string, unknown>;
1939
+ title?: string | undefined;
1940
+ } | {
1941
+ type: "mermaid";
1942
+ code: string;
1943
+ title?: string | undefined;
1801
1944
  })[] | undefined;
1802
1945
  }[];
1803
1946
  layout: "grid";
@@ -1911,6 +2054,19 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
1911
2054
  src: string;
1912
2055
  alt?: string | undefined;
1913
2056
  fit?: "contain" | "cover" | undefined;
2057
+ } | {
2058
+ type: "imageRef";
2059
+ ref: string;
2060
+ alt?: string | undefined;
2061
+ fit?: "contain" | "cover" | undefined;
2062
+ } | {
2063
+ type: "chart";
2064
+ chartData: Record<string, unknown>;
2065
+ title?: string | undefined;
2066
+ } | {
2067
+ type: "mermaid";
2068
+ code: string;
2069
+ title?: string | undefined;
1914
2070
  })[] | undefined;
1915
2071
  dark?: boolean | undefined;
1916
2072
  ratio?: number | undefined;
@@ -1957,6 +2113,19 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
1957
2113
  src: string;
1958
2114
  alt?: string | undefined;
1959
2115
  fit?: "contain" | "cover" | undefined;
2116
+ } | {
2117
+ type: "imageRef";
2118
+ ref: string;
2119
+ alt?: string | undefined;
2120
+ fit?: "contain" | "cover" | undefined;
2121
+ } | {
2122
+ type: "chart";
2123
+ chartData: Record<string, unknown>;
2124
+ title?: string | undefined;
2125
+ } | {
2126
+ type: "mermaid";
2127
+ code: string;
2128
+ title?: string | undefined;
1960
2129
  })[] | undefined;
1961
2130
  dark?: boolean | undefined;
1962
2131
  ratio?: number | undefined;
@@ -2010,6 +2179,19 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
2010
2179
  src: string;
2011
2180
  alt?: string | undefined;
2012
2181
  fit?: "contain" | "cover" | undefined;
2182
+ } | {
2183
+ type: "imageRef";
2184
+ ref: string;
2185
+ alt?: string | undefined;
2186
+ fit?: "contain" | "cover" | undefined;
2187
+ } | {
2188
+ type: "chart";
2189
+ chartData: Record<string, unknown>;
2190
+ title?: string | undefined;
2191
+ } | {
2192
+ type: "mermaid";
2193
+ code: string;
2194
+ title?: string | undefined;
2013
2195
  })[] | undefined;
2014
2196
  accentColor?: "success" | "primary" | "accent" | "warning" | "danger" | "info" | "highlight" | undefined;
2015
2197
  }[];
@@ -1,17 +1,55 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import nodePath from "node:path";
4
+ import crypto from "node:crypto";
1
5
  import { marked } from "marked";
2
6
  import puppeteer from "puppeteer";
3
7
  const isCI = process.env.CI === "true";
8
+ /** Determine the appropriate waitUntil strategy based on HTML content */
9
+ const resolveWaitUntil = (html) => {
10
+ const hasExternalImages = html.includes("<img") && /src=["']https?:\/\//.test(html);
11
+ const hasLocalImages = html.includes("<img") && /src=["']file:\/\//.test(html);
12
+ if (hasExternalImages)
13
+ return "networkidle0";
14
+ if (hasLocalImages)
15
+ return "load";
16
+ return "domcontentloaded";
17
+ };
18
+ /**
19
+ * Load HTML into a Puppeteer page.
20
+ * When the HTML references file:// URLs, write it to a temp file
21
+ * and navigate via page.goto (setContent uses about:blank origin
22
+ * which blocks file:// loading).
23
+ */
24
+ const loadHtmlIntoPage = async (page, html, timeout_ms) => {
25
+ const waitUntil = resolveWaitUntil(html);
26
+ const hasFileUrls = /file:\/\//.test(html);
27
+ if (hasFileUrls) {
28
+ const tmpFile = nodePath.join(os.tmpdir(), `mulmocast_render_${crypto.randomUUID()}.html`);
29
+ fs.writeFileSync(tmpFile, html);
30
+ try {
31
+ await page.goto(`file://${tmpFile}`, { waitUntil, timeout: timeout_ms });
32
+ }
33
+ finally {
34
+ try {
35
+ fs.unlinkSync(tmpFile);
36
+ }
37
+ catch {
38
+ /* ignore cleanup errors */
39
+ }
40
+ }
41
+ }
42
+ else {
43
+ await page.setContent(html, { waitUntil, timeout: timeout_ms });
44
+ }
45
+ };
4
46
  export const renderHTMLToImage = async (html, outputPath, width, height, isMermaid = false, omitBackground = false) => {
5
47
  // Use Puppeteer to render HTML to an image
6
48
  const browser = await puppeteer.launch({
7
- args: isCI ? ["--no-sandbox"] : [],
49
+ args: isCI ? ["--no-sandbox", "--allow-file-access-from-files"] : ["--allow-file-access-from-files"],
8
50
  });
9
51
  const page = await browser.newPage();
10
- // Set the page content to the HTML generated from the Markdown
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 });
52
+ await loadHtmlIntoPage(page, html, 30000);
15
53
  // Adjust page settings if needed (like width, height, etc.)
16
54
  await page.setViewport({ width, height });
17
55
  // height:100% ensures background fills viewport; only reset html, let body styles come from custom CSS
@@ -1,5 +1,19 @@
1
1
  import { ImageProcessorParams } from "../../types/index.js";
2
+ import type { SlideLayout, ContentBlock } from "../../slide/index.js";
2
3
  export declare const imageType = "slide";
4
+ /**
5
+ * Collect all content block arrays from a slide layout.
6
+ * Only layouts that embed ContentBlock[] are handled:
7
+ * columns, comparison, grid, split, matrix
8
+ */
9
+ export declare const collectContentArrays: (slide: SlideLayout) => ContentBlock[][];
10
+ /**
11
+ * Deep-clone a slide layout and resolve `imageRef` content blocks
12
+ * into `image` blocks using the resolved imageRefs map and a path-to-URL converter.
13
+ * Default converter produces data URLs (for self-contained HTML).
14
+ * Pass `toFileUrl` for Puppeteer rendering (avoids huge inline base64).
15
+ */
16
+ export declare const resolveSlideImageRefs: (slide: SlideLayout, imageRefs: Record<string, string>, converter?: (filePath: string) => string) => SlideLayout;
3
17
  export declare const process: (params: ImageProcessorParams) => Promise<string | undefined>;
4
18
  export declare const path: (params: ImageProcessorParams) => string;
5
19
  export declare const html: (params: ImageProcessorParams) => Promise<string | undefined>;
@@ -1,7 +1,93 @@
1
+ import nodePath from "node:path";
2
+ import { pathToFileURL } from "node:url";
1
3
  import { generateSlideHTML } from "../../slide/index.js";
2
4
  import { renderHTMLToImage } from "../html_render.js";
3
5
  import { parrotingImagePath } from "./utils.js";
6
+ import { pathToDataUrl } from "../../methods/mulmo_media_source.js";
7
+ import { imageAction, imageFileTarget, unknownMediaType } from "../error_cause.js";
4
8
  export const imageType = "slide";
9
+ const slideImageRefError = (refKey) => ({
10
+ type: unknownMediaType,
11
+ action: imageAction,
12
+ target: imageFileTarget,
13
+ agentName: "slidePlugin",
14
+ refKey,
15
+ });
16
+ /** Convert a file path to a file:// URL string */
17
+ const toFileUrl = (filePath) => {
18
+ return pathToFileURL(nodePath.resolve(filePath)).href;
19
+ };
20
+ /**
21
+ * Collect all content block arrays from a slide layout.
22
+ * Only layouts that embed ContentBlock[] are handled:
23
+ * columns, comparison, grid, split, matrix
24
+ */
25
+ export const collectContentArrays = (slide) => {
26
+ const result = [];
27
+ switch (slide.layout) {
28
+ case "columns":
29
+ slide.columns.forEach((col) => {
30
+ if (col.content)
31
+ result.push(col.content);
32
+ });
33
+ break;
34
+ case "comparison":
35
+ if (slide.left.content)
36
+ result.push(slide.left.content);
37
+ if (slide.right.content)
38
+ result.push(slide.right.content);
39
+ break;
40
+ case "grid":
41
+ slide.items.forEach((item) => {
42
+ if (item.content)
43
+ result.push(item.content);
44
+ });
45
+ break;
46
+ case "split":
47
+ if (slide.left?.content)
48
+ result.push(slide.left.content);
49
+ if (slide.right?.content)
50
+ result.push(slide.right.content);
51
+ break;
52
+ case "matrix":
53
+ slide.cells.forEach((cell) => {
54
+ if (cell.content)
55
+ result.push(cell.content);
56
+ });
57
+ break;
58
+ default:
59
+ // title, bigQuote, stats, timeline, table, funnel — no content blocks
60
+ break;
61
+ }
62
+ return result;
63
+ };
64
+ /**
65
+ * Deep-clone a slide layout and resolve `imageRef` content blocks
66
+ * into `image` blocks using the resolved imageRefs map and a path-to-URL converter.
67
+ * Default converter produces data URLs (for self-contained HTML).
68
+ * Pass `toFileUrl` for Puppeteer rendering (avoids huge inline base64).
69
+ */
70
+ export const resolveSlideImageRefs = (slide, imageRefs, converter = pathToDataUrl) => {
71
+ const cloned = JSON.parse(JSON.stringify(slide));
72
+ const contentArrays = collectContentArrays(cloned);
73
+ contentArrays.forEach((blocks) => {
74
+ blocks.forEach((block, index) => {
75
+ if (block.type !== "imageRef")
76
+ return;
77
+ const filePath = imageRefs[block.ref];
78
+ if (!filePath) {
79
+ throw new Error(`Unknown image ref key: "${block.ref}"`, { cause: slideImageRefError(block.ref) });
80
+ }
81
+ blocks[index] = {
82
+ type: "image",
83
+ src: converter(filePath),
84
+ ...(block.alt !== undefined && { alt: block.alt }),
85
+ ...(block.fit !== undefined && { fit: block.fit }),
86
+ };
87
+ });
88
+ });
89
+ return cloned;
90
+ };
5
91
  const resolveTheme = (params) => {
6
92
  const { beat, context } = params;
7
93
  if (!beat.image || beat.image.type !== imageType) {
@@ -14,12 +100,24 @@ const resolveTheme = (params) => {
14
100
  }
15
101
  return theme;
16
102
  };
103
+ const resolveSlide = (params, converter = pathToDataUrl) => {
104
+ const { beat, imageRefs } = params;
105
+ if (!beat.image || beat.image.type !== imageType) {
106
+ throw new Error("resolveSlide called on non-slide beat");
107
+ }
108
+ const slide = beat.image.slide;
109
+ if (imageRefs && Object.keys(imageRefs).length > 0) {
110
+ return resolveSlideImageRefs(slide, imageRefs, converter);
111
+ }
112
+ return slide;
113
+ };
17
114
  const processSlide = async (params) => {
18
115
  const { beat, imagePath, canvasSize } = params;
19
116
  if (!beat.image || beat.image.type !== imageType)
20
117
  return;
21
118
  const theme = resolveTheme(params);
22
- const html = generateSlideHTML(theme, beat.image.slide);
119
+ const slide = resolveSlide(params, toFileUrl);
120
+ const html = generateSlideHTML(theme, slide);
23
121
  await renderHTMLToImage(html, imagePath, canvasSize.width, canvasSize.height);
24
122
  return imagePath;
25
123
  };
@@ -28,7 +126,8 @@ const dumpHtml = async (params) => {
28
126
  if (!beat.image || beat.image.type !== imageType)
29
127
  return;
30
128
  const theme = resolveTheme(params);
31
- return generateSlideHTML(theme, beat.image.slide);
129
+ const slide = resolveSlide(params);
130
+ return generateSlideHTML(theme, slide);
32
131
  };
33
132
  export const process = processSlide;
34
133
  export const path = parrotingImagePath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "2.1.40",
3
+ "version": "2.2.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.node.js",
@@ -17,7 +17,11 @@
17
17
  "default": "./lib/data/index.js"
18
18
  },
19
19
  "./assets/*": "./assets/*",
20
- "./scripts/*": "./scripts/*"
20
+ "./scripts/*": "./scripts/*",
21
+ "./tools/complete_script": {
22
+ "types": "./lib/tools/complete_script.d.ts",
23
+ "default": "./lib/tools/complete_script.js"
24
+ }
21
25
  },
22
26
  "bin": {
23
27
  "mulmo": "lib/cli/bin.js",
@@ -30,6 +34,9 @@
30
34
  "./assets/audio/silent60sec.mp3",
31
35
  "./assets/html/",
32
36
  "./assets/images/",
37
+ "./assets/schemas/",
38
+ "./assets/slide_themes/",
39
+ "./assets/styles/",
33
40
  "./assets/templates/"
34
41
  ],
35
42
  "directories": {
Binary file
Binary file
Binary file
@@ -0,0 +1,148 @@
1
+ {
2
+ "$mulmocast": { "version": "1.1" },
3
+ "lang": "en",
4
+ "title": "Chart & Mermaid Content Blocks Demo",
5
+ "slideParams": {
6
+ "theme": {
7
+ "colors": {
8
+ "bg": "0F172A",
9
+ "bgCard": "1E293B",
10
+ "bgCardAlt": "334155",
11
+ "text": "F8FAFC",
12
+ "textMuted": "CBD5E1",
13
+ "textDim": "64748B",
14
+ "primary": "3B82F6",
15
+ "accent": "8B5CF6",
16
+ "success": "22C55E",
17
+ "warning": "F59E0B",
18
+ "danger": "EF4444",
19
+ "info": "14B8A6",
20
+ "highlight": "EC4899"
21
+ },
22
+ "fonts": { "title": "Georgia", "body": "Calibri", "mono": "Consolas" }
23
+ }
24
+ },
25
+ "beats": [
26
+ {
27
+ "text": "This slide shows a bar chart inside a columns layout.",
28
+ "image": {
29
+ "type": "slide",
30
+ "slide": {
31
+ "layout": "columns",
32
+ "title": "Quarterly Revenue",
33
+ "subtitle": "FY2025 performance overview",
34
+ "columns": [
35
+ {
36
+ "title": "Revenue by Quarter",
37
+ "accentColor": "primary",
38
+ "content": [
39
+ {
40
+ "type": "chart",
41
+ "title": "Revenue ($ millions)",
42
+ "chartData": {
43
+ "type": "bar",
44
+ "data": {
45
+ "labels": ["Q1", "Q2", "Q3", "Q4"],
46
+ "datasets": [
47
+ {
48
+ "label": "Revenue",
49
+ "data": [12, 19, 15, 24],
50
+ "backgroundColor": ["#3B82F6", "#8B5CF6", "#22C55E", "#F59E0B"]
51
+ }
52
+ ]
53
+ }
54
+ }
55
+ }
56
+ ]
57
+ },
58
+ {
59
+ "title": "Key Takeaways",
60
+ "accentColor": "success",
61
+ "content": [
62
+ { "type": "metric", "value": "$70M", "label": "Total Revenue", "color": "primary" },
63
+ { "type": "bullets", "items": ["Q4 strongest quarter", "24% QoQ growth in Q4", "Exceeded annual target by 8%"] }
64
+ ]
65
+ }
66
+ ]
67
+ }
68
+ }
69
+ },
70
+ {
71
+ "text": "This slide demonstrates a mermaid diagram in a split layout.",
72
+ "image": {
73
+ "type": "slide",
74
+ "slide": {
75
+ "layout": "split",
76
+ "left": {
77
+ "title": "System Architecture",
78
+ "accentColor": "accent",
79
+ "content": [
80
+ {
81
+ "type": "mermaid",
82
+ "title": "Data Flow",
83
+ "code": "graph TD\n A[Client] --> B[API Gateway]\n B --> C[Auth Service]\n B --> D[App Service]\n D --> E[Database]\n D --> F[Cache]"
84
+ }
85
+ ]
86
+ },
87
+ "right": {
88
+ "title": "Components",
89
+ "accentColor": "info",
90
+ "content": [
91
+ {
92
+ "type": "bullets",
93
+ "items": [
94
+ "API Gateway handles routing",
95
+ "Auth Service manages tokens",
96
+ "App Service processes requests",
97
+ "Database stores persistent data",
98
+ "Cache layer for performance"
99
+ ]
100
+ }
101
+ ]
102
+ }
103
+ }
104
+ }
105
+ },
106
+ {
107
+ "text": "This slide combines both chart and mermaid in a comparison layout.",
108
+ "image": {
109
+ "type": "slide",
110
+ "slide": {
111
+ "layout": "comparison",
112
+ "title": "Pipeline Analysis",
113
+ "left": {
114
+ "title": "Conversion Funnel",
115
+ "accentColor": "primary",
116
+ "content": [
117
+ {
118
+ "type": "chart",
119
+ "chartData": {
120
+ "type": "doughnut",
121
+ "data": {
122
+ "labels": ["Leads", "Qualified", "Proposals", "Won"],
123
+ "datasets": [
124
+ {
125
+ "data": [500, 200, 80, 35],
126
+ "backgroundColor": ["#3B82F6", "#8B5CF6", "#22C55E", "#F59E0B"]
127
+ }
128
+ ]
129
+ }
130
+ }
131
+ }
132
+ ]
133
+ },
134
+ "right": {
135
+ "title": "Process Flow",
136
+ "accentColor": "accent",
137
+ "content": [
138
+ {
139
+ "type": "mermaid",
140
+ "code": "graph LR\n A[Lead] --> B[Qualify]\n B --> C[Propose]\n C --> D[Close]\n D --> E[Onboard]"
141
+ }
142
+ ]
143
+ }
144
+ }
145
+ }
146
+ }
147
+ ]
148
+ }