@aivorynet/slaide 1.0.0

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 (145) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +201 -0
  3. package/README.md +87 -0
  4. package/bin/slaide.js +25 -0
  5. package/dist/assets.d.ts +10 -0
  6. package/dist/assets.js +54 -0
  7. package/dist/assets.js.map +1 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +433 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/compare/index.d.ts +24 -0
  12. package/dist/compare/index.js +246 -0
  13. package/dist/compare/index.js.map +1 -0
  14. package/dist/compare/ssim.d.ts +2 -0
  15. package/dist/compare/ssim.js +46 -0
  16. package/dist/compare/ssim.js.map +1 -0
  17. package/dist/compiler/chrome.d.ts +7 -0
  18. package/dist/compiler/chrome.js +94 -0
  19. package/dist/compiler/chrome.js.map +1 -0
  20. package/dist/compiler/compile.d.ts +2 -0
  21. package/dist/compiler/compile.js +432 -0
  22. package/dist/compiler/compile.js.map +1 -0
  23. package/dist/compiler/markdown.d.ts +26 -0
  24. package/dist/compiler/markdown.js +439 -0
  25. package/dist/compiler/markdown.js.map +1 -0
  26. package/dist/compiler/tokens.d.ts +13 -0
  27. package/dist/compiler/tokens.js +127 -0
  28. package/dist/compiler/tokens.js.map +1 -0
  29. package/dist/container.d.ts +47 -0
  30. package/dist/container.js +309 -0
  31. package/dist/container.js.map +1 -0
  32. package/dist/engine-entry.d.ts +1 -0
  33. package/dist/engine-entry.js +71 -0
  34. package/dist/engine-entry.js.map +1 -0
  35. package/dist/export-keynote/keynote.d.ts +10 -0
  36. package/dist/export-keynote/keynote.js +58 -0
  37. package/dist/export-keynote/keynote.js.map +1 -0
  38. package/dist/export-pptx/embed-fonts.d.ts +5 -0
  39. package/dist/export-pptx/embed-fonts.js +159 -0
  40. package/dist/export-pptx/embed-fonts.js.map +1 -0
  41. package/dist/export-pptx/inject-anim.d.ts +28 -0
  42. package/dist/export-pptx/inject-anim.js +150 -0
  43. package/dist/export-pptx/inject-anim.js.map +1 -0
  44. package/dist/export-pptx/pptx.d.ts +10 -0
  45. package/dist/export-pptx/pptx.js +425 -0
  46. package/dist/export-pptx/pptx.js.map +1 -0
  47. package/dist/export-pptx/transitions.d.ts +16 -0
  48. package/dist/export-pptx/transitions.js +82 -0
  49. package/dist/export-pptx/transitions.js.map +1 -0
  50. package/dist/import/emit.d.ts +5 -0
  51. package/dist/import/emit.js +274 -0
  52. package/dist/import/emit.js.map +1 -0
  53. package/dist/import/index.d.ts +21 -0
  54. package/dist/import/index.js +192 -0
  55. package/dist/import/index.js.map +1 -0
  56. package/dist/import/pptx.d.ts +117 -0
  57. package/dist/import/pptx.js +1043 -0
  58. package/dist/import/pptx.js.map +1 -0
  59. package/dist/import/raster-com.d.ts +27 -0
  60. package/dist/import/raster-com.js +113 -0
  61. package/dist/import/raster-com.js.map +1 -0
  62. package/dist/import/raster-extension.d.ts +35 -0
  63. package/dist/import/raster-extension.js +27 -0
  64. package/dist/import/raster-extension.js.map +1 -0
  65. package/dist/index.d.ts +63 -0
  66. package/dist/index.js +174 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/install/detect.d.ts +17 -0
  69. package/dist/install/detect.js +82 -0
  70. package/dist/install/detect.js.map +1 -0
  71. package/dist/install/index.d.ts +20 -0
  72. package/dist/install/index.js +126 -0
  73. package/dist/install/index.js.map +1 -0
  74. package/dist/install/registry.d.ts +33 -0
  75. package/dist/install/registry.js +169 -0
  76. package/dist/install/registry.js.map +1 -0
  77. package/dist/install/skills.d.ts +17 -0
  78. package/dist/install/skills.js +72 -0
  79. package/dist/install/skills.js.map +1 -0
  80. package/dist/master-io.d.ts +7 -0
  81. package/dist/master-io.js +55 -0
  82. package/dist/master-io.js.map +1 -0
  83. package/dist/mcp/server.d.ts +3 -0
  84. package/dist/mcp/server.js +114 -0
  85. package/dist/mcp/server.js.map +1 -0
  86. package/dist/optimize/export-optimize.d.ts +21 -0
  87. package/dist/optimize/export-optimize.js +167 -0
  88. package/dist/optimize/export-optimize.js.map +1 -0
  89. package/dist/parser/frontmatter.d.ts +8 -0
  90. package/dist/parser/frontmatter.js +45 -0
  91. package/dist/parser/frontmatter.js.map +1 -0
  92. package/dist/parser/parse.d.ts +2 -0
  93. package/dist/parser/parse.js +184 -0
  94. package/dist/parser/parse.js.map +1 -0
  95. package/dist/render/anim.d.ts +50 -0
  96. package/dist/render/anim.js +213 -0
  97. package/dist/render/anim.js.map +1 -0
  98. package/dist/render/charts.d.ts +3 -0
  99. package/dist/render/charts.js +171 -0
  100. package/dist/render/charts.js.map +1 -0
  101. package/dist/render/css.d.ts +3 -0
  102. package/dist/render/css.js +183 -0
  103. package/dist/render/css.js.map +1 -0
  104. package/dist/render/echarts-lib.generated.d.ts +1 -0
  105. package/dist/render/echarts-lib.generated.js +7 -0
  106. package/dist/render/echarts-lib.generated.js.map +1 -0
  107. package/dist/render/html.d.ts +5 -0
  108. package/dist/render/html.js +186 -0
  109. package/dist/render/html.js.map +1 -0
  110. package/dist/render/inject.d.ts +12 -0
  111. package/dist/render/inject.js +19 -0
  112. package/dist/render/inject.js.map +1 -0
  113. package/dist/render/mermaid-lib.generated.d.ts +1 -0
  114. package/dist/render/mermaid-lib.generated.js +7 -0
  115. package/dist/render/mermaid-lib.generated.js.map +1 -0
  116. package/dist/render/runtime.d.ts +1 -0
  117. package/dist/render/runtime.js +393 -0
  118. package/dist/render/runtime.js.map +1 -0
  119. package/dist/render-pdf/pdf.d.ts +9 -0
  120. package/dist/render-pdf/pdf.js +53 -0
  121. package/dist/render-pdf/pdf.js.map +1 -0
  122. package/dist/render-png/montage.d.ts +14 -0
  123. package/dist/render-png/montage.js +75 -0
  124. package/dist/render-png/montage.js.map +1 -0
  125. package/dist/render-png/shoot.d.ts +25 -0
  126. package/dist/render-png/shoot.js +79 -0
  127. package/dist/render-png/shoot.js.map +1 -0
  128. package/dist/scaffold.d.ts +9 -0
  129. package/dist/scaffold.js +36 -0
  130. package/dist/scaffold.js.map +1 -0
  131. package/dist/types.d.ts +212 -0
  132. package/dist/types.js +7 -0
  133. package/dist/types.js.map +1 -0
  134. package/dist/util.d.ts +6 -0
  135. package/dist/util.js +28 -0
  136. package/dist/util.js.map +1 -0
  137. package/package.json +66 -0
  138. package/skills/slaide/SKILL.md +64 -0
  139. package/skills/slaide/agents/openai.yaml +12 -0
  140. package/skills/slaide/examples/branded-deck.slaide +198 -0
  141. package/skills/slaide/examples/branded-theme.slaide.yaml +187 -0
  142. package/skills/slaide/examples/sample.slaide +98 -0
  143. package/skills/slaide/reference.md +177 -0
  144. package/skills/slaide/themes.md +171 -0
  145. package/themes/aurora.slaide.yaml +136 -0
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function buildServer(): McpServer;
3
+ export declare function runStdio(): Promise<void>;
@@ -0,0 +1,114 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // @slaide/mcp — MCP server over slaide. Thin: every tool calls core.
4
+ // Exposes the language spec + theme catalog as Resources so agents pull grammar
5
+ // on demand, and enforces validate-before-render in the tool descriptions.
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
+ import { z } from 'zod';
9
+ import { writeFileSync, readFileSync, mkdirSync } from 'node:fs';
10
+ import { dirname, resolve } from 'node:path';
11
+ import { validateSource, renderDeckHtml, renderPdfFromHtmlPublic, listThemes, getSpec, getThemeSchema, } from '../index.js';
12
+ import { scaffoldDeck } from '../scaffold.js';
13
+ import { ENTRANCE_NAMES, SLIDE_TRANSITION_NAMES } from '../render/anim.js';
14
+ function animSpec() {
15
+ return ('# slaide animations\n\n' +
16
+ 'Pick effects **by name** — the runtime/CSS handles them, no code needed.\n\n' +
17
+ '## Slide transitions\n' +
18
+ 'Set in slide frontmatter: `transition: <name>` (or `~transition:` to cascade).\n' +
19
+ 'Per-slide timing: `transition-ms: 600`, `transition-ease: ease-out`.\n\n' +
20
+ SLIDE_TRANSITION_NAMES.map((n) => `- ${n}`).join('\n') +
21
+ '\n\n## Element entrances (builds)\n' +
22
+ 'Append to a build step: `- point >>> <name>` with optional `delay=`, `dur=`, `ease=`\n' +
23
+ '(e.g. `- point >>> zoom-in delay=150`). A bare `>>>` uses `fade-up`.\n\n' +
24
+ ENTRANCE_NAMES.map((n) => `- ${n}`).join('\n') +
25
+ '\n\nThemes may define more via the master `animations:` map (see slaide://themes).\n');
26
+ }
27
+ function resolveSource(args) {
28
+ if (args.source != null)
29
+ return { source: args.source, dir: process.cwd() };
30
+ if (args.path)
31
+ return { source: readFileSync(args.path, 'utf8'), dir: dirname(resolve(args.path)) };
32
+ throw new Error('Provide either `source` (deck text) or `path` (file path).');
33
+ }
34
+ function text(obj, isError = false) {
35
+ return { content: [{ type: 'text', text: typeof obj === 'string' ? obj : JSON.stringify(obj, null, 2) }], isError };
36
+ }
37
+ export function buildServer() {
38
+ const server = new McpServer({ name: 'slaide', version: '1.0.0' }, { instructions: 'Author and render slaide decks (HTML + PDF). Always slaide_validate before rendering; read the slaide://spec resource for grammar.' });
39
+ server.registerTool('slaide_scaffold', {
40
+ title: 'Scaffold a slaide deck',
41
+ description: 'Create starter slaide source from a title and optional outline. Returns the deck text (write it to a .slaide file).',
42
+ inputSchema: {
43
+ title: z.string(),
44
+ subtitle: z.string().optional(),
45
+ outline: z.array(z.string()).optional(),
46
+ master: z.string().optional().describe('Master path; omit for the bundled theme.'),
47
+ },
48
+ }, async (a) => text(scaffoldDeck(a)));
49
+ server.registerTool('slaide_validate', {
50
+ title: 'Validate a slaide deck',
51
+ description: 'Validate deck source against the language + theme. Returns {ok, diagnostics:[{severity,code,message,line}]}. ALWAYS call this before rendering and fix any errors.',
52
+ inputSchema: { source: z.string().optional(), path: z.string().optional() },
53
+ }, async (a) => {
54
+ const { source, dir } = resolveSource(a);
55
+ const res = validateSource(source, dir);
56
+ return text(res, !res.ok);
57
+ });
58
+ server.registerTool('slaide_render_html', {
59
+ title: 'Render a slaide deck to HTML',
60
+ description: 'Render to a self-contained, navigable HTML presentation (assets inlined). Writes to outPath and returns {outPath, slides, warnings}.',
61
+ inputSchema: {
62
+ source: z.string().optional(),
63
+ path: z.string().optional(),
64
+ outPath: z.string().describe('Output .html path.'),
65
+ },
66
+ }, async (a) => {
67
+ const { source, dir } = resolveSource(a);
68
+ const { html, ir } = renderDeckHtml(source, dir, { mode: 'web', inline: true });
69
+ mkdirSync(dirname(resolve(a.outPath)), { recursive: true });
70
+ writeFileSync(a.outPath, html, 'utf8');
71
+ return text({ outPath: a.outPath, slides: ir.slides.length, warnings: ir.warnings });
72
+ });
73
+ server.registerTool('slaide_render_pdf', {
74
+ title: 'Render a slaide deck to PDF',
75
+ description: 'Render to a paginated, high-fidelity PDF (one page per slide, builds settled). Needs Playwright. Writes to outPath and returns {outPath, slides}.',
76
+ inputSchema: {
77
+ source: z.string().optional(),
78
+ path: z.string().optional(),
79
+ outPath: z.string().describe('Output .pdf path.'),
80
+ },
81
+ }, async (a) => {
82
+ const { source, dir } = resolveSource(a);
83
+ const { html, ir } = renderDeckHtml(source, dir, { mode: 'print', inline: true });
84
+ mkdirSync(dirname(resolve(a.outPath)), { recursive: true });
85
+ await renderPdfFromHtmlPublic(html, a.outPath);
86
+ return text({ outPath: a.outPath, slides: ir.slides.length });
87
+ });
88
+ server.registerTool('slaide_list_themes', {
89
+ title: 'List bundled themes',
90
+ description: 'List available master themes and their layouts.',
91
+ inputSchema: {},
92
+ }, async () => text(listThemes().map((t) => ({ name: t.name, layouts: t.layouts, description: t.description }))));
93
+ // Resources: the language spec + theme/layout catalog (pull grammar on demand).
94
+ server.registerResource('spec', 'slaide://spec', { title: 'slaide language spec', description: 'The slaide authoring grammar.', mimeType: 'text/markdown' }, async (uri) => ({ contents: [{ uri: uri.href, text: getSpec() }] }));
95
+ server.registerResource('themes', 'slaide://themes', { title: 'slaide theme/master guide', description: 'How to author a master + the layout catalog.', mimeType: 'text/markdown' }, async (uri) => ({ contents: [{ uri: uri.href, text: getThemeSchema() }] }));
96
+ server.registerResource('anim', 'slaide://anim', { title: 'slaide animations', description: 'Named slide transitions + element entrances, reusable by name.', mimeType: 'text/markdown' }, async (uri) => ({ contents: [{ uri: uri.href, text: animSpec() }] }));
97
+ server.registerPrompt('new_deck', { title: 'Start a new deck', description: 'Template for authoring a new slaide deck.', argsSchema: { topic: z.string() } }, ({ topic }) => ({
98
+ messages: [
99
+ {
100
+ role: 'user',
101
+ content: {
102
+ type: 'text',
103
+ text: `Read the slaide://spec resource, then write a slaide deck about "${topic}". Use the cover, section, title-content, two-cols and image-right layouts. Call slaide_validate, fix any errors, then slaide_render_html.`,
104
+ },
105
+ },
106
+ ],
107
+ }));
108
+ return server;
109
+ }
110
+ export async function runStdio() {
111
+ const server = buildServer();
112
+ await server.connect(new StdioServerTransport());
113
+ }
114
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,sCAAsC;AACtC,qEAAqE;AACrE,gFAAgF;AAChF,2EAA2E;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EACL,cAAc,EACd,cAAc,EACd,uBAAuB,EACvB,UAAU,EACV,OAAO,EACP,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3E,SAAS,QAAQ;IACf,OAAO,CACL,yBAAyB;QACzB,8EAA8E;QAC9E,wBAAwB;QACxB,kFAAkF;QAClF,0EAA0E;QAC1E,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACtD,qCAAqC;QACrC,wFAAwF;QACxF,0EAA0E;QAC1E,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAC9C,sFAAsF,CACvF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,IAAwC;IAC7D,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;IAC5E,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IACpG,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,IAAI,CAAC,GAAY,EAAE,OAAO,GAAG,KAAK;IACzC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AAC/H,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EACpC,EAAE,YAAY,EAAE,oIAAoI,EAAE,CACvJ,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,qHAAqH;QAClI,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;YACjB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC/B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;SACnF;KACF,EACD,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CACnC,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,oKAAoK;QACjL,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE;KAC5E,EACD,KAAK,EAAE,CAAC,EAAE,EAAE;QACV,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,8BAA8B;QACrC,WAAW,EAAE,sIAAsI;QACnJ,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;SACnD;KACF,EACD,KAAK,EAAE,CAAC,EAAE,EAAE;QACV,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EAAE,mJAAmJ;QAChK,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;SAClD;KACF,EACD,KAAK,EAAE,CAAC,EAAE,EAAE;QACV,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,iDAAiD;QAC9D,WAAW,EAAE,EAAE;KAChB,EACD,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAC9G,CAAC;IAEF,gFAAgF;IAChF,MAAM,CAAC,gBAAgB,CACrB,MAAM,EACN,eAAe,EACf,EAAE,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,+BAA+B,EAAE,QAAQ,EAAE,eAAe,EAAE,EAC1G,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,CACpE,CAAC;IACF,MAAM,CAAC,gBAAgB,CACrB,QAAQ,EACR,iBAAiB,EACjB,EAAE,KAAK,EAAE,2BAA2B,EAAE,WAAW,EAAE,8CAA8C,EAAE,QAAQ,EAAE,eAAe,EAAE,EAC9H,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,CAC3E,CAAC;IACF,MAAM,CAAC,gBAAgB,CACrB,MAAM,EACN,eAAe,EACf,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,gEAAgE,EAAE,QAAQ,EAAE,eAAe,EAAE,EACxI,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,CACrE,CAAC;IAEF,MAAM,CAAC,cAAc,CACnB,UAAU,EACV,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,2CAA2C,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAC1H,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oEAAoE,KAAK,4IAA4I;iBAC5N;aACF;SACF;KACF,CAAC,CACH,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,21 @@
1
+ /** Image optimization knobs. `quality` is 1..100; `maxWidth` downscales (never upscales). */
2
+ export interface ImageOpts {
3
+ maxWidth?: number;
4
+ quality?: number;
5
+ }
6
+ /** Bake charts and/or optimize inlined images for a standalone HTML export, in one session. */
7
+ export declare function optimizeExportHtml(html: string, opts: {
8
+ canvas: {
9
+ width: number;
10
+ height: number;
11
+ };
12
+ bake?: boolean;
13
+ image?: ImageOpts;
14
+ browser?: import('playwright').Browser;
15
+ }): Promise<string>;
16
+ /** Re-encode raster asset buffers, KEEPING each one's format (so its filename stays valid).
17
+ * Returns a buffer only when smaller. Used when packing a `.slaidec`. */
18
+ export declare function optimizeImageBuffers(files: {
19
+ name: string;
20
+ buf: Buffer;
21
+ }[], o: ImageOpts, injected?: import('playwright').Browser): Promise<Map<string, Buffer>>;
@@ -0,0 +1,167 @@
1
+ async function loadPlaywright() {
2
+ try {
3
+ return await import('playwright');
4
+ }
5
+ catch {
6
+ throw new Error('This export option needs Playwright:\n npm install playwright\n npx playwright install chromium');
7
+ }
8
+ }
9
+ /** Decode a data URI in the page, optionally downscale to maxWidth, re-encode to `mime`@quality. */
10
+ function recode(page, dataUri, mime, o) {
11
+ return page.evaluate(async (a) => {
12
+ const img = new Image();
13
+ const ok = await new Promise((res) => {
14
+ img.onload = () => res(true);
15
+ img.onerror = () => res(false);
16
+ img.src = a.uri;
17
+ });
18
+ if (!ok || !img.naturalWidth)
19
+ return a.uri;
20
+ const w = img.naturalWidth;
21
+ const h = img.naturalHeight;
22
+ const scale = a.maxWidth && w > a.maxWidth ? a.maxWidth / w : 1;
23
+ const cw = Math.max(1, Math.round(w * scale));
24
+ const ch = Math.max(1, Math.round(h * scale));
25
+ const c = document.createElement('canvas');
26
+ c.width = cw;
27
+ c.height = ch;
28
+ const ctx = c.getContext('2d');
29
+ if (!ctx)
30
+ return a.uri;
31
+ ctx.drawImage(img, 0, 0, cw, ch);
32
+ try {
33
+ return c.toDataURL(a.mime, a.quality / 100);
34
+ }
35
+ catch {
36
+ return a.uri;
37
+ }
38
+ }, { uri: dataUri, mime, maxWidth: o.maxWidth ?? 0, quality: o.quality ?? 80 });
39
+ }
40
+ // Matches inlined raster data URIs (NOT svg+xml — vectors are already tiny).
41
+ const DATAURI_RE = /data:image\/(?:png|jpe?g|webp);base64,[A-Za-z0-9+/=]+/g;
42
+ async function optimizeImagesInHtml(page, html, o) {
43
+ const uris = Array.from(new Set(html.match(DATAURI_RE) ?? []));
44
+ let out = html;
45
+ for (const uri of uris) {
46
+ // WebP keeps transparency and gives the best ratio for inlined HTML.
47
+ const webp = await recode(page, uri, 'image/webp', o);
48
+ if (webp && webp.startsWith('data:') && webp.length < uri.length)
49
+ out = out.split(uri).join(webp);
50
+ }
51
+ return out;
52
+ }
53
+ /** Bake charts and/or optimize inlined images for a standalone HTML export, in one session. */
54
+ export async function optimizeExportHtml(html, opts) {
55
+ // Real charts are present only when an engine lib tag was injected (the `.sl-chart`
56
+ // class string is always in the stylesheet, so don't key off that).
57
+ const needBake = !!opts.bake && (html.includes('id="sl-mermaid-lib"') || html.includes('id="sl-echart-lib"'));
58
+ if (!needBake && !opts.image)
59
+ return html;
60
+ const { chromium } = await loadPlaywright();
61
+ const browser = opts.browser ?? (await chromium.launch());
62
+ try {
63
+ const page = await browser.newPage({ viewport: { width: opts.canvas.width, height: opts.canvas.height } });
64
+ let out = html;
65
+ if (needBake) {
66
+ await page.setContent(out, { waitUntil: 'networkidle' });
67
+ await page.evaluate(() => document.fonts?.ready);
68
+ // Render each chart with ITS slide active — a chart sizes to its slot, and a slot in a
69
+ // flowing/box layout measures wrong while a different slide is active (the live runtime
70
+ // avoids this by only rendering a chart when its slide becomes active). Stepping through
71
+ // matches that, so a baked chart lands exactly where the live renderer puts it.
72
+ await page.evaluate(async () => {
73
+ const w = window;
74
+ const slides = Array.from(document.querySelectorAll('.sl-slide'));
75
+ for (let i = 0; i < slides.length; i++) {
76
+ const s = slides[i];
77
+ if (!s.querySelector('.sl-chart:not([data-rendered])'))
78
+ continue;
79
+ if (w.slaide && typeof w.slaide.goTo === 'function')
80
+ w.slaide.goTo(i);
81
+ await new Promise((r) => setTimeout(r, 90)); // let layout settle on the now-active slide
82
+ if (w.__slaideCharts)
83
+ await w.__slaideCharts.renderIn(s);
84
+ }
85
+ w.__slaideChartsReady = true;
86
+ });
87
+ await page
88
+ .waitForFunction(() => window.__slaideChartsReady === true, { timeout: 8000 })
89
+ .catch(() => { });
90
+ out = await page.evaluate(() => {
91
+ // Freeze each chart as its rendered SVG; drop the now-useless data + engine plumbing.
92
+ document.querySelectorAll('.sl-chart').forEach((el) => {
93
+ const svg = el.querySelector('svg');
94
+ if (svg) {
95
+ // ECharts renders the SVG `position:absolute` inside its own sizing wrapper. Frozen
96
+ // as the chart's only child that wrapper is gone, so the absolute SVG escapes to the
97
+ // slide origin — pin it back to normal flow (it's centred by the .sl-chart flexbox).
98
+ svg.style.position = 'static';
99
+ svg.style.left = '';
100
+ svg.style.top = '';
101
+ el.innerHTML = svg.outerHTML;
102
+ }
103
+ el.removeAttribute('data-graph');
104
+ el.removeAttribute('data-option');
105
+ el.removeAttribute('data-rendered');
106
+ });
107
+ document.querySelectorAll('#sl-mermaid-lib, #sl-echart-lib').forEach((n) => n.remove());
108
+ document.querySelectorAll('script').forEach((s) => {
109
+ if (s.textContent && s.textContent.indexOf('__slaideCharts') >= 0)
110
+ s.remove();
111
+ });
112
+ // Drop transient runtime state so the static file opens clean (the nav runtime re-inits).
113
+ const stage = document.querySelector('.sl-stage');
114
+ if (stage)
115
+ stage.style.transform = '';
116
+ document.querySelectorAll('.sl-active').forEach((s) => s.classList.remove('sl-active'));
117
+ document.querySelectorAll('.sl-shown').forEach((s) => s.classList.remove('sl-shown'));
118
+ // Stepping slides to bake charts leaves mid-flight transition classes on the slides
119
+ // (animationend never fires within the headless freeze window) — strip every sl-anim-*
120
+ // so the static file doesn't play the cover's out-transition on load (a black first slide).
121
+ document.querySelectorAll('.sl-slide').forEach((s) => {
122
+ Array.from(s.classList).forEach((c) => {
123
+ if (c.indexOf('sl-anim-') === 0)
124
+ s.classList.remove(c);
125
+ });
126
+ });
127
+ return '<!doctype html>\n' + document.documentElement.outerHTML;
128
+ });
129
+ }
130
+ if (opts.image)
131
+ out = await optimizeImagesInHtml(page, out, opts.image);
132
+ return out;
133
+ }
134
+ finally {
135
+ if (!opts.browser)
136
+ await browser.close();
137
+ }
138
+ }
139
+ /** Re-encode raster asset buffers, KEEPING each one's format (so its filename stays valid).
140
+ * Returns a buffer only when smaller. Used when packing a `.slaidec`. */
141
+ export async function optimizeImageBuffers(files, o, injected) {
142
+ const result = new Map();
143
+ const targets = files.filter((f) => /\.(png|jpe?g|webp)$/i.test(f.name));
144
+ if (!targets.length)
145
+ return result;
146
+ const { chromium } = await loadPlaywright();
147
+ const browser = injected ?? (await chromium.launch());
148
+ try {
149
+ const page = await browser.newPage();
150
+ for (const f of targets) {
151
+ const ext = (f.name.match(/\.(png|jpe?g|webp)$/i)?.[1] || '').toLowerCase();
152
+ const mime = ext === 'png' ? 'image/png' : ext === 'webp' ? 'image/webp' : 'image/jpeg';
153
+ const re = await recode(page, `data:${mime};base64,${f.buf.toString('base64')}`, mime, o);
154
+ if (re && re.startsWith('data:')) {
155
+ const b = Buffer.from(re.split(',')[1] ?? '', 'base64');
156
+ if (b.length && b.length < f.buf.length)
157
+ result.set(f.name, b);
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+ finally {
163
+ if (!injected)
164
+ await browser.close();
165
+ }
166
+ }
167
+ //# sourceMappingURL=export-optimize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-optimize.js","sourceRoot":"","sources":["../../src/optimize/export-optimize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ declare const FENCE: RegExp;
2
+ /** Is a text block "config-like" (a simple YAML mapping of key: value lines)? */
3
+ export declare function isConfigLike(text: string): boolean;
4
+ /** Parse a YAML mapping, tolerating the `~key` cascade prefix (kept verbatim).
5
+ * On malformed YAML, `onError` is invoked with the parser message (the config is no
6
+ * longer silently swallowed) and an empty mapping is returned. */
7
+ export declare function parseConfig(text: string, onError?: (message: string) => void): Record<string, unknown>;
8
+ export { FENCE };
@@ -0,0 +1,45 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // Front-matter / config-block parsing helpers.
4
+ import yaml from 'js-yaml';
5
+ const FENCE = /^---\s*$/;
6
+ /** Is a text block "config-like" (a simple YAML mapping of key: value lines)? */
7
+ export function isConfigLike(text) {
8
+ const lines = text.split('\n');
9
+ let sawKey = false;
10
+ for (const raw of lines) {
11
+ const line = raw.trim();
12
+ if (line === '' || line.startsWith('#'))
13
+ continue;
14
+ // key: or ~key: (cascade prefix) optionally indented; also list/scalar
15
+ // continuations of a previous key are allowed (start with - or whitespace).
16
+ if (/^[~]?[A-Za-z_][\w-]*\s*:/.test(line)) {
17
+ sawKey = true;
18
+ continue;
19
+ }
20
+ if (/^-\s/.test(line))
21
+ continue; // yaml list item
22
+ return false;
23
+ }
24
+ return sawKey;
25
+ }
26
+ /** Parse a YAML mapping, tolerating the `~key` cascade prefix (kept verbatim).
27
+ * On malformed YAML, `onError` is invoked with the parser message (the config is no
28
+ * longer silently swallowed) and an empty mapping is returned. */
29
+ export function parseConfig(text, onError) {
30
+ if (text.trim() === '')
31
+ return {};
32
+ try {
33
+ const obj = yaml.load(text);
34
+ if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
35
+ return obj;
36
+ }
37
+ return {};
38
+ }
39
+ catch (e) {
40
+ onError?.(e.message.split('\n')[0]);
41
+ return {};
42
+ }
43
+ }
44
+ export { FENCE };
45
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/parser/frontmatter.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,sCAAsC;AACtC,+CAA+C;AAC/C,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,MAAM,KAAK,GAAG,UAAU,CAAC;AAEzB,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClD,0EAA0E;QAC1E,4EAA4E;QAC5E,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,GAAG,IAAI,CAAC;YACd,SAAS;QACX,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,iBAAiB;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;mEAEmE;AACnE,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,OAAmC;IAC3E,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1D,OAAO,GAA8B,CAAC;QACxC,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,CAAE,CAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ParsedDeck } from '../types.js';
2
+ export declare function parseDeck(content: string): ParsedDeck;
@@ -0,0 +1,184 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // Deck parser: a .slaide file -> ParsedDeck (AST).
4
+ //
5
+ // Format (deterministic, no configurable separators):
6
+ // --- leading fence
7
+ // <deck headmatter (config)> the one place for deck-wide config
8
+ // ---
9
+ // <slide frontmatter?> optional, config-like, fenced
10
+ // ---
11
+ // <slide body> markdown + `:: region ::` + `>>>` + `??? notes`
12
+ // --- slide separator
13
+ // ...
14
+ //
15
+ // A fenced block after a separator is treated as the next slide's *frontmatter*
16
+ // iff it is config-like AND another fence follows; otherwise it is the body.
17
+ import { FENCE, isConfigLike, parseConfig } from './frontmatter.js';
18
+ const CODE_FENCE = /^\s*(```|~~~)/;
19
+ function splitSegments(content) {
20
+ const lines = content.split(/\r?\n/);
21
+ const segments = [];
22
+ let buf = [];
23
+ let start = 1;
24
+ let inCode = false;
25
+ lines.forEach((line, i) => {
26
+ if (CODE_FENCE.test(line))
27
+ inCode = !inCode;
28
+ if (!inCode && FENCE.test(line)) {
29
+ segments.push({ text: buf.join('\n'), line: start });
30
+ buf = [];
31
+ start = i + 2; // next line, 1-based
32
+ }
33
+ else {
34
+ buf.push(line);
35
+ }
36
+ });
37
+ segments.push({ text: buf.join('\n'), line: start });
38
+ return segments;
39
+ }
40
+ const REGION_RE = /^::\s*([\w-]+)\s*::\s*$/;
41
+ // Keys that legitimately appear in slide frontmatter. Used only to detect a
42
+ // config-shaped *body* mistakenly eaten as frontmatter (see ambiguous-frontmatter).
43
+ const KNOWN_SLIDE_KEYS = new Set([
44
+ 'layout', 'background', 'transition', 'transition-ms', 'transition-ease', 'variant', 'chrome', 'footer', 'logo', 'morph', 'notes',
45
+ 'title', 'author', 'company', 'date', 'subtitle',
46
+ ]);
47
+ /** Split a slide body into regions and extract speaker notes. The `::` region
48
+ * markers, `??? notes`, and the build/blank-line splitting are all suppressed
49
+ * inside fenced code blocks (```/~~~) so a deck's own slaide source can be shown
50
+ * verbatim in a code sample without being parsed as structure. */
51
+ function parseBody(text) {
52
+ const lines = text.split('\n');
53
+ const noteChunks = [];
54
+ const kept = [];
55
+ // First pass: pull out `??? ...` note blocks (continue until a blank line) —
56
+ // but never while inside a fenced code block.
57
+ let inCode = false;
58
+ for (let i = 0; i < lines.length; i++) {
59
+ const line = lines[i];
60
+ if (CODE_FENCE.test(line)) {
61
+ inCode = !inCode;
62
+ kept.push(line);
63
+ continue;
64
+ }
65
+ if (inCode) {
66
+ kept.push(line);
67
+ continue;
68
+ }
69
+ // `\??? …` escapes a literal triple-question-mark line into the body.
70
+ if (/^\\\?\?\?/.test(line)) {
71
+ kept.push(line.slice(1));
72
+ continue;
73
+ }
74
+ const m = line.match(/^\?\?\?\s?(.*)$/);
75
+ if (m) {
76
+ const chunk = [m[1]];
77
+ let j = i + 1;
78
+ while (j < lines.length &&
79
+ lines[j].trim() !== '' &&
80
+ !REGION_RE.test(lines[j]) &&
81
+ !CODE_FENCE.test(lines[j])) {
82
+ chunk.push(lines[j]);
83
+ j++;
84
+ }
85
+ noteChunks.push(chunk.join('\n').trim());
86
+ i = j - 1;
87
+ continue;
88
+ }
89
+ kept.push(line);
90
+ }
91
+ // Second pass: route remaining lines into regions — again, fence-aware.
92
+ const regions = [];
93
+ let current = { name: 'default', lines: [] };
94
+ const flush = () => {
95
+ const md = current.lines.join('\n').trim();
96
+ if (md !== '' || current.name !== 'default') {
97
+ regions.push({ name: current.name, markdown: md });
98
+ }
99
+ };
100
+ inCode = false;
101
+ for (const line of kept) {
102
+ if (CODE_FENCE.test(line)) {
103
+ inCode = !inCode;
104
+ current.lines.push(line);
105
+ continue;
106
+ }
107
+ if (!inCode && /^\\::/.test(line)) {
108
+ // `\:: name ::` escapes a literal region-marker-looking line into the body.
109
+ current.lines.push(line.slice(1));
110
+ continue;
111
+ }
112
+ const m = inCode ? null : line.match(REGION_RE);
113
+ if (m) {
114
+ flush();
115
+ current = { name: m[1], lines: [] };
116
+ }
117
+ else {
118
+ current.lines.push(line);
119
+ }
120
+ }
121
+ flush();
122
+ return {
123
+ regions: regions.length ? regions : [{ name: 'default', markdown: '' }],
124
+ notes: noteChunks.length ? noteChunks.join('\n\n') : null,
125
+ };
126
+ }
127
+ export function parseDeck(content) {
128
+ const warnings = [];
129
+ const segments = splitSegments(content);
130
+ // Drop a leading empty segment (file begins with `---`).
131
+ let idx = 0;
132
+ if (segments.length && segments[0].text.trim() === '')
133
+ idx = 1;
134
+ // Headmatter: the first non-empty segment, if it is config-like.
135
+ let headmatter = {};
136
+ if (idx < segments.length && isConfigLike(segments[idx].text)) {
137
+ const line = segments[idx].line;
138
+ headmatter = parseConfig(segments[idx].text, (msg) => warnings.push({ code: 'bad-config', message: `Deck headmatter is not valid YAML (rendered with defaults): ${msg}`, line }));
139
+ idx++;
140
+ }
141
+ else {
142
+ warnings.push({
143
+ code: 'no-headmatter',
144
+ message: 'No deck headmatter found; expected a leading `---` config block (e.g. `master: ./theme.yaml`).',
145
+ line: 1,
146
+ });
147
+ }
148
+ // Remaining segments -> slides.
149
+ const slides = [];
150
+ const rest = segments.slice(idx).filter((s, i, arr) => !(i === arr.length - 1 && s.text.trim() === ''));
151
+ for (let i = 0; i < rest.length;) {
152
+ const seg = rest[i];
153
+ let frontmatter = {};
154
+ let bodySeg = seg;
155
+ const hasNext = i + 1 < rest.length;
156
+ if (isConfigLike(seg.text) && hasNext) {
157
+ frontmatter = parseConfig(seg.text, (msg) => warnings.push({ code: 'bad-config', message: `Slide frontmatter is not valid YAML (rendered with defaults): ${msg}`, line: seg.line }));
158
+ // A config-shaped *body* (e.g. a "Field: value" spec sheet) followed by a `---`
159
+ // is otherwise silently consumed as frontmatter. If none of its keys are known
160
+ // slide-config keys, warn — the author likely meant body content (escape a line
161
+ // with a leading backslash, or separate with an explicit `---`).
162
+ const keys = Object.keys(frontmatter).map((k) => k.replace(/^~/, ''));
163
+ if (keys.length && !keys.some((k) => KNOWN_SLIDE_KEYS.has(k))) {
164
+ warnings.push({
165
+ code: 'ambiguous-frontmatter',
166
+ message: `Slide ${slides.length + 1}: a config-shaped block (${keys.slice(0, 3).join(', ')}…) was read as frontmatter, not body. If it is slide content, escape the first line with \\ or add an explicit \`---\`.`,
167
+ line: seg.line,
168
+ });
169
+ }
170
+ bodySeg = rest[i + 1];
171
+ i += 2;
172
+ }
173
+ else {
174
+ i += 1;
175
+ }
176
+ const { regions, notes } = parseBody(bodySeg.text);
177
+ slides.push({ frontmatter, regions, notes, sourceLine: bodySeg.line });
178
+ }
179
+ if (slides.length === 0) {
180
+ warnings.push({ code: 'empty-deck', message: 'No slides found in deck.', line: 1 });
181
+ }
182
+ return { headmatter, slides, warnings };
183
+ }
184
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/parser/parse.ts"],"names":[],"mappings":"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"}