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.
- package/README.md +1 -1
- package/assets/schemas/html_prompt.json +60 -0
- package/assets/schemas/mulmo_script.json +283 -0
- package/assets/slide_themes/corporate.json +18 -0
- package/assets/slide_themes/creative.json +18 -0
- package/assets/slide_themes/dark.json +18 -0
- package/assets/slide_themes/minimal.json +18 -0
- package/assets/slide_themes/pop.json +18 -0
- package/assets/slide_themes/warm.json +18 -0
- package/assets/styles/akira_comic.json +22 -0
- package/assets/styles/ani.json +43 -0
- package/assets/styles/children_book.json +13 -0
- package/assets/styles/comic_strips.json +13 -0
- package/assets/styles/drslump_comic.json +22 -0
- package/assets/styles/ghibli_comic.json +22 -0
- package/assets/styles/ghibli_shorts.json +28 -0
- package/assets/styles/ghost_comic.json +29 -0
- package/assets/styles/leda.json +29 -0
- package/assets/styles/onepiece_comic.json +22 -0
- package/assets/styles/slide_corporate.json +30 -0
- package/assets/styles/slide_creative.json +30 -0
- package/assets/styles/slide_dark.json +30 -0
- package/assets/styles/slide_minimal.json +30 -0
- package/assets/styles/slide_pop.json +30 -0
- package/assets/styles/slide_warm.json +30 -0
- package/lib/actions/image_agents.d.ts +2 -1
- package/lib/actions/image_agents.js +3 -3
- package/lib/actions/images.d.ts +3 -1
- package/lib/actions/images.js +1 -0
- package/lib/data/index.d.ts +2 -0
- package/lib/data/index.js +2 -0
- package/lib/data/slideStyles.d.ts +206 -0
- package/lib/data/slideStyles.js +206 -0
- package/lib/data/slideThemes.d.ts +134 -0
- package/lib/data/slideThemes.js +134 -0
- package/lib/methods/mulmo_media_source.d.ts +1 -0
- package/lib/methods/mulmo_media_source.js +17 -3
- package/lib/slide/blocks.d.ts +2 -0
- package/lib/slide/blocks.js +54 -2
- package/lib/slide/index.d.ts +2 -2
- package/lib/slide/index.js +1 -1
- package/lib/slide/layouts/columns.js +4 -4
- package/lib/slide/layouts/comparison.js +4 -3
- package/lib/slide/layouts/grid.js +3 -3
- package/lib/slide/render.js +24 -1
- package/lib/slide/schema.d.ts +454 -0
- package/lib/slide/schema.js +19 -0
- package/lib/slide/utils.d.ts +12 -1
- package/lib/slide/utils.js +55 -2
- package/lib/types/schema.d.ts +448 -0
- package/lib/types/slide.d.ts +454 -0
- package/lib/types/slide.js +19 -0
- package/lib/types/type.d.ts +1 -0
- package/lib/utils/context.d.ts +182 -0
- package/lib/utils/html_render.js +44 -6
- package/lib/utils/image_plugins/slide.d.ts +14 -0
- package/lib/utils/image_plugins/slide.js +101 -2
- package/package.json +9 -2
- package/scripts/test/img_detector.png +0 -0
- package/scripts/test/img_higgs.png +0 -0
- package/scripts/test/img_lhc.png +0 -0
- package/scripts/test/test_slide_chart_mermaid.json +148 -0
- package/scripts/test/test_slide_image_ref.json +261 -0
- package/scripts/test/test_slide_image_ref_en.json +287 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
export const slideStyles = {
|
|
2
|
+
slide_corporate: {
|
|
3
|
+
$mulmocast: {
|
|
4
|
+
credit: "closing",
|
|
5
|
+
version: "1.1",
|
|
6
|
+
},
|
|
7
|
+
canvasSize: {
|
|
8
|
+
height: 720,
|
|
9
|
+
width: 1280,
|
|
10
|
+
},
|
|
11
|
+
slideParams: {
|
|
12
|
+
theme: {
|
|
13
|
+
colors: {
|
|
14
|
+
accent: "7C3AED",
|
|
15
|
+
bg: "F8FAFC",
|
|
16
|
+
bgCard: "FFFFFF",
|
|
17
|
+
bgCardAlt: "F1F5F9",
|
|
18
|
+
danger: "DC2626",
|
|
19
|
+
highlight: "DB2777",
|
|
20
|
+
info: "0891B2",
|
|
21
|
+
primary: "2563EB",
|
|
22
|
+
success: "16A34A",
|
|
23
|
+
text: "0F172A",
|
|
24
|
+
textDim: "94A3B8",
|
|
25
|
+
textMuted: "475569",
|
|
26
|
+
warning: "EA580C",
|
|
27
|
+
},
|
|
28
|
+
fonts: {
|
|
29
|
+
body: "Helvetica",
|
|
30
|
+
mono: "Menlo",
|
|
31
|
+
title: "Georgia",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
slide_creative: {
|
|
37
|
+
$mulmocast: {
|
|
38
|
+
credit: "closing",
|
|
39
|
+
version: "1.1",
|
|
40
|
+
},
|
|
41
|
+
canvasSize: {
|
|
42
|
+
height: 720,
|
|
43
|
+
width: 1280,
|
|
44
|
+
},
|
|
45
|
+
slideParams: {
|
|
46
|
+
theme: {
|
|
47
|
+
colors: {
|
|
48
|
+
accent: "FB923C",
|
|
49
|
+
bg: "1C1917",
|
|
50
|
+
bgCard: "292524",
|
|
51
|
+
bgCardAlt: "3D3733",
|
|
52
|
+
danger: "EF4444",
|
|
53
|
+
highlight: "E879F9",
|
|
54
|
+
info: "38BDF8",
|
|
55
|
+
primary: "F43F5E",
|
|
56
|
+
success: "4ADE80",
|
|
57
|
+
text: "FAFAF9",
|
|
58
|
+
textDim: "A8A29E",
|
|
59
|
+
textMuted: "D6D3D1",
|
|
60
|
+
warning: "FBBF24",
|
|
61
|
+
},
|
|
62
|
+
fonts: {
|
|
63
|
+
body: "Helvetica",
|
|
64
|
+
mono: "Consolas",
|
|
65
|
+
title: "Georgia",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
slide_dark: {
|
|
71
|
+
$mulmocast: {
|
|
72
|
+
credit: "closing",
|
|
73
|
+
version: "1.1",
|
|
74
|
+
},
|
|
75
|
+
canvasSize: {
|
|
76
|
+
height: 720,
|
|
77
|
+
width: 1280,
|
|
78
|
+
},
|
|
79
|
+
slideParams: {
|
|
80
|
+
theme: {
|
|
81
|
+
colors: {
|
|
82
|
+
accent: "8B5CF6",
|
|
83
|
+
bg: "0F172A",
|
|
84
|
+
bgCard: "1E293B",
|
|
85
|
+
bgCardAlt: "334155",
|
|
86
|
+
danger: "EF4444",
|
|
87
|
+
highlight: "EC4899",
|
|
88
|
+
info: "14B8A6",
|
|
89
|
+
primary: "3B82F6",
|
|
90
|
+
success: "22C55E",
|
|
91
|
+
text: "F8FAFC",
|
|
92
|
+
textDim: "64748B",
|
|
93
|
+
textMuted: "CBD5E1",
|
|
94
|
+
warning: "F59E0B",
|
|
95
|
+
},
|
|
96
|
+
fonts: {
|
|
97
|
+
body: "Calibri",
|
|
98
|
+
mono: "Consolas",
|
|
99
|
+
title: "Georgia",
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
slide_minimal: {
|
|
105
|
+
$mulmocast: {
|
|
106
|
+
credit: "closing",
|
|
107
|
+
version: "1.1",
|
|
108
|
+
},
|
|
109
|
+
canvasSize: {
|
|
110
|
+
height: 720,
|
|
111
|
+
width: 1280,
|
|
112
|
+
},
|
|
113
|
+
slideParams: {
|
|
114
|
+
theme: {
|
|
115
|
+
colors: {
|
|
116
|
+
accent: "7C3AED",
|
|
117
|
+
bg: "F8FAFC",
|
|
118
|
+
bgCard: "FFFFFF",
|
|
119
|
+
bgCardAlt: "F1F5F9",
|
|
120
|
+
danger: "DC2626",
|
|
121
|
+
highlight: "DB2777",
|
|
122
|
+
info: "0891B2",
|
|
123
|
+
primary: "2563EB",
|
|
124
|
+
success: "059669",
|
|
125
|
+
text: "0F172A",
|
|
126
|
+
textDim: "94A3B8",
|
|
127
|
+
textMuted: "475569",
|
|
128
|
+
warning: "D97706",
|
|
129
|
+
},
|
|
130
|
+
fonts: {
|
|
131
|
+
body: "Calibri",
|
|
132
|
+
mono: "Consolas",
|
|
133
|
+
title: "Trebuchet MS",
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
slide_pop: {
|
|
139
|
+
$mulmocast: {
|
|
140
|
+
credit: "closing",
|
|
141
|
+
version: "1.1",
|
|
142
|
+
},
|
|
143
|
+
canvasSize: {
|
|
144
|
+
height: 720,
|
|
145
|
+
width: 1280,
|
|
146
|
+
},
|
|
147
|
+
slideParams: {
|
|
148
|
+
theme: {
|
|
149
|
+
colors: {
|
|
150
|
+
accent: "7C3AED",
|
|
151
|
+
bg: "FFF0F5",
|
|
152
|
+
bgCard: "FFFFFF",
|
|
153
|
+
bgCardAlt: "FDE8EF",
|
|
154
|
+
danger: "EF4444",
|
|
155
|
+
highlight: "F97316",
|
|
156
|
+
info: "06B6D4",
|
|
157
|
+
primary: "E91E63",
|
|
158
|
+
success: "10B981",
|
|
159
|
+
text: "1A1A2E",
|
|
160
|
+
textDim: "9090B0",
|
|
161
|
+
textMuted: "4A4A6A",
|
|
162
|
+
warning: "F59E0B",
|
|
163
|
+
},
|
|
164
|
+
fonts: {
|
|
165
|
+
body: "Calibri",
|
|
166
|
+
mono: "Consolas",
|
|
167
|
+
title: "Georgia",
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
slide_warm: {
|
|
173
|
+
$mulmocast: {
|
|
174
|
+
credit: "closing",
|
|
175
|
+
version: "1.1",
|
|
176
|
+
},
|
|
177
|
+
canvasSize: {
|
|
178
|
+
height: 720,
|
|
179
|
+
width: 1280,
|
|
180
|
+
},
|
|
181
|
+
slideParams: {
|
|
182
|
+
theme: {
|
|
183
|
+
colors: {
|
|
184
|
+
accent: "D946EF",
|
|
185
|
+
bg: "FFFBEB",
|
|
186
|
+
bgCard: "FFFFFF",
|
|
187
|
+
bgCardAlt: "FEF3C7",
|
|
188
|
+
danger: "DC2626",
|
|
189
|
+
highlight: "E11D48",
|
|
190
|
+
info: "0284C7",
|
|
191
|
+
primary: "EA580C",
|
|
192
|
+
success: "16A34A",
|
|
193
|
+
text: "1C1917",
|
|
194
|
+
textDim: "A8A29E",
|
|
195
|
+
textMuted: "57534E",
|
|
196
|
+
warning: "CA8A04",
|
|
197
|
+
},
|
|
198
|
+
fonts: {
|
|
199
|
+
body: "Calibri",
|
|
200
|
+
mono: "Consolas",
|
|
201
|
+
title: "Georgia",
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export declare const slideThemes: {
|
|
2
|
+
corporate: {
|
|
3
|
+
colors: {
|
|
4
|
+
accent: string;
|
|
5
|
+
bg: string;
|
|
6
|
+
bgCard: string;
|
|
7
|
+
bgCardAlt: string;
|
|
8
|
+
danger: string;
|
|
9
|
+
highlight: string;
|
|
10
|
+
info: string;
|
|
11
|
+
primary: string;
|
|
12
|
+
success: string;
|
|
13
|
+
text: string;
|
|
14
|
+
textDim: string;
|
|
15
|
+
textMuted: string;
|
|
16
|
+
warning: string;
|
|
17
|
+
};
|
|
18
|
+
fonts: {
|
|
19
|
+
body: string;
|
|
20
|
+
mono: string;
|
|
21
|
+
title: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
creative: {
|
|
25
|
+
colors: {
|
|
26
|
+
accent: string;
|
|
27
|
+
bg: string;
|
|
28
|
+
bgCard: string;
|
|
29
|
+
bgCardAlt: string;
|
|
30
|
+
danger: string;
|
|
31
|
+
highlight: string;
|
|
32
|
+
info: string;
|
|
33
|
+
primary: string;
|
|
34
|
+
success: string;
|
|
35
|
+
text: string;
|
|
36
|
+
textDim: string;
|
|
37
|
+
textMuted: string;
|
|
38
|
+
warning: string;
|
|
39
|
+
};
|
|
40
|
+
fonts: {
|
|
41
|
+
body: string;
|
|
42
|
+
mono: string;
|
|
43
|
+
title: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
dark: {
|
|
47
|
+
colors: {
|
|
48
|
+
accent: string;
|
|
49
|
+
bg: string;
|
|
50
|
+
bgCard: string;
|
|
51
|
+
bgCardAlt: string;
|
|
52
|
+
danger: string;
|
|
53
|
+
highlight: string;
|
|
54
|
+
info: string;
|
|
55
|
+
primary: string;
|
|
56
|
+
success: string;
|
|
57
|
+
text: string;
|
|
58
|
+
textDim: string;
|
|
59
|
+
textMuted: string;
|
|
60
|
+
warning: string;
|
|
61
|
+
};
|
|
62
|
+
fonts: {
|
|
63
|
+
body: string;
|
|
64
|
+
mono: string;
|
|
65
|
+
title: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
minimal: {
|
|
69
|
+
colors: {
|
|
70
|
+
accent: string;
|
|
71
|
+
bg: string;
|
|
72
|
+
bgCard: string;
|
|
73
|
+
bgCardAlt: string;
|
|
74
|
+
danger: string;
|
|
75
|
+
highlight: string;
|
|
76
|
+
info: string;
|
|
77
|
+
primary: string;
|
|
78
|
+
success: string;
|
|
79
|
+
text: string;
|
|
80
|
+
textDim: string;
|
|
81
|
+
textMuted: string;
|
|
82
|
+
warning: string;
|
|
83
|
+
};
|
|
84
|
+
fonts: {
|
|
85
|
+
body: string;
|
|
86
|
+
mono: string;
|
|
87
|
+
title: string;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
pop: {
|
|
91
|
+
colors: {
|
|
92
|
+
accent: string;
|
|
93
|
+
bg: string;
|
|
94
|
+
bgCard: string;
|
|
95
|
+
bgCardAlt: string;
|
|
96
|
+
danger: string;
|
|
97
|
+
highlight: string;
|
|
98
|
+
info: string;
|
|
99
|
+
primary: string;
|
|
100
|
+
success: string;
|
|
101
|
+
text: string;
|
|
102
|
+
textDim: string;
|
|
103
|
+
textMuted: string;
|
|
104
|
+
warning: string;
|
|
105
|
+
};
|
|
106
|
+
fonts: {
|
|
107
|
+
body: string;
|
|
108
|
+
mono: string;
|
|
109
|
+
title: string;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
warm: {
|
|
113
|
+
colors: {
|
|
114
|
+
accent: string;
|
|
115
|
+
bg: string;
|
|
116
|
+
bgCard: string;
|
|
117
|
+
bgCardAlt: string;
|
|
118
|
+
danger: string;
|
|
119
|
+
highlight: string;
|
|
120
|
+
info: string;
|
|
121
|
+
primary: string;
|
|
122
|
+
success: string;
|
|
123
|
+
text: string;
|
|
124
|
+
textDim: string;
|
|
125
|
+
textMuted: string;
|
|
126
|
+
warning: string;
|
|
127
|
+
};
|
|
128
|
+
fonts: {
|
|
129
|
+
body: string;
|
|
130
|
+
mono: string;
|
|
131
|
+
title: string;
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export const slideThemes = {
|
|
2
|
+
corporate: {
|
|
3
|
+
colors: {
|
|
4
|
+
accent: "7C3AED",
|
|
5
|
+
bg: "F8FAFC",
|
|
6
|
+
bgCard: "FFFFFF",
|
|
7
|
+
bgCardAlt: "F1F5F9",
|
|
8
|
+
danger: "DC2626",
|
|
9
|
+
highlight: "DB2777",
|
|
10
|
+
info: "0891B2",
|
|
11
|
+
primary: "2563EB",
|
|
12
|
+
success: "16A34A",
|
|
13
|
+
text: "0F172A",
|
|
14
|
+
textDim: "94A3B8",
|
|
15
|
+
textMuted: "475569",
|
|
16
|
+
warning: "EA580C",
|
|
17
|
+
},
|
|
18
|
+
fonts: {
|
|
19
|
+
body: "Helvetica",
|
|
20
|
+
mono: "Menlo",
|
|
21
|
+
title: "Georgia",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
creative: {
|
|
25
|
+
colors: {
|
|
26
|
+
accent: "FB923C",
|
|
27
|
+
bg: "1C1917",
|
|
28
|
+
bgCard: "292524",
|
|
29
|
+
bgCardAlt: "3D3733",
|
|
30
|
+
danger: "EF4444",
|
|
31
|
+
highlight: "E879F9",
|
|
32
|
+
info: "38BDF8",
|
|
33
|
+
primary: "F43F5E",
|
|
34
|
+
success: "4ADE80",
|
|
35
|
+
text: "FAFAF9",
|
|
36
|
+
textDim: "A8A29E",
|
|
37
|
+
textMuted: "D6D3D1",
|
|
38
|
+
warning: "FBBF24",
|
|
39
|
+
},
|
|
40
|
+
fonts: {
|
|
41
|
+
body: "Helvetica",
|
|
42
|
+
mono: "Consolas",
|
|
43
|
+
title: "Georgia",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
dark: {
|
|
47
|
+
colors: {
|
|
48
|
+
accent: "8B5CF6",
|
|
49
|
+
bg: "0F172A",
|
|
50
|
+
bgCard: "1E293B",
|
|
51
|
+
bgCardAlt: "334155",
|
|
52
|
+
danger: "EF4444",
|
|
53
|
+
highlight: "EC4899",
|
|
54
|
+
info: "14B8A6",
|
|
55
|
+
primary: "3B82F6",
|
|
56
|
+
success: "22C55E",
|
|
57
|
+
text: "F8FAFC",
|
|
58
|
+
textDim: "64748B",
|
|
59
|
+
textMuted: "CBD5E1",
|
|
60
|
+
warning: "F59E0B",
|
|
61
|
+
},
|
|
62
|
+
fonts: {
|
|
63
|
+
body: "Calibri",
|
|
64
|
+
mono: "Consolas",
|
|
65
|
+
title: "Georgia",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
minimal: {
|
|
69
|
+
colors: {
|
|
70
|
+
accent: "7C3AED",
|
|
71
|
+
bg: "F8FAFC",
|
|
72
|
+
bgCard: "FFFFFF",
|
|
73
|
+
bgCardAlt: "F1F5F9",
|
|
74
|
+
danger: "DC2626",
|
|
75
|
+
highlight: "DB2777",
|
|
76
|
+
info: "0891B2",
|
|
77
|
+
primary: "2563EB",
|
|
78
|
+
success: "059669",
|
|
79
|
+
text: "0F172A",
|
|
80
|
+
textDim: "94A3B8",
|
|
81
|
+
textMuted: "475569",
|
|
82
|
+
warning: "D97706",
|
|
83
|
+
},
|
|
84
|
+
fonts: {
|
|
85
|
+
body: "Calibri",
|
|
86
|
+
mono: "Consolas",
|
|
87
|
+
title: "Trebuchet MS",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
pop: {
|
|
91
|
+
colors: {
|
|
92
|
+
accent: "7C3AED",
|
|
93
|
+
bg: "FFF0F5",
|
|
94
|
+
bgCard: "FFFFFF",
|
|
95
|
+
bgCardAlt: "FDE8EF",
|
|
96
|
+
danger: "EF4444",
|
|
97
|
+
highlight: "F97316",
|
|
98
|
+
info: "06B6D4",
|
|
99
|
+
primary: "E91E63",
|
|
100
|
+
success: "10B981",
|
|
101
|
+
text: "1A1A2E",
|
|
102
|
+
textDim: "9090B0",
|
|
103
|
+
textMuted: "4A4A6A",
|
|
104
|
+
warning: "F59E0B",
|
|
105
|
+
},
|
|
106
|
+
fonts: {
|
|
107
|
+
body: "Calibri",
|
|
108
|
+
mono: "Consolas",
|
|
109
|
+
title: "Georgia",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
warm: {
|
|
113
|
+
colors: {
|
|
114
|
+
accent: "D946EF",
|
|
115
|
+
bg: "FFFBEB",
|
|
116
|
+
bgCard: "FFFFFF",
|
|
117
|
+
bgCardAlt: "FEF3C7",
|
|
118
|
+
danger: "DC2626",
|
|
119
|
+
highlight: "E11D48",
|
|
120
|
+
info: "0284C7",
|
|
121
|
+
primary: "EA580C",
|
|
122
|
+
success: "16A34A",
|
|
123
|
+
text: "1C1917",
|
|
124
|
+
textDim: "A8A29E",
|
|
125
|
+
textMuted: "57534E",
|
|
126
|
+
warning: "CA8A04",
|
|
127
|
+
},
|
|
128
|
+
fonts: {
|
|
129
|
+
body: "Calibri",
|
|
130
|
+
mono: "Consolas",
|
|
131
|
+
title: "Georgia",
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MulmoMediaSource, MulmoMediaMermaidSource, MulmoStudioContext, ImageType } from "../types/index.js";
|
|
2
2
|
export declare const getExtention: (contentType: string | null, url: string) => string;
|
|
3
|
+
export declare const pathToDataUrl: (filePath: string) => string;
|
|
3
4
|
export declare const MulmoMediaSourceMethods: {
|
|
4
5
|
getText(mediaSource: MulmoMediaMermaidSource, context: MulmoStudioContext): Promise<string | null>;
|
|
5
6
|
resolve(mediaSource: MulmoMediaSource | undefined, context: MulmoStudioContext): string | null;
|
|
@@ -60,12 +60,26 @@ const urlToDataUrl = async (url, timeoutMs = DEFAULT_FETCH_TIMEOUT_MS) => {
|
|
|
60
60
|
clearTimeout(timeoutId);
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
|
+
/** Map file extension to MIME type for data URLs */
|
|
64
|
+
const extensionToMimeType = (ext) => {
|
|
65
|
+
const mimeMap = {
|
|
66
|
+
jpg: "image/jpeg",
|
|
67
|
+
jpeg: "image/jpeg",
|
|
68
|
+
png: "image/png",
|
|
69
|
+
gif: "image/gif",
|
|
70
|
+
webp: "image/webp",
|
|
71
|
+
svg: "image/svg+xml",
|
|
72
|
+
bmp: "image/bmp",
|
|
73
|
+
ico: "image/x-icon",
|
|
74
|
+
};
|
|
75
|
+
return mimeMap[ext.toLowerCase()] ?? `image/${ext}`;
|
|
76
|
+
};
|
|
63
77
|
// Convert local file path to data URL (base64 encoded)
|
|
64
|
-
const pathToDataUrl = (filePath) => {
|
|
78
|
+
export const pathToDataUrl = (filePath) => {
|
|
65
79
|
assert(fs.existsSync(filePath), `File not found: ${filePath}`, false, mediaSourceFileNotFoundError(filePath));
|
|
66
80
|
const buffer = fs.readFileSync(filePath);
|
|
67
|
-
const
|
|
68
|
-
const mimeType =
|
|
81
|
+
const ext = filePath.split(".").pop()?.toLowerCase() ?? "png";
|
|
82
|
+
const mimeType = extensionToMimeType(ext);
|
|
69
83
|
return `data:${mimeType};base64,${buffer.toString("base64")}`;
|
|
70
84
|
};
|
|
71
85
|
// Convert base64 string to data URL format
|
package/lib/slide/blocks.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ import type { ContentBlock } from "./schema.js";
|
|
|
3
3
|
export declare const renderContentBlock: (block: ContentBlock) => string;
|
|
4
4
|
/** Render an array of content blocks to HTML */
|
|
5
5
|
export declare const renderContentBlocks: (blocks: ContentBlock[]) => string;
|
|
6
|
+
/** Render content blocks with fixed aspect-ratio container for image blocks (used in card layouts) */
|
|
7
|
+
export declare const renderCardContentBlocks: (blocks: ContentBlock[]) => string;
|
package/lib/slide/blocks.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { escapeHtml, nl2br, c } from "./utils.js";
|
|
1
|
+
import { escapeHtml, nl2br, c, generateSlideId } from "./utils.js";
|
|
2
2
|
/** Render a single content block to HTML */
|
|
3
3
|
export const renderContentBlock = (block) => {
|
|
4
4
|
switch (block.type) {
|
|
@@ -16,6 +16,12 @@ export const renderContentBlock = (block) => {
|
|
|
16
16
|
return renderDivider(block);
|
|
17
17
|
case "image":
|
|
18
18
|
return renderImage(block);
|
|
19
|
+
case "imageRef":
|
|
20
|
+
return renderImageRefPlaceholder(block);
|
|
21
|
+
case "chart":
|
|
22
|
+
return renderChart(block);
|
|
23
|
+
case "mermaid":
|
|
24
|
+
return renderMermaid(block);
|
|
19
25
|
default:
|
|
20
26
|
return `<p class="text-sm text-d-muted font-body">[unknown block type]</p>`;
|
|
21
27
|
}
|
|
@@ -24,6 +30,17 @@ export const renderContentBlock = (block) => {
|
|
|
24
30
|
export const renderContentBlocks = (blocks) => {
|
|
25
31
|
return blocks.map(renderContentBlock).join("\n");
|
|
26
32
|
};
|
|
33
|
+
/** Render content blocks with fixed aspect-ratio container for image blocks (used in card layouts) */
|
|
34
|
+
export const renderCardContentBlocks = (blocks) => {
|
|
35
|
+
return blocks
|
|
36
|
+
.map((block) => {
|
|
37
|
+
if (block.type === "image") {
|
|
38
|
+
return `<div class="aspect-video shrink-0 overflow-hidden">${renderContentBlock(block)}</div>`;
|
|
39
|
+
}
|
|
40
|
+
return renderContentBlock(block);
|
|
41
|
+
})
|
|
42
|
+
.join("\n");
|
|
43
|
+
};
|
|
27
44
|
const resolveTextColor = (block) => {
|
|
28
45
|
if (block.color)
|
|
29
46
|
return `text-${c(block.color)}`;
|
|
@@ -93,5 +110,40 @@ const renderDivider = (block) => {
|
|
|
93
110
|
};
|
|
94
111
|
const renderImage = (block) => {
|
|
95
112
|
const fit = block.fit === "cover" ? "object-cover" : "object-contain";
|
|
96
|
-
return `<img src="${escapeHtml(block.src)}" alt="${escapeHtml(block.alt || "")}" class="rounded ${fit}
|
|
113
|
+
return `<div class="min-h-0 flex-1 overflow-hidden flex items-center"><img src="${escapeHtml(block.src)}" alt="${escapeHtml(block.alt || "")}" class="rounded ${fit} w-full h-full" /></div>`;
|
|
114
|
+
};
|
|
115
|
+
/** Placeholder for unresolved imageRef blocks — should be resolved before rendering */
|
|
116
|
+
const renderImageRefPlaceholder = (block) => {
|
|
117
|
+
return `<div class="min-h-0 flex-1 overflow-hidden flex items-center justify-center bg-d-alt rounded"><p class="text-sm text-d-dim font-body">[imageRef: ${escapeHtml(block.ref)}]</p></div>`;
|
|
118
|
+
};
|
|
119
|
+
const renderChart = (block) => {
|
|
120
|
+
const chartId = generateSlideId("chart");
|
|
121
|
+
const chartData = JSON.stringify(block.chartData);
|
|
122
|
+
const titleHtml = block.title ? `<p class="text-sm font-bold text-d-text font-body mb-2">${escapeHtml(block.title)}</p>` : "";
|
|
123
|
+
return `<div class="flex-1 min-h-0 flex flex-col">
|
|
124
|
+
${titleHtml}
|
|
125
|
+
<div class="flex-1 min-h-0 relative">
|
|
126
|
+
<canvas id="${chartId}" data-chart-ready="false"></canvas>
|
|
127
|
+
</div>
|
|
128
|
+
<script>(function(){
|
|
129
|
+
const ctx=document.getElementById('${chartId}');
|
|
130
|
+
const d=${chartData};
|
|
131
|
+
if(!d.options)d.options={};
|
|
132
|
+
d.options.animation=false;
|
|
133
|
+
d.options.responsive=true;
|
|
134
|
+
d.options.maintainAspectRatio=false;
|
|
135
|
+
new Chart(ctx,d);
|
|
136
|
+
requestAnimationFrame(()=>requestAnimationFrame(()=>{ctx.dataset.chartReady="true"}));
|
|
137
|
+
})()</script>
|
|
138
|
+
</div>`;
|
|
139
|
+
};
|
|
140
|
+
const renderMermaid = (block) => {
|
|
141
|
+
const mermaidId = generateSlideId("mermaid");
|
|
142
|
+
const titleHtml = block.title ? `<p class="text-sm font-bold text-d-text font-body mb-2">${escapeHtml(block.title)}</p>` : "";
|
|
143
|
+
return `<div class="flex-1 min-h-0 flex flex-col">
|
|
144
|
+
${titleHtml}
|
|
145
|
+
<div class="flex-1 min-h-0 flex justify-center items-center">
|
|
146
|
+
<div id="${mermaidId}" class="mermaid">${escapeHtml(block.code)}</div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>`;
|
|
97
149
|
};
|
package/lib/slide/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { generateSlideHTML } from "./render.js";
|
|
2
2
|
export { renderSlideContent } from "./layouts/index.js";
|
|
3
3
|
export { renderContentBlock, renderContentBlocks } from "./blocks.js";
|
|
4
|
-
export { mulmoSlideMediaSchema, slideLayoutSchema, slideThemeSchema, contentBlockSchema, accentColorKeySchema } from "./schema.js";
|
|
5
|
-
export type { MulmoSlideMedia, SlideLayout, SlideTheme, SlideThemeColors, SlideThemeFonts, ContentBlock, AccentColorKey, TitleSlide, ColumnsSlide, ComparisonSlide, GridSlide, BigQuoteSlide, StatsSlide, TimelineSlide, SplitSlide, MatrixSlide, TableSlide, FunnelSlide, Card, CalloutBar, SlideStyle, } from "./schema.js";
|
|
4
|
+
export { mulmoSlideMediaSchema, slideLayoutSchema, slideThemeSchema, contentBlockSchema, imageRefBlockSchema, chartBlockSchema, mermaidBlockSchema, accentColorKeySchema, } from "./schema.js";
|
|
5
|
+
export type { MulmoSlideMedia, SlideLayout, SlideTheme, SlideThemeColors, SlideThemeFonts, ContentBlock, ImageRefBlock, ChartBlock, MermaidBlock, AccentColorKey, TitleSlide, ColumnsSlide, ComparisonSlide, GridSlide, BigQuoteSlide, StatsSlide, TimelineSlide, SplitSlide, MatrixSlide, TableSlide, FunnelSlide, Card, CalloutBar, SlideStyle, } from "./schema.js";
|
package/lib/slide/index.js
CHANGED
|
@@ -4,4 +4,4 @@ export { generateSlideHTML } from "./render.js";
|
|
|
4
4
|
export { renderSlideContent } from "./layouts/index.js";
|
|
5
5
|
export { renderContentBlock, renderContentBlocks } from "./blocks.js";
|
|
6
6
|
// Schemas
|
|
7
|
-
export { mulmoSlideMediaSchema, slideLayoutSchema, slideThemeSchema, contentBlockSchema, accentColorKeySchema } from "./schema.js";
|
|
7
|
+
export { mulmoSlideMediaSchema, slideLayoutSchema, slideThemeSchema, contentBlockSchema, imageRefBlockSchema, chartBlockSchema, mermaidBlockSchema, accentColorKeySchema, } from "./schema.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { escapeHtml, c, cardWrap, numBadge, iconSquare, slideHeader, renderCalloutBar } from "../utils.js";
|
|
2
|
-
import {
|
|
2
|
+
import { renderCardContentBlocks } from "../blocks.js";
|
|
3
3
|
const buildColumnCard = (col) => {
|
|
4
4
|
const accent = col.accentColor || "primary";
|
|
5
5
|
const inner = [];
|
|
@@ -23,8 +23,8 @@ const buildColumnCard = (col) => {
|
|
|
23
23
|
}
|
|
24
24
|
if (col.content) {
|
|
25
25
|
const centerCls = col.icon ? "text-center" : "";
|
|
26
|
-
inner.push(`<div class="mt-3 space-y-3 ${centerCls}">`);
|
|
27
|
-
inner.push(
|
|
26
|
+
inner.push(`<div class="mt-3 space-y-3 flex-1 min-h-0 overflow-hidden flex flex-col ${centerCls}">`);
|
|
27
|
+
inner.push(renderCardContentBlocks(col.content));
|
|
28
28
|
inner.push(`</div>`);
|
|
29
29
|
}
|
|
30
30
|
if (col.footer) {
|
|
@@ -43,7 +43,7 @@ export const layoutColumns = (data) => {
|
|
|
43
43
|
colElements.push(`<div class="flex items-center shrink-0"><span class="text-2xl text-d-dim">\u25B6</span></div>`);
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
|
-
parts.push(`<div class="flex gap-4 px-12 mt-5 flex-1">`);
|
|
46
|
+
parts.push(`<div class="flex gap-4 px-12 mt-5 flex-1 min-h-0 items-stretch">`);
|
|
47
47
|
parts.push(colElements.join("\n"));
|
|
48
48
|
parts.push(`</div>`);
|
|
49
49
|
if (data.callout) {
|
|
@@ -5,19 +5,20 @@ const buildPanel = (panel) => {
|
|
|
5
5
|
const inner = [];
|
|
6
6
|
inner.push(`<h3 class="text-xl font-bold text-${c(accent)} font-body">${escapeHtml(panel.title)}</h3>`);
|
|
7
7
|
if (panel.content) {
|
|
8
|
-
inner.push(`<div class="mt-4 space-y-3">`);
|
|
8
|
+
inner.push(`<div class="mt-4 space-y-3 flex-1 min-h-0 overflow-hidden flex flex-col">`);
|
|
9
9
|
inner.push(renderContentBlocks(panel.content));
|
|
10
10
|
inner.push(`</div>`);
|
|
11
11
|
}
|
|
12
12
|
if (panel.footer) {
|
|
13
|
-
|
|
13
|
+
if (!panel.content)
|
|
14
|
+
inner.push(`<div class="flex-1"></div>`);
|
|
14
15
|
inner.push(`<p class="text-sm text-d-dim font-body mt-3">${escapeHtml(panel.footer)}</p>`);
|
|
15
16
|
}
|
|
16
17
|
return cardWrap(accent, inner.join("\n"), "flex-1");
|
|
17
18
|
};
|
|
18
19
|
export const layoutComparison = (data) => {
|
|
19
20
|
const parts = [slideHeader(data)];
|
|
20
|
-
parts.push(`<div class="flex gap-5 px-12 mt-5 flex-1">`);
|
|
21
|
+
parts.push(`<div class="flex gap-5 px-12 mt-5 flex-1 min-h-0 items-stretch">`);
|
|
21
22
|
parts.push(buildPanel(data.left));
|
|
22
23
|
parts.push(buildPanel(data.right));
|
|
23
24
|
parts.push(`</div>`);
|