mulmocast 2.6.16 → 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 (53) hide show
  1. package/lib/actions/viewer.js +1 -1
  2. package/lib/cli/bin.js +0 -0
  3. package/lib/mcp/server.js +0 -0
  4. package/lib/types/schema.d.ts +457 -457
  5. package/lib/types/schema.js +2 -2
  6. package/lib/utils/context.d.ts +728 -728
  7. package/lib/utils/image_plugins/slide.d.ts +1 -1
  8. package/lib/utils/image_plugins/slide.js +1 -1
  9. package/package.json +7 -6
  10. package/lib/data/styles.d.ts +0 -255
  11. package/lib/data/styles.js +0 -284
  12. package/lib/slide/blocks.d.ts +0 -13
  13. package/lib/slide/blocks.js +0 -251
  14. package/lib/slide/index.d.ts +0 -6
  15. package/lib/slide/index.js +0 -7
  16. package/lib/slide/layouts/big_quote.d.ts +0 -2
  17. package/lib/slide/layouts/big_quote.js +0 -19
  18. package/lib/slide/layouts/columns.d.ts +0 -2
  19. package/lib/slide/layouts/columns.js +0 -53
  20. package/lib/slide/layouts/comparison.d.ts +0 -2
  21. package/lib/slide/layouts/comparison.js +0 -25
  22. package/lib/slide/layouts/funnel.d.ts +0 -2
  23. package/lib/slide/layouts/funnel.js +0 -25
  24. package/lib/slide/layouts/grid.d.ts +0 -2
  25. package/lib/slide/layouts/grid.js +0 -38
  26. package/lib/slide/layouts/index.d.ts +0 -3
  27. package/lib/slide/layouts/index.js +0 -46
  28. package/lib/slide/layouts/matrix.d.ts +0 -2
  29. package/lib/slide/layouts/matrix.js +0 -53
  30. package/lib/slide/layouts/split.d.ts +0 -2
  31. package/lib/slide/layouts/split.js +0 -51
  32. package/lib/slide/layouts/stats.d.ts +0 -2
  33. package/lib/slide/layouts/stats.js +0 -23
  34. package/lib/slide/layouts/table.d.ts +0 -2
  35. package/lib/slide/layouts/table.js +0 -10
  36. package/lib/slide/layouts/timeline.d.ts +0 -2
  37. package/lib/slide/layouts/timeline.js +0 -27
  38. package/lib/slide/layouts/title.d.ts +0 -2
  39. package/lib/slide/layouts/title.js +0 -19
  40. package/lib/slide/layouts/waterfall.d.ts +0 -2
  41. package/lib/slide/layouts/waterfall.js +0 -63
  42. package/lib/slide/render.d.ts +0 -17
  43. package/lib/slide/render.js +0 -101
  44. package/lib/slide/schema.d.ts +0 -9309
  45. package/lib/slide/schema.js +0 -434
  46. package/lib/slide/utils.d.ts +0 -76
  47. package/lib/slide/utils.js +0 -243
  48. package/lib/types/slide.d.ts +0 -9309
  49. package/lib/types/slide.js +0 -434
  50. package/lib/utils/browser_pool.d.ts +0 -5
  51. package/lib/utils/browser_pool.js +0 -39
  52. package/lib/utils/markdown.d.ts +0 -3
  53. package/lib/utils/markdown.js +0 -49
