@docx4j/core-ts 0.4.0 → 0.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.
Files changed (49) hide show
  1. package/README.md +5 -2
  2. package/dist/html/convert.mjs +38 -14
  3. package/dist/model/content/Body.d.mts +13 -1
  4. package/dist/model/content/Body.mjs +90 -19
  5. package/dist/model/content/Comment.mjs +7 -0
  6. package/dist/model/content/InlinePicture.d.mts +71 -7
  7. package/dist/model/content/InlinePicture.mjs +201 -28
  8. package/dist/model/content/List.mjs +10 -1
  9. package/dist/model/content/Paragraph.d.mts +28 -5
  10. package/dist/model/content/Paragraph.mjs +77 -37
  11. package/dist/model/content/Range.d.mts +18 -2
  12. package/dist/model/content/Range.mjs +194 -64
  13. package/dist/model/content/TrackedChange.d.mts +129 -3
  14. package/dist/model/content/TrackedChange.mjs +577 -12
  15. package/dist/model/content/binder.d.mts +2 -1
  16. package/dist/model/content/binder.mjs +48 -1
  17. package/dist/model/content/index.d.mts +2 -2
  18. package/dist/model/content/index.mjs +1 -1
  19. package/dist/model/content/relationships.d.mts +30 -0
  20. package/dist/model/content/relationships.mjs +133 -0
  21. package/dist/model/content/tree.d.mts +52 -2
  22. package/dist/model/content/tree.mjs +48 -3
  23. package/dist/model/customxml/pictures.d.mts +5 -2
  24. package/dist/model/customxml/pictures.mjs +13 -7
  25. package/dist/model/fonts/families.generated.mjs +2 -2
  26. package/dist/model/fonts/registry.mjs +7 -1
  27. package/dist/model/fonts/substitutions.generated.mjs +2 -2
  28. package/dist/model/fonts/themes.generated.mjs +1 -1
  29. package/dist/model/listnumbering/definitions.mjs +18 -0
  30. package/dist/model/properties/PropertyResolver.d.mts +27 -6
  31. package/dist/model/properties/PropertyResolver.mjs +83 -16
  32. package/dist/model/properties/catalogue.d.mts +15 -1
  33. package/dist/model/properties/catalogue.mjs +80 -27
  34. package/dist/model/properties/table.d.mts +16 -2
  35. package/dist/model/properties/table.mjs +13 -3
  36. package/dist/opc/Load.d.mts +9 -2
  37. package/dist/opc/index.d.mts +2 -2
  38. package/dist/opc/index.mjs +2 -2
  39. package/dist/opc/mce/preprocessor.d.mts +62 -6
  40. package/dist/opc/mce/preprocessor.mjs +142 -35
  41. package/dist/opc/mce/understood.d.mts +10 -0
  42. package/dist/opc/mce/understood.mjs +25 -3
  43. package/dist/packages/OpcPackage.d.mts +7 -0
  44. package/dist/packages/OpcPackage.mjs +15 -3
  45. package/dist/packages/WordprocessingMLPackage.d.mts +35 -2
  46. package/dist/packages/WordprocessingMLPackage.mjs +98 -2
  47. package/dist/parts/XmlPart.d.mts +26 -5
  48. package/dist/parts/XmlPart.mjs +67 -18
  49. package/package.json +2 -2
