deckjsx 0.6.0 → 0.7.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 +52 -40
- package/dist/{adapter-C8xw46nz.d.mts → adapter-NxGlM8_c.d.mts} +2 -2
- package/dist/adapter.d.mts +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/{index-C5l8PX5V.d.mts → index-C-LDA3Lj.d.mts} +257 -134
- package/dist/index.d.mts +144 -18
- package/dist/index.mjs +484 -138
- package/dist/inspect.d.mts +2 -2
- package/dist/{jsx-C671yNZa.mjs → jsx-DetoUfLm.mjs} +1 -12
- package/dist/jsx-dev-runtime.d.mts +2 -2
- package/dist/jsx-dev-runtime.mjs +1 -1
- package/dist/{jsx-runtime-DwfBuBkY.d.mts → jsx-runtime-Dz8WBHpq.d.mts} +2 -3
- package/dist/jsx-runtime.d.mts +2 -2
- package/dist/jsx-runtime.mjs +1 -1
- package/dist/{pptx-PzEK54aA.d.mts → pptx-DaSXvESd.d.mts} +1 -1
- package/package.json +1 -1
- package/dist/{adapter-BbtteJ7s.mjs → adapter-rS3mWdi0.mjs} +5 -5
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as diagnostic, c as SemanticGraphDiagnosticError, d as formatDiagnostics, i as createDiagnostics, l as StyleDiagnosticError, n as EMU_PER_INCH, o as CompositionDiagnosticError, r as POINTS_PER_INCH, s as DeckDiagnosticError, t as pptxgenjs, u as formatDiagnostic } from "./adapter-
|
|
2
|
-
import { a as isContentNode, c as Shape, d as
|
|
1
|
+
import { a as diagnostic, c as SemanticGraphDiagnosticError, d as formatDiagnostics, i as createDiagnostics, l as StyleDiagnosticError, n as EMU_PER_INCH, o as CompositionDiagnosticError, r as POINTS_PER_INCH, s as DeckDiagnosticError, t as pptxgenjs, u as formatDiagnostic } from "./adapter-rS3mWdi0.mjs";
|
|
2
|
+
import { a as isContentNode, c as Shape, d as isAuthorNodeValue, f as toAuthorJsxNode, h as isAuthoredTag, i as isAuthorNode, l as Text, m as isAuthorTreeNode, n as createElement, o as isSlideNode, p as createAuthorElement, s as Image, t as Fragment, u as View } from "./jsx-DetoUfLm.mjs";
|
|
3
3
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname } from "node:path";
|
|
5
5
|
//#region src/composition/types.ts
|
|
@@ -20,6 +20,226 @@ function stageSummary(stage, diagnostics, artifact) {
|
|
|
20
20
|
artifact
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
+
const DEFAULT_FONT_SIZE_PT = 16 / 96 * 72;
|
|
24
|
+
const CH_WIDTH_RATIO = .5;
|
|
25
|
+
const DECK_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:in|pt|px|%|em|rem|vh|vw|ch)$/i;
|
|
26
|
+
const DECK_POINT_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:pt|in|px|em|rem|vh|vw|ch)$/i;
|
|
27
|
+
function pointsToEmu(value) {
|
|
28
|
+
return value / 72 * EMU_PER_INCH;
|
|
29
|
+
}
|
|
30
|
+
function parsePercentage$1(value) {
|
|
31
|
+
const trimmed = value.trim();
|
|
32
|
+
if (!trimmed.endsWith("%")) return;
|
|
33
|
+
return Number.parseFloat(trimmed.slice(0, -1));
|
|
34
|
+
}
|
|
35
|
+
function resolvePointUnitBase(context) {
|
|
36
|
+
return context?.fontSizePt ?? DEFAULT_FONT_SIZE_PT;
|
|
37
|
+
}
|
|
38
|
+
function isDeckLengthString(value) {
|
|
39
|
+
return DECK_LENGTH_PATTERN.test(value.trim());
|
|
40
|
+
}
|
|
41
|
+
function isDeckPointLengthString(value) {
|
|
42
|
+
return DECK_POINT_LENGTH_PATTERN.test(value.trim());
|
|
43
|
+
}
|
|
44
|
+
function parseLengthToken(value, baseEmu, fallback = 0, context) {
|
|
45
|
+
const trimmed = value.trim();
|
|
46
|
+
if (trimmed === "0") return 0;
|
|
47
|
+
if (!isDeckLengthString(trimmed)) throw new Error(`Unsupported length value: ${value}`);
|
|
48
|
+
return parseLength(trimmed, baseEmu, fallback, context);
|
|
49
|
+
}
|
|
50
|
+
function parsePointToken(value, fallback = 0, context) {
|
|
51
|
+
const trimmed = value.trim();
|
|
52
|
+
if (trimmed === "0") return 0;
|
|
53
|
+
if (!isDeckPointLengthString(trimmed)) throw new Error(`Unsupported point value: ${value}`);
|
|
54
|
+
return parsePointValue(trimmed, fallback, context);
|
|
55
|
+
}
|
|
56
|
+
function parsePointValue(value, fallback = 0, context) {
|
|
57
|
+
if (value === void 0) return fallback;
|
|
58
|
+
if (typeof value === "number") return value;
|
|
59
|
+
if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2));
|
|
60
|
+
if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * 72;
|
|
61
|
+
if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * 72;
|
|
62
|
+
if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
|
|
63
|
+
if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context);
|
|
64
|
+
if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
|
|
65
|
+
if (value.endsWith("vw")) {
|
|
66
|
+
const viewportWidthEmu = context?.viewportWidthEmu;
|
|
67
|
+
if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport point value without viewport context: ${value}`);
|
|
68
|
+
return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
69
|
+
}
|
|
70
|
+
if (value.endsWith("vh")) {
|
|
71
|
+
const viewportHeightEmu = context?.viewportHeightEmu;
|
|
72
|
+
if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport point value without viewport context: ${value}`);
|
|
73
|
+
return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Unsupported point value: ${value}`);
|
|
76
|
+
}
|
|
77
|
+
function parseStrokeWidth(value, fallback = 0, context) {
|
|
78
|
+
if (value === void 0) return fallback;
|
|
79
|
+
if (typeof value === "number") return value;
|
|
80
|
+
if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2));
|
|
81
|
+
if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * 72;
|
|
82
|
+
if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * 72;
|
|
83
|
+
if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
|
|
84
|
+
if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context);
|
|
85
|
+
if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
|
|
86
|
+
if (value.endsWith("vw")) {
|
|
87
|
+
const viewportWidthEmu = context?.viewportWidthEmu;
|
|
88
|
+
if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport stroke width without viewport context: ${value}`);
|
|
89
|
+
return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
90
|
+
}
|
|
91
|
+
if (value.endsWith("vh")) {
|
|
92
|
+
const viewportHeightEmu = context?.viewportHeightEmu;
|
|
93
|
+
if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport stroke width without viewport context: ${value}`);
|
|
94
|
+
return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
95
|
+
}
|
|
96
|
+
throw new Error(`Unsupported stroke width: ${value}`);
|
|
97
|
+
}
|
|
98
|
+
function parseLength(value, baseEmu, fallback = 0, context) {
|
|
99
|
+
if (value === void 0) return fallback;
|
|
100
|
+
if (typeof value === "number") return value * EMU_PER_INCH;
|
|
101
|
+
if (value.endsWith("%")) return baseEmu * Number.parseFloat(value.slice(0, -1)) / 100;
|
|
102
|
+
if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * EMU_PER_INCH;
|
|
103
|
+
if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2)) / 72 * EMU_PER_INCH;
|
|
104
|
+
if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * EMU_PER_INCH;
|
|
105
|
+
if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT * EMU_PER_INCH / 72;
|
|
106
|
+
if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * EMU_PER_INCH / 72;
|
|
107
|
+
if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO * EMU_PER_INCH / 72;
|
|
108
|
+
if (value.endsWith("vw")) {
|
|
109
|
+
const viewportWidthEmu = context?.viewportWidthEmu;
|
|
110
|
+
if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport length without viewport context: ${value}`);
|
|
111
|
+
return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100;
|
|
112
|
+
}
|
|
113
|
+
if (value.endsWith("vh")) {
|
|
114
|
+
const viewportHeightEmu = context?.viewportHeightEmu;
|
|
115
|
+
if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport length without viewport context: ${value}`);
|
|
116
|
+
return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100;
|
|
117
|
+
}
|
|
118
|
+
throw new Error(`Unsupported length value: ${value}`);
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/templates.ts
|
|
122
|
+
const TEMPLATE_AREA_REF = Symbol("deckjsx.templateAreaRef");
|
|
123
|
+
/**
|
|
124
|
+
* Create the runtime template handle passed to a templated slide factory.
|
|
125
|
+
*
|
|
126
|
+
* @param templates - Deck-local Slide Template set.
|
|
127
|
+
* @param name - Selected Slide Template name.
|
|
128
|
+
* @returns A handle exposing `$name` and typed Template Area References for the selected template.
|
|
129
|
+
*/
|
|
130
|
+
function createTemplateHandle(templates, name) {
|
|
131
|
+
const template = templates[name];
|
|
132
|
+
const handle = { $name: name };
|
|
133
|
+
if (template && isRecord$2(template.areas)) Object.keys(template.areas).forEach((area) => {
|
|
134
|
+
handle[area] = createTemplateAreaRef(name, area);
|
|
135
|
+
});
|
|
136
|
+
return handle;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Create an internal Template Area Reference object for a template handle property.
|
|
140
|
+
*
|
|
141
|
+
* @param template - Slide Template name that owns the area.
|
|
142
|
+
* @param area - Template Area name within the template.
|
|
143
|
+
* @returns A branded Template Area Reference accepted by the `area` JSX prop.
|
|
144
|
+
*/
|
|
145
|
+
function createTemplateAreaRef(template, area) {
|
|
146
|
+
return {
|
|
147
|
+
type: "deckjsx.templateAreaRef",
|
|
148
|
+
template,
|
|
149
|
+
area,
|
|
150
|
+
[TEMPLATE_AREA_REF]: true
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Return whether a value is a deckjsx-created Template Area Reference.
|
|
155
|
+
*
|
|
156
|
+
* @param value - Unknown runtime value to test.
|
|
157
|
+
* @returns `true` when the value carries deckjsx's Template Area Reference runtime brand.
|
|
158
|
+
*/
|
|
159
|
+
function isTemplateAreaRef(value) {
|
|
160
|
+
return isRecord$2(value) && value.type === "deckjsx.templateAreaRef" && value[TEMPLATE_AREA_REF] === true && typeof value.template === "string" && typeof value.area === "string";
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Extract the serializable template and area names from a Template Area Reference.
|
|
164
|
+
*
|
|
165
|
+
* @param value - Template Area Reference produced by a template handle.
|
|
166
|
+
* @returns The template and area names used by graph construction and diagnostics.
|
|
167
|
+
*/
|
|
168
|
+
function templateRefValue(value) {
|
|
169
|
+
return {
|
|
170
|
+
template: value.template,
|
|
171
|
+
area: value.area
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Validate a Deck-local Slide Template set and return author-facing diagnostics.
|
|
176
|
+
*
|
|
177
|
+
* @param templates - Deck-local Slide Template set to validate.
|
|
178
|
+
* @param path - Diagnostic path prefix used in labels.
|
|
179
|
+
* @returns Diagnostics for malformed templates, areas, frames, or reserved names.
|
|
180
|
+
*/
|
|
181
|
+
function validateSlideTemplates(templates, path = "templates") {
|
|
182
|
+
if (templates === void 0) return [];
|
|
183
|
+
if (!isRecord$2(templates)) return [templateDiagnostic("E_TEMPLATE_SET_INVALID", "invalid slide templates", path)];
|
|
184
|
+
const diagnostics = [];
|
|
185
|
+
Object.entries(templates).forEach(([templateName, template]) => {
|
|
186
|
+
const templatePath = `${path}.${templateName}`;
|
|
187
|
+
if (invalidName(templateName)) diagnostics.push(templateDiagnostic("E_TEMPLATE_RESERVED_NAME", "reserved slide template name", templatePath, `Slide Template name "${templateName}" is invalid.`, ["Template names must not be empty or start with deckjsx-reserved \"$\"."]));
|
|
188
|
+
if (!isRecord$2(template)) {
|
|
189
|
+
diagnostics.push(templateDiagnostic("E_TEMPLATE_INVALID", "invalid slide template", templatePath));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (!isRecord$2(template.areas)) {
|
|
193
|
+
diagnostics.push(templateDiagnostic("E_TEMPLATE_AREAS_INVALID", "invalid template areas", `${templatePath}.areas`));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
Object.entries(template.areas).forEach(([areaName, area]) => {
|
|
197
|
+
const areaPath = `${templatePath}.areas.${areaName}`;
|
|
198
|
+
if (invalidName(areaName)) diagnostics.push(templateDiagnostic("E_TEMPLATE_AREA_RESERVED_NAME", "reserved template area name", areaPath, `Template Area name "${areaName}" is invalid.`, ["Template Area names must not be empty or start with deckjsx-reserved \"$\"."]));
|
|
199
|
+
if (!isRecord$2(area)) {
|
|
200
|
+
diagnostics.push(templateDiagnostic("E_TEMPLATE_AREA_INVALID", "invalid area", areaPath));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
diagnostics.push(...validateFrame(area.frame, `${areaPath}.frame`));
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
return diagnostics;
|
|
207
|
+
}
|
|
208
|
+
function validateFrame(value, path) {
|
|
209
|
+
if (!isRecord$2(value)) return [templateDiagnostic("E_TEMPLATE_AREA_FRAME_INVALID", "invalid area frame", path)];
|
|
210
|
+
const diagnostics = [];
|
|
211
|
+
[
|
|
212
|
+
"x",
|
|
213
|
+
"y",
|
|
214
|
+
"width",
|
|
215
|
+
"height"
|
|
216
|
+
].forEach((key) => {
|
|
217
|
+
if (!validLength(value[key])) diagnostics.push(templateDiagnostic("E_TEMPLATE_AREA_FRAME_INCOMPLETE", "template area frame is incomplete", `${path}.${key}`, `Template Area frame must define a valid ${key} value.`));
|
|
218
|
+
});
|
|
219
|
+
return diagnostics;
|
|
220
|
+
}
|
|
221
|
+
function invalidName(value) {
|
|
222
|
+
return value.trim().length === 0 || value.startsWith("$");
|
|
223
|
+
}
|
|
224
|
+
function validLength(value) {
|
|
225
|
+
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && isDeckLengthString(value);
|
|
226
|
+
}
|
|
227
|
+
function isRecord$2(value) {
|
|
228
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
229
|
+
}
|
|
230
|
+
function templateDiagnostic(code, title, path, message = "Slide Template definitions must be an object keyed by template and area names.", help) {
|
|
231
|
+
return diagnostic({
|
|
232
|
+
severity: "error",
|
|
233
|
+
code,
|
|
234
|
+
title,
|
|
235
|
+
message,
|
|
236
|
+
labels: [{
|
|
237
|
+
path,
|
|
238
|
+
message
|
|
239
|
+
}],
|
|
240
|
+
...help ? { help } : {}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
23
243
|
//#endregion
|
|
24
244
|
//#region src/composition/resolve.ts
|
|
25
245
|
const MAX_COMPOSITION_DEPTH = 64;
|
|
@@ -60,13 +280,10 @@ function validateSourceKey(sourceKey) {
|
|
|
60
280
|
}
|
|
61
281
|
function describeInvalidRoot(value) {
|
|
62
282
|
if (isAuthorNodeValue(value)) return "Slide factory returned an AuthorNode value instead of an Author Tree node.";
|
|
63
|
-
if (isAuthorTreeNode(value)) return "Slide factory returned an
|
|
283
|
+
if (isAuthorTreeNode(value)) return "Slide factory returned an Author Tree node that cannot be used as slide content.";
|
|
64
284
|
if (value === null) return "Slide factory returned null.";
|
|
65
285
|
return `Slide factory returned ${typeof value}.`;
|
|
66
286
|
}
|
|
67
|
-
function isSlideRoot(value) {
|
|
68
|
-
return value.kind === "element" && value.source.kind === "component" && value.source.component === "Slide";
|
|
69
|
-
}
|
|
70
287
|
function isPromiseLike(value) {
|
|
71
288
|
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
72
289
|
}
|
|
@@ -158,6 +375,7 @@ function resolveSource(source, context) {
|
|
|
158
375
|
let slideCount = 0;
|
|
159
376
|
const sourceKeys = /* @__PURE__ */ new Set();
|
|
160
377
|
const slotOrigins = collectSourceSlots(effectiveContext, context);
|
|
378
|
+
validateSlideTemplates(sourceState.templates, `${context.sourcePath} > templates`).forEach((item) => addDiagnostic$1(context, item));
|
|
161
379
|
const nextContextBase = {
|
|
162
380
|
diagnostics: context.diagnostics,
|
|
163
381
|
stack: [...context.stack, sourceState.cycleId],
|
|
@@ -168,6 +386,7 @@ function resolveSource(source, context) {
|
|
|
168
386
|
entries.push({
|
|
169
387
|
kind: "slide",
|
|
170
388
|
factory: entry.factory,
|
|
389
|
+
...entry.options ? { options: entry.options } : {},
|
|
171
390
|
path: `${context.sourcePath} > slideFactory[${index}]`
|
|
172
391
|
});
|
|
173
392
|
slideCount += 1;
|
|
@@ -219,6 +438,7 @@ function resolveSource(source, context) {
|
|
|
219
438
|
sourceIdentityMaterial: context.sourceIdentityMaterial,
|
|
220
439
|
stylesheets: sourceState.stylesheets,
|
|
221
440
|
...activeTheme ? { theme: activeTheme } : {},
|
|
441
|
+
...sourceState.templates ? { templates: sourceState.templates } : {},
|
|
222
442
|
context: effectiveContext,
|
|
223
443
|
entries,
|
|
224
444
|
slideCount,
|
|
@@ -245,13 +465,26 @@ function flattenPlan(plan, deckTotalSlides, deckSlideIndex, roots, diagnostics)
|
|
|
245
465
|
context: plan.context.value,
|
|
246
466
|
composition
|
|
247
467
|
} : { composition };
|
|
248
|
-
const
|
|
249
|
-
|
|
468
|
+
const slideTemplate = entry.options?.template;
|
|
469
|
+
const factoryInput = typeof slideTemplate === "string" && plan.templates ? {
|
|
470
|
+
...input,
|
|
471
|
+
template: createTemplateHandle(plan.templates, slideTemplate)
|
|
472
|
+
} : input;
|
|
473
|
+
const content = entry.factory(factoryInput);
|
|
474
|
+
const root = content === null || content === void 0 || typeof content === "boolean" || isAuthorTreeNode(content) || Array.isArray(content) || typeof content !== "object" ? createAuthorElement({
|
|
475
|
+
source: {
|
|
476
|
+
kind: "component",
|
|
477
|
+
component: "Slide"
|
|
478
|
+
},
|
|
479
|
+
props: entry.options ?? {},
|
|
480
|
+
children: [content]
|
|
481
|
+
}) : content;
|
|
482
|
+
if (!isAuthorTreeNode(root) || root.kind !== "element") diagnostics.push(compositionDiagnostic({
|
|
250
483
|
code: "E_COMPOSITION_INVALID_ROOT",
|
|
251
|
-
title: "slide factory must return
|
|
484
|
+
title: "slide factory must return slide content",
|
|
252
485
|
path: entry.path,
|
|
253
486
|
message: describeInvalidRoot(root),
|
|
254
|
-
help: ["Return
|
|
487
|
+
help: ["Return JSX content from the factory passed to deck.slide()."]
|
|
255
488
|
}));
|
|
256
489
|
else roots.push({
|
|
257
490
|
root,
|
|
@@ -259,6 +492,7 @@ function flattenPlan(plan, deckTotalSlides, deckSlideIndex, roots, diagnostics)
|
|
|
259
492
|
sourceIdentityMaterial: plan.sourceIdentityMaterial,
|
|
260
493
|
stylesheets: plan.stylesheets,
|
|
261
494
|
...plan.theme ? { theme: plan.theme } : {},
|
|
495
|
+
...plan.templates ? { templates: plan.templates } : {},
|
|
262
496
|
path: entry.path,
|
|
263
497
|
composition,
|
|
264
498
|
slotOrigins: plan.slotOrigins
|
|
@@ -299,7 +533,7 @@ function appendIndexValue(index, key, value) {
|
|
|
299
533
|
values.push(value);
|
|
300
534
|
index.set(key, values);
|
|
301
535
|
}
|
|
302
|
-
function sourceKeyFor$
|
|
536
|
+
function sourceKeyFor$3(source) {
|
|
303
537
|
return !source || source.kind === "root" ? ROOT_SOURCE_ARTIFACT_KEY$1 : source.sourceIdentity;
|
|
304
538
|
}
|
|
305
539
|
function projectionShapeDiagnostics(projection) {
|
|
@@ -377,7 +611,7 @@ function safeProjectionParts(projection) {
|
|
|
377
611
|
function partsBySourceKey(parts) {
|
|
378
612
|
const index = /* @__PURE__ */ new Map();
|
|
379
613
|
parts.forEach((part) => {
|
|
380
|
-
appendIndexValue(index, sourceKeyFor$
|
|
614
|
+
appendIndexValue(index, sourceKeyFor$3(part.origin?.source), part.id);
|
|
381
615
|
});
|
|
382
616
|
return index;
|
|
383
617
|
}
|
|
@@ -1307,13 +1541,13 @@ function themeDiagnostics(theme) {
|
|
|
1307
1541
|
}
|
|
1308
1542
|
//#endregion
|
|
1309
1543
|
//#region src/style/resolve.ts
|
|
1310
|
-
function sourceKeyFor$
|
|
1544
|
+
function sourceKeyFor$2(source) {
|
|
1311
1545
|
return !source || source.kind === "root" ? "root" : source.sourceIdentity;
|
|
1312
1546
|
}
|
|
1313
1547
|
function classesBySource(roots) {
|
|
1314
1548
|
const stylesheets = /* @__PURE__ */ new Map();
|
|
1315
1549
|
roots.forEach((root) => {
|
|
1316
|
-
const key = sourceKeyFor$
|
|
1550
|
+
const key = sourceKeyFor$2(root.source);
|
|
1317
1551
|
if (!stylesheets.has(key)) stylesheets.set(key, root.stylesheets);
|
|
1318
1552
|
});
|
|
1319
1553
|
return stylesheets;
|
|
@@ -1322,7 +1556,7 @@ function themesBySource(roots) {
|
|
|
1322
1556
|
const themes = /* @__PURE__ */ new Map();
|
|
1323
1557
|
roots.forEach((root) => {
|
|
1324
1558
|
if (!root.theme) return;
|
|
1325
|
-
themes.set(sourceKeyFor$
|
|
1559
|
+
themes.set(sourceKeyFor$2(root.source), root.theme);
|
|
1326
1560
|
});
|
|
1327
1561
|
return themes;
|
|
1328
1562
|
}
|
|
@@ -1411,7 +1645,7 @@ function resolveStyles(graph, roots) {
|
|
|
1411
1645
|
});
|
|
1412
1646
|
graph.nodes.forEach((node) => {
|
|
1413
1647
|
if (!isStyleCapableNode(node)) return;
|
|
1414
|
-
const sourceKey = sourceKeyFor$
|
|
1648
|
+
const sourceKey = sourceKeyFor$2(node.origin.source);
|
|
1415
1649
|
const entity = node.styleRef ? graph.styles.get(node.styleRef) : void 0;
|
|
1416
1650
|
let registry = registries.get(sourceKey);
|
|
1417
1651
|
if (!registry) {
|
|
@@ -1431,7 +1665,7 @@ const ROOT_SOURCE_ARTIFACT_KEY = "deck:root";
|
|
|
1431
1665
|
function combineDiagnostics$1(...diagnostics) {
|
|
1432
1666
|
return createDiagnostics(diagnostics.flatMap((item) => item.items));
|
|
1433
1667
|
}
|
|
1434
|
-
function sourceKeyFor(source) {
|
|
1668
|
+
function sourceKeyFor$1(source) {
|
|
1435
1669
|
return !source || source.kind === "root" ? ROOT_SOURCE_ARTIFACT_KEY : source.sourceIdentity;
|
|
1436
1670
|
}
|
|
1437
1671
|
var PipelineArtifactCollection = class {
|
|
@@ -1476,7 +1710,7 @@ var PipelineArtifactCollection = class {
|
|
|
1476
1710
|
}
|
|
1477
1711
|
const rootsBySourceKey = /* @__PURE__ */ new Map();
|
|
1478
1712
|
roots.forEach((root) => {
|
|
1479
|
-
const sourceKey = sourceKeyFor(root.source);
|
|
1713
|
+
const sourceKey = sourceKeyFor$1(root.source);
|
|
1480
1714
|
const current = rootsBySourceKey.get(sourceKey);
|
|
1481
1715
|
if (current) {
|
|
1482
1716
|
current.rootCount += 1;
|
|
@@ -1537,13 +1771,13 @@ var PipelineArtifactCollection = class {
|
|
|
1537
1771
|
const sourceByKey = /* @__PURE__ */ new Map();
|
|
1538
1772
|
sourceByKey.set(ROOT_SOURCE_ARTIFACT_KEY, { kind: "root" });
|
|
1539
1773
|
input.roots.forEach((root) => {
|
|
1540
|
-
sourceByKey.set(sourceKeyFor(root.source), root.source);
|
|
1774
|
+
sourceByKey.set(sourceKeyFor$1(root.source), root.source);
|
|
1541
1775
|
});
|
|
1542
1776
|
const nodesBySourceKey = /* @__PURE__ */ new Map();
|
|
1543
1777
|
const stylesBySourceKey = /* @__PURE__ */ new Map();
|
|
1544
1778
|
const assetsBySourceKey = /* @__PURE__ */ new Map();
|
|
1545
1779
|
input.graph.nodes.forEach((node) => {
|
|
1546
|
-
const sourceKey = sourceKeyFor(node.origin.source);
|
|
1780
|
+
const sourceKey = sourceKeyFor$1(node.origin.source);
|
|
1547
1781
|
sourceByKey.set(sourceKey, node.origin.source ?? { kind: "root" });
|
|
1548
1782
|
const nodeIds = nodesBySourceKey.get(sourceKey) ?? [];
|
|
1549
1783
|
nodeIds.push(node.id);
|
|
@@ -1772,9 +2006,12 @@ function classRefsFor(value) {
|
|
|
1772
2006
|
}));
|
|
1773
2007
|
}
|
|
1774
2008
|
function directStyleProps(props) {
|
|
1775
|
-
const { children: _children, className: _className, data: _data, name: _name, shape: _shape, src: _src, style: _style, ...directStyle } = props;
|
|
2009
|
+
const { children: _children, className: _className, data: _data, area: _area, name: _name, shape: _shape, src: _src, style: _style, template: _template, ...directStyle } = props;
|
|
1776
2010
|
return Object.keys(directStyle).length === 0 ? void 0 : directStyle;
|
|
1777
2011
|
}
|
|
2012
|
+
function sourceKeyFor(source) {
|
|
2013
|
+
return !source || source.kind === "root" ? "root" : source.sourceIdentity;
|
|
2014
|
+
}
|
|
1778
2015
|
function mergedAuthoredStyle(props) {
|
|
1779
2016
|
const directStyle = directStyleProps(props);
|
|
1780
2017
|
const inlineStyle = props.style;
|
|
@@ -1840,6 +2077,7 @@ function assetForImage(state, idMaterial, props, path) {
|
|
|
1840
2077
|
}
|
|
1841
2078
|
function semanticBase(state, node, id, kind, path, material, context) {
|
|
1842
2079
|
const styleRef = styleRefFor(state, material, kind, node.props);
|
|
2080
|
+
const templateAreaRef = templateAreaRefFor(state, node.props.area, path, context);
|
|
1843
2081
|
return {
|
|
1844
2082
|
id,
|
|
1845
2083
|
kind,
|
|
@@ -1848,9 +2086,88 @@ function semanticBase(state, node, id, kind, path, material, context) {
|
|
|
1848
2086
|
...node.source.kind === "component" ? { authoredComponent: node.source.component } : {},
|
|
1849
2087
|
...node.key !== void 0 ? { key: node.key } : {},
|
|
1850
2088
|
...nodeRole(node) ? { role: nodeRole(node) } : {},
|
|
1851
|
-
...styleRef ? { styleRef } : {}
|
|
2089
|
+
...styleRef ? { styleRef } : {},
|
|
2090
|
+
...templateAreaRef ? { templateAreaRef } : {}
|
|
1852
2091
|
};
|
|
1853
2092
|
}
|
|
2093
|
+
function templateAreaDiagnostic(input) {
|
|
2094
|
+
return diagnostic({
|
|
2095
|
+
severity: "error",
|
|
2096
|
+
code: input.code,
|
|
2097
|
+
title: input.title,
|
|
2098
|
+
message: input.message,
|
|
2099
|
+
labels: [{
|
|
2100
|
+
path: input.path,
|
|
2101
|
+
message: input.message
|
|
2102
|
+
}],
|
|
2103
|
+
...input.help ? { help: input.help } : {}
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
function templateAreaRefFor(state, value, path, context) {
|
|
2107
|
+
if (value === void 0) return;
|
|
2108
|
+
if (!isTemplateAreaRef(value)) {
|
|
2109
|
+
addDiagnostic(state, templateAreaDiagnostic({
|
|
2110
|
+
code: "E_TEMPLATE_AREA_REF_INVALID",
|
|
2111
|
+
title: "template area reference is invalid",
|
|
2112
|
+
path,
|
|
2113
|
+
message: "The area prop must receive a Template Area Reference from the slide factory.",
|
|
2114
|
+
help: ["Use area={template.areaName} inside deck.slide({ template }, ...)."]
|
|
2115
|
+
}));
|
|
2116
|
+
return;
|
|
2117
|
+
}
|
|
2118
|
+
const ref = templateRefValue(value);
|
|
2119
|
+
if (!context.activeSlideTemplate) {
|
|
2120
|
+
addDiagnostic(state, templateAreaDiagnostic({
|
|
2121
|
+
code: "E_TEMPLATE_AREA_WITHOUT_TEMPLATE",
|
|
2122
|
+
title: "template area used without active template",
|
|
2123
|
+
path,
|
|
2124
|
+
message: `Template area "${ref.area}" was used on a slide without an active Slide Template.`
|
|
2125
|
+
}));
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
if (ref.template !== context.activeSlideTemplate) {
|
|
2129
|
+
addDiagnostic(state, templateAreaDiagnostic({
|
|
2130
|
+
code: "E_TEMPLATE_AREA_REF_MISMATCH",
|
|
2131
|
+
title: "template area belongs to another template",
|
|
2132
|
+
path,
|
|
2133
|
+
message: `Template area "${ref.area}" belongs to Slide Template "${ref.template}", but the active Slide Template is "${context.activeSlideTemplate}".`,
|
|
2134
|
+
help: ["Use the template handle passed to this slide factory."]
|
|
2135
|
+
}));
|
|
2136
|
+
return;
|
|
2137
|
+
}
|
|
2138
|
+
if (!context.directSlideChild) {
|
|
2139
|
+
addDiagnostic(state, templateAreaDiagnostic({
|
|
2140
|
+
code: "E_TEMPLATE_AREA_NESTED",
|
|
2141
|
+
title: "template area is nested",
|
|
2142
|
+
path,
|
|
2143
|
+
message: `Template area "${ref.area}" must be attached to a direct slide child.`,
|
|
2144
|
+
help: ["Place the area prop on a slide direct child, or wrap nested content in a container."]
|
|
2145
|
+
}));
|
|
2146
|
+
return;
|
|
2147
|
+
}
|
|
2148
|
+
if (!(context.activeSlideTemplates?.[ref.template])?.areas?.[ref.area]) {
|
|
2149
|
+
addDiagnostic(state, templateAreaDiagnostic({
|
|
2150
|
+
code: "E_TEMPLATE_AREA_NOT_FOUND",
|
|
2151
|
+
title: "template area was not found",
|
|
2152
|
+
path,
|
|
2153
|
+
message: `Template area "${ref.area}" does not exist in Slide Template "${ref.template}".`
|
|
2154
|
+
}));
|
|
2155
|
+
return;
|
|
2156
|
+
}
|
|
2157
|
+
const existing = context.usedTemplateAreas?.get(ref.area);
|
|
2158
|
+
if (existing) {
|
|
2159
|
+
addDiagnostic(state, templateAreaDiagnostic({
|
|
2160
|
+
code: "E_TEMPLATE_AREA_DUPLICATE",
|
|
2161
|
+
title: "template area is used more than once",
|
|
2162
|
+
path,
|
|
2163
|
+
message: `Template area "${ref.area}" is already used by ${existing}.`,
|
|
2164
|
+
help: ["Wrap multiple elements in a single container that carries the area prop."]
|
|
2165
|
+
}));
|
|
2166
|
+
return;
|
|
2167
|
+
}
|
|
2168
|
+
context.usedTemplateAreas?.set(ref.area, path);
|
|
2169
|
+
return ref;
|
|
2170
|
+
}
|
|
1854
2171
|
function buildTextRunFromLeaf(state, leaf, context, index) {
|
|
1855
2172
|
const text = typeof leaf.value === "string" ? leaf.value : String(leaf.value);
|
|
1856
2173
|
if (text.trim().length === 0) return;
|
|
@@ -1921,7 +2238,8 @@ function buildTextLikeNode(state, node, id, path, material, context) {
|
|
|
1921
2238
|
parentId: id,
|
|
1922
2239
|
parentMaterial: material,
|
|
1923
2240
|
path,
|
|
1924
|
-
inline: true
|
|
2241
|
+
inline: true,
|
|
2242
|
+
directSlideChild: false
|
|
1925
2243
|
}, index);
|
|
1926
2244
|
if (run) inlineChildren.push(run.id);
|
|
1927
2245
|
return;
|
|
@@ -1932,7 +2250,8 @@ function buildTextLikeNode(state, node, id, path, material, context) {
|
|
|
1932
2250
|
parentId: id,
|
|
1933
2251
|
parentMaterial: material,
|
|
1934
2252
|
path,
|
|
1935
|
-
inline: true
|
|
2253
|
+
inline: true,
|
|
2254
|
+
directSlideChild: false
|
|
1936
2255
|
});
|
|
1937
2256
|
const segment = `fragment:${keySegment(child.key, index)}`;
|
|
1938
2257
|
inlineChildren.push(...buildChildren(state, child.children, {
|
|
@@ -1948,7 +2267,8 @@ function buildTextLikeNode(state, node, id, path, material, context) {
|
|
|
1948
2267
|
parentId: id,
|
|
1949
2268
|
parentMaterial: material,
|
|
1950
2269
|
path,
|
|
1951
|
-
inline: true
|
|
2270
|
+
inline: true,
|
|
2271
|
+
directSlideChild: false
|
|
1952
2272
|
}, index);
|
|
1953
2273
|
if (built) inlineChildren.push(built.id);
|
|
1954
2274
|
return;
|
|
@@ -2034,6 +2354,14 @@ function buildNode(state, node, context, index) {
|
|
|
2034
2354
|
kind: "shape"
|
|
2035
2355
|
};
|
|
2036
2356
|
}
|
|
2357
|
+
const slideTemplateName = kind === "slide" && typeof node.props.template === "string" ? node.props.template : void 0;
|
|
2358
|
+
const slideTemplates = kind === "slide" ? state.templates.get(sourceKeyFor(sourceFor(nodeContext))) : void 0;
|
|
2359
|
+
if (kind === "slide" && slideTemplateName && !slideTemplates?.[slideTemplateName]) addDiagnostic(state, templateAreaDiagnostic({
|
|
2360
|
+
code: "E_TEMPLATE_NOT_FOUND",
|
|
2361
|
+
title: "slide template was not found",
|
|
2362
|
+
path,
|
|
2363
|
+
message: `Slide Template "${slideTemplateName}" is not defined for this Deck source.`
|
|
2364
|
+
}));
|
|
2037
2365
|
const childIds = buildChildren(state, node.children, {
|
|
2038
2366
|
parentId: id,
|
|
2039
2367
|
parentMaterial: material,
|
|
@@ -2041,12 +2369,17 @@ function buildNode(state, node, context, index) {
|
|
|
2041
2369
|
inline: false,
|
|
2042
2370
|
source: sourceFor(nodeContext),
|
|
2043
2371
|
slotOrigins: nodeContext.slotOrigins,
|
|
2044
|
-
activeSlot: nodeContext.activeSlot
|
|
2372
|
+
activeSlot: nodeContext.activeSlot,
|
|
2373
|
+
activeSlideTemplate: slideTemplateName ?? nodeContext.activeSlideTemplate,
|
|
2374
|
+
activeSlideTemplates: kind === "slide" ? slideTemplates : nodeContext.activeSlideTemplates,
|
|
2375
|
+
directSlideChild: kind === "slide",
|
|
2376
|
+
usedTemplateAreas: kind === "slide" ? /* @__PURE__ */ new Map() : nodeContext.usedTemplateAreas
|
|
2045
2377
|
});
|
|
2046
2378
|
state.nodes.set(id, {
|
|
2047
2379
|
...semanticBase(state, node, id, kind, path, material, nodeContext),
|
|
2048
2380
|
kind,
|
|
2049
2381
|
...kind === "slide" && typeof node.props.name === "string" ? { name: node.props.name } : {},
|
|
2382
|
+
...kind === "slide" && slideTemplateName ? { templateRef: { name: slideTemplateName } } : {},
|
|
2050
2383
|
children: childIds
|
|
2051
2384
|
});
|
|
2052
2385
|
return {
|
|
@@ -2080,11 +2413,13 @@ function buildSemanticAuthorGraph(roots) {
|
|
|
2080
2413
|
nodes: /* @__PURE__ */ new Map(),
|
|
2081
2414
|
styles: /* @__PURE__ */ new Map(),
|
|
2082
2415
|
assets: /* @__PURE__ */ new Map(),
|
|
2416
|
+
templates: /* @__PURE__ */ new Map(),
|
|
2083
2417
|
diagnostics: []
|
|
2084
2418
|
};
|
|
2085
2419
|
const slideIds = [];
|
|
2086
2420
|
roots.forEach((root, index) => {
|
|
2087
2421
|
const composed = "root" in root ? root : asComposedRoot(root, index);
|
|
2422
|
+
if (composed.templates) state.templates.set(sourceKeyFor(composed.source), composed.templates);
|
|
2088
2423
|
const built = buildNode(state, composed.root, {
|
|
2089
2424
|
parentId: documentId,
|
|
2090
2425
|
parentMaterial: [
|
|
@@ -2095,7 +2430,10 @@ function buildSemanticAuthorGraph(roots) {
|
|
|
2095
2430
|
path: composed.path,
|
|
2096
2431
|
inline: false,
|
|
2097
2432
|
source: composed.source,
|
|
2098
|
-
slotOrigins: composed.slotOrigins
|
|
2433
|
+
slotOrigins: composed.slotOrigins,
|
|
2434
|
+
activeSlideTemplate: void 0,
|
|
2435
|
+
activeSlideTemplates: void 0,
|
|
2436
|
+
directSlideChild: false
|
|
2099
2437
|
}, composed.composition.slideIndex);
|
|
2100
2438
|
if (built) slideIds.push(built.id);
|
|
2101
2439
|
});
|
|
@@ -2117,108 +2455,12 @@ function buildSemanticAuthorGraph(roots) {
|
|
|
2117
2455
|
documentId,
|
|
2118
2456
|
nodes: state.nodes,
|
|
2119
2457
|
styles: state.styles,
|
|
2120
|
-
assets: state.assets
|
|
2458
|
+
assets: state.assets,
|
|
2459
|
+
templates: state.templates
|
|
2121
2460
|
},
|
|
2122
2461
|
diagnostics
|
|
2123
2462
|
};
|
|
2124
2463
|
}
|
|
2125
|
-
const DEFAULT_FONT_SIZE_PT = 16 / 96 * 72;
|
|
2126
|
-
const CH_WIDTH_RATIO = .5;
|
|
2127
|
-
const DECK_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:in|pt|px|%|em|rem|vh|vw|ch)$/i;
|
|
2128
|
-
const DECK_POINT_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:pt|in|px|em|rem|vh|vw|ch)$/i;
|
|
2129
|
-
function pointsToEmu(value) {
|
|
2130
|
-
return value / 72 * EMU_PER_INCH;
|
|
2131
|
-
}
|
|
2132
|
-
function parsePercentage$1(value) {
|
|
2133
|
-
const trimmed = value.trim();
|
|
2134
|
-
if (!trimmed.endsWith("%")) return;
|
|
2135
|
-
return Number.parseFloat(trimmed.slice(0, -1));
|
|
2136
|
-
}
|
|
2137
|
-
function resolvePointUnitBase(context) {
|
|
2138
|
-
return context?.fontSizePt ?? DEFAULT_FONT_SIZE_PT;
|
|
2139
|
-
}
|
|
2140
|
-
function isDeckLengthString(value) {
|
|
2141
|
-
return DECK_LENGTH_PATTERN.test(value.trim());
|
|
2142
|
-
}
|
|
2143
|
-
function isDeckPointLengthString(value) {
|
|
2144
|
-
return DECK_POINT_LENGTH_PATTERN.test(value.trim());
|
|
2145
|
-
}
|
|
2146
|
-
function parseLengthToken(value, baseEmu, fallback = 0, context) {
|
|
2147
|
-
const trimmed = value.trim();
|
|
2148
|
-
if (trimmed === "0") return 0;
|
|
2149
|
-
if (!isDeckLengthString(trimmed)) throw new Error(`Unsupported length value: ${value}`);
|
|
2150
|
-
return parseLength(trimmed, baseEmu, fallback, context);
|
|
2151
|
-
}
|
|
2152
|
-
function parsePointToken(value, fallback = 0, context) {
|
|
2153
|
-
const trimmed = value.trim();
|
|
2154
|
-
if (trimmed === "0") return 0;
|
|
2155
|
-
if (!isDeckPointLengthString(trimmed)) throw new Error(`Unsupported point value: ${value}`);
|
|
2156
|
-
return parsePointValue(trimmed, fallback, context);
|
|
2157
|
-
}
|
|
2158
|
-
function parsePointValue(value, fallback = 0, context) {
|
|
2159
|
-
if (value === void 0) return fallback;
|
|
2160
|
-
if (typeof value === "number") return value;
|
|
2161
|
-
if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2));
|
|
2162
|
-
if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * 72;
|
|
2163
|
-
if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * 72;
|
|
2164
|
-
if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
|
|
2165
|
-
if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context);
|
|
2166
|
-
if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
|
|
2167
|
-
if (value.endsWith("vw")) {
|
|
2168
|
-
const viewportWidthEmu = context?.viewportWidthEmu;
|
|
2169
|
-
if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport point value without viewport context: ${value}`);
|
|
2170
|
-
return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
2171
|
-
}
|
|
2172
|
-
if (value.endsWith("vh")) {
|
|
2173
|
-
const viewportHeightEmu = context?.viewportHeightEmu;
|
|
2174
|
-
if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport point value without viewport context: ${value}`);
|
|
2175
|
-
return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
2176
|
-
}
|
|
2177
|
-
throw new Error(`Unsupported point value: ${value}`);
|
|
2178
|
-
}
|
|
2179
|
-
function parseStrokeWidth(value, fallback = 0, context) {
|
|
2180
|
-
if (value === void 0) return fallback;
|
|
2181
|
-
if (typeof value === "number") return value;
|
|
2182
|
-
if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2));
|
|
2183
|
-
if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * 72;
|
|
2184
|
-
if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * 72;
|
|
2185
|
-
if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
|
|
2186
|
-
if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context);
|
|
2187
|
-
if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
|
|
2188
|
-
if (value.endsWith("vw")) {
|
|
2189
|
-
const viewportWidthEmu = context?.viewportWidthEmu;
|
|
2190
|
-
if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport stroke width without viewport context: ${value}`);
|
|
2191
|
-
return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
2192
|
-
}
|
|
2193
|
-
if (value.endsWith("vh")) {
|
|
2194
|
-
const viewportHeightEmu = context?.viewportHeightEmu;
|
|
2195
|
-
if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport stroke width without viewport context: ${value}`);
|
|
2196
|
-
return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
|
|
2197
|
-
}
|
|
2198
|
-
throw new Error(`Unsupported stroke width: ${value}`);
|
|
2199
|
-
}
|
|
2200
|
-
function parseLength(value, baseEmu, fallback = 0, context) {
|
|
2201
|
-
if (value === void 0) return fallback;
|
|
2202
|
-
if (typeof value === "number") return value * EMU_PER_INCH;
|
|
2203
|
-
if (value.endsWith("%")) return baseEmu * Number.parseFloat(value.slice(0, -1)) / 100;
|
|
2204
|
-
if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * EMU_PER_INCH;
|
|
2205
|
-
if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2)) / 72 * EMU_PER_INCH;
|
|
2206
|
-
if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * EMU_PER_INCH;
|
|
2207
|
-
if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT * EMU_PER_INCH / 72;
|
|
2208
|
-
if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * EMU_PER_INCH / 72;
|
|
2209
|
-
if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO * EMU_PER_INCH / 72;
|
|
2210
|
-
if (value.endsWith("vw")) {
|
|
2211
|
-
const viewportWidthEmu = context?.viewportWidthEmu;
|
|
2212
|
-
if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport length without viewport context: ${value}`);
|
|
2213
|
-
return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100;
|
|
2214
|
-
}
|
|
2215
|
-
if (value.endsWith("vh")) {
|
|
2216
|
-
const viewportHeightEmu = context?.viewportHeightEmu;
|
|
2217
|
-
if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport length without viewport context: ${value}`);
|
|
2218
|
-
return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100;
|
|
2219
|
-
}
|
|
2220
|
-
throw new Error(`Unsupported length value: ${value}`);
|
|
2221
|
-
}
|
|
2222
2464
|
//#endregion
|
|
2223
2465
|
//#region src/layout/frame.ts
|
|
2224
2466
|
function intersectClipRect(frame, clipRect) {
|
|
@@ -6182,7 +6424,7 @@ function compileNode(child, parentFrame, idGenerator, placement, clipRect, conte
|
|
|
6182
6424
|
}
|
|
6183
6425
|
}
|
|
6184
6426
|
function compileSlide(root, context, slideFrame, idGenerator, lengthContext, resolutionOptions) {
|
|
6185
|
-
if (!isSlideNode(root)) throw new Error(`Slide factory at index ${context.slideIndex} must
|
|
6427
|
+
if (!isSlideNode(root)) throw new Error(`Slide factory at index ${context.slideIndex} must resolve to a slide node.`);
|
|
6186
6428
|
const slideProps = normalizeSlideProps(root.props);
|
|
6187
6429
|
const backgroundBoxFrames = resolveBackgroundBoxFrames(slideFrame);
|
|
6188
6430
|
const backgroundFill = resolveBackgroundLayers(slideProps.backgroundColor ?? slideProps.backgroundImage ?? slideProps.background, slideProps.backgroundTransparency, {
|
|
@@ -6246,6 +6488,28 @@ function resolvedPropsFor(node, resolvedStyles) {
|
|
|
6246
6488
|
if (!resolved) return {};
|
|
6247
6489
|
return Object.fromEntries(Object.entries(resolved.properties).filter(([, property]) => property.source.layer !== "default").map(([key, property]) => [key, property.value]));
|
|
6248
6490
|
}
|
|
6491
|
+
function sourceKeyForOrigin(source) {
|
|
6492
|
+
return !source || source.kind === "root" ? "root" : source.sourceIdentity;
|
|
6493
|
+
}
|
|
6494
|
+
function propsWithTemplateAreaFrame(resolvedStyles, node, templates) {
|
|
6495
|
+
const props = resolvedPropsFor(node, resolvedStyles);
|
|
6496
|
+
const ref = node.templateAreaRef;
|
|
6497
|
+
if (!ref) return props;
|
|
6498
|
+
const frame = templates?.[ref.template]?.areas?.[ref.area]?.frame;
|
|
6499
|
+
if (!frame) return props;
|
|
6500
|
+
const resolved = resolvedStyles.get(node.id);
|
|
6501
|
+
const merged = { ...props };
|
|
6502
|
+
[
|
|
6503
|
+
"x",
|
|
6504
|
+
"y",
|
|
6505
|
+
"width",
|
|
6506
|
+
"height"
|
|
6507
|
+
].forEach((key) => {
|
|
6508
|
+
if (resolved?.properties[key]?.source.layer === "style") return;
|
|
6509
|
+
merged[key] = frame[key];
|
|
6510
|
+
});
|
|
6511
|
+
return merged;
|
|
6512
|
+
}
|
|
6249
6513
|
function pushDefined(values, value) {
|
|
6250
6514
|
if (value !== void 0) values.push(value);
|
|
6251
6515
|
}
|
|
@@ -6294,22 +6558,25 @@ function textChildrenFromGraph(graph, resolvedStyles, childIds, origins) {
|
|
|
6294
6558
|
return [];
|
|
6295
6559
|
});
|
|
6296
6560
|
}
|
|
6297
|
-
function contentChildrenFromGraph(graph, resolvedStyles, childIds, origins) {
|
|
6561
|
+
function contentChildrenFromGraph(graph, resolvedStyles, childIds, origins, templates) {
|
|
6298
6562
|
return childIds.flatMap((childId) => {
|
|
6299
6563
|
const child = graph.nodes.get(childId);
|
|
6300
6564
|
if (!child) return [];
|
|
6301
|
-
const node = layoutAuthorNodeFromGraph(graph, resolvedStyles, child, origins);
|
|
6565
|
+
const node = layoutAuthorNodeFromGraph(graph, resolvedStyles, child, origins, templates);
|
|
6302
6566
|
return node ? [node] : [];
|
|
6303
6567
|
});
|
|
6304
6568
|
}
|
|
6305
|
-
function layoutAuthorNodeFromGraph(graph, resolvedStyles, node, origins) {
|
|
6306
|
-
const props =
|
|
6569
|
+
function layoutAuthorNodeFromGraph(graph, resolvedStyles, node, origins, templates) {
|
|
6570
|
+
const props = propsWithTemplateAreaFrame(resolvedStyles, node, templates);
|
|
6307
6571
|
switch (node.kind) {
|
|
6308
|
-
case "slide":
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6572
|
+
case "slide": {
|
|
6573
|
+
const slideTemplates = graph.templates.get(sourceKeyForOrigin(node.origin.source));
|
|
6574
|
+
return rememberOrigin(layoutNode("slide", {
|
|
6575
|
+
...props,
|
|
6576
|
+
name: node.name
|
|
6577
|
+
}, contentChildrenFromGraph(graph, resolvedStyles, node.children, origins, slideTemplates)), layoutOriginFor(graph, node), origins);
|
|
6578
|
+
}
|
|
6579
|
+
case "container": return rememberOrigin(layoutNode("view", props, contentChildrenFromGraph(graph, resolvedStyles, node.children, origins, templates)), layoutOriginFor(graph, node), origins);
|
|
6313
6580
|
case "text": return rememberOrigin(layoutNode("text", props, textChildrenFromGraph(graph, resolvedStyles, node.inlineChildren, origins)), layoutOriginFor(graph, node), origins);
|
|
6314
6581
|
case "image": {
|
|
6315
6582
|
const asset = node.assetRef ? graph.assets.get(node.assetRef) : void 0;
|
|
@@ -7793,9 +8060,23 @@ function projectedArtifactStatus(value, diagnostics) {
|
|
|
7793
8060
|
if (value === void 0) return "missing";
|
|
7794
8061
|
return diagnostics.hasErrors ? "partial" : "available";
|
|
7795
8062
|
}
|
|
8063
|
+
/**
|
|
8064
|
+
* A Deck with Source Context already bound.
|
|
8065
|
+
*
|
|
8066
|
+
* Bound sources can be mounted, compiled, projected, or rendered, but they are not an authoring
|
|
8067
|
+
* registration surface. Use `Deck#withSource(...)` when a child Deck requires Source Context and
|
|
8068
|
+
* should be executed as a standalone source.
|
|
8069
|
+
*
|
|
8070
|
+
* @typeParam TSourceContext - The Source Context type already bound to this source.
|
|
8071
|
+
* @typeParam TTemplates - The Deck-local Slide Template set owned by the source Deck.
|
|
8072
|
+
*/
|
|
7796
8073
|
var BoundSource = class {
|
|
7797
8074
|
#source;
|
|
7798
8075
|
#sourceContext;
|
|
8076
|
+
/**
|
|
8077
|
+
* @param source - The Deck whose Source Context should be bound.
|
|
8078
|
+
* @param sourceContext - The Source Context value used whenever this source is composed.
|
|
8079
|
+
*/
|
|
7799
8080
|
constructor(source, sourceContext) {
|
|
7800
8081
|
this.#source = source;
|
|
7801
8082
|
this.#sourceContext = sourceContext;
|
|
@@ -7806,6 +8087,7 @@ var BoundSource = class {
|
|
|
7806
8087
|
entries: source.entries,
|
|
7807
8088
|
stylesheets: source.stylesheets,
|
|
7808
8089
|
...source.theme ? { theme: source.theme } : {},
|
|
8090
|
+
...source.templates ? { templates: source.templates } : {},
|
|
7809
8091
|
cycleId: source.cycleId,
|
|
7810
8092
|
boundContext: {
|
|
7811
8093
|
present: true,
|
|
@@ -7813,15 +8095,31 @@ var BoundSource = class {
|
|
|
7813
8095
|
}
|
|
7814
8096
|
};
|
|
7815
8097
|
}
|
|
8098
|
+
/**
|
|
8099
|
+
* Compile this bound source into a Semantic Author Graph and resolved style inspection data.
|
|
8100
|
+
*
|
|
8101
|
+
* @returns A compile result with diagnostics, stage summaries, and graph artifacts when available.
|
|
8102
|
+
*/
|
|
7816
8103
|
compile() {
|
|
7817
8104
|
return compileSource(this);
|
|
7818
8105
|
}
|
|
8106
|
+
/**
|
|
8107
|
+
* Project this bound source into the configured output document model.
|
|
8108
|
+
*
|
|
8109
|
+
* @returns A project result with diagnostics, stage summaries, and the projected model when valid.
|
|
8110
|
+
*/
|
|
7819
8111
|
project() {
|
|
7820
8112
|
return projectSource({
|
|
7821
8113
|
source: this,
|
|
7822
8114
|
options: this.#source.options
|
|
7823
8115
|
});
|
|
7824
8116
|
}
|
|
8117
|
+
/**
|
|
8118
|
+
* Render this bound source with the default writer adapter or an explicit Writer Adapter.
|
|
8119
|
+
*
|
|
8120
|
+
* @param config - Render options for the default adapter, or an explicit Writer Adapter.
|
|
8121
|
+
* @returns A Promise resolving to render diagnostics, stage summaries, and an artifact when render succeeds.
|
|
8122
|
+
*/
|
|
7825
8123
|
render(config) {
|
|
7826
8124
|
return renderSource({
|
|
7827
8125
|
source: this,
|
|
@@ -7830,12 +8128,26 @@ var BoundSource = class {
|
|
|
7830
8128
|
});
|
|
7831
8129
|
}
|
|
7832
8130
|
};
|
|
8131
|
+
/**
|
|
8132
|
+
* The main authoring object for a deckjsx document.
|
|
8133
|
+
*
|
|
8134
|
+
* A Deck owns slide declarations, source-local stylesheets, optional Theme configuration, and
|
|
8135
|
+
* Deck-local Slide Templates. It compiles JSX authoring into the Semantic Author Graph, projects
|
|
8136
|
+
* that graph into an output document model, and renders the projected model through a writer.
|
|
8137
|
+
*
|
|
8138
|
+
* @typeParam TSourceContext - Source Context required by this Deck's slide factories.
|
|
8139
|
+
* @typeParam TTemplates - Deck-local Slide Template set inferred from `new Deck({ templates })`.
|
|
8140
|
+
*/
|
|
7833
8141
|
var Deck = class {
|
|
7834
8142
|
#options;
|
|
7835
8143
|
#entries = [];
|
|
7836
8144
|
#stylesheets = [];
|
|
7837
8145
|
#artifacts = new PipelineArtifactCollection();
|
|
8146
|
+
/** Bind Source Context to this Deck so it can be compiled, projected, rendered, or mounted. */
|
|
7838
8147
|
withSource;
|
|
8148
|
+
/**
|
|
8149
|
+
* @param options - Deck configuration, including layout, metadata, Theme, output format, and Deck Templates.
|
|
8150
|
+
*/
|
|
7839
8151
|
constructor(options) {
|
|
7840
8152
|
this.#options = options;
|
|
7841
8153
|
this.withSource = ((sourceContext) => new BoundSource(this, sourceContext));
|
|
@@ -7848,19 +8160,30 @@ var Deck = class {
|
|
|
7848
8160
|
entries: this.#entries,
|
|
7849
8161
|
stylesheets: this.#stylesheets,
|
|
7850
8162
|
...this.#options.theme ? { theme: this.#options.theme } : {},
|
|
8163
|
+
...this.#options.templates ? { templates: this.#options.templates } : {},
|
|
7851
8164
|
cycleId: this,
|
|
7852
8165
|
boundContext: { present: false }
|
|
7853
8166
|
};
|
|
7854
8167
|
}
|
|
8168
|
+
/**
|
|
8169
|
+
* Register a source-local StyleSheet for CSS-like `className` resolution.
|
|
8170
|
+
*
|
|
8171
|
+
* @param stylesheet - The StyleSheet to apply to slides declared by this Deck source.
|
|
8172
|
+
* @returns This Deck, for fluent authoring.
|
|
8173
|
+
*/
|
|
7855
8174
|
useStyles(stylesheet) {
|
|
7856
8175
|
this.#stylesheets.push(stylesheet);
|
|
7857
8176
|
this.#artifacts.invalidateFromSource();
|
|
7858
8177
|
return this;
|
|
7859
8178
|
}
|
|
7860
|
-
|
|
8179
|
+
slide(optionsOrFactory, maybeFactory) {
|
|
8180
|
+
const options = typeof optionsOrFactory === "function" ? void 0 : optionsOrFactory;
|
|
8181
|
+
const factory = typeof optionsOrFactory === "function" ? optionsOrFactory : maybeFactory;
|
|
8182
|
+
if (!factory) throw new Error("deck.slide() requires a slide factory.");
|
|
7861
8183
|
this.#entries.push({
|
|
7862
8184
|
kind: "slide",
|
|
7863
|
-
|
|
8185
|
+
...options ? { options } : {},
|
|
8186
|
+
factory
|
|
7864
8187
|
});
|
|
7865
8188
|
this.#artifacts.invalidateFromSource();
|
|
7866
8189
|
return this;
|
|
@@ -7876,10 +8199,22 @@ var Deck = class {
|
|
|
7876
8199
|
this.#artifacts.invalidateFromSource();
|
|
7877
8200
|
return this;
|
|
7878
8201
|
}
|
|
8202
|
+
/**
|
|
8203
|
+
* Replace the current compiled graph artifact before calling `project()` or `render()`.
|
|
8204
|
+
*
|
|
8205
|
+
* @param graph - The Semantic Author Graph to use as this Deck's compiled state.
|
|
8206
|
+
* @returns This Deck, for fluent pipeline editing.
|
|
8207
|
+
*/
|
|
7879
8208
|
defineGraph(graph) {
|
|
7880
8209
|
this.#artifacts.replaceGraphArtifact(this, graph);
|
|
7881
8210
|
return this;
|
|
7882
8211
|
}
|
|
8212
|
+
/**
|
|
8213
|
+
* Replace the current projected document model artifact before calling `render()`.
|
|
8214
|
+
*
|
|
8215
|
+
* @param projection - The projected PPTX Package Model to use as this Deck's projection state.
|
|
8216
|
+
* @returns This Deck, for fluent pipeline editing.
|
|
8217
|
+
*/
|
|
7883
8218
|
defineProjection(projection) {
|
|
7884
8219
|
this.#artifacts.replaceProjectionArtifact(projection);
|
|
7885
8220
|
return this;
|
|
@@ -7897,6 +8232,11 @@ var Deck = class {
|
|
|
7897
8232
|
}
|
|
7898
8233
|
return compileSource(this, this.#artifacts);
|
|
7899
8234
|
}
|
|
8235
|
+
/**
|
|
8236
|
+
* Project this root Deck into the configured output document model.
|
|
8237
|
+
*
|
|
8238
|
+
* @returns A project result with diagnostics, stage summaries, and the projected model when valid.
|
|
8239
|
+
*/
|
|
7900
8240
|
project() {
|
|
7901
8241
|
return projectSource({
|
|
7902
8242
|
source: this,
|
|
@@ -7906,6 +8246,12 @@ var Deck = class {
|
|
|
7906
8246
|
artifacts: this.#artifacts
|
|
7907
8247
|
});
|
|
7908
8248
|
}
|
|
8249
|
+
/**
|
|
8250
|
+
* Render this root Deck with the default writer adapter or an explicit Writer Adapter.
|
|
8251
|
+
*
|
|
8252
|
+
* @param config - Render options for the default adapter, or an explicit Writer Adapter.
|
|
8253
|
+
* @returns A Promise resolving to render diagnostics, stage summaries, and an artifact when render succeeds.
|
|
8254
|
+
*/
|
|
7909
8255
|
render(config) {
|
|
7910
8256
|
return renderSource({
|
|
7911
8257
|
source: this,
|
|
@@ -7918,4 +8264,4 @@ var Deck = class {
|
|
|
7918
8264
|
}
|
|
7919
8265
|
};
|
|
7920
8266
|
//#endregion
|
|
7921
|
-
export { CompositionDiagnosticError, Deck, DeckDiagnosticError, EMU_PER_INCH, Fragment, Image, POINTS_PER_INCH, SemanticGraphDiagnosticError, Shape,
|
|
8267
|
+
export { CompositionDiagnosticError, Deck, DeckDiagnosticError, EMU_PER_INCH, Fragment, Image, POINTS_PER_INCH, SemanticGraphDiagnosticError, Shape, StyleDiagnosticError, StyleSheet, Text, Theme, View, createElement, formatDiagnostic, formatDiagnostics };
|