@classic-homes/slides 0.2.0 → 0.2.1
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 +4 -2
- package/dist/{chunk-TXNQKBWJ.js → chunk-33EPZMT6.js} +2 -2
- package/dist/{chunk-TM3TNVHB.js → chunk-7FROOJCY.js} +260 -96
- package/dist/chunk-7FROOJCY.js.map +1 -0
- package/dist/{chunk-CKVKX2ZD.js → chunk-MYY5GZC2.js} +2 -2
- package/dist/cli.js +15 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +14 -2
- package/dist/index.js +13 -124
- package/dist/index.js.map +1 -1
- package/dist/{mcp-5R6YD3QW.js → mcp-DGMQTIQI.js} +4 -4
- package/dist/node.d.ts +2 -2
- package/dist/node.js +2 -2
- package/dist/{render-CZ4g2fa9.d.ts → render-DTz7tLKM.d.ts} +14 -1
- package/package.json +11 -3
- package/dist/chunk-TM3TNVHB.js.map +0 -1
- /package/dist/{chunk-TXNQKBWJ.js.map → chunk-33EPZMT6.js.map} +0 -0
- /package/dist/{chunk-CKVKX2ZD.js.map → chunk-MYY5GZC2.js.map} +0 -0
- /package/dist/{mcp-5R6YD3QW.js.map → mcp-DGMQTIQI.js.map} +0 -0
package/README.md
CHANGED
|
@@ -91,10 +91,12 @@ flags errors and crowded slides.
|
|
|
91
91
|
## With an AI agent (MCP)
|
|
92
92
|
|
|
93
93
|
The package ships an MCP server that edits deck files slide by slide and
|
|
94
|
-
validates before every save, so an agent cannot leave a deck broken.
|
|
94
|
+
validates before every save, so an agent cannot leave a deck broken. It needs
|
|
95
|
+
`@modelcontextprotocol/sdk` (an optional peer, so apps that only render decks
|
|
96
|
+
don't install it).
|
|
95
97
|
|
|
96
98
|
```bash
|
|
97
|
-
claude mcp add classic-slides -- npx -y @classic-homes/slides mcp --root ./decks
|
|
99
|
+
claude mcp add classic-slides -- npx -y -p @classic-homes/slides -p @modelcontextprotocol/sdk classic-slides mcp --root ./decks
|
|
98
100
|
```
|
|
99
101
|
|
|
100
102
|
Then ask: _"Build a 10-slide deck in closing-day.yaml for first-time buyers
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
LAYOUTS,
|
|
4
4
|
baseSlide,
|
|
5
5
|
getLayout
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7FROOJCY.js";
|
|
7
7
|
|
|
8
8
|
// src/catalog.ts
|
|
9
9
|
import { z } from "zod";
|
|
@@ -66,4 +66,4 @@ export {
|
|
|
66
66
|
deckJsonSchema,
|
|
67
67
|
AUTHORING_GUIDE
|
|
68
68
|
};
|
|
69
|
-
//# sourceMappingURL=chunk-
|
|
69
|
+
//# sourceMappingURL=chunk-33EPZMT6.js.map
|
|
@@ -881,102 +881,158 @@ function getLayout(name) {
|
|
|
881
881
|
return byName.get(name);
|
|
882
882
|
}
|
|
883
883
|
|
|
884
|
-
// src/
|
|
884
|
+
// src/editor.ts
|
|
885
885
|
import { z as z4 } from "zod";
|
|
886
|
-
var
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
886
|
+
var MULTILINE = /* @__PURE__ */ new Set(["lead", "body", "text", "quote", "footnote", "sub", "notes", "caption"]);
|
|
887
|
+
var LABELS = {
|
|
888
|
+
eyebrowSub: "Eyebrow subtitle",
|
|
889
|
+
showJourney: "Show journey strip",
|
|
890
|
+
stepDone: "Step completed",
|
|
891
|
+
mediaSide: "Photo side",
|
|
892
|
+
imageAspect: "Photo shape",
|
|
893
|
+
numberFrom: "First badge number",
|
|
894
|
+
url: "URL",
|
|
895
|
+
id: "Slide id"
|
|
896
|
+
};
|
|
897
|
+
function labelFor(key) {
|
|
898
|
+
if (LABELS[key]) return LABELS[key];
|
|
899
|
+
const words = key.replace(/([A-Z])/g, " $1").toLowerCase();
|
|
900
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
901
|
+
}
|
|
902
|
+
function unwrap(schema) {
|
|
903
|
+
let s = schema;
|
|
904
|
+
let required = true;
|
|
905
|
+
let dflt;
|
|
906
|
+
let description = schema.description;
|
|
907
|
+
for (; ; ) {
|
|
908
|
+
description ??= s.description;
|
|
909
|
+
if (s instanceof z4.ZodOptional || s instanceof z4.ZodNullable) {
|
|
910
|
+
required = false;
|
|
911
|
+
s = s.unwrap();
|
|
912
|
+
} else if (s instanceof z4.ZodDefault) {
|
|
913
|
+
required = false;
|
|
914
|
+
dflt = s._def.defaultValue();
|
|
915
|
+
s = s._def.innerType;
|
|
916
|
+
} else break;
|
|
912
917
|
}
|
|
913
|
-
return {
|
|
918
|
+
return { inner: s, required, default: dflt, description };
|
|
914
919
|
}
|
|
915
|
-
function
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
920
|
+
function isText(s) {
|
|
921
|
+
return s === Text || s instanceof z4.ZodString && s.description === Text.description;
|
|
922
|
+
}
|
|
923
|
+
function describeField(key, schema) {
|
|
924
|
+
const { inner, required, default: dflt, description } = unwrap(schema);
|
|
925
|
+
const base = {
|
|
926
|
+
key,
|
|
927
|
+
label: labelFor(key),
|
|
928
|
+
required,
|
|
929
|
+
...description ? { description } : {},
|
|
930
|
+
...dflt !== void 0 ? { default: dflt } : {},
|
|
931
|
+
...MULTILINE.has(key) ? { multiline: true } : {}
|
|
932
|
+
};
|
|
933
|
+
if (inner === Image) return { ...base, kind: "image" };
|
|
934
|
+
if (inner === Item) return { ...base, kind: "item" };
|
|
935
|
+
if (isText(inner)) return { ...base, kind: "inline" };
|
|
936
|
+
if (inner instanceof z4.ZodString) return { ...base, kind: "string" };
|
|
937
|
+
if (inner instanceof z4.ZodBoolean) return { ...base, kind: "boolean" };
|
|
938
|
+
if (inner instanceof z4.ZodEnum) return { ...base, kind: "enum", options: [...inner.options] };
|
|
939
|
+
if (inner instanceof z4.ZodLiteral) return { ...base, kind: "enum", options: [inner.value] };
|
|
940
|
+
if (inner instanceof z4.ZodNumber) {
|
|
941
|
+
return {
|
|
942
|
+
...base,
|
|
943
|
+
kind: "number",
|
|
944
|
+
integer: inner.isInt,
|
|
945
|
+
...inner.minValue !== null ? { min: inner.minValue } : {},
|
|
946
|
+
...inner.maxValue !== null ? { max: inner.maxValue } : {}
|
|
947
|
+
};
|
|
919
948
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
if (slide.id) {
|
|
930
|
-
if (seen.has(slide.id))
|
|
931
|
-
issues.push({
|
|
932
|
-
level: "error",
|
|
933
|
-
path: ["slides", i, "id"],
|
|
934
|
-
message: `Duplicate slide id "${slide.id}".`
|
|
935
|
-
});
|
|
936
|
-
seen.add(slide.id);
|
|
937
|
-
}
|
|
938
|
-
if ((slide.step || slide.showJourney || slide.layout === "journey") && !steps) {
|
|
939
|
-
issues.push({
|
|
940
|
-
level: "error",
|
|
941
|
-
path: ["slides", i, slide.step ? "step" : "layout"],
|
|
942
|
-
message: "This slide uses the journey, but the deck has no journey.steps defined."
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
if (slide.step && steps && slide.step > steps) {
|
|
946
|
-
issues.push({
|
|
947
|
-
level: "error",
|
|
948
|
-
path: ["slides", i, "step"],
|
|
949
|
-
message: `Step ${slide.step} is past the last journey step (${steps}).`
|
|
950
|
-
});
|
|
949
|
+
if (inner instanceof z4.ZodUnion) {
|
|
950
|
+
const opts = inner.options;
|
|
951
|
+
if (opts.every((o) => o instanceof z4.ZodLiteral)) {
|
|
952
|
+
return {
|
|
953
|
+
...base,
|
|
954
|
+
kind: "enum",
|
|
955
|
+
options: opts.map((o) => o.value)
|
|
956
|
+
};
|
|
951
957
|
}
|
|
952
|
-
|
|
953
|
-
if (deck.slides[0]?.layout !== "title") {
|
|
954
|
-
issues.push({
|
|
955
|
-
level: "warning",
|
|
956
|
-
path: ["slides", 0, "layout"],
|
|
957
|
-
message: 'Decks usually open with a "title" slide.'
|
|
958
|
-
});
|
|
958
|
+
return { ...base, kind: "string" };
|
|
959
959
|
}
|
|
960
|
-
|
|
960
|
+
if (inner instanceof z4.ZodArray) {
|
|
961
|
+
const el = inner.element;
|
|
962
|
+
return {
|
|
963
|
+
...base,
|
|
964
|
+
kind: "list",
|
|
965
|
+
of: { ...describeField("", el), label: labelFor(key.replace(/s$/, "")) },
|
|
966
|
+
...inner._def.minLength ? { min: inner._def.minLength.value } : {},
|
|
967
|
+
...inner._def.maxLength ? { max: inner._def.maxLength.value } : {}
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
if (inner instanceof z4.ZodObject) {
|
|
971
|
+
return {
|
|
972
|
+
...base,
|
|
973
|
+
kind: "group",
|
|
974
|
+
fields: Object.entries(inner.shape).map(
|
|
975
|
+
([k, v]) => describeField(k, v)
|
|
976
|
+
)
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
return { ...base, kind: "string" };
|
|
961
980
|
}
|
|
962
|
-
function
|
|
963
|
-
|
|
964
|
-
return path.map(
|
|
965
|
-
(p, i) => typeof p === "number" ? path[i - 1] === "slides" ? `slide ${p + 1}` : String(p + 1) : p
|
|
966
|
-
).filter((p) => p !== "slides").join(" \u203A ");
|
|
981
|
+
function commonSlideFields() {
|
|
982
|
+
return Object.entries(baseSlide).map(([k, v]) => describeField(k, v));
|
|
967
983
|
}
|
|
968
|
-
function
|
|
969
|
-
|
|
984
|
+
function layoutEditorInfo(name) {
|
|
985
|
+
const layout = getLayout(name);
|
|
986
|
+
if (!layout) return void 0;
|
|
987
|
+
return {
|
|
988
|
+
name: layout.name,
|
|
989
|
+
description: layout.description,
|
|
990
|
+
whenToUse: layout.whenToUse,
|
|
991
|
+
defaults: layout.defaults ?? {},
|
|
992
|
+
fields: Object.entries(layout.shape).map(
|
|
993
|
+
([k, v]) => describeField(k, v)
|
|
994
|
+
),
|
|
995
|
+
example: layout.example
|
|
996
|
+
};
|
|
970
997
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
998
|
+
function allLayoutEditorInfo() {
|
|
999
|
+
return LAYOUTS.map((l) => layoutEditorInfo(l.name));
|
|
1000
|
+
}
|
|
1001
|
+
var PLACEHOLDER_IMAGE = "data:image/svg+xml;base64," + btoa(
|
|
1002
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 1600 1000"><rect width="1600" height="1000" fill="#ecebe6"/><rect x="24" y="24" width="1552" height="952" fill="none" stroke="#b9bcb4" stroke-width="6" stroke-dasharray="28 20"/><text x="800" y="520" text-anchor="middle" font-family="Figtree,Arial,sans-serif" font-size="64" fill="#7a7a7a">Add a photo</text></svg>'
|
|
1003
|
+
);
|
|
1004
|
+
function isPlaceholderImage(src) {
|
|
1005
|
+
return src === PLACEHOLDER_IMAGE;
|
|
1006
|
+
}
|
|
1007
|
+
function blankSlide(name) {
|
|
1008
|
+
const layout = getLayout(name);
|
|
1009
|
+
if (!layout) return void 0;
|
|
1010
|
+
return JSON.parse(
|
|
1011
|
+
JSON.stringify(layout.example),
|
|
1012
|
+
(key, value) => key === "src" && typeof value === "string" && !/^(https?:|data:)/.test(value) ? PLACEHOLDER_IMAGE : value
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// src/schema/deck.ts
|
|
1017
|
+
import { z as z5 } from "zod";
|
|
1018
|
+
var slideSchemas = LAYOUTS.map(
|
|
1019
|
+
(layout) => z5.object({ layout: z5.literal(layout.name), ...baseSlide, ...layout.shape }).strict().describe(`${layout.description} Use for: ${layout.whenToUse}`)
|
|
1020
|
+
);
|
|
1021
|
+
var SlideSchema = z5.discriminatedUnion("layout", slideSchemas);
|
|
1022
|
+
var DeckSchema = z5.object({
|
|
1023
|
+
title: z5.string().min(1).describe("Deck title (browser tab, file name, gallery)."),
|
|
1024
|
+
description: z5.string().optional().describe("One sentence: who the deck is for and what it covers."),
|
|
1025
|
+
author: z5.string().optional(),
|
|
1026
|
+
date: z5.string().optional(),
|
|
1027
|
+
lang: z5.string().default("en"),
|
|
1028
|
+
journey: z5.object({
|
|
1029
|
+
steps: z5.array(Text).min(2).max(10).describe("Short names of each step, in order."),
|
|
1030
|
+
label: z5.string().default("STEP").describe("Word on the vertical step rail.")
|
|
1031
|
+
}).optional().describe(
|
|
1032
|
+
'Optional numbered journey (agenda). Enables the journey layout, step rails and "you are here" strips.'
|
|
1033
|
+
),
|
|
1034
|
+
slides: z5.array(SlideSchema).min(1)
|
|
1035
|
+
}).strict();
|
|
980
1036
|
|
|
981
1037
|
// src/render.ts
|
|
982
1038
|
import QRCode from "qrcode";
|
|
@@ -1015,7 +1071,11 @@ var RUNTIME_JS = String.raw`
|
|
|
1015
1071
|
notesBody.innerHTML = n.html || '<p><i>No notes for this slide.</i></p>';
|
|
1016
1072
|
notesTime.textContent = n.time || '';
|
|
1017
1073
|
}
|
|
1018
|
-
|
|
1074
|
+
// Sandboxed or srcdoc frames may refuse history access; the deep link is optional.
|
|
1075
|
+
try {
|
|
1076
|
+
if (location.hash !== '#slide-' + (i + 1)) history.replaceState(null, '', '#slide-' + (i + 1));
|
|
1077
|
+
} catch (_) {}
|
|
1078
|
+
if (window.parent !== window) window.parent.postMessage({ type: 'classic-slides:slide', index: i, count: slides.length }, '*');
|
|
1019
1079
|
}
|
|
1020
1080
|
|
|
1021
1081
|
// Current slide comes from the scroll position, the single source of truth.
|
|
@@ -1038,7 +1098,20 @@ var RUNTIME_JS = String.raw`
|
|
|
1038
1098
|
});
|
|
1039
1099
|
}, { passive: true });
|
|
1040
1100
|
|
|
1041
|
-
|
|
1101
|
+
// Scroll the deck element itself; scrolling the slide into view would also move an embedding page.
|
|
1102
|
+
function go(n, instant) {
|
|
1103
|
+
const t = clamp(n);
|
|
1104
|
+
deck.scrollTo({ top: t * deck.clientHeight, behavior: instant ? 'auto' : 'smooth' });
|
|
1105
|
+
setActive(t);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// Embedders (editors, previews) can drive the deck: postMessage({ type: 'classic-slides:go', index }).
|
|
1109
|
+
window.addEventListener('message', (e) => {
|
|
1110
|
+
const d = e.data;
|
|
1111
|
+
if (!d || typeof d !== 'object') return;
|
|
1112
|
+
if (d.type === 'classic-slides:go' && Number.isInteger(d.index)) go(d.index, true);
|
|
1113
|
+
else if (d.type === 'classic-slides:notes') { if (notes.classList.contains('open') !== !!d.open) toggleNotes(); }
|
|
1114
|
+
});
|
|
1042
1115
|
|
|
1043
1116
|
document.addEventListener('keydown', (e) => {
|
|
1044
1117
|
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
@@ -1058,7 +1131,8 @@ var RUNTIME_JS = String.raw`
|
|
|
1058
1131
|
}
|
|
1059
1132
|
|
|
1060
1133
|
const m = /^#slide-(\d+)$/.exec(location.hash);
|
|
1061
|
-
|
|
1134
|
+
const initial = m ? Number(m[1]) - 1 : Number(document.body.dataset.initialSlide || 0);
|
|
1135
|
+
if (initial > 0) requestAnimationFrame(() => go(initial, true));
|
|
1062
1136
|
else setActive(0);
|
|
1063
1137
|
})();
|
|
1064
1138
|
`;
|
|
@@ -1374,6 +1448,7 @@ img.natural,.media img.natural,.photo-grid img.natural{width:auto;max-width:min(
|
|
|
1374
1448
|
`;
|
|
1375
1449
|
|
|
1376
1450
|
// src/render.ts
|
|
1451
|
+
var PREVIEW_SIZE = { width: 1280, height: 720 };
|
|
1377
1452
|
var passThrough = (src) => {
|
|
1378
1453
|
if (/^(data:|https?:)/.test(src)) return src;
|
|
1379
1454
|
throw new Error(
|
|
@@ -1422,12 +1497,14 @@ async function renderDeck(input, options = {}) {
|
|
|
1422
1497
|
};
|
|
1423
1498
|
const sections = [];
|
|
1424
1499
|
const notes = [];
|
|
1500
|
+
const slideMap = [];
|
|
1425
1501
|
deck.slides.forEach((slide, i) => {
|
|
1426
1502
|
const layout = getLayout(slide.layout);
|
|
1427
1503
|
const rendered = layout.render(slide, ctx);
|
|
1428
1504
|
const list = Array.isArray(rendered) ? rendered : [rendered];
|
|
1429
1505
|
const track = slide.track ?? layout.defaults?.track ?? "value";
|
|
1430
1506
|
const bg = slide.background ?? layout.defaults?.background ?? "paper";
|
|
1507
|
+
slideMap.push(list.map((_, j) => sections.length + j));
|
|
1431
1508
|
list.forEach((r, j) => {
|
|
1432
1509
|
const classes = ["slide", `layout-${layout.name}`, ...r.classes ?? []];
|
|
1433
1510
|
if (bg !== "paper") classes.push("solid", `bg-${bg}`);
|
|
@@ -1459,7 +1536,7 @@ ${deck.description ? `<meta name="description" content="${escapeAttr(deck.descri
|
|
|
1459
1536
|
<style id="brand-fonts">${fontsCss()}</style>
|
|
1460
1537
|
<style>${tokensCss()}${DECK_CSS}</style>
|
|
1461
1538
|
</head>
|
|
1462
|
-
<body>
|
|
1539
|
+
<body${options.initialSlide ? ` data-initial-slide="${Math.max(0, Math.floor(options.initialSlide))}"` : ""}>
|
|
1463
1540
|
<div class="rail" id="rail"></div>
|
|
1464
1541
|
<main class="deck" id="deck">
|
|
1465
1542
|
${sections.join("\n")}
|
|
@@ -1473,13 +1550,96 @@ ${source}<script>${RUNTIME_JS}</script>
|
|
|
1473
1550
|
</body>
|
|
1474
1551
|
</html>
|
|
1475
1552
|
`;
|
|
1476
|
-
return { html, deck, slideCount: sections.length, warnings: result.issues };
|
|
1553
|
+
return { html, deck, slideCount: sections.length, slideMap, warnings: result.issues };
|
|
1477
1554
|
}
|
|
1478
1555
|
function extractDeckSource(html) {
|
|
1479
1556
|
const m = /<script type="application\/json" id="deck-source">([\s\S]*?)<\/script>/.exec(html);
|
|
1480
1557
|
return m ? JSON.parse(m[1]) : void 0;
|
|
1481
1558
|
}
|
|
1482
1559
|
|
|
1560
|
+
// src/validate.ts
|
|
1561
|
+
function fromZod(issue) {
|
|
1562
|
+
let message = issue.message;
|
|
1563
|
+
if (issue.code === "invalid_union_discriminator") {
|
|
1564
|
+
message = `Unknown layout. Use one of: ${issue.options.join(", ")}.`;
|
|
1565
|
+
} else if (issue.code === "unrecognized_keys") {
|
|
1566
|
+
message = `Unknown field(s) ${issue.keys.map((k) => `"${k}"`).join(", ")} for this layout.`;
|
|
1567
|
+
}
|
|
1568
|
+
return { level: "error", path: issue.path, message };
|
|
1569
|
+
}
|
|
1570
|
+
function validateDeck(input) {
|
|
1571
|
+
const parsed = DeckSchema.safeParse(input);
|
|
1572
|
+
if (!parsed.success) {
|
|
1573
|
+
return { ok: false, issues: parsed.error.issues.map(fromZod) };
|
|
1574
|
+
}
|
|
1575
|
+
const deck = parsed.data;
|
|
1576
|
+
const issues = [];
|
|
1577
|
+
const steps = deck.journey?.steps.length ?? 0;
|
|
1578
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1579
|
+
deck.slides.forEach((slide, i) => {
|
|
1580
|
+
const layout = getLayout(slide.layout);
|
|
1581
|
+
for (const issue of layout.lint?.(slide) ?? []) {
|
|
1582
|
+
issues.push({ ...issue, path: ["slides", i, ...issue.path] });
|
|
1583
|
+
}
|
|
1584
|
+
if (collectImageSources(slide).has(PLACEHOLDER_IMAGE)) {
|
|
1585
|
+
issues.push({
|
|
1586
|
+
level: "warning",
|
|
1587
|
+
path: ["slides", i],
|
|
1588
|
+
message: "Replace the placeholder photo before presenting."
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
if (slide.id) {
|
|
1592
|
+
if (seen.has(slide.id))
|
|
1593
|
+
issues.push({
|
|
1594
|
+
level: "error",
|
|
1595
|
+
path: ["slides", i, "id"],
|
|
1596
|
+
message: `Duplicate slide id "${slide.id}".`
|
|
1597
|
+
});
|
|
1598
|
+
seen.add(slide.id);
|
|
1599
|
+
}
|
|
1600
|
+
if ((slide.step || slide.showJourney || slide.layout === "journey") && !steps) {
|
|
1601
|
+
issues.push({
|
|
1602
|
+
level: "error",
|
|
1603
|
+
path: ["slides", i, slide.step ? "step" : "layout"],
|
|
1604
|
+
message: "This slide uses the journey, but the deck has no journey.steps defined."
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
if (slide.step && steps && slide.step > steps) {
|
|
1608
|
+
issues.push({
|
|
1609
|
+
level: "error",
|
|
1610
|
+
path: ["slides", i, "step"],
|
|
1611
|
+
message: `Step ${slide.step} is past the last journey step (${steps}).`
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
if (deck.slides[0]?.layout !== "title") {
|
|
1616
|
+
issues.push({
|
|
1617
|
+
level: "warning",
|
|
1618
|
+
path: ["slides", 0, "layout"],
|
|
1619
|
+
message: 'Decks usually open with a "title" slide.'
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
return { ok: !issues.some((i) => i.level === "error"), deck, issues };
|
|
1623
|
+
}
|
|
1624
|
+
function formatPath(path) {
|
|
1625
|
+
if (!path.length) return "deck";
|
|
1626
|
+
return path.map(
|
|
1627
|
+
(p, i) => typeof p === "number" ? path[i - 1] === "slides" ? `slide ${p + 1}` : String(p + 1) : p
|
|
1628
|
+
).filter((p) => p !== "slides").join(" \u203A ");
|
|
1629
|
+
}
|
|
1630
|
+
function formatIssues(issues) {
|
|
1631
|
+
return issues.map((i) => `${i.level === "error" ? "\u2716" : "\u26A0"} ${formatPath(i.path)}: ${i.message}`).join("\n");
|
|
1632
|
+
}
|
|
1633
|
+
var DeckError = class extends Error {
|
|
1634
|
+
constructor(issues) {
|
|
1635
|
+
super(`Deck is not valid:
|
|
1636
|
+
${formatIssues(issues.filter((i) => i.level === "error"))}`);
|
|
1637
|
+
this.issues = issues;
|
|
1638
|
+
this.name = "DeckError";
|
|
1639
|
+
}
|
|
1640
|
+
issues;
|
|
1641
|
+
};
|
|
1642
|
+
|
|
1483
1643
|
// src/parse.ts
|
|
1484
1644
|
import YAML from "yaml";
|
|
1485
1645
|
function parseDeckSource(text) {
|
|
@@ -1497,24 +1657,28 @@ export {
|
|
|
1497
1657
|
escapeHtml,
|
|
1498
1658
|
inline,
|
|
1499
1659
|
prose,
|
|
1500
|
-
Text,
|
|
1501
|
-
Image,
|
|
1502
|
-
Item,
|
|
1503
1660
|
baseSlide,
|
|
1504
1661
|
PALETTE,
|
|
1505
1662
|
LOGO_SVG,
|
|
1506
1663
|
LAYOUTS,
|
|
1507
1664
|
getLayout,
|
|
1665
|
+
commonSlideFields,
|
|
1666
|
+
layoutEditorInfo,
|
|
1667
|
+
allLayoutEditorInfo,
|
|
1668
|
+
PLACEHOLDER_IMAGE,
|
|
1669
|
+
isPlaceholderImage,
|
|
1670
|
+
blankSlide,
|
|
1508
1671
|
SlideSchema,
|
|
1509
1672
|
DeckSchema,
|
|
1510
1673
|
validateDeck,
|
|
1511
1674
|
formatPath,
|
|
1512
1675
|
formatIssues,
|
|
1513
1676
|
DeckError,
|
|
1677
|
+
PREVIEW_SIZE,
|
|
1514
1678
|
collectImageSources,
|
|
1515
1679
|
renderDeck,
|
|
1516
1680
|
extractDeckSource,
|
|
1517
1681
|
parseDeckSource,
|
|
1518
1682
|
stringifyDeck
|
|
1519
1683
|
};
|
|
1520
|
-
//# sourceMappingURL=chunk-
|
|
1684
|
+
//# sourceMappingURL=chunk-7FROOJCY.js.map
|