package/README.md CHANGED
@@ -43,8 +43,11 @@ const ooxml = await pkg.saveFlatOpc(); // pkg:package, for insertOo
43
43
  ```
44
44
 
45
45
  A part that is never touched is written back byte for byte; `getContents()` (or a view over
46
- it) marks a part for re-marshalling. `mc:AlternateContent` is resolved when a part is
47
- unmarshalled, as Word does on open (`{ mcePreprocess: false }` to keep it). Subpaths
46
+ it) marks a part for re-marshalling. `mc:AlternateContent` is kept with every branch, as docx4j
47
+ keeps it: the content API reads the branch Word would (the first `mc:Choice` whose namespaces are
48
+ understood, else the `mc:Fallback`), an edit lands in every branch, and a save writes them all
49
+ (`{ mcePreprocess: true }` resolves the element when a part is unmarshalled instead, as Word does on
50
+ open). Subpaths
48
51
  `@docx4j/core-ts/opc`, `/parts`, `/packages` and `/model` give the layers separately,
49
52
  `/office-js` the `Word` shim (below), `/html` HTML to WordprocessingML (a converter to an
50
53
  intermediate form and a builder from it, CR-005 section 8; the HTML parser is yours, a browser's
@@ -454,19 +454,37 @@ function tableFrom(el, w) {
454
454
  w.report.tables++;
455
455
  return { kind: 'table', rows, style: w.tableStyle };
456
456
  }
457
- /** Block-level content in document order: paragraphs, headings, list items, tables; containers descended into. */
457
+ /** Elements a line holds: gathered with the text beside them into one paragraph when they stand under a container. */
458
+ const INLINE_TAGS = new Set(['span', 'a', 'b', 'strong', 'i', 'em', 'u', 's', 'strike', 'del', 'ins', 'sub', 'sup', 'code', 'font', 'small', 'big', 'mark', 'abbr', 'cite', 'q', 'kbd', 'var', 'samp', 'tt', 'time', 'label', 'wbr', 'br']);
459
+ /** What makes an inline element a container after all: a block inside it (`<span><p>` in Word's HTML, `<a><div>`). */
460
+ const BLOCK_INSIDE = 'p,h1,h2,h3,h4,h5,h6,li,pre,blockquote,ul,ol,dl,table,div,section,article,header,footer,nav,aside,main,figure,figcaption,hr,img';
461
+ /**
462
+ * Block-level content in document order: paragraphs, headings, list items, tables; containers descended into.
463
+ * Text and inline elements met under a container (a cell without a paragraph; ChatGPT's note after a table, a
464
+ * `span` holding a `span` per word) are one paragraph together, up to the next block or the container's end,
465
+ * as a browser lays them out: a paragraph per text node had made a paragraph of every word.
466
+ */
458
467
  function walkBlocks(parent, out, w) {
459
468
  var _a;
460
- const pending = null;
461
- void pending;
469
+ let pending = null;
470
+ const flush = () => {
471
+ if (pending === null)
472
+ return;
473
+ while (pending.length > 0 && 'br' in pending[pending.length - 1])
474
+ pending.pop();
475
+ trimEdges(pending);
476
+ if (pending.length > 0) {
477
+ out.push({ kind: 'paragraph', style: null, inlines: pending });
478
+ w.report.paragraphs++;
479
+ }
480
+ pending = null;
481
+ };
462
482
  for (const node of Array.from(parent.childNodes)) {
463
483
  if (node.nodeType === 3) {
464
- // Bare text under a container (a cell without a paragraph): its own paragraph.
465
- const text = ((_a = node.textContent) !== null && _a !== void 0 ? _a : '').replace(/[ \t\r\n]+/g, ' ').trim();
466
- if (text !== '') {
467
- out.push({ kind: 'paragraph', style: null, inlines: [{ text }] });
468
- w.report.paragraphs++;
469
- }
484
+ if (pending === null && ((_a = node.textContent) !== null && _a !== void 0 ? _a : '').trim() === '')
485
+ continue; // the markup's own line ends between blocks
486
+ pending !== null && pending !== void 0 ? pending : (pending = []);
487
+ walkInline(node, pending, {}, w, false);
470
488
  continue;
471
489
  }
472
490
  if (node.nodeType !== 1)
@@ -475,6 +493,14 @@ function walkBlocks(parent, out, w) {
475
493
  const tag = el.tagName.toLowerCase();
476
494
  if (tag === 'script' || tag === 'style' || tag === 'head' || tag === 'meta' || tag === 'link' || tag === 'title' || tag === 'o:p')
477
495
  continue;
496
+ if (INLINE_TAGS.has(tag) && el.querySelector(BLOCK_INSIDE) === null) {
497
+ if (tag === 'br' && pending === null)
498
+ continue; // a break between blocks starts no paragraph
499
+ pending !== null && pending !== void 0 ? pending : (pending = []);
500
+ walkInline(el, pending, {}, w, false);
501
+ continue;
502
+ }
503
+ flush();
478
504
  if (tag === 'p' || HEADING.test(tag) || tag === 'li' || tag === 'pre' || tag === 'blockquote' && el.querySelector('p') === null) {
479
505
  out.push(paragraphFrom(el, w));
480
506
  continue;
@@ -486,19 +512,17 @@ function walkBlocks(parent, out, w) {
486
512
  continue;
487
513
  }
488
514
  if (tag === 'table') {
489
- if (w.listStack.length === 0 || true)
490
- out.push(tableFrom(el, w));
515
+ out.push(tableFrom(el, w));
491
516
  continue;
492
517
  }
493
518
  if (tag === 'img') {
494
519
  w.drop('images');
495
520
  continue;
496
521
  }
497
- if (tag === 'br')
498
- continue;
499
- // A container (div, body, html, span at block level, blockquote with paragraphs, td outside a table): its blocks.
522
+ // A container (div, body, html, a span holding blocks, blockquote with paragraphs, td outside a table): its blocks.
500
523
  walkBlocks(el, out, w);
501
524
  }
525
+ flush();
502
526
  }
503
527
  /**
504
528
  * Where a parsed fragment's elements are: a browser's `DOMParser` wraps a bare fragment (the text
@@ -192,7 +192,8 @@ export declare class Body {
192
192
  replaceText(find: string, replace: string, options?: SearchOptions): number;
193
193
  /**
194
194
  * Removes everything (section properties stay). While the package tracks changes, every
195
- * paragraph is marked deleted and every row's `w:trPr` takes a `w:del` instead.
195
+ * paragraph is marked deleted and every row's `w:trPr` takes a `w:del` instead. Removed outright,
196
+ * the relationships the content held (its pictures' images) are settled on save (CR-002 section 47).
196
197
  */
197
198
  clear(): void;
198
199
  /**
@@ -256,3 +257,14 @@ export declare class Body {
256
257
  */
257
258
  insertContentControl(kind?: ContentControlType): ContentControl;
258
259
  }
260
+ /**
261
+ * A story's tracked changes resolved (`Body.acceptAll` or `rejectAll`), then those of each text box in
262
+ * it - a `w:txbxContent`, in a DrawingML shape or a VML one - which Word counts as a story of its own
263
+ * (CR-002 section 49). A text box inside a text box is reached through its own story. Returns how many
264
+ * changes were listed.
265
+ *
266
+ * In a kept `mc:AlternateContent` the text box of every branch is resolved, so that each says the same
267
+ * afterwards (docx4j's `McMode.ALL`), and the changes are counted in the selected branch alone, so a
268
+ * text box held in both counts once, as a resolved load's does (CR-010 phase 3).
269
+ */
270
+ export declare function resolveStory(body: Body, what: 'accept' | 'reject'): number;
@@ -1,5 +1,5 @@
1
1
  import { Docx4JException, PropertyResolverNotCreatedException } from '../../opc/exceptions.mjs';
2
- import { typeNameOf, childrenOf, linkParents, BLOCK_LEVEL_TYPES, textOf, textOfView, rowsOf, cellsOf } from './tree.mjs';
2
+ import { typeNameOf, childrenOf, linkParents, BLOCK_LEVEL_TYPES, textOf, textOfView, rowsOf, cellsOf, selectedBranchOf, ALTERNATE_CONTENT } from './tree.mjs';
3
3
  import { r as textRun, br as breakItem, tbl as tableOf } from '@docx4j/generated-objects-ts/builders/wml';
4
4
  import { runOf, paragraphOf, runsOf } from './tree.mjs';
5
5
  import { Paragraph } from './Paragraph.mjs';
@@ -9,10 +9,11 @@ import { sdt as sdtOf, nextSdtId } from '@docx4j/generated-objects-ts/builders/w
9
9
  import { controlIdScope, sdtKindFor, declareSdtExtensions } from '../customxml/insert.mjs';
10
10
  import { InlinePicture, addImage, writableWidthEmu } from './InlinePicture.mjs';
11
11
  import { contentOf } from './ooxml.mjs';
12
+ import { relationshipIdsIn, queueRelationshipRemovals } from './relationships.mjs';
12
13
  import { expandReplacement } from './search.mjs';
13
14
  import { commentApi } from './comments.mjs';
14
15
  import { trackerOf, trackInsertedBlock, markHolderInserted } from './tracking.mjs';
15
- import { trackedChangesOfRow, trackedChangeTokensOfParagraph, groupTouching, BREAK, tablePropertiesChangeOf, cellChangeOf, bodySectionChangeOf, resolveUnlisted, holderInsertionAt } from './TrackedChange.mjs';
16
+ import { trackedChangesOfRow, trackedChangeTokensOfParagraph, groupTouching, BREAK, tablePropertiesChangeOf, cellChangeOf, bodySectionChangeOf, resolveUnlisted, holderInsertionAt, resolving } from './TrackedChange.mjs';
16
17
  import { listsOf, listLabelsOf } from './List.mjs';
17
18
  /**
18
19
  * A subset of Office JS `Word.Body` over any container with block-level content: the main
@@ -264,8 +265,11 @@ export class Body {
264
265
  throw new Docx4JException('This body has no part, so an image cannot be related to it');
265
266
  const { run, drawing } = addImage(this.part, base64, this.container, writableWidthEmu(this.container), options);
266
267
  const paragraph = this.insertParagraph('', location);
267
- paragraph.p.content.push(run);
268
- linkParents(run, paragraph.p);
268
+ // under tracking the picture is an insertion, as its paragraph's mark is (insertBreak's form)
269
+ const tracker = paragraph.changeTracker;
270
+ const item = tracker ? tracker.ins([run]) : run;
271
+ paragraph.p.content.push(item);
272
+ linkParents(item, paragraph.p);
269
273
  return new InlinePicture(drawing, run, paragraph);
270
274
  }
271
275
  insertBreak(type, location) {
@@ -370,11 +374,16 @@ export class Body {
370
374
  }
371
375
  /**
372
376
  * Removes everything (section properties stay). While the package tracks changes, every
373
- * paragraph is marked deleted and every row's `w:trPr` takes a `w:del` instead.
377
+ * paragraph is marked deleted and every row's `w:trPr` takes a `w:del` instead. Removed outright,
378
+ * the relationships the content held (its pictures' images) are settled on save (CR-002 section 47).
374
379
  */
375
380
  clear() {
381
+ var _a;
376
382
  const tracker = this.changeTracker;
377
383
  if (!tracker) {
384
+ const ids = new Set();
385
+ relationshipIdsIn(this.content, ids);
386
+ queueRelationshipRemovals((_a = this.package_) === null || _a === void 0 ? void 0 : _a.pendingRelationshipRemovals, this.part, ids);
378
387
  this.content.length = 0;
379
388
  return;
380
389
  }
@@ -427,14 +436,14 @@ export class Body {
427
436
  // belongs to that change, which accepts or rejects it along with the row.
428
437
  const tokens = [];
429
438
  for (const cell of cellsOf(row.element.value)) {
430
- const cellChange = cellChangeOf(cell.element, cell.container, row.element.value);
439
+ const cellChange = cellChangeOf(cell.element, cell.container, row.element.value, this);
431
440
  if (cellChange)
432
441
  tokens.push(cellChange, BREAK);
433
442
  visit((_b = childrenOf(cell.element.value)) !== null && _b !== void 0 ? _b : [], tokens);
434
443
  tokens.push(BREAK);
435
444
  }
436
445
  const inner = groupTouching(tokens);
437
- const rowChanges = trackedChangesOfRow(row.element, row.container, inner, { element: el, container: items });
446
+ const rowChanges = trackedChangesOfRow(row.element, row.container, inner, { element: el, container: items }, this);
438
447
  if (rowChanges.length > 0)
439
448
  into.push(...rowChanges);
440
449
  else {
@@ -481,18 +490,22 @@ export class Body {
481
490
  * pass that resolves nothing ends it.
482
491
  */
483
492
  resolveAll(what) {
484
- let changes = this.getTrackedChanges();
485
- const count = changes.length;
486
- while (changes.length > 0) {
487
- for (let i = changes.length - 1; i >= 0; i--)
488
- changes[i][what]();
489
- const left = this.getTrackedChanges();
490
- if (left.length >= changes.length)
491
- break;
492
- changes = left;
493
- }
494
- // and what is never listed: a cell merge, a numbering change, records that change nothing
495
- resolveUnlisted(this.content, what);
493
+ let count = 0;
494
+ // one resolution for the lot, so the bookmarks are read before the first and after the last
495
+ resolving(this.package_, this, () => {
496
+ let changes = this.getTrackedChanges();
497
+ count = changes.length;
498
+ while (changes.length > 0) {
499
+ for (let i = changes.length - 1; i >= 0; i--)
500
+ changes[i][what]();
501
+ const left = this.getTrackedChanges();
502
+ if (left.length >= changes.length)
503
+ break;
504
+ changes = left;
505
+ }
506
+ // and what is never listed: a cell merge, a numbering change, records that change nothing
507
+ resolveUnlisted(this.content, what);
508
+ });
496
509
  return count;
497
510
  }
498
511
  /** Every `w:tr` in this body's tables, in document order (rows of nested tables included). */
@@ -777,3 +790,61 @@ function describe(el) {
777
790
  const tn = typeNameOf(el);
778
791
  return `${(_b = (_a = el.name) === null || _a === void 0 ? void 0 : _a.localPart) !== null && _b !== void 0 ? _b : '?'} (${tn !== null && tn !== void 0 ? tn : 'no TYPE_NAME'})`;
779
792
  }
793
+ /**
794
+ * A story's tracked changes resolved (`Body.acceptAll` or `rejectAll`), then those of each text box in
795
+ * it - a `w:txbxContent`, in a DrawingML shape or a VML one - which Word counts as a story of its own
796
+ * (CR-002 section 49). A text box inside a text box is reached through its own story. Returns how many
797
+ * changes were listed.
798
+ *
799
+ * In a kept `mc:AlternateContent` the text box of every branch is resolved, so that each says the same
800
+ * afterwards (docx4j's `McMode.ALL`), and the changes are counted in the selected branch alone, so a
801
+ * text box held in both counts once, as a resolved load's does (CR-010 phase 3).
802
+ */
803
+ export function resolveStory(body, what) {
804
+ let count = what === 'accept' ? body.acceptAll() : body.rejectAll();
805
+ for (const { box, selected } of textBoxesIn(body.container)) {
806
+ const resolved = resolveStory(body.sub(box), what);
807
+ if (selected)
808
+ count += resolved;
809
+ }
810
+ return count;
811
+ }
812
+ /**
813
+ * The `w:txbxContent` of every text box in a story's content, not descending into one found, each with
814
+ * whether it is in a branch a reader takes: false inside a branch of a kept `mc:AlternateContent` other
815
+ * than its selected one (`selectedBranchOf`).
816
+ */
817
+ function textBoxesIn(container) {
818
+ const out = [];
819
+ const seen = new Set();
820
+ const visit = (o, selected) => {
821
+ var _a;
822
+ if (typeof o !== 'object' || o === null || seen.has(o))
823
+ return;
824
+ if (typeof o.nodeType === 'number')
825
+ return; // DOM the model does not type
826
+ seen.add(o);
827
+ if (Array.isArray(o)) {
828
+ for (const item of o)
829
+ visit(item, selected);
830
+ return;
831
+ }
832
+ const typeName = o.TYPE_NAME;
833
+ if (typeName === 'org_docx4j_wml.CTTxbxContent') {
834
+ out.push({ box: o, selected });
835
+ return;
836
+ }
837
+ if (typeName === ALTERNATE_CONTENT) {
838
+ const ac = o;
839
+ const read = selectedBranchOf(ac);
840
+ for (const branch of [...((_a = ac.choice) !== null && _a !== void 0 ? _a : []), ...(ac.fallback ? [ac.fallback] : [])])
841
+ visit(branch.any, selected && branch.any === read);
842
+ return;
843
+ }
844
+ for (const key in o)
845
+ if (key !== 'PARENT')
846
+ visit(o[key], selected);
847
+ };
848
+ visit(container.content, true);
849
+ return out;
850
+ }
@@ -9,6 +9,7 @@ import { Paragraph } from './Paragraph.mjs';
9
9
  import { Range } from './Range.mjs';
10
10
  import { runOf, paragraphOf, typeNameOf } from './tree.mjs';
11
11
  import { revisionDateOf, wordCalendarOf, copyRPr } from './tracking.mjs';
12
+ import { relationshipIdsIn, queueRelationshipRemovals } from './relationships.mjs';
12
13
  import { COMMENT_REFERENCE_STYLE, COMMENT_TEXT_STYLE, commentExOf, commentIdsOf, commentPartsAccess, commentParaId, initialsOf, isDone, markersOf, markersOfParagraph, nextCommentId, paraIdTaken, randomHexId, removeMarkers, setCommentApi, } from './comments.mjs';
13
14
  /**
14
15
  * A subset of Office JS `Word.Comment` over a `w:comment` and the markers that anchor it. A view:
@@ -191,6 +192,12 @@ export class Comment {
191
192
  if (i >= 0)
192
193
  comments.splice(i, 1);
193
194
  }
195
+ // what the comment's own content related to - a picture's image - goes on save when nothing else
196
+ // uses it, as for a picture deleted outright (CR-002 section 50; docx4j's Removals)
197
+ const released = new Set();
198
+ relationshipIdsIn(this.element.content, released);
199
+ const pkg = this.body.package_;
200
+ queueRelationshipRemovals(pkg === null || pkg === void 0 ? void 0 : pkg.pendingRelationshipRemovals, this.parts.commentsPart, released);
194
201
  const paraId = this.paraId;
195
202
  if (paraId === undefined)
196
203
  return;
@@ -1,4 +1,5 @@
1
1
  import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
2
+ import type * as dml from '@docx4j/generated-objects-ts/modules/org_docx4j_dml';
2
3
  import type * as wp from '@docx4j/generated-objects-ts/modules/org_docx4j_dml_wordprocessingDrawing';
3
4
  import { IMAGE_CONTENT_TYPES_BY_EXTENSION } from '../../opc/ContentTypes.mjs';
4
5
  import { ImagePart } from '../../parts/BinaryPart.mjs';
@@ -72,9 +73,35 @@ export declare function addImagePart(source: Part, base64: string): NewImagePart
72
73
  export declare function addImage(source: Part, base64: string, scope: object, maxCx: number | undefined, options?: InlinePictureOptions): NewPicture;
73
74
  /** The writable width of a section in EMU (page width less the margins), for scaling. */
74
75
  export declare function writableWidthEmu(container: object): number | undefined;
76
+ /** The `asvg:svgBlip` in a blip's `a:extLst`, if any: an SVG picture's SVG (CR-002 section 52). */
77
+ export declare function svgBlipOf(blip: dml.CTBlip | undefined): {
78
+ embed?: string;
79
+ } | undefined;
75
80
  /**
76
- * A subset of Office JS `Word.InlinePicture` over a `w:drawing` holding a `wp:inline`. A view:
77
- * the drawing, the run it is in and the paragraph. Sizes are points, as Office JS reports them.
81
+ * Points a blip at a new image the way Word's own picture binding does (test/README.md checks 46 and
82
+ * 47; CR-002 section 52). The blip's effects and other extensions stay.
83
+ * - A raster image goes in `r:embed`, and an `asvg:svgBlip` is taken away. Left in place, Word would go
84
+ * on drawing its old SVG, and would replace the new image with a PNG of that SVG when it saves.
85
+ * - An SVG goes under the `asvg:svgBlip`, and `r:embed` is taken away. Word puts a PNG of the SVG it
86
+ * makes itself in `r:embed`, which this package cannot make, and Word 365 draws the SVG without one.
87
+ * `r:link` is left as it was.
88
+ */
89
+ export declare function setBlipImage(blip: dml.CTBlip, relId: string, svg: boolean): void;
90
+ /**
91
+ * The inline pictures a run's item holds: the item itself when it is a `w:drawing` whose `wp:inline`
92
+ * holds a `pic:pic`, and those in a kept `mc:AlternateContent`'s selected branch (`selectedBranchOf`,
93
+ * CR-010 phase 3). A drawing of anything else, such as a chart, a text box, a group or SmartArt, is no
94
+ * inline picture: Office JS lists none for an inline text box (CR-010 section 12.6, test/README.md
95
+ * check 42).
96
+ */
97
+ export declare function picturesIn(item: Element): Element<wml.Drawing>[];
98
+ /**
99
+ * A subset of Office JS `Word.InlinePicture` over a `w:drawing` holding a `wp:inline` with a `pic:pic`.
100
+ * A view: the drawing, the run it is in and the paragraph. Sizes are points, as Office JS reports them.
101
+ *
102
+ * A picture in a kept `mc:AlternateContent`'s selected branch has the element as its `holder`. Reads and
103
+ * the setters are the selected branch's drawing; `delete` removes the element whole, every branch with
104
+ * it (CR-010 phase 3).
78
105
  */
79
106
  export declare class InlinePicture {
80
107
  /** The `w:drawing` element pair. */
@@ -82,11 +109,15 @@ export declare class InlinePicture {
82
109
  /** The run holding the drawing, and the array holding the run. */
83
110
  readonly run: Element<wml.R>;
84
111
  readonly paragraph: Paragraph;
112
+ /** The run's item the drawing stands in, where that is not the drawing: a kept `mc:AlternateContent`. */
113
+ readonly holder?: Element | undefined;
85
114
  constructor(
86
115
  /** The `w:drawing` element pair. */
87
116
  element: Element<wml.Drawing>,
88
117
  /** The run holding the drawing, and the array holding the run. */
89
- run: Element<wml.R>, paragraph: Paragraph);
118
+ run: Element<wml.R>, paragraph: Paragraph,
119
+ /** The run's item the drawing stands in, where that is not the drawing: a kept `mc:AlternateContent`. */
120
+ holder?: Element | undefined);
90
121
  /** The wp:inline; a floating picture (wp:anchor) is not an InlinePicture, and throws. */
91
122
  get inline(): wp.Inline;
92
123
  /** Width in points, as Office JS. */
@@ -100,18 +131,51 @@ export declare class InlinePicture {
100
131
  /** wp:docPr/@title (typed since objects 0.1.3; before that the attribute was not marshalled, CR-002 section 8). */
101
132
  get altTextTitle(): string;
102
133
  set altTextTitle(text: string);
103
- /** The kind of image, from the content type of the part the picture embeds. */
134
+ /**
135
+ * The kind of image, from the content type of the part `getBase64` reads: `Svg` for an SVG picture
136
+ * (`svgImagePart`), else the `a:blip`'s part's. Office JS gives `null` for an SVG picture, though its
137
+ * typings declare the property non-null and `Word.ImageFormat` has `Svg` (test/README.md check 45);
138
+ * this package gives `Svg`, a departure (CR-002 section 52).
139
+ */
104
140
  get imageFormat(): ImageFormat;
105
141
  /** The relationship id of the embedded image (r:embed), if any (extension). */
106
142
  get relId(): string | undefined;
107
- /** The image's bytes as base64 (Office JS getBase64ImageSrc). */
143
+ /**
144
+ * The relationship id of the SVG the picture embeds beside its image, if any (extension): the
145
+ * `r:embed` of an `asvg:svgBlip` in the `a:blip`'s `a:extLst`, as Office 2016 and later write an SVG
146
+ * picture, with the `a:blip`'s own image a PNG of it for readers that don't understand SVG.
147
+ */
148
+ get svgRelId(): string | undefined;
149
+ /**
150
+ * The image's bytes as base64 (Office JS getBase64ImageSrc). For an SVG picture, the SVG
151
+ * (`svgImagePart`), as Office JS gives it (test/README.md check 43); else the `a:blip`'s image.
152
+ */
108
153
  getBase64(): Promise<string>;
109
154
  /** Office JS's name for `getBase64()`. */
110
155
  getBase64ImageSrc(): Promise<string>;
111
- /** The image part this picture embeds (extension). */
156
+ /** The image part this picture embeds: the `a:blip`'s, which is an SVG picture's PNG (extension). */
112
157
  imagePart(): ImagePart | undefined;
113
- /** Removes the picture; the run goes too when the picture was all it held. */
158
+ /** The SVG part an SVG picture embeds beside its image (`svgRelId`), if any (extension). */
159
+ svgImagePart(): ImagePart | undefined;
160
+ private partFor;
161
+ /**
162
+ * Removes the picture; the run goes too when the picture was all it held. A picture in a kept
163
+ * `mc:AlternateContent` takes the element with it, every branch (`holder`).
164
+ *
165
+ * While the package tracks changes it is marked deleted instead: its run goes into a `w:del`, and
166
+ * when the run held more than the picture, the picture is first given a run of its own with the
167
+ * same properties, so the deletion holds it alone. Accepting the deletion then takes it, and its
168
+ * image part with it (CR-002 section 46). A picture its author inserted under tracking is taken
169
+ * back, as `Paragraph.delete` takes back its own text, and one inside a deletion is refused.
170
+ *
171
+ * A picture removed outright (tracking off, or taken back) queues its image relationship on the
172
+ * package. On save the relationship goes if nothing then references it, and the image part with it
173
+ * when nothing else targets it. Waiting for the save lets a picture cut and pasted back keep its
174
+ * image.
175
+ */
114
176
  delete(): void;
177
+ /** The picture's run in a `w:del`, the picture split into a run of its own when the run held more. */
178
+ private markDeleted;
115
179
  private pic;
116
180
  private resize;
117
181
  }