@docx4j/core-ts 0.4.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.
Files changed (166) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +34 -3
  3. package/dist/html/convert.mjs +40 -15
  4. package/dist/html/elements.mjs +2 -1
  5. package/dist/model/color/ColorMath.d.mts +29 -0
  6. package/dist/model/color/ColorMath.mjs +146 -0
  7. package/dist/model/color/ColorTables.d.mts +6 -0
  8. package/dist/model/color/ColorTables.mjs +83 -0
  9. package/dist/model/color/DrawingMLColors.d.mts +52 -0
  10. package/dist/model/color/DrawingMLColors.mjs +374 -0
  11. package/dist/model/color/ResolvedColor.d.mts +36 -0
  12. package/dist/model/color/ResolvedColor.mjs +65 -0
  13. package/dist/model/color/SpreadsheetColors.d.mts +36 -0
  14. package/dist/model/color/SpreadsheetColors.mjs +84 -0
  15. package/dist/model/color/StyleFill.d.mts +28 -0
  16. package/dist/model/color/StyleFill.mjs +21 -0
  17. package/dist/model/color/ThemeColors.d.mts +86 -0
  18. package/dist/model/color/ThemeColors.mjs +304 -0
  19. package/dist/model/color/WordColors.d.mts +71 -0
  20. package/dist/model/color/WordColors.mjs +121 -0
  21. package/dist/model/color/index.d.mts +6 -0
  22. package/dist/model/color/index.mjs +30 -0
  23. package/dist/model/content/Body.d.mts +153 -19
  24. package/dist/model/content/Body.mjs +570 -131
  25. package/dist/model/content/Comment.d.mts +21 -3
  26. package/dist/model/content/Comment.mjs +202 -19
  27. package/dist/model/content/ContentControl.d.mts +197 -18
  28. package/dist/model/content/ContentControl.mjs +664 -95
  29. package/dist/model/content/Font.d.mts +67 -17
  30. package/dist/model/content/Font.mjs +114 -35
  31. package/dist/model/content/InlinePicture.d.mts +82 -7
  32. package/dist/model/content/InlinePicture.mjs +221 -28
  33. package/dist/model/content/List.mjs +13 -1
  34. package/dist/model/content/Paragraph.d.mts +213 -14
  35. package/dist/model/content/Paragraph.mjs +936 -100
  36. package/dist/model/content/Range.d.mts +242 -11
  37. package/dist/model/content/Range.mjs +975 -119
  38. package/dist/model/content/ResolvedView.d.mts +104 -0
  39. package/dist/model/content/ResolvedView.mjs +596 -0
  40. package/dist/model/content/Table.d.mts +29 -3
  41. package/dist/model/content/Table.mjs +109 -33
  42. package/dist/model/content/TrackedChange.d.mts +301 -16
  43. package/dist/model/content/TrackedChange.mjs +1284 -158
  44. package/dist/model/content/binder.d.mts +2 -1
  45. package/dist/model/content/binder.mjs +48 -1
  46. package/dist/model/content/comments.d.mts +20 -6
  47. package/dist/model/content/comments.mjs +67 -57
  48. package/dist/model/content/generalException.d.mts +18 -0
  49. package/dist/model/content/generalException.mjs +24 -0
  50. package/dist/model/content/index.d.mts +8 -3
  51. package/dist/model/content/index.mjs +7 -2
  52. package/dist/model/content/mathText.d.mts +21 -0
  53. package/dist/model/content/mathText.mjs +267 -0
  54. package/dist/model/content/officeText.d.mts +27 -0
  55. package/dist/model/content/officeText.mjs +74 -0
  56. package/dist/model/content/outline.d.mts +5 -0
  57. package/dist/model/content/outline.mjs +13 -0
  58. package/dist/model/content/placeholders.d.mts +110 -0
  59. package/dist/model/content/placeholders.mjs +253 -0
  60. package/dist/model/content/relationships.d.mts +30 -0
  61. package/dist/model/content/relationships.mjs +133 -0
  62. package/dist/model/content/search.d.mts +72 -0
  63. package/dist/model/content/search.mjs +204 -2
  64. package/dist/model/content/spanEdits.d.mts +159 -0
  65. package/dist/model/content/spanEdits.mjs +728 -0
  66. package/dist/model/content/story.d.mts +44 -0
  67. package/dist/model/content/story.mjs +92 -0
  68. package/dist/model/content/tableColumns.d.mts +1 -1
  69. package/dist/model/content/tableColumns.mjs +108 -80
  70. package/dist/model/content/tableRevisions.d.mts +11 -3
  71. package/dist/model/content/tableRevisions.mjs +72 -42
  72. package/dist/model/content/tableRules.d.mts +30 -0
  73. package/dist/model/content/tableRules.mjs +100 -0
  74. package/dist/model/content/textBoxes.d.mts +18 -0
  75. package/dist/model/content/textBoxes.mjs +105 -0
  76. package/dist/model/content/trackedChangeFilter.d.mts +39 -0
  77. package/dist/model/content/trackedChangeFilter.mjs +81 -0
  78. package/dist/model/content/tracking.d.mts +28 -0
  79. package/dist/model/content/tracking.mjs +149 -10
  80. package/dist/model/content/tree.d.mts +212 -13
  81. package/dist/model/content/tree.mjs +356 -35
  82. package/dist/model/customxml/CustomXmlPartCollection.d.mts +8 -0
  83. package/dist/model/customxml/CustomXmlPartCollection.mjs +34 -11
  84. package/dist/model/customxml/XmlMapping.d.mts +1 -1
  85. package/dist/model/customxml/XmlMapping.mjs +11 -0
  86. package/dist/model/customxml/bindings.d.mts +21 -2
  87. package/dist/model/customxml/bindings.mjs +76 -32
  88. package/dist/model/customxml/kinds.d.mts +8 -3
  89. package/dist/model/customxml/kinds.mjs +26 -5
  90. package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
  91. package/dist/model/customxml/picturePlaceholder.mjs +32 -0
  92. package/dist/model/customxml/pictures.d.mts +9 -5
  93. package/dist/model/customxml/pictures.mjs +31 -13
  94. package/dist/model/customxml/xhtml.mjs +8 -2
  95. package/dist/model/fonts/families.generated.mjs +2 -2
  96. package/dist/model/fonts/registry.mjs +7 -1
  97. package/dist/model/fonts/substitutions.generated.mjs +2 -2
  98. package/dist/model/fonts/themes.generated.mjs +1 -1
  99. package/dist/model/index.d.mts +2 -0
  100. package/dist/model/index.mjs +4 -0
  101. package/dist/model/listnumbering/Emulator.d.mts +37 -5
  102. package/dist/model/listnumbering/Emulator.mjs +63 -9
  103. package/dist/model/listnumbering/definitions.mjs +18 -0
  104. package/dist/model/properties/PropertyResolver.d.mts +87 -7
  105. package/dist/model/properties/PropertyResolver.mjs +197 -17
  106. package/dist/model/properties/catalogue.d.mts +32 -4
  107. package/dist/model/properties/catalogue.mjs +115 -36
  108. package/dist/model/properties/log.d.mts +1 -1
  109. package/dist/model/properties/log.mjs +5 -5
  110. package/dist/model/properties/table.d.mts +16 -2
  111. package/dist/model/properties/table.mjs +17 -5
  112. package/dist/model/text/Extractor.d.mts +289 -0
  113. package/dist/model/text/Extractor.mjs +2162 -0
  114. package/dist/model/text/LinkTargets.d.mts +45 -0
  115. package/dist/model/text/LinkTargets.mjs +170 -0
  116. package/dist/model/text/MarkdownExporter.d.mts +140 -0
  117. package/dist/model/text/MarkdownExporter.mjs +255 -0
  118. package/dist/model/text/PlainText.d.mts +29 -0
  119. package/dist/model/text/PlainText.mjs +539 -0
  120. package/dist/model/text/TextContext.d.mts +161 -0
  121. package/dist/model/text/TextContext.mjs +425 -0
  122. package/dist/model/text/TextOptions.d.mts +150 -0
  123. package/dist/model/text/TextOptions.mjs +278 -0
  124. package/dist/model/text/TextResult.d.mts +504 -0
  125. package/dist/model/text/TextResult.mjs +526 -0
  126. package/dist/model/text/Texts.d.mts +99 -0
  127. package/dist/model/text/Texts.mjs +187 -0
  128. package/dist/model/text/WmlToMarkdown.d.mts +120 -0
  129. package/dist/model/text/WmlToMarkdown.mjs +911 -0
  130. package/dist/model/text/commonmark.d.mts +121 -0
  131. package/dist/model/text/commonmark.mjs +655 -0
  132. package/dist/model/text/index.d.mts +7 -0
  133. package/dist/model/text/index.mjs +8 -0
  134. package/dist/model/text/normalize.d.mts +8 -0
  135. package/dist/model/text/normalize.mjs +13 -0
  136. package/dist/model/text/outline.d.mts +4 -0
  137. package/dist/model/text/outline.mjs +71 -0
  138. package/dist/office-js/fragment.d.mts +7 -5
  139. package/dist/office-js/fragment.mjs +63 -14
  140. package/dist/office-js/proxy.d.mts +8 -0
  141. package/dist/office-js/proxy.mjs +29 -0
  142. package/dist/office-js/run.mjs +2 -0
  143. package/dist/office-js/supported.generated.mjs +16 -0
  144. package/dist/office-js/toApiScript.mjs +21 -5
  145. package/dist/opc/Load.d.mts +9 -2
  146. package/dist/opc/Save.d.mts +17 -0
  147. package/dist/opc/Save.mjs +12 -2
  148. package/dist/opc/index.d.mts +3 -3
  149. package/dist/opc/index.mjs +2 -2
  150. package/dist/opc/mce/preprocessor.d.mts +88 -7
  151. package/dist/opc/mce/preprocessor.mjs +144 -37
  152. package/dist/opc/mce/understood.d.mts +34 -0
  153. package/dist/opc/mce/understood.mjs +55 -3
  154. package/dist/packages/OpcPackage.d.mts +20 -0
  155. package/dist/packages/OpcPackage.mjs +16 -3
  156. package/dist/packages/WordprocessingMLPackage.d.mts +77 -7
  157. package/dist/packages/WordprocessingMLPackage.mjs +242 -11
  158. package/dist/parts/DefaultXmlPart.mjs +2 -2
  159. package/dist/parts/Part.d.mts +10 -2
  160. package/dist/parts/XmlPart.d.mts +35 -32
  161. package/dist/parts/XmlPart.mjs +107 -107
  162. package/dist/parts/wml/comments.mjs +30 -0
  163. package/dist/parts/wml/index.mjs +12 -0
  164. package/dist/xml/dom.d.mts +7 -0
  165. package/dist/xml/dom.mjs +18 -0
  166. package/package.json +2 -2
