deckjsx 0.5.0 → 0.6.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
@@ -7,18 +7,19 @@ The intended architecture is:
7
7
 
8
8
  ```text
9
9
  JSX
10
- -> Presentation IR
11
- -> Backend
12
- |- PptxGenJS backend
13
- `- OOXML direct backend (future)
10
+ -> Author Tree
11
+ -> Semantic Author Graph
12
+ -> Output Projection
13
+ -> Output Writer
14
14
  ```
15
15
 
16
16
  This project is being designed as a compiler, not as a thin `PptxGenJS` wrapper.
17
- The API uses a class-based compiler with callback-based `.add()`, `.render()`, and `.output()`.
18
- Authoring uses typed JSX elements with a `style` object prop.
17
+ The API uses a class-based compiler with callback-based `.add()`, `.compile()`, `.project()`, and
18
+ `.render()`. Authoring uses typed JSX elements with CSS-like style and class semantics.
19
19
 
20
20
  The implementation preserves the compiler model with explicit module boundaries for authoring,
21
- style normalization, layout, IR, backend emission, and Node runtime output.
21
+ semantic graph construction, style resolution, output projection, writer adapters, and runtime
22
+ output.
22
23
 
23
24
  ## Install
24
25
 
@@ -26,7 +27,7 @@ style normalization, layout, IR, backend emission, and Node runtime output.
26
27
  npm install deckjsx
27
28
  ```
28
29
 
29
- The package currently targets Node.js output and ships a `pptxgenjs` backend.
30
+ The package currently targets PPTX output and ships a temporary `pptxgenjs` writer adapter.
30
31
 
31
32
  ## Usage
32
33
 
@@ -59,8 +60,7 @@ deck.add(({ composition }) => (
59
60
 
60
61
  <section style={{ display: "grid", gridTemplateColumns: "1fr 1fr", columnGap: 0.35 }}>
61
62
  <p style={{ fontSize: 18, color: "#334155", fit: "shrink" }}>
62
- Author slides with typed JSX, inspect the generated IR, and emit PPTX files through the
63
- backend boundary.
63
+ Author slides with typed JSX, inspect the projected document model, and render PPTX files.
64
64
  </p>
65
65
  <figure style={{ backgroundColor: "#E0F2FE", borderRadius: 0.15, padding: 0.25 }}>
66
66
  <img src="chart.png" style={{ width: "100%", height: "100%", fit: "contain" }} />
@@ -78,12 +78,12 @@ deck.add(({ composition }) => (
78
78
  </Slide>
79
79
  ));
80
80
 
81
- const ir = deck.render();
82
- await deck.output({ backend: "pptxgenjs", output: "quarterly-review.pptx" });
81
+ const project = deck.project();
82
+ await deck.render({ output: "quarterly-review.pptx" });
83
83
  ```
84
84
 
85
- Use `deck.render()` for tests, snapshots, and backend-independent inspection. Use
86
- `deck.output({ backend: "pptxgenjs", output })` when writing a PowerPoint file.
85
+ Use `deck.compile()` for authoring semantics, `deck.project()` for output-facing inspection, and
86
+ `deck.render({ output })` when writing a PowerPoint file.
87
87
 
88
88
  ## JSX elements
89
89
 
@@ -118,7 +118,13 @@ Image elements compile to images and require either `src` or `data`:
118
118
  ```
119
119
 
120
120
  Primitive string and number children inside view-like elements are normalized to implicit text
121
- nodes. Inline rich text with `span` is intentionally reserved for a later release.
121
+ nodes. Inline rich text uses `span` inside text-like elements:
122
+
123
+ ```tsx
124
+ <p>
125
+ Revenue grew <span style={{ color: "#16A34A", fontWeight: 700 }}>12%</span>.
126
+ </p>
127
+ ```
122
128
 
123
129
  ## View Layout Semantics
124
130
 
@@ -25,9 +25,64 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
  }) : target, mod));
26
26
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
27
27
  //#endregion
