deckjsx 0.2.1 → 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 CHANGED
@@ -38,8 +38,8 @@ const deck = new Deck({
38
38
  meta: { title: "Quarterly Review", author: "deckjsx" },
39
39
  });
40
40
 
41
- deck.add(({ slideIndex, totalSlides }) => (
42
- <Slide name={`Slide ${slideIndex + 1}`} style={{ backgroundColor: "#F8FAFC" }}>
41
+ deck.add(({ composition }) => (
42
+ <Slide name={`Slide ${composition.slideIndex + 1}`} style={{ backgroundColor: "#F8FAFC" }}>
43
43
  <main
44
44
  style={{
45
45
  x: 0.7,
@@ -71,7 +71,7 @@ deck.add(({ slideIndex, totalSlides }) => (
71
71
  <p
72
72
  style={{ width: "100%", height: 0.3, fontSize: 11, color: "#64748B", textAlign: "right" }}
73
73
  >
74
- {slideIndex + 1} / {totalSlides}
74
+ {composition.slideIndex + 1} / {composition.totalSlides}
75
75
  </p>
76
76
  </footer>
77
77
  </main>
package/dist/index.d.mts CHANGED
@@ -1,151 +1,5 @@
1
- import { $ as ImageStyle, A as CssFlexDirection, At as ViewStyle, B as CssJustifyContent, C as CssAlignContent, Ct as TextProps, D as CssBoxSizing, Dt as TextTabStopLength, E as CssAspectRatio, Et as TextTabStopAuthoring, F as CssGridShorthand, Ft as AuthoredTag, G as CssVisibility, H as CssObjectPosition, I as CssGridTemplate, It as SectioningTag, J as DeckOptions, K as DeckJsxIntrinsicElements, L as CssGridTemplateAreas, M as CssGridAutoFlow, Mt as JsxKey, N as CssGridLine, Nt as SourceSpan, O as CssDisplay, Ot as VerticalAlign, P as CssGridPlacement, Pt as AuthoredComponent, Q as ImageProps, R as CssGridTemplateShorthand, S as ContentJsxChild, St as TextJsxChild, T as CssAlignSelf, Tt as TextTabStopAlignment, U as CssOverflow, V as CssJustifySelf, W as CssPosition, X as ImageCropAuthoring, Y as DeckPointLength, Z as ImageCropValue, _ as AuthorNodeProps, _t as StackAxis, a as createElement, at as IntrinsicViewTag, b as BorderStyle, bt as StrokeLineJoin, c as isSlideNode, ct as OutputConfig, d as Slide, dt as SlideContext, et as ImplementedBackendName, f as Text, ft as SlideFactory, g as AuthorNodeMap, gt as StackAlignment, h as AuthorNodeKind, ht as Spacing, i as Fragment, it as IntrinsicTextTag, j as CssFlexWrap, k as CssFlexBasis, kt as ViewProps, l as Image, lt as ShapeProps, m as AuthorNode, mt as SlideStyle, nt as IntrinsicImgProps, o as isAuthorNode, ot as JsxNode, p as View, pt as SlideProps, q as DeckLength, rt as IntrinsicPProps, s as isContentNode, st as LayoutMode, tt as IntrinsicDivProps, u as Shape, ut as ShapeStyle, v as AuthorNodePropsMap, vt as StrokeDashType, w as CssAlignItems, wt as TextStyle, x as ContentAuthorNode, xt as TextFit, y as BackendName, yt as StrokeLineCap, z as CssGridTrack } from "./jsx-runtime-ru5t8S3z.mjs";
1
+ import { $ as ImageStyle, $t as SourceIdentity, A as CssFlexDirection, At as CompositionContext, B as CssJustifyContent, Bt as GraphNodeId, C as CssAlignContent, Ct as TextTabStopAlignment, D as CssBoxSizing, Dt as ViewProps, E as CssAspectRatio, Et as VerticalAlign, F as CssGridShorthand, Ft as SourceContextInput, G as CssVisibility, Gt as SemanticNode, H as CssObjectPosition, Ht as SemanticContainerNode, I as CssGridTemplate, It as SourceContextMapper, J as DeckOptions, Jt as SemanticRole, K as DeckJsxIntrinsicElements, Kt as SemanticNodeKind, L as CssGridTemplateAreas, Lt as AssetEntity, M as CssGridAutoFlow, Mt as CompositionSourceInternals, N as CssGridLine, Nt as SlideFactory, O as CssDisplay, Ot as ViewStyle, P as CssGridPlacement, Pt as SlideFactoryInput, Q as ImageProps, Qt as SemanticTextRunNode, R as CssGridTemplateShorthand, Rt as AssetEntityId, S as ContentJsxChild, St as TextStyle, T as CssAlignSelf, Tt as TextTabStopLength, U as CssOverflow, Ut as SemanticDocumentNode, V as CssJustifySelf, Vt as SemanticAuthorGraph, W as CssPosition, Wt as SemanticImageNode, X as ImageCropAuthoring, Xt as SemanticSlideNode, Y as DeckPointLength, Yt as SemanticShapeNode, Z as ImageCropValue, Zt as SemanticTextNode, _ as AuthorNodeProps, _t as StrokeLineCap, a as createElement, an as DiagnosticSeverity, at as IntrinsicViewTag, b as BorderStyle, bt as TextJsxChild, c as isSlideNode, cn as formatDiagnostics, ct as OutputConfig, d as Slide, dn as SemanticGraphDiagnosticError, dt as SlideProps, en as SourceOrigin, et as ImplementedBackendName, f as Text, ft as SlideStyle, g as AuthorNodeMap, gt as StrokeDashType, h as AuthorNodeKind, ht as StackAxis, i as Fragment, in as DiagnosticLabel, it as IntrinsicTextTag, j as CssFlexWrap, jt as CompositionSource, k as CssFlexBasis, kt as COMPOSITION_SOURCE, l as Image, ln as CompositionDiagnosticError, lt as ShapeProps, m as AuthorNode, mn as SourceSpan, mt as StackAlignment, nn as StyleEntityId, nt as IntrinsicImgProps, o as isAuthorNode, on as Diagnostics, ot as JsxNode, p as View, pn as JsxKey, pt as Spacing, q as DeckLength, qt as SemanticOrigin, rn as Diagnostic, rt as IntrinsicPProps, s as isContentNode, sn as formatDiagnostic, st as LayoutMode, tn as StyleEntity, tt as IntrinsicDivProps, u as Shape, un as DeckDiagnosticError, ut as ShapeStyle, v as AuthorNodePropsMap, vt as StrokeLineJoin, w as CssAlignItems, wt as TextTabStopAuthoring, x as ContentAuthorNode, xt as TextProps, y as BackendName, yt as TextFit, z as CssGridTrack, zt as BaseSemanticNode } from "./jsx-runtime-DauuRkY2.mjs";
2
2
 
3
- //#region src/diagnostics/errors.d.ts
4
- declare class DeckDiagnosticError extends Error {
5
- readonly diagnostics: Diagnostics;
6
- constructor(message: string, diagnostics: Diagnostics);
7
- }
8
- declare class SemanticGraphDiagnosticError extends DeckDiagnosticError {
9
- constructor(diagnostics: Diagnostics);
10
- }
11
- //#endregion
12
- //#region src/diagnostics/format.d.ts
13
- declare function formatDiagnostic(diagnostic: Diagnostic): string;
14
- declare function formatDiagnostics(diagnostics: Diagnostics): string;
15
- //#endregion
16
- //#region src/diagnostics/index.d.ts
17
- type DiagnosticSeverity = "error" | "warning";
18
- type DiagnosticLabel = {
19
- readonly message: string;
20
- readonly path: string;
21
- readonly sourceSpan?: SourceSpan;
22
- readonly severity?: "primary" | "secondary";
23
- };
24
- type Diagnostic = {
25
- readonly severity: DiagnosticSeverity;
26
- readonly code: string;
27
- readonly title: string;
28
- readonly message?: string;
29
- readonly labels: readonly DiagnosticLabel[];
30
- readonly notes?: readonly string[];
31
- readonly help?: readonly string[];
32
- };
33
- type Diagnostics = {
34
- readonly items: readonly Diagnostic[];
35
- readonly hasErrors: boolean;
36
- readonly hasWarnings: boolean;
37
- };
38
- //#endregion
39
- //#region src/graph/types.d.ts
40
- type Brand<T, B extends string> = T & {
41
- readonly __brand: B;
42
- };
43
- type GraphNodeId = Brand<string, "GraphNodeId">;
44
- type StyleEntityId = Brand<string, "StyleEntityId">;
45
- type AssetEntityId = Brand<string, "AssetEntityId">;
46
- type SemanticNodeKind = "container" | "document" | "image" | "shape" | "slide" | "text" | "textRun";
47
- type SemanticRole = {
48
- readonly kind: "document";
49
- } | {
50
- readonly kind: "slide";
51
- } | {
52
- readonly kind: "genericContainer";
53
- } | {
54
- readonly kind: "sectioning";
55
- readonly tag: SectioningTag;
56
- } | {
57
- readonly kind: "figure";
58
- } | {
59
- readonly kind: "paragraph";
60
- } | {
61
- readonly kind: "heading";
62
- readonly level: 1 | 2 | 3 | 4 | 5 | 6;
63
- } | {
64
- readonly kind: "image";
65
- } | {
66
- readonly kind: "shape";
67
- };
68
- type SemanticOrigin = {
69
- readonly kind: "authored" | "implicit";
70
- readonly path: string;
71
- readonly sourceSpan?: SourceSpan;
72
- readonly reason?: "primitive-text-in-container";
73
- };
74
- type BaseSemanticNode = {
75
- readonly id: GraphNodeId;
76
- readonly kind: SemanticNodeKind;
77
- readonly origin: SemanticOrigin;
78
- readonly authoredTag?: AuthoredTag;
79
- readonly authoredComponent?: AuthoredComponent;
80
- readonly role?: SemanticRole;
81
- readonly key?: JsxKey;
82
- readonly styleRef?: StyleEntityId;
83
- };
84
- type SemanticDocumentNode = BaseSemanticNode & {
85
- readonly kind: "document";
86
- readonly children: readonly GraphNodeId[];
87
- };
88
- type SemanticSlideNode = BaseSemanticNode & {
89
- readonly kind: "slide";
90
- readonly name?: string;
91
- readonly children: readonly GraphNodeId[];
92
- };
93
- type SemanticContainerNode = BaseSemanticNode & {
94
- readonly kind: "container";
95
- readonly children: readonly GraphNodeId[];
96
- };
97
- type SemanticTextNode = BaseSemanticNode & {
98
- readonly kind: "text";
99
- readonly inlineChildren: readonly GraphNodeId[];
100
- readonly implicit?: boolean;
101
- };
102
- type SemanticTextRunNode = BaseSemanticNode & {
103
- readonly kind: "textRun";
104
- readonly text: string;
105
- };
106
- type SemanticImageNode = BaseSemanticNode & {
107
- readonly kind: "image";
108
- readonly assetRef?: AssetEntityId;
109
- };
110
- type SemanticShapeNode = BaseSemanticNode & {
111
- readonly kind: "shape";
112
- };
113
- type SemanticNode = SemanticContainerNode | SemanticDocumentNode | SemanticImageNode | SemanticShapeNode | SemanticSlideNode | SemanticTextNode | SemanticTextRunNode;
114
- type StyleEntity = {
115
- readonly id: StyleEntityId;
116
- readonly target: SemanticNodeKind;
117
- readonly authored: {
118
- readonly style?: unknown;
119
- readonly direct?: unknown;
120
- };
121
- readonly resolved?: unknown;
122
- };
123
- type AssetEntity = {
124
- readonly id: AssetEntityId;
125
- readonly kind: "image";
126
- readonly source: {
127
- readonly kind: "path";
128
- readonly path: string;
129
- } | {
130
- readonly kind: "data";
131
- readonly data: string;
132
- };
133
- readonly metadata: {
134
- readonly mediaType?: string;
135
- readonly byteLength?: number;
136
- readonly widthPx?: number;
137
- readonly heightPx?: number;
138
- readonly contentHash?: string;
139
- };
140
- readonly resolution: "failed" | "resolved" | "unresolved";
141
- };
142
- type SemanticAuthorGraph = {
143
- readonly documentId: GraphNodeId;
144
- readonly nodes: ReadonlyMap<GraphNodeId, SemanticNode>;
145
- readonly styles: ReadonlyMap<StyleEntityId, StyleEntity>;
146
- readonly assets: ReadonlyMap<AssetEntityId, AssetEntity>;
147
- };
148
- //#endregion
149
3
  //#region src/ir/index.d.ts
150
4
  type PresentationIR = {
151
5
  version: "0.1";
@@ -394,11 +248,11 @@ type CompileInspectResult = {
394
248
  readonly graph?: SemanticAuthorGraph;
395
249
  readonly diagnostics: Diagnostics;
396
250
  };
397
- declare class Deck {
251
+ type WithSource<TSourceContext> = [TSourceContext] extends [void] ? never : (sourceContext: TSourceContext) => BoundSource<TSourceContext>;
252
+ declare class BoundSource<TSourceContext = void> implements CompositionSource<TSourceContext> {
398
253
  #private;
399
- constructor(options: DeckOptions);
400
- add(slide: SlideFactory): this;
401
- render(): PresentationIR;
254
+ constructor(source: Deck<TSourceContext>, sourceContext: TSourceContext);
255
+ [COMPOSITION_SOURCE](): CompositionSourceInternals<TSourceContext>;
402
256
  compile(): SemanticAuthorGraph;
403
257
  compile(config: {
404
258
  mode?: "strict";
@@ -406,8 +260,28 @@ declare class Deck {
406
260
  compile(config: {
407
261
  mode: "inspect";
408
262
  }): CompileInspectResult;
263
+ render(): PresentationIR;
409
264
  output(config: OutputConfig): Promise<void>;
410
265
  }
266
+ declare class Deck<TSourceContext = void> implements CompositionSource<TSourceContext> {
267
+ #private;
268
+ readonly withSource: WithSource<TSourceContext>;
269
+ constructor(options: DeckOptions);
270
+ get options(): DeckOptions;
271
+ [COMPOSITION_SOURCE](): CompositionSourceInternals<TSourceContext>;
272
+ add(slide: SlideFactory<TSourceContext>): this;
273
+ mount<TChildContext>(sourceKey: string, child: Deck<TChildContext>, ...context: [TChildContext] extends [void] ? [] : [sourceContext: SourceContextInput<TSourceContext, TChildContext>]): this;
274
+ mount<TChildContext>(sourceKey: string, child: BoundSource<TChildContext>): this;
275
+ render(this: Deck<void>): PresentationIR;
276
+ compile(this: Deck<void>): SemanticAuthorGraph;
277
+ compile(this: Deck<void>, config: {
278
+ mode?: "strict";
279
+ }): SemanticAuthorGraph;
280
+ compile(this: Deck<void>, config: {
281
+ mode: "inspect";
282
+ }): CompileInspectResult;
283
+ output(this: Deck<void>, config: OutputConfig): Promise<void>;
284
+ }
411
285
  //#endregion
412
286
  //#region src/backends/pptxgenjs.d.ts
413
287
  declare function pptxgenjsBackend(): CompileBackend;
@@ -430,4 +304,4 @@ declare global {
430
304
  }
431
305
  }
432
306
  //#endregion
433
- export { type AssetEntity, type AssetEntityId, type AuthorNode, type AuthorNodeKind, type AuthorNodeMap, type AuthorNodeProps, type AuthorNodePropsMap, type BackendArtifact, type BackendName, type BackgroundImageLayerIR, type BackgroundLayerIR, type BaseNodeIR, type BaseSemanticNode, type BorderStyle, type CompileBackend, type CompileInspectResult, type CompileMode, type ContentAuthorNode, type ContentJsxChild, type CssAlignContent, type CssAlignItems, type CssAlignSelf, type CssAspectRatio, type CssBoxSizing, type CssDisplay, type CssFlexBasis, type CssFlexDirection, type CssFlexWrap, type CssGridAutoFlow, type CssGridLine, type CssGridPlacement, type CssGridShorthand, type CssGridTemplate, type CssGridTemplateAreas, type CssGridTemplateShorthand, type CssGridTrack, type CssJustifyContent, type CssJustifySelf, type CssObjectPosition, type CssOverflow, type CssPosition, type CssVisibility, Deck, DeckDiagnosticError, type DeckJsxIntrinsicElements, type DeckLength, type DeckOptions, type DeckPointLength, type Diagnostic, type DiagnosticLabel, type DiagnosticSeverity, type Diagnostics, EMU_PER_INCH, type EdgeStrokeIR, type FillIR, Fragment, type FrameIR, type GraphNodeId, type GroupIR, type HyperlinkIR, Image, type ImageCropAuthoring, type ImageCropIR, type ImageCropValue, type ImageIR, type ImageProps, type ImageSourceIR, type ImageStyle, type ImplementedBackendName, type IntrinsicDivProps, type IntrinsicImgProps, type IntrinsicPProps, type IntrinsicTextTag, type IntrinsicViewTag, type JsxKey, type JsxNode, type LayoutMode, type LinearGradientFillIR, type LinearGradientStopIR, type NodeIR, type ObjectPositionIR, type OutputConfig, POINTS_PER_INCH, type PresentationIR, type RadialGradientFillIR, type SemanticAuthorGraph, type SemanticContainerNode, type SemanticDocumentNode, SemanticGraphDiagnosticError, type SemanticImageNode, type SemanticNode, type SemanticNodeKind, type SemanticOrigin, type SemanticRole, type SemanticShapeNode, type SemanticSlideNode, type SemanticTextNode, type SemanticTextRunNode, type ShadowIR, Shape, type ShapeIR, type ShapeProps, type ShapeStyle, type SizeIR, Slide, type SlideContext, type SlideFactory, type SlideIR, type SlideProps, type SlideStyle, type SolidFillIR, type SourceSpan, type Spacing, type StackAlignment, type StackAxis, type StrokeDashType, type StrokeIR, type StrokeLineCap, type StrokeLineJoin, type StyleEntity, type StyleEntityId, Text, type TextBulletListIR, type TextContentIR, type TextFit, type TextIR, type TextJsxChild, type TextListIR, type TextNoListIR, type TextNumberListIR, type TextProps, type TextRunIR, type TextStyle, type TextStyleIR, type TextTabStopAlignment, type TextTabStopAuthoring, type TextTabStopIR, type TextTabStopLength, type VerticalAlign, View, type ViewProps, type ViewStyle, createElement, formatDiagnostic, formatDiagnostics, isAuthorNode, isContentNode, isSlideNode, pptxgenjsBackend };
307
+ export { type AssetEntity, type AssetEntityId, type AuthorNode, type AuthorNodeKind, type AuthorNodeMap, type AuthorNodeProps, type AuthorNodePropsMap, type BackendArtifact, type BackendName, type BackgroundImageLayerIR, type BackgroundLayerIR, type BaseNodeIR, type BaseSemanticNode, type BorderStyle, type BoundSource, type CompileBackend, type CompileInspectResult, type CompileMode, type CompositionContext, CompositionDiagnosticError, type ContentAuthorNode, type ContentJsxChild, type CssAlignContent, type CssAlignItems, type CssAlignSelf, type CssAspectRatio, type CssBoxSizing, type CssDisplay, type CssFlexBasis, type CssFlexDirection, type CssFlexWrap, type CssGridAutoFlow, type CssGridLine, type CssGridPlacement, type CssGridShorthand, type CssGridTemplate, type CssGridTemplateAreas, type CssGridTemplateShorthand, type CssGridTrack, type CssJustifyContent, type CssJustifySelf, type CssObjectPosition, type CssOverflow, type CssPosition, type CssVisibility, Deck, DeckDiagnosticError, type DeckJsxIntrinsicElements, type DeckLength, type DeckOptions, type DeckPointLength, type Diagnostic, type DiagnosticLabel, type DiagnosticSeverity, type Diagnostics, EMU_PER_INCH, type EdgeStrokeIR, type FillIR, Fragment, type FrameIR, type GraphNodeId, type GroupIR, type HyperlinkIR, Image, type ImageCropAuthoring, type ImageCropIR, type ImageCropValue, type ImageIR, type ImageProps, type ImageSourceIR, type ImageStyle, type ImplementedBackendName, type IntrinsicDivProps, type IntrinsicImgProps, type IntrinsicPProps, type IntrinsicTextTag, type IntrinsicViewTag, type JsxKey, type JsxNode, type LayoutMode, type LinearGradientFillIR, type LinearGradientStopIR, type NodeIR, type ObjectPositionIR, type OutputConfig, POINTS_PER_INCH, type PresentationIR, type RadialGradientFillIR, type SemanticAuthorGraph, type SemanticContainerNode, type SemanticDocumentNode, SemanticGraphDiagnosticError, type SemanticImageNode, type SemanticNode, type SemanticNodeKind, type SemanticOrigin, type SemanticRole, type SemanticShapeNode, type SemanticSlideNode, type SemanticTextNode, type SemanticTextRunNode, type ShadowIR, Shape, type ShapeIR, type ShapeProps, type ShapeStyle, type SizeIR, Slide, type SlideFactory, type SlideFactoryInput, type SlideIR, type SlideProps, type SlideStyle, type SolidFillIR, type SourceContextMapper, type SourceIdentity, type SourceOrigin, type SourceSpan, type Spacing, type StackAlignment, type StackAxis, type StrokeDashType, type StrokeIR, type StrokeLineCap, type StrokeLineJoin, type StyleEntity, type StyleEntityId, Text, type TextBulletListIR, type TextContentIR, type TextFit, type TextIR, type TextJsxChild, type TextListIR, type TextNoListIR, type TextNumberListIR, type TextProps, type TextRunIR, type TextStyle, type TextStyleIR, type TextTabStopAlignment, type TextTabStopAuthoring, type TextTabStopIR, type TextTabStopLength, type VerticalAlign, View, type ViewProps, type ViewStyle, createElement, formatDiagnostic, formatDiagnostics, isAuthorNode, isContentNode, isSlideNode, pptxgenjsBackend };
package/dist/index.mjs CHANGED
@@ -4139,17 +4139,12 @@ function renderPresentation(options, slides) {
4139
4139
  meta: options.meta,
4140
4140
  size: slideSize,
4141
4141
  slides: slides.map((factory, slideIndex) => {
4142
- return compileSlide(toLegacyJsxNode(factory({
4142
+ return compileSlide(toLegacyJsxNode(factory({ composition: {
4143
4143
  slideIndex,
4144
4144
  totalSlides: slides.length,
4145
- context: {
4146
- slideIndex,
4147
- totalSlides: slides.length
4148
- }
4149
- })), {
4150
- slideIndex,
4151
- totalSlides: slides.length
4152
- }, slideFrame, idGenerator, lengthContext);
4145
+ deckSlideIndex: slideIndex,
4146
+ deckTotalSlides: slides.length
4147
+ } })), { slideIndex }, slideFrame, idGenerator, lengthContext);
4153
4148
  })
4154
4149
  };
4155
4150
  }
@@ -4188,6 +4183,12 @@ var SemanticGraphDiagnosticError = class extends DeckDiagnosticError {
4188
4183
  this.name = "SemanticGraphDiagnosticError";
4189
4184
  }
4190
4185
  };
4186
+ var CompositionDiagnosticError = class extends DeckDiagnosticError {
4187
+ constructor(diagnostics) {
4188
+ super(formatDiagnostics(diagnostics), diagnostics);
4189
+ this.name = "CompositionDiagnosticError";
4190
+ }
4191
+ };
4191
4192
  //#endregion
4192
4193
  //#region src/diagnostics/index.ts
4193
4194
  function createDiagnostics(items = []) {
@@ -4201,6 +4202,276 @@ function diagnostic(input) {
4201
4202
  return input;
4202
4203
  }
4203
4204
  //#endregion
4205
+ //#region src/composition/types.ts
4206
+ const COMPOSITION_SOURCE = Symbol("deckjsx.compositionSource");
4207
+ function sourceIdentity(value) {
4208
+ return value;
4209
+ }
4210
+ //#endregion
4211
+ //#region src/composition/resolve.ts
4212
+ const MAX_COMPOSITION_DEPTH = 64;
4213
+ const ROOT_SOURCE = { kind: "root" };
4214
+ function addDiagnostic$1(context, item) {
4215
+ context.diagnostics.push(item);
4216
+ }
4217
+ function compositionDiagnostic(input) {
4218
+ return diagnostic({
4219
+ severity: "error",
4220
+ code: input.code,
4221
+ title: input.title,
4222
+ message: input.message,
4223
+ labels: [{
4224
+ path: input.path,
4225
+ message: input.message
4226
+ }],
4227
+ ...input.help ? { help: input.help } : {}
4228
+ });
4229
+ }
4230
+ function sourcePathFor(parentPath, sourceKey) {
4231
+ return parentPath === "root" ? sourceKey : `${parentPath}/${sourceKey}`;
4232
+ }
4233
+ function sourceOriginFor(parent, sourceKey) {
4234
+ return {
4235
+ kind: "mounted",
4236
+ sourceKey,
4237
+ sourceIdentity: sourceIdentity(`${parent.kind === "root" ? "" : `${parent.sourceIdentity}/`}${sourceKey}`)
4238
+ };
4239
+ }
4240
+ function sourceMaterialFor(source) {
4241
+ return source.kind === "root" ? ["source", "root"] : ["source", source.sourceIdentity];
4242
+ }
4243
+ function validateSourceKey(sourceKey) {
4244
+ if (sourceKey.trim().length === 0) return "Source Key must not be empty.";
4245
+ if (sourceKey === "." || sourceKey === "..") return "Source Key must not be dot or dot-dot.";
4246
+ if (sourceKey.includes("/")) return "Source Key must not contain /.";
4247
+ }
4248
+ function describeInvalidRoot(value) {
4249
+ if (isLegacyAuthorNode(value)) return "Slide factory returned a legacy author node.";
4250
+ if (isAuthorTreeNode(value)) return "Slide factory returned an author tree node that is not a <Slide /> root.";
4251
+ if (value === null) return "Slide factory returned null.";
4252
+ return `Slide factory returned ${typeof value}.`;
4253
+ }
4254
+ function isSlideRoot(value) {
4255
+ return value.kind === "element" && value.source.kind === "component" && value.source.component === "Slide";
4256
+ }
4257
+ function isPromiseLike(value) {
4258
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
4259
+ }
4260
+ function mapSlotOrigins(value, origin, targets, seen) {
4261
+ if (isAuthorTreeNode(value)) {
4262
+ targets.set(value, origin);
4263
+ return;
4264
+ }
4265
+ if (!Array.isArray(value)) return;
4266
+ if (seen.has(value)) return;
4267
+ seen.add(value);
4268
+ value.forEach((item) => mapSlotOrigins(item, origin, targets, seen));
4269
+ }
4270
+ function collectSourceSlots(context, parent) {
4271
+ const origins = /* @__PURE__ */ new WeakMap();
4272
+ if (!context.present || typeof context.value !== "object" || context.value === null) return origins;
4273
+ Object.entries(context.value).forEach(([field, value]) => {
4274
+ mapSlotOrigins(value, {
4275
+ source: parent.slotOwnerSource,
4276
+ field,
4277
+ identityMaterial: [...parent.slotOwnerMaterial, `slot:${field}`]
4278
+ }, origins, /* @__PURE__ */ new WeakSet());
4279
+ });
4280
+ return origins;
4281
+ }
4282
+ function childContextFor(entry, context, path) {
4283
+ if (entry.invalidExtraContext) {
4284
+ addDiagnostic$1(context, compositionDiagnostic({
4285
+ code: "E_COMPOSITION_INVALID_MOUNT",
4286
+ title: "mount received invalid source context",
4287
+ path,
4288
+ message: "A Bound Source cannot receive additional Source Context."
4289
+ }));
4290
+ return;
4291
+ }
4292
+ if (entry.contextProvider === void 0) return { present: false };
4293
+ if (typeof entry.contextProvider !== "function") return {
4294
+ present: true,
4295
+ value: entry.contextProvider
4296
+ };
4297
+ try {
4298
+ const value = context.context.present ? entry.contextProvider(context.context.value) : entry.contextProvider();
4299
+ if (isPromiseLike(value)) {
4300
+ addDiagnostic$1(context, compositionDiagnostic({
4301
+ code: "E_COMPOSITION_CONTEXT_MAPPER_ASYNC",
4302
+ title: "source context mapper returned a Promise",
4303
+ path,
4304
+ message: "Source Context Mappers must be synchronous in v0.3."
4305
+ }));
4306
+ return;
4307
+ }
4308
+ return {
4309
+ present: true,
4310
+ value
4311
+ };
4312
+ } catch (error) {
4313
+ addDiagnostic$1(context, compositionDiagnostic({
4314
+ code: "E_COMPOSITION_CONTEXT_MAPPER_FAILED",
4315
+ title: "source context mapper failed",
4316
+ path,
4317
+ message: error instanceof Error ? error.message : "Source Context Mapper threw."
4318
+ }));
4319
+ return;
4320
+ }
4321
+ }
4322
+ function resolveSource(source, context) {
4323
+ const sourceState = source[COMPOSITION_SOURCE]();
4324
+ const effectiveContext = context.context.present ? context.context : sourceState.boundContext;
4325
+ if (context.depth > MAX_COMPOSITION_DEPTH) {
4326
+ addDiagnostic$1(context, compositionDiagnostic({
4327
+ code: "E_COMPOSITION_DEPTH_EXCEEDED",
4328
+ title: "composition depth exceeded",
4329
+ path: context.sourcePath,
4330
+ message: `Composition depth exceeded ${MAX_COMPOSITION_DEPTH}.`
4331
+ }));
4332
+ return;
4333
+ }
4334
+ if (context.stack.indexOf(sourceState.cycleId) !== -1) {
4335
+ addDiagnostic$1(context, compositionDiagnostic({
4336
+ code: "E_COMPOSITION_CYCLE",
4337
+ title: "composition cycle detected",
4338
+ path: context.sourcePath,
4339
+ message: "A Deck cannot mount itself through its descendant sources."
4340
+ }));
4341
+ return;
4342
+ }
4343
+ const entries = [];
4344
+ let slideCount = 0;
4345
+ const sourceKeys = /* @__PURE__ */ new Set();
4346
+ const slotOrigins = collectSourceSlots(effectiveContext, context);
4347
+ const nextContextBase = {
4348
+ diagnostics: context.diagnostics,
4349
+ stack: [...context.stack, sourceState.cycleId],
4350
+ depth: context.depth + 1
4351
+ };
4352
+ sourceState.entries.forEach((entry, index) => {
4353
+ if (entry.kind === "slide") {
4354
+ entries.push({
4355
+ kind: "slide",
4356
+ factory: entry.factory,
4357
+ path: `${context.sourcePath} > slideFactory[${index}]`
4358
+ });
4359
+ slideCount += 1;
4360
+ return;
4361
+ }
4362
+ const mountPath = `${context.sourcePath} > mount[${entry.sourceKey}]`;
4363
+ const invalidKey = validateSourceKey(entry.sourceKey);
4364
+ if (invalidKey) {
4365
+ addDiagnostic$1(context, compositionDiagnostic({
4366
+ code: "E_COMPOSITION_INVALID_SOURCE_KEY",
4367
+ title: "invalid source key",
4368
+ path: mountPath,
4369
+ message: invalidKey
4370
+ }));
4371
+ return;
4372
+ }
4373
+ if (sourceKeys.has(entry.sourceKey)) {
4374
+ addDiagnostic$1(context, compositionDiagnostic({
4375
+ code: "E_COMPOSITION_DUPLICATE_SOURCE_KEY",
4376
+ title: "duplicate source key",
4377
+ path: mountPath,
4378
+ message: `Source Key "${entry.sourceKey}" is already used in this parent source.`
4379
+ }));
4380
+ return;
4381
+ }
4382
+ sourceKeys.add(entry.sourceKey);
4383
+ const childContext = childContextFor(entry, context, mountPath);
4384
+ if (!childContext) return;
4385
+ const childSource = sourceOriginFor(context.source, entry.sourceKey);
4386
+ const childPlan = resolveSource(entry.source, {
4387
+ ...nextContextBase,
4388
+ source: childSource,
4389
+ sourceIdentityMaterial: sourceMaterialFor(childSource),
4390
+ sourcePath: sourcePathFor(context.sourcePath, entry.sourceKey),
4391
+ context: childContext,
4392
+ slotOwnerSource: context.source,
4393
+ slotOwnerMaterial: context.sourceIdentityMaterial
4394
+ });
4395
+ if (!childPlan) return;
4396
+ entries.push({
4397
+ kind: "source",
4398
+ source: childPlan
4399
+ });
4400
+ slideCount += childPlan.slideCount;
4401
+ });
4402
+ return {
4403
+ source: context.source,
4404
+ sourceIdentityMaterial: context.sourceIdentityMaterial,
4405
+ context: effectiveContext,
4406
+ entries,
4407
+ slideCount,
4408
+ slotOrigins
4409
+ };
4410
+ }
4411
+ function flattenPlan(plan, deckTotalSlides, deckSlideIndex, roots, diagnostics) {
4412
+ let sourceSlideIndex = 0;
4413
+ let nextDeckSlideIndex = deckSlideIndex;
4414
+ for (const entry of plan.entries) {
4415
+ if (entry.kind === "source") {
4416
+ nextDeckSlideIndex = flattenPlan(entry.source, deckTotalSlides, nextDeckSlideIndex, roots, diagnostics);
4417
+ sourceSlideIndex += entry.source.slideCount;
4418
+ continue;
4419
+ }
4420
+ const composition = {
4421
+ ...plan.source.kind === "mounted" ? { sourceKey: plan.source.sourceKey } : {},
4422
+ slideIndex: sourceSlideIndex,
4423
+ totalSlides: plan.slideCount,
4424
+ deckSlideIndex: nextDeckSlideIndex,
4425
+ deckTotalSlides
4426
+ };
4427
+ const input = plan.context.present ? {
4428
+ context: plan.context.value,
4429
+ composition
4430
+ } : { composition };
4431
+ const root = entry.factory(input);
4432
+ if (!isAuthorTreeNode(root) || !isSlideRoot(root)) diagnostics.push(compositionDiagnostic({
4433
+ code: "E_COMPOSITION_INVALID_ROOT",
4434
+ title: "slide factory must return a <Slide /> root",
4435
+ path: entry.path,
4436
+ message: describeInvalidRoot(root),
4437
+ help: ["Return <Slide>...</Slide> from the slide factory passed to deck.add()."]
4438
+ }));
4439
+ else roots.push({
4440
+ root,
4441
+ source: plan.source,
4442
+ sourceIdentityMaterial: plan.sourceIdentityMaterial,
4443
+ path: entry.path,
4444
+ composition,
4445
+ slotOrigins: plan.slotOrigins
4446
+ });
4447
+ sourceSlideIndex += 1;
4448
+ nextDeckSlideIndex += 1;
4449
+ }
4450
+ return nextDeckSlideIndex;
4451
+ }
4452
+ function resolveComposition(source) {
4453
+ const diagnostics = [];
4454
+ const rootPlan = resolveSource(source, {
4455
+ diagnostics,
4456
+ stack: [],
4457
+ depth: 0,
4458
+ source: ROOT_SOURCE,
4459
+ sourceIdentityMaterial: sourceMaterialFor(ROOT_SOURCE),
4460
+ sourcePath: "root",
4461
+ context: { present: false },
4462
+ slotOwnerSource: ROOT_SOURCE,
4463
+ slotOwnerMaterial: sourceMaterialFor(ROOT_SOURCE)
4464
+ });
4465
+ if (!rootPlan) return { diagnostics: createDiagnostics(diagnostics) };
4466
+ const roots = [];
4467
+ flattenPlan(rootPlan, rootPlan.slideCount, 0, roots, diagnostics);
4468
+ const resolvedDiagnostics = createDiagnostics(diagnostics);
4469
+ return {
4470
+ ...resolvedDiagnostics.hasErrors ? {} : { roots },
4471
+ diagnostics: resolvedDiagnostics
4472
+ };
4473
+ }
4474
+ //#endregion
4204
4475
  //#region src/graph/identity.ts
4205
4476
  function slug(value) {
4206
4477
  return value.replace(/[^a-zA-Z0-9:_-]+/g, "_");
@@ -4281,17 +4552,32 @@ function nodeSemanticKind(node) {
4281
4552
  function nodeRole(node) {
4282
4553
  return node.source.kind === "tag" ? semanticRoleForTag(node.source.tag) : semanticRoleForComponent(node.source.component);
4283
4554
  }
4284
- function originFor(node, path) {
4555
+ function sourceFor(context) {
4556
+ return context.activeSlot?.source ?? context.source;
4557
+ }
4558
+ function contextForNode(node, context) {
4559
+ const slot = context.slotOrigins.get(node);
4560
+ if (!slot) return context;
4561
+ return {
4562
+ ...context,
4563
+ activeSlot: slot,
4564
+ parentMaterial: [...context.parentMaterial, ...slot.identityMaterial],
4565
+ path: `${context.path} > slot[${slot.field}]`
4566
+ };
4567
+ }
4568
+ function originFor(node, path, context) {
4285
4569
  return {
4286
4570
  kind: "authored",
4287
4571
  path,
4572
+ source: sourceFor(context),
4288
4573
  ...node.sourceSpan ? { sourceSpan: node.sourceSpan } : {}
4289
4574
  };
4290
4575
  }
4291
- function textOriginFor(node, path) {
4576
+ function textOriginFor(node, path, context) {
4292
4577
  return {
4293
4578
  kind: "authored",
4294
4579
  path,
4580
+ source: sourceFor(context),
4295
4581
  ...node.sourceSpan ? { sourceSpan: node.sourceSpan } : {}
4296
4582
  };
4297
4583
  }
@@ -4352,12 +4638,12 @@ function assetForImage(state, idMaterial, props, path) {
4352
4638
  state.assets.set(id, entity);
4353
4639
  return id;
4354
4640
  }
4355
- function semanticBase(state, node, id, kind, path, material) {
4641
+ function semanticBase(state, node, id, kind, path, material, context) {
4356
4642
  const styleRef = styleRefFor(state, material, kind, node.props);
4357
4643
  return {
4358
4644
  id,
4359
4645
  kind,
4360
- origin: originFor(node, path),
4646
+ origin: originFor(node, path, context),
4361
4647
  ...node.source.kind === "tag" ? { authoredTag: node.source.tag } : {},
4362
4648
  ...node.source.kind === "component" ? { authoredComponent: node.source.component } : {},
4363
4649
  ...node.key !== void 0 ? { key: node.key } : {},
@@ -4374,7 +4660,7 @@ function buildTextRunFromLeaf(state, leaf, context, index) {
4374
4660
  state.nodes.set(id, {
4375
4661
  id,
4376
4662
  kind: "textRun",
4377
- origin: textOriginFor(leaf, path),
4663
+ origin: textOriginFor(leaf, path, context),
4378
4664
  text
4379
4665
  });
4380
4666
  return {
@@ -4396,6 +4682,7 @@ function buildImplicitTextNode(state, leaf, context, index) {
4396
4682
  origin: {
4397
4683
  kind: "implicit",
4398
4684
  path: `${context.path} > implicitText[${index}]`,
4685
+ source: sourceFor(context),
4399
4686
  ...leaf.sourceSpan ? { sourceSpan: leaf.sourceSpan } : {},
4400
4687
  reason: "primitive-text-in-container"
4401
4688
  },
@@ -4411,11 +4698,12 @@ function buildChildren(state, children, context) {
4411
4698
  const ids = [];
4412
4699
  children.forEach((child, index) => {
4413
4700
  if (child.kind === "fragment") {
4701
+ const childContext = contextForNode(child, context);
4414
4702
  const segment = `fragment:${keySegment(child.key, index)}`;
4415
4703
  ids.push(...buildChildren(state, child.children, {
4416
- ...context,
4417
- parentMaterial: [...context.parentMaterial, segment],
4418
- path: `${context.path} > fragment[${keySegment(child.key, index)}]`
4704
+ ...childContext,
4705
+ parentMaterial: [...childContext.parentMaterial, segment],
4706
+ path: `${childContext.path} > fragment[${keySegment(child.key, index)}]`
4419
4707
  }));
4420
4708
  return;
4421
4709
  }
@@ -4424,11 +4712,12 @@ function buildChildren(state, children, context) {
4424
4712
  });
4425
4713
  return ids;
4426
4714
  }
4427
- function buildTextLikeNode(state, node, id, path, material) {
4715
+ function buildTextLikeNode(state, node, id, path, material, context) {
4428
4716
  const inlineChildren = [];
4429
4717
  node.children.forEach((child, index) => {
4430
4718
  if (child.kind === "text") {
4431
4719
  const run = buildTextRunFromLeaf(state, child, {
4720
+ ...context,
4432
4721
  parentId: id,
4433
4722
  parentMaterial: material,
4434
4723
  path,
@@ -4438,16 +4727,24 @@ function buildTextLikeNode(state, node, id, path, material) {
4438
4727
  return;
4439
4728
  }
4440
4729
  if (child.kind === "fragment") {
4441
- inlineChildren.push(...buildChildren(state, child.children, {
4730
+ const childContext = contextForNode(child, {
4731
+ ...context,
4442
4732
  parentId: id,
4443
- parentMaterial: [...material, `fragment:${keySegment(child.key, index)}`],
4444
- path: `${path} > fragment[${keySegment(child.key, index)}]`,
4733
+ parentMaterial: material,
4734
+ path,
4445
4735
  inline: true
4736
+ });
4737
+ const segment = `fragment:${keySegment(child.key, index)}`;
4738
+ inlineChildren.push(...buildChildren(state, child.children, {
4739
+ ...childContext,
4740
+ parentMaterial: [...childContext.parentMaterial, segment],
4741
+ path: `${childContext.path} > fragment[${keySegment(child.key, index)}]`
4446
4742
  }));
4447
4743
  return;
4448
4744
  }
4449
4745
  if (child.source.kind === "tag" && child.source.tag === "span") {
4450
4746
  const built = buildNode(state, child, {
4747
+ ...context,
4451
4748
  parentId: id,
4452
4749
  parentMaterial: material,
4453
4750
  path,
@@ -4459,7 +4756,7 @@ function buildTextLikeNode(state, node, id, path, material) {
4459
4756
  addDiagnostic(state, invalidStructure(`${path} > ${sourceName(child)}[${index}]`, "block content cannot appear inside text", "Text-like elements accept primitive text and inline spans only."));
4460
4757
  });
4461
4758
  state.nodes.set(id, {
4462
- ...semanticBase(state, node, id, "text", path, material),
4759
+ ...semanticBase(state, node, id, "text", path, material, context),
4463
4760
  kind: "text",
4464
4761
  inlineChildren
4465
4762
  });
@@ -4488,13 +4785,14 @@ function collectInlineText(state, children, path) {
4488
4785
  return text;
4489
4786
  }
4490
4787
  function buildNode(state, node, context, index) {
4788
+ const nodeContext = contextForNode(node, context);
4491
4789
  if (node.kind === "fragment") return;
4492
- if (node.kind === "text") return context.inline ? buildTextRunFromLeaf(state, node, context, index) : buildImplicitTextNode(state, node, context, index);
4790
+ if (node.kind === "text") return nodeContext.inline ? buildTextRunFromLeaf(state, node, nodeContext, index) : buildImplicitTextNode(state, node, nodeContext, index);
4493
4791
  const kind = nodeSemanticKind(node);
4494
4792
  const segment = `${sourceName(node)}:${keySegment(node.key, index)}`;
4495
- const material = [...context.parentMaterial, segment];
4793
+ const material = [...nodeContext.parentMaterial, segment];
4496
4794
  const id = graphNodeId(material);
4497
- const path = `${context.path} > ${sourceName(node)}[${keySegment(node.key, index)}]`;
4795
+ const path = `${nodeContext.path} > ${sourceName(node)}[${keySegment(node.key, index)}]`;
4498
4796
  if (kind === "textRun") {
4499
4797
  if (!context.inline) {
4500
4798
  addDiagnostic(state, invalidStructure(path, "span cannot appear here", "span must be inside a text-like element.", ["Wrap the span in <p>...</p> or move it inside an existing text element."]));
@@ -4502,7 +4800,7 @@ function buildNode(state, node, context, index) {
4502
4800
  }
4503
4801
  const text = collectInlineText(state, node.children, path);
4504
4802
  state.nodes.set(id, {
4505
- ...semanticBase(state, node, id, "textRun", path, material),
4803
+ ...semanticBase(state, node, id, "textRun", path, material, nodeContext),
4506
4804
  kind: "textRun",
4507
4805
  text
4508
4806
  });
@@ -4511,12 +4809,12 @@ function buildNode(state, node, context, index) {
4511
4809
  kind: "textRun"
4512
4810
  };
4513
4811
  }
4514
- if (kind === "text") return buildTextLikeNode(state, node, id, path, material);
4812
+ if (kind === "text") return buildTextLikeNode(state, node, id, path, material, nodeContext);
4515
4813
  if (kind === "image") {
4516
4814
  if (node.children.length > 0) addDiagnostic(state, invalidStructure(path, "image cannot have children", "Image nodes are leaf nodes."));
4517
4815
  const assetRef = assetForImage(state, material, node.props, path);
4518
4816
  state.nodes.set(id, {
4519
- ...semanticBase(state, node, id, "image", path, material),
4817
+ ...semanticBase(state, node, id, "image", path, material, nodeContext),
4520
4818
  kind: "image",
4521
4819
  ...assetRef ? { assetRef } : {}
4522
4820
  });
@@ -4529,10 +4827,13 @@ function buildNode(state, node, context, index) {
4529
4827
  parentId: id,
4530
4828
  parentMaterial: material,
4531
4829
  path,
4532
- inline: false
4830
+ inline: false,
4831
+ source: sourceFor(nodeContext),
4832
+ slotOrigins: nodeContext.slotOrigins,
4833
+ activeSlot: nodeContext.activeSlot
4533
4834
  });
4534
4835
  state.nodes.set(id, {
4535
- ...semanticBase(state, node, id, kind, path, material),
4836
+ ...semanticBase(state, node, id, kind, path, material, nodeContext),
4536
4837
  kind,
4537
4838
  children: childIds
4538
4839
  });
@@ -4541,6 +4842,25 @@ function buildNode(state, node, context, index) {
4541
4842
  kind
4542
4843
  };
4543
4844
  }
4845
+ function rootSource() {
4846
+ return { kind: "root" };
4847
+ }
4848
+ function asComposedRoot(root, index) {
4849
+ if (root.kind !== "element") throw new Error("Semantic graph roots must be element nodes.");
4850
+ return {
4851
+ root,
4852
+ source: rootSource(),
4853
+ sourceIdentityMaterial: ["source", "root"],
4854
+ path: `document > slideFactory[${index}]`,
4855
+ composition: {
4856
+ slideIndex: index,
4857
+ totalSlides: 0,
4858
+ deckSlideIndex: index,
4859
+ deckTotalSlides: 0
4860
+ },
4861
+ slotOrigins: /* @__PURE__ */ new WeakMap()
4862
+ };
4863
+ }
4544
4864
  function buildSemanticAuthorGraph(roots) {
4545
4865
  const documentId = graphNodeId(["document", "root"]);
4546
4866
  const state = {
@@ -4549,20 +4869,33 @@ function buildSemanticAuthorGraph(roots) {
4549
4869
  assets: /* @__PURE__ */ new Map(),
4550
4870
  diagnostics: []
4551
4871
  };
4872
+ const slideIds = [];
4873
+ roots.forEach((root, index) => {
4874
+ const composed = "root" in root ? root : asComposedRoot(root, index);
4875
+ const built = buildNode(state, composed.root, {
4876
+ parentId: documentId,
4877
+ parentMaterial: [
4878
+ "document",
4879
+ "root",
4880
+ ...composed.sourceIdentityMaterial
4881
+ ],
4882
+ path: composed.path,
4883
+ inline: false,
4884
+ source: composed.source,
4885
+ slotOrigins: composed.slotOrigins
4886
+ }, composed.composition.slideIndex);
4887
+ if (built) slideIds.push(built.id);
4888
+ });
4552
4889
  const documentNode = {
4553
4890
  id: documentId,
4554
4891
  kind: "document",
4555
4892
  origin: {
4556
4893
  kind: "implicit",
4557
- path: "document"
4894
+ path: "document",
4895
+ source: rootSource()
4558
4896
  },
4559
4897
  role: { kind: "document" },
4560
- children: buildChildren(state, roots, {
4561
- parentId: documentId,
4562
- parentMaterial: ["document", "root"],
4563
- path: "document",
4564
- inline: false
4565
- })
4898
+ children: slideIds
4566
4899
  };
4567
4900
  state.nodes.set(documentId, documentNode);
4568
4901
  const diagnostics = createDiagnostics(state.diagnostics);
@@ -15702,78 +16035,105 @@ async function outputPresentation(presentation, config) {
15702
16035
  }
15703
16036
  //#endregion
15704
16037
  //#region src/deck.ts
15705
- function isSlideRoot(value) {
15706
- return value.kind === "element" && value.source.kind === "component" && value.source.component === "Slide";
15707
- }
15708
- function describeInvalidRoot(value) {
15709
- if (isLegacyAuthorNode(value)) return "Slide factory returned a legacy author node.";
15710
- if (isAuthorTreeNode(value)) return "Slide factory returned an author tree node that is not a <Slide /> root.";
15711
- if (value === null) return "Slide factory returned null.";
15712
- return `Slide factory returned ${typeof value}.`;
15713
- }
15714
- function invalidRootSourceSpan(value) {
15715
- return isAuthorTreeNode(value) ? value.sourceSpan : void 0;
15716
- }
15717
- function invalidRootDiagnostic(value, slideIndex) {
15718
- const path = `document > slideFactory[${slideIndex}]`;
15719
- return diagnostic({
15720
- severity: "error",
15721
- code: "E_COMPILE_ROOT",
15722
- title: "slide factory must return a <Slide /> root",
15723
- message: describeInvalidRoot(value),
15724
- labels: [{
15725
- path,
15726
- message: "Expected a deckjsx Author Tree <Slide /> node.",
15727
- ...invalidRootSourceSpan(value) ? { sourceSpan: invalidRootSourceSpan(value) } : {}
15728
- }],
15729
- help: ["Return <Slide>...</Slide> from the slide factory passed to deck.add()."]
15730
- });
15731
- }
16038
+ function hasMountedSources(entries) {
16039
+ return entries.some((entry) => entry.kind === "mount");
16040
+ }
16041
+ function directSlideFactories(entries) {
16042
+ return entries.flatMap((entry) => entry.kind === "slide" ? [entry.factory] : []);
16043
+ }
16044
+ function mountedSourceError() {
16045
+ return /* @__PURE__ */ new Error("Mounted sources are supported by compile() only until the output pipeline supports graph composition.");
16046
+ }
16047
+ function compileSource(source, config = {}) {
16048
+ const composition = resolveComposition(source);
16049
+ if (composition.diagnostics.hasErrors) {
16050
+ if (config.mode === "inspect") return { diagnostics: composition.diagnostics };
16051
+ throw new CompositionDiagnosticError(composition.diagnostics);
16052
+ }
16053
+ const result = buildSemanticAuthorGraph(composition.roots ?? []);
16054
+ if (config.mode === "inspect") return result;
16055
+ if (result.diagnostics.hasErrors) throw new SemanticGraphDiagnosticError(result.diagnostics);
16056
+ if (!result.graph) throw new SemanticGraphDiagnosticError(result.diagnostics);
16057
+ return result.graph;
16058
+ }
16059
+ var BoundSource = class {
16060
+ #source;
16061
+ #sourceContext;
16062
+ constructor(source, sourceContext) {
16063
+ this.#source = source;
16064
+ this.#sourceContext = sourceContext;
16065
+ }
16066
+ [COMPOSITION_SOURCE]() {
16067
+ const source = this.#source[COMPOSITION_SOURCE]();
16068
+ return {
16069
+ entries: source.entries,
16070
+ cycleId: source.cycleId,
16071
+ boundContext: {
16072
+ present: true,
16073
+ value: this.#sourceContext
16074
+ }
16075
+ };
16076
+ }
16077
+ compile(config = {}) {
16078
+ return compileSource(this, config);
16079
+ }
16080
+ render() {
16081
+ const source = this.#source[COMPOSITION_SOURCE]();
16082
+ if (hasMountedSources(source.entries)) throw mountedSourceError();
16083
+ return renderPresentation(this.#source.options, directSlideFactories(source.entries).map((factory) => (input) => factory({
16084
+ ...input,
16085
+ context: this.#sourceContext
16086
+ })));
16087
+ }
16088
+ async output(config) {
16089
+ await outputPresentation(this.render(), config);
16090
+ }
16091
+ };
15732
16092
  var Deck = class {
15733
16093
  #options;
15734
- #slides = [];
16094
+ #entries = [];
16095
+ withSource;
15735
16096
  constructor(options) {
15736
16097
  this.#options = options;
16098
+ this.withSource = ((sourceContext) => new BoundSource(this, sourceContext));
16099
+ }
16100
+ get options() {
16101
+ return this.#options;
16102
+ }
16103
+ [COMPOSITION_SOURCE]() {
16104
+ return {
16105
+ entries: this.#entries,
16106
+ cycleId: this,
16107
+ boundContext: { present: false }
16108
+ };
15737
16109
  }
15738
16110
  add(slide) {
15739
- this.#slides.push(slide);
16111
+ this.#entries.push({
16112
+ kind: "slide",
16113
+ factory: slide
16114
+ });
16115
+ return this;
16116
+ }
16117
+ mount(sourceKey, child, ...context) {
16118
+ this.#entries.push({
16119
+ kind: "mount",
16120
+ sourceKey,
16121
+ source: child,
16122
+ ...context.length > 0 ? { contextProvider: context[0] } : {},
16123
+ ...child instanceof BoundSource && context.length > 0 ? { invalidExtraContext: true } : {}
16124
+ });
15740
16125
  return this;
15741
16126
  }
15742
16127
  render() {
15743
- return renderPresentation(this.#options, this.#slides);
16128
+ if (hasMountedSources(this.#entries)) throw mountedSourceError();
16129
+ return renderPresentation(this.#options, directSlideFactories(this.#entries));
15744
16130
  }
15745
16131
  compile(config = {}) {
15746
- const roots = [];
15747
- const diagnostics = [];
15748
- this.#slides.forEach((factory, slideIndex) => {
15749
- const root = factory({
15750
- slideIndex,
15751
- totalSlides: this.#slides.length,
15752
- context: {
15753
- slideIndex,
15754
- totalSlides: this.#slides.length
15755
- }
15756
- });
15757
- if (!isAuthorTreeNode(root) || !isSlideRoot(root)) {
15758
- diagnostics.push(invalidRootDiagnostic(root, slideIndex));
15759
- return;
15760
- }
15761
- roots.push(root);
15762
- });
15763
- if (diagnostics.length > 0) {
15764
- const result = { diagnostics: createDiagnostics(diagnostics) };
15765
- if (config.mode === "inspect") return result;
15766
- throw new SemanticGraphDiagnosticError(result.diagnostics);
15767
- }
15768
- const result = buildSemanticAuthorGraph(roots);
15769
- if (config.mode === "inspect") return result;
15770
- if (result.diagnostics.hasErrors) throw new SemanticGraphDiagnosticError(result.diagnostics);
15771
- if (!result.graph) throw new SemanticGraphDiagnosticError(result.diagnostics);
15772
- return result.graph;
16132
+ return compileSource(this, config);
15773
16133
  }
15774
16134
  async output(config) {
15775
16135
  await outputPresentation(this.render(), config);
15776
16136
  }
15777
16137
  };
15778
16138
  //#endregion
15779
- export { Deck, DeckDiagnosticError, EMU_PER_INCH, Fragment, Image, POINTS_PER_INCH, SemanticGraphDiagnosticError, Shape, Slide, Text, View, createElement, formatDiagnostic, formatDiagnostics, isAuthorNode, isContentNode, isSlideNode, pptxgenjsBackend };
16139
+ export { CompositionDiagnosticError, Deck, DeckDiagnosticError, EMU_PER_INCH, Fragment, Image, POINTS_PER_INCH, SemanticGraphDiagnosticError, Shape, Slide, Text, View, createElement, formatDiagnostic, formatDiagnostics, isAuthorNode, isContentNode, isSlideNode, pptxgenjsBackend };
@@ -1,4 +1,4 @@
1
- import { Mt as JsxKey, i as Fragment, jt as AuthorTreeNode, n as jsx, r as jsxs, t as JSX } from "./jsx-runtime-ru5t8S3z.mjs";
1
+ import { fn as AuthorTreeNode, i as Fragment, n as jsx, pn as JsxKey, r as jsxs, t as JSX } from "./jsx-runtime-DauuRkY2.mjs";
2
2
 
3
3
  //#region src/jsx-dev-runtime.d.ts
4
4
  declare function jsxDEV(type: unknown, props: unknown, key?: JsxKey, _isStaticChildren?: boolean, source?: unknown): AuthorTreeNode;
@@ -44,6 +44,207 @@ type AuthorTextLeaf = {
44
44
  type AuthorTreeNode = AuthorElementNode | AuthorFragmentNode | AuthorTextLeaf;
45
45
  type AuthorTreeChild = AuthorTreeNode | string | number | boolean | null | undefined | readonly AuthorTreeChild[];
46
46
  //#endregion
47
+ //#region src/diagnostics/errors.d.ts
48
+ declare class DeckDiagnosticError extends Error {
49
+ readonly diagnostics: Diagnostics;
50
+ constructor(message: string, diagnostics: Diagnostics);
51
+ }
52
+ declare class SemanticGraphDiagnosticError extends DeckDiagnosticError {
53
+ constructor(diagnostics: Diagnostics);
54
+ }
55
+ declare class CompositionDiagnosticError extends DeckDiagnosticError {
56
+ constructor(diagnostics: Diagnostics);
57
+ }
58
+ //#endregion
59
+ //#region src/diagnostics/format.d.ts
60
+ declare function formatDiagnostic(diagnostic: Diagnostic): string;
61
+ declare function formatDiagnostics(diagnostics: Diagnostics): string;
62
+ //#endregion
63
+ //#region src/diagnostics/index.d.ts
64
+ type DiagnosticSeverity = "error" | "warning";
65
+ type DiagnosticLabel = {
66
+ readonly message: string;
67
+ readonly path: string;
68
+ readonly sourceSpan?: SourceSpan;
69
+ readonly severity?: "primary" | "secondary";
70
+ };
71
+ type Diagnostic = {
72
+ readonly severity: DiagnosticSeverity;
73
+ readonly code: string;
74
+ readonly title: string;
75
+ readonly message?: string;
76
+ readonly labels: readonly DiagnosticLabel[];
77
+ readonly notes?: readonly string[];
78
+ readonly help?: readonly string[];
79
+ };
80
+ type Diagnostics = {
81
+ readonly items: readonly Diagnostic[];
82
+ readonly hasErrors: boolean;
83
+ readonly hasWarnings: boolean;
84
+ };
85
+ //#endregion
86
+ //#region src/graph/types.d.ts
87
+ type Brand<T, B extends string> = T & {
88
+ readonly __brand: B;
89
+ };
90
+ type GraphNodeId = Brand<string, "GraphNodeId">;
91
+ type StyleEntityId = Brand<string, "StyleEntityId">;
92
+ type AssetEntityId = Brand<string, "AssetEntityId">;
93
+ type SourceIdentity = Brand<string, "SourceIdentity">;
94
+ type SemanticNodeKind = "container" | "document" | "image" | "shape" | "slide" | "text" | "textRun";
95
+ type SemanticRole = {
96
+ readonly kind: "document";
97
+ } | {
98
+ readonly kind: "slide";
99
+ } | {
100
+ readonly kind: "genericContainer";
101
+ } | {
102
+ readonly kind: "sectioning";
103
+ readonly tag: SectioningTag;
104
+ } | {
105
+ readonly kind: "figure";
106
+ } | {
107
+ readonly kind: "paragraph";
108
+ } | {
109
+ readonly kind: "heading";
110
+ readonly level: 1 | 2 | 3 | 4 | 5 | 6;
111
+ } | {
112
+ readonly kind: "image";
113
+ } | {
114
+ readonly kind: "shape";
115
+ };
116
+ type SourceOrigin = {
117
+ readonly kind: "root";
118
+ } | {
119
+ readonly kind: "mounted";
120
+ readonly sourceKey: string;
121
+ readonly sourceIdentity: SourceIdentity;
122
+ };
123
+ type SemanticOrigin = {
124
+ readonly kind: "authored" | "implicit";
125
+ readonly path: string;
126
+ readonly source?: SourceOrigin;
127
+ readonly sourceSpan?: SourceSpan;
128
+ readonly reason?: "primitive-text-in-container";
129
+ };
130
+ type BaseSemanticNode = {
131
+ readonly id: GraphNodeId;
132
+ readonly kind: SemanticNodeKind;
133
+ readonly origin: SemanticOrigin;
134
+ readonly authoredTag?: AuthoredTag;
135
+ readonly authoredComponent?: AuthoredComponent;
136
+ readonly role?: SemanticRole;
137
+ readonly key?: JsxKey;
138
+ readonly styleRef?: StyleEntityId;
139
+ };
140
+ type SemanticDocumentNode = BaseSemanticNode & {
141
+ readonly kind: "document";
142
+ readonly children: readonly GraphNodeId[];
143
+ };
144
+ type SemanticSlideNode = BaseSemanticNode & {
145
+ readonly kind: "slide";
146
+ readonly name?: string;
147
+ readonly children: readonly GraphNodeId[];
148
+ };
149
+ type SemanticContainerNode = BaseSemanticNode & {
150
+ readonly kind: "container";
151
+ readonly children: readonly GraphNodeId[];
152
+ };
153
+ type SemanticTextNode = BaseSemanticNode & {
154
+ readonly kind: "text";
155
+ readonly inlineChildren: readonly GraphNodeId[];
156
+ readonly implicit?: boolean;
157
+ };
158
+ type SemanticTextRunNode = BaseSemanticNode & {
159
+ readonly kind: "textRun";
160
+ readonly text: string;
161
+ };
162
+ type SemanticImageNode = BaseSemanticNode & {
163
+ readonly kind: "image";
164
+ readonly assetRef?: AssetEntityId;
165
+ };
166
+ type SemanticShapeNode = BaseSemanticNode & {
167
+ readonly kind: "shape";
168
+ };
169
+ type SemanticNode = SemanticContainerNode | SemanticDocumentNode | SemanticImageNode | SemanticShapeNode | SemanticSlideNode | SemanticTextNode | SemanticTextRunNode;
170
+ type StyleEntity = {
171
+ readonly id: StyleEntityId;
172
+ readonly target: SemanticNodeKind;
173
+ readonly authored: {
174
+ readonly style?: unknown;
175
+ readonly direct?: unknown;
176
+ };
177
+ readonly resolved?: unknown;
178
+ };
179
+ type AssetEntity = {
180
+ readonly id: AssetEntityId;
181
+ readonly kind: "image";
182
+ readonly source: {
183
+ readonly kind: "path";
184
+ readonly path: string;
185
+ } | {
186
+ readonly kind: "data";
187
+ readonly data: string;
188
+ };
189
+ readonly metadata: {
190
+ readonly mediaType?: string;
191
+ readonly byteLength?: number;
192
+ readonly widthPx?: number;
193
+ readonly heightPx?: number;
194
+ readonly contentHash?: string;
195
+ };
196
+ readonly resolution: "failed" | "resolved" | "unresolved";
197
+ };
198
+ type SemanticAuthorGraph = {
199
+ readonly documentId: GraphNodeId;
200
+ readonly nodes: ReadonlyMap<GraphNodeId, SemanticNode>;
201
+ readonly styles: ReadonlyMap<StyleEntityId, StyleEntity>;
202
+ readonly assets: ReadonlyMap<AssetEntityId, AssetEntity>;
203
+ };
204
+ //#endregion
205
+ //#region src/composition/types.d.ts
206
+ declare const COMPOSITION_SOURCE: unique symbol;
207
+ type CompositionContext = {
208
+ readonly sourceKey?: string;
209
+ readonly slideIndex: number;
210
+ readonly totalSlides: number;
211
+ readonly deckSlideIndex: number;
212
+ readonly deckTotalSlides: number;
213
+ };
214
+ type SlideFactoryInput<TSourceContext = void> = [TSourceContext] extends [void] ? {
215
+ readonly composition: CompositionContext;
216
+ } : {
217
+ readonly context: TSourceContext;
218
+ readonly composition: CompositionContext;
219
+ };
220
+ type SlideFactory<TSourceContext = void> = (input: SlideFactoryInput<TSourceContext>) => JsxNode;
221
+ type SourceContextMapper<TParentContext, TChildContext> = [TParentContext] extends [void] ? () => TChildContext : (context: TParentContext) => TChildContext;
222
+ type SourceContextInput<TParentContext, TChildContext> = TChildContext | SourceContextMapper<TParentContext, TChildContext>;
223
+ type SourceContextBinding<TSourceContext = unknown> = {
224
+ readonly present: false;
225
+ } | {
226
+ readonly present: true;
227
+ readonly value: TSourceContext;
228
+ };
229
+ type CompositionEntry<TSourceContext = unknown> = {
230
+ readonly kind: "slide";
231
+ readonly factory: SlideFactory<TSourceContext>;
232
+ } | {
233
+ readonly kind: "mount";
234
+ readonly sourceKey: string;
235
+ readonly source: CompositionSource<unknown>;
236
+ readonly contextProvider?: SourceContextInput<TSourceContext, unknown>;
237
+ readonly invalidExtraContext?: boolean;
238
+ };
239
+ type CompositionSourceInternals<TSourceContext = unknown> = {
240
+ readonly entries: readonly CompositionEntry<TSourceContext>[];
241
+ readonly cycleId: object;
242
+ readonly boundContext: SourceContextBinding<TSourceContext>;
243
+ };
244
+ type CompositionSource<TSourceContext = unknown> = {
245
+ readonly [COMPOSITION_SOURCE]: () => CompositionSourceInternals<TSourceContext>;
246
+ };
247
+ //#endregion
47
248
  //#region src/authoring/index.d.ts
48
249
  type DeckLength = number | `${number}${"in" | "pt" | "px" | "%" | "em" | "rem" | "vh" | "vw" | "ch"}`;
49
250
  type DeckPointLength = number | `${number}${"pt" | "in" | "px" | "em" | "rem" | "vh" | "vw" | "ch"}`;
@@ -319,15 +520,6 @@ type DeckOptions = {
319
520
  subject?: string;
320
521
  };
321
522
  };
322
- type SlideContext = {
323
- slideIndex: number;
324
- totalSlides: number;
325
- context?: {
326
- slideIndex: number;
327
- totalSlides: number;
328
- };
329
- };
330
- type SlideFactory = (context: SlideContext) => JsxNode;
331
523
  type OutputConfig = {
332
524
  backend: ImplementedBackendName;
333
525
  output: string;
@@ -485,4 +677,4 @@ declare namespace JSX {
485
677
  }
486
678
  }
487
679
  //#endregion
488
- export { ImageStyle as $, CssFlexDirection as A, ViewStyle as At, CssJustifyContent as B, CssAlignContent as C, TextProps as Ct, CssBoxSizing as D, TextTabStopLength as Dt, CssAspectRatio as E, TextTabStopAuthoring as Et, CssGridShorthand as F, AuthoredTag as Ft, CssVisibility as G, CssObjectPosition as H, CssGridTemplate as I, SectioningTag as It, DeckOptions as J, DeckJsxIntrinsicElements as K, CssGridTemplateAreas as L, CssGridAutoFlow as M, JsxKey as Mt, CssGridLine as N, SourceSpan as Nt, CssDisplay as O, VerticalAlign as Ot, CssGridPlacement as P, AuthoredComponent as Pt, ImageProps as Q, CssGridTemplateShorthand as R, ContentJsxChild as S, TextJsxChild as St, CssAlignSelf as T, TextTabStopAlignment as Tt, CssOverflow as U, CssJustifySelf as V, CssPosition as W, ImageCropAuthoring as X, DeckPointLength as Y, ImageCropValue as Z, AuthorNodeProps as _, StackAxis as _t, createElement as a, IntrinsicViewTag as at, BorderStyle as b, StrokeLineJoin as bt, isSlideNode as c, OutputConfig as ct, Slide as d, SlideContext as dt, ImplementedBackendName as et, Text as f, SlideFactory as ft, AuthorNodeMap as g, StackAlignment as gt, AuthorNodeKind as h, Spacing as ht, Fragment as i, IntrinsicTextTag as it, CssFlexWrap as j, AuthorTreeNode as jt, CssFlexBasis as k, ViewProps as kt, Image as l, ShapeProps as lt, AuthorNode as m, SlideStyle as mt, jsx as n, IntrinsicImgProps as nt, isAuthorNode as o, JsxNode as ot, View as p, SlideProps as pt, DeckLength as q, jsxs as r, IntrinsicPProps as rt, isContentNode as s, LayoutMode as st, JSX as t, IntrinsicDivProps as tt, Shape as u, ShapeStyle as ut, AuthorNodePropsMap as v, StrokeDashType as vt, CssAlignItems as w, TextStyle as wt, ContentAuthorNode as x, TextFit as xt, BackendName as y, StrokeLineCap as yt, CssGridTrack as z };
680
+ export { ImageStyle as $, SourceIdentity as $t, CssFlexDirection as A, CompositionContext as At, CssJustifyContent as B, GraphNodeId as Bt, CssAlignContent as C, TextTabStopAlignment as Ct, CssBoxSizing as D, ViewProps as Dt, CssAspectRatio as E, VerticalAlign as Et, CssGridShorthand as F, SourceContextInput as Ft, CssVisibility as G, SemanticNode as Gt, CssObjectPosition as H, SemanticContainerNode as Ht, CssGridTemplate as I, SourceContextMapper as It, DeckOptions as J, SemanticRole as Jt, DeckJsxIntrinsicElements as K, SemanticNodeKind as Kt, CssGridTemplateAreas as L, AssetEntity as Lt, CssGridAutoFlow as M, CompositionSourceInternals as Mt, CssGridLine as N, SlideFactory as Nt, CssDisplay as O, ViewStyle as Ot, CssGridPlacement as P, SlideFactoryInput as Pt, ImageProps as Q, SemanticTextRunNode as Qt, CssGridTemplateShorthand as R, AssetEntityId as Rt, ContentJsxChild as S, TextStyle as St, CssAlignSelf as T, TextTabStopLength as Tt, CssOverflow as U, SemanticDocumentNode as Ut, CssJustifySelf as V, SemanticAuthorGraph as Vt, CssPosition as W, SemanticImageNode as Wt, ImageCropAuthoring as X, SemanticSlideNode as Xt, DeckPointLength as Y, SemanticShapeNode as Yt, ImageCropValue as Z, SemanticTextNode as Zt, AuthorNodeProps as _, StrokeLineCap as _t, createElement as a, DiagnosticSeverity as an, IntrinsicViewTag as at, BorderStyle as b, TextJsxChild as bt, isSlideNode as c, formatDiagnostics as cn, OutputConfig as ct, Slide as d, SemanticGraphDiagnosticError as dn, SlideProps as dt, SourceOrigin as en, ImplementedBackendName as et, Text as f, AuthorTreeNode as fn, SlideStyle as ft, AuthorNodeMap as g, StrokeDashType as gt, AuthorNodeKind as h, StackAxis as ht, Fragment as i, DiagnosticLabel as in, IntrinsicTextTag as it, CssFlexWrap as j, CompositionSource as jt, CssFlexBasis as k, COMPOSITION_SOURCE as kt, Image as l, CompositionDiagnosticError as ln, ShapeProps as lt, AuthorNode as m, SourceSpan as mn, StackAlignment as mt, jsx as n, StyleEntityId as nn, IntrinsicImgProps as nt, isAuthorNode as o, Diagnostics as on, JsxNode as ot, View as p, JsxKey as pn, Spacing as pt, DeckLength as q, SemanticOrigin as qt, jsxs as r, Diagnostic as rn, IntrinsicPProps as rt, isContentNode as s, formatDiagnostic as sn, LayoutMode as st, JSX as t, StyleEntity as tn, IntrinsicDivProps as tt, Shape as u, DeckDiagnosticError as un, ShapeStyle as ut, AuthorNodePropsMap as v, StrokeLineJoin as vt, CssAlignItems as w, TextTabStopAuthoring as wt, ContentAuthorNode as x, TextProps as xt, BackendName as y, TextFit as yt, CssGridTrack as z, BaseSemanticNode as zt };
@@ -1,2 +1,2 @@
1
- import { Mt as JsxKey, i as Fragment, n as jsx, r as jsxs, t as JSX } from "./jsx-runtime-ru5t8S3z.mjs";
1
+ import { i as Fragment, n as jsx, pn as JsxKey, r as jsxs, t as JSX } from "./jsx-runtime-DauuRkY2.mjs";
2
2
  export { Fragment, JSX, JsxKey, jsx, jsxs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deckjsx",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Generate PowerPoint presentations from TSX/JSX through a compiler pipeline.",
5
5
  "license": "MIT",
6
6
  "author": "deckjsx contributors",