mulmocast 0.0.2 → 0.0.3

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 (74) hide show
  1. package/README.md +27 -9
  2. package/assets/font/NotoSansJP-Regular.ttf +0 -0
  3. package/assets/html/chart.html +1 -10
  4. package/assets/html/mermaid.html +1 -13
  5. package/assets/templates/business.json +16 -27
  6. package/assets/templates/coding.json +58 -21
  7. package/lib/actions/audio.d.ts +1 -1
  8. package/lib/actions/audio.js +43 -27
  9. package/lib/actions/images.js +20 -26
  10. package/lib/actions/index.d.ts +5 -0
  11. package/lib/actions/index.js +5 -0
  12. package/lib/actions/movie.d.ts +9 -1
  13. package/lib/actions/movie.js +97 -38
  14. package/lib/actions/pdf.d.ts +2 -0
  15. package/lib/actions/pdf.js +211 -0
  16. package/lib/actions/pdf2.d.ts +2 -0
  17. package/lib/actions/pdf2.js +203 -0
  18. package/lib/actions/translate.js +22 -9
  19. package/lib/agents/anthropic_agent.d.ts +23 -0
  20. package/lib/agents/anthropic_agent.js +162 -0
  21. package/lib/agents/combine_audio_files_agent.js +13 -22
  22. package/lib/agents/nested_agent.d.ts +9 -0
  23. package/lib/agents/nested_agent.js +138 -0
  24. package/lib/cli/args.d.ts +3 -1
  25. package/lib/cli/args.js +49 -34
  26. package/lib/cli/cli.d.ts +14 -0
  27. package/lib/cli/cli.js +48 -46
  28. package/lib/cli/tool-args.d.ts +2 -0
  29. package/lib/cli/tool-args.js +12 -2
  30. package/lib/cli/tool-cli.js +6 -4
  31. package/lib/methods/index.d.ts +1 -0
  32. package/lib/methods/index.js +1 -0
  33. package/lib/methods/mulmo_media_source.d.ts +4 -0
  34. package/lib/methods/mulmo_media_source.js +21 -0
  35. package/lib/methods/mulmo_script.d.ts +2 -6
  36. package/lib/methods/mulmo_script.js +12 -5
  37. package/lib/tools/create_mulmo_script_interactively.d.ts +1 -1
  38. package/lib/tools/create_mulmo_script_interactively.js +61 -20
  39. package/lib/types/index.d.ts +1 -0
  40. package/lib/types/index.js +1 -0
  41. package/lib/types/schema.d.ts +3626 -3162
  42. package/lib/types/schema.js +75 -41
  43. package/lib/types/type.d.ts +28 -1
  44. package/lib/utils/const.d.ts +2 -0
  45. package/lib/utils/const.js +2 -0
  46. package/lib/utils/file.d.ts +4 -1
  47. package/lib/utils/file.js +15 -1
  48. package/lib/utils/filters.js +1 -1
  49. package/lib/utils/image_plugins/chart.d.ts +3 -0
  50. package/lib/utils/image_plugins/chart.js +18 -0
  51. package/lib/utils/image_plugins/image.d.ts +2 -0
  52. package/lib/utils/image_plugins/image.js +3 -0
  53. package/lib/utils/image_plugins/index.d.ts +7 -0
  54. package/lib/utils/image_plugins/index.js +7 -0
  55. package/lib/utils/image_plugins/markdown.d.ts +3 -0
  56. package/lib/utils/image_plugins/markdown.js +11 -0
  57. package/lib/utils/image_plugins/mermaid.d.ts +3 -0
  58. package/lib/utils/image_plugins/mermaid.js +21 -0
  59. package/lib/utils/image_plugins/movie.d.ts +2 -0
  60. package/lib/utils/image_plugins/movie.js +3 -0
  61. package/lib/utils/image_plugins/source.d.ts +4 -0
  62. package/lib/utils/image_plugins/source.js +15 -0
  63. package/lib/utils/image_plugins/text_slide.d.ts +3 -0
  64. package/lib/utils/image_plugins/text_slide.js +12 -0
  65. package/lib/utils/image_plugins/type_guards.d.ts +6 -0
  66. package/lib/utils/image_plugins/type_guards.js +21 -0
  67. package/lib/utils/markdown.js +4 -1
  68. package/lib/utils/pdf.d.ts +8 -0
  69. package/lib/utils/pdf.js +75 -0
  70. package/lib/utils/preprocess.d.ts +58 -128
  71. package/lib/utils/preprocess.js +37 -37
  72. package/lib/utils/utils.d.ts +12 -0
  73. package/lib/utils/utils.js +34 -0
  74. package/package.json +13 -4