28
- //#region src/types.ts
29
- const EMU_PER_INCH = 914400;
30
- const POINTS_PER_INCH = 72;
28
+ //#region src/diagnostics/format.ts
29
+ function formatSpan(path) {
30
+ return ` at ${path}`;
31
+ }
32
+ function formatDiagnostic(diagnostic) {
33
+ const lines = [`${diagnostic.severity}[${diagnostic.code}]: ${diagnostic.title}`];
34
+ if (diagnostic.message) lines.push(` ${diagnostic.message}`);
35
+ for (const label of diagnostic.labels) {
36
+ lines.push(formatSpan(label.path));
37
+ lines.push(` = ${label.message}`);
38
+ }
39
+ for (const note of diagnostic.notes ?? []) lines.push(`note: ${note}`);
40
+ for (const help of diagnostic.help ?? []) lines.push(`help: ${help}`);
41
+ return lines.join("\n");
42
+ }
43
+ function formatDiagnostics(diagnostics) {
44
+ return diagnostics.items.map((item) => formatDiagnostic(item)).join("\n\n");
45
+ }
46
+ //#endregion
47
+ //#region src/diagnostics/errors.ts
48
+ var DeckDiagnosticError = class extends Error {
49
+ diagnostics;
50
+ constructor(message, diagnostics) {
51
+ super(message);
52
+ this.name = "DeckDiagnosticError";
53
+ this.diagnostics = diagnostics;
54
+ }
55
+ };
56
+ var SemanticGraphDiagnosticError = class extends DeckDiagnosticError {
57
+ constructor(diagnostics) {
58
+ super(formatDiagnostics(diagnostics), diagnostics);
59
+ this.name = "SemanticGraphDiagnosticError";
60
+ }
61
+ };
62
+ var CompositionDiagnosticError = class extends DeckDiagnosticError {
63
+ constructor(diagnostics) {
64
+ super(formatDiagnostics(diagnostics), diagnostics);
65
+ this.name = "CompositionDiagnosticError";
66
+ }
67
+ };
68
+ var StyleDiagnosticError = class extends DeckDiagnosticError {
69
+ constructor(diagnostics) {
70
+ super(formatDiagnostics(diagnostics), diagnostics);
71
+ this.name = "StyleDiagnosticError";
72
+ }
73
+ };
74
+ //#endregion
75
+ //#region src/diagnostics/index.ts
76
+ function createDiagnostics(items = []) {
77
+ return {
78
+ items,
79
+ hasErrors: items.some((item) => item.severity === "error"),
80
+ hasWarnings: items.some((item) => item.severity === "warning")
81
+ };
82
+ }
83
+ function diagnostic(input) {
84
+ return input;
85
+ }
31
86
  //#endregion
32
87
  //#region node_modules/inherits/inherits_browser.js
33
88
  var require_inherits_browser = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -10314,9 +10369,13 @@ var require_lib = /* @__PURE__ */ __commonJSMin(((exports, module) => {
10314
10369
  module.exports = JSZip;
10315
10370
  }));
10316
10371
  //#endregion
10317
- //#region src/backends/pptxgenjs-xml-patches.ts
10372
+ //#region src/types.ts
10318
10373
  var import_dist = require_dist();
10319
10374
  var import_lib = /* @__PURE__ */ __toESM(require_lib(), 1);
10375
+ const EMU_PER_INCH = 914400;
10376
+ const POINTS_PER_INCH = 72;
10377
+ //#endregion
10378
+ //#region src/writers/pptxgenjs-xml-patches.ts
10320
10379
  function emuToInches$1(value) {
10321
10380
  return value / EMU_PER_INCH;
10322
10381
  }
@@ -10717,14 +10776,15 @@ function patchSlideBlocks(xml, patch) {
10717
10776
  }
10718
10777
  return patchedXml;
10719
10778
  }
10720
- function buildSlideXmlPatchPlan(slideIR) {
10721
- const images = [...collectBackgroundLayerImages(slideIR.backgroundLayers), ...collectRenderableImages(slideIR.nodes)];
10722
- const texts = collectRenderableTextNodes(slideIR.nodes);
10779
+ function buildSlideXmlPatchPlan(slidePart) {
10780
+ const slide = slidePart.payload;
10781
+ const images = [...collectBackgroundLayerImages(slide.backgroundLayers), ...collectRenderableImages(slide.elements)];
10782
+ const texts = collectRenderableTextNodes(slide.elements);
10723
10783
  return {
10724
10784
  pictureSrcRects: images.map((image) => resolveImageSrcRect(image)),
10725
- shapeFills: [...slideIR.backgroundLayers?.map((layer) => buildBackgroundLayerFillXml(layer)) ?? [], ...collectShapeFillPatches(slideIR.nodes)],
10726
- shapeLines: collectShapeLinePatches(slideIR.nodes),
10727
- slideBackgroundFill: buildGradientFillXml(slideIR.background),
10785
+ shapeFills: [...slide.backgroundLayers?.map((layer) => buildBackgroundLayerFillXml(layer)) ?? [], ...collectShapeFillPatches(slide.elements)],
10786
+ shapeLines: collectShapeLinePatches(slide.elements),
10787
+ slideBackgroundFill: buildGradientFillXml(slide.background),
10728
10788
  textIndentsEmu: texts.map((text) => text.style.textIndentPt === void 0 ? void 0 : pointsToEmu$1(text.style.textIndentPt))
10729
10789
  };
10730
10790
  }
@@ -10765,10 +10825,10 @@ function applySlideXmlPatchPlan(slideXml, plan) {
10765
10825
  }
10766
10826
  });
