@shbernal/ts-pptx 3.4.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/browser.d.ts +2 -2
- package/dist/browser.js +1 -1
- package/dist/{diagnostics-B0OmTOoz.d.ts → diagnostics-BDuR8UkG.d.ts} +3 -3
- package/dist/{diagnostics-B0OmTOoz.d.ts.map → diagnostics-BDuR8UkG.d.ts.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/html.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/inspect.d.ts +28 -4
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +41 -9
- package/dist/inspect.js.map +1 -1
- package/dist/math.d.ts +1 -1
- package/dist/measure.d.ts +1 -1
- package/dist/{namespaces-Sy_m7Nhd.js → namespaces-CcKuzeuE.js} +5 -2
- package/dist/{namespaces-Sy_m7Nhd.js.map → namespaces-CcKuzeuE.js.map} +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.js +1 -1
- package/dist/{notes-bWApshah.js → notes-DNqAggXx.js} +2 -2
- package/dist/{notes-bWApshah.js.map → notes-DNqAggXx.js.map} +1 -1
- package/dist/{presentation-3rAKKRfm.js → presentation-VfJ_FT7E.js} +156 -8
- package/dist/presentation-VfJ_FT7E.js.map +1 -0
- package/dist/{presentation-types-D7cgT-eG.d.ts → presentation-types-CpkTx9Xa.d.ts} +165 -4
- package/dist/presentation-types-CpkTx9Xa.d.ts.map +1 -0
- package/dist/read.d.ts +3 -3
- 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 +68 -30
- package/dist/script.js.map +1 -1
- package/dist/{shapes-Dyw5bxwO.js → shapes-Kt51vry6.js} +357 -13
- package/dist/shapes-Kt51vry6.js.map +1 -0
- package/dist/{text-DSN3anEh.js → text-D04NUMvA.js} +4 -4
- package/dist/{text-DSN3anEh.js.map → text-D04NUMvA.js.map} +1 -1
- package/dist/zip.d.ts +1 -1
- package/package.json +1 -1
- package/dist/presentation-3rAKKRfm.js.map +0 -1
- package/dist/presentation-types-D7cgT-eG.d.ts.map +0 -1
- package/dist/shapes-Dyw5bxwO.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as warn } from "./diagnostics-CPVADSL1.js";
|
|
2
2
|
import { i as PackageReadError, n as InvalidOptionError, o as UnsupportedFeatureError, t as InternalError } from "./errors-Bvln0H-7.js";
|
|
3
|
-
import {
|
|
3
|
+
import { M as TEXT_HORZ_OVERFLOW, N as TEXT_VERTICAL, P as checkEnumOrThrow, a as NOTES_MASTER_REL, c as OFFICE_DOCUMENT_REL, h as SLIDE_MASTER_REL, j as TEXT_ANCHORS, p as SLIDE_LAYOUT_REL, r as IMAGE_REL, t as OOXML_NS, v as THEME_REL, x as getImageSizeFromBytes, y as fitSrcRectPercents } from "./namespaces-CcKuzeuE.js";
|
|
4
4
|
import { DOMParser, MIME_TYPE, XMLSerializer, onErrorStopParsing } from "@xmldom/xmldom";
|
|
5
5
|
/** Parse an XML string strictly: any well-formedness error throws. */
|
|
6
6
|
function parseXml(xml) {
|
|
@@ -2529,6 +2529,16 @@ var Paragraph = class {
|
|
|
2529
2529
|
}
|
|
2530
2530
|
return out;
|
|
2531
2531
|
}
|
|
2532
|
+
/**
|
|
2533
|
+
* Replace **this paragraph's** content with a single run, preserving the character
|
|
2534
|
+
* formatting (`a:rPr`) of its first existing run and leaving its `a:pPr` (level,
|
|
2535
|
+
* alignment, bullet) alone. Sibling paragraphs are untouched — the difference from
|
|
2536
|
+
* {@link TextFrame.text}, which collapses the whole body to one paragraph.
|
|
2537
|
+
*/
|
|
2538
|
+
set text(value) {
|
|
2539
|
+
setParagraphText(this.element, value);
|
|
2540
|
+
this.part.markDirty();
|
|
2541
|
+
}
|
|
2532
2542
|
/** Escape hatch: the underlying `a:p` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
|
|
2533
2543
|
get element_() {
|
|
2534
2544
|
return this.element;
|
|
@@ -2672,8 +2682,6 @@ function setTextBodyText(txBody, value) {
|
|
|
2672
2682
|
const doc = txBody.ownerDocument;
|
|
2673
2683
|
if (!doc) throw new InternalError("oxml/node-has-no-document", "Cannot set text: text body has no owner document");
|
|
2674
2684
|
const paragraphs = getElements(txBody, "a:p");
|
|
2675
|
-
const firstRun = paragraphs[0] && firstChild(paragraphs[0], "a:r");
|
|
2676
|
-
const rPrTemplate = firstRun && firstChild(firstRun, "a:rPr");
|
|
2677
2685
|
for (let i = paragraphs.length - 1; i >= 1; i--) {
|
|
2678
2686
|
const extra = paragraphs[i];
|
|
2679
2687
|
if (extra) txBody.removeChild(extra);
|
|
@@ -2683,6 +2691,21 @@ function setTextBodyText(txBody, value) {
|
|
|
2683
2691
|
p = createElement(doc, "a:p");
|
|
2684
2692
|
txBody.appendChild(p);
|
|
2685
2693
|
}
|
|
2694
|
+
setParagraphText(p, value);
|
|
2695
|
+
}
|
|
2696
|
+
/**
|
|
2697
|
+
* Replace **one paragraph's** content with a single run, preserving the `a:rPr` of that
|
|
2698
|
+
* paragraph's first existing run and leaving its `a:pPr` (level, alignment, bullet) alone.
|
|
2699
|
+
* Sibling paragraphs are untouched, which is the whole difference from
|
|
2700
|
+
* {@link setTextBodyText} and the reason this exists: a SmartArt drawing cache packs several
|
|
2701
|
+
* nodes' text into one `dsp:txBody`, so collapsing the body there would delete the other
|
|
2702
|
+
* nodes' strings. Does **not** mark any part dirty — the caller owns the `Part`.
|
|
2703
|
+
*/
|
|
2704
|
+
function setParagraphText(p, value) {
|
|
2705
|
+
const doc = p.ownerDocument;
|
|
2706
|
+
if (!doc) throw new InternalError("oxml/node-has-no-document", "Cannot set text: paragraph has no owner document");
|
|
2707
|
+
const firstRun = firstChild(p, "a:r");
|
|
2708
|
+
const rPrTemplate = firstRun && firstChild(firstRun, "a:rPr");
|
|
2686
2709
|
for (const child of childElements(p)) if (child.localName === "r" || child.localName === "br" || child.localName === "fld") p.removeChild(child);
|
|
2687
2710
|
const run = createElement(doc, "a:r");
|
|
2688
2711
|
if (rPrTemplate) run.appendChild(rPrTemplate.cloneNode(true));
|
|
@@ -4468,6 +4491,55 @@ function floatValue(value) {
|
|
|
4468
4491
|
}
|
|
4469
4492
|
//#endregion
|
|
4470
4493
|
//#region src/read/api/diagram.ts
|
|
4494
|
+
/**
|
|
4495
|
+
* Read proxies for a SmartArt diagram (`dgm:dataModel`) hosted in a `p:graphicFrame`.
|
|
4496
|
+
*
|
|
4497
|
+
* SmartArt is a four-part construct, and the frame itself holds none of it: the
|
|
4498
|
+
* `a:graphicData` carries only a `dgm:relIds` with four relationship ids pointing at the
|
|
4499
|
+
* data, layout, quick-style and colours parts under `/ppt/diagrams/`. The **data** part is
|
|
4500
|
+
* the one with content in it — a flat `dgm:ptLst` of points plus a `dgm:cxnLst` of
|
|
4501
|
+
* connections that give the points their tree — and it is what this surface decodes. The
|
|
4502
|
+
* other three are generated presets (`urn:microsoft.com/office/officeart/…`) describing how
|
|
4503
|
+
* PowerPoint *draws* the graph rather than what it says; they surface as parts, not getters.
|
|
4504
|
+
*
|
|
4505
|
+
* The text is ordinary DrawingML: `dgm:pt/dgm:t` is an `a:CT_TextBody`, the same type a
|
|
4506
|
+
* shape's `p:txBody` is, so a point's text reads back through the same
|
|
4507
|
+
* {@link TextFrame}/`Paragraph`/`Run` proxies as any other text on the slide, run formatting
|
|
4508
|
+
* included.
|
|
4509
|
+
*
|
|
4510
|
+
* **Not every point is content.** A saved data model interleaves the user's nodes with
|
|
4511
|
+
* points the layout engine generated (`pres`), the diagram root (`doc`), and the transition
|
|
4512
|
+
* points sitting on each edge (`parTrans`/`sibTrans`, which carry text only where a layout
|
|
4513
|
+
* labels its arrows). {@link Diagram.text} applies exactly that filter; {@link Diagram.points}
|
|
4514
|
+
* applies none, so a consumer that needs the raw graph gets it.
|
|
4515
|
+
*
|
|
4516
|
+
* **The structure is in the connections, and {@link Diagram.nodes} is the view of it.** A
|
|
4517
|
+
* `parOf` edge names the parent in `@srcId`, the child in `@destId` and the child's sibling
|
|
4518
|
+
* position in `@srcOrd`; `points` order is document order and says nothing about depth. Three
|
|
4519
|
+
* decisions that tree makes, each of which could defensibly have gone the other way:
|
|
4520
|
+
*
|
|
4521
|
+
* - **`asst` points are in it.** An assistant is user content, and an org chart merely draws
|
|
4522
|
+
* it off the main branch rather than under it. {@link DiagramPoint.type} carries the
|
|
4523
|
+
* distinction, so folding it silently in with `node` would hide something a consumer can
|
|
4524
|
+
* act on while omitting it would lose authored text.
|
|
4525
|
+
* - **Transition points are not.** A `parTrans`/`sibTrans` labels an *edge*, not a node, and
|
|
4526
|
+
* reaches its edge through {@link DiagramConnection.parentTransitionId} /
|
|
4527
|
+
* `siblingTransitionId`. Hanging one off `children` would make the tree disagree with what
|
|
4528
|
+
* PowerPoint's own text pane shows.
|
|
4529
|
+
* - **A cycle in `parOf` throws.** It is a corrupt model rather than a shape the format can
|
|
4530
|
+
* express, and the walk would not terminate; see `diagram/parent-edge-cycle`.
|
|
4531
|
+
*
|
|
4532
|
+
* **A point's text is stored twice.** The data model is what PowerPoint reads, but a deck
|
|
4533
|
+
* also carries a *drawing* part (`dsp:drawing`) holding a copy of every drawn string, and
|
|
4534
|
+
* every renderer without a SmartArt layout engine — LibreOffice, Google Slides, thumbnailers
|
|
4535
|
+
* — paints that copy and nothing else. {@link DiagramPoint.drawnShape} is the link between
|
|
4536
|
+
* the two, and {@link DiagramPoint.text}'s setter is what keeps them in step.
|
|
4537
|
+
*
|
|
4538
|
+
* Authoring a SmartArt graphic from nothing is out of scope: the layout part is a
|
|
4539
|
+
* constraint-solver program PowerPoint executes, and the presentation tree it generates is
|
|
4540
|
+
* not derivable from the user's content. Editing the text of one that already exists is
|
|
4541
|
+
* supported — see {@link DiagramPoint.text}.
|
|
4542
|
+
*/
|
|
4471
4543
|
const POINT_TYPES = [
|
|
4472
4544
|
"node",
|
|
4473
4545
|
"asst",
|
|
@@ -4484,17 +4556,100 @@ const CONNECTION_TYPES = [
|
|
|
4484
4556
|
];
|
|
4485
4557
|
/** The MS extension (`dgm:extLst/a:ext`) whose `@relId` names the fallback drawing part. */
|
|
4486
4558
|
const DRAWING_EXT_URI = "http://schemas.microsoft.com/office/drawing/2008/diagram";
|
|
4559
|
+
/**
|
|
4560
|
+
* The node → drawn-shape index of one diagram: the `presOf` edges of the data model and the
|
|
4561
|
+
* `dsp:sp` elements of the drawing part, both keyed for lookup.
|
|
4562
|
+
*
|
|
4563
|
+
* Built once per {@link Diagram}, and only when a point is actually asked what draws it — the
|
|
4564
|
+
* drawing part is a second XML DOM and a consumer reading node text should not pay to parse
|
|
4565
|
+
* it. The consequence of that memo: a consumer who *adds* or *removes* shapes in the drawing
|
|
4566
|
+
* part through the escape hatches must re-reach the diagram to see them here.
|
|
4567
|
+
*/
|
|
4568
|
+
var DrawingIndex = class {
|
|
4569
|
+
drawingPart;
|
|
4570
|
+
themeContext;
|
|
4571
|
+
/** `presOf` arms out of each source point, in `@srcOrd` order. */
|
|
4572
|
+
#arms = /* @__PURE__ */ new Map();
|
|
4573
|
+
/** Each `dsp:sp` by the `pres` modelId it draws. */
|
|
4574
|
+
#shapes = /* @__PURE__ */ new Map();
|
|
4575
|
+
constructor(root, drawingPart, themeContext) {
|
|
4576
|
+
this.drawingPart = drawingPart;
|
|
4577
|
+
this.themeContext = themeContext;
|
|
4578
|
+
const cxnLst = root && firstChild(root, "dgm:cxnLst");
|
|
4579
|
+
for (const cxn of cxnLst ? getElements(cxnLst, "dgm:cxn") : []) {
|
|
4580
|
+
if (attr(cxn, "type") !== "presOf") continue;
|
|
4581
|
+
const srcId = attr(cxn, "srcId");
|
|
4582
|
+
const destId = attr(cxn, "destId");
|
|
4583
|
+
if (!srcId || !destId) continue;
|
|
4584
|
+
const arm = {
|
|
4585
|
+
destId,
|
|
4586
|
+
destinationOrder: intValue(attr(cxn, "destOrd")) ?? 0,
|
|
4587
|
+
sourceOrder: intValue(attr(cxn, "srcOrd")) ?? 0
|
|
4588
|
+
};
|
|
4589
|
+
const list = this.#arms.get(srcId);
|
|
4590
|
+
if (list) list.push(arm);
|
|
4591
|
+
else this.#arms.set(srcId, [arm]);
|
|
4592
|
+
}
|
|
4593
|
+
for (const list of this.#arms.values()) list.sort((a, b) => a.sourceOrder - b.sourceOrder);
|
|
4594
|
+
const drawingRoot = drawingPart?.dom.documentElement ?? null;
|
|
4595
|
+
for (const sp of drawingRoot ? descendantsByTag(drawingRoot, OOXML_NS.dsp, "sp") : []) {
|
|
4596
|
+
const modelId = attr(sp, "modelId");
|
|
4597
|
+
if (modelId !== null && !this.#shapes.has(modelId)) this.#shapes.set(modelId, sp);
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
/**
|
|
4601
|
+
* Resolve one authored point to the `pres` point that presents it and to the drawn
|
|
4602
|
+
* paragraph carrying its text.
|
|
4603
|
+
*
|
|
4604
|
+
* A point commonly has **several** `presOf` arms — an org-chart node's box and the
|
|
4605
|
+
* connector beneath it are two presentations of one node — so the arm is chosen by what it
|
|
4606
|
+
* reaches rather than by its `@srcOrd`: the first, in `@srcOrd` order, whose `pres` point
|
|
4607
|
+
* draws a `dsp:sp` that has a `dsp:txBody`. That selector produced a unique hit for all 90
|
|
4608
|
+
* authored points measured across five layout families, and it degrades to "no arm" rather
|
|
4609
|
+
* than to "the wrong arm" on a layout that was not.
|
|
4610
|
+
*/
|
|
4611
|
+
resolve(modelId) {
|
|
4612
|
+
const arms = (modelId === null ? void 0 : this.#arms.get(modelId)) ?? [];
|
|
4613
|
+
const first = arms[0];
|
|
4614
|
+
if (!first) return {
|
|
4615
|
+
presentationId: null,
|
|
4616
|
+
drawnShape: null
|
|
4617
|
+
};
|
|
4618
|
+
for (const arm of arms) {
|
|
4619
|
+
const sp = this.#shapes.get(arm.destId);
|
|
4620
|
+
const txBody = sp && firstChild(sp, "dsp:txBody");
|
|
4621
|
+
if (!sp || !txBody || !this.drawingPart) continue;
|
|
4622
|
+
const paragraph = getElements(txBody, "a:p")[arm.destinationOrder];
|
|
4623
|
+
return {
|
|
4624
|
+
presentationId: arm.destId,
|
|
4625
|
+
drawnShape: paragraph ? {
|
|
4626
|
+
part: this.drawingPart,
|
|
4627
|
+
modelId: arm.destId,
|
|
4628
|
+
paragraphIndex: arm.destinationOrder,
|
|
4629
|
+
textFrame: new TextFrame(txBody, this.drawingPart, this.themeContext),
|
|
4630
|
+
element_: sp
|
|
4631
|
+
} : null
|
|
4632
|
+
};
|
|
4633
|
+
}
|
|
4634
|
+
return {
|
|
4635
|
+
presentationId: first.destId,
|
|
4636
|
+
drawnShape: null
|
|
4637
|
+
};
|
|
4638
|
+
}
|
|
4639
|
+
};
|
|
4487
4640
|
/** One point (`dgm:pt`) of a diagram's data model. */
|
|
4488
4641
|
var DiagramPoint = class {
|
|
4489
4642
|
pt;
|
|
4490
4643
|
part;
|
|
4491
4644
|
themeContext;
|
|
4492
4645
|
relationships;
|
|
4493
|
-
|
|
4646
|
+
drawing;
|
|
4647
|
+
constructor(pt, part, themeContext, relationships, drawing) {
|
|
4494
4648
|
this.pt = pt;
|
|
4495
4649
|
this.part = part;
|
|
4496
4650
|
this.themeContext = themeContext;
|
|
4497
4651
|
this.relationships = relationships;
|
|
4652
|
+
this.drawing = drawing;
|
|
4498
4653
|
}
|
|
4499
4654
|
/** This point's id (`@modelId`), which connections reference. */
|
|
4500
4655
|
get modelId() {
|
|
@@ -4530,15 +4685,87 @@ var DiagramPoint = class {
|
|
|
4530
4685
|
* This point's text body (`dgm:t`) as a {@link TextFrame}, or `null` when the point
|
|
4531
4686
|
* carries none. It is an `a:CT_TextBody` like any other, so `paragraphs`, `runs` and the
|
|
4532
4687
|
* `resolved*` getters all apply.
|
|
4688
|
+
*
|
|
4689
|
+
* **Writing through this edits the data model only**, and leaves the drawing cache
|
|
4690
|
+
* holding the old string — which is what PowerPoint-less renderers draw. It is the escape
|
|
4691
|
+
* hatch for run-level formatting, so it does exactly what it is told and nothing more;
|
|
4692
|
+
* {@link text}'s setter is the path that mirrors.
|
|
4533
4693
|
*/
|
|
4534
4694
|
get textFrame() {
|
|
4535
4695
|
const t = firstChild(this.pt, "dgm:t");
|
|
4536
4696
|
return t ? new TextFrame(t, this.part, this.themeContext, void 0, this.relationships) : null;
|
|
4537
4697
|
}
|
|
4698
|
+
/**
|
|
4699
|
+
* The generated `pres` point that presents this one (`dgm:cxn[@type="presOf"]/@destId`),
|
|
4700
|
+
* or `null` when nothing presents it — the normal state of an unlabelled transition point.
|
|
4701
|
+
*
|
|
4702
|
+
* Where a point has several `presOf` arms the one named here is the arm that draws text;
|
|
4703
|
+
* see {@link drawnShape}, which resolves both.
|
|
4704
|
+
*/
|
|
4705
|
+
get presentationId() {
|
|
4706
|
+
return this.drawing?.().resolve(this.modelId).presentationId ?? null;
|
|
4707
|
+
}
|
|
4708
|
+
/**
|
|
4709
|
+
* The paragraph of the fallback drawing part (`dsp:drawing`) that carries this point's
|
|
4710
|
+
* text, or `null` when nothing draws it.
|
|
4711
|
+
*
|
|
4712
|
+
* The mapping runs through the `pres` point rather than directly: a `dsp:sp/@modelId` is
|
|
4713
|
+
* always a `pres` point's id, so a lookup keyed on the authored point's own id finds
|
|
4714
|
+
* nothing at all. It is many-to-one in both directions — one shape draws several points
|
|
4715
|
+
* (`@destOrd` says which paragraph is whose, and it can contradict document order), and
|
|
4716
|
+
* one point has several presentations, of which at most one holds text.
|
|
4717
|
+
*
|
|
4718
|
+
* `null` is a defined outcome, not a failure, and covers four real cases: the package
|
|
4719
|
+
* carries no drawing part; the point has no `presOf` edge (every unlabelled
|
|
4720
|
+
* `parTrans`/`sibTrans`); the `pres` point draws no `dsp:sp`; and the shape it draws has
|
|
4721
|
+
* no `dsp:txBody` (a connector, or a picture node's filled rectangle).
|
|
4722
|
+
*/
|
|
4723
|
+
get drawnShape() {
|
|
4724
|
+
return this.drawing?.().resolve(this.modelId).drawnShape ?? null;
|
|
4725
|
+
}
|
|
4538
4726
|
/** This point's text, paragraphs joined by `\n`; `''` when it carries none. */
|
|
4539
4727
|
get text() {
|
|
4540
4728
|
return this.textFrame?.text ?? "";
|
|
4541
4729
|
}
|
|
4730
|
+
/**
|
|
4731
|
+
* Replace this point's text, in the data model **and** in the drawing cache.
|
|
4732
|
+
*
|
|
4733
|
+
* A diagram stores every string twice. `dgm:t` is what PowerPoint reads, and it recomputes
|
|
4734
|
+
* the drawing from the data model on open; the `dsp:drawing` part is what every other
|
|
4735
|
+
* renderer paints, and none of them recompute anything. Writing only the first is an edit
|
|
4736
|
+
* that is invisible in LibreOffice, Google Slides, thumbnailers and web previews until
|
|
4737
|
+
* someone opens the deck in PowerPoint and saves it.
|
|
4738
|
+
*
|
|
4739
|
+
* The data-model write always happens. The mirror is best-effort: when the point resolves
|
|
4740
|
+
* to no drawn paragraph (see {@link drawnShape} for the four ways that occurs) the cache
|
|
4741
|
+
* keeps the old string and a `diagram/drawing-cache-not-updated` diagnostic says so.
|
|
4742
|
+
* Throwing instead would make the common case unusable in order to report the rare one,
|
|
4743
|
+
* and returning a status would be a shape no other text setter here has.
|
|
4744
|
+
*
|
|
4745
|
+
* Two things it deliberately does not do. It does **not** recompute geometry: the drawn
|
|
4746
|
+
* shape keeps its cached position and size, so a much longer string overflows its box in
|
|
4747
|
+
* those same renderers until PowerPoint re-lays the diagram out. And it does not *create*
|
|
4748
|
+
* a place to draw text — a transition point whose layout has no label slot has no
|
|
4749
|
+
* `dsp:sp`, and PowerPoint strips text put on one, so the honest outcome is the
|
|
4750
|
+
* diagnostic. Like every other `text` setter here it collapses the point to one run,
|
|
4751
|
+
* keeping the first run's `a:rPr`; use {@link textFrame} for run-level work.
|
|
4752
|
+
*/
|
|
4753
|
+
set text(value) {
|
|
4754
|
+
const frame = this.textFrame;
|
|
4755
|
+
if (!frame) {
|
|
4756
|
+
warn("diagram/point-has-no-text-body", `SmartArt point ${this.#label()} (type ${this.type}) has no dgm:t, so it is not a point text can be written to; nothing was changed`);
|
|
4757
|
+
return;
|
|
4758
|
+
}
|
|
4759
|
+
frame.text = value;
|
|
4760
|
+
const drawn = this.drawnShape;
|
|
4761
|
+
const paragraph = drawn?.textFrame.paragraphs[drawn.paragraphIndex];
|
|
4762
|
+
if (!drawn || !paragraph) {
|
|
4763
|
+
warn("diagram/drawing-cache-not-updated", `SmartArt point ${this.#label()} resolves to no drawn paragraph, so ${this.part.partName} now holds the new text but the drawing cache still holds the old one; PowerPoint redraws it on open, other renderers do not`);
|
|
4764
|
+
return;
|
|
4765
|
+
}
|
|
4766
|
+
setParagraphText(paragraph.element_, value);
|
|
4767
|
+
drawn.part.markDirty();
|
|
4768
|
+
}
|
|
4542
4769
|
/** Escape hatch: the underlying `dgm:pt` element. After mutating it call {@link Diagram.markDirty}. */
|
|
4543
4770
|
get element_() {
|
|
4544
4771
|
return this.pt;
|
|
@@ -4546,7 +4773,29 @@ var DiagramPoint = class {
|
|
|
4546
4773
|
#prSet() {
|
|
4547
4774
|
return firstChild(this.pt, "dgm:prSet");
|
|
4548
4775
|
}
|
|
4776
|
+
/** How a diagnostic names this point: its `@modelId`, which is all a corrupt point may have. */
|
|
4777
|
+
#label() {
|
|
4778
|
+
return this.modelId ?? "(no modelId)";
|
|
4779
|
+
}
|
|
4549
4780
|
};
|
|
4781
|
+
/**
|
|
4782
|
+
* One user-authored point in its place in the diagram's tree — a `node` or an `asst`, never a
|
|
4783
|
+
* generated `pres` point or a transition label. See {@link Diagram.nodes}.
|
|
4784
|
+
*/
|
|
4785
|
+
var DiagramNode = class {
|
|
4786
|
+
point;
|
|
4787
|
+
parent;
|
|
4788
|
+
level;
|
|
4789
|
+
/** Child nodes, ordered by their `parOf` edge's `@srcOrd`. Empty for a leaf. */
|
|
4790
|
+
children = [];
|
|
4791
|
+
constructor(point, parent, level) {
|
|
4792
|
+
this.point = point;
|
|
4793
|
+
this.parent = parent;
|
|
4794
|
+
this.level = level;
|
|
4795
|
+
}
|
|
4796
|
+
};
|
|
4797
|
+
/** Sort key for a root with no `parOf` edge at all, so it lands after the ordered ones. */
|
|
4798
|
+
const MAX_ORDER = Number.MAX_SAFE_INTEGER;
|
|
4550
4799
|
/** A SmartArt graphic frame's diagram, backed by its `dgm:dataModel` part. */
|
|
4551
4800
|
var Diagram = class {
|
|
4552
4801
|
part;
|
|
@@ -4554,6 +4803,9 @@ var Diagram = class {
|
|
|
4554
4803
|
opc;
|
|
4555
4804
|
frameRelationships;
|
|
4556
4805
|
themeContext;
|
|
4806
|
+
#relationships;
|
|
4807
|
+
#docPrSetCache;
|
|
4808
|
+
#drawing;
|
|
4557
4809
|
constructor(part, relIds, opc, frameRelationships, themeContext) {
|
|
4558
4810
|
this.part = part;
|
|
4559
4811
|
this.relIds = relIds;
|
|
@@ -4568,14 +4820,88 @@ var Diagram = class {
|
|
|
4568
4820
|
/**
|
|
4569
4821
|
* Every point (`dgm:ptLst/dgm:pt`) in document order, unfiltered — generated `pres`
|
|
4570
4822
|
* points and the `doc` root included. Filter on {@link DiagramPoint.type} for the user's
|
|
4571
|
-
* nodes; {@link text} is the shortcut for the common case.
|
|
4823
|
+
* nodes; {@link text} is the shortcut for the common case, {@link nodes} the structured one.
|
|
4824
|
+
*
|
|
4825
|
+
* Built per access like every other read proxy (`docs/reference/pptx-read.md`, "Object
|
|
4826
|
+
* model"), so `points[0] !== points[0]` while both wrap the same `dgm:pt`. Key a `Map`
|
|
4827
|
+
* on {@link DiagramPoint.modelId}, not on the point.
|
|
4572
4828
|
*/
|
|
4573
4829
|
get points() {
|
|
4574
4830
|
const root = this.#root();
|
|
4575
4831
|
const ptLst = root && firstChild(root, "dgm:ptLst");
|
|
4576
4832
|
if (!ptLst) return [];
|
|
4577
|
-
const relationships = this.opc.relationshipsFor(this.part.partName);
|
|
4578
|
-
|
|
4833
|
+
const relationships = this.#relationships ??= this.opc.relationshipsFor(this.part.partName);
|
|
4834
|
+
const drawing = () => this.#drawingIndex();
|
|
4835
|
+
return getElements(ptLst, "dgm:pt").map((pt) => new DiagramPoint(pt, this.part, this.themeContext, relationships, drawing));
|
|
4836
|
+
}
|
|
4837
|
+
/**
|
|
4838
|
+
* The authored tree — every `node` and `asst` point in its place, roots in `@srcOrd`
|
|
4839
|
+
* order — as a view over {@link points} and {@link connections} rather than a replacement
|
|
4840
|
+
* for either.
|
|
4841
|
+
*
|
|
4842
|
+
* A root is a content point whose `parOf` parent is not itself content, which in a
|
|
4843
|
+
* PowerPoint-authored model means the `doc` point. Transition points are not members; see
|
|
4844
|
+
* this module's header for that decision and the two beside it.
|
|
4845
|
+
*
|
|
4846
|
+
* @throws PackageReadError `diagram/parent-edge-cycle` when the `parOf` edges make a
|
|
4847
|
+
* point its own ancestor, which is a corrupt model rather than a diagram shape.
|
|
4848
|
+
*/
|
|
4849
|
+
get nodes() {
|
|
4850
|
+
const content = /* @__PURE__ */ new Map();
|
|
4851
|
+
for (const point of this.points) {
|
|
4852
|
+
const modelId = point.modelId;
|
|
4853
|
+
if (modelId !== null && (point.type === "node" || point.type === "asst")) content.set(modelId, point);
|
|
4854
|
+
}
|
|
4855
|
+
const childrenOf = /* @__PURE__ */ new Map();
|
|
4856
|
+
const edgeTo = /* @__PURE__ */ new Map();
|
|
4857
|
+
for (const connection of this.connections) {
|
|
4858
|
+
const { sourceId, destinationId } = connection;
|
|
4859
|
+
if (connection.type !== "parOf" || sourceId === null || destinationId === null) continue;
|
|
4860
|
+
if (!content.has(destinationId)) continue;
|
|
4861
|
+
const edge = {
|
|
4862
|
+
parentId: sourceId,
|
|
4863
|
+
childId: destinationId,
|
|
4864
|
+
order: connection.sourceOrder ?? 0
|
|
4865
|
+
};
|
|
4866
|
+
const list = childrenOf.get(sourceId);
|
|
4867
|
+
if (list) list.push(edge);
|
|
4868
|
+
else childrenOf.set(sourceId, [edge]);
|
|
4869
|
+
edgeTo.set(destinationId, edge);
|
|
4870
|
+
}
|
|
4871
|
+
for (const list of childrenOf.values()) list.sort((a, b) => a.order - b.order);
|
|
4872
|
+
const roots = [...content].filter(([modelId]) => {
|
|
4873
|
+
const parentId = edgeTo.get(modelId)?.parentId;
|
|
4874
|
+
return parentId === void 0 || !content.has(parentId);
|
|
4875
|
+
});
|
|
4876
|
+
roots.sort(([a], [b]) => (edgeTo.get(a)?.order ?? MAX_ORDER) - (edgeTo.get(b)?.order ?? MAX_ORDER));
|
|
4877
|
+
const placed = /* @__PURE__ */ new Set();
|
|
4878
|
+
const build = (point, parent, level, path) => {
|
|
4879
|
+
const modelId = point.modelId;
|
|
4880
|
+
if (modelId !== null && path.has(modelId)) throw this.#cycleError(modelId);
|
|
4881
|
+
const node = new DiagramNode(point, parent, level);
|
|
4882
|
+
if (modelId === null) return node;
|
|
4883
|
+
placed.add(modelId);
|
|
4884
|
+
path.add(modelId);
|
|
4885
|
+
for (const edge of childrenOf.get(modelId) ?? []) {
|
|
4886
|
+
const child = content.get(edge.childId);
|
|
4887
|
+
if (child) node.children.push(build(child, node, level + 1, path));
|
|
4888
|
+
}
|
|
4889
|
+
path.delete(modelId);
|
|
4890
|
+
return node;
|
|
4891
|
+
};
|
|
4892
|
+
const tree = roots.map(([, point]) => build(point, null, 0, /* @__PURE__ */ new Set()));
|
|
4893
|
+
if (placed.size !== content.size) {
|
|
4894
|
+
const orphan = [...content.keys()].find((modelId) => !placed.has(modelId));
|
|
4895
|
+
throw this.#cycleError(orphan ?? "(unidentified)");
|
|
4896
|
+
}
|
|
4897
|
+
return tree;
|
|
4898
|
+
}
|
|
4899
|
+
/**
|
|
4900
|
+
* The point with this `@modelId`, or `null` — the lookup every connection getter implies,
|
|
4901
|
+
* since a `DiagramConnection` names its ends by id and nothing else resolves them.
|
|
4902
|
+
*/
|
|
4903
|
+
point(modelId) {
|
|
4904
|
+
return this.points.find((candidate) => candidate.modelId === modelId) ?? null;
|
|
4579
4905
|
}
|
|
4580
4906
|
/** Every edge (`dgm:cxnLst/dgm:cxn`) in document order. */
|
|
4581
4907
|
get connections() {
|
|
@@ -4666,14 +4992,32 @@ var Diagram = class {
|
|
|
4666
4992
|
#root() {
|
|
4667
4993
|
return this.part.dom.documentElement;
|
|
4668
4994
|
}
|
|
4669
|
-
#
|
|
4995
|
+
#cycleError(modelId) {
|
|
4996
|
+
return new PackageReadError("diagram/parent-edge-cycle", `Diagram ${this.part.partName} has a parOf cycle reaching point ${modelId}, so its points do not form a tree`);
|
|
4997
|
+
}
|
|
4998
|
+
/**
|
|
4999
|
+
* The `doc` point's `dgm:prSet`, which carries all three preset ids — resolved once
|
|
5000
|
+
* rather than once per getter, since each lookup is a scan of the whole `ptLst`.
|
|
5001
|
+
* `undefined` means "not looked up yet"; `null` means "looked up, not there".
|
|
5002
|
+
*/
|
|
5003
|
+
#docPrSet() {
|
|
5004
|
+
if (this.#docPrSetCache !== void 0) return this.#docPrSetCache;
|
|
4670
5005
|
const root = this.#root();
|
|
4671
5006
|
const ptLst = root && firstChild(root, "dgm:ptLst");
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
5007
|
+
const doc = ptLst && getElements(ptLst, "dgm:pt").find((pt) => attr(pt, "type") === "doc");
|
|
5008
|
+
return this.#docPrSetCache = doc && firstChild(doc, "dgm:prSet") || null;
|
|
5009
|
+
}
|
|
5010
|
+
#docPrSetAttr(name) {
|
|
5011
|
+
const prSet = this.#docPrSet();
|
|
4675
5012
|
return prSet ? attr(prSet, name) : null;
|
|
4676
5013
|
}
|
|
5014
|
+
/**
|
|
5015
|
+
* The drawing index, built on first use and kept — see {@link DrawingIndex} for what that
|
|
5016
|
+
* memo costs a consumer who mutates the drawing part's shape tree by hand.
|
|
5017
|
+
*/
|
|
5018
|
+
#drawingIndex() {
|
|
5019
|
+
return this.#drawing ??= new DrawingIndex(this.#root(), this.drawingPart, this.themeContext);
|
|
5020
|
+
}
|
|
4677
5021
|
#relPart(qname) {
|
|
4678
5022
|
return this.#partForRelId(attr(this.relIds, qname));
|
|
4679
5023
|
}
|
|
@@ -6242,6 +6586,6 @@ function findShapeByIdDeep(shapes, id) {
|
|
|
6242
6586
|
}
|
|
6243
6587
|
}
|
|
6244
6588
|
//#endregion
|
|
6245
|
-
export {
|
|
6589
|
+
export { carriedDecorations as $, spPrXfrmEmu as A, resolveSingleRel as At, applyColorTransforms as B, getElements as Bt, Connector as C, SPPR_SCENE3D_AFTER as Ct, Paragraph as D, relativePartName as Dt, Shape as E, partNameToZipPath as Et, resolveLayoutColorContext as F, createElement as Ft, placeholderInheritedListStyles as G, parseXml as Gt, RUN_PROP_NAMES as H, insertInOrder as Ht, resolveMasterColorContext as I, descendantsByTag as It, placeholderOf as J, replaceInParent as Jt, placeholderInheritedRunProps as K, removeAttr as Kt, resolveNotesColorContext as L, escapeXmlAttribute as Lt, readPictureFill as M, attr as Mt, readGradientFill as N, boolValue as Nt, Run as O, relsPartNameFor as Ot, resolveColorElement as P, childElements as Pt, cSldOf as Q, resolveSlideColorContext as R, firstChild as Rt, ChartSeries as S, SPPR_LN_AFTER as St, AutoShape as T, partNameExtension as Tt, placeholderInheritedAnchor as U, intValue as Ut, LST_STYLE_LEVELS as V, getOrAddChild as Vt, placeholderInheritedColor as W, ownerDocumentOf as Wt, slideDefinesProp as X, setAttr as Xt, slideDefinesColor as Y, serializeXml as Yt, cSldName as Z, ChartEx as _, RPR_FILL_AFTER as _t, isConnector as a, SCHEME_SLOTS as at, Chart as b, SPPR_EFFECT_AFTER as bt, isPicture as c, isA as ct, Table as d, resolveColor as dt, collectElements as et, TableCell as f, resolveSchemeToken as ft, DiagramPoint as g, FILL_CHOICES as gt, DiagramNode as h, substitutePhClr as ht, isAutoShape as i, spTreeOf as it, readPatternFill as j, zipPathToPartName as jt, TextFrame as k, resolveRelativePartName as kt, wrapShapeElement as l, parseClrMap as lt, Diagram as m, styleRefLine as mt, buildShapes as n, nthShapeChild as nt, isGraphicFrame as o, fmtEntry as ot, TableRow as p, styleRefFill as pt, placeholderInheritedXfrm as q, removeChildrenByQName as qt, findShapeByIdDeep as r, nvPrOf as rt, isGroupShape as s, intAttr as st, GroupShape as t, firstShapeChild as tt, GraphicFrame as u, parseClrScheme as ut, ChartExAxis as v, SHAPE_AFTER_SPPR as vt, Picture as w, SPPR_SP3D_AFTER as wt, ChartAxis as x, SPPR_FILL_AFTER as xt, ChartExSeries as y, SPPR_AFTER_XFRM as yt, resolveSlideThemeParts as z, firstChildElement as zt };
|
|
6246
6590
|
|
|
6247
|
-
//# sourceMappingURL=shapes-
|
|
6591
|
+
//# sourceMappingURL=shapes-Kt51vry6.js.map
|