@@ -1,10 +0,0 @@
1
- import { slideHeader, renderOptionalCallout } from "../utils.js";
2
- import { renderTableCore } from "../blocks.js";
3
- export const layoutTable = (data) => {
4
- const parts = [slideHeader(data)];
5
- parts.push(`<div class="px-12 mt-5 flex-1 overflow-auto">`);
6
- parts.push(renderTableCore(data.headers, data.rows, data.rowHeaders, data.striped));
7
- parts.push(`</div>`);
8
- parts.push(renderOptionalCallout(data.callout));
9
- return parts.join("\n");
10
- };
@@ -1,2 +0,0 @@
1
- import type { TimelineSlide } from "../schema.js";
2
- export declare const layoutTimeline: (data: TimelineSlide) => string;
@@ -1,27 +0,0 @@
1
- import { renderInlineMarkup, c, resolveItemColor, centeredSlideHeader } from "../utils.js";
2
- export const layoutTimeline = (data) => {
3
- const parts = [];
4
- const items = data.items || [];
5
- parts.push(centeredSlideHeader(data));
6
- // Timeline items
7
- parts.push(`<div class="flex items-start mt-10 relative">`);
8
- parts.push(`<div class="absolute left-4 right-4 top-[52px] h-[2px] bg-d-alt"></div>`);
9
- items.forEach((item) => {
10
- const color = resolveItemColor(item.color, data.accentColor);
11
- const dotBorder = item.done ? `bg-${c(color)}` : `bg-d-alt`;
12
- const dotInner = item.done ? "bg-d-text" : `bg-${c(color)}`;
13
- parts.push(`<div class="flex-1 flex flex-col items-center text-center relative z-10">`);
14
- parts.push(` <div class="w-10 h-10 rounded-full ${dotBorder} flex items-center justify-center shadow-lg">`);
15
- parts.push(` <div class="w-4 h-4 rounded-full ${dotInner}"></div>`);
16
- parts.push(` </div>`);
17
- parts.push(` <p class="text-sm font-bold text-${c(color)} font-body mt-4">${renderInlineMarkup(item.date)}</p>`);
18
- parts.push(` <p class="text-base font-bold text-d-text font-body mt-2">${renderInlineMarkup(item.title)}</p>`);
19
- if (item.description) {
20
- parts.push(` <p class="text-sm text-d-muted font-body mt-1 px-3">${renderInlineMarkup(item.description)}</p>`);
21
- }
22
- parts.push(`</div>`);
23
- });
24
- parts.push(`</div>`);
25
- parts.push(`</div>`);
26
- return parts.join("\n");
27
- };
@@ -1,2 +0,0 @@
1
- import type { TitleSlide } from "../schema.js";
2
- export declare const layoutTitle: (data: TitleSlide) => string;
@@ -1,19 +0,0 @@
1
- import { renderInlineMarkup, accentBar } from "../utils.js";
2
- export const layoutTitle = (data) => {
3
- return [
4
- accentBar("primary"),
5
- `<div class="absolute -top-20 -right-8 w-[360px] h-[360px] rounded-full bg-d-primary opacity-10"></div>`,
6
- `<div class="absolute -bottom-12 -left-16 w-[280px] h-[280px] rounded-full bg-d-accent opacity-10"></div>`,
7
- `<div class="flex flex-col justify-center h-full px-16 relative z-10">`,
8
- ` <h1 class="text-[60px] leading-tight font-title font-bold text-d-text">${renderInlineMarkup(data.title)}</h1>`,
9
- data.subtitle ? ` <p class="text-2xl text-d-muted mt-6 font-body">${renderInlineMarkup(data.subtitle)}</p>` : "",
10
- data.author ? ` <p class="text-lg text-d-dim mt-10 font-body">${renderInlineMarkup(data.author)}</p>` : "",
11
- data.note
12
- ? ` <div class="bg-d-card px-4 py-2 mt-6 inline-block rounded"><p class="text-sm text-d-dim font-body">${renderInlineMarkup(data.note)}</p></div>`
13
- : "",
14
- `</div>`,
15
- accentBar("accent", "absolute bottom-0 left-0 right-0"),
16
- ]
17
- .filter(Boolean)
18
- .join("\n");
19
- };
@@ -1,2 +0,0 @@
1
- import type { WaterfallSlide } from "../schema.js";
2
- export declare const layoutWaterfall: (data: WaterfallSlide) => string;
@@ -1,63 +0,0 @@
1
- import { renderInlineMarkup, c, slideHeader, renderOptionalCallout } from "../utils.js";
2
- /** Height of the chart area as percentage of available space */
3
- const CHART_HEIGHT_PCT = 75;
4
- export const layoutWaterfall = (data) => {
5
- const parts = [slideHeader(data)];
6
- const items = data.items || [];
7
- const positions = buildWaterfallPositions(items);
8
- const globalMax = Math.max(...positions.map((p) => p.top));
9
- const globalMin = Math.min(...positions.map((p) => p.bottom));
10
- const range = globalMax - globalMin || 1;
11
- parts.push(`<div class="flex gap-1 px-12 mt-4 flex-1" style="min-height: 0">`);
12
- items.forEach((item, i) => {
13
- const pos = positions[i];
14
- const isTotal = item.isTotal ?? false;
15
- const isPositive = item.value >= 0;
16
- const color = resolveBarColor(item.color, isTotal, isPositive);
17
- const bottomPct = ((pos.bottom - globalMin) / range) * CHART_HEIGHT_PCT;
18
- const heightPct = Math.max(((pos.top - pos.bottom) / range) * CHART_HEIGHT_PCT, 1.5);
19
- const topOfBar = bottomPct + heightPct;
20
- const labelTopPct = 100 - topOfBar;
21
- const formattedValue = formatValue(item.value, data.unit, isTotal);
22
- parts.push(`<div class="flex-1 relative" style="height: 100%">`);
23
- // Value label (above bar)
24
- parts.push(` <p class="absolute w-full text-xs font-bold text-d-text font-body text-center" style="top: ${labelTopPct - 4}%">${renderInlineMarkup(formattedValue)}</p>`);
25
- // Bar (absolute positioned from bottom)
26
- parts.push(` <div class="absolute left-1 right-1 bg-${c(color)} rounded-t" style="bottom: ${bottomPct}%; height: ${heightPct}%"></div>`);
27
- // Bottom label
28
- parts.push(` <p class="absolute bottom-0 w-full text-xs text-d-muted font-body text-center" style="transform: translateY(100%)">${renderInlineMarkup(item.label)}</p>`);
29
- parts.push(`</div>`);
30
- });
31
- parts.push(`</div>`);
32
- // Labels area
33
- parts.push(`<div class="h-10 shrink-0"></div>`);
34
- parts.push(renderOptionalCallout(data.callout));
35
- return parts.join("\n");
36
- };
37
- const buildWaterfallPositions = (items) => {
38
- let runningTotal = 0;
39
- return items.map((item) => {
40
- if (item.isTotal) {
41
- runningTotal = item.value;
42
- return { top: Math.max(item.value, 0), bottom: Math.min(item.value, 0) };
43
- }
44
- const prevTotal = runningTotal;
45
- runningTotal += item.value;
46
- if (item.value >= 0) {
47
- return { top: runningTotal, bottom: prevTotal };
48
- }
49
- return { top: prevTotal, bottom: runningTotal };
50
- });
51
- };
52
- const resolveBarColor = (itemColor, isTotal, isPositive) => {
53
- if (itemColor)
54
- return itemColor;
55
- if (isTotal)
56
- return "primary";
57
- return isPositive ? "success" : "danger";
58
- };
59
- const formatValue = (value, unit, isTotal) => {
60
- const prefix = !isTotal && value > 0 ? "+" : "";
61
- const suffix = unit ? ` ${unit}` : "";
62
- return `${prefix}${value}${suffix}`;
63
- };
@@ -1,17 +0,0 @@
1
- import type { SlideTheme, SlideLayout } from "./schema.js";
2
- /** Pre-resolved branding data (all sources converted to data URLs) */
3
- export type ResolvedBranding = {
4
- logo?: {
5
- dataUrl: string;
6
- position: string;
7
- width: number;
8
- };
9
- backgroundImage?: {
10
- dataUrl: string;
11
- size: string;
12
- opacity: number;
13
- bgOpacity?: number;
14
- };
15
- };
16
- /** Generate a complete HTML document for a single slide */
17
- export declare const generateSlideHTML: (theme: SlideTheme, slide: SlideLayout, reference?: string, branding?: ResolvedBranding) => string;
@@ -1,101 +0,0 @@
1
- import { escapeHtml, buildTailwindConfig, sanitizeHex, detectBlockTypes } from "./utils.js";
2
- import { renderSlideContent } from "./layouts/index.js";
3
- /** Determine if a hex color is dark (luminance < 128) */
4
- const isDarkBg = (hex) => {
5
- const r = parseInt(hex.slice(0, 2), 16);
6
- const g = parseInt(hex.slice(2, 4), 16);
7
- const b = parseInt(hex.slice(4, 6), 16);
8
- return (r * 299 + g * 587 + b * 114) / 1000 < 128;
9
- };
10
- /** Build CDN script tags for chart/mermaid when needed */
11
- const buildCdnScripts = (theme, slide) => {
12
- const { hasChart, hasMermaid, chartPlugins } = detectBlockTypes(slide);
13
- const scripts = [];
14
- if (hasChart) {
15
- scripts.push('<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>');
16
- chartPlugins.forEach((cdn) => {
17
- scripts.push(`<script src="${cdn}"></script>`);
18
- });
19
- }
20
- if (hasMermaid) {
21
- const mermaidTheme = isDarkBg(theme.colors.bg) ? "dark" : "default";
22
- scripts.push(`<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
23
- <script>mermaid.initialize({startOnLoad:true,theme:'${mermaidTheme}'})</script>`);
24
- }
25
- return scripts.join("\n");
26
- };
27
- /** Map branding logo position to Tailwind CSS classes */
28
- const logoPositionClasses = {
29
- "top-left": "top-5 left-6",
30
- "top-right": "top-5 right-6",
31
- "bottom-left": "bottom-5 left-6",
32
- "bottom-right": "bottom-5 right-6",
33
- };
34
- /**
35
- * Render branding background layers.
36
- * - Without bgOpacity: image overlaid on slide bg at given opacity
37
- * - With bgOpacity: image at full opacity, then slide bg color as semi-transparent overlay
38
- */
39
- const renderBrandingBackground = (branding, bgHex) => {
40
- if (!branding.backgroundImage)
41
- return "";
42
- const { dataUrl, size, opacity, bgOpacity } = branding.backgroundImage;
43
- const bgSize = size === "fill" ? "100% 100%" : size;
44
- if (bgOpacity !== undefined) {
45
- const parts = [];
46
- parts.push(`<div class="absolute inset-0 z-0" style="background-image:url('${dataUrl}');background-size:${bgSize};background-position:center;background-repeat:no-repeat;opacity:${opacity}"></div>`);
47
- parts.push(`<div class="absolute inset-0 z-0" style="background-color:#${bgHex};opacity:${bgOpacity}"></div>`);
48
- return parts.join("\n");
49
- }
50
- return `<div class="absolute inset-0 z-0" style="background-image:url('${dataUrl}');background-size:${bgSize};background-position:center;background-repeat:no-repeat;opacity:${opacity}"></div>`;
51
- };
52
- /** Render branding logo element */
53
- const renderBrandingLogo = (branding) => {
54
- if (!branding.logo)
55
- return "";
56
- const { dataUrl, position, width } = branding.logo;
57
- const posClasses = logoPositionClasses[position] ?? logoPositionClasses["top-right"];
58
- return `<img class="absolute ${posClasses} z-10" src="${dataUrl}" width="${width}" alt="" style="pointer-events:none">`;
59
- };
60
- /** Generate a complete HTML document for a single slide */
61
- export const generateSlideHTML = (theme, slide, reference, branding) => {
62
- const content = renderSlideContent(slide);
63
- const twConfig = buildTailwindConfig(theme);
64
- const cdnScripts = buildCdnScripts(theme, slide);
65
- const slideStyle = slide.style;
66
- const hasBgOpacity = branding?.backgroundImage?.bgOpacity !== undefined;
67
- const bgCls = hasBgOpacity || slideStyle?.bgColor ? "" : "bg-d-bg";
68
- const bgColorStyle = slideStyle?.bgColor ? ` style="background-color:#${sanitizeHex(slideStyle.bgColor)}"` : "";
69
- const inlineStyle = hasBgOpacity ? "" : bgColorStyle;
70
- const footer = slideStyle?.footer ? `<p class="absolute bottom-2 right-4 text-xs text-d-dim font-body">${escapeHtml(slideStyle.footer)}</p>` : "";
71
- const referenceHtml = reference
72
- ? `<div class="mt-auto px-4 pb-2"><p class="text-sm text-d-muted font-body opacity-80">${escapeHtml(reference)}</p></div>`
73
- : "";
74
- const bgHex = sanitizeHex(slideStyle?.bgColor ?? theme.colors.bg);
75
- const brandingBg = branding ? renderBrandingBackground(branding, bgHex) : "";
76
- const brandingLogo = branding ? renderBrandingLogo(branding) : "";
77
- return `<!DOCTYPE html>
78
- <html lang="en" class="h-full">
79
- <head>
80
- <meta charset="UTF-8">
81
- <meta name="viewport" content="width=1280">
82
- <script src="https://cdn.tailwindcss.com"></script>
83
- <script>tailwind.config = ${twConfig}</script>
84
- ${cdnScripts}
85
- <style>
86
- html, body { height: 100%; margin: 0; padding: 0; overflow: hidden; }
87
- </style>
88
- </head>
89
- <body class="h-full">
90
- <div class="relative overflow-hidden ${bgCls} w-full h-full flex flex-col"${inlineStyle}>
91
- ${brandingBg}
92
- <div class="relative z-[1] flex flex-col flex-1">
93
- ${content}
94
- ${referenceHtml}
95
- ${footer}
96
- </div>
97
- ${brandingLogo}
98
- </div>
99
- </body>
100
- </html>`;
101
- };