@@ -4,7 +4,9 @@ import { ContentTypes, IMAGE_CONTENT_TYPES_BY_EXTENSION } from '../../opc/Conten
4
4
  import { base64Decode, base64Encode, decodeXmlText } from '../../xml/dom.mjs';
5
5
  import { ImagePart } from '../../parts/BinaryPart.mjs';
6
6
  import { PartName } from '../../opc/PartName.mjs';
7
- import { find, runOf } from './tree.mjs';
7
+ import { find, runOf, linkParents, revisionKindOf, isElement, typeNameOf, isAlternateContent, selectedBranchOf, assertOutsideBranch } from './tree.mjs';
8
+ import { copyRPr } from './tracking.mjs';
9
+ import { relationshipIdsIn, queueRelationshipRemovals } from './relationships.mjs';
8
10
  /** English Metric Units per inch, and per twip (docx4j UnitsOfMeasurement). */
9
11
  const EMU_PER_INCH = 914400;
10
12
  const EMU_PER_TWIP = 635;
@@ -227,6 +229,14 @@ function freeImageName(pkg, extension) {
227
229
  return name;
228
230
  }
229
231
  }
232
+ /**
233
+ * The run showing an image already related from the part as `relId`, an inline picture `cx` by `cy` EMU, its drawing id
234
+ * the next free one in `scope` and named `Picture <id>`, as `addImage` names one.
235
+ */
236
+ export function imageRunOf(relId, scope, cx, cy) {
237
+ const id = nextDrawingId(scope);
238
+ return runOf([inlinePicture(relId, { cx, cy, id, name: `Picture ${id}`, descr: '' })]);
239
+ }
230
240
  /** An id no other drawing in this part uses: wp:docPr and pic:cNvPr are the same type. */
231
241
  function nextDrawingId(scope) {
232
242
  let max = 0;
@@ -248,6 +258,57 @@ export function writableWidthEmu(container) {
248
258
  const twips = pgSz.w - left - right;
249
259
  return twips > 0 ? twips * EMU_PER_TWIP : undefined;
250
260
  }
261
+ /** The TYPE_NAME of `asvg:svgBlip`, Office 2016's SVG picture extension of an `a:blip`. */
262
+ const SVG_BLIP = 'org_docx4j_com_microsoft_schemas_office_drawing_x2016_SVG_main.CTSVGBlip';
263
+ /** The `a:ext` URI that `asvg:svgBlip` stands under, and its namespace. */
264
+ const SVG_BLIP_EXT_URI = '{96DAC541-7B7A-43D3-8B79-37D633B846F1}';
265
+ const SVG_NS = 'http://schemas.microsoft.com/office/drawing/2016/SVG/main';
266
+ /** The `asvg:svgBlip` in a blip's `a:extLst`, if any: an SVG picture's SVG (CR-002 section 52). */
267
+ export function svgBlipOf(blip) {
268
+ var _a, _b;
269
+ for (const ext of (_b = (_a = blip === null || blip === void 0 ? void 0 : blip.extLst) === null || _a === void 0 ? void 0 : _a.ext) !== null && _b !== void 0 ? _b : []) {
270
+ const any = ext.any;
271
+ if (isElement(any) && typeNameOf(any) === SVG_BLIP)
272
+ return any.value;
273
+ }
274
+ return undefined;
275
+ }
276
+ /**
277
+ * Points a blip at a new image the way Word's own picture binding does (test/README.md checks 46 and
278
+ * 47; CR-002 section 52). The blip's effects and other extensions stay.
279
+ * - A raster image goes in `r:embed`, and an `asvg:svgBlip` is taken away. Left in place, Word would go
280
+ * on drawing its old SVG, and would replace the new image with a PNG of that SVG when it saves.
281
+ * - An SVG goes under the `asvg:svgBlip`, and `r:embed` is taken away. Word puts a PNG of the SVG it
282
+ * makes itself in `r:embed`, which this package cannot make, and Word 365 draws the SVG without one.
283
+ * `r:link` is left as it was.
284
+ */
285
+ export function setBlipImage(blip, relId, svg) {
286
+ var _a, _b;
287
+ if (!svg) {
288
+ blip.embed = relId;
289
+ const list = blip.extLst;
290
+ if (list === null || list === void 0 ? void 0 : list.ext) {
291
+ list.ext = list.ext.filter((ext) => !(isElement(ext.any) && typeNameOf(ext.any) === SVG_BLIP));
292
+ if (list.ext.length === 0)
293
+ delete blip.extLst;
294
+ }
295
+ return;
296
+ }
297
+ delete blip.embed;
298
+ const existing = svgBlipOf(blip);
299
+ if (existing) {
300
+ existing.embed = relId;
301
+ return;
302
+ }
303
+ const list = ((_a = blip.extLst) !== null && _a !== void 0 ? _a : (blip.extLst = { TYPE_NAME: 'org_docx4j_dml.CTOfficeArtExtensionList', ext: [] }));
304
+ const ext = {
305
+ TYPE_NAME: 'org_docx4j_dml.CTOfficeArtExtension',
306
+ uri: SVG_BLIP_EXT_URI,
307
+ any: { name: { namespaceURI: SVG_NS, localPart: 'svgBlip' }, value: { TYPE_NAME: SVG_BLIP, embed: relId } },
308
+ };
309
+ ((_b = list.ext) !== null && _b !== void 0 ? _b : (list.ext = [])).push(ext);
310
+ linkParents(list, blip);
311
+ }
251
312
  const FORMAT_BY_CONTENT_TYPE = {
252
313
  [ContentTypes.IMAGE_PNG]: 'Png', [ContentTypes.IMAGE_X_PNG]: 'Png', [ContentTypes.IMAGE_JPEG]: 'Jpeg',
253
314
  [ContentTypes.IMAGE_GIF]: 'Gif', [ContentTypes.IMAGE_BMP]: 'Bmp', [ContentTypes.IMAGE_TIFF]: 'Tiff',
@@ -255,18 +316,48 @@ const FORMAT_BY_CONTENT_TYPE = {
255
316
  [ContentTypes.IMAGE_WMF]: 'Wmf',
256
317
  };
257
318
  /**
258
- * A subset of Office JS `Word.InlinePicture` over a `w:drawing` holding a `wp:inline`. A view:
259
- * the drawing, the run it is in and the paragraph. Sizes are points, as Office JS reports them.
319
+ * The inline pictures a run's item holds: the item itself when it is a `w:drawing` whose `wp:inline`
320
+ * holds a `pic:pic`, and those in a kept `mc:AlternateContent`'s selected branch (`selectedBranchOf`,
321
+ * CR-010 phase 3). A drawing of anything else, such as a chart, a text box, a group or SmartArt, is no
322
+ * inline picture: Office JS lists none for an inline text box (CR-010 section 12.6, test/README.md
323
+ * check 42).
324
+ */
325
+ export function picturesIn(item) {
326
+ var _a;
327
+ if (isAlternateContent(item)) {
328
+ return ((_a = selectedBranchOf(item.value)) !== null && _a !== void 0 ? _a : []).flatMap((child) => (isElement(child) ? picturesIn(child) : []));
329
+ }
330
+ return item.name.localPart === 'drawing' && holdsInlinePicture(item.value) ? [item] : [];
331
+ }
332
+ /** True for a drawing whose `wp:inline` holds a `pic:pic`. */
333
+ function holdsInlinePicture(drawing) {
334
+ var _a, _b, _c, _d;
335
+ const inline = (_a = drawing.anchorOrInline) === null || _a === void 0 ? void 0 : _a[0];
336
+ if (!inline || inline.TYPE_NAME !== 'org_docx4j_dml_wordprocessingDrawing.Inline')
337
+ return false;
338
+ const first = (_d = (_c = (_b = inline.graphic) === null || _b === void 0 ? void 0 : _b.graphicData) === null || _c === void 0 ? void 0 : _c.any) === null || _d === void 0 ? void 0 : _d[0];
339
+ return isElement(first) && typeNameOf(first) === 'org_docx4j_dml_picture.Pic';
340
+ }
341
+ /**
342
+ * A subset of Office JS `Word.InlinePicture` over a `w:drawing` holding a `wp:inline` with a `pic:pic`.
343
+ * A view: the drawing, the run it is in and the paragraph. Sizes are points, as Office JS reports them.
344
+ *
345
+ * A picture in a kept `mc:AlternateContent`'s selected branch has the element as its `holder`. Reads and
346
+ * the setters are the selected branch's drawing; `delete` removes the element whole, every branch with
347
+ * it (CR-010 phase 3).
260
348
  */
261
349
  export class InlinePicture {
262
350
  constructor(
263
351
  /** The `w:drawing` element pair. */
264
352
  element,
265
353
  /** The run holding the drawing, and the array holding the run. */
266
- run, paragraph) {
354
+ run, paragraph,
355
+ /** The run's item the drawing stands in, where that is not the drawing: a kept `mc:AlternateContent`. */
356
+ holder) {
267
357
  this.element = element;
268
358
  this.run = run;
269
359
  this.paragraph = paragraph;
360
+ this.holder = holder;
270
361
  }
271
362
  /** The wp:inline; a floating picture (wp:anchor) is not an InlinePicture, and throws. */
272
363
  get inline() {
@@ -296,6 +387,7 @@ export class InlinePicture {
296
387
  return (_a = this.inline.docPr.descr) !== null && _a !== void 0 ? _a : '';
297
388
  }
298
389
  set altTextDescription(text) {
390
+ this.assertWritable();
299
391
  this.inline.docPr.descr = text;
300
392
  const p = this.pic();
301
393
  if (p)
@@ -307,22 +399,42 @@ export class InlinePicture {
307
399
  return (_a = this.inline.docPr.title) !== null && _a !== void 0 ? _a : '';
308
400
  }
309
401
  set altTextTitle(text) {
402
+ this.assertWritable();
310
403
  this.inline.docPr.title = text;
311
404
  }
312
- /** The kind of image, from the content type of the part the picture embeds. */
405
+ /**
406
+ * The kind of image, from the content type of the part `getBase64` reads: `Svg` for an SVG picture
407
+ * (`svgImagePart`), else the `a:blip`'s part's. Office JS gives `null` for an SVG picture, though its
408
+ * typings declare the property non-null and `Word.ImageFormat` has `Svg` (test/README.md check 45);
409
+ * this package gives `Svg`, a departure (CR-002 section 52).
410
+ */
313
411
  get imageFormat() {
314
- var _a;
315
- const part = this.imagePart();
316
- return (_a = (part && FORMAT_BY_CONTENT_TYPE[part.contentType])) !== null && _a !== void 0 ? _a : 'Unsupported';
412
+ var _a, _b;
413
+ const part = (_a = this.svgImagePart()) !== null && _a !== void 0 ? _a : this.imagePart();
414
+ return (_b = (part && FORMAT_BY_CONTENT_TYPE[part.contentType])) !== null && _b !== void 0 ? _b : 'Unsupported';
317
415
  }
318
416
  /** The relationship id of the embedded image (r:embed), if any (extension). */
319
417
  get relId() {
320
418
  var _a, _b;
321
419
  return (_b = (_a = this.pic()) === null || _a === void 0 ? void 0 : _a.blipFill.blip) === null || _b === void 0 ? void 0 : _b.embed;
322
420
  }
323
- /** The image's bytes as base64 (Office JS getBase64ImageSrc). */
421
+ /**
422
+ * The relationship id of the SVG the picture embeds beside its image, if any (extension): the
423
+ * `r:embed` of an `asvg:svgBlip` in the `a:blip`'s `a:extLst`, as Office 2016 and later write an SVG
424
+ * picture, with the `a:blip`'s own image a PNG of it for readers that don't understand SVG.
425
+ */
426
+ get svgRelId() {
427
+ var _a, _b;
428
+ const embed = (_b = svgBlipOf((_a = this.pic()) === null || _a === void 0 ? void 0 : _a.blipFill.blip)) === null || _b === void 0 ? void 0 : _b.embed;
429
+ return embed === undefined || embed === '' ? undefined : embed;
430
+ }
431
+ /**
432
+ * The image's bytes as base64 (Office JS getBase64ImageSrc). For an SVG picture, the SVG
433
+ * (`svgImagePart`), as Office JS gives it (test/README.md check 43); else the `a:blip`'s image.
434
+ */
324
435
  async getBase64() {
325
- const part = this.imagePart();
436
+ var _a;
437
+ const part = (_a = this.svgImagePart()) !== null && _a !== void 0 ? _a : this.imagePart();
326
438
  if (!part)
327
439
  throw new Docx4JException('This picture has no image part (a linked or missing image)');
328
440
  return base64Encode(await part.getBytes());
@@ -331,37 +443,115 @@ export class InlinePicture {
331
443
  getBase64ImageSrc() {
332
444
  return this.getBase64();
333
445
  }
334
- /** The image part this picture embeds (extension). */
446
+ /** The image part this picture embeds: the `a:blip`'s, which is an SVG picture's PNG (extension). */
335
447
  imagePart() {
448
+ return this.partFor(this.relId);
449
+ }
450
+ /** The SVG part an SVG picture embeds beside its image (`svgRelId`), if any (extension). */
451
+ svgImagePart() {
452
+ return this.partFor(this.svgRelId);
453
+ }
454
+ partFor(relId) {
336
455
  var _a;
337
- const relId = this.relId;
338
456
  const source = this.paragraph.parentBody.part;
339
457
  if (!relId || !source)
340
458
  return undefined;
341
459
  const part = (_a = source.relationshipsPart) === null || _a === void 0 ? void 0 : _a.getPart(relId);
342
460
  return part instanceof ImagePart ? part : undefined;
343
461
  }
344
- /** Removes the picture; the run goes too when the picture was all it held. */
462
+ /**
463
+ * Removes the picture; the run goes too when the picture was all it held. A picture in a kept
464
+ * `mc:AlternateContent` takes the element with it, every branch (`holder`).
465
+ *
466
+ * While the package tracks changes it is marked deleted instead: its run goes into a `w:del`, and
467
+ * when the run held more than the picture, the picture is first given a run of its own with the
468
+ * same properties, so the deletion holds it alone. Accepting the deletion then takes it, and its
469
+ * image part with it (CR-002 section 46). A picture its author inserted under tracking is taken
470
+ * back, as `Paragraph.delete` takes back its own text, and one inside a deletion is refused.
471
+ *
472
+ * A picture removed outright (tracking off, or taken back) queues its image relationship on the
473
+ * package. On save the relationship goes if nothing then references it, and the image part with it
474
+ * when nothing else targets it. Waiting for the save lets a picture cut and pasted back keep its
475
+ * image.
476
+ */
345
477
  delete() {
346
- var _a;
478
+ var _a, _b;
479
+ this.assertWritable();
480
+ const place = placeOf(this.paragraph.p, this.run);
481
+ if (!place)
482
+ return;
483
+ const revision = place.revision;
484
+ const tracker = this.paragraph.changeTracker;
485
+ if (tracker && ((revision === null || revision === void 0 ? void 0 : revision.kind) === 'del' || (revision === null || revision === void 0 ? void 0 : revision.kind) === 'moveFrom')) {
486
+ throw new Docx4JException(`This picture is inside a w:${revision.kind} (deleted by ${revision.value.author}); reject the deletion first`);
487
+ }
488
+ if (tracker && !tracker.ownInsertion(revision)) {
489
+ this.markDeleted(tracker, place);
490
+ return;
491
+ }
492
+ const item = (_a = this.holder) !== null && _a !== void 0 ? _a : this.element;
347
493
  const content = this.run.value.content;
348
- const at = (_a = content === null || content === void 0 ? void 0 : content.indexOf(this.element)) !== null && _a !== void 0 ? _a : -1;
494
+ const at = (_b = content === null || content === void 0 ? void 0 : content.indexOf(item)) !== null && _b !== void 0 ? _b : -1;
349
495
  if (content && at >= 0)
350
496
  content.splice(at, 1);
351
497
  if (!content || content.length === 0) {
352
- const holder = runHolderOf(this.paragraph.p, this.run);
353
- const i = holder ? holder.indexOf(this.run) : -1;
354
- if (holder && i >= 0)
355
- holder.splice(i, 1);
498
+ const i = place.items.indexOf(this.run);
499
+ if (i >= 0)
500
+ place.items.splice(i, 1);
501
+ if (revision && revision.items.length === 0) { // an insertion left empty goes with it
502
+ const j = revision.owner.indexOf(revision.element);
503
+ if (j >= 0)
504
+ revision.owner.splice(j, 1);
505
+ }
356
506
  }
507
+ const ids = new Set();
508
+ relationshipIdsIn(item, ids);
509
+ const pkg = this.paragraph.parentBody.package_;
510
+ queueRelationshipRemovals(pkg === null || pkg === void 0 ? void 0 : pkg.pendingRelationshipRemovals, this.paragraph.parentBody.part, ids);
511
+ }
512
+ /** The picture's run in a `w:del`, the picture split into a run of its own when the run held more. */
513
+ markDeleted(tracker, place) {
514
+ var _a, _b;
515
+ const run = this.run;
516
+ const at = place.items.indexOf(run);
517
+ const content = ((_a = run.value.content) !== null && _a !== void 0 ? _a : []);
518
+ const item = (_b = this.holder) !== null && _b !== void 0 ? _b : this.element;
519
+ const i = content.indexOf(item);
520
+ if (at < 0 || i < 0)
521
+ return;
522
+ const before = content.slice(0, i);
523
+ const after = content.slice(i + 1);
524
+ const pieces = [];
525
+ let alone = run;
526
+ if (before.length > 0 || after.length > 0) {
527
+ alone = runOf([item], copyRPr(run.value.rPr));
528
+ if (before.length > 0) {
529
+ run.value.content = before;
530
+ pieces.push(run);
531
+ }
532
+ }
533
+ pieces.push(tracker.del([alone]));
534
+ if (after.length > 0)
535
+ pieces.push(runOf(after, copyRPr(run.value.rPr)));
536
+ place.items.splice(at, 1, ...pieces);
537
+ linkParents(pieces, place.parent);
357
538
  }
358
539
  pic() {
359
540
  const any = this.inline.graphic.graphicData.any;
360
541
  const first = any === null || any === void 0 ? void 0 : any[0];
361
542
  return first && typeof first === 'object' && 'value' in first ? first.value : undefined;
362
543
  }
544
+ /**
545
+ * Refuses a write to a picture in a paragraph in a branch of a kept block-, row- or cell-level
546
+ * `mc:AlternateContent` (CR-013 D4). A picture in a run-level element's branch is the run's own, and
547
+ * deleting it removes the element (CR-010 phase 3).
548
+ */
549
+ assertWritable() {
550
+ assertOutsideBranch(this.paragraph.p, 'InlinePicture', 'this picture');
551
+ }
363
552
  resize(cx, cy) {
364
553
  var _a, _b;
554
+ this.assertWritable();
365
555
  const extent = this.inline.extent;
366
556
  const ratio = extent.cy / extent.cx;
367
557
  const w = cx !== null && cx !== void 0 ? cx : Math.max(1, Math.round(cy / ratio));
@@ -375,24 +565,27 @@ export class InlinePicture {
375
565
  }
376
566
  }
377
567
  }
378
- /** The array holding a run inside a paragraph (the paragraph's content, or a holder's). */
379
- function runHolderOf(p, run) {
380
- const seek = (items) => {
381
- var _a, _b, _c;
568
+ function placeOf(p, run) {
569
+ const seek = (items, parent, revision) => {
570
+ var _a, _b, _c, _d;
382
571
  if (!items)
383
572
  return undefined;
384
573
  if (items.includes(run))
385
- return items;
574
+ return revision ? { items, parent, revision } : { items, parent };
386
575
  for (const item of items) {
387
576
  const v = item.value;
388
577
  if (typeof v !== 'object' || v === null)
389
578
  continue;
390
- const nested = seek((_b = (_a = v.content) !== null && _a !== void 0 ? _a : v.customXmlOrSmartTagOrSdt) !== null && _b !== void 0 ? _b : (_c = v.sdtContent) === null || _c === void 0 ? void 0 : _c.content);
391
- if (nested)
392
- return nested;
579
+ const holder = (_a = v.sdtContent) !== null && _a !== void 0 ? _a : v;
580
+ const nested = (_c = (_b = v.content) !== null && _b !== void 0 ? _b : v.customXmlOrSmartTagOrSdt) !== null && _c !== void 0 ? _c : (_d = v.sdtContent) === null || _d === void 0 ? void 0 : _d.content;
581
+ const kind = revisionKindOf(item);
582
+ const inner = kind && nested ? { kind, element: item, value: v, items: nested, owner: items } : revision;
583
+ const found = seek(nested, holder, inner);
584
+ if (found)
585
+ return found;
393
586
  }
394
587
  return undefined;
395
588
  };
396
- return seek(p.content);
589
+ return seek(p.content, p, undefined);
397
590
  }
398
591
  export { IMAGE_CONTENT_TYPES_BY_EXTENSION };
@@ -5,7 +5,7 @@ import { Docx4JException } from '../../opc/exceptions.mjs';
5
5
  import { DEFAULT_NUMBERING_XML } from '../../parts/wml/defaultNumbering.mjs';
6
6
  import { NumberingState, storyKindOf } from '../listnumbering/state.mjs';
7
7
  import { LEVELS } from '../listnumbering/definitions.mjs';
8
- import { isElement, linkParents } from './tree.mjs';
8
+ import { isElement, linkParents, selectedBranchOf, ALTERNATE_CONTENT } from './tree.mjs';
9
9
  import { Font } from './Font.mjs';
10
10
  function packageOf(body) {
11
11
  const pkg = body.package_;
@@ -60,6 +60,9 @@ function numRefOf(paragraph) {
60
60
  * counts in. `test/parity.test.mjs`'s `walkNumbering`, which is the harness's own walk: a text
61
61
  * box's paragraphs stay in this story's list (they are in the part, in document order) but
62
62
  * count in a story of their own, which is docx4j's rule (CR-014 probe P7).
63
+ *
64
+ * A kept `mc:AlternateContent` is walked through its selected branch alone (`selectedBranchOf`,
65
+ * docx4j's `McMode.READ`), so a text box held in both branches counts once (CR-010 phase 3).
63
66
  */
64
67
  function walkStory(root, state, emit) {
65
68
  const walk = (value, current) => {
@@ -70,11 +73,17 @@ function walkStory(root, state, emit) {
70
73
  }
71
74
  if (typeof value !== 'object' || value === null)
72
75
  return;
76
+ if (typeof value.nodeType === 'number')
77
+ return; // DOM the model does not type
73
78
  if (isElement(value)) {
74
79
  walk(value.value, current);
75
80
  return;
76
81
  }
77
82
  const node = value;
83
+ if (node.TYPE_NAME === ALTERNATE_CONTENT) {
84
+ walk(selectedBranchOf(node), current);
85
+ return;
86
+ }
78
87
  let inner = current;
79
88
  if (node.TYPE_NAME === 'org_docx4j_wml.P')
80
89
  emit(node, current);
@@ -155,6 +164,9 @@ function nullObject(className) {
155
164
  return () => ({ isNullObject: true });
156
165
  if (prop === 'then')
157
166
  return undefined;
167
+ // Office JS code loads a null object and syncs before reading isNullObject, as the shim's allows (CR-014 phase 1)
168
+ if (prop === 'load' || prop === 'track' || prop === 'untrack')
169
+ return () => proxy;
158
170
  return fail(prop);
159
171
  },
160
172
  set(_target, prop) {