mulmocast 2.6.15 → 2.6.17

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 (65) hide show
  1. package/lib/actions/index.d.ts +1 -0
  2. package/lib/actions/index.js +1 -0
  3. package/lib/actions/viewer.d.ts +3 -0
  4. package/lib/actions/viewer.js +173 -0
  5. package/lib/cli/bin.js +0 -0
  6. package/lib/cli/commands/viewer/builder.d.ts +20 -0
  7. package/lib/cli/commands/viewer/builder.js +6 -0
  8. package/lib/cli/commands/viewer/handler.d.ts +4 -0
  9. package/lib/cli/commands/viewer/handler.js +11 -0
  10. package/lib/cli/commands/viewer/index.d.ts +4 -0
  11. package/lib/cli/commands/viewer/index.js +4 -0
  12. package/lib/cli/main.js +2 -0
  13. package/lib/mcp/server.js +0 -0
  14. package/lib/types/schema.d.ts +458 -457
  15. package/lib/types/schema.js +3 -2
  16. package/lib/types/type.d.ts +1 -1
  17. package/lib/utils/context.d.ts +729 -728
  18. package/lib/utils/context.js +1 -0
  19. package/lib/utils/image_plugins/slide.d.ts +1 -1
  20. package/lib/utils/image_plugins/slide.js +1 -1
  21. package/package.json +12 -11
  22. package/lib/data/styles.d.ts +0 -255
  23. package/lib/data/styles.js +0 -284
  24. package/lib/slide/blocks.d.ts +0 -13
  25. package/lib/slide/blocks.js +0 -251
  26. package/lib/slide/index.d.ts +0 -6
  27. package/lib/slide/index.js +0 -7
  28. package/lib/slide/layouts/big_quote.d.ts +0 -2
  29. package/lib/slide/layouts/big_quote.js +0 -19
  30. package/lib/slide/layouts/columns.d.ts +0 -2
  31. package/lib/slide/layouts/columns.js +0 -53
  32. package/lib/slide/layouts/comparison.d.ts +0 -2
  33. package/lib/slide/layouts/comparison.js +0 -25
  34. package/lib/slide/layouts/funnel.d.ts +0 -2
  35. package/lib/slide/layouts/funnel.js +0 -25
  36. package/lib/slide/layouts/grid.d.ts +0 -2
  37. package/lib/slide/layouts/grid.js +0 -38
  38. package/lib/slide/layouts/index.d.ts +0 -3
  39. package/lib/slide/layouts/index.js +0 -46
  40. package/lib/slide/layouts/matrix.d.ts +0 -2
  41. package/lib/slide/layouts/matrix.js +0 -53
  42. package/lib/slide/layouts/split.d.ts +0 -2
  43. package/lib/slide/layouts/split.js +0 -51
  44. package/lib/slide/layouts/stats.d.ts +0 -2
  45. package/lib/slide/layouts/stats.js +0 -23
  46. package/lib/slide/layouts/table.d.ts +0 -2
  47. package/lib/slide/layouts/table.js +0 -10
  48. package/lib/slide/layouts/timeline.d.ts +0 -2
  49. package/lib/slide/layouts/timeline.js +0 -27
  50. package/lib/slide/layouts/title.d.ts +0 -2
  51. package/lib/slide/layouts/title.js +0 -19
  52. package/lib/slide/layouts/waterfall.d.ts +0 -2
  53. package/lib/slide/layouts/waterfall.js +0 -63
  54. package/lib/slide/render.d.ts +0 -17
  55. package/lib/slide/render.js +0 -101
  56. package/lib/slide/schema.d.ts +0 -9309
  57. package/lib/slide/schema.js +0 -434
  58. package/lib/slide/utils.d.ts +0 -76
  59. package/lib/slide/utils.js +0 -243
  60. package/lib/types/slide.d.ts +0 -9309
  61. package/lib/types/slide.js +0 -434
  62. package/lib/utils/browser_pool.d.ts +0 -5
  63. package/lib/utils/browser_pool.js +0 -39
  64. package/lib/utils/markdown.d.ts +0 -3
  65. package/lib/utils/markdown.js +0 -49
@@ -8,4 +8,5 @@ export * from "./pdf.js";
8
8
  export * from "./translate.js";
9
9
  export * from "./markdown.js";
10
10
  export * from "./html.js";
11
+ export * from "./viewer.js";
11
12
  export * from "./bundle.js";
@@ -8,4 +8,5 @@ export * from "./pdf.js";
8
8
  export * from "./translate.js";
9
9
  export * from "./markdown.js";
10
10
  export * from "./html.js";
11
+ export * from "./viewer.js";
11
12
  export * from "./bundle.js";
