@classic-homes/slides 0.2.0 → 0.3.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 +74 -25
- package/dist/{chunk-CKVKX2ZD.js → chunk-2IPLZ3SA.js} +37 -7
- package/dist/chunk-2IPLZ3SA.js.map +1 -0
- package/dist/{chunk-TM3TNVHB.js → chunk-GXGDPBAR.js} +2717 -493
- package/dist/chunk-GXGDPBAR.js.map +1 -0
- package/dist/chunk-YI7A4EWX.js +107 -0
- package/dist/chunk-YI7A4EWX.js.map +1 -0
- package/dist/cli.js +15 -5
- package/dist/cli.js.map +1 -1
- package/dist/echarts-render-2QVSBZ6V.js +50 -0
- package/dist/echarts-render-2QVSBZ6V.js.map +1 -0
- package/dist/index.d.ts +149 -4
- package/dist/index.js +72 -133
- package/dist/index.js.map +1 -1
- package/dist/{mcp-5R6YD3QW.js → mcp-PUA45IS7.js} +17 -14
- package/dist/mcp-PUA45IS7.js.map +1 -0
- package/dist/node.d.ts +4 -2
- package/dist/node.js +2 -2
- package/dist/render-DcyKuBRD.d.ts +580 -0
- package/package.json +13 -3
- package/dist/chunk-CKVKX2ZD.js.map +0 -1
- package/dist/chunk-TM3TNVHB.js.map +0 -1
- package/dist/chunk-TXNQKBWJ.js +0 -69
- package/dist/chunk-TXNQKBWJ.js.map +0 -1
- package/dist/chunk-VONVGYRL.js +0 -52
- package/dist/chunk-VONVGYRL.js.map +0 -1
- package/dist/mcp-5R6YD3QW.js.map +0 -1
- package/dist/render-CZ4g2fa9.d.ts +0 -136
package/dist/chunk-TXNQKBWJ.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DeckSchema,
|
|
3
|
-
LAYOUTS,
|
|
4
|
-
baseSlide,
|
|
5
|
-
getLayout
|
|
6
|
-
} from "./chunk-TM3TNVHB.js";
|
|
7
|
-
|
|
8
|
-
// src/catalog.ts
|
|
9
|
-
import { z } from "zod";
|
|
10
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
11
|
-
function listLayouts() {
|
|
12
|
-
return LAYOUTS.map((l) => ({ name: l.name, description: l.description, whenToUse: l.whenToUse }));
|
|
13
|
-
}
|
|
14
|
-
function describeLayout(name) {
|
|
15
|
-
const layout = getLayout(name);
|
|
16
|
-
if (!layout) return void 0;
|
|
17
|
-
const schema = z.object({ layout: z.literal(layout.name), ...layout.shape, ...baseSlide });
|
|
18
|
-
return {
|
|
19
|
-
name: layout.name,
|
|
20
|
-
description: layout.description,
|
|
21
|
-
whenToUse: layout.whenToUse,
|
|
22
|
-
defaults: layout.defaults ?? {},
|
|
23
|
-
schema: zodToJsonSchema(schema, { $refStrategy: "none" }),
|
|
24
|
-
example: layout.example
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
function deckJsonSchema() {
|
|
28
|
-
return zodToJsonSchema(DeckSchema, { name: "ClassicDeck", $refStrategy: "none" });
|
|
29
|
-
}
|
|
30
|
-
var AUTHORING_GUIDE = `# Writing a Classic Homes deck
|
|
31
|
-
|
|
32
|
-
A deck is a YAML (or JSON) file: deck-level fields plus a list of slides. Each slide
|
|
33
|
-
picks a **layout** and fills its fields. Layouts own all styling \u2014 there is no way to
|
|
34
|
-
set colours, fonts or sizes directly, which is what keeps every deck on-brand.
|
|
35
|
-
|
|
36
|
-
## Principles
|
|
37
|
-
- **One idea per slide.** The headline states the point. Detail goes in \`notes\`.
|
|
38
|
-
- **Short copy.** Titles under ~70 characters, bullets a few words, at most 6 bullets.
|
|
39
|
-
\`validate\` warns when a slide gets crowded \u2014 split it rather than shrinking text.
|
|
40
|
-
- **Speaker notes on every content slide.** Presenters press N to see them.
|
|
41
|
-
- **Real photos over decoration.** Every image needs \`alt\` text.
|
|
42
|
-
- **Tracks** colour the accent: \`value\` (red, default) for the homeowner/value story,
|
|
43
|
-
\`build\` (teal) for construction/process, \`neutral\` (navy) for framing slides.
|
|
44
|
-
- **Backgrounds**: \`paper\` (default) for content; solid \`navy\`/\`red\`/\`teal\`/\`plum\`/\`grey\`/\`stone\`
|
|
45
|
-
for section dividers and moments of emphasis. Don't put dense content on solid grounds.
|
|
46
|
-
|
|
47
|
-
## Inline text
|
|
48
|
-
\`**bold**\`, \`*highlight*\` (accent colour), \`\\\`code\\\`\`, \`[label](https://\u2026)\`. No HTML.
|
|
49
|
-
|
|
50
|
-
## Journey decks
|
|
51
|
-
Set \`journey.steps\` at deck level to get a numbered agenda. Then:
|
|
52
|
-
- a \`journey\` slide shows the full map,
|
|
53
|
-
- \`step: 3\` on any slide draws the vertical STEP rail,
|
|
54
|
-
- \`showJourney: true\` adds the compact "you are here" strip (great on \`section\` slides).
|
|
55
|
-
|
|
56
|
-
## Typical shape
|
|
57
|
-
1. \`title\`
|
|
58
|
-
2. \`statement\` or \`journey\` (why we're here / the agenda)
|
|
59
|
-
3. per part: \`section\` \u2192 2\u20135 content slides (\`bullets\`, \`split\`, \`cards\`, \`stats\`, \`photos\`, \`walkthrough\`)
|
|
60
|
-
4. \`qr\` (where to go next) \u2192 \`contacts\` \u2192 closing \`statement\`
|
|
61
|
-
`;
|
|
62
|
-
|
|
63
|
-
export {
|
|
64
|
-
listLayouts,
|
|
65
|
-
describeLayout,
|
|
66
|
-
deckJsonSchema,
|
|
67
|
-
AUTHORING_GUIDE
|
|
68
|
-
};
|
|
69
|
-
//# sourceMappingURL=chunk-TXNQKBWJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/catalog.ts"],"sourcesContent":["import { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { LAYOUTS, getLayout } from './layouts/index.js';\nimport { baseSlide } from './schema/common.js';\nimport { DeckSchema } from './schema/deck.js';\n\nexport interface LayoutSummary {\n name: string;\n description: string;\n whenToUse: string;\n}\n\nexport function listLayouts(): LayoutSummary[] {\n return LAYOUTS.map((l) => ({ name: l.name, description: l.description, whenToUse: l.whenToUse }));\n}\n\n/** Full description of one layout: fields as JSON Schema plus a working example. */\nexport function describeLayout(name: string) {\n const layout = getLayout(name);\n if (!layout) return undefined;\n const schema = z.object({ layout: z.literal(layout.name), ...layout.shape, ...baseSlide });\n return {\n name: layout.name,\n description: layout.description,\n whenToUse: layout.whenToUse,\n defaults: layout.defaults ?? {},\n schema: zodToJsonSchema(schema, { $refStrategy: 'none' }),\n example: layout.example,\n };\n}\n\n/** JSON Schema for a whole deck (editor tooling, `$schema` in deck files). */\nexport function deckJsonSchema() {\n return zodToJsonSchema(DeckSchema, { name: 'ClassicDeck', $refStrategy: 'none' });\n}\n\n/** Authoring guidance shared by the CLI, MCP server and docs. */\nexport const AUTHORING_GUIDE = `# Writing a Classic Homes deck\n\nA deck is a YAML (or JSON) file: deck-level fields plus a list of slides. Each slide\npicks a **layout** and fills its fields. Layouts own all styling — there is no way to\nset colours, fonts or sizes directly, which is what keeps every deck on-brand.\n\n## Principles\n- **One idea per slide.** The headline states the point. Detail goes in \\`notes\\`.\n- **Short copy.** Titles under ~70 characters, bullets a few words, at most 6 bullets.\n \\`validate\\` warns when a slide gets crowded — split it rather than shrinking text.\n- **Speaker notes on every content slide.** Presenters press N to see them.\n- **Real photos over decoration.** Every image needs \\`alt\\` text.\n- **Tracks** colour the accent: \\`value\\` (red, default) for the homeowner/value story,\n \\`build\\` (teal) for construction/process, \\`neutral\\` (navy) for framing slides.\n- **Backgrounds**: \\`paper\\` (default) for content; solid \\`navy\\`/\\`red\\`/\\`teal\\`/\\`plum\\`/\\`grey\\`/\\`stone\\`\n for section dividers and moments of emphasis. Don't put dense content on solid grounds.\n\n## Inline text\n\\`**bold**\\`, \\`*highlight*\\` (accent colour), \\`\\\\\\`code\\\\\\`\\`, \\`[label](https://…)\\`. No HTML.\n\n## Journey decks\nSet \\`journey.steps\\` at deck level to get a numbered agenda. Then:\n- a \\`journey\\` slide shows the full map,\n- \\`step: 3\\` on any slide draws the vertical STEP rail,\n- \\`showJourney: true\\` adds the compact \"you are here\" strip (great on \\`section\\` slides).\n\n## Typical shape\n1. \\`title\\`\n2. \\`statement\\` or \\`journey\\` (why we're here / the agenda)\n3. per part: \\`section\\` → 2–5 content slides (\\`bullets\\`, \\`split\\`, \\`cards\\`, \\`stats\\`, \\`photos\\`, \\`walkthrough\\`)\n4. \\`qr\\` (where to go next) → \\`contacts\\` → closing \\`statement\\`\n`;\n"],"mappings":";;;;;;;;AAAA,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAWzB,SAAS,cAA+B;AAC7C,SAAO,QAAQ,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,EAAE,aAAa,WAAW,EAAE,UAAU,EAAE;AAClG;AAGO,SAAS,eAAe,MAAc;AAC3C,QAAM,SAAS,UAAU,IAAI;AAC7B,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,OAAO,IAAI,GAAG,GAAG,OAAO,OAAO,GAAG,UAAU,CAAC;AACzF,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,aAAa,OAAO;AAAA,IACpB,WAAW,OAAO;AAAA,IAClB,UAAU,OAAO,YAAY,CAAC;AAAA,IAC9B,QAAQ,gBAAgB,QAAQ,EAAE,cAAc,OAAO,CAAC;AAAA,IACxD,SAAS,OAAO;AAAA,EAClB;AACF;AAGO,SAAS,iBAAiB;AAC/B,SAAO,gBAAgB,YAAY,EAAE,MAAM,eAAe,cAAc,OAAO,CAAC;AAClF;AAGO,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
|
package/dist/chunk-VONVGYRL.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// src/edit.ts
|
|
2
|
-
function findSlide(deck, ref) {
|
|
3
|
-
const index = typeof ref === "number" || /^\d+$/.test(ref) ? Number(ref) - 1 : deck.slides.findIndex((s) => s.id === ref);
|
|
4
|
-
if (index < 0 || index >= deck.slides.length) {
|
|
5
|
-
throw new Error(
|
|
6
|
-
`No slide "${ref}". The deck has ${deck.slides.length} slides; use a 1-based number or a slide id.`
|
|
7
|
-
);
|
|
8
|
-
}
|
|
9
|
-
return index;
|
|
10
|
-
}
|
|
11
|
-
function addSlide(deck, slide, position) {
|
|
12
|
-
const at = position === void 0 ? deck.slides.length : Math.max(0, Math.min(deck.slides.length, position - 1));
|
|
13
|
-
deck.slides.splice(at, 0, slide);
|
|
14
|
-
return at + 1;
|
|
15
|
-
}
|
|
16
|
-
function updateSlide(deck, ref, patch) {
|
|
17
|
-
const i = findSlide(deck, ref);
|
|
18
|
-
const next = patch.layout && patch.layout !== deck.slides[i].layout ? {} : { ...deck.slides[i] };
|
|
19
|
-
for (const [k, v] of Object.entries(patch)) {
|
|
20
|
-
if (v === null) delete next[k];
|
|
21
|
-
else next[k] = v;
|
|
22
|
-
}
|
|
23
|
-
deck.slides[i] = next;
|
|
24
|
-
return i + 1;
|
|
25
|
-
}
|
|
26
|
-
function moveSlide(deck, ref, to) {
|
|
27
|
-
const from = findSlide(deck, ref);
|
|
28
|
-
const [slide] = deck.slides.splice(from, 1);
|
|
29
|
-
const at = Math.max(0, Math.min(deck.slides.length, to - 1));
|
|
30
|
-
deck.slides.splice(at, 0, slide);
|
|
31
|
-
return at + 1;
|
|
32
|
-
}
|
|
33
|
-
function removeSlide(deck, ref) {
|
|
34
|
-
const i = findSlide(deck, ref);
|
|
35
|
-
return deck.slides.splice(i, 1)[0];
|
|
36
|
-
}
|
|
37
|
-
function outline(deck) {
|
|
38
|
-
return deck.slides.map((s, i) => {
|
|
39
|
-
const label = s.title ?? s.quote ?? s.kicker ?? "";
|
|
40
|
-
return `${i + 1}. [${s.layout}]${s.id ? ` #${s.id}` : ""} ${label}`.trim();
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export {
|
|
45
|
-
findSlide,
|
|
46
|
-
addSlide,
|
|
47
|
-
updateSlide,
|
|
48
|
-
moveSlide,
|
|
49
|
-
removeSlide,
|
|
50
|
-
outline
|
|
51
|
-
};
|
|
52
|
-
//# sourceMappingURL=chunk-VONVGYRL.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/edit.ts"],"sourcesContent":["/**\n * Slide-level edits on a deck object. Pure functions shared by the MCP\n * server and (later) the hosted editor, so agents change one slide at a\n * time instead of rewriting whole files.\n */\nexport interface EditableDeck {\n slides: Record<string, unknown>[];\n [key: string]: unknown;\n}\n\n/** A slide reference: its `id`, or its 1-based position. */\nexport type SlideRef = string | number;\n\nexport function findSlide(deck: EditableDeck, ref: SlideRef): number {\n const index =\n typeof ref === 'number' || /^\\d+$/.test(ref)\n ? Number(ref) - 1\n : deck.slides.findIndex((s) => s.id === ref);\n if (index < 0 || index >= deck.slides.length) {\n throw new Error(\n `No slide \"${ref}\". The deck has ${deck.slides.length} slides; use a 1-based number or a slide id.`\n );\n }\n return index;\n}\n\n/** Inserts a slide. `position` is 1-based; omitted appends. Returns the new slide's position. */\nexport function addSlide(\n deck: EditableDeck,\n slide: Record<string, unknown>,\n position?: number\n): number {\n const at =\n position === undefined\n ? deck.slides.length\n : Math.max(0, Math.min(deck.slides.length, position - 1));\n deck.slides.splice(at, 0, slide);\n return at + 1;\n}\n\n/** Shallow-merges fields into a slide. A field set to null is removed. Changing `layout` replaces the slide. */\nexport function updateSlide(\n deck: EditableDeck,\n ref: SlideRef,\n patch: Record<string, unknown>\n): number {\n const i = findSlide(deck, ref);\n const next = patch.layout && patch.layout !== deck.slides[i].layout ? {} : { ...deck.slides[i] };\n for (const [k, v] of Object.entries(patch)) {\n if (v === null) delete (next as Record<string, unknown>)[k];\n else (next as Record<string, unknown>)[k] = v;\n }\n deck.slides[i] = next;\n return i + 1;\n}\n\nexport function moveSlide(deck: EditableDeck, ref: SlideRef, to: number): number {\n const from = findSlide(deck, ref);\n const [slide] = deck.slides.splice(from, 1);\n const at = Math.max(0, Math.min(deck.slides.length, to - 1));\n deck.slides.splice(at, 0, slide);\n return at + 1;\n}\n\nexport function removeSlide(deck: EditableDeck, ref: SlideRef): Record<string, unknown> {\n const i = findSlide(deck, ref);\n return deck.slides.splice(i, 1)[0];\n}\n\n/** One-line outline of each slide, for agents and CLIs. */\nexport function outline(deck: EditableDeck): string[] {\n return deck.slides.map((s, i) => {\n const label = (s.title ?? s.quote ?? s.kicker ?? '') as string;\n return `${i + 1}. [${s.layout}]${s.id ? ` #${s.id}` : ''} ${label}`.trim();\n });\n}\n"],"mappings":";AAaO,SAAS,UAAU,MAAoB,KAAuB;AACnE,QAAM,QACJ,OAAO,QAAQ,YAAY,QAAQ,KAAK,GAAG,IACvC,OAAO,GAAG,IAAI,IACd,KAAK,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG;AAC/C,MAAI,QAAQ,KAAK,SAAS,KAAK,OAAO,QAAQ;AAC5C,UAAM,IAAI;AAAA,MACR,aAAa,GAAG,mBAAmB,KAAK,OAAO,MAAM;AAAA,IACvD;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,SACd,MACA,OACA,UACQ;AACR,QAAM,KACJ,aAAa,SACT,KAAK,OAAO,SACZ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO,QAAQ,WAAW,CAAC,CAAC;AAC5D,OAAK,OAAO,OAAO,IAAI,GAAG,KAAK;AAC/B,SAAO,KAAK;AACd;AAGO,SAAS,YACd,MACA,KACA,OACQ;AACR,QAAM,IAAI,UAAU,MAAM,GAAG;AAC7B,QAAM,OAAO,MAAM,UAAU,MAAM,WAAW,KAAK,OAAO,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,EAAE;AAC/F,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC1C,QAAI,MAAM,KAAM,QAAQ,KAAiC,CAAC;AAAA,QACrD,CAAC,KAAiC,CAAC,IAAI;AAAA,EAC9C;AACA,OAAK,OAAO,CAAC,IAAI;AACjB,SAAO,IAAI;AACb;AAEO,SAAS,UAAU,MAAoB,KAAe,IAAoB;AAC/E,QAAM,OAAO,UAAU,MAAM,GAAG;AAChC,QAAM,CAAC,KAAK,IAAI,KAAK,OAAO,OAAO,MAAM,CAAC;AAC1C,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,CAAC,CAAC;AAC3D,OAAK,OAAO,OAAO,IAAI,GAAG,KAAK;AAC/B,SAAO,KAAK;AACd;AAEO,SAAS,YAAY,MAAoB,KAAwC;AACtF,QAAM,IAAI,UAAU,MAAM,GAAG;AAC7B,SAAO,KAAK,OAAO,OAAO,GAAG,CAAC,EAAE,CAAC;AACnC;AAGO,SAAS,QAAQ,MAA8B;AACpD,SAAO,KAAK,OAAO,IAAI,CAAC,GAAG,MAAM;AAC/B,UAAM,QAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU;AACjD,WAAO,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,KAAK,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,KAAK,GAAG,KAAK;AAAA,EAC3E,CAAC;AACH;","names":[]}
|
package/dist/mcp-5R6YD3QW.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/node/mcp.ts"],"sourcesContent":["/**\n * Local MCP server (stdio) for building decks on disk with an AI agent.\n *\n * Tools work slide-by-slide on a YAML deck file and validate before every\n * save, so an agent can never leave a deck in a broken state. File access is\n * confined to the root directory the server was started in.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { access } from 'node:fs/promises';\nimport { relative, resolve, sep } from 'node:path';\nimport { z } from 'zod';\nimport { AUTHORING_GUIDE, describeLayout, listLayouts } from '../catalog.js';\nimport {\n addSlide,\n moveSlide,\n outline,\n removeSlide,\n updateSlide,\n type EditableDeck,\n} from '../edit.js';\nimport { stringifyDeck } from '../parse.js';\nimport { formatIssues, validateDeck } from '../validate.js';\nimport { buildDeckFile, loadDeckFile, saveDeckFile } from './index.js';\n\nconst VERSION = '0.1.0';\n\ntype ToolResult = { content: { type: 'text'; text: string }[]; isError?: boolean };\nconst text = (t: string, isError = false): ToolResult => ({\n content: [{ type: 'text', text: t }],\n ...(isError ? { isError } : {}),\n});\n\nexport function createSlidesMcpServer(rootDir = process.cwd()): McpServer {\n const root = resolve(rootDir);\n const server = new McpServer({ name: 'classic-slides', version: VERSION });\n\n function safePath(p: string): string {\n const abs = resolve(root, p);\n if (abs !== root && !abs.startsWith(root + sep))\n throw new Error(`Path \"${p}\" is outside the deck root ${root}.`);\n if (!/\\.(ya?ml|json)$/i.test(abs))\n throw new Error('Deck files must end in .yaml, .yml or .json.');\n return abs;\n }\n\n async function load(p: string): Promise<{ abs: string; deck: EditableDeck }> {\n const abs = safePath(p);\n const deck = (await loadDeckFile(abs)) as EditableDeck;\n if (!deck || !Array.isArray(deck.slides))\n throw new Error(`${p} is not a deck file (no slides list).`);\n return { abs, deck };\n }\n\n /** Validates, then saves only when there are no errors. */\n async function commit(abs: string, deck: EditableDeck, done: string): Promise<ToolResult> {\n const v = validateDeck(deck);\n if (!v.ok) {\n return text(\n `Not saved — the change would make the deck invalid:\\n${formatIssues(v.issues)}\\n\\nFix the fields and try again.`,\n true\n );\n }\n await saveDeckFile(abs, deck);\n const warnings = v.issues.filter((i) => i.level === 'warning');\n return text(\n `${done}\\n\\nOutline:\\n${outline(deck).join('\\n')}${warnings.length ? `\\n\\nWarnings (saved anyway):\\n${formatIssues(warnings)}` : ''}`\n );\n }\n\n const run =\n <A>(fn: (args: A) => Promise<ToolResult>) =>\n async (args: A): Promise<ToolResult> => {\n try {\n return await fn(args);\n } catch (e) {\n return text(e instanceof Error ? e.message : String(e), true);\n }\n };\n\n const Path = z.string().describe(`Deck file path, relative to ${root}.`);\n const Ref = z.union([z.string(), z.number()]).describe('Slide id, or 1-based slide number.');\n const SlideObj = z\n .record(z.unknown())\n .describe('A slide object: { layout, ...fields }. See get_layout for fields.');\n\n server.tool(\n 'list_layouts',\n 'List every slide layout with what it is for. Start here.',\n {},\n async () =>\n text(\n listLayouts()\n .map((l) => `- **${l.name}** — ${l.description}\\n Use for: ${l.whenToUse}`)\n .join('\\n')\n )\n );\n\n server.tool(\n 'get_layout',\n 'Full field reference (JSON Schema) and a working example for one layout.',\n { name: z.string() },\n run(async ({ name }) => {\n const d = describeLayout(name);\n if (!d) return text(`Unknown layout \"${name}\". Call list_layouts.`, true);\n return text(JSON.stringify(d, null, 2));\n })\n );\n\n server.tool(\n 'get_authoring_guide',\n 'Brand and writing rules for Classic Homes decks. Read before writing slides.',\n {},\n async () => text(AUTHORING_GUIDE)\n );\n\n server.tool(\n 'create_deck',\n 'Create a new deck file. Optionally include the first slides.',\n {\n path: Path,\n title: z.string(),\n description: z.string().optional(),\n journeySteps: z\n .array(z.string())\n .optional()\n .describe('Numbered agenda steps; enables journey features.'),\n slides: z.array(SlideObj).optional(),\n overwrite: z.boolean().default(false),\n },\n run(async ({ path, title, description, journeySteps, slides, overwrite }) => {\n const abs = safePath(path);\n if (!overwrite) {\n const exists = await access(abs).then(\n () => true,\n () => false\n );\n if (exists)\n return text(\n `${path} already exists. Use read_deck and edit it, or pass overwrite: true.`,\n true\n );\n }\n const deck: EditableDeck = {\n title,\n ...(description ? { description } : {}),\n ...(journeySteps?.length ? { journey: { steps: journeySteps } } : {}),\n slides: slides?.length ? slides : [{ layout: 'title', title }],\n };\n return commit(abs, deck, `Created ${path}.`);\n })\n );\n\n server.tool(\n 'read_deck',\n 'Read a deck: outline plus the full YAML source.',\n { path: Path },\n run(async ({ path }) => {\n const { deck } = await load(path);\n return text(\n `Outline:\\n${outline(deck).join('\\n')}\\n\\nSource:\\n\\`\\`\\`yaml\\n${stringifyDeck(deck)}\\`\\`\\``\n );\n })\n );\n\n server.tool(\n 'update_deck',\n 'Change deck-level fields (title, description, author, date, journey). Set a field to null to remove it.',\n { path: Path, fields: z.record(z.unknown()) },\n run(async ({ path, fields }) => {\n const { abs, deck } = await load(path);\n for (const [k, v] of Object.entries(fields)) {\n if (k === 'slides') return text('Use the slide tools to change slides.', true);\n if (v === null) delete deck[k];\n else deck[k] = v;\n }\n return commit(abs, deck, 'Deck fields updated.');\n })\n );\n\n server.tool(\n 'add_slide',\n 'Insert a slide. position is 1-based; omit to append.',\n { path: Path, slide: SlideObj, position: z.number().int().positive().optional() },\n run(async ({ path, slide, position }) => {\n const { abs, deck } = await load(path);\n const at = addSlide(deck, slide, position);\n return commit(abs, deck, `Added slide ${at}.`);\n })\n );\n\n server.tool(\n 'add_slides',\n 'Append several slides at once (e.g. a whole section). Saved only if all are valid.',\n { path: Path, slides: z.array(SlideObj).min(1) },\n run(async ({ path, slides }) => {\n const { abs, deck } = await load(path);\n slides.forEach((s) => addSlide(deck, s));\n return commit(abs, deck, `Added ${slides.length} slides.`);\n })\n );\n\n server.tool(\n 'update_slide',\n 'Merge fields into a slide. Set a field to null to remove it. Changing layout replaces the slide.',\n { path: Path, slide: Ref, fields: z.record(z.unknown()) },\n run(async ({ path, slide, fields }) => {\n const { abs, deck } = await load(path);\n const at = updateSlide(deck, slide, fields);\n return commit(abs, deck, `Updated slide ${at}.`);\n })\n );\n\n server.tool(\n 'move_slide',\n 'Move a slide to a new 1-based position.',\n { path: Path, slide: Ref, to: z.number().int().positive() },\n run(async ({ path, slide, to }) => {\n const { abs, deck } = await load(path);\n const at = moveSlide(deck, slide, to);\n return commit(abs, deck, `Moved slide to ${at}.`);\n })\n );\n\n server.tool(\n 'delete_slide',\n 'Delete a slide.',\n { path: Path, slide: Ref },\n run(async ({ path, slide }) => {\n const { abs, deck } = await load(path);\n const removed = removeSlide(deck, slide);\n return commit(abs, deck, `Deleted [${removed.layout}] slide.`);\n })\n );\n\n server.tool(\n 'validate_deck',\n 'Check a deck for errors and crowded slides. Fix every error and most warnings before building.',\n { path: Path },\n run(async ({ path }) => {\n const { deck } = await load(path);\n const v = validateDeck(deck);\n if (!v.issues.length) return text('Deck is valid with no warnings.');\n return text(\n `${v.ok ? 'Valid, with warnings' : 'Invalid'}:\\n${formatIssues(v.issues)}`,\n !v.ok\n );\n })\n );\n\n server.tool(\n 'build_deck',\n 'Render the deck to one self-contained HTML file (images and fonts inlined). Returns the output path.',\n {\n path: Path,\n out: z.string().optional().describe('Output .html path; defaults next to the deck.'),\n },\n run(async ({ path, out }) => {\n const abs = safePath(path);\n let outAbs: string | undefined;\n if (out) {\n outAbs = resolve(root, out);\n if (!outAbs.startsWith(root + sep) || !outAbs.endsWith('.html'))\n throw new Error('out must be an .html path inside the deck root.');\n }\n const warnings: string[] = [];\n const r = await buildDeckFile(abs, { out: outAbs, onWarning: (w) => warnings.push(w) });\n return text(\n `Built ${relative(root, r.out)} — ${r.slideCount} slides, ${(r.bytes / 1024 / 1024).toFixed(2)} MB. Open it in a browser to present (N = notes, F = fullscreen).${\n warnings.length ? `\\n\\nImage warnings:\\n- ${warnings.join('\\n- ')}` : ''\n }${r.warnings.length ? `\\n\\nContent warnings:\\n${formatIssues(r.warnings)}` : ''}`\n );\n })\n );\n\n server.resource(\n 'authoring-guide',\n 'slides://guide',\n { mimeType: 'text/markdown' },\n async (uri) => ({\n contents: [{ uri: uri.href, mimeType: 'text/markdown', text: AUTHORING_GUIDE }],\n })\n );\n\n server.prompt(\n 'build_deck_from_outline',\n 'Turn a topic and rough outline into a finished, validated deck.',\n {\n path: z.string().describe('Where to save the deck, e.g. decks/closing-day.yaml'),\n topic: z.string(),\n audience: z.string(),\n outline: z.string().optional().describe('Bullet outline, notes, or pasted source material.'),\n },\n ({ path, topic, audience, outline: src }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Build a Classic Homes presentation.\n\nTopic: ${topic}\nAudience: ${audience}\nSave to: ${path}\n${src ? `\\nSource material:\\n${src}\\n` : ''}\nSteps:\n1. Call get_authoring_guide and list_layouts. Call get_layout for each layout you plan to use.\n2. Plan the slide list (one idea per slide) before writing.\n3. create_deck, then add_slides one section at a time. Put detail in each slide's notes.\n4. validate_deck and fix every error and crowding warning.\n5. build_deck and report the output path with a one-line summary per section.`,\n },\n },\n ],\n })\n );\n\n return server;\n}\n\nexport async function runStdio(rootDir?: string): Promise<void> {\n const server = createSlidesMcpServer(rootDir);\n await server.connect(new StdioServerTransport());\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
/** The deck-level fields a layout may read while rendering. */
|
|
4
|
-
interface DeckContext {
|
|
5
|
-
title: string;
|
|
6
|
-
journey?: {
|
|
7
|
-
steps: string[];
|
|
8
|
-
label: string;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
interface RenderContext {
|
|
12
|
-
deck: DeckContext;
|
|
13
|
-
/** Resolved image sources (original src → data URI or URL). */
|
|
14
|
-
image(src: string): string;
|
|
15
|
-
/** Pre-rendered QR code SVG for a URL. */
|
|
16
|
-
qr(url: string): string;
|
|
17
|
-
}
|
|
18
|
-
/** One rendered <section>. Layouts return several when one entry expands into a sequence. */
|
|
19
|
-
interface RenderedSlide {
|
|
20
|
-
html: string;
|
|
21
|
-
/** Extra classes on the section (layout class is added automatically). */
|
|
22
|
-
classes?: string[];
|
|
23
|
-
/** Overrides the slide's own notes (e.g. per-stage notes in a walkthrough). */
|
|
24
|
-
notes?: string;
|
|
25
|
-
time?: string;
|
|
26
|
-
}
|
|
27
|
-
interface LayoutIssue {
|
|
28
|
-
level: 'error' | 'warning';
|
|
29
|
-
path: (string | number)[];
|
|
30
|
-
message: string;
|
|
31
|
-
}
|
|
32
|
-
interface LayoutDef<Shape extends z.ZodRawShape = z.ZodRawShape> {
|
|
33
|
-
/** Value of `layout` in the deck file. */
|
|
34
|
-
name: string;
|
|
35
|
-
/** One line: what the slide looks like. */
|
|
36
|
-
description: string;
|
|
37
|
-
/** When an author or agent should pick this layout. */
|
|
38
|
-
whenToUse: string;
|
|
39
|
-
/** Layout-specific fields (base slide fields are added by the deck schema). */
|
|
40
|
-
shape: Shape;
|
|
41
|
-
/** Defaults applied when the slide leaves them unset. */
|
|
42
|
-
defaults?: {
|
|
43
|
-
background?: string;
|
|
44
|
-
track?: 'value' | 'build' | 'neutral';
|
|
45
|
-
};
|
|
46
|
-
/** A complete, valid example slide. */
|
|
47
|
-
example: Record<string, unknown>;
|
|
48
|
-
/** Soft checks beyond the schema: length and density limits that keep slides clean. */
|
|
49
|
-
lint?(slide: z.infer<z.ZodObject<Shape>>): LayoutIssue[];
|
|
50
|
-
render(slide: z.infer<z.ZodObject<Shape>>, ctx: RenderContext): RenderedSlide | RenderedSlide[];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** Every layout, in the order they are offered to authors. */
|
|
54
|
-
declare const LAYOUTS: readonly LayoutDef<any>[];
|
|
55
|
-
type LayoutName = 'title' | 'section' | 'statement' | 'bullets' | 'split' | 'cards' | 'stats' | 'comparison' | 'journey' | 'photos' | 'image' | 'walkthrough' | 'quote' | 'qr' | 'contacts';
|
|
56
|
-
declare function getLayout(name: string): LayoutDef | undefined;
|
|
57
|
-
|
|
58
|
-
/** Fields every slide has after parsing; layout-specific fields ride along. */
|
|
59
|
-
interface SlideData {
|
|
60
|
-
layout: LayoutName;
|
|
61
|
-
id?: string;
|
|
62
|
-
track?: 'value' | 'build' | 'neutral';
|
|
63
|
-
background?: 'paper' | 'navy' | 'slate' | 'red' | 'teal' | 'plum' | 'grey' | 'stone';
|
|
64
|
-
notes?: string;
|
|
65
|
-
time?: string;
|
|
66
|
-
step?: number;
|
|
67
|
-
stepDone?: boolean;
|
|
68
|
-
showJourney?: boolean;
|
|
69
|
-
[field: string]: unknown;
|
|
70
|
-
}
|
|
71
|
-
interface Deck {
|
|
72
|
-
title: string;
|
|
73
|
-
description?: string;
|
|
74
|
-
author?: string;
|
|
75
|
-
date?: string;
|
|
76
|
-
lang: string;
|
|
77
|
-
journey?: {
|
|
78
|
-
steps: string[];
|
|
79
|
-
label: string;
|
|
80
|
-
};
|
|
81
|
-
slides: SlideData[];
|
|
82
|
-
}
|
|
83
|
-
/** A deck as authored (before defaults are applied). */
|
|
84
|
-
type DeckInput = Omit<Partial<Deck>, 'slides' | 'journey'> & {
|
|
85
|
-
title: string;
|
|
86
|
-
journey?: {
|
|
87
|
-
steps: string[];
|
|
88
|
-
label?: string;
|
|
89
|
-
};
|
|
90
|
-
slides: ({
|
|
91
|
-
layout: LayoutName;
|
|
92
|
-
} & Record<string, unknown>)[];
|
|
93
|
-
};
|
|
94
|
-
type SlideInput = DeckInput['slides'][number];
|
|
95
|
-
declare const SlideSchema: z.ZodType<SlideData, z.ZodTypeDef, unknown>;
|
|
96
|
-
declare const DeckSchema: z.ZodType<Deck, z.ZodTypeDef, unknown>;
|
|
97
|
-
|
|
98
|
-
interface ValidationResult {
|
|
99
|
-
ok: boolean;
|
|
100
|
-
deck?: Deck;
|
|
101
|
-
/** Errors block rendering; warnings are advice that keeps slides clean. */
|
|
102
|
-
issues: LayoutIssue[];
|
|
103
|
-
}
|
|
104
|
-
declare function validateDeck(input: unknown): ValidationResult;
|
|
105
|
-
/** Human path: slides.3.items.0 → "slide 4 › items › 1" (positions are 1-based, like the outline). */
|
|
106
|
-
declare function formatPath(path: (string | number)[]): string;
|
|
107
|
-
declare function formatIssues(issues: LayoutIssue[]): string;
|
|
108
|
-
declare class DeckError extends Error {
|
|
109
|
-
issues: LayoutIssue[];
|
|
110
|
-
constructor(issues: LayoutIssue[]);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
type ImageResolver = (src: string) => Promise<string> | string;
|
|
114
|
-
interface RenderOptions {
|
|
115
|
-
/**
|
|
116
|
-
* Turns an image `src` from the deck into something the browser can load,
|
|
117
|
-
* normally a data: URI so the file stays self-contained. The default passes
|
|
118
|
-
* data: and https: URLs through and rejects everything else.
|
|
119
|
-
*/
|
|
120
|
-
resolveImage?: ImageResolver;
|
|
121
|
-
/** Embed the deck source (JSON, without image data) so the HTML can be re-opened for editing. Default true. */
|
|
122
|
-
embedSource?: boolean;
|
|
123
|
-
}
|
|
124
|
-
interface RenderResult {
|
|
125
|
-
html: string;
|
|
126
|
-
deck: Deck;
|
|
127
|
-
slideCount: number;
|
|
128
|
-
warnings: ReturnType<typeof validateDeck>['issues'];
|
|
129
|
-
}
|
|
130
|
-
/** Collects every image src in the deck (any object with a string `src`). */
|
|
131
|
-
declare function collectImageSources(value: unknown, out?: Set<string>): Set<string>;
|
|
132
|
-
declare function renderDeck(input: unknown, options?: RenderOptions): Promise<RenderResult>;
|
|
133
|
-
/** Pulls the embedded deck source back out of a rendered HTML file. */
|
|
134
|
-
declare function extractDeckSource(html: string): unknown | undefined;
|
|
135
|
-
|
|
136
|
-
export { type Deck as D, type ImageResolver as I, LAYOUTS as L, type RenderOptions as R, type SlideData as S, type ValidationResult as V, DeckError as a, type DeckInput as b, DeckSchema as c, type LayoutDef as d, type LayoutIssue as e, type LayoutName as f, type RenderResult as g, type SlideInput as h, SlideSchema as i, collectImageSources as j, extractDeckSource as k, formatIssues as l, formatPath as m, getLayout as n, renderDeck as r, validateDeck as v };
|