@shbernal/ts-pptx 3.3.0 → 3.5.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/dist/{autopage-D1sqK6j7.js → autopage-BYlTzX-l.js} +8 -5
- package/dist/autopage-BYlTzX-l.js.map +1 -0
- package/dist/browser.d.ts +5 -5
- package/dist/browser.js +11 -11
- package/dist/browser.js.map +1 -1
- package/dist/{diagnostics-B2yWpcjB.d.ts → diagnostics-BDuR8UkG.d.ts} +39 -7
- package/dist/diagnostics-BDuR8UkG.d.ts.map +1 -0
- package/dist/{diagnostics-H1QzgRSw.js → diagnostics-CPVADSL1.js} +29 -3
- package/dist/{diagnostics-H1QzgRSw.js.map → diagnostics-CPVADSL1.js.map} +1 -1
- package/dist/{errors-fB1KDJKQ.d.ts → errors-CgnueTYL.d.ts} +3 -3
- package/dist/{errors-fB1KDJKQ.d.ts.map → errors-CgnueTYL.d.ts.map} +1 -1
- package/dist/{fit-CYJ1jkQI.js → fit-TjpNbMru.js} +3 -3
- package/dist/{fit-CYJ1jkQI.js.map → fit-TjpNbMru.js.map} +1 -1
- package/dist/{html-dom-CzewEdE1.js → html-dom-yUSdCExA.js} +5 -5
- package/dist/html-dom-yUSdCExA.js.map +1 -0
- package/dist/html.d.ts +3 -3
- package/dist/html.js +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +16 -33
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +28 -4
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +43 -10
- package/dist/inspect.js.map +1 -1
- package/dist/math.d.ts +1 -1
- package/dist/measure.d.ts +2 -2
- package/dist/measure.js +1 -1
- package/dist/{st-enums-bVnezkMJ.js → namespaces-CcKuzeuE.js} +291 -200
- package/dist/namespaces-CcKuzeuE.js.map +1 -0
- package/dist/node.d.ts +5 -5
- package/dist/node.js +7 -19
- package/dist/node.js.map +1 -1
- package/dist/{notes-SCvpJz0l.js → notes-DNqAggXx.js} +221 -140
- package/dist/notes-DNqAggXx.js.map +1 -0
- package/dist/{pres-Cb-1xDne.d.ts → pres-Dybf7ZUl.d.ts} +2 -2
- package/dist/{pres-Cb-1xDne.d.ts.map → pres-Dybf7ZUl.d.ts.map} +1 -1
- package/dist/{presentation-DeKTJGHf.js → presentation-VfJ_FT7E.js} +306 -234
- package/dist/presentation-VfJ_FT7E.js.map +1 -0
- package/dist/{presentation-types-B50aOUFI.d.ts → presentation-types-CpkTx9Xa.d.ts} +352 -16
- package/dist/presentation-types-CpkTx9Xa.d.ts.map +1 -0
- package/dist/read.d.ts +4 -4
- package/dist/read.js +3 -3
- package/dist/script.d.ts +2 -2
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +128 -63
- package/dist/script.js.map +1 -1
- package/dist/{shapes-BXVgsk0F.js → shapes-Kt51vry6.js} +717 -54
- package/dist/shapes-Kt51vry6.js.map +1 -0
- package/dist/{slide-DWw9UoI6.d.ts → slide-B_aInw3N.d.ts} +208 -180
- package/dist/slide-B_aInw3N.d.ts.map +1 -0
- package/dist/{text-uM-zGton.js → text-D04NUMvA.js} +3563 -3437
- package/dist/text-D04NUMvA.js.map +1 -0
- package/dist/{units-internal-CGf4VrXy.js → units-internal-DNvK2I6o.js} +54 -34
- package/dist/{units-internal-CGf4VrXy.js.map → units-internal-DNvK2I6o.js.map} +1 -1
- package/dist/zip.d.ts +1 -1
- package/package.json +4 -4
- package/dist/autopage-D1sqK6j7.js.map +0 -1
- package/dist/diagnostics-B2yWpcjB.d.ts.map +0 -1
- package/dist/html-dom-CzewEdE1.js.map +0 -1
- package/dist/notes-SCvpJz0l.js.map +0 -1
- package/dist/presentation-DeKTJGHf.js.map +0 -1
- package/dist/presentation-types-B50aOUFI.d.ts.map +0 -1
- package/dist/shapes-BXVgsk0F.js.map +0 -1
- package/dist/slide-DWw9UoI6.d.ts.map +0 -1
- package/dist/st-enums-bVnezkMJ.js.map +0 -1
- package/dist/text-uM-zGton.js.map +0 -1
package/dist/script.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { a as TsPptxError, i as PackageReadError, n as InvalidOptionError, o as UnsupportedFeatureError, r as MediaError, t as InternalError } from "./errors-Bvln0H-7.js";
|
|
2
|
-
import {
|
|
2
|
+
import { t as OOXML_NS } from "./namespaces-CcKuzeuE.js";
|
|
3
|
+
import { a as isConnector, c as isPicture, i as isAutoShape, o as isGraphicFrame, s as isGroupShape } from "./shapes-Kt51vry6.js";
|
|
3
4
|
//#region src/script/fidelity.ts
|
|
4
5
|
/**
|
|
5
6
|
* Accumulates notes while a deck is walked, so the walk itself stays a plain
|
|
@@ -350,12 +351,8 @@ function noteUncarriedGeometry(picture, notes, subject) {
|
|
|
350
351
|
* Each check here is a standing argument for a real accessor. When one lands, the
|
|
351
352
|
* corresponding function should be deleted, not kept in sync.
|
|
352
353
|
*/
|
|
353
|
-
/** DrawingML main namespace — hosts `a:videoFile` / `a:audioFile` under `p:nvPr`. */
|
|
354
|
-
const A_NS = "http://schemas.openxmlformats.org/drawingml/2006/main";
|
|
355
354
|
/** Office MathML namespace — the equation body itself, wrapped by `a14:m` in a text run. */
|
|
356
355
|
const MATH_NS = "http://schemas.openxmlformats.org/officeDocument/2006/math";
|
|
357
|
-
/** PresentationML main namespace — `p:grpSpPr`, `p:txStyles`, `p:spTree`. */
|
|
358
|
-
const P_NS = "http://schemas.openxmlformats.org/presentationml/2006/main";
|
|
359
356
|
/** Shape-tree children that carry drawing content, as opposed to the tree's own properties. */
|
|
360
357
|
const SHAPE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
361
358
|
"sp",
|
|
@@ -404,7 +401,7 @@ function children(element) {
|
|
|
404
401
|
* without this check a video converts to a static image that looks deliberate.
|
|
405
402
|
*/
|
|
406
403
|
function isAudioVideo(element) {
|
|
407
|
-
return has(element,
|
|
404
|
+
return has(element, OOXML_NS.a, "videoFile") || has(element, OOXML_NS.a, "audioFile");
|
|
408
405
|
}
|
|
409
406
|
/**
|
|
410
407
|
* `true` when this shape's text body contains an OMML equation.
|
|
@@ -431,7 +428,7 @@ function hasEquation(element) {
|
|
|
431
428
|
* would otherwise answer for its first child.
|
|
432
429
|
*/
|
|
433
430
|
function isTextBox(element) {
|
|
434
|
-
return child(child(element,
|
|
431
|
+
return child(child(element, OOXML_NS.p, "nvSpPr"), OOXML_NS.p, "cNvSpPr")?.getAttribute("txBox") === "1";
|
|
435
432
|
}
|
|
436
433
|
/**
|
|
437
434
|
* `true` when a group's child coordinate space equals its own frame, so its children are
|
|
@@ -446,12 +443,12 @@ function isTextBox(element) {
|
|
|
446
443
|
* `true` rather than unknown.
|
|
447
444
|
*/
|
|
448
445
|
function hasIdentityChildSpace(element) {
|
|
449
|
-
const xfrm = child(child(element,
|
|
446
|
+
const xfrm = child(child(element, OOXML_NS.p, "grpSpPr"), OOXML_NS.a, "xfrm");
|
|
450
447
|
if (!xfrm) return true;
|
|
451
|
-
const off = child(xfrm,
|
|
452
|
-
const ext = child(xfrm,
|
|
453
|
-
const chOff = child(xfrm,
|
|
454
|
-
const chExt = child(xfrm,
|
|
448
|
+
const off = child(xfrm, OOXML_NS.a, "off");
|
|
449
|
+
const ext = child(xfrm, OOXML_NS.a, "ext");
|
|
450
|
+
const chOff = child(xfrm, OOXML_NS.a, "chOff");
|
|
451
|
+
const chExt = child(xfrm, OOXML_NS.a, "chExt");
|
|
455
452
|
if (!off || !ext || !chOff || !chExt) return true;
|
|
456
453
|
return off.getAttribute("x") === chOff.getAttribute("x") && off.getAttribute("y") === chOff.getAttribute("y") && ext.getAttribute("cx") === chExt.getAttribute("cx") && ext.getAttribute("cy") === chExt.getAttribute("cy");
|
|
457
454
|
}
|
|
@@ -464,7 +461,7 @@ function hasIdentityChildSpace(element) {
|
|
|
464
461
|
* scheme is repainted with Office's, and this is the only way to notice.
|
|
465
462
|
*/
|
|
466
463
|
function hasFormatScheme(element) {
|
|
467
|
-
return has(element,
|
|
464
|
+
return has(element, OOXML_NS.a, "fmtScheme");
|
|
468
465
|
}
|
|
469
466
|
/**
|
|
470
467
|
* `true` when this slide master declares per-level text styles (`p:txStyles`) with content.
|
|
@@ -474,7 +471,7 @@ function hasFormatScheme(element) {
|
|
|
474
471
|
* converter and comes back as PowerPoint's built-in default.
|
|
475
472
|
*/
|
|
476
473
|
function hasTextStyles(element) {
|
|
477
|
-
return children(child(element,
|
|
474
|
+
return children(child(element, OOXML_NS.p, "txStyles")).some((group) => children(group).length > 0);
|
|
478
475
|
}
|
|
479
476
|
/**
|
|
480
477
|
* `true` when this shape is a placeholder — the tier that *reserves* a region for a slide to
|
|
@@ -492,7 +489,7 @@ function hasTextStyles(element) {
|
|
|
492
489
|
* cannot survive being flattened into loose objects.
|
|
493
490
|
*/
|
|
494
491
|
function isPlaceholderShape(element) {
|
|
495
|
-
return has(element,
|
|
492
|
+
return has(element, OOXML_NS.p, "ph");
|
|
496
493
|
}
|
|
497
494
|
/**
|
|
498
495
|
* `true` when this master or layout carries a shape that is not a placeholder — a logo, a
|
|
@@ -506,7 +503,7 @@ function isPlaceholderShape(element) {
|
|
|
506
503
|
* rather than an unconditional note.
|
|
507
504
|
*/
|
|
508
505
|
function hasDecorativeShapes(element) {
|
|
509
|
-
return children(child(child(element,
|
|
506
|
+
return children(child(child(element, OOXML_NS.p, "cSld"), OOXML_NS.p, "spTree")).some((shape) => shape.namespaceURI === OOXML_NS.p && SHAPE_ELEMENTS.has(shape.localName ?? "") && !isPlaceholderShape(shape));
|
|
510
507
|
}
|
|
511
508
|
//#endregion
|
|
512
509
|
//#region src/script/from-read/text.ts
|
|
@@ -1781,18 +1778,40 @@ function connectorCall(shape, notes) {
|
|
|
1781
1778
|
...nameOf(shape)
|
|
1782
1779
|
};
|
|
1783
1780
|
}
|
|
1781
|
+
/**
|
|
1782
|
+
* Why a graphic frame cannot be authored from a script, or `null` when it can.
|
|
1783
|
+
*
|
|
1784
|
+
* The single enumeration of the payloads with no write-API emitter, and the reason it is a
|
|
1785
|
+
* function rather than a condition spelled at each site: `graphicFrameCall` needs it to pick
|
|
1786
|
+
* a fidelity note, and `hasUnwritableContent` in `from-read/deck.ts` needs it to decide
|
|
1787
|
+
* whether the printer must copy the slide instead of transcribing it. Those were two
|
|
1788
|
+
* hand-maintained lists, they disagreed — the deck-level one named extended charts only — and
|
|
1789
|
+
* a SmartArt slide was therefore transcribed with a hole where the graphic had been. The two
|
|
1790
|
+
* consequences are the same for every member, so the membership has to be too.
|
|
1791
|
+
*/
|
|
1792
|
+
function unwritableFramePayload(shape) {
|
|
1793
|
+
if (shape.table || shape.chart) return null;
|
|
1794
|
+
if (shape.hasChartEx) return "chartEx";
|
|
1795
|
+
if (shape.hasDiagram) return "diagram";
|
|
1796
|
+
return "unknown";
|
|
1797
|
+
}
|
|
1784
1798
|
/** A `GraphicFrame` hosts a table or a chart; both have their own mapper. */
|
|
1785
1799
|
function graphicFrameCall(shape, notes, assets) {
|
|
1786
1800
|
const table = shape.table;
|
|
1787
1801
|
if (table) return tableCall(shape, table, notes, assets);
|
|
1788
1802
|
const chart = shape.chart;
|
|
1789
1803
|
if (chart) return chartCall(shape, chart, notes);
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1804
|
+
switch (unwritableFramePayload(shape)) {
|
|
1805
|
+
case "chartEx":
|
|
1806
|
+
notes.note("chartEx.all", "dropped", "unwritable", "an extended chart (waterfall, funnel, box-and-whisker, …) has a full reader but no write-API counterpart");
|
|
1807
|
+
return null;
|
|
1808
|
+
case "diagram":
|
|
1809
|
+
notes.note("diagram.all", "dropped", "unwritable", "a SmartArt diagram has a full reader and its text can be edited in place through it (DiagramPoint.text), but no write API authors one from a script, so a converted script cannot describe this frame");
|
|
1810
|
+
return null;
|
|
1811
|
+
default:
|
|
1812
|
+
notes.note("graphicFrame.unknown", "dropped", "unread", "this graphic frame hosts none of a table, a chart or a SmartArt diagram (an OLE object or an ink annotation), which the read model does not decode");
|
|
1813
|
+
return null;
|
|
1793
1814
|
}
|
|
1794
|
-
notes.note("graphicFrame.unknown", "dropped", "unread", "this graphic frame hosts neither a table nor a chart (SmartArt or an OLE object), which the read model does not decode");
|
|
1795
|
-
return null;
|
|
1796
1815
|
}
|
|
1797
1816
|
/**
|
|
1798
1817
|
* A `GroupShape` becomes `addGroup`, with each child mapped and re-tagged into the
|
|
@@ -1840,6 +1859,28 @@ function groupCall(shape, notes, assets) {
|
|
|
1840
1859
|
* `addGroup` excludes. The tagged form is a single-key object, not a `{ type, args }` pair.
|
|
1841
1860
|
*/
|
|
1842
1861
|
function asGroupChild(call) {
|
|
1862
|
+
const shared = commonShapeVariant(call);
|
|
1863
|
+
if (shared) return shared;
|
|
1864
|
+
const [first, second] = call.args;
|
|
1865
|
+
switch (call.method) {
|
|
1866
|
+
case "addGroup": return { group: compact({
|
|
1867
|
+
children: first,
|
|
1868
|
+
options: second
|
|
1869
|
+
}) ?? {} };
|
|
1870
|
+
default: return null;
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
/**
|
|
1874
|
+
* The three key-tagged variants both union-shaped call sites emit identically: a text box, an
|
|
1875
|
+
* auto shape, and an image. `null` when `call.method` is not one of them, which is the signal
|
|
1876
|
+
* for the caller to try its own extra arms.
|
|
1877
|
+
*
|
|
1878
|
+
* Shared rather than duplicated because this is exactly where a fourth common variant would be
|
|
1879
|
+
* added to one site and forgotten in the other. What is deliberately *not* shared is either
|
|
1880
|
+
* caller's `default`: a group child silently declines a chart, while a layout object reports it
|
|
1881
|
+
* as a fidelity loss, and that difference is the point of having two functions.
|
|
1882
|
+
*/
|
|
1883
|
+
function commonShapeVariant(call) {
|
|
1843
1884
|
const [first, second] = call.args;
|
|
1844
1885
|
switch (call.method) {
|
|
1845
1886
|
case "addText": return { text: compact({
|
|
@@ -1851,10 +1892,6 @@ function asGroupChild(call) {
|
|
|
1851
1892
|
options: second
|
|
1852
1893
|
}) ?? {} };
|
|
1853
1894
|
case "addImage": return { image: first ?? {} };
|
|
1854
|
-
case "addGroup": return { group: compact({
|
|
1855
|
-
children: first,
|
|
1856
|
-
options: second
|
|
1857
|
-
}) ?? {} };
|
|
1858
1895
|
default: return null;
|
|
1859
1896
|
}
|
|
1860
1897
|
}
|
|
@@ -1891,17 +1928,10 @@ function masterObject(shape, notes, assets) {
|
|
|
1891
1928
|
}
|
|
1892
1929
|
const call = shapeCall(shape, notes, assets);
|
|
1893
1930
|
if (!call) return null;
|
|
1931
|
+
const shared = commonShapeVariant(call);
|
|
1932
|
+
if (shared) return shared;
|
|
1894
1933
|
const [first, second] = call.args;
|
|
1895
1934
|
switch (call.method) {
|
|
1896
|
-
case "addText": return { text: compact({
|
|
1897
|
-
text: first,
|
|
1898
|
-
options: second
|
|
1899
|
-
}) ?? {} };
|
|
1900
|
-
case "addShape": return { shape: compact({
|
|
1901
|
-
type: first,
|
|
1902
|
-
options: second
|
|
1903
|
-
}) ?? {} };
|
|
1904
|
-
case "addImage": return { image: first ?? {} };
|
|
1905
1935
|
case "addChart": {
|
|
1906
1936
|
const options = second !== null && typeof second === "object" && !Array.isArray(second) && !isAssetRef(second) ? second : null;
|
|
1907
1937
|
const type = options?.["type"];
|
|
@@ -2380,7 +2410,7 @@ function slideToIr(slide, number, collector, assets, layouts) {
|
|
|
2380
2410
|
};
|
|
2381
2411
|
const transition = transitionToIr(slide, notes, assets);
|
|
2382
2412
|
const carried = hasUnwritableContent(slide);
|
|
2383
|
-
if (carried) notes.note("slide.carried", "flattened", "unwritable", "this slide holds
|
|
2413
|
+
if (carried) notes.note("slide.carried", "flattened", "unwritable", "this slide holds a graphic frame the write API cannot author (an extended chart, a SmartArt diagram, an OLE object or ink); a printer that can copy the source slide does so instead of transcribing it, so it renders correctly but the emitted script does not describe its contents. The per-shape note beside this one says which construct forced the copy");
|
|
2384
2414
|
const calls = [];
|
|
2385
2415
|
for (const shape of slide.shapes) {
|
|
2386
2416
|
const call = shapeCall(shape, notes, assets);
|
|
@@ -2397,11 +2427,16 @@ function slideToIr(slide, number, collector, assets, layouts) {
|
|
|
2397
2427
|
/**
|
|
2398
2428
|
* `true` when the slide holds something with no write-API expression at all, forcing a
|
|
2399
2429
|
* carried slide. Descends into groups, since a group can host a graphic frame.
|
|
2430
|
+
*
|
|
2431
|
+
* Membership comes from {@link unwritableFramePayload}, which `graphicFrameCall` also uses to
|
|
2432
|
+
* pick its note — one enumeration, so the two cannot drift apart again. This test named
|
|
2433
|
+
* extended charts alone until then, which is why a slide holding SmartArt (or an OLE object,
|
|
2434
|
+
* or ink) was transcribed as `authored` and rendered with a hole where the graphic had been.
|
|
2400
2435
|
*/
|
|
2401
2436
|
function hasUnwritableContent(slide) {
|
|
2402
2437
|
const check = (shapes) => shapes.some((shape) => {
|
|
2403
2438
|
if (isGroupShape(shape)) return check(shape.shapes);
|
|
2404
|
-
return isGraphicFrame(shape) && shape
|
|
2439
|
+
return isGraphicFrame(shape) && unwritableFramePayload(shape) !== null;
|
|
2405
2440
|
});
|
|
2406
2441
|
return check(slide.shapes);
|
|
2407
2442
|
}
|
|
@@ -2709,6 +2744,28 @@ function wrap(text, width, continuation) {
|
|
|
2709
2744
|
if (current) lines.push(current);
|
|
2710
2745
|
return lines;
|
|
2711
2746
|
}
|
|
2747
|
+
/**
|
|
2748
|
+
* Close out a printed script: the accumulated lines as one module source, plus the
|
|
2749
|
+
* asset side-car the caller has to write beside it.
|
|
2750
|
+
*
|
|
2751
|
+
* Both tiers end this way, and the `assetMode` test is the whole reason it is worth
|
|
2752
|
+
* naming. In `'inline'` mode the bytes are already in {@link PrintedScript.code} as
|
|
2753
|
+
* `data:` literals, so the map must come back **empty** — a tier that returned them
|
|
2754
|
+
* anyway would have its caller write every image to disk as well, and the script would
|
|
2755
|
+
* ignore the files it was handed.
|
|
2756
|
+
* @param {string[]} lines - the script's lines, in order
|
|
2757
|
+
* @param {DeckIr} ir - the IR being printed, for its assets
|
|
2758
|
+
* @param {AssetMode} assetMode - how image bytes reach the script
|
|
2759
|
+
* @param {FidelityNote[]} notes - the losses that apply to this output
|
|
2760
|
+
* @returns {PrintedScript} the finished script
|
|
2761
|
+
*/
|
|
2762
|
+
function printedScript(lines, ir, assetMode, notes) {
|
|
2763
|
+
return {
|
|
2764
|
+
code: lines.join("\n"),
|
|
2765
|
+
assets: new Map(assetMode === "file" ? ir.assets.map((asset) => [asset.name, asset.bytes]) : []),
|
|
2766
|
+
notes
|
|
2767
|
+
};
|
|
2768
|
+
}
|
|
2712
2769
|
//#endregion
|
|
2713
2770
|
//#region src/script/print/script.ts
|
|
2714
2771
|
/**
|
|
@@ -2794,19 +2851,22 @@ function printScript(ir, options = {}) {
|
|
|
2794
2851
|
const assetLines = printAssetBindings(ir, assetNames, assetDir, assetMode);
|
|
2795
2852
|
if (assetLines.length > 0) lines.push("", ...assetLines);
|
|
2796
2853
|
lines.push("", "/**", " * A generator sized to the template. appendSlides compares slide sizes exactly and", " * throws when they differ, so the inches here must round-trip to the source EMU.", " */", "function generator(): TsPptx {", " const pptx = new TsPptx()", `\tpptx.defineLayout({ name: 'source', width: ${inches(ir.slideSize.widthEmu)}, height: ${inches(ir.slideSize.heightEmu)} })`, " pptx.layout = 'source'", " return pptx", "}", ...body, "", `await writeFile(here(${printString(outputPath)}), await deck.save())`, "");
|
|
2797
|
-
return
|
|
2798
|
-
code: lines.join("\n"),
|
|
2799
|
-
assets: new Map(assetMode === "file" ? ir.assets.map((asset) => [asset.name, asset.bytes]) : []),
|
|
2800
|
-
notes
|
|
2801
|
-
};
|
|
2854
|
+
return printedScript(lines, ir, assetMode, notes);
|
|
2802
2855
|
}
|
|
2803
2856
|
/**
|
|
2804
|
-
* The slide statements, batched into generators.
|
|
2857
|
+
* The slide statements, batched into generators, preceded by the layout handles they bind to.
|
|
2805
2858
|
*
|
|
2806
2859
|
* A batch ends when the layout changes or a carried slide interrupts, because
|
|
2807
2860
|
* `appendSlides` binds one layout per call and a carried slide is not authored at all.
|
|
2861
|
+
*
|
|
2862
|
+
* Every layout `const` is hoisted above the first statement rather than emitted where it is
|
|
2863
|
+
* first used. `deck.layouts()` is a snapshot of the gallery, and `importSlide` — the call a
|
|
2864
|
+
* carried slide prints — grows that gallery with the source slide's own layout and master.
|
|
2865
|
+
* Resolving a handle after one has run is therefore resolving against a deck that has already
|
|
2866
|
+
* moved; capturing every handle up front is the only ordering that cannot.
|
|
2808
2867
|
*/
|
|
2809
2868
|
function printSlides$1(ir, collector, printAsset) {
|
|
2869
|
+
const declarations = [];
|
|
2810
2870
|
const lines = [];
|
|
2811
2871
|
let batch = [];
|
|
2812
2872
|
let generatorIndex = 0;
|
|
@@ -2818,7 +2878,7 @@ function printSlides$1(ir, collector, printAsset) {
|
|
|
2818
2878
|
const name = `gen${++generatorIndex}`;
|
|
2819
2879
|
lines.push("", `const ${name} = generator()`);
|
|
2820
2880
|
for (const slide of batch) lines.push(...printAuthoredSlide(slide, name, collector, printAsset));
|
|
2821
|
-
lines.push("",
|
|
2881
|
+
lines.push("", printAppend(name, first, collector, declaredLayouts, declarations));
|
|
2822
2882
|
batch = [];
|
|
2823
2883
|
};
|
|
2824
2884
|
for (const slide of ir.slides) {
|
|
@@ -2832,31 +2892,39 @@ function printSlides$1(ir, collector, printAsset) {
|
|
|
2832
2892
|
batch.push(slide);
|
|
2833
2893
|
}
|
|
2834
2894
|
flush();
|
|
2835
|
-
return
|
|
2895
|
+
return declarations.length > 0 ? [
|
|
2896
|
+
"",
|
|
2897
|
+
...declarations,
|
|
2898
|
+
...lines
|
|
2899
|
+
] : lines;
|
|
2836
2900
|
}
|
|
2837
2901
|
/**
|
|
2838
2902
|
* The `appendSlides` call closing a batch, binding by layout name where that is
|
|
2839
|
-
* unambiguous and by gallery position where it is not.
|
|
2903
|
+
* unambiguous and by gallery position where it is not. Any handle it needs is appended to
|
|
2904
|
+
* `declarations`, which the caller hoists above every statement.
|
|
2840
2905
|
*
|
|
2841
2906
|
* Binding by name is preferred because it survives being re-pointed at a different
|
|
2842
2907
|
* template and because it is legible. But `appendSlides` *throws* on an ambiguous name
|
|
2843
|
-
* rather than picking one,
|
|
2844
|
-
*
|
|
2908
|
+
* rather than picking one, so the positional form resolves the case where the name does not
|
|
2909
|
+
* identify one layout: a multi-master deck that repeats layout names.
|
|
2910
|
+
*
|
|
2911
|
+
* A carried slide used to demote every binding in the script to a position too, because its
|
|
2912
|
+
* `importSlide` copied the source layout in under a second name-alike entry. `importSlide`
|
|
2913
|
+
* now binds to the chrome the template already holds (`read/api/ops/part-reuse.ts`), and
|
|
2914
|
+
* this deck's template *is* the source file, so the gallery no longer grows and the names
|
|
2915
|
+
* stay unambiguous.
|
|
2845
2916
|
*/
|
|
2846
|
-
function printAppend(generatorName, first, collector, declared) {
|
|
2917
|
+
function printAppend(generatorName, first, collector, declared, declarations) {
|
|
2847
2918
|
const layout = first.layout;
|
|
2848
|
-
if (!layout) return
|
|
2849
|
-
if (layout.nameIsUnique) return
|
|
2919
|
+
if (!layout) return `await deck.appendSlides(${generatorName}, { layout: fallbackLayout })`;
|
|
2920
|
+
if (layout.nameIsUnique) return `await deck.appendSlides(${generatorName}, { layout: ${printString(layout.name)} })`;
|
|
2850
2921
|
scopeNotes(collector, first.number).note("slide.layout", "approximated", "unsupported", `more than one layout in the source deck is named ${JSON.stringify(layout.name)}, so this slide binds to gallery position ${layout.index} instead; re-pointing the script at a different template will not track the name`);
|
|
2851
2922
|
const identifier = `layout${layout.index}`;
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
`if (!${identifier}) throw new Error('the template has no layout at position ${layout.index}')`,
|
|
2858
|
-
append
|
|
2859
|
-
];
|
|
2923
|
+
if (!declared.has(layout.index)) {
|
|
2924
|
+
declared.add(layout.index);
|
|
2925
|
+
declarations.push(`const ${identifier} = deck.layouts()[${layout.index}] // ${JSON.stringify(layout.name)}`, `if (!${identifier}) throw new Error('the template has no layout at position ${layout.index}')`);
|
|
2926
|
+
}
|
|
2927
|
+
return `await deck.appendSlides(${generatorName}, { layout: ${identifier} })`;
|
|
2860
2928
|
}
|
|
2861
2929
|
/** One authored slide, plus the layout-binding note this tier is responsible for. */
|
|
2862
2930
|
function printAuthoredSlide(slide, generatorName, collector, printAsset) {
|
|
@@ -2928,11 +2996,7 @@ function printStandaloneScript(ir, options = {}) {
|
|
|
2928
2996
|
if (assetLines.length > 0) lines.push("", ...assetLines);
|
|
2929
2997
|
if (masters.length > 0) lines.push("", ...masters);
|
|
2930
2998
|
lines.push(...body, "", `await pptx.writeFile({ fileName: here(${printString(outputPath)}) })`, "");
|
|
2931
|
-
return
|
|
2932
|
-
code: lines.join("\n"),
|
|
2933
|
-
assets: new Map(assetMode === "file" ? ir.assets.map((asset) => [asset.name, asset.bytes]) : []),
|
|
2934
|
-
notes
|
|
2935
|
-
};
|
|
2999
|
+
return printedScript(lines, ir, assetMode, notes);
|
|
2936
3000
|
}
|
|
2937
3001
|
/**
|
|
2938
3002
|
* The document properties the write API can set.
|
|
@@ -3267,6 +3331,7 @@ const NOTE_FIELDS = {
|
|
|
3267
3331
|
"deck.docProps": [],
|
|
3268
3332
|
"deck.docPropsDefault": [],
|
|
3269
3333
|
"deck.slideSize": ["widthEmu", "heightEmu"],
|
|
3334
|
+
"diagram.all": ["*"],
|
|
3270
3335
|
"fill.gradient.path": ["gradient", "fill"],
|
|
3271
3336
|
"fill.picture": ["fill", "color"],
|
|
3272
3337
|
"fill.picture.geometry": [],
|