@@ -0,0 +1,3 @@
1
+ import { MulmoStudioContext } from "../types/index.js";
2
+ export declare const viewerFilePath: (context: MulmoStudioContext) => string;
3
+ export declare const viewer: (context: MulmoStudioContext) => Promise<void>;
@@ -0,0 +1,173 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { localizedText } from "../utils/utils.js";
4
+ import { writingMessage } from "../utils/file.js";
5
+ import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
6
+ import { escapeHtml } from "@mulmocast/deck";
7
+ const imageMimeTypes = {
8
+ png: "image/png",
9
+ jpg: "image/jpeg",
10
+ jpeg: "image/jpeg",
11
+ gif: "image/gif",
12
+ webp: "image/webp",
13
+ svg: "image/svg+xml",
14
+ };
15
+ const imageToDataUri = (filePath) => {
16
+ if (!fs.existsSync(filePath)) {
17
+ return null;
18
+ }
19
+ const ext = path.extname(filePath).slice(1).toLowerCase();
20
+ const mime = imageMimeTypes[ext] ?? "image/png";
21
+ const base64 = fs.readFileSync(filePath).toString("base64");
22
+ return `data:${mime};base64,${base64}`;
23
+ };
24
+ const collectSlides = (context) => {
25
+ const { studio, multiLingual, lang = "en" } = context;
26
+ const slides = [];
27
+ studio.script.beats.forEach((beat, index) => {
28
+ const studioBeat = studio.beats[index];
29
+ // Prefer the HTML-rendered frame over the source image, matching pdf.ts / movie.ts.
30
+ const source = studioBeat?.htmlImageFile ?? studioBeat?.imageFile;
31
+ if (!source)
32
+ return;
33
+ const dataUri = imageToDataUri(source);
34
+ if (!dataUri)
35
+ return;
36
+ slides.push({
37
+ dataUri,
38
+ caption: localizedText(beat, multiLingual?.[index], lang),
39
+ });
40
+ });
41
+ return slides;
42
+ };
43
+ const viewerStyles = `
44
+ html, body { margin: 0; padding: 0; height: 100vh; overflow: hidden; background: #000; }
45
+ #deck { position: relative; width: 100vw; height: 100vh; }
46
+ section.slide {
47
+ position: absolute;
48
+ inset: 0;
49
+ display: flex;
50
+ flex-direction: column;
51
+ align-items: center;
52
+ justify-content: center;
53
+ visibility: hidden;
54
+ padding: 24px;
55
+ box-sizing: border-box;
56
+ }
57
+ section.slide.active { visibility: visible; }
58
+ section.slide img {
59
+ max-width: 100%;
60
+ max-height: 80vh;
61
+ object-fit: contain;
62
+ user-select: none;
63
+ }
64
+ section.slide p.caption {
65
+ color: #eee;
66
+ margin-top: 16px;
67
+ text-align: center;
68
+ font-family: system-ui, -apple-system, sans-serif;
69
+ max-width: 80ch;
70
+ max-height: 15vh;
71
+ overflow: hidden;
72
+ }
73
+ #counter {
74
+ position: fixed;
75
+ right: 16px;
76
+ bottom: 12px;
77
+ color: #aaa;
78
+ font-family: system-ui, -apple-system, sans-serif;
79
+ font-size: 14px;
80
+ user-select: none;
81
+ pointer-events: none;
82
+ }
83
+ `;
84
+ const viewerScript = `
85
+ (function () {
86
+ const slides = document.querySelectorAll("section.slide");
87
+ const counter = document.getElementById("counter");
88
+ if (slides.length === 0) return;
89
+ let current = 0;
90
+ const show = (i) => {
91
+ slides[current].classList.remove("active");
92
+ current = Math.max(0, Math.min(slides.length - 1, i));
93
+ slides[current].classList.add("active");
94
+ counter.textContent = (current + 1) + " / " + slides.length;
95
+ };
96
+ document.addEventListener("keydown", (e) => {
97
+ if (e.key === "ArrowRight" || e.key === " " || e.key === "PageDown") {
98
+ e.preventDefault();
99
+ show(current + 1);
100
+ } else if (e.key === "ArrowLeft" || e.key === "PageUp") {
101
+ e.preventDefault();
102
+ show(current - 1);
103
+ } else if (e.key === "Home") {
104
+ e.preventDefault();
105
+ show(0);
106
+ } else if (e.key === "End") {
107
+ e.preventDefault();
108
+ show(slides.length - 1);
109
+ } else if (e.key === "f" || e.key === "F") {
110
+ if (!document.fullscreenElement) {
111
+ document.documentElement.requestFullscreen && document.documentElement.requestFullscreen();
112
+ } else {
113
+ document.exitFullscreen && document.exitFullscreen();
114
+ }
115
+ } else if (e.key === "Escape") {
116
+ document.exitFullscreen && document.exitFullscreen();
117
+ }
118
+ });
119
+ document.addEventListener("click", () => show(current + 1));
120
+ show(0);
121
+ })();
122
+ `;
123
+ const generateViewerHtml = (context) => {
124
+ const title = context.studio.script.title || "MulmoCast Viewer";
125
+ const slides = collectSlides(context);
126
+ const slidesHtml = slides
127
+ .map((s, i) => {
128
+ const captionHtml = s.caption.trim() ? `<p class="caption">${escapeHtml(s.caption)}</p>` : "";
129
+ const cls = i === 0 ? "slide active" : "slide";
130
+ return ` <section class="${cls}"><img src="${s.dataUri}" alt="Slide ${i + 1}" />${captionHtml}</section>`;
131
+ })
132
+ .join("\n");
133
+ return `<!doctype html>
134
+ <html lang="en">
135
+ <head>
136
+ <meta charset="UTF-8" />
137
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
138
+ <title>${escapeHtml(title)}</title>
139
+ <style>${viewerStyles}</style>
140
+ </head>
141
+ <body>
142
+ <div id="deck">
143
+ ${slidesHtml}
144
+ </div>
145
+ <div id="counter"></div>
146
+ <script>${viewerScript}</script>
147
+ </body>
148
+ </html>
149
+ `;
150
+ };
151
+ export const viewerFilePath = (context) => {
152
+ const { studio, fileDirs, lang = "en" } = context;
153
+ const langSuffix = studio.script.lang !== lang ? `_${lang}` : "";
154
+ const filename = `${studio.filename}${langSuffix}_viewer.html`;
155
+ return path.join(fileDirs.outDirPath, filename);
156
+ };
157
+ const generateViewer = (context) => {
158
+ const outputPath = viewerFilePath(context);
159
+ const htmlContent = generateViewerHtml(context);
160
+ fs.writeFileSync(outputPath, htmlContent, "utf8");
161
+ writingMessage(outputPath);
162
+ };
163
+ export const viewer = async (context) => {
164
+ try {
165
+ MulmoStudioContextMethods.setSessionState(context, "viewer", true);
166
+ generateViewer(context);
167
+ MulmoStudioContextMethods.setSessionState(context, "viewer", false, true);
168
+ }
169
+ catch (error) {
170
+ MulmoStudioContextMethods.setSessionState(context, "viewer", false, false);
171
+ throw error;
172
+ }
173
+ };
package/lib/cli/bin.js CHANGED
File without changes
@@ -0,0 +1,20 @@
1
+ import type { Argv } from "yargs";
2
+ export declare const builder: (yargs: Argv) => Argv<{
3
+ o: string | undefined;
4
+ } & {
5
+ b: string | undefined;
6
+ } & {
7
+ l: string | undefined;
8
+ } & {
9
+ f: boolean;
10
+ } & {
11
+ g: boolean;
12
+ } & {
13
+ backup: boolean;
14
+ } & {
15
+ p: string | undefined;
16
+ } & {
17
+ file: string | undefined;
18
+ } & {
19
+ i: string | undefined;
20
+ }>;
@@ -0,0 +1,6 @@
1
+ import { commonOptions } from "../../common.js";
2
+ export const builder = (yargs) => commonOptions(yargs).option("i", {
3
+ alias: "imagedir",
4
+ describe: "Image output directory",
5
+ type: "string",
6
+ });
@@ -0,0 +1,4 @@
1
+ import { CliArgs } from "../../../types/cli_types.js";
2
+ export declare const handler: (argv: CliArgs<{
3
+ i?: string;
4
+ }>) => Promise<void>;
@@ -0,0 +1,11 @@
1
+ import { images, viewer } from "../../../actions/index.js";
2
+ import { initializeContext, runTranslateIfNeeded } from "../../helpers.js";
3
+ export const handler = async (argv) => {
4
+ const context = await initializeContext(argv);
5
+ if (!context) {
6
+ process.exit(1);
7
+ }
8
+ await runTranslateIfNeeded(context);
9
+ await images(context);
10
+ await viewer(context);
11
+ };
@@ -0,0 +1,4 @@
1
+ export declare const command = "viewer <file>";
2
+ export declare const desc = "Generate a zero-dependency, single-file HTML slideshow viewer (openable via file://)";
3
+ export { builder } from "./builder.js";
4
+ export { handler } from "./handler.js";
@@ -0,0 +1,4 @@
1
+ export const command = "viewer <file>";
2
+ export const desc = "Generate a zero-dependency, single-file HTML slideshow viewer (openable via file://)";
3
+ export { builder } from "./builder.js";
4
+ export { handler } from "./handler.js";
package/lib/cli/main.js CHANGED
@@ -12,6 +12,7 @@ import * as pdfCmd from "./commands/pdf/index.js";
12
12
  import * as markdownCmd from "./commands/markdown/index.js";
13
13
  import * as bundleCmd from "./commands/bundle/index.js";
14
14
  import * as htmlCmd from "./commands/html/index.js";
15
+ import * as viewerCmd from "./commands/viewer/index.js";
15
16
  import * as toolCmd from "./commands/tool/index.js";
16
17
  import { GraphAILogger } from "graphai";
17
18
  dotenv.config({ quiet: true });
@@ -42,6 +43,7 @@ export const cliMain = async () => {
42
43
  .command(markdownCmd)
43
44
  .command(bundleCmd)
44
45
  .command(htmlCmd)
46
+ .command(viewerCmd)
45
47
  .command(toolCmd)
46
48
  .demandCommand()
47
49
  .strict()
package/lib/mcp/server.js CHANGED
File without changes