@@ -22,56 +22,57 @@ export const speechOptionsSchema = z
22
22
  const speakerIdSchema = z.string();
23
23
  const speakerDataSchema = z
24
24
  .object({
25
- displayName: z.record(langSchema, z.string()),
25
+ displayName: z.record(langSchema, z.string()).optional(),
26
26
  voiceId: z.string(),
27
27
  speechOptions: speechOptionsSchema.optional(),
28
28
  })
29
29
  .strict();
30
30
  export const speakerDictionarySchema = z.record(speakerIdSchema, speakerDataSchema);
31
- const mediaSourceSchema = z.discriminatedUnion("kind", [
31
+ export const mediaSourceSchema = z.discriminatedUnion("kind", [
32
32
  z.object({ kind: z.literal("url"), url: URLStringSchema }).strict(), // https://example.com/foo.pdf
33
- z.object({ kind: z.literal("data"), data: z.string() }).strict(), // base64
33
+ z.object({ kind: z.literal("base64"), data: z.string() }).strict(), // base64
34
+ z.object({ kind: z.literal("text"), text: z.string() }).strict(), // plain text
34
35
  z.object({ kind: z.literal("path"), path: z.string() }).strict(), // foo.pdf
35
36
  ]);
36
37
  // String is easier for AI, string array is easier for human
37
38
  const stringOrStringArray = z.union([z.string(), z.array(z.string())]);
38
- const MulmoMarkdownMediaSchema = z
39
+ export const mulmoMarkdownMediaSchema = z
39
40
  .object({
40
41
  type: z.literal("markdown"),
41
42
  markdown: stringOrStringArray,
42
43
  })
43
44
  .strict();
44
- const MulmoWebMediaSchema = z
45
+ const mulmoWebMediaSchema = z
45
46
  .object({
46
47
  type: z.literal("web"),
47
48
  url: URLStringSchema,
48
49
  })
49
50
  .strict();
50
- const MulmoPdfMediaSchema = z
51
+ const mulmoPdfMediaSchema = z
51
52
  .object({
52
53
  type: z.literal("pdf"),
53
54
  source: mediaSourceSchema,
54
55
  })
55
56
  .strict();
56
- const MulmoImageMediaSchema = z
57
+ export const mulmoImageMediaSchema = z
57
58
  .object({
58
59
  type: z.literal("image"),
59
60
  source: mediaSourceSchema,
60
61
  })
61
62
  .strict();
62
- const MulmoSvgMediaSchema = z
63
+ const mulmoSvgMediaSchema = z
63
64
  .object({
64
65
  type: z.literal("svg"),
65
66
  source: mediaSourceSchema,
66
67
  })
67
68
  .strict();
68
- const MulmoMovieMediaSchema = z
69
+ const mulmoMovieMediaSchema = z
69
70
  .object({
70
71
  type: z.literal("movie"),
71
72
  source: mediaSourceSchema,
72
73
  })
73
74
  .strict();
74
- const MulmoTextSlideMediaSchema = z
75
+ export const mulmoTextSlideMediaSchema = z
75
76
  .object({
76
77
  type: z.literal("textSlide"),
77
78
  slide: z.object({
@@ -80,44 +81,45 @@ const MulmoTextSlideMediaSchema = z
80
81
  }),
81
82
  })
82
83
  .strict();
83
- const MulmoChartMediaSchema = z
84
+ export const mulmoChartMediaSchema = z
84
85
  .object({
85
86
  type: z.literal("chart"),
86
87
  title: z.string(),
87
88
  chartData: z.record(z.any()),
88
89
  })
89
90
  .strict();
90
- const MulmoMermaidMediaSchema = z
91
+ export const mulmoMermaidMediaSchema = z
91
92
  .object({
92
93
  type: z.literal("mermaid"),
93
94
  title: z.string().describe("The title of the diagram"),
94
- code: z.string().describe("The code of the mermaid diagram"),
95
+ code: mediaSourceSchema.describe("The code of the mermaid diagram"),
96
+ appendix: z.array(z.string()).optional().describe("The appendix of the mermaid diagram; typically, style information."),
95
97
  })
96
98
  .strict();
97
99
  export const mulmoImageAssetSchema = z.union([
98
- MulmoMarkdownMediaSchema,
99
- MulmoWebMediaSchema,
100
- MulmoPdfMediaSchema,
101
- MulmoImageMediaSchema,
102
- MulmoSvgMediaSchema,
103
- MulmoMovieMediaSchema,
104
- MulmoTextSlideMediaSchema,
105
- MulmoChartMediaSchema,
106
- MulmoMermaidMediaSchema,
100
+ mulmoMarkdownMediaSchema,
101
+ mulmoWebMediaSchema,
102
+ mulmoPdfMediaSchema,
103
+ mulmoImageMediaSchema,
104
+ mulmoSvgMediaSchema,
105
+ mulmoMovieMediaSchema,
106
+ mulmoTextSlideMediaSchema,
107
+ mulmoChartMediaSchema,
108
+ mulmoMermaidMediaSchema,
107
109
  ]);
108
- const MulmoAudioMediaSchema = z
110
+ const mulmoAudioMediaSchema = z
109
111
  .object({
110
112
  type: z.literal("audio"),
111
113
  source: mediaSourceSchema,
112
114
  })
113
115
  .strict();
114
- const MulmoMidiMediaSchema = z
116
+ const mulmoMidiMediaSchema = z
115
117
  .object({
116
118
  type: z.literal("midi"),
117
119
  source: z.string(), // TODO: define it later
118
120
  })
119
121
  .strict();
120
- export const mulmoAudioAssetSchema = z.union([MulmoAudioMediaSchema, MulmoMidiMediaSchema]);
122
+ export const mulmoAudioAssetSchema = z.union([mulmoAudioMediaSchema, mulmoMidiMediaSchema]);
121
123
  export const mulmoImageParamsSchema = z
122
124
  .object({
123
125
  model: z.string().optional(), // default: provider specific
@@ -128,7 +130,7 @@ export const mulmoImageParamsSchema = z
128
130
  .strict();
129
131
  export const textSlideParamsSchema = z
130
132
  .object({
131
- cssStyles: z.array(z.string()),
133
+ cssStyles: stringOrStringArray,
132
134
  })
133
135
  .strict();
134
136
  export const videoParamsSchema = z
@@ -138,7 +140,7 @@ export const videoParamsSchema = z
138
140
  .strict();
139
141
  export const mulmoBeatSchema = z
140
142
  .object({
141
- speaker: speakerIdSchema,
143
+ speaker: speakerIdSchema.default("Presenter"),
142
144
  text: z.string(),
143
145
  image: mulmoImageAssetSchema.optional(),
144
146
  audio: mulmoAudioAssetSchema.optional(),
@@ -169,17 +171,19 @@ export const mulmoSpeechParamsSchema = z
169
171
  })
170
172
  .strict();
171
173
  export const text2ImageProviderSchema = z.union([z.literal("openai"), z.literal("google")]).default("openai");
172
- export const mulmoScriptSchema = z
173
- .object({
174
- // global settings
174
+ export const mulmoPresentationStyleSchema = z.object({
175
175
  $mulmocast: mulmoCastCreditSchema,
176
- title: z.string(),
177
- description: z.string().optional(),
178
- reference: z.string().optional(),
179
- lang: langSchema.optional(), // default "en"
180
176
  canvasSize: mulmoCanvasDimensionSchema, // has default value
181
- beats: z.array(mulmoBeatSchema),
182
- speechParams: mulmoSpeechParamsSchema,
177
+ speechParams: mulmoSpeechParamsSchema.default({
178
+ speakers: {
179
+ Presenter: {
180
+ voiceId: "shimmer",
181
+ displayName: {
182
+ en: "Presenter",
183
+ },
184
+ },
185
+ },
186
+ }),
183
187
  imageParams: mulmoImageParamsSchema
184
188
  .extend({
185
189
  provider: text2ImageProviderSchema, // has default value
@@ -188,15 +192,30 @@ export const mulmoScriptSchema = z
188
192
  // for textSlides
189
193
  textSlideParams: textSlideParamsSchema.optional(),
190
194
  videoParams: videoParamsSchema.optional(),
191
- // images: ImageInfo[] // generated
192
- imagePath: z.string().optional(), // for keynote images movie ??
195
+ // TODO: Switch to showCaptions later
193
196
  omitCaptions: z.boolean().optional(), // default is false
197
+ });
198
+ export const mulmoReferenceSchema = z.object({
199
+ url: URLStringSchema,
200
+ title: z.string().optional(),
201
+ description: z.string().optional(),
202
+ type: z.union([z.literal("article"), z.literal("image"), z.literal("video"), z.literal("audio")]).default("article"),
203
+ });
204
+ export const mulmoScriptSchema = mulmoPresentationStyleSchema
205
+ .extend({
206
+ title: z.string().optional(),
207
+ description: z.string().optional(),
208
+ references: z.array(mulmoReferenceSchema).optional(),
209
+ lang: langSchema.optional(), // default "en"
210
+ beats: z.array(mulmoBeatSchema).min(1),
211
+ // TODO: Delete it later
212
+ imagePath: z.string().optional(), // for keynote images movie ??
194
213
  // for debugging
195
214
  __test_invalid__: z.boolean().optional(),
196
215
  })
197
216
  .strict();
198
- export const mulmoStudioBeatSchema = mulmoBeatSchema
199
- .extend({
217
+ export const mulmoStudioBeatSchema = z
218
+ .object({
200
219
  multiLingualTexts: multiLingualTextsSchema.optional(),
201
220
  hash: z.string().optional(),
202
221
  duration: z.number().optional(),
@@ -208,7 +227,7 @@ export const mulmoStudioSchema = z
208
227
  .object({
209
228
  script: mulmoScriptSchema,
210
229
  filename: z.string(),
211
- beats: z.array(mulmoStudioBeatSchema),
230
+ beats: z.array(mulmoStudioBeatSchema).min(1),
212
231
  })
213
232
  .strict();
214
233
  export const mulmoScriptTemplateSchema = z
@@ -219,4 +238,19 @@ export const mulmoScriptTemplateSchema = z
219
238
  script: mulmoScriptSchema.optional(),
220
239
  })
221
240
  .strict();
241
+ export const mulmoStoryboardSceneSchema = z
242
+ .object({
243
+ description: z.string(),
244
+ references: z.array(mulmoReferenceSchema).optional(),
245
+ })
246
+ .describe("A detailed description of the content of the scene, not the presentation style")
247
+ .strict();
248
+ export const mulmoStoryboardSchema = z
249
+ .object({
250
+ title: z.string(),
251
+ references: z.array(mulmoReferenceSchema).optional(),
252
+ scenes: z.array(mulmoStoryboardSceneSchema),
253
+ })
254
+ .describe("A storyboard for a presentation, a story, a video, etc.")
255
+ .strict();
222
256
  export const urlsSchema = z.array(z.string().url({ message: "Invalid URL format" }));
@@ -1,4 +1,5 @@
1
- import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoSpeechParamsSchema, textSlideParamsSchema, speechOptionsSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, text2ImageProviderSchema, text2SpeechProviderSchema } from "./schema.js";
1
+ import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoSpeechParamsSchema, textSlideParamsSchema, speechOptionsSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, text2ImageProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema } from "./schema.js";
2
+ import { pdf_modes, pdf_sizes } from "../utils/const.js";
2
3
  import { z } from "zod";
3
4
  export type LANG = z.infer<typeof langSchema>;
4
5
  export type MulmoBeat = z.infer<typeof mulmoBeatSchema>;
@@ -11,10 +12,19 @@ export type Text2ImageProvider = z.infer<typeof text2ImageProviderSchema>;
11
12
  export type Text2SpeechProvider = z.infer<typeof text2SpeechProviderSchema>;
12
13
  export type LocalizedText = z.infer<typeof localizedTextSchema>;
13
14
  export type MulmoScript = z.infer<typeof mulmoScriptSchema>;
15
+ export type MulmoPresentationStyle = z.infer<typeof mulmoPresentationStyleSchema>;
14
16
  export type MulmoCanvasDimension = z.infer<typeof mulmoCanvasDimensionSchema>;
17
+ export type MulmoStoryboardScene = z.infer<typeof mulmoStoryboardSceneSchema>;
18
+ export type MulmoStoryboard = z.infer<typeof mulmoStoryboardSchema>;
15
19
  export type MulmoStudioBeat = z.infer<typeof mulmoStudioBeatSchema>;
20
+ export type MulmoMediaSource = z.infer<typeof mediaSourceSchema>;
16
21
  export type MulmoStudio = z.infer<typeof mulmoStudioSchema>;
17
22
  export type MulmoScriptTemplate = z.infer<typeof mulmoScriptTemplateSchema>;
23
+ export type MulmoTextSlideMedia = z.infer<typeof mulmoTextSlideMediaSchema>;
24
+ export type MulmoMarkdownMedia = z.infer<typeof mulmoMarkdownMediaSchema>;
25
+ export type MulmoImageMedia = z.infer<typeof mulmoImageMediaSchema>;
26
+ export type MulmoChartMedia = z.infer<typeof mulmoChartMediaSchema>;
27
+ export type MulmoMermaidMedia = z.infer<typeof mulmoMermaidMediaSchema>;
18
28
  export type FileDirs = {
19
29
  mulmoFilePath: string;
20
30
  mulmoFileDirPath: string;
@@ -34,4 +44,21 @@ export type ScriptingParams = {
34
44
  cacheDirPath: string;
35
45
  templateName: string;
36
46
  filename: string;
47
+ llm_model?: string;
48
+ llm_agent?: string;
37
49
  };
50
+ export type ImageProcessorParams = {
51
+ beat: MulmoBeat;
52
+ context: MulmoStudioContext;
53
+ imagePath: string;
54
+ textSlideStyle: string;
55
+ canvasSize: MulmoCanvasDimension;
56
+ };
57
+ export type PDFMode = (typeof pdf_modes)[number];
58
+ export type PDFSize = (typeof pdf_sizes)[number];
59
+ export type Text2ImageAgentInfo = {
60
+ provider: Text2ImageProvider;
61
+ agent: string;
62
+ imageParams: MulmoImageParams;
63
+ };
64
+ export type BeatMediaType = "movie" | "image";
@@ -2,3 +2,5 @@ export declare const outDirName = "output";
2
2
  export declare const audioDirName = "audio";
3
3
  export declare const imageDirName = "images";
4
4
  export declare const cacheDirName = "cache";
5
+ export declare const pdf_modes: string[];
6
+ export declare const pdf_sizes: string[];
@@ -2,3 +2,5 @@ export const outDirName = "output";
2
2
  export const audioDirName = "audio";
3
3
  export const imageDirName = "images";
4
4
  export const cacheDirName = "cache";
5
+ export const pdf_modes = ["slide", "talk", "handout"];
6
+ export const pdf_sizes = ["letter", "a4"];
@@ -1,4 +1,5 @@
1
- import { MulmoScript, MulmoScriptTemplate } from "../types/index.js";
1
+ import { MulmoScript, MulmoScriptTemplate, MulmoMediaSource, MulmoStudioContext } from "../types/index.js";
2
+ import { PDFMode } from "../types/index.js";
2
3
  export declare function readMulmoScriptFile<T = MulmoScript>(path: string, errorMessage: string): {
3
4
  mulmoData: T;
4
5
  mulmoDataPath: string;
@@ -28,6 +29,7 @@ export declare const getAudioSegmentFilePath: (audioDirPath: string, studioFileN
28
29
  export declare const getAudioCombinedFilePath: (audioDirPath: string, fileName: string) => string;
29
30
  export declare const getAudioArtifactFilePath: (outDirPath: string, fileName: string) => string;
30
31
  export declare const getOutputVideoFilePath: (outDirPath: string, fileName: string) => string;
32
+ export declare const getOutputPdfFilePath: (outDirPath: string, fileName: string, pdfMode: PDFMode) => string;
31
33
  export declare const getTemplateFilePath: (templateName: string) => string;
32
34
  export declare const mkdir: (dirPath: string) => void;
33
35
  export declare const silentPath: string;
@@ -41,3 +43,4 @@ export declare const getAvailableTemplates: () => (MulmoScriptTemplate & {
41
43
  filename: string;
42
44
  })[];
43
45
  export declare const writingMessage: (filePath: string) => void;
46
+ export declare const resolveMediaSource: (source: MulmoMediaSource, context: MulmoStudioContext) => string | null;
package/lib/utils/file.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
+ import { parse as yamlParse } from "yaml";
3
4
  import { fileURLToPath } from "url";
4
5
  import { GraphAILogger } from "graphai";
5
6
  import { MulmoScriptTemplateMethods } from "../methods/mulmo_script_template.js";
7
+ import { MulmoStudioContextMethods } from "../methods/index.js";
6
8
  import { mulmoScriptTemplateSchema } from "../types/schema.js";
7
9
  const __filename = fileURLToPath(import.meta.url);
8
10
  const __dirname = path.dirname(__filename);
@@ -16,7 +18,7 @@ export function readMulmoScriptFile(arg2, errorMessage) {
16
18
  return null;
17
19
  }
18
20
  const scriptData = fs.readFileSync(scriptPath, "utf-8");
19
- const script = JSON.parse(scriptData);
21
+ const script = ([".yaml", ".yml"].includes(path.extname(scriptPath).toLowerCase()) ? yamlParse(scriptData) : JSON.parse(scriptData));
20
22
  const parsedPath = path.parse(scriptPath);
21
23
  return {
22
24
  mulmoData: script,
@@ -58,6 +60,9 @@ export const getAudioArtifactFilePath = (outDirPath, fileName) => {
58
60
  export const getOutputVideoFilePath = (outDirPath, fileName) => {
59
61
  return path.resolve(outDirPath, fileName + ".mp4");
60
62
  };
63
+ export const getOutputPdfFilePath = (outDirPath, fileName, pdfMode) => {
64
+ return path.resolve(outDirPath, fileName + "_" + pdfMode + ".pdf");
65
+ };
61
66
  export const getTemplateFilePath = (templateName) => {
62
67
  return path.resolve(__dirname, "../../assets/templates/" + templateName + ".json");
63
68
  };
@@ -117,3 +122,12 @@ export const getAvailableTemplates = () => {
117
122
  export const writingMessage = (filePath) => {
118
123
  GraphAILogger.info(`writing: ${filePath}`);
119
124
  };
125
+ export const resolveMediaSource = (source, context) => {
126
+ if (source.kind === "path") {
127
+ return MulmoStudioContextMethods.resolveAssetPath(context, source.path);
128
+ }
129
+ if (source.kind === "url") {
130
+ return source.url;
131
+ }
132
+ return null;
133
+ };
@@ -4,7 +4,7 @@ import path from "path";
4
4
  import fsPromise from "fs/promises";
5
5
  import { GraphAILogger } from "graphai";
6
6
  import { writingMessage } from "./file.js";
7
- import { text2hash } from "./text_hash.js";
7
+ import { text2hash } from "./utils.js";
8
8
  export const fileCacheAgentFilter = async (context, next) => {
9
9
  const { namedInputs } = context;
10
10
  const { file, text, force } = namedInputs;
@@ -0,0 +1,3 @@
1
+ import { ImageProcessorParams } from "../../types/index.js";
2
+ export declare const imageType = "chart";
3
+ export declare const process: (params: ImageProcessorParams) => Promise<string | undefined>;
@@ -0,0 +1,18 @@
1
+ import { getHTMLFile } from "../file.js";
2
+ import { renderHTMLToImage, interpolate } from "../markdown.js";
3
+ export const imageType = "chart";
4
+ const processChart = async (params) => {
5
+ const { beat, imagePath, canvasSize, textSlideStyle } = params;
6
+ if (!beat.image || beat.image.type !== imageType)
7
+ return;
8
+ const template = getHTMLFile("chart");
9
+ const htmlData = interpolate(template, {
10
+ title: beat.image.title,
11
+ style: textSlideStyle,
12
+ width: Math.round(canvasSize.width * 0.625).toString(),
13
+ chart_data: JSON.stringify(beat.image.chartData),
14
+ });
15
+ await renderHTMLToImage(htmlData, imagePath, canvasSize.width, canvasSize.height);
16
+ return imagePath;
17
+ };
18
+ export const process = processChart;
@@ -0,0 +1,2 @@
1
+ export declare const imageType = "image";
2
+ export declare const process: (params: import("../../types/type.js").ImageProcessorParams) => string | undefined;
@@ -0,0 +1,3 @@
1
+ import { processSource } from "./source.js";
2
+ export const imageType = "image";
3
+ export const process = processSource(imageType);
@@ -0,0 +1,7 @@
1
+ import * as pluginTextSlide from "./text_slide.js";
2
+ import * as pluginMarkdown from "./markdown.js";
3
+ import * as pluginImage from "./image.js";
4
+ import * as pluginChart from "./chart.js";
5
+ import * as pluginMermaid from "./mermaid.js";
6
+ import * as pluginMovie from "./movie.js";
7
+ export declare const imagePlugins: (typeof pluginTextSlide | typeof pluginMarkdown | typeof pluginImage | typeof pluginChart | typeof pluginMermaid | typeof pluginMovie)[];
@@ -0,0 +1,7 @@
1
+ import * as pluginTextSlide from "./text_slide.js";
2
+ import * as pluginMarkdown from "./markdown.js";
3
+ import * as pluginImage from "./image.js";
4
+ import * as pluginChart from "./chart.js";
5
+ import * as pluginMermaid from "./mermaid.js";
6
+ import * as pluginMovie from "./movie.js";
7
+ export const imagePlugins = [pluginTextSlide, pluginMarkdown, pluginImage, pluginChart, pluginMermaid, pluginMovie];
@@ -0,0 +1,3 @@
1
+ import { ImageProcessorParams } from "../../types/index.js";
2
+ export declare const imageType = "markdown";
3
+ export declare const process: (params: ImageProcessorParams) => Promise<string | undefined>;
@@ -0,0 +1,11 @@
1
+ import { renderMarkdownToImage } from "../markdown.js";
2
+ export const imageType = "markdown";
3
+ const processMarkdown = async (params) => {
4
+ const { beat, imagePath, textSlideStyle, canvasSize } = params;
5
+ if (!beat.image || beat.image.type !== imageType)
6
+ return;
7
+ const markdown = Array.isArray(beat.image.markdown) ? beat.image.markdown.join("\n") : beat.image.markdown;
8
+ await renderMarkdownToImage(markdown, textSlideStyle, imagePath, canvasSize.width, canvasSize.height);
9
+ return imagePath;
10
+ };
11
+ export const process = processMarkdown;
@@ -0,0 +1,3 @@
1
+ import { ImageProcessorParams } from "../../types/index.js";
2
+ export declare const imageType = "mermaid";
3
+ export declare const process: (params: ImageProcessorParams) => Promise<string | undefined>;
@@ -0,0 +1,21 @@
1
+ import { MulmoMediaSourceMethods } from "../../methods/index.js";
2
+ import { getHTMLFile } from "../file.js";
3
+ import { renderHTMLToImage, interpolate } from "../markdown.js";
4
+ export const imageType = "mermaid";
5
+ const processMermaid = async (params) => {
6
+ const { beat, imagePath, canvasSize, context, textSlideStyle } = params;
7
+ if (!beat.image || beat.image.type !== imageType)
8
+ return;
9
+ const template = getHTMLFile("mermaid");
10
+ const diagram_code = await MulmoMediaSourceMethods.getText(beat.image.code, context);
11
+ if (diagram_code) {
12
+ const htmlData = interpolate(template, {
13
+ title: beat.image.title,
14
+ style: textSlideStyle,
15
+ diagram_code: `${diagram_code}\n${beat.image.appendix?.join("\n") ?? ""}`,
16
+ });
17
+ await renderHTMLToImage(htmlData, imagePath, canvasSize.width, canvasSize.height);
18
+ }
19
+ return imagePath;
20
+ };
21
+ export const process = processMermaid;
@@ -0,0 +1,2 @@
1
+ export declare const imageType = "movie";
2
+ export declare const process: (params: import("../../types/type.js").ImageProcessorParams) => string | undefined;
@@ -0,0 +1,3 @@
1
+ import { processSource } from "./source.js";
2
+ export const imageType = "movie";
3
+ export const process = processSource(imageType);
@@ -0,0 +1,4 @@
1
+ import { ImageProcessorParams } from "../../types/index.js";
2
+ type ImageType = "image" | "movie";
3
+ export declare const processSource: (imageType: ImageType) => (params: ImageProcessorParams) => string | undefined;
4
+ export {};
@@ -0,0 +1,15 @@
1
+ import { GraphAILogger } from "graphai";
2
+ import { resolveMediaSource } from "../../utils/file.js";
3
+ export const processSource = (imageType) => {
4
+ return (params) => {
5
+ const { beat, context } = params;
6
+ if (!beat.image || beat.image.type !== imageType)
7
+ return;
8
+ const path = resolveMediaSource(beat.image.source, context);
9
+ if (path) {
10
+ return path;
11
+ }
12
+ GraphAILogger.error(`Image Plugin unknown ${imageType} source type:`, beat.image);
13
+ throw new Error(`ERROR: unknown ${imageType} source type`);
14
+ };
15
+ };
@@ -0,0 +1,3 @@
1
+ import { ImageProcessorParams } from "../../types/index.js";
2
+ export declare const imageType = "textSlide";
3
+ export declare const process: (params: ImageProcessorParams) => Promise<string | undefined>;
@@ -0,0 +1,12 @@
1
+ import { renderMarkdownToImage } from "../markdown.js";
2
+ export const imageType = "textSlide";
3
+ const processTextSlide = async (params) => {
4
+ const { beat, imagePath, textSlideStyle, canvasSize } = params;
5
+ if (!beat.image || beat.image.type !== imageType)
6
+ return;
7
+ const slide = beat.image.slide;
8
+ const markdown = `# ${slide.title}\n` + slide.bullets.map((text) => `- ${text}`).join("\n");
9
+ await renderMarkdownToImage(markdown, textSlideStyle, imagePath, canvasSize.width, canvasSize.height);
10
+ return imagePath;
11
+ };
12
+ export const process = processTextSlide;
@@ -0,0 +1,6 @@
1
+ import { MulmoTextSlideMedia, MulmoMarkdownMedia, MulmoImageMedia, MulmoChartMedia, MulmoMermaidMedia } from "../../types/index.js";
2
+ export declare const isMulmoImageTextSlide: (value: unknown) => value is MulmoTextSlideMedia;
3
+ export declare const isMulmoImageMarkdown: (value: unknown) => value is MulmoMarkdownMedia;
4
+ export declare const isMulmoImageImage: (value: unknown) => value is MulmoImageMedia;
5
+ export declare const isMulmoImageChart: (value: unknown) => value is MulmoChartMedia;
6
+ export declare const isMulmoImageMermaild: (value: unknown) => value is MulmoMermaidMedia;
@@ -0,0 +1,21 @@
1
+ import { mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mulmoMermaidMediaSchema, } from "../../types/index.js";
2
+ export const isMulmoImageTextSlide = (value) => {
3
+ const result = mulmoTextSlideMediaSchema.safeParse(value);
4
+ return result.success;
5
+ };
6
+ export const isMulmoImageMarkdown = (value) => {
7
+ const result = mulmoMarkdownMediaSchema.safeParse(value);
8
+ return result.success;
9
+ };
10
+ export const isMulmoImageImage = (value) => {
11
+ const result = mulmoImageMediaSchema.safeParse(value);
12
+ return result.success;
13
+ };
14
+ export const isMulmoImageChart = (value) => {
15
+ const result = mulmoChartMediaSchema.safeParse(value);
16
+ return result.success;
17
+ };
18
+ export const isMulmoImageMermaild = (value) => {
19
+ const result = mulmoMermaidMediaSchema.safeParse(value);
20
+ return result.success;
21
+ };
@@ -1,9 +1,12 @@
1
1
  import { GraphAILogger } from "graphai";
2
2
  import { marked } from "marked";
3
3
  import puppeteer from "puppeteer";
4
+ const isCI = process.env.CI === "true";
4
5
  export const renderHTMLToImage = async (html, outputPath, width, height) => {
5
6
  // Use Puppeteer to render HTML to an image
6
- const browser = await puppeteer.launch();
7
+ const browser = await puppeteer.launch({
8
+ args: isCI ? ["--no-sandbox"] : [],
9
+ });
7
10
  const page = await browser.newPage();
8
11
  // Set the page content to the HTML generated from the Markdown
9
12
  await page.setContent(html);
@@ -0,0 +1,8 @@
1
+ import { PDFFont } from "pdf-lib";
2
+ export declare const fontSize = 12;
3
+ export declare const textMargin = 6;
4
+ export declare const drawSize: (fitWidth: boolean, expectWidth: number, expectHeight: number, origWidth: number, origHeight: number) => {
5
+ drawWidth: number;
6
+ drawHeight: number;
7
+ };
8
+ export declare const wrapText: (text: string, font: PDFFont, fontSize: number, maxWidth: number) => string[];
@@ -0,0 +1,75 @@
1
+ export const fontSize = 12;
2
+ export const textMargin = 6;
3
+ export const drawSize = (fitWidth, expectWidth, expectHeight, origWidth, origHeight) => {
4
+ if (fitWidth) {
5
+ const drawWidth = expectWidth;
6
+ const scale = drawWidth / origWidth;
7
+ const drawHeight = origHeight * scale;
8
+ return {
9
+ drawWidth,
10
+ drawHeight,
11
+ };
12
+ }
13
+ const drawHeight = expectHeight;
14
+ const scale = drawHeight / origHeight;
15
+ const drawWidth = origWidth * scale;
16
+ return {
17
+ drawWidth,
18
+ drawHeight,
19
+ };
20
+ };
21
+ const isFullwidth = (char) => {
22
+ const code = char.charCodeAt(0);
23
+ return ((code >= 0x3000 && code <= 0x9fff) || // CJK, punctuation, kana
24
+ (code >= 0xff00 && code <= 0xffef) // Fullwidth ASCII
25
+ );
26
+ };
27
+ export const wrapText = (text, font, fontSize, maxWidth) => {
28
+ const lines = [];
29
+ for (const rawLine of text.split("\n")) {
30
+ let line = "";
31
+ let buffer = "";
32
+ for (let i = 0; i < rawLine.length; i++) {
33
+ const char = rawLine[i];
34
+ buffer += char;
35
+ const width = font.widthOfTextAtSize(line + buffer, fontSize);
36
+ const nextChar = rawLine[i + 1];
37
+ const currentIsFull = isFullwidth(char);
38
+ const nextIsFull = nextChar && isFullwidth(nextChar);
39
+ const isBreakable = currentIsFull || (!currentIsFull && (char === " " || nextChar === " " || nextIsFull));
40
+ if (width > maxWidth && buffer) {
41
+ lines.push(line);
42
+ line = "";
43
+ buffer = char;
44
+ }
45
+ if (isBreakable || i === rawLine.length - 1) {
46
+ line += buffer;
47
+ buffer = "";
48
+ }
49
+ }
50
+ if (line)
51
+ lines.push(line);
52
+ }
53
+ return lines;
54
+ };
55
+ /*
56
+ export const wrapText = (text: string, font: PDFFont, fontSize: number, maxWidth: number) => {
57
+ const words = text.split(" ");
58
+ const lines = [];
59
+ let currentLine = "";
60
+
61
+ for (const word of words) {
62
+ const nextLine = currentLine ? `${currentLine} ${word}` : word;
63
+ // console.log(nextLine);
64
+ const width = font.widthOfTextAtSize(nextLine ?? "", fontSize);
65
+ if (width <= maxWidth) {
66
+ currentLine = nextLine;
67
+ } else {
68
+ lines.push(currentLine);
69
+ currentLine = word;
70
+ }
71
+ }
72
+ if (currentLine) lines.push(currentLine);
73
+ return lines;
74
+ };
75
+ */