10767
10827
  }
10768
- async function patchPresentationXml(data, ir) {
10828
+ async function patchPresentationXml(data, projection) {
10769
10829
  const zip = await import_lib.default.loadAsync(data);
10770
- for (const [slideIndex, slideIR] of ir.slides.entries()) {
10771
- const patchPlan = buildSlideXmlPatchPlan(slideIR);
10830
+ for (const [slideIndex, slide] of projection.slides.entries()) {
10831
+ const patchPlan = buildSlideXmlPatchPlan(slide);
10772
10832
  if (!hasSlideXmlPatchPlan(patchPlan)) continue;
10773
10833
  const slidePath = `ppt/slides/slide${slideIndex + 1}.xml`;
10774
10834
  const slideFile = zip.file(slidePath);
@@ -10779,7 +10839,8 @@ async function patchPresentationXml(data, ir) {
10779
10839
  return zip.generateAsync({ type: "uint8array" });
10780
10840
  }
10781
10841
  //#endregion
10782
- //#region src/backends/pptxgenjs.ts
10842
+ //#region src/writers/pptxgenjs.ts
10843
+ const PPTX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
10783
10844
  const TRANSPARENT_FILL = {
10784
10845
  color: "FFFFFF",
10785
10846
  transparency: 100
@@ -10789,7 +10850,6 @@ const TRANSPARENT_LINE = {
10789
10850
  transparency: 100,
10790
10851
  width: 0
10791
10852
  };
10792
- const PPTX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
10793
10853
  function resolvePptxGenJSConstructor(moduleValue) {
10794
10854
  if (typeof moduleValue === "function") return moduleValue;
10795
10855
  if (typeof moduleValue === "object" && moduleValue !== null && "default" in moduleValue) {
@@ -10799,6 +10859,11 @@ function resolvePptxGenJSConstructor(moduleValue) {
10799
10859
  throw new Error("Unable to resolve PptxGenJS constructor.");
10800
10860
  }
10801
10861
  const PptxGenJS = resolvePptxGenJSConstructor(PptxGenJSModule);
10862
+ function normalizeBuffer(data) {
10863
+ if (data instanceof Uint8Array) return data;
10864
+ if (data instanceof ArrayBuffer) return new Uint8Array(data);
10865
+ throw new Error("Unsupported PptxGenJS output type received.");
10866
+ }
10802
10867
  function emuToInches(value) {
10803
10868
  return value / EMU_PER_INCH;
10804
10869
  }
@@ -10814,14 +10879,6 @@ function combineTransparency(transparency, opacity) {
10814
10879
  function combineOpacities(parentOpacity, nodeOpacity) {
10815
10880
  return (parentOpacity ?? 1) * (nodeOpacity ?? 1);
10816
10881
  }
10817
- function normalizeBuffer(data) {
10818
- if (data instanceof Uint8Array) return data;
10819
- if (data instanceof ArrayBuffer) return new Uint8Array(data);
10820
- throw new Error("Unsupported PptxGenJS output type received.");
10821
- }
10822
- function assertNever(value) {
10823
- throw new Error(`Unhandled PptxGenJS backend value: ${String(value)}`);
10824
- }
10825
10882
  function mapShapeName(shape, radiusEmu) {
10826
10883
  if (shape === "rect") return radiusEmu && radiusEmu > 0 ? "roundRect" : "rect";
10827
10884
  if (shape === "ellipse") return "ellipse";
@@ -10829,15 +10886,11 @@ function mapShapeName(shape, radiusEmu) {
10829
10886
  }
10830
10887
  function toPptxFill(fill, opacity) {
10831
10888
  if (!fill) return;
10832
- switch (fill.kind) {
10833
- case "solid": return {
10834
- color: fill.color,
10835
- transparency: combineTransparency(fill.transparency, opacity)
10836
- };
10837
- case "linear-gradient":
10838
- case "radial-gradient": return TRANSPARENT_FILL;
10839
- default: return assertNever(fill);
10840
- }
10889
+ if (fill.kind !== "solid") return TRANSPARENT_FILL;
10890
+ return {
10891
+ color: fill.color,
10892
+ transparency: combineTransparency(fill.transparency, opacity)
10893
+ };
10841
10894
  }
10842
10895
  function toPptxLine(stroke, opacity) {
10843
10896
  if (!stroke) return;
@@ -10859,6 +10912,14 @@ function toPptxShadow(shadow, opacity) {
10859
10912
  angle: shadow.angle
10860
10913
  };
10861
10914
  }
10915
+ function toPptxUnderline(style) {
10916
+ if (!style.underline && !style.underlineStyle && !style.underlineColor) return;
10917
+ if (!style.underlineStyle && !style.underlineColor) return style.underline;
10918
+ return {
10919
+ ...style.underlineStyle ? { style: style.underlineStyle } : {},
10920
+ ...style.underlineColor ? { color: style.underlineColor } : {}
10921
+ };
10922
+ }
10862
10923
  function toPptxBullet(list) {
10863
10924
  if (!list) return;
10864
10925
  if (list.type === "none") return false;
@@ -10876,21 +10937,6 @@ function toPptxBullet(list) {
10876
10937
  ...list.indentPt !== void 0 ? { indent: list.indentPt } : {}
10877
10938
  };
10878
10939
  }
10879
- function toPptxUnderline(style) {
10880
- if (!style.underline && !style.underlineStyle && !style.underlineColor) return;
10881
- if (!style.underlineStyle && !style.underlineColor) return style.underline;
10882
- return {
10883
- ...style.underlineStyle ? { style: style.underlineStyle } : {},
10884
- ...style.underlineColor ? { color: style.underlineColor } : {}
10885
- };
10886
- }
10887
- function toPptxTabStops(tabStops) {
10888
- if (!tabStops || tabStops.length === 0) return;
10889
- return tabStops.map((tabStop) => ({
10890
- position: tabStop.positionIn,
10891
- ...tabStop.alignment ? { alignment: tabStop.alignment } : {}
10892
- }));
10893
- }
10894
10940
  function toPptxTextRunOptions(style) {
10895
10941
  if (!style) return;
10896
10942
  const options = {
@@ -10906,27 +10952,26 @@ function toPptxTextRunOptions(style) {
10906
10952
  subscript: style.subscript,
10907
10953
  breakLine: false
10908
10954
  };
10909
- if (Object.values(options).every((value) => value === void 0 || value === false)) return;
10910
- return options;
10955
+ return Object.values(options).every((value) => value === void 0 || value === false) ? void 0 : options;
10911
10956
  }
10912
- function emitOutlineShape(slide, shapeName, frame, outline, radiusEmu, effectiveOpacity, rotation, flipH, flipV) {
10913
- if (!outline) return;
10914
- const insetEmu = pointsToEmu(outline.widthPt) / 2;
10957
+ function emitOutlineShape(slide, shapeName, node, effectiveOpacity) {
10958
+ if (!node.outline) return;
10959
+ const insetEmu = pointsToEmu(node.outline.widthPt) / 2;
10915
10960
  slide.addShape(shapeName, {
10916
- x: emuToInches(frame.xEmu - insetEmu),
10917
- y: emuToInches(frame.yEmu - insetEmu),
10918
- w: emuToInches(frame.widthEmu + insetEmu * 2),
10919
- h: emuToInches(frame.heightEmu + insetEmu * 2),
10961
+ x: emuToInches(node.frame.xEmu - insetEmu),
10962
+ y: emuToInches(node.frame.yEmu - insetEmu),
10963
+ w: emuToInches(node.frame.widthEmu + insetEmu * 2),
10964
+ h: emuToInches(node.frame.heightEmu + insetEmu * 2),
10920
10965
  fill: TRANSPARENT_FILL,
10921
- line: toPptxLine(outline, effectiveOpacity),
10922
- radius: radiusEmu ? emuToInches(radiusEmu + insetEmu) : void 0,
10923
- rotate: rotation,
10924
- flipH,
10925
- flipV
10966
+ line: toPptxLine(node.outline, effectiveOpacity),
10967
+ radius: node.radiusEmu ? emuToInches(node.radiusEmu + insetEmu) : void 0,
10968
+ rotate: node.rotation,
10969
+ flipH: node.flipH,
10970
+ flipV: node.flipV
10926
10971
  });
10927
10972
  }
10928
- function emitEdgeStrokes(slide, frame, edgeStrokes, effectiveOpacity, rotation, flipH, flipV) {
10929
- if (!edgeStrokes) return;
10973
+ function emitEdgeStrokes(slide, node, effectiveOpacity) {
10974
+ if (!node.edgeStrokes) return;
10930
10975
  const emitLine = (stroke, xEmu, yEmu, widthEmu, heightEmu) => {
10931
10976
  if (!stroke) return;
10932
10977
  slide.addShape("line", {
@@ -10935,19 +10980,19 @@ function emitEdgeStrokes(slide, frame, edgeStrokes, effectiveOpacity, rotation,
10935
10980
  w: emuToInches(widthEmu),
10936
10981
  h: emuToInches(heightEmu),
10937
10982
  line: toPptxLine(stroke, effectiveOpacity),
10938
- rotate: rotation,
10939
- flipH,
10940
- flipV
10983
+ rotate: node.rotation,
10984
+ flipH: node.flipH,
10985
+ flipV: node.flipV
10941
10986
  });
10942
10987
  };
10943
- emitLine(edgeStrokes.top, frame.xEmu, frame.yEmu, frame.widthEmu, 0);
10944
- emitLine(edgeStrokes.right, frame.xEmu + frame.widthEmu, frame.yEmu, 0, frame.heightEmu);
10945
- emitLine(edgeStrokes.bottom, frame.xEmu, frame.yEmu + frame.heightEmu, frame.widthEmu, 0);
10946
- emitLine(edgeStrokes.left, frame.xEmu, frame.yEmu, 0, frame.heightEmu);
10988
+ emitLine(node.edgeStrokes.top, node.frame.xEmu, node.frame.yEmu, node.frame.widthEmu, 0);
10989
+ emitLine(node.edgeStrokes.right, node.frame.xEmu + node.frame.widthEmu, node.frame.yEmu, 0, node.frame.heightEmu);
10990
+ emitLine(node.edgeStrokes.bottom, node.frame.xEmu, node.frame.yEmu + node.frame.heightEmu, node.frame.widthEmu, 0);
10991
+ emitLine(node.edgeStrokes.left, node.frame.xEmu, node.frame.yEmu, 0, node.frame.heightEmu);
10947
10992
  }
10948
- function emitBackgroundLayers(slide, frame, backgroundLayers, shapeName, radiusEmu, effectiveOpacity, rotation, flipH, flipV) {
10949
- if (!backgroundLayers || backgroundLayers.length === 0) return;
10950
- for (const layer of backgroundLayers) {
10993
+ function emitBackgroundLayers(slide, node, shapeName, effectiveOpacity) {
10994
+ if (!node.backgroundLayers || node.backgroundLayers.length === 0) return;
10995
+ for (const layer of node.backgroundLayers) {
10951
10996
  if (isBackgroundImageLayer(layer)) {
10952
10997
  for (const tile of expandBackgroundImageLayer(layer)) slide.addImage({
10953
10998
  x: emuToInches(tile.frame.xEmu),
@@ -10957,13 +11002,13 @@ function emitBackgroundLayers(slide, frame, backgroundLayers, shapeName, radiusE
10957
11002
  path: tile.source.kind === "path" ? tile.source.path : void 0,
10958
11003
  data: tile.source.kind === "data" ? tile.source.data : void 0,
10959
11004
  transparency: combineTransparency(layer.transparency, effectiveOpacity),
10960
- rotate: rotation,
10961
- flipH,
10962
- flipV
11005
+ rotate: node.rotation,
11006
+ flipH: node.flipH,
11007
+ flipV: node.flipV
10963
11008
  });
10964
11009
  continue;
10965
11010
  }
10966
- const layerFrame = "frame" in layer && layer.frame ? layer.frame : frame;
11011
+ const layerFrame = "frame" in layer && layer.frame ? layer.frame : node.frame;
10967
11012
  slide.addShape(shapeName, {
10968
11013
  x: emuToInches(layerFrame.xEmu),
10969
11014
  y: emuToInches(layerFrame.yEmu),
@@ -10971,18 +11016,19 @@ function emitBackgroundLayers(slide, frame, backgroundLayers, shapeName, radiusE
10971
11016
  h: emuToInches(layerFrame.heightEmu),
10972
11017
  fill: toPptxFill(layer, effectiveOpacity),
10973
11018
  line: TRANSPARENT_LINE,
10974
- radius: radiusEmu ? emuToInches(radiusEmu) : void 0,
10975
- rotate: rotation,
10976
- flipH,
10977
- flipV
11019
+ radius: node.radiusEmu ? emuToInches(node.radiusEmu) : void 0,
11020
+ rotate: node.rotation,
11021
+ flipH: node.flipH,
11022
+ flipV: node.flipV
10978
11023
  });
10979
11024
  }
10980
11025
  }
10981
11026
  function emitText(slide, node, inheritedOpacity) {
10982
11027
  const effectiveOpacity = combineOpacities(inheritedOpacity, node.opacity);
10983
- emitOutlineShape(slide, node.radiusEmu && node.radiusEmu > 0 ? "roundRect" : "rect", node.frame, node.outline, node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
10984
- emitEdgeStrokes(slide, node.frame, node.edgeStrokes, effectiveOpacity, node.rotation, node.flipH, node.flipV);
10985
- emitBackgroundLayers(slide, node.frame, node.backgroundLayers, node.radiusEmu && node.radiusEmu > 0 ? "roundRect" : "rect", node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
11028
+ const shapeName = node.radiusEmu && node.radiusEmu > 0 ? "roundRect" : "rect";
11029
+ emitOutlineShape(slide, shapeName, node, effectiveOpacity);
11030
+ emitEdgeStrokes(slide, node, effectiveOpacity);
11031
+ emitBackgroundLayers(slide, node, shapeName, effectiveOpacity);
10986
11032
  const textContent = node.content.runs ? node.content.runs.map((run) => {
10987
11033
  const options = toPptxTextRunOptions(run.style);
10988
11034
  return {
@@ -11009,7 +11055,10 @@ function emitText(slide, node, inheritedOpacity) {
11009
11055
  lineSpacingMultiple: node.style.lineSpacingMultiple,
11010
11056
  paraSpaceBefore: node.style.paragraphSpacingBefore,
11011
11057
  paraSpaceAfter: node.style.paragraphSpacingAfter,
11012
- tabStops: toPptxTabStops(node.style.tabStops),
11058
+ tabStops: node.style.tabStops?.map((tabStop) => ({
11059
+ position: tabStop.positionIn,
11060
+ ...tabStop.alignment ? { alignment: tabStop.alignment } : {}
11061
+ })),
11013
11062
  charSpacing: node.style.charSpacing,
11014
11063
  bullet: toPptxBullet(node.style.list),
11015
11064
  rtlMode: node.style.rtlMode,
@@ -11018,7 +11067,7 @@ function emitText(slide, node, inheritedOpacity) {
11018
11067
  subscript: node.style.subscript,
11019
11068
  fit: node.style.fit,
11020
11069
  wrap: node.style.wrap,
11021
- shape: node.radiusEmu && node.radiusEmu > 0 ? "roundRect" : "rect",
11070
+ shape: shapeName,
11022
11071
  fill: toPptxFill(node.fill, effectiveOpacity),
11023
11072
  line: toPptxLine(node.stroke, effectiveOpacity),
11024
11073
  shadow: toPptxShadow(node.shadow, effectiveOpacity),
@@ -11050,10 +11099,11 @@ function emitImage(slide, node, inheritedOpacity) {
11050
11099
  }
11051
11100
  function emitShape(slide, node, inheritedOpacity) {
11052
11101
  const effectiveOpacity = combineOpacities(inheritedOpacity, node.opacity);
11053
- emitOutlineShape(slide, mapShapeName(node.shape, node.radiusEmu), node.frame, node.outline, node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
11054
- emitEdgeStrokes(slide, node.frame, node.edgeStrokes, effectiveOpacity, node.rotation, node.flipH, node.flipV);
11055
- emitBackgroundLayers(slide, node.frame, node.backgroundLayers, mapShapeName(node.shape, node.radiusEmu), node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
11056
- slide.addShape(mapShapeName(node.shape, node.radiusEmu), {
11102
+ const shapeName = mapShapeName(node.shape, node.radiusEmu);
11103
+ emitOutlineShape(slide, shapeName, node, effectiveOpacity);
11104
+ emitEdgeStrokes(slide, node, effectiveOpacity);
11105
+ emitBackgroundLayers(slide, node, shapeName, effectiveOpacity);
11106
+ slide.addShape(shapeName, {
11057
11107
  x: emuToInches(node.frame.xEmu),
11058
11108
  y: emuToInches(node.frame.yEmu),
11059
11109
  w: emuToInches(node.frame.widthEmu),
@@ -11069,10 +11119,11 @@ function emitShape(slide, node, inheritedOpacity) {
11069
11119
  }
11070
11120
  function emitGroup(slide, node, inheritedOpacity) {
11071
11121
  const effectiveOpacity = combineOpacities(inheritedOpacity, node.opacity);
11072
- emitOutlineShape(slide, mapShapeName("rect", node.radiusEmu), node.frame, node.outline, node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
11073
- emitEdgeStrokes(slide, node.frame, node.edgeStrokes, effectiveOpacity, node.rotation, node.flipH, node.flipV);
11074
- emitBackgroundLayers(slide, node.frame, node.backgroundLayers, mapShapeName("rect", node.radiusEmu), node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
11075
- if (node.fill || node.stroke || node.shadow) slide.addShape(mapShapeName("rect", node.radiusEmu), {
11122
+ const shapeName = mapShapeName("rect", node.radiusEmu);
11123
+ emitOutlineShape(slide, shapeName, node, effectiveOpacity);
11124
+ emitEdgeStrokes(slide, node, effectiveOpacity);
11125
+ emitBackgroundLayers(slide, node, shapeName, effectiveOpacity);
11126
+ if (node.fill || node.stroke || node.shadow) slide.addShape(shapeName, {
11076
11127
  x: emuToInches(node.frame.xEmu),
11077
11128
  y: emuToInches(node.frame.yEmu),
11078
11129
  w: emuToInches(node.frame.widthEmu),
@@ -11084,60 +11135,110 @@ function emitGroup(slide, node, inheritedOpacity) {
11084
11135
  flipH: node.flipH,
11085
11136
  flipV: node.flipV
11086
11137
  });
11087
- for (const child of node.children) emitNode(slide, child, effectiveOpacity);
11138
+ for (const child of node.children) emitElement(slide, child, effectiveOpacity);
11088
11139
  }
11089
- function emitNode(slide, node, inheritedOpacity) {
11140
+ function emitElement(slide, node, inheritedOpacity) {
11090
11141
  if (node.visibility === "hidden") return;
11091
11142
  switch (node.kind) {
11092
11143
  case "group":
11093
11144
  emitGroup(slide, node, inheritedOpacity);
11094
11145
  return;
11095
- case "text":
11096
- emitText(slide, node, inheritedOpacity);
11097
- return;
11098
11146
  case "image":
11099
11147
  emitImage(slide, node, inheritedOpacity);
11100
11148
  return;
11101
11149
  case "shape":
11102
11150
  emitShape(slide, node, inheritedOpacity);
11103
11151
  return;
11104
- default: assertNever(node);
11152
+ case "text":
11153
+ emitText(slide, node, inheritedOpacity);
11154
+ return;
11105
11155
  }
11106
11156
  }
11107
- function pptxgenjsBackend() {
11157
+ function emitSlideBackgroundLayers(slide, projection, backgroundLayers) {
11158
+ if (!backgroundLayers || backgroundLayers.length === 0) return;
11159
+ for (const layer of backgroundLayers) {
11160
+ if (isBackgroundImageLayer(layer)) {
11161
+ for (const tile of expandBackgroundImageLayer(layer)) slide.addImage({
11162
+ x: emuToInches(tile.frame.xEmu),
11163
+ y: emuToInches(tile.frame.yEmu),
11164
+ w: emuToInches(tile.frame.widthEmu),
11165
+ h: emuToInches(tile.frame.heightEmu),
11166
+ path: tile.source.kind === "path" ? tile.source.path : void 0,
11167
+ data: tile.source.kind === "data" ? tile.source.data : void 0,
11168
+ transparency: layer.transparency
11169
+ });
11170
+ continue;
11171
+ }
11172
+ const layerFrame = "frame" in layer && layer.frame ? layer.frame : {
11173
+ xEmu: 0,
11174
+ yEmu: 0,
11175
+ widthEmu: projection.size.widthEmu,
11176
+ heightEmu: projection.size.heightEmu
11177
+ };
11178
+ slide.addShape("rect", {
11179
+ x: emuToInches(layerFrame.xEmu),
11180
+ y: emuToInches(layerFrame.yEmu),
11181
+ w: emuToInches(layerFrame.widthEmu),
11182
+ h: emuToInches(layerFrame.heightEmu),
11183
+ fill: toPptxFill(layer),
11184
+ line: TRANSPARENT_LINE
11185
+ });
11186
+ }
11187
+ }
11188
+ function adapterDiagnostics() {
11189
+ return createDiagnostics([diagnostic({
11190
+ severity: "warning",
11191
+ code: "W_PPTXGENJS_TEMPORARY_ADAPTER",
11192
+ title: "pptxgenjs adapter is temporary",
11193
+ message: "The pptxgenjs adapter consumes the Pptx Package Model directly, but it cannot serialize every projected package-part detail yet.",
11194
+ labels: [{
11195
+ path: "render.adapter",
11196
+ message: "Some package metadata is adapter-limited."
11197
+ }]
11198
+ })]);
11199
+ }
11200
+ async function renderPptxPackageWithPptxGenjs(projection) {
11201
+ const pptx = new PptxGenJS();
11202
+ const layoutName = "DECKJSX_CUSTOM";
11203
+ pptx.defineLayout({
11204
+ name: layoutName,
11205
+ width: projection.size.widthEmu / EMU_PER_INCH,
11206
+ height: projection.size.heightEmu / EMU_PER_INCH
11207
+ });
11208
+ pptx.layout = layoutName;
11209
+ if (projection.meta?.author) pptx.author = projection.meta.author;
11210
+ if (projection.meta?.title) pptx.title = projection.meta.title;
11211
+ if (projection.meta?.subject) pptx.subject = projection.meta.subject;
11212
+ for (const slidePart of projection.slides) {
11213
+ const slide = pptx.addSlide();
11214
+ if (slidePart.payload.background) slide.background = toPptxFill(slidePart.payload.background);
11215
+ emitSlideBackgroundLayers(slide, projection, slidePart.payload.backgroundLayers);
11216
+ for (const element of slidePart.payload.elements) emitElement(slide, element);
11217
+ }
11218
+ const bytes = await patchPresentationXml(normalizeBuffer(await pptx.write({ outputType: "uint8array" })), projection);
11219
+ return {
11220
+ diagnostics: adapterDiagnostics(),
11221
+ artifact: {
11222
+ format: "pptx",
11223
+ mediaType: PPTX_MIME_TYPE,
11224
+ extension: "pptx",
11225
+ bytes
11226
+ }
11227
+ };
11228
+ }
11229
+ //#endregion
11230
+ //#region src/adapter.ts
11231
+ function pptxgenjs(options = {}) {
11108
11232
  return {
11233
+ kind: "deckjsx.writerAdapter",
11109
11234
  name: "pptxgenjs",
11110
- async emit(ir) {
11111
- const pptx = new PptxGenJS();
11112
- const layoutName = "DECKJSX_CUSTOM";
11113
- pptx.defineLayout({
11114
- name: layoutName,
11115
- width: ir.size.widthEmu / EMU_PER_INCH,
11116
- height: ir.size.heightEmu / EMU_PER_INCH
11117
- });
11118
- pptx.layout = layoutName;
11119
- if (ir.meta?.author) pptx.author = ir.meta.author;
11120
- if (ir.meta?.title) pptx.title = ir.meta.title;
11121
- if (ir.meta?.subject) pptx.subject = ir.meta.subject;
11122
- for (const slideIR of ir.slides) {
11123
- const slide = pptx.addSlide();
11124
- if (slideIR.background) slide.background = toPptxFill(slideIR.background);
11125
- emitBackgroundLayers(slide, {
11126
- xEmu: 0,
11127
- yEmu: 0,
11128
- widthEmu: ir.size.widthEmu,
11129
- heightEmu: ir.size.heightEmu
11130
- }, slideIR.backgroundLayers, "rect");
11131
- for (const node of slideIR.nodes) emitNode(slide, node);
11132
- }
11133
- return {
11134
- kind: "buffer",
11135
- mimeType: PPTX_MIME_TYPE,
11136
- data: await patchPresentationXml(normalizeBuffer(await pptx.write({ outputType: "uint8array" })), ir),
11137
- extension: "pptx"
11138
- };
11235
+ projectionFormat: "pptx",
11236
+ format: "pptx",
11237
+ options,
11238
+ async render(projection) {
11239
+ return renderPptxPackageWithPptxGenjs(projection);
11139
11240
  }
11140
11241
  };
11141
11242
  }
11142
11243
  //#endregion
11143
- export { EMU_PER_INCH as n, POINTS_PER_INCH as r, pptxgenjsBackend as t };
11244
+ export { diagnostic as a, SemanticGraphDiagnosticError as c, formatDiagnostics as d, createDiagnostics as i, StyleDiagnosticError as l, EMU_PER_INCH as n, CompositionDiagnosticError as o, POINTS_PER_INCH as r, DeckDiagnosticError as s, pptxgenjs as t, formatDiagnostic as u };
@@ -0,0 +1,22 @@
1
+ import { Yt as Diagnostics } from "./index-C5l8PX5V.mjs";
2
+ import { F as OutputFormat, L as ProjectionFormat, s as PptxPackageModel, z as RenderedArtifact } from "./pptx-PzEK54aA.mjs";
3
+
4
+ //#region src/adapter.d.ts
5
+ type RenderOptions = {
6
+ readonly output?: string;
7
+ };
8
+ type WriterAdapterResult<TFormat extends OutputFormat = OutputFormat> = {
9
+ readonly diagnostics: Diagnostics;
10
+ readonly artifact?: RenderedArtifact<TFormat>;
11
+ };
12
+ type WriterAdapter<TProjection = unknown, TFormat extends OutputFormat = OutputFormat> = {
13
+ readonly kind: "deckjsx.writerAdapter";
14
+ readonly name: string;
15
+ readonly projectionFormat: ProjectionFormat;
16
+ readonly format: TFormat;
17
+ readonly options: RenderOptions;
18
+ render(projection: TProjection): Promise<WriterAdapterResult<TFormat>>;
19
+ };
20
+ declare function pptxgenjs(options?: RenderOptions): WriterAdapter<PptxPackageModel, "pptx">;
21
+ //#endregion
22
+ export { pptxgenjs as i, WriterAdapter as n, WriterAdapterResult as r, RenderOptions as t };
@@ -0,0 +1,2 @@
1
+ import { i as pptxgenjs, n as WriterAdapter, r as WriterAdapterResult, t as RenderOptions } from "./adapter-C8xw46nz.mjs";
2
+ export { RenderOptions, WriterAdapter, WriterAdapterResult, pptxgenjs };
@@ -0,0 +1,2 @@
1
+ import { t as pptxgenjs } from "./adapter-BbtteJ7s.mjs";
2
+ export { pptxgenjs };