@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.
- package/CHANGELOG.md +26 -0
- package/LICENSE +201 -0
- package/README.md +87 -0
- package/bin/slaide.js +25 -0
- package/dist/assets.d.ts +10 -0
- package/dist/assets.js +54 -0
- package/dist/assets.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +433 -0
- package/dist/cli.js.map +1 -0
- package/dist/compare/index.d.ts +24 -0
- package/dist/compare/index.js +246 -0
- package/dist/compare/index.js.map +1 -0
- package/dist/compare/ssim.d.ts +2 -0
- package/dist/compare/ssim.js +46 -0
- package/dist/compare/ssim.js.map +1 -0
- package/dist/compiler/chrome.d.ts +7 -0
- package/dist/compiler/chrome.js +94 -0
- package/dist/compiler/chrome.js.map +1 -0
- package/dist/compiler/compile.d.ts +2 -0
- package/dist/compiler/compile.js +432 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/markdown.d.ts +26 -0
- package/dist/compiler/markdown.js +439 -0
- package/dist/compiler/markdown.js.map +1 -0
- package/dist/compiler/tokens.d.ts +13 -0
- package/dist/compiler/tokens.js +127 -0
- package/dist/compiler/tokens.js.map +1 -0
- package/dist/container.d.ts +47 -0
- package/dist/container.js +309 -0
- package/dist/container.js.map +1 -0
- package/dist/engine-entry.d.ts +1 -0
- package/dist/engine-entry.js +71 -0
- package/dist/engine-entry.js.map +1 -0
- package/dist/export-keynote/keynote.d.ts +10 -0
- package/dist/export-keynote/keynote.js +58 -0
- package/dist/export-keynote/keynote.js.map +1 -0
- package/dist/export-pptx/embed-fonts.d.ts +5 -0
- package/dist/export-pptx/embed-fonts.js +159 -0
- package/dist/export-pptx/embed-fonts.js.map +1 -0
- package/dist/export-pptx/inject-anim.d.ts +28 -0
- package/dist/export-pptx/inject-anim.js +150 -0
- package/dist/export-pptx/inject-anim.js.map +1 -0
- package/dist/export-pptx/pptx.d.ts +10 -0
- package/dist/export-pptx/pptx.js +425 -0
- package/dist/export-pptx/pptx.js.map +1 -0
- package/dist/export-pptx/transitions.d.ts +16 -0
- package/dist/export-pptx/transitions.js +82 -0
- package/dist/export-pptx/transitions.js.map +1 -0
- package/dist/import/emit.d.ts +5 -0
- package/dist/import/emit.js +274 -0
- package/dist/import/emit.js.map +1 -0
- package/dist/import/index.d.ts +21 -0
- package/dist/import/index.js +192 -0
- package/dist/import/index.js.map +1 -0
- package/dist/import/pptx.d.ts +117 -0
- package/dist/import/pptx.js +1043 -0
- package/dist/import/pptx.js.map +1 -0
- package/dist/import/raster-com.d.ts +27 -0
- package/dist/import/raster-com.js +113 -0
- package/dist/import/raster-com.js.map +1 -0
- package/dist/import/raster-extension.d.ts +35 -0
- package/dist/import/raster-extension.js +27 -0
- package/dist/import/raster-extension.js.map +1 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +174 -0
- package/dist/index.js.map +1 -0
- package/dist/install/detect.d.ts +17 -0
- package/dist/install/detect.js +82 -0
- package/dist/install/detect.js.map +1 -0
- package/dist/install/index.d.ts +20 -0
- package/dist/install/index.js +126 -0
- package/dist/install/index.js.map +1 -0
- package/dist/install/registry.d.ts +33 -0
- package/dist/install/registry.js +169 -0
- package/dist/install/registry.js.map +1 -0
- package/dist/install/skills.d.ts +17 -0
- package/dist/install/skills.js +72 -0
- package/dist/install/skills.js.map +1 -0
- package/dist/master-io.d.ts +7 -0
- package/dist/master-io.js +55 -0
- package/dist/master-io.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.js +114 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/optimize/export-optimize.d.ts +21 -0
- package/dist/optimize/export-optimize.js +167 -0
- package/dist/optimize/export-optimize.js.map +1 -0
- package/dist/parser/frontmatter.d.ts +8 -0
- package/dist/parser/frontmatter.js +45 -0
- package/dist/parser/frontmatter.js.map +1 -0
- package/dist/parser/parse.d.ts +2 -0
- package/dist/parser/parse.js +184 -0
- package/dist/parser/parse.js.map +1 -0
- package/dist/render/anim.d.ts +50 -0
- package/dist/render/anim.js +213 -0
- package/dist/render/anim.js.map +1 -0
- package/dist/render/charts.d.ts +3 -0
- package/dist/render/charts.js +171 -0
- package/dist/render/charts.js.map +1 -0
- package/dist/render/css.d.ts +3 -0
- package/dist/render/css.js +183 -0
- package/dist/render/css.js.map +1 -0
- package/dist/render/echarts-lib.generated.d.ts +1 -0
- package/dist/render/echarts-lib.generated.js +7 -0
- package/dist/render/echarts-lib.generated.js.map +1 -0
- package/dist/render/html.d.ts +5 -0
- package/dist/render/html.js +186 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/inject.d.ts +12 -0
- package/dist/render/inject.js +19 -0
- package/dist/render/inject.js.map +1 -0
- package/dist/render/mermaid-lib.generated.d.ts +1 -0
- package/dist/render/mermaid-lib.generated.js +7 -0
- package/dist/render/mermaid-lib.generated.js.map +1 -0
- package/dist/render/runtime.d.ts +1 -0
- package/dist/render/runtime.js +393 -0
- package/dist/render/runtime.js.map +1 -0
- package/dist/render-pdf/pdf.d.ts +9 -0
- package/dist/render-pdf/pdf.js +53 -0
- package/dist/render-pdf/pdf.js.map +1 -0
- package/dist/render-png/montage.d.ts +14 -0
- package/dist/render-png/montage.js +75 -0
- package/dist/render-png/montage.js.map +1 -0
- package/dist/render-png/shoot.d.ts +25 -0
- package/dist/render-png/shoot.js +79 -0
- package/dist/render-png/shoot.js.map +1 -0
- package/dist/scaffold.d.ts +9 -0
- package/dist/scaffold.js +36 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/types.d.ts +212 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +6 -0
- package/dist/util.js +28 -0
- package/dist/util.js.map +1 -0
- package/package.json +66 -0
- package/skills/slaide/SKILL.md +64 -0
- package/skills/slaide/agents/openai.yaml +12 -0
- package/skills/slaide/examples/branded-deck.slaide +198 -0
- package/skills/slaide/examples/branded-theme.slaide.yaml +187 -0
- package/skills/slaide/examples/sample.slaide +98 -0
- package/skills/slaide/reference.md +177 -0
- package/skills/slaide/themes.md +171 -0
- package/themes/aurora.slaide.yaml +136 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copyright 2026 AIVory, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// @slaide/render-png — Playwright headless-Chromium capture of every slide to a
|
|
4
|
+
// PNG, with all builds settled. This is the fast "see your deck" loop: authoring
|
|
5
|
+
// a theme without it means flying blind (you can ship invisible text and never
|
|
6
|
+
// know). Renders the same web runtime markup, so PNGs match what an audience sees.
|
|
7
|
+
import { renderDeckHtml } from '../index.js';
|
|
8
|
+
import { readFileSync, mkdirSync } from 'node:fs';
|
|
9
|
+
import { dirname, resolve, join } from 'node:path';
|
|
10
|
+
async function loadPlaywright() {
|
|
11
|
+
try {
|
|
12
|
+
return await import('playwright');
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
throw new Error('PNG export needs Playwright. Install it:\n' +
|
|
16
|
+
' npm install playwright\n' +
|
|
17
|
+
' npx playwright install chromium');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Render a self-contained web-deck HTML + its IR to per-slide PNGs (builds settled). */
|
|
21
|
+
export async function shootHtml(html, ir, opts = {}) {
|
|
22
|
+
const outDir = opts.out ?? 'out/shots';
|
|
23
|
+
// Derive the missing dimension from the canvas aspect so `--width 512` yields a 16:9
|
|
24
|
+
// shot (not a portrait frame letterboxed top/bottom). Both unset → full canvas size.
|
|
25
|
+
const cw = ir.canvas.width;
|
|
26
|
+
const ch = ir.canvas.height;
|
|
27
|
+
let width = opts.width;
|
|
28
|
+
let height = opts.height;
|
|
29
|
+
if (width && !height)
|
|
30
|
+
height = Math.round((width * ch) / cw);
|
|
31
|
+
else if (height && !width)
|
|
32
|
+
width = Math.round((height * cw) / ch);
|
|
33
|
+
width = width ?? cw;
|
|
34
|
+
height = height ?? ch;
|
|
35
|
+
const scale = opts.scale ?? 1;
|
|
36
|
+
const tag = opts.tag ?? 'slide';
|
|
37
|
+
const fmt = opts.format ?? 'png';
|
|
38
|
+
const quality = Math.max(1, Math.min(100, opts.quality ?? 82));
|
|
39
|
+
mkdirSync(outDir, { recursive: true });
|
|
40
|
+
const { chromium } = await loadPlaywright();
|
|
41
|
+
const browser = opts.browser ?? (await chromium.launch());
|
|
42
|
+
try {
|
|
43
|
+
const page = await browser.newPage({ viewport: { width, height }, deviceScaleFactor: scale });
|
|
44
|
+
let doc = html;
|
|
45
|
+
if (opts.hideChrome) {
|
|
46
|
+
doc = doc.replace('</head>', '<style>.sl-counter,.sl-progress,.sl-notes,.sl-help,.sl-present-toggle{display:none !important;}</style></head>');
|
|
47
|
+
}
|
|
48
|
+
await page.setContent(doc, { waitUntil: 'networkidle' });
|
|
49
|
+
await page.evaluate(() => document.fonts?.ready);
|
|
50
|
+
// Render all charts (lazy in the runtime) and wait until they settle so every
|
|
51
|
+
// captured frame includes them. No-op + immediate for chart-free decks.
|
|
52
|
+
await page.evaluate(() => window.__slaideCharts?.renderAll());
|
|
53
|
+
await page
|
|
54
|
+
.waitForFunction(() => window.__slaideChartsReady === true, { timeout: 8000 })
|
|
55
|
+
.catch(() => { });
|
|
56
|
+
await page.waitForTimeout(400);
|
|
57
|
+
const paths = [];
|
|
58
|
+
for (let i = 0; i < ir.slides.length; i++) {
|
|
59
|
+
// window.slaide.show(n) reveals slide n with every build settled (shown).
|
|
60
|
+
await page.evaluate((n) => window.slaide.show(n), i);
|
|
61
|
+
await page.waitForTimeout(180);
|
|
62
|
+
const p = join(outDir, `${tag}-${String(i + 1).padStart(2, '0')}.${fmt === 'jpeg' ? 'jpg' : 'png'}`);
|
|
63
|
+
await page.screenshot(fmt === 'jpeg' ? { path: p, type: 'jpeg', quality } : { path: p });
|
|
64
|
+
paths.push(p);
|
|
65
|
+
}
|
|
66
|
+
return paths;
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
if (!opts.browser)
|
|
70
|
+
await browser.close();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Render every slide of a deck file to <out>/<tag>-NN.png. Returns the file paths. */
|
|
74
|
+
export async function shootDeck(deckPath, opts = {}) {
|
|
75
|
+
const src = readFileSync(deckPath, 'utf8');
|
|
76
|
+
const { html, ir } = renderDeckHtml(src, dirname(resolve(deckPath)), { mode: 'web', inline: true });
|
|
77
|
+
return shootHtml(html, ir, opts);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=shoot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shoot.js","sourceRoot":"","sources":["../../src/render-png/shoot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ScaffoldOptions {
|
|
2
|
+
title: string;
|
|
3
|
+
subtitle?: string;
|
|
4
|
+
/** Section/slide titles to stub out. */
|
|
5
|
+
outline?: string[];
|
|
6
|
+
/** Master reference; omit to use the bundled default theme. */
|
|
7
|
+
master?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function scaffoldDeck(opts: ScaffoldOptions): string;
|
package/dist/scaffold.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function scaffoldDeck(opts) {
|
|
2
|
+
const lines = [];
|
|
3
|
+
lines.push('---');
|
|
4
|
+
if (opts.master)
|
|
5
|
+
lines.push(`master: ${opts.master}`);
|
|
6
|
+
lines.push(`title: ${opts.title}`);
|
|
7
|
+
lines.push('~transition: slide-left');
|
|
8
|
+
lines.push('---');
|
|
9
|
+
lines.push('layout: cover');
|
|
10
|
+
lines.push('---');
|
|
11
|
+
lines.push(':: title ::');
|
|
12
|
+
lines.push(opts.title);
|
|
13
|
+
lines.push(':: subtitle ::');
|
|
14
|
+
lines.push(opts.subtitle ?? 'A presentation written in slaide');
|
|
15
|
+
lines.push('');
|
|
16
|
+
lines.push('??? Speaker notes for the opening slide.');
|
|
17
|
+
for (const item of opts.outline ?? ['Overview', 'Details', 'Summary']) {
|
|
18
|
+
lines.push('');
|
|
19
|
+
lines.push('---');
|
|
20
|
+
lines.push('layout: title-content');
|
|
21
|
+
lines.push('---');
|
|
22
|
+
lines.push(`## ${item}`);
|
|
23
|
+
lines.push('');
|
|
24
|
+
lines.push('- First point >>>');
|
|
25
|
+
lines.push('- Second point >>>');
|
|
26
|
+
lines.push('- Third point >>>');
|
|
27
|
+
}
|
|
28
|
+
lines.push('');
|
|
29
|
+
lines.push('---');
|
|
30
|
+
lines.push('layout: section');
|
|
31
|
+
lines.push('---');
|
|
32
|
+
lines.push('# Thank you');
|
|
33
|
+
lines.push('');
|
|
34
|
+
return lines.join('\n') + '\n';
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,YAAY,CAAC,IAAqB;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,IAAI,IAAI,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACnC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACtC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,kCAAkC,CAAC,CAAC;IAChE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAEvD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;QACtE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACjC,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
export declare const SCHEMA_VERSION: "slaide/1";
|
|
2
|
+
export interface Warning {
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
line?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ParsedRegion {
|
|
8
|
+
name: string;
|
|
9
|
+
/** Raw markdown (region marker stripped). Build/anchor sigils handled in compiler. */
|
|
10
|
+
markdown: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ParsedSlide {
|
|
13
|
+
/** Per-slide config (scoped) merged with cascaded keys at compile time. */
|
|
14
|
+
frontmatter: Record<string, unknown>;
|
|
15
|
+
regions: ParsedRegion[];
|
|
16
|
+
notes: string | null;
|
|
17
|
+
sourceLine: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ParsedDeck {
|
|
20
|
+
headmatter: Record<string, unknown>;
|
|
21
|
+
slides: ParsedSlide[];
|
|
22
|
+
warnings: Warning[];
|
|
23
|
+
}
|
|
24
|
+
export interface MasterFont {
|
|
25
|
+
family: string;
|
|
26
|
+
provider?: 'google' | 'local' | 'system';
|
|
27
|
+
weights?: number[];
|
|
28
|
+
}
|
|
29
|
+
export interface TypeScale {
|
|
30
|
+
base: string;
|
|
31
|
+
ratio: number;
|
|
32
|
+
steps: Record<string, number | string>;
|
|
33
|
+
}
|
|
34
|
+
export interface MasterColors {
|
|
35
|
+
palette: Record<string, string>;
|
|
36
|
+
roles: Record<string, string>;
|
|
37
|
+
}
|
|
38
|
+
export type BackgroundDef = {
|
|
39
|
+
type: 'solid';
|
|
40
|
+
color: string;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'gradient';
|
|
43
|
+
stops: string[];
|
|
44
|
+
angle?: number;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'image';
|
|
47
|
+
src: string;
|
|
48
|
+
fit?: 'cover' | 'contain';
|
|
49
|
+
dim?: number;
|
|
50
|
+
};
|
|
51
|
+
export interface SlotDef {
|
|
52
|
+
type: string;
|
|
53
|
+
style?: Record<string, string>;
|
|
54
|
+
}
|
|
55
|
+
export interface LayoutDef {
|
|
56
|
+
/** grid-template-areas rows, each a quoted string of area names. */
|
|
57
|
+
areas: string[];
|
|
58
|
+
rows?: string;
|
|
59
|
+
cols?: string;
|
|
60
|
+
background?: string;
|
|
61
|
+
variant?: string;
|
|
62
|
+
slots: Record<string, SlotDef>;
|
|
63
|
+
padding?: string;
|
|
64
|
+
gap?: string;
|
|
65
|
+
align?: string;
|
|
66
|
+
chrome?: boolean | string;
|
|
67
|
+
logo?: boolean;
|
|
68
|
+
}
|
|
69
|
+
export interface VariantDef {
|
|
70
|
+
roles?: Record<string, string>;
|
|
71
|
+
tokens?: Record<string, string>;
|
|
72
|
+
}
|
|
73
|
+
export interface ChromeBand {
|
|
74
|
+
left?: string;
|
|
75
|
+
center?: string;
|
|
76
|
+
right?: string;
|
|
77
|
+
}
|
|
78
|
+
export interface ChromeDef {
|
|
79
|
+
header?: ChromeBand;
|
|
80
|
+
footer?: ChromeBand;
|
|
81
|
+
/** Raw inline SVG or HTML for a logo mark. */
|
|
82
|
+
logo?: string;
|
|
83
|
+
/** Logo corner: top-left | top-right | bottom-left | bottom-right. */
|
|
84
|
+
logoPos?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface Master {
|
|
87
|
+
schema?: string;
|
|
88
|
+
name: string;
|
|
89
|
+
description?: string;
|
|
90
|
+
canvas?: {
|
|
91
|
+
aspect?: string;
|
|
92
|
+
width?: number;
|
|
93
|
+
height?: number;
|
|
94
|
+
};
|
|
95
|
+
fonts?: Record<string, MasterFont>;
|
|
96
|
+
typeScale?: TypeScale;
|
|
97
|
+
colors?: MasterColors;
|
|
98
|
+
/** Named gradients -> CSS gradient strings (used by `.grad` spans and slot styles). */
|
|
99
|
+
gradients?: Record<string, string>;
|
|
100
|
+
/** Raw CSS custom-property overrides merged into the deck tokens (e.g. spacing/chrome). */
|
|
101
|
+
tokens?: Record<string, string>;
|
|
102
|
+
backgrounds?: Record<string, BackgroundDef>;
|
|
103
|
+
layouts?: Record<string, LayoutDef>;
|
|
104
|
+
variants?: Record<string, VariantDef>;
|
|
105
|
+
transitions?: {
|
|
106
|
+
default?: string;
|
|
107
|
+
duration?: number;
|
|
108
|
+
ease?: string;
|
|
109
|
+
};
|
|
110
|
+
/** Theme-defined named animations (slide transitions and/or element entrances),
|
|
111
|
+
* merged into the built-in catalog so authors/AI can reference them by name. */
|
|
112
|
+
animations?: Record<string, MasterAnimationDef>;
|
|
113
|
+
chrome?: ChromeDef;
|
|
114
|
+
/** Interactive-presentation UI toggles (web runtime only; never affects PDF/print). */
|
|
115
|
+
ui?: {
|
|
116
|
+
progress?: boolean;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export interface MasterAnimationDef {
|
|
120
|
+
/** slide transition: keyframe body for the entering slide, e.g. "from{…} to{…}". */
|
|
121
|
+
in?: string;
|
|
122
|
+
/** slide transition: keyframe body for the leaving slide. */
|
|
123
|
+
out?: string;
|
|
124
|
+
/** element entrance: pre-reveal hidden state, e.g. "opacity:0;transform:scale(.8)". */
|
|
125
|
+
hidden?: string;
|
|
126
|
+
/** force interpretation as an entrance (otherwise inferred from `hidden` vs `in`/`out`). */
|
|
127
|
+
entrance?: boolean;
|
|
128
|
+
duration?: number;
|
|
129
|
+
ease?: string;
|
|
130
|
+
}
|
|
131
|
+
export interface RegionIR {
|
|
132
|
+
name: string;
|
|
133
|
+
/** Original parsed region name in the source (`default` or a `:: marker ::`),
|
|
134
|
+
* before routing to a layout slot — source-provenance for round-tripping the
|
|
135
|
+
* rendered DOM back to its source region (the DOM `name` is the slot, which may
|
|
136
|
+
* differ from the source name for the default region). */
|
|
137
|
+
source: string;
|
|
138
|
+
/** Rendered HTML, with build elements carrying data-build. */
|
|
139
|
+
html: string;
|
|
140
|
+
/** Style hints resolved from the slot definition. */
|
|
141
|
+
slotType: string;
|
|
142
|
+
style: Record<string, string>;
|
|
143
|
+
}
|
|
144
|
+
export interface SlideIR {
|
|
145
|
+
index: number;
|
|
146
|
+
layout: string;
|
|
147
|
+
transition: string;
|
|
148
|
+
background: BackgroundDef | null;
|
|
149
|
+
/** master-defined names for this slide (for editor round-tripping; null when unset). */
|
|
150
|
+
bgName?: string | null;
|
|
151
|
+
variantName?: string | null;
|
|
152
|
+
/** grid CSS for this slide's layout. */
|
|
153
|
+
grid: {
|
|
154
|
+
areas: string;
|
|
155
|
+
rows: string;
|
|
156
|
+
cols: string;
|
|
157
|
+
padding: string;
|
|
158
|
+
gap: string;
|
|
159
|
+
align: string;
|
|
160
|
+
};
|
|
161
|
+
regions: RegionIR[];
|
|
162
|
+
notes: string | null;
|
|
163
|
+
/** total number of build steps on this slide. */
|
|
164
|
+
buildCount: number;
|
|
165
|
+
morph: string | null;
|
|
166
|
+
/** per-slide CSS custom property overrides (from variants). */
|
|
167
|
+
vars: Record<string, string>;
|
|
168
|
+
/** resolved chrome (placeholders substituted, inline markdown rendered). */
|
|
169
|
+
chrome: ResolvedChrome | null;
|
|
170
|
+
}
|
|
171
|
+
export interface ResolvedChrome {
|
|
172
|
+
header: {
|
|
173
|
+
left: string;
|
|
174
|
+
center: string;
|
|
175
|
+
right: string;
|
|
176
|
+
} | null;
|
|
177
|
+
footer: {
|
|
178
|
+
left: string;
|
|
179
|
+
center: string;
|
|
180
|
+
right: string;
|
|
181
|
+
} | null;
|
|
182
|
+
logo: string | null;
|
|
183
|
+
logoPos: string;
|
|
184
|
+
}
|
|
185
|
+
export interface DeckIR {
|
|
186
|
+
schema: string;
|
|
187
|
+
meta: {
|
|
188
|
+
title: string | null;
|
|
189
|
+
author: string | null;
|
|
190
|
+
};
|
|
191
|
+
canvas: {
|
|
192
|
+
width: number;
|
|
193
|
+
height: number;
|
|
194
|
+
aspect: string;
|
|
195
|
+
};
|
|
196
|
+
/** flat CSS custom properties, e.g. "--color-text": "#fff". */
|
|
197
|
+
tokens: Record<string, string>;
|
|
198
|
+
/** font import directives (e.g. google fonts URL or @font-face css). */
|
|
199
|
+
fontImports: string[];
|
|
200
|
+
transitions: {
|
|
201
|
+
default: string;
|
|
202
|
+
duration: number;
|
|
203
|
+
};
|
|
204
|
+
/** CSS for master-defined custom animations (appended to the deck stylesheet). */
|
|
205
|
+
animCss: string;
|
|
206
|
+
/** Resolved interactive-UI toggles (web runtime only). */
|
|
207
|
+
ui: {
|
|
208
|
+
progress: boolean;
|
|
209
|
+
};
|
|
210
|
+
slides: SlideIR[];
|
|
211
|
+
warnings: Warning[];
|
|
212
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Copyright 2026 AIVory, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// Shared types for the slaide pipeline: parser AST and the compiled IR.
|
|
4
|
+
// The IR (DeckIR) is the durable, renderer-agnostic contract. Bump SCHEMA_VERSION
|
|
5
|
+
// only with a migration story (see plan: @slaide/migrate).
|
|
6
|
+
export const SCHEMA_VERSION = 'slaide/1';
|
|
7
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,sCAAsC;AACtC,wEAAwE;AACxE,kFAAkF;AAClF,2DAA2D;AAE3D,MAAM,CAAC,MAAM,cAAc,GAAG,UAAmB,CAAC"}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Escape text for safe interpolation into HTML (text or double-quoted attrs). */
|
|
2
|
+
export declare function escapeHtml(s: string): string;
|
|
3
|
+
/** Serialize a CSS property map into a `prop:val;prop:val` string. */
|
|
4
|
+
export declare function serializeStyle(style: Record<string, string>): string;
|
|
5
|
+
/** Expand an anchor spec `"x y w h"` into absolute-position CSS properties. */
|
|
6
|
+
export declare function expandAnchor(spec: string): Record<string, string>;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright 2026 AIVory, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// Small shared helpers used across the pipeline.
|
|
4
|
+
/** Escape text for safe interpolation into HTML (text or double-quoted attrs). */
|
|
5
|
+
export function escapeHtml(s) {
|
|
6
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
7
|
+
}
|
|
8
|
+
/** Serialize a CSS property map into a `prop:val;prop:val` string. */
|
|
9
|
+
export function serializeStyle(style) {
|
|
10
|
+
return Object.entries(style)
|
|
11
|
+
.map(([k, v]) => `${k}:${v}`)
|
|
12
|
+
.join(';');
|
|
13
|
+
}
|
|
14
|
+
/** Expand an anchor spec `"x y w h"` into absolute-position CSS properties. */
|
|
15
|
+
export function expandAnchor(spec) {
|
|
16
|
+
const [x, y, w, h] = spec.trim().split(/\s+/);
|
|
17
|
+
const out = { position: 'absolute' };
|
|
18
|
+
if (x)
|
|
19
|
+
out.left = x;
|
|
20
|
+
if (y)
|
|
21
|
+
out.top = y;
|
|
22
|
+
if (w)
|
|
23
|
+
out.width = w;
|
|
24
|
+
if (h)
|
|
25
|
+
out.height = h;
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,sCAAsC;AACtC,iDAAiD;AAEjD,kFAAkF;AAClF,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACtG,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,cAAc,CAAC,KAA6B;IAC1D,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SACzB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;SAC5B,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,GAAG,GAA2B,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAC7D,IAAI,CAAC;QAAE,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;IACpB,IAAI,CAAC;QAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IACnB,IAAI,CAAC;QAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACrB,IAAI,CAAC;QAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACtB,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aivorynet/slaide",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "An AI-authorable slide language with beautiful web + PDF output",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"author": "Paul Piper",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"slides",
|
|
10
|
+
"presentation",
|
|
11
|
+
"markdown",
|
|
12
|
+
"pdf",
|
|
13
|
+
"ai",
|
|
14
|
+
"deck",
|
|
15
|
+
"powerpoint-alternative"
|
|
16
|
+
],
|
|
17
|
+
"bin": {
|
|
18
|
+
"slaide": "bin/slaide.js"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./dist/index.js",
|
|
22
|
+
"./cli": "./dist/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"bin",
|
|
27
|
+
"themes",
|
|
28
|
+
"skills",
|
|
29
|
+
"CHANGELOG.md"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.json",
|
|
33
|
+
"build:engine": "bun build src/engine-entry.ts --compile --external playwright --external playwright-core --external chromium-bidi --outfile viewer/vendor/slaide-engine",
|
|
34
|
+
"build:viewer": "npm run build:engine && cargo build --release --manifest-path viewer/Cargo.toml",
|
|
35
|
+
"dev": "tsx src/cli.ts",
|
|
36
|
+
"slaide": "tsx src/cli.ts",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:watch": "vitest"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
42
|
+
"ajv": "^8.17.1",
|
|
43
|
+
"ajv-formats": "^3.0.1",
|
|
44
|
+
"fast-xml-parser": "^4.5.6",
|
|
45
|
+
"js-yaml": "^4.1.0",
|
|
46
|
+
"jszip": "^3.10.1",
|
|
47
|
+
"markdown-it": "^14.1.0",
|
|
48
|
+
"zod": "^3.24.1"
|
|
49
|
+
},
|
|
50
|
+
"optionalDependencies": {
|
|
51
|
+
"playwright": "^1.49.0",
|
|
52
|
+
"pptxgenjs": "^3.12.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/js-yaml": "^4.0.9",
|
|
56
|
+
"@types/markdown-it": "^14.1.2",
|
|
57
|
+
"@types/node": "^22.10.0",
|
|
58
|
+
"@types/pngjs": "^6.0.5",
|
|
59
|
+
"pdf-to-png-converter": "^4.1.1",
|
|
60
|
+
"pixelmatch": "^7.2.0",
|
|
61
|
+
"pngjs": "^7.0.0",
|
|
62
|
+
"tsx": "^4.19.2",
|
|
63
|
+
"typescript": "^5.7.2",
|
|
64
|
+
"vitest": "^2.1.8"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slaide
|
|
3
|
+
description: Author and render slaide presentations — a Markdown + YAML slide language that exports a web deck, a high-fidelity PDF, editable PPTX, and a JPEG contact sheet you read to SEE the deck. Use when asked to make slides, a deck, a talk, or a presentation, or to edit / render / import a .slaide, .slaide.yaml, or .pptx file.
|
|
4
|
+
paths:
|
|
5
|
+
- "**/*.slaide"
|
|
6
|
+
- "**/*.slaide.yaml"
|
|
7
|
+
- "**/*.slaidec"
|
|
8
|
+
allowed-tools: Bash(slaide *), Bash(npx @aivorynet/slaide *), Bash(npm run slaide *)
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# slaide
|
|
12
|
+
|
|
13
|
+
One `.slaide` file (Markdown + a small YAML header) → web deck + PDF + PPTX. You write content; a reusable **master** (`*.slaide.yaml`) carries the design. Reference layouts / colours / fonts / classes **by name** from the master — never hand-style.
|
|
14
|
+
|
|
15
|
+
Run as `npx @aivorynet/slaide <cmd>` (or `npm run slaide -- <cmd>` where a script exists; at a monorepo root `npm run slaide -w @aivorynet/slaide -- <cmd>`, which shifts cwd to `core/` — pass **absolute** deck paths).
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
1. **Read** `reference.md` (language) and `themes.md` (masters/layouts/footguns). `examples/` is a worked deck + theme.
|
|
19
|
+
2. **`slaide slots <deck>`** — prints the master's real layouts, slots, colours, gradients, sizes, transitions. Reference these **by name**. (Run on the deck, not the master.)
|
|
20
|
+
3. **Write** the `.slaide` — and the master, if authoring one.
|
|
21
|
+
4. **`slaide validate <deck> --strict`** — a **gate**: must be clean. Every `unknown-*` / `low-contrast` / `non-embeddable-font` means something renders wrong even when it "looks valid".
|
|
22
|
+
5. **See it.** You can't open a browser, so: **`slaide shoot <deck> --montage out/sheet.jpg`** tiles every slide into one JPEG — **Read that image.** It's the only way to catch the common defects: overlapping / clipped text, hollow cards, weak contrast, overflow. Iterate until it looks genuinely professional — not just until validate passes.
|
|
23
|
+
|
|
24
|
+
## Format in 30 seconds
|
|
25
|
+
```
|
|
26
|
+
---
|
|
27
|
+
master: ./theme.slaide.yaml # omit → bundled "aurora"
|
|
28
|
+
title: My Talk
|
|
29
|
+
~transition: slide-left # `~` cascades to later slides
|
|
30
|
+
---
|
|
31
|
+
layout: cover
|
|
32
|
+
---
|
|
33
|
+
:: title ::
|
|
34
|
+
My Talk
|
|
35
|
+
:: subtitle ::
|
|
36
|
+
written in slaide
|
|
37
|
+
---
|
|
38
|
+
layout: title-content
|
|
39
|
+
---
|
|
40
|
+
## Why it's nice
|
|
41
|
+
- Plain text in >>> # `>>>` = reveal step
|
|
42
|
+
- Beautiful out >>>
|
|
43
|
+
??? Speaker note (audience never sees this).
|
|
44
|
+
```
|
|
45
|
+
- `---` separates slides; the first config block is deck headmatter; a `key:`-only block after `---` is a slide's frontmatter.
|
|
46
|
+
- `:: name ::` routes Markdown into a layout slot. `[text]{.class}` = styled span (colour `.accent`, gradient `.grad`, size `.lg`). `>>>` = build. `??? text` = note. Inside ``` fences these sigils are literal.
|
|
47
|
+
- Charts: ` ```echart ` (data viz, ECharts option as JSON) and ` ```mermaid ` (diagrams) → theme-coloured SVG. Put a chart in a slot with height (a `1fr` row).
|
|
48
|
+
|
|
49
|
+
## Authoring a master → themes.md
|
|
50
|
+
Define fonts, a type scale, two-tier colour (palette + roles), gradients, backgrounds, grid layouts, chrome — all data. Reference **roles, not hex**, so a reskin is a palette swap. Past "tidy", give the deck **one signature** (a faint logo-derived motif or a recurring accent panel) and vary composition slide to slide. The load-bearing footguns — dark-on-dark text, hollow `box:` cards, chrome-corner collisions — are flagged in `themes.md`; heed them. A deck about slaide itself: use the shipped brand in the sibling `slaide-hugo` repo, don't invent one.
|
|
51
|
+
|
|
52
|
+
## Commands (prefix `npx @aivorynet/slaide`)
|
|
53
|
+
| Command | Does |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `slots <deck>` | List the master's vocabulary (source of truth) |
|
|
56
|
+
| `validate <deck> [--strict]` | Line-numbered diagnostics; `--strict` fails on warnings |
|
|
57
|
+
| `shoot <deck> --montage out/sheet.jpg` | All slides → one JPEG contact sheet — the see-it loop (Playwright) |
|
|
58
|
+
| `shoot <deck> --out shots --jpeg` | One image per slide |
|
|
59
|
+
| `build <deck> --out out` | Self-contained HTML; charts baked to SVG |
|
|
60
|
+
| `export <deck> --pdf` · `--pptx` | PDF · editable PowerPoint (Playwright) |
|
|
61
|
+
| `import <file.pptx\|.key>` | PowerPoint/Keynote → slaide |
|
|
62
|
+
| `new <file>` · `themes` · `pack`/`unpack` | scaffold · list themes · bundle `.slaidec` |
|
|
63
|
+
|
|
64
|
+
If Playwright is missing: `npx playwright install chromium` once.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Codex-specific skill metadata (Agent Skills open standard).
|
|
2
|
+
# Install this skill folder under .agents/skills/slaide for OpenAI Codex.
|
|
3
|
+
display_name: slaide
|
|
4
|
+
description: Author and render slaide presentations (markdown + YAML → web deck + PDF).
|
|
5
|
+
icon: "🎞️"
|
|
6
|
+
brand_color: "#6C8Cff"
|
|
7
|
+
policy:
|
|
8
|
+
allow_implicit_invocation: true
|
|
9
|
+
dependencies:
|
|
10
|
+
tools:
|
|
11
|
+
# Optional: if the slaide MCP server is registered, Codex can use its tools.
|
|
12
|
+
- slaide
|