@classic-homes/slides 0.4.0 → 0.5.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/README.md +13 -0
- package/dist/{chunk-L7G3VH7K.js → chunk-GX6P2SE6.js} +17 -3
- package/dist/chunk-GX6P2SE6.js.map +1 -0
- package/dist/{chunk-PTTLL6PQ.js → chunk-OUAMH2TP.js} +72 -2
- package/dist/chunk-OUAMH2TP.js.map +1 -0
- package/dist/{chunk-JFUJ47TP.js → chunk-TEE3OGRQ.js} +2 -2
- package/dist/cli.js +23 -4
- package/dist/cli.js.map +1 -1
- package/dist/{render-CU0sXO2y.d.ts → images-8N30SsCW.d.ts} +38 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/{mcp-UX32IP2J.js → mcp-3WAVCLQ2.js} +4 -4
- package/dist/node.d.ts +15 -3
- package/dist/node.js +4 -2
- package/package.json +1 -1
- package/dist/chunk-L7G3VH7K.js.map +0 -1
- package/dist/chunk-PTTLL6PQ.js.map +0 -1
- /package/dist/{chunk-JFUJ47TP.js.map → chunk-TEE3OGRQ.js.map} +0 -0
- /package/dist/{mcp-UX32IP2J.js.map → mcp-3WAVCLQ2.js.map} +0 -0
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
LAYOUT_CATEGORIES,
|
|
5
5
|
baseSlide,
|
|
6
6
|
getLayout
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OUAMH2TP.js";
|
|
8
8
|
|
|
9
9
|
// src/catalog.ts
|
|
10
10
|
import { z } from "zod";
|
|
@@ -104,4 +104,4 @@ export {
|
|
|
104
104
|
deckJsonSchema,
|
|
105
105
|
AUTHORING_GUIDE
|
|
106
106
|
};
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
107
|
+
//# sourceMappingURL=chunk-TEE3OGRQ.js.map
|
package/dist/cli.js
CHANGED
|
@@ -4,18 +4,19 @@ import {
|
|
|
4
4
|
deckJsonSchema,
|
|
5
5
|
describeLayout,
|
|
6
6
|
listLayouts
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-TEE3OGRQ.js";
|
|
8
8
|
import {
|
|
9
9
|
buildDeckFile,
|
|
10
|
+
exportDeckFile,
|
|
10
11
|
fileImageResolver,
|
|
11
12
|
loadDeckFile
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GX6P2SE6.js";
|
|
13
14
|
import {
|
|
14
15
|
DeckError,
|
|
15
16
|
formatIssues,
|
|
16
17
|
renderDeck,
|
|
17
18
|
validateDeck
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-OUAMH2TP.js";
|
|
19
20
|
|
|
20
21
|
// src/node/cli.ts
|
|
21
22
|
import { watch } from "fs";
|
|
@@ -30,12 +31,14 @@ Usage
|
|
|
30
31
|
classic-slides new <file.yaml> [--starter basic|journey] Start a deck from a starter
|
|
31
32
|
classic-slides build <file.yaml> [-o out.html] Render one self-contained HTML file
|
|
32
33
|
classic-slides dev <file.yaml> [--port 4321] Live preview; reloads on save
|
|
34
|
+
classic-slides export <file.yaml> [-o out.json] Portable JSON with images inlined, for import
|
|
33
35
|
classic-slides validate <file.yaml> Check for errors and crowded slides
|
|
34
36
|
classic-slides layouts [name] List layouts, or show one in detail
|
|
35
37
|
classic-slides guide Print the authoring guide
|
|
36
38
|
classic-slides schema Print the deck JSON Schema
|
|
37
39
|
classic-slides mcp [--root dir] Run the MCP server on stdio
|
|
38
40
|
`;
|
|
41
|
+
var IMPORT_WARN_MB = 10;
|
|
39
42
|
var pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
40
43
|
async function main() {
|
|
41
44
|
const { positionals, values } = parseArgs({
|
|
@@ -76,6 +79,22 @@ Next: classic-slides dev ${basename(target)}`);
|
|
|
76
79
|
console.log(`\u2714 ${r.out} \u2014 ${r.slideCount} slides, ${(r.bytes / 1024 / 1024).toFixed(2)} MB`);
|
|
77
80
|
return;
|
|
78
81
|
}
|
|
82
|
+
case "export": {
|
|
83
|
+
if (!arg) throw new Error("Usage: classic-slides export <file.yaml>");
|
|
84
|
+
const r = await exportDeckFile(arg, {
|
|
85
|
+
out: values.out,
|
|
86
|
+
onWarning: (w) => console.warn(`\u26A0 ${w}`)
|
|
87
|
+
});
|
|
88
|
+
for (const w of r.warnings) console.warn(`\u26A0 Not inlined: ${w.src} \u2014 ${w.message}`);
|
|
89
|
+
const mb = r.bytes / 1024 / 1024;
|
|
90
|
+
console.log(`\u2714 ${r.out} \u2014 ${mb.toFixed(2)} MB`);
|
|
91
|
+
if (mb > IMPORT_WARN_MB)
|
|
92
|
+
console.warn(
|
|
93
|
+
`\u26A0 Over ${IMPORT_WARN_MB} MB; the deck editor may refuse it. Resize large photos (~2000px wide).`
|
|
94
|
+
);
|
|
95
|
+
process.exitCode = r.warnings.length ? 1 : 0;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
79
98
|
case "validate": {
|
|
80
99
|
if (!arg) throw new Error("Usage: classic-slides validate <file.yaml>");
|
|
81
100
|
const v = validateDeck(await loadDeckFile(resolve(arg)));
|
|
@@ -107,7 +126,7 @@ ${"".padEnd(12)} Use for: ${l.whenToUse}
|
|
|
107
126
|
case "mcp": {
|
|
108
127
|
let mcp;
|
|
109
128
|
try {
|
|
110
|
-
mcp = await import("./mcp-
|
|
129
|
+
mcp = await import("./mcp-3WAVCLQ2.js");
|
|
111
130
|
} catch (e) {
|
|
112
131
|
if (e.code === "ERR_MODULE_NOT_FOUND") {
|
|
113
132
|
throw new Error(
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/node/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * classic-slides — build branded Classic Homes decks from YAML.\n */\nimport { watch } from 'node:fs';\nimport { access, copyFile, mkdir } from 'node:fs/promises';\nimport { createServer } from 'node:http';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { parseArgs } from 'node:util';\nimport { AUTHORING_GUIDE, deckJsonSchema, describeLayout, listLayouts } from '../catalog.js';\nimport { renderDeck } from '../render.js';\nimport { DeckError, formatIssues, validateDeck } from '../validate.js';\nimport { buildDeckFile, fileImageResolver, loadDeckFile } from './index.js';\n\nconst HELP = `classic-slides — branded Classic Homes presentations\n\nUsage\n classic-slides new <file.yaml> [--starter basic|journey] Start a deck from a starter\n classic-slides build <file.yaml> [-o out.html] Render one self-contained HTML file\n classic-slides dev <file.yaml> [--port 4321] Live preview; reloads on save\n classic-slides validate <file.yaml> Check for errors and crowded slides\n classic-slides layouts [name] List layouts, or show one in detail\n classic-slides guide Print the authoring guide\n classic-slides schema Print the deck JSON Schema\n classic-slides mcp [--root dir] Run the MCP server on stdio\n`;\n\nconst pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\n\nasync function main() {\n const { positionals, values } = parseArgs({\n allowPositionals: true,\n options: {\n out: { type: 'string', short: 'o' },\n port: { type: 'string', default: '4321' },\n starter: { type: 'string', default: 'basic' },\n root: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n },\n });\n const [cmd, arg] = positionals;\n\n if (!cmd || values.help) return void process.stdout.write(HELP);\n\n switch (cmd) {\n case 'new': {\n if (!arg) throw new Error('Usage: classic-slides new <file.yaml>');\n const target = resolve(arg.endsWith('.yaml') || arg.endsWith('.yml') ? arg : `${arg}.yaml`);\n if (\n await access(target).then(\n () => true,\n () => false\n )\n )\n throw new Error(`${target} already exists.`);\n const starter = join(pkgRoot, 'starters', `${values.starter}.yaml`);\n await mkdir(dirname(target), { recursive: true });\n await copyFile(starter, target);\n console.log(`Created ${target}\\nNext: classic-slides dev ${basename(target)}`);\n return;\n }\n case 'build': {\n if (!arg) throw new Error('Usage: classic-slides build <file.yaml>');\n const r = await buildDeckFile(arg, {\n out: values.out,\n onWarning: (w) => console.warn(`⚠ ${w}`),\n });\n if (r.warnings.length) console.warn(formatIssues(r.warnings));\n console.log(`✔ ${r.out} — ${r.slideCount} slides, ${(r.bytes / 1024 / 1024).toFixed(2)} MB`);\n return;\n }\n case 'validate': {\n if (!arg) throw new Error('Usage: classic-slides validate <file.yaml>');\n const v = validateDeck(await loadDeckFile(resolve(arg)));\n console.log(v.issues.length ? formatIssues(v.issues) : '✔ Valid, no warnings');\n process.exitCode = v.ok ? 0 : 1;\n return;\n }\n case 'dev':\n return dev(arg, Number(values.port));\n case 'layouts': {\n if (arg) {\n const d = describeLayout(arg);\n if (!d) throw new Error(`Unknown layout \"${arg}\".`);\n console.log(JSON.stringify(d, null, 2));\n } else {\n for (const l of listLayouts())\n console.log(\n `${l.name.padEnd(12)} ${l.description}\\n${''.padEnd(12)} Use for: ${l.whenToUse}\\n`\n );\n }\n return;\n }\n case 'guide':\n return void console.log(AUTHORING_GUIDE);\n case 'schema':\n return void console.log(JSON.stringify(deckJsonSchema(), null, 2));\n case 'mcp': {\n // The MCP SDK is an optional peer so apps that only render decks don't install it.\n let mcp: typeof import('./mcp.js');\n try {\n mcp = await import('./mcp.js');\n } catch (e) {\n if ((e as { code?: string }).code === 'ERR_MODULE_NOT_FOUND') {\n throw new Error(\n 'The MCP server needs @modelcontextprotocol/sdk. Run it with:\\n npx -y -p @classic-homes/slides -p @modelcontextprotocol/sdk classic-slides mcp'\n );\n }\n throw e;\n }\n return mcp.runStdio(values.root);\n }\n default:\n throw new Error(`Unknown command \"${cmd}\".\\n\\n${HELP}`);\n }\n}\n\n/** Preview server: renders on every request and reloads the page when the deck folder changes. */\nasync function dev(file: string | undefined, port: number) {\n if (!file) throw new Error('Usage: classic-slides dev <file.yaml>');\n const abs = resolve(file);\n const dir = dirname(abs);\n const clients = new Set<import('node:http').ServerResponse>();\n const reload = `<script>new EventSource('/__reload').onmessage=()=>location.reload()</script>`;\n\n const errorPage = (msg: string) =>\n `<!doctype html><meta charset=\"utf-8\"><title>Deck error</title><body style=\"font:15px/1.5 ui-monospace,monospace;padding:40px;background:#fdf2f2;color:#7f1d1d\"><h2 style=\"font-family:system-ui\">Deck has problems</h2><pre style=\"white-space:pre-wrap\">${msg\n .replace(/&/g, '&')\n .replace(/</g, '<')}</pre>${reload}`;\n\n createServer(async (req, res) => {\n if (req.url === '/__reload') {\n res.writeHead(200, {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache',\n connection: 'keep-alive',\n });\n res.write(': ok\\n\\n');\n clients.add(res);\n req.on('close', () => clients.delete(res));\n return;\n }\n let html: string;\n try {\n const deck = await loadDeckFile(abs);\n const r = await renderDeck(deck, {\n resolveImage: fileImageResolver(dir),\n embedSource: false,\n });\n html = r.html.replace('</body>', `${reload}</body>`);\n if (r.warnings.length) console.warn(formatIssues(r.warnings));\n } catch (e) {\n html = errorPage(\n e instanceof DeckError ? formatIssues(e.issues) : e instanceof Error ? e.message : String(e)\n );\n }\n res.writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-store' });\n res.end(html);\n }).listen(port, () =>\n console.log(`Previewing ${file} at http://localhost:${port} (Ctrl+C to stop)`)\n );\n\n let timer: NodeJS.Timeout | undefined;\n watch(dir, { recursive: true }, (_, name) => {\n if (name && /\\.html$/.test(name)) return;\n clearTimeout(timer);\n timer = setTimeout(() => clients.forEach((c) => c.write('data: reload\\n\\n')), 120);\n });\n}\n\nmain().catch((e) => {\n console.error(e instanceof DeckError ? e.message : `✖ ${e instanceof Error ? e.message : e}`);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/node/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * classic-slides — build branded Classic Homes decks from YAML.\n */\nimport { watch } from 'node:fs';\nimport { access, copyFile, mkdir } from 'node:fs/promises';\nimport { createServer } from 'node:http';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { parseArgs } from 'node:util';\nimport { AUTHORING_GUIDE, deckJsonSchema, describeLayout, listLayouts } from '../catalog.js';\nimport { renderDeck } from '../render.js';\nimport { DeckError, formatIssues, validateDeck } from '../validate.js';\nimport { buildDeckFile, exportDeckFile, fileImageResolver, loadDeckFile } from './index.js';\n\nconst HELP = `classic-slides — branded Classic Homes presentations\n\nUsage\n classic-slides new <file.yaml> [--starter basic|journey] Start a deck from a starter\n classic-slides build <file.yaml> [-o out.html] Render one self-contained HTML file\n classic-slides dev <file.yaml> [--port 4321] Live preview; reloads on save\n classic-slides export <file.yaml> [-o out.json] Portable JSON with images inlined, for import\n classic-slides validate <file.yaml> Check for errors and crowded slides\n classic-slides layouts [name] List layouts, or show one in detail\n classic-slides guide Print the authoring guide\n classic-slides schema Print the deck JSON Schema\n classic-slides mcp [--root dir] Run the MCP server on stdio\n`;\n\n/** Size above which hosted deck imports are likely to be refused. */\nconst IMPORT_WARN_MB = 10;\n\nconst pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\n\nasync function main() {\n const { positionals, values } = parseArgs({\n allowPositionals: true,\n options: {\n out: { type: 'string', short: 'o' },\n port: { type: 'string', default: '4321' },\n starter: { type: 'string', default: 'basic' },\n root: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n },\n });\n const [cmd, arg] = positionals;\n\n if (!cmd || values.help) return void process.stdout.write(HELP);\n\n switch (cmd) {\n case 'new': {\n if (!arg) throw new Error('Usage: classic-slides new <file.yaml>');\n const target = resolve(arg.endsWith('.yaml') || arg.endsWith('.yml') ? arg : `${arg}.yaml`);\n if (\n await access(target).then(\n () => true,\n () => false\n )\n )\n throw new Error(`${target} already exists.`);\n const starter = join(pkgRoot, 'starters', `${values.starter}.yaml`);\n await mkdir(dirname(target), { recursive: true });\n await copyFile(starter, target);\n console.log(`Created ${target}\\nNext: classic-slides dev ${basename(target)}`);\n return;\n }\n case 'build': {\n if (!arg) throw new Error('Usage: classic-slides build <file.yaml>');\n const r = await buildDeckFile(arg, {\n out: values.out,\n onWarning: (w) => console.warn(`⚠ ${w}`),\n });\n if (r.warnings.length) console.warn(formatIssues(r.warnings));\n console.log(`✔ ${r.out} — ${r.slideCount} slides, ${(r.bytes / 1024 / 1024).toFixed(2)} MB`);\n return;\n }\n case 'export': {\n if (!arg) throw new Error('Usage: classic-slides export <file.yaml>');\n const r = await exportDeckFile(arg, {\n out: values.out,\n onWarning: (w) => console.warn(`⚠ ${w}`),\n });\n for (const w of r.warnings) console.warn(`⚠ Not inlined: ${w.src} — ${w.message}`);\n const mb = r.bytes / 1024 / 1024;\n console.log(`✔ ${r.out} — ${mb.toFixed(2)} MB`);\n if (mb > IMPORT_WARN_MB)\n console.warn(\n `⚠ Over ${IMPORT_WARN_MB} MB; the deck editor may refuse it. Resize large photos (~2000px wide).`\n );\n process.exitCode = r.warnings.length ? 1 : 0;\n return;\n }\n case 'validate': {\n if (!arg) throw new Error('Usage: classic-slides validate <file.yaml>');\n const v = validateDeck(await loadDeckFile(resolve(arg)));\n console.log(v.issues.length ? formatIssues(v.issues) : '✔ Valid, no warnings');\n process.exitCode = v.ok ? 0 : 1;\n return;\n }\n case 'dev':\n return dev(arg, Number(values.port));\n case 'layouts': {\n if (arg) {\n const d = describeLayout(arg);\n if (!d) throw new Error(`Unknown layout \"${arg}\".`);\n console.log(JSON.stringify(d, null, 2));\n } else {\n for (const l of listLayouts())\n console.log(\n `${l.name.padEnd(12)} ${l.description}\\n${''.padEnd(12)} Use for: ${l.whenToUse}\\n`\n );\n }\n return;\n }\n case 'guide':\n return void console.log(AUTHORING_GUIDE);\n case 'schema':\n return void console.log(JSON.stringify(deckJsonSchema(), null, 2));\n case 'mcp': {\n // The MCP SDK is an optional peer so apps that only render decks don't install it.\n let mcp: typeof import('./mcp.js');\n try {\n mcp = await import('./mcp.js');\n } catch (e) {\n if ((e as { code?: string }).code === 'ERR_MODULE_NOT_FOUND') {\n throw new Error(\n 'The MCP server needs @modelcontextprotocol/sdk. Run it with:\\n npx -y -p @classic-homes/slides -p @modelcontextprotocol/sdk classic-slides mcp'\n );\n }\n throw e;\n }\n return mcp.runStdio(values.root);\n }\n default:\n throw new Error(`Unknown command \"${cmd}\".\\n\\n${HELP}`);\n }\n}\n\n/** Preview server: renders on every request and reloads the page when the deck folder changes. */\nasync function dev(file: string | undefined, port: number) {\n if (!file) throw new Error('Usage: classic-slides dev <file.yaml>');\n const abs = resolve(file);\n const dir = dirname(abs);\n const clients = new Set<import('node:http').ServerResponse>();\n const reload = `<script>new EventSource('/__reload').onmessage=()=>location.reload()</script>`;\n\n const errorPage = (msg: string) =>\n `<!doctype html><meta charset=\"utf-8\"><title>Deck error</title><body style=\"font:15px/1.5 ui-monospace,monospace;padding:40px;background:#fdf2f2;color:#7f1d1d\"><h2 style=\"font-family:system-ui\">Deck has problems</h2><pre style=\"white-space:pre-wrap\">${msg\n .replace(/&/g, '&')\n .replace(/</g, '<')}</pre>${reload}`;\n\n createServer(async (req, res) => {\n if (req.url === '/__reload') {\n res.writeHead(200, {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache',\n connection: 'keep-alive',\n });\n res.write(': ok\\n\\n');\n clients.add(res);\n req.on('close', () => clients.delete(res));\n return;\n }\n let html: string;\n try {\n const deck = await loadDeckFile(abs);\n const r = await renderDeck(deck, {\n resolveImage: fileImageResolver(dir),\n embedSource: false,\n });\n html = r.html.replace('</body>', `${reload}</body>`);\n if (r.warnings.length) console.warn(formatIssues(r.warnings));\n } catch (e) {\n html = errorPage(\n e instanceof DeckError ? formatIssues(e.issues) : e instanceof Error ? e.message : String(e)\n );\n }\n res.writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-store' });\n res.end(html);\n }).listen(port, () =>\n console.log(`Previewing ${file} at http://localhost:${port} (Ctrl+C to stop)`)\n );\n\n let timer: NodeJS.Timeout | undefined;\n watch(dir, { recursive: true }, (_, name) => {\n if (name && /\\.html$/.test(name)) return;\n clearTimeout(timer);\n timer = setTimeout(() => clients.forEach((c) => c.write('data: reload\\n\\n')), 120);\n });\n}\n\nmain().catch((e) => {\n console.error(e instanceof DeckError ? e.message : `✖ ${e instanceof Error ? e.message : e}`);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|
|
@@ -601,4 +601,41 @@ declare function renderDeck(input: unknown, options?: RenderOptions): Promise<Re
|
|
|
601
601
|
/** Pulls the embedded deck source back out of a rendered HTML file. */
|
|
602
602
|
declare function extractDeckSource(html: string): unknown | undefined;
|
|
603
603
|
|
|
604
|
-
|
|
604
|
+
/**
|
|
605
|
+
* Rewrites every image src in a deck: inline them as data URIs for a portable
|
|
606
|
+
* single-file export, or swap data URIs for hosted URLs on import.
|
|
607
|
+
*/
|
|
608
|
+
|
|
609
|
+
interface MapImagesOptions extends ValidateOptions {
|
|
610
|
+
/** Images rewritten at once. Default 4. */
|
|
611
|
+
concurrency?: number;
|
|
612
|
+
}
|
|
613
|
+
interface InlineImagesResult {
|
|
614
|
+
/** A copy of the input deck with image srcs replaced. */
|
|
615
|
+
deck: unknown;
|
|
616
|
+
/** Images left as they were because the resolver failed. */
|
|
617
|
+
warnings: {
|
|
618
|
+
src: string;
|
|
619
|
+
message: string;
|
|
620
|
+
}[];
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Calls `fn` once per distinct image src and returns a copy of `input` with
|
|
624
|
+
* each src replaced by the result. The deck is validated first so images
|
|
625
|
+
* written as plain strings (`image: photo.jpg`) are found too; the copy keeps
|
|
626
|
+
* the author's shape (strings stay strings, no schema defaults are added).
|
|
627
|
+
* Throws `DeckError` if the deck is invalid, or the first error from `fn`.
|
|
628
|
+
*/
|
|
629
|
+
declare function mapDeckImages(input: unknown, fn: (src: string) => string | Promise<string>, options?: MapImagesOptions): Promise<unknown>;
|
|
630
|
+
/**
|
|
631
|
+
* Inlines every image as a data URI so the deck is one self-contained file.
|
|
632
|
+
* Images the resolver can't load are left as-is and reported in `warnings`.
|
|
633
|
+
*/
|
|
634
|
+
declare function inlineDeckImages(input: unknown, resolve: ImageResolver, options?: MapImagesOptions): Promise<InlineImagesResult>;
|
|
635
|
+
/**
|
|
636
|
+
* Replaces every data-URI image with the src `upload` returns (e.g. a hosted
|
|
637
|
+
* URL). Other srcs are untouched. Errors from `upload` are thrown.
|
|
638
|
+
*/
|
|
639
|
+
declare function externalizeDeckImages(input: unknown, upload: (dataUri: string) => string | Promise<string>, options?: MapImagesOptions): Promise<unknown>;
|
|
640
|
+
|
|
641
|
+
export { type ValidationResult as A, type BrandPalette as B, CLASSIC_HOMES_BRAND as C, type Deck as D, checkPalette as E, type FieldMarker as F, collectImageSources as G, externalizeDeckImages as H, type ImageInput as I, extractDeckSource as J, fieldMarkers as K, type LayoutCategory as L, type MapImagesOptions as M, formatIssues as N, formatPath as O, PREVIEW_SIZE as P, getLayout as Q, type RenderOptions as R, type SlideData as S, inlineDeckImages as T, mapDeckImages as U, type ValidateOptions as V, renderDeck as W, resolveBrand as X, validateBrandProfile as Y, validateDeck as Z, BrandPaletteSchema as a, type BrandProfile as b, type BrandProfileInput as c, BrandProfileSchema as d, CLASSIC_HOMES_PALETTE as e, type DeckBrand as f, DeckBrandSchema as g, DeckError as h, type DeckInput as i, DeckSchema as j, type DeckSettings as k, DeckSettingsSchema as l, type ImageResolver as m, type ImageValue as n, type InlineImagesResult as o, type ItemValue as p, LAYOUTS as q, LAYOUT_CATEGORIES as r, LAYOUT_CATEGORY_ORDER as s, type LayoutDef as t, type LayoutIssue as u, type LayoutName as v, type RenderResult as w, type ResolvedBrand as x, type SlideInput as y, SlideSchema as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { L as LayoutCategory, B as BrandPalette } from './
|
|
2
|
-
export { a as BrandPaletteSchema, b as BrandProfile, c as BrandProfileInput, d as BrandProfileSchema, C as CLASSIC_HOMES_BRAND, e as CLASSIC_HOMES_PALETTE, D as Deck, f as DeckBrand, g as DeckBrandSchema, h as DeckError, i as DeckInput, j as DeckSchema, k as DeckSettings, l as DeckSettingsSchema, F as FieldMarker, I as ImageInput, m as ImageResolver, n as ImageValue, o as
|
|
1
|
+
import { L as LayoutCategory, B as BrandPalette } from './images-8N30SsCW.js';
|
|
2
|
+
export { a as BrandPaletteSchema, b as BrandProfile, c as BrandProfileInput, d as BrandProfileSchema, C as CLASSIC_HOMES_BRAND, e as CLASSIC_HOMES_PALETTE, D as Deck, f as DeckBrand, g as DeckBrandSchema, h as DeckError, i as DeckInput, j as DeckSchema, k as DeckSettings, l as DeckSettingsSchema, F as FieldMarker, I as ImageInput, m as ImageResolver, n as ImageValue, o as InlineImagesResult, p as ItemValue, q as LAYOUTS, r as LAYOUT_CATEGORIES, s as LAYOUT_CATEGORY_ORDER, t as LayoutDef, u as LayoutIssue, v as LayoutName, M as MapImagesOptions, P as PREVIEW_SIZE, R as RenderOptions, w as RenderResult, x as ResolvedBrand, S as SlideData, y as SlideInput, z as SlideSchema, V as ValidateOptions, A as ValidationResult, E as checkPalette, G as collectImageSources, H as externalizeDeckImages, J as extractDeckSource, K as fieldMarkers, N as formatIssues, O as formatPath, Q as getLayout, T as inlineDeckImages, U as mapDeckImages, W as renderDeck, X as resolveBrand, Y as validateBrandProfile, Z as validateDeck } from './images-8N30SsCW.js';
|
|
3
3
|
import * as zod_to_json_schema from 'zod-to-json-schema';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
deckJsonSchema,
|
|
4
4
|
describeLayout,
|
|
5
5
|
listLayouts
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TEE3OGRQ.js";
|
|
7
7
|
import {
|
|
8
8
|
BrandPaletteSchema,
|
|
9
9
|
BrandProfileSchema,
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
describeChart,
|
|
35
35
|
ensureSlideIds,
|
|
36
36
|
escapeHtml,
|
|
37
|
+
externalizeDeckImages,
|
|
37
38
|
extractDeckSource,
|
|
38
39
|
fieldMarkers,
|
|
39
40
|
findSlide,
|
|
@@ -42,10 +43,12 @@ import {
|
|
|
42
43
|
formatValue,
|
|
43
44
|
getLayout,
|
|
44
45
|
inline,
|
|
46
|
+
inlineDeckImages,
|
|
45
47
|
isPlaceholderImage,
|
|
46
48
|
layoutEditorInfo,
|
|
47
49
|
layoutGalleryDeck,
|
|
48
50
|
logoLockup,
|
|
51
|
+
mapDeckImages,
|
|
49
52
|
moveSlide,
|
|
50
53
|
newSlideId,
|
|
51
54
|
outline,
|
|
@@ -62,7 +65,7 @@ import {
|
|
|
62
65
|
validateBrandProfile,
|
|
63
66
|
validateDeck,
|
|
64
67
|
videoEmbedUrl
|
|
65
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-OUAMH2TP.js";
|
|
66
69
|
|
|
67
70
|
// src/generated/runtime-hash.ts
|
|
68
71
|
var RUNTIME_SCRIPT_HASH = "sha256-gElvQAb4VPvKu4UeyJRVKuoHYNp8NGhXwx2EhL7NB88=";
|
|
@@ -100,6 +103,7 @@ export {
|
|
|
100
103
|
describeLayout,
|
|
101
104
|
ensureSlideIds,
|
|
102
105
|
escapeHtml,
|
|
106
|
+
externalizeDeckImages,
|
|
103
107
|
extractDeckSource,
|
|
104
108
|
fieldMarkers,
|
|
105
109
|
findSlide,
|
|
@@ -108,11 +112,13 @@ export {
|
|
|
108
112
|
formatValue,
|
|
109
113
|
getLayout,
|
|
110
114
|
inline,
|
|
115
|
+
inlineDeckImages,
|
|
111
116
|
isPlaceholderImage,
|
|
112
117
|
layoutEditorInfo,
|
|
113
118
|
layoutGalleryDeck,
|
|
114
119
|
listLayouts,
|
|
115
120
|
logoLockup,
|
|
121
|
+
mapDeckImages,
|
|
116
122
|
moveSlide,
|
|
117
123
|
newSlideId,
|
|
118
124
|
outline,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generated/runtime-hash.ts"],"sourcesContent":["// Generated by scripts/embed-fonts.ts. Do not edit.\n/** CSP source for the inline presenter runtime: script-src '<hash>'. */\nexport const RUNTIME_SCRIPT_HASH = 'sha256-gElvQAb4VPvKu4UeyJRVKuoHYNp8NGhXwx2EhL7NB88=';\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/generated/runtime-hash.ts"],"sourcesContent":["// Generated by scripts/embed-fonts.ts. Do not edit.\n/** CSP source for the inline presenter runtime: script-src '<hash>'. */\nexport const RUNTIME_SCRIPT_HASH = 'sha256-gElvQAb4VPvKu4UeyJRVKuoHYNp8NGhXwx2EhL7NB88=';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEO,IAAM,sBAAsB;","names":[]}
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
AUTHORING_GUIDE,
|
|
3
3
|
describeLayout,
|
|
4
4
|
listLayouts
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TEE3OGRQ.js";
|
|
6
6
|
import {
|
|
7
7
|
buildDeckFile,
|
|
8
8
|
confinedPath,
|
|
9
9
|
loadDeckFile,
|
|
10
10
|
saveDeckFile
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GX6P2SE6.js";
|
|
12
12
|
import {
|
|
13
13
|
addSlide,
|
|
14
14
|
formatIssues,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
stringifyDeck,
|
|
19
19
|
updateSlide,
|
|
20
20
|
validateDeck
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-OUAMH2TP.js";
|
|
22
22
|
|
|
23
23
|
// src/node/mcp.ts
|
|
24
24
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -320,4 +320,4 @@ export {
|
|
|
320
320
|
createSlidesMcpServer,
|
|
321
321
|
runStdio
|
|
322
322
|
};
|
|
323
|
-
//# sourceMappingURL=mcp-
|
|
323
|
+
//# sourceMappingURL=mcp-3WAVCLQ2.js.map
|
package/dist/node.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RenderOptions,
|
|
2
|
-
export {
|
|
1
|
+
import { R as RenderOptions, w as RenderResult, o as InlineImagesResult, m as ImageResolver } from './images-8N30SsCW.js';
|
|
2
|
+
export { W as renderDeck } from './images-8N30SsCW.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
/** Largest single image we inline without warning. Big photos bloat the deck file. */
|
|
@@ -23,5 +23,17 @@ declare function buildDeckFile(path: string, options?: BuildOptions): Promise<Re
|
|
|
23
23
|
out: string;
|
|
24
24
|
bytes: number;
|
|
25
25
|
}>;
|
|
26
|
+
interface ExportOptions extends FileResolverOptions {
|
|
27
|
+
out?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Writes a portable copy of a deck file: JSON with every image inlined as a
|
|
31
|
+
* data URI, ready to import into a hosted deck editor. Defaults to
|
|
32
|
+
* `<name>.deck.json` next to the source.
|
|
33
|
+
*/
|
|
34
|
+
declare function exportDeckFile(path: string, options?: ExportOptions): Promise<InlineImagesResult & {
|
|
35
|
+
out: string;
|
|
36
|
+
bytes: number;
|
|
37
|
+
}>;
|
|
26
38
|
|
|
27
|
-
export { type BuildOptions, type FileResolverOptions, IMAGE_WARN_BYTES, buildDeckFile, fileImageResolver, loadDeckFile, saveDeckFile };
|
|
39
|
+
export { type BuildOptions, type ExportOptions, type FileResolverOptions, IMAGE_WARN_BYTES, buildDeckFile, exportDeckFile, fileImageResolver, loadDeckFile, saveDeckFile };
|
package/dist/node.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IMAGE_WARN_BYTES,
|
|
3
3
|
buildDeckFile,
|
|
4
|
+
exportDeckFile,
|
|
4
5
|
fileImageResolver,
|
|
5
6
|
loadDeckFile,
|
|
6
7
|
saveDeckFile
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GX6P2SE6.js";
|
|
8
9
|
import {
|
|
9
10
|
renderDeck
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-OUAMH2TP.js";
|
|
11
12
|
export {
|
|
12
13
|
IMAGE_WARN_BYTES,
|
|
13
14
|
buildDeckFile,
|
|
15
|
+
exportDeckFile,
|
|
14
16
|
fileImageResolver,
|
|
15
17
|
loadDeckFile,
|
|
16
18
|
renderDeck,
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/node/index.ts","../src/node/paths.ts"],"sourcesContent":["/** Node-only helpers: read deck files, inline local images, write HTML. */\nimport { readFile, stat, writeFile } from 'node:fs/promises';\nimport { dirname, extname, isAbsolute, join, resolve } from 'node:path';\nimport { confinedPath } from './paths.js';\nimport { parseDeckSource, stringifyDeck } from '../parse.js';\nimport {\n renderDeck,\n type ImageResolver,\n type RenderOptions,\n type RenderResult,\n} from '../render.js';\n\nconst MIME: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.webp': 'image/webp',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.avif': 'image/avif',\n};\n\n/** Largest single image we inline without warning. Big photos bloat the deck file. */\nexport const IMAGE_WARN_BYTES = 800 * 1024;\n\nexport interface FileResolverOptions {\n /** Restrict local image reads and build paths to this root (used by the MCP server). */\n rootDir?: string;\n /** Fetch https images and inline them so the deck works offline. Default true. */\n inlineRemote?: boolean;\n onWarning?: (message: string) => void;\n}\n\n/** Resolves image paths relative to the deck file and inlines them as data URIs. */\nexport function fileImageResolver(\n baseDir: string,\n options: FileResolverOptions = {}\n): ImageResolver {\n const warn = options.onWarning ?? (() => {});\n return async (src) => {\n if (src.startsWith('data:')) return src;\n if (/^https?:/.test(src)) {\n if (options.inlineRemote === false) return src;\n const res = await fetch(src);\n if (!res.ok) throw new Error(`Image ${src} returned HTTP ${res.status}`);\n const type = res.headers.get('content-type') ?? 'application/octet-stream';\n const buf = Buffer.from(await res.arrayBuffer());\n if (buf.length > IMAGE_WARN_BYTES)\n warn(`${src} is ${(buf.length / 1024).toFixed(0)} KB; consider a smaller copy.`);\n return `data:${type};base64,${buf.toString('base64')}`;\n }\n const candidate = isAbsolute(src) ? src : join(baseDir, src);\n const path = options.rootDir ? confinedPath(options.rootDir, candidate) : candidate;\n const type = MIME[extname(path).toLowerCase()];\n if (!type)\n throw new Error(`Unsupported image type for \"${src}\". Use jpg, png, webp, gif, svg or avif.`);\n let buf: Buffer;\n try {\n buf = await readFile(path);\n } catch {\n throw new Error(`Image not found: \"${src}\" (looked in ${path})`);\n }\n if (buf.length > IMAGE_WARN_BYTES)\n warn(`${src} is ${(buf.length / 1024).toFixed(0)} KB; consider resizing to ~2000px wide.`);\n return `data:${type};base64,${buf.toString('base64')}`;\n };\n}\n\nexport async function loadDeckFile(path: string): Promise<unknown> {\n return parseDeckSource(await readFile(path, 'utf8'));\n}\n\nexport async function saveDeckFile(path: string, deck: unknown): Promise<void> {\n const text = path.endsWith('.json') ? JSON.stringify(deck, null, 2) + '\\n' : stringifyDeck(deck);\n await writeFile(path, text);\n}\n\nexport interface BuildOptions extends Omit<RenderOptions, 'resolveImage'>, FileResolverOptions {\n out?: string;\n}\n\n/** Renders a deck file to a self-contained HTML file next to it (or at `out`). */\nexport async function buildDeckFile(\n path: string,\n options: BuildOptions = {}\n): Promise<RenderResult & { out: string; bytes: number }> {\n const abs = options.rootDir ? confinedPath(options.rootDir, resolve(path)) : resolve(path);\n const deck = await loadDeckFile(abs);\n const result = await renderDeck(deck, {\n ...options,\n resolveImage: fileImageResolver(dirname(abs), options),\n });\n const candidate = options.out\n ? resolve(options.out)\n : abs.replace(/\\.(ya?ml|json)$/i, '') + '.html';\n const out = options.rootDir ? confinedPath(options.rootDir, candidate) : candidate;\n await writeFile(out, result.html);\n return { ...result, out, bytes: (await stat(out)).size };\n}\n\nexport { renderDeck };\n","/** Canonical containment for existing files and new output files. */\nimport { lstatSync, realpathSync } from 'node:fs';\nimport { dirname, relative, resolve, sep } from 'node:path';\n\nexport function confinedPath(root: string, path: string): string {\n const canonicalRoot = realpathSync(root);\n const absolute = resolve(path);\n let ancestor = absolute;\n for (;;) {\n try {\n const canonical = resolve(realpathSync(ancestor), relative(ancestor, absolute));\n if (canonical !== canonicalRoot && !canonical.startsWith(canonicalRoot + sep)) {\n throw new Error(`Path \"${path}\" is outside the deck root ${root}.`);\n }\n return canonical;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT' || ancestor === dirname(ancestor))\n throw error;\n if (lstatSync(ancestor, { throwIfNoEntry: false })?.isSymbolicLink()) {\n throw new Error(`Cannot follow dangling symlink \"${ancestor}\".`);\n }\n ancestor = dirname(ancestor);\n }\n }\n}\n"],"mappings":"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","names":["dirname","resolve","type","buf","resolve","dirname"]}
|