@office-open/docx 0.10.1 → 0.10.3

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.
@@ -1,6 +1,6 @@
1
- import { DOCX_PARTS, Relationships, TargetModeType, ThemeColor, appPropertiesDesc, blipDesc, buildContentTypeOverrides, convertEmuToPixels, convertInchesToTwip, convertPixelsToEmu, convertToEmu, convertToTwip, convertUniversalMeasureToEmu, customGeometryDesc, customPropertiesDesc, decimalNumber, derivePasswordHash, effectListDesc, eighthPointMeasureValue, fillDesc, hexColorValue, hpsMeasureValue, measurementOrPercentValue, outlineDesc, parseColorChoice, pointMeasureValue, signedTwipsMeasureValue, toUint8Array, twipsMeasureValue, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid, xsdVerticalMergeRev } from "@office-open/core";
2
- import { attr, attrBool, attrMeasure, attrNum, children, colorAttr, element, escapeXml, findChild, findDeep, stringify, textOf } from "@office-open/xml";
3
- import { calculateEffectExtent, createColorElement, createEffectDag, createScene3D, createShape3D, customGeometryDesc as customGeometryDesc$1, effectListDesc as effectListDesc$1, extractBlipFillMedia, fillDesc as fillDesc$1, outlineDesc as outlineDesc$1, scene3DDesc, shape3DDesc, transform2DDesc } from "@office-open/core/drawingml";
1
+ import { DOCX_PARTS, Media, Relationships, TargetModeType, ThemeColor, appPropertiesDesc, blipDesc, buildContentTypeOverrides, convertEmuToPixels, convertInchesToTwip, convertPixelsToEmu, convertToEmu, convertToTwip, convertUniversalMeasureToEmu, customGeometryDesc, customPropertiesDesc, decimalNumber, derivePasswordHash, effectListDesc, eighthPointMeasureValue, fillDesc, hexColorValue, hpsMeasureValue, measurementOrPercentValue, outlineDesc, parseColorChoice, pointMeasureValue, presetGeometryDesc, signedTwipsMeasureValue, toUint8Array, twipsMeasureValue, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid, xsdVerticalMergeRev } from "@office-open/core";
2
+ import { calculateEffectExtent, createColorElement, createEffectDag, createScene3D, createShape3D, customGeometryDesc as customGeometryDesc$1, effectListDesc as effectListDesc$1, fillDesc as fillDesc$1, outlineDesc as outlineDesc$1, presetGeometryDesc as presetGeometryDesc$1, scene3DDesc, shape3DDesc, transform2DDesc } from "@office-open/core/drawingml";
3
+ import { attr, attrBool, attrMeasure, attrNum, children, colorAttr, element, escapeXml, findChild, findFirst, stringify, textOf } from "@office-open/xml";
4
4
  import { chartSpaceDesc } from "@office-open/core/chart";
5
5
  import { createDataModel } from "@office-open/core/smartart";
6
6
  //#region src/parts/paragraph/formatting/alignment.ts
@@ -295,95 +295,6 @@ const createTransformation = (options) => ({
295
295
  rotation: options.rotation ? options.rotation * 6e4 : void 0,
296
296
  ...options.effectExtent ? { effectExtent: options.effectExtent } : {}
297
297
  });
298
- /**
299
- * Manages embedded media (images) in a document.
300
- *
301
- * Media stores all images referenced in the document and provides
302
- * access to their data for packaging into the DOCX file. Each image
303
- * is stored with a unique key for retrieval.
304
- *
305
- * @example
306
- * ```typescript
307
- * const media = new Media();
308
- * media.addImage("image1", {
309
- * type: "png",
310
- * fileName: "image1.png",
311
- * transformation: {
312
- * pixels: { x: 200, y: 100 },
313
- * emus: { x: 1828800, y: 914400 }
314
- * },
315
- * data: imageBuffer
316
- * });
317
- * const allImages = media.Array;
318
- * ```
319
- */
320
- var Media = class {
321
- map;
322
- nextMediaCounter = 0;
323
- constructor() {
324
- this.map = /* @__PURE__ */ new Map();
325
- }
326
- /**
327
- * Allocates the next sequential media file name (Office-style `image1.png`,
328
- * `image2.png`, …). The counter is package-global because media is shared
329
- * across the document, headers, and footers, matching MS Office's numbering.
330
- *
331
- * Deterministic across runs (unlike random ids) so round-trip output is stable
332
- * and diffable. Callers pair this with {@link findByContent} to reuse an
333
- * existing entry for byte-identical content before allocating a new name.
334
- *
335
- * @param type - File extension / image type token (e.g. "png", "jpg")
336
- * @returns A sequential file name like `image3.png`
337
- */
338
- nextMediaName(type) {
339
- return `image${++this.nextMediaCounter}.${type}`;
340
- }
341
- /**
342
- * Adds an image to the media collection.
343
- *
344
- * @param key - Unique identifier for this image
345
- * @param mediaData - Complete image data including file name, transformation, and raw data
346
- */
347
- addImage(key, mediaData) {
348
- this.map.set(key, mediaData);
349
- }
350
- /**
351
- * Finds an existing image with byte-identical content (content-based dedup).
352
- *
353
- * Returns the matching entry's key (fileName) so callers reuse it instead of
354
- * registering a duplicate — e.g. a VML fallback image that mirrors the Choice
355
- * blip should share one relationship/file, matching Office's output.
356
- *
357
- * @param data - Raw image bytes to search for
358
- * @returns The matching entry's key, or `undefined` if no match
359
- */
360
- findByContent(data) {
361
- for (const [key, md] of this.map) {
362
- const existing = toUint8Array(md.data);
363
- if (existing.length !== data.length) continue;
364
- let match = true;
365
- for (let i = 0; i < existing.length; i++) if (existing[i] !== data[i]) {
366
- match = false;
367
- break;
368
- }
369
- if (match) return key;
370
- }
371
- }
372
- /**
373
- * Gets all images as an array.
374
- *
375
- * @returns Read-only array of all media data in the collection
376
- */
377
- get array() {
378
- return [...this.map.values()];
379
- }
380
- };
381
- //#endregion
382
- //#region src/shared/media/data.ts
383
- /**
384
- * @ignore
385
- */
386
- const WORKAROUND2 = "";
387
298
  //#endregion
388
299
  //#region src/parts/paragraph/run/image-run.ts
389
300
  const createImageData$1 = (data, transformation, key, sourceRectangle, nonVisualProperties) => ({
@@ -558,7 +469,7 @@ const createBodyProperties = (options = {}) => {
558
469
  * (noAutofit/normAutofit/spAutoFit). prstTxWarp/scene3d/text-3D are not yet
559
470
  * parsed (later phase).
560
471
  */
561
- const parseBodyProperties = (el) => {
472
+ const parseBodyProperties = (el, ctx) => {
562
473
  const result = {};
563
474
  const rotation = attrNum(el, "rot");
564
475
  if (rotation !== void 0) result.rotation = rotation;
@@ -610,6 +521,31 @@ const parseBodyProperties = (el) => {
610
521
  result.normAutofit = normOpts;
611
522
  } else if (findChild(el, "a:spAutoFit")) result.spAutoFit = true;
612
523
  }
524
+ const prstTxWarp = findChild(el, "a:prstTxWarp");
525
+ if (prstTxWarp) {
526
+ const preset = attr(prstTxWarp, "prst") ?? "";
527
+ const avLst = findChild(prstTxWarp, "a:avLst");
528
+ const adjustments = [];
529
+ for (const gd of avLst?.elements ?? []) if (gd.type === "element" && gd.name === "a:gd") adjustments.push({
530
+ name: attr(gd, "name") ?? "",
531
+ formula: attr(gd, "fmla") ?? ""
532
+ });
533
+ result.prstTxWarp = {
534
+ preset,
535
+ ...adjustments.length > 0 ? { adjustments } : {}
536
+ };
537
+ }
538
+ const scene3d = findChild(el, "a:scene3d");
539
+ if (scene3d) result.scene3d = scene3DDesc.parse(scene3d, ctx);
540
+ const sp3d = findChild(el, "a:sp3d");
541
+ if (sp3d) result.sp3d = shape3DDesc.parse(sp3d, ctx);
542
+ else {
543
+ const flatTx = findChild(el, "a:flatTx");
544
+ if (flatTx) {
545
+ const z = attrNum(flatTx, "z");
546
+ result.flatTx = z !== void 0 ? { z } : {};
547
+ }
548
+ }
613
549
  return result;
614
550
  };
615
551
  //#endregion
@@ -1356,15 +1292,15 @@ const objectDesc = {
1356
1292
  const styleHeight = typeof heightVal === "number" ? `${heightVal}px` : heightVal;
1357
1293
  const shapeChildren = [];
1358
1294
  if (opts.iconImage) {
1359
- const iconFileName = ctx.file.media.nextMediaName(opts.iconImage.type);
1360
- const iconMediaData = {
1361
- type: opts.iconImage.type,
1362
- ...createImageData$1(toUint8Array(opts.iconImage.data), {
1295
+ const rawData = toUint8Array(opts.iconImage.data);
1296
+ const iconType = opts.iconImage.type;
1297
+ const { fileName: iconFileName } = ctx.file.media.addMedia(rawData, iconType, (fileName) => ({
1298
+ type: iconType,
1299
+ ...createImageData$1(rawData, {
1363
1300
  width: widthVal,
1364
1301
  height: heightVal
1365
- }, iconFileName)
1366
- };
1367
- ctx.file.media.addImage(iconFileName, iconMediaData);
1302
+ }, fileName)
1303
+ }));
1368
1304
  const titleAttr = opts.iconImage.title ? ` o:title="${opts.iconImage.title}"` : "";
1369
1305
  shapeChildren.push(`<v:imagedata r:id="{${iconFileName}}"${titleAttr}/>`);
1370
1306
  }
@@ -2392,9 +2328,6 @@ function stringifyRunProperties(opts) {
2392
2328
  *
2393
2329
  * @module
2394
2330
  */
2395
- function escapeAttr$2(s) {
2396
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
2397
- }
2398
2331
  const ALTCHUNK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
2399
2332
  function wrapHtmlDocument(fragment) {
2400
2333
  if (/<(!DOCTYPE|html|HTML)/i.test(fragment)) return fragment;
@@ -2406,8 +2339,8 @@ const altChunkDesc = {
2406
2339
  const relId = uniqueId();
2407
2340
  const extension = opts.extension;
2408
2341
  const partPath = `afchunks/afchunk${relId}.${extension}`;
2409
- const rawData = typeof opts.data === "string" ? new TextEncoder().encode(opts.data) : opts.data;
2410
- const data = opts.contentType === "text/html" && typeof opts.data === "string" ? new TextEncoder().encode(wrapHtmlDocument(opts.data)) : rawData;
2342
+ const rawData = typeof opts.data === "string" ? toUint8Array(opts.data) : opts.data;
2343
+ const data = opts.contentType === "text/html" && typeof opts.data === "string" ? toUint8Array(wrapHtmlDocument(opts.data)) : rawData;
2411
2344
  ctx.fileData.document.relationships.addRelationship(relId, ALTCHUNK_REL_TYPE, partPath);
2412
2345
  ctx.fileData.altChunks.addAltChunk(relId, {
2413
2346
  key: relId,
@@ -2479,28 +2412,25 @@ const subDocDesc = {
2479
2412
  return { data: new Uint8Array(0) };
2480
2413
  }
2481
2414
  };
2482
- function escapeXml$2(s) {
2483
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
2484
- }
2485
2415
  function sdtListItemXml(item, forceValue) {
2486
2416
  const attrs = [];
2487
- if (item.displayText !== void 0) attrs.push(`w:displayText="${escapeXml$2(item.displayText)}"`);
2417
+ if (item.displayText !== void 0) attrs.push(`w:displayText="${escapeXml(item.displayText)}"`);
2488
2418
  const value = item.value ?? (forceValue ? item.displayText : void 0);
2489
- if (value !== void 0) attrs.push(`w:value="${escapeXml$2(value)}"`);
2419
+ if (value !== void 0) attrs.push(`w:value="${escapeXml(value)}"`);
2490
2420
  return `<w:listItem ${attrs.join(" ")}/>`;
2491
2421
  }
2492
2422
  function sdtListTypeXml(name, options) {
2493
2423
  const parts = [];
2494
2424
  if (options.items) for (const item of options.items) parts.push(sdtListItemXml(item, name === "w:dropDownList"));
2495
2425
  const attrs = [];
2496
- if (options.lastValue !== void 0) attrs.push(`w:lastValue="${escapeXml$2(options.lastValue)}"`);
2426
+ if (options.lastValue !== void 0) attrs.push(`w:lastValue="${escapeXml(options.lastValue)}"`);
2497
2427
  const attrStr = attrs.length ? " " + attrs.join(" ") : "";
2498
2428
  return parts.length ? `<${name}${attrStr}>${parts.join("")}</${name}>` : `<${name}${attrStr}/>`;
2499
2429
  }
2500
2430
  function sdtDateXml(options) {
2501
2431
  const parts = [];
2502
- if (options.dateFormat !== void 0) parts.push(`<w:dateFormat w:val="${escapeXml$2(options.dateFormat)}"/>`);
2503
- if (options.languageId !== void 0) parts.push(`<w:lid w:val="${escapeXml$2(options.languageId)}"/>`);
2432
+ if (options.dateFormat !== void 0) parts.push(`<w:dateFormat w:val="${escapeXml(options.dateFormat)}"/>`);
2433
+ if (options.languageId !== void 0) parts.push(`<w:lid w:val="${escapeXml(options.languageId)}"/>`);
2504
2434
  if (options.storeMappedDataAs !== void 0) parts.push(`<w:storeMappedDataAs w:val="${options.storeMappedDataAs}"/>`);
2505
2435
  if (options.calendar !== void 0) parts.push(`<w:calendar w:val="${options.calendar}"/>`);
2506
2436
  const attrs = [];
@@ -2509,14 +2439,14 @@ function sdtDateXml(options) {
2509
2439
  return parts.length ? `<w:date${attrStr}>${parts.join("")}</w:date>` : `<w:date${attrStr}/>`;
2510
2440
  }
2511
2441
  function sdtDataBindingXml(options) {
2512
- const attrs = [`w:xpath="${escapeXml$2(options.xpath)}"`, `w:storeItemID="${escapeXml$2(options.storeItemID)}"`];
2513
- if (options.prefixMappings !== void 0) attrs.push(`w:prefixMappings="${escapeXml$2(options.prefixMappings)}"`);
2442
+ const attrs = [`w:xpath="${escapeXml(options.xpath)}"`, `w:storeItemID="${escapeXml(options.storeItemID)}"`];
2443
+ if (options.prefixMappings !== void 0) attrs.push(`w:prefixMappings="${escapeXml(options.prefixMappings)}"`);
2514
2444
  return `<w:dataBinding ${attrs.join(" ")}/>`;
2515
2445
  }
2516
2446
  function sdtDocPartXml(name, options) {
2517
2447
  const parts = [];
2518
- if (options.gallery !== void 0) parts.push(`<w:docPartGallery w:val="${escapeXml$2(options.gallery)}"/>`);
2519
- if (options.category !== void 0) parts.push(`<w:docPartCategory w:val="${escapeXml$2(options.category)}"/>`);
2448
+ if (options.gallery !== void 0) parts.push(`<w:docPartGallery w:val="${escapeXml(options.gallery)}"/>`);
2449
+ if (options.category !== void 0) parts.push(`<w:docPartCategory w:val="${escapeXml(options.category)}"/>`);
2520
2450
  if (options.unique !== void 0) parts.push(options.unique ? "<w:docPartUnique/>" : "<w:docPartUnique w:val=\"0\"/>");
2521
2451
  return parts.length ? `<${name}>${parts.join("")}</${name}>` : `<${name}/>`;
2522
2452
  }
@@ -2543,18 +2473,18 @@ const DEFAULT_UNCHECKED = {
2543
2473
  function sdtCheckboxXml(opts) {
2544
2474
  const checked = opts.checkedState ?? DEFAULT_CHECKED;
2545
2475
  const unchecked = opts.uncheckedState ?? DEFAULT_UNCHECKED;
2546
- return `<w14:checkbox ${W14_NS}>${(opts.checked ? "<w14:checked/>" : "<w14:checked w14:val=\"0\"/>") + `<w14:checkedState w14:val="${escapeXml$2(checked.val)}" w14:font="${escapeXml$2(checked.font ?? CHECKBOX_FONT)}"/><w14:uncheckedState w14:val="${escapeXml$2(unchecked.val)}" w14:font="${escapeXml$2(unchecked.font ?? CHECKBOX_FONT)}"/>`}</w14:checkbox>`;
2476
+ return `<w14:checkbox ${W14_NS}>${(opts.checked ? "<w14:checked/>" : "<w14:checked w14:val=\"0\"/>") + `<w14:checkedState w14:val="${escapeXml(checked.val)}" w14:font="${escapeXml(checked.font ?? CHECKBOX_FONT)}"/><w14:uncheckedState w14:val="${escapeXml(unchecked.val)}" w14:font="${escapeXml(unchecked.font ?? CHECKBOX_FONT)}"/>`}</w14:checkbox>`;
2547
2477
  }
2548
2478
  /** Build the run that renders a checkbox content control's current state symbol. */
2549
2479
  function checkboxSymbolRunInner(cb) {
2550
2480
  const symbol = cb.checked ?? false ? cb.checkedState ?? DEFAULT_CHECKED : cb.uncheckedState ?? DEFAULT_UNCHECKED;
2551
- const font = escapeXml$2(symbol.font ?? CHECKBOX_FONT);
2552
- return `<w:r><w:rPr><w:rFonts w:ascii="${font}" w:hAnsi="${font}"/></w:rPr><w:t>${escapeXml$2(String.fromCodePoint(parseInt(symbol.val, 16)))}</w:t></w:r>`;
2481
+ const font = escapeXml(symbol.font ?? CHECKBOX_FONT);
2482
+ return `<w:r><w:rPr><w:rFonts w:ascii="${font}" w:hAnsi="${font}"/></w:rPr><w:t>${escapeXml(String.fromCodePoint(parseInt(symbol.val, 16)))}</w:t></w:r>`;
2553
2483
  }
2554
2484
  function stringifySdtPr(opts) {
2555
2485
  const parts = [];
2556
- if (opts.alias !== void 0) parts.push(`<w:alias w:val="${escapeXml$2(opts.alias)}"/>`);
2557
- if (opts.tag !== void 0) parts.push(`<w:tag w:val="${escapeXml$2(opts.tag)}"/>`);
2486
+ if (opts.alias !== void 0) parts.push(`<w:alias w:val="${escapeXml(opts.alias)}"/>`);
2487
+ if (opts.tag !== void 0) parts.push(`<w:tag w:val="${escapeXml(opts.tag)}"/>`);
2558
2488
  if (opts.id !== void 0) parts.push(`<w:id w:val="${opts.id}"/>`);
2559
2489
  if (opts.lock !== void 0) parts.push(`<w:lock w:val="${opts.lock}"/>`);
2560
2490
  if (opts.temporary !== void 0) parts.push(onOffAttr("w:temporary", opts.temporary));
@@ -2787,10 +2717,10 @@ const sdtBlockDesc = {
2787
2717
  };
2788
2718
  function buildCustomXmlPropertiesXml(pr) {
2789
2719
  const parts = ["<w:customXmlPr>"];
2790
- if (pr.placeholder !== void 0) parts.push(`<w:placeholder w:val="${escapeAttr$2(pr.placeholder)}"/>`);
2720
+ if (pr.placeholder !== void 0) parts.push(`<w:placeholder w:val="${escapeXml(pr.placeholder)}"/>`);
2791
2721
  if (pr.attributes) for (const attr of pr.attributes) {
2792
- const attrParts = [`w:name="${escapeAttr$2(attr.name)}"`, `w:val="${escapeAttr$2(attr.val)}"`];
2793
- if (attr.uri !== void 0) attrParts.push(`w:uri="${escapeAttr$2(attr.uri)}"`);
2722
+ const attrParts = [`w:name="${escapeXml(attr.name)}"`, `w:val="${escapeXml(attr.val)}"`];
2723
+ if (attr.uri !== void 0) attrParts.push(`w:uri="${escapeXml(attr.uri)}"`);
2794
2724
  parts.push(`<w:attr ${attrParts.join(" ")}/>`);
2795
2725
  }
2796
2726
  parts.push("</w:customXmlPr>");
@@ -2799,10 +2729,14 @@ function buildCustomXmlPropertiesXml(pr) {
2799
2729
  /**
2800
2730
  * Serialize the common customXml shell (element/uri/customXmlPr) wrapping
2801
2731
  * arbitrary content. Shared by all four customXml levels (block/run/row/cell).
2732
+ *
2733
+ * @deprecated Microsoft Word removed support for `w:customXml` inline markup on
2734
+ * 2010-01-10 (i4i Inc. v. Microsoft ruling); Word deletes these elements on
2735
+ * open. Prefer content controls (`w:sdt`) or a `customXml` part.
2802
2736
  */
2803
2737
  function stringifyCustomXmlShell(opts, contentXml) {
2804
- const attrs = [`w:element="${escapeAttr$2(opts.element)}"`];
2805
- if (opts.uri !== void 0) attrs.push(`w:uri="${escapeAttr$2(opts.uri)}"`);
2738
+ const attrs = [`w:element="${escapeXml(opts.element)}"`];
2739
+ if (opts.uri !== void 0) attrs.push(`w:uri="${escapeXml(opts.uri)}"`);
2806
2740
  const prXml = opts.customXmlPr ? buildCustomXmlPropertiesXml(opts.customXmlPr) : "";
2807
2741
  return `<w:customXml ${attrs.join(" ")}>${prXml}${contentXml}</w:customXml>`;
2808
2742
  }
@@ -4264,15 +4198,15 @@ function stringifyMathInput(value) {
4264
4198
  if ("integral" in value) return stringifyNAry(value.integral, "∫");
4265
4199
  if ("limitLower" in value) {
4266
4200
  const opts = value.limitLower;
4267
- return `<m:limLow>${opts.properties ? "" : ""}<m:e>${stringifyChildren(opts.children)}</m:e><m:lim>${stringifyChildren(opts.limit)}</m:lim></m:limLow>`;
4201
+ return `<m:limLow><m:e>${stringifyChildren(opts.children)}</m:e><m:lim>${stringifyChildren(opts.limit)}</m:lim></m:limLow>`;
4268
4202
  }
4269
4203
  if ("limitUpper" in value) {
4270
4204
  const opts = value.limitUpper;
4271
- return `<m:limUpp>${opts.properties ? "" : ""}<m:e>${stringifyChildren(opts.children)}</m:e><m:lim>${stringifyChildren(opts.limit)}</m:lim></m:limUpp>`;
4205
+ return `<m:limUpp><m:e>${stringifyChildren(opts.children)}</m:e><m:lim>${stringifyChildren(opts.limit)}</m:lim></m:limUpp>`;
4272
4206
  }
4273
4207
  if ("function" in value) {
4274
4208
  const opts = value.function;
4275
- return `<m:func>${opts.properties ? "" : ""}<m:fName>${stringifyChildren(opts.name)}</m:fName><m:e>${stringifyChildren(opts.children)}</m:e></m:func>`;
4209
+ return `<m:func><m:fName>${stringifyChildren(opts.name)}</m:fName><m:e>${stringifyChildren(opts.children)}</m:e></m:func>`;
4276
4210
  }
4277
4211
  if ("matrix" in value) {
4278
4212
  const opts = value.matrix;
@@ -4836,13 +4770,17 @@ function stringifyBodyChild(child, ctx) {
4836
4770
  if ("customXml" in child) return customXmlBlockDesc.stringify(child.customXml, ctx) ?? "";
4837
4771
  if ("bookmarkStart" in child) {
4838
4772
  const bs = child.bookmarkStart;
4839
- const bsDisp = bs.displacedByCustomXml ? ` w:displacedByCustomXml="${bs.displacedByCustomXml}"` : "";
4840
- return `<w:bookmarkStart w:id="${bs.id}" w:name="${bs.name}"${bsDisp}/>`;
4773
+ const a = [`w:id="${bs.id}"`, `w:name="${escapeXml(bs.name)}"`];
4774
+ if (bs.displacedByCustomXml) a.push(`w:displacedByCustomXml="${bs.displacedByCustomXml}"`);
4775
+ if (bs.colFirst !== void 0) a.push(`w:colFirst="${bs.colFirst}"`);
4776
+ if (bs.colLast !== void 0) a.push(`w:colLast="${bs.colLast}"`);
4777
+ return `<w:bookmarkStart ${a.join(" ")}/>`;
4841
4778
  }
4842
4779
  if ("bookmarkEnd" in child) {
4843
4780
  const be = child.bookmarkEnd;
4844
- const beDisp = be.displacedByCustomXml ? ` w:displacedByCustomXml="${be.displacedByCustomXml}"` : "";
4845
- return `<w:bookmarkEnd w:id="${be.id}"${beDisp}/>`;
4781
+ const a = [`w:id="${be.id}"`];
4782
+ if (be.displacedByCustomXml) a.push(`w:displacedByCustomXml="${be.displacedByCustomXml}"`);
4783
+ return `<w:bookmarkEnd ${a.join(" ")}/>`;
4846
4784
  }
4847
4785
  if ("rawXml" in child) return child.rawXml;
4848
4786
  throw new Error("Unknown section child type");
@@ -4851,21 +4789,25 @@ function stringifyBodyChild(child, ctx) {
4851
4789
  const vmlStyleMap = styleToKeyMap;
4852
4790
  function stringifyDocumentBackground(opts, ctx) {
4853
4791
  if (opts.rawXml) {
4854
- if (opts.rawMedia) for (const m of opts.rawMedia) ctx.file.media.addImage(m.fileName, {
4855
- type: m.type,
4856
- data: toUint8Array(m.data),
4857
- fileName: m.fileName,
4858
- transformation: {
4859
- emus: {
4860
- x: 0,
4861
- y: 0
4862
- },
4863
- pixels: {
4864
- x: 0,
4865
- y: 0
4792
+ if (opts.rawMedia) for (const m of opts.rawMedia) {
4793
+ const data = toUint8Array(m.data);
4794
+ const entry = ctx.file.media.addMedia(data, m.type, (fileName) => ({
4795
+ type: m.type,
4796
+ data,
4797
+ fileName,
4798
+ transformation: {
4799
+ emus: {
4800
+ x: 0,
4801
+ y: 0
4802
+ },
4803
+ pixels: {
4804
+ x: 0,
4805
+ y: 0
4806
+ }
4866
4807
  }
4867
- }
4868
- });
4808
+ }), m.fileName);
4809
+ if (entry.fileName !== m.fileName) opts.rawXml = opts.rawXml.split(`{${m.fileName}}`).join(`{${entry.fileName}}`);
4810
+ }
4869
4811
  return opts.rawXml;
4870
4812
  }
4871
4813
  const attrs = [];
@@ -4875,12 +4817,12 @@ function stringifyDocumentBackground(opts, ctx) {
4875
4817
  if (opts.themeTint !== void 0) attrs.push(`w:themeTint="${uCharHexNumber(opts.themeTint)}"`);
4876
4818
  const attrStr = attrs.join(" ");
4877
4819
  if (opts.image) {
4878
- const fileName = ctx.file.media.nextMediaName(opts.image.type);
4879
- const rawData = toUint8Array(opts.image.data);
4880
- ctx.file.media.addImage(fileName, {
4881
- type: opts.image.type,
4820
+ const image = opts.image;
4821
+ const rawData = toUint8Array(image.data);
4822
+ const { fileName } = ctx.file.media.addMedia(rawData, image.type, (name) => ({
4823
+ type: image.type,
4882
4824
  data: rawData,
4883
- fileName,
4825
+ fileName: name,
4884
4826
  transformation: {
4885
4827
  emus: {
4886
4828
  x: 0,
@@ -4891,7 +4833,7 @@ function stringifyDocumentBackground(opts, ctx) {
4891
4833
  y: 0
4892
4834
  }
4893
4835
  }
4894
- });
4836
+ }));
4895
4837
  return `<w:background ${attrStr}>${`<v:background id="_x0000_s1025"><v:fill r:id="{${fileName}}" o:title="${fileName}" recolor="t" type="frame"/></v:background>`}</w:background>`;
4896
4838
  }
4897
4839
  return `<w:background ${attrStr}/>`;
@@ -5334,6 +5276,12 @@ function parseMoveRangeStart(el) {
5334
5276
  if (author !== void 0) m.author = author;
5335
5277
  const date = attr(el, "w:date");
5336
5278
  if (date !== void 0) m.date = date;
5279
+ const disp = attr(el, "w:displacedByCustomXml");
5280
+ if (disp === "before" || disp === "after") m.displacedByCustomXml = disp;
5281
+ const colFirst = attrNum(el, "w:colFirst");
5282
+ if (colFirst !== void 0) m.colFirst = colFirst;
5283
+ const colLast = attrNum(el, "w:colLast");
5284
+ if (colLast !== void 0) m.colLast = colLast;
5337
5285
  return m;
5338
5286
  }
5339
5287
  /** Parse a customXml range start (Ins/Del/MoveFrom/MoveTo). */
@@ -5347,6 +5295,15 @@ function parseCustomXmlRangeStart(el) {
5347
5295
  if (date !== void 0) m.date = date;
5348
5296
  return m;
5349
5297
  }
5298
+ /** Parse a CT_MarkupRange end marker (id + displacedByCustomXml). */
5299
+ function parseMarkupRangeOptions(el) {
5300
+ const id = attrNum(el, "w:id");
5301
+ if (id === void 0) return void 0;
5302
+ const m = { id };
5303
+ const disp = attr(el, "w:displacedByCustomXml");
5304
+ if (disp === "before" || disp === "after") m.displacedByCustomXml = disp;
5305
+ return m;
5306
+ }
5350
5307
  /**
5351
5308
  * Parse a w:p element into ParagraphOptions.
5352
5309
  */
@@ -5508,6 +5465,10 @@ function parseRunLevelChildren(elements, ctx) {
5508
5465
  };
5509
5466
  const disp = attr(child, "w:displacedByCustomXml");
5510
5467
  if (disp === "before" || disp === "after") bookmarkStart.displacedByCustomXml = disp;
5468
+ const colFirst = attrNum(child, "w:colFirst");
5469
+ if (colFirst !== void 0) bookmarkStart.colFirst = colFirst;
5470
+ const colLast = attrNum(child, "w:colLast");
5471
+ if (colLast !== void 0) bookmarkStart.colLast = colLast;
5511
5472
  childList.push({ bookmarkStart });
5512
5473
  }
5513
5474
  break;
@@ -5523,13 +5484,13 @@ function parseRunLevelChildren(elements, ctx) {
5523
5484
  break;
5524
5485
  }
5525
5486
  case "w:commentRangeStart": {
5526
- const id = attrNum(child, "w:id");
5527
- if (id !== void 0) childList.push({ commentRangeStart: id });
5487
+ const m = parseMarkupRangeOptions(child);
5488
+ if (m) childList.push({ commentRangeStart: m });
5528
5489
  break;
5529
5490
  }
5530
5491
  case "w:commentRangeEnd": {
5531
- const id = attrNum(child, "w:id");
5532
- if (id !== void 0) childList.push({ commentRangeEnd: id });
5492
+ const m = parseMarkupRangeOptions(child);
5493
+ if (m) childList.push({ commentRangeEnd: m });
5533
5494
  break;
5534
5495
  }
5535
5496
  case "w:commentReference": {
@@ -5721,8 +5682,8 @@ function parseRunLevelChildren(elements, ctx) {
5721
5682
  break;
5722
5683
  }
5723
5684
  case "w:moveFromRangeEnd": {
5724
- const id = attrNum(child, "w:id");
5725
- if (id !== void 0) childList.push({ moveFromRangeEnd: id });
5685
+ const m = parseMarkupRangeOptions(child);
5686
+ if (m) childList.push({ moveFromRangeEnd: m });
5726
5687
  break;
5727
5688
  }
5728
5689
  case "w:moveToRangeStart": {
@@ -5731,8 +5692,8 @@ function parseRunLevelChildren(elements, ctx) {
5731
5692
  break;
5732
5693
  }
5733
5694
  case "w:moveToRangeEnd": {
5734
- const id = attrNum(child, "w:id");
5735
- if (id !== void 0) childList.push({ moveToRangeEnd: id });
5695
+ const m = parseMarkupRangeOptions(child);
5696
+ if (m) childList.push({ moveToRangeEnd: m });
5736
5697
  break;
5737
5698
  }
5738
5699
  case "w:customXmlInsRangeStart": {
@@ -5841,7 +5802,7 @@ function parseParagraph(el, ctx) {
5841
5802
  * based on the graphicData URI.
5842
5803
  */
5843
5804
  function parseDrawingRun(el, ctx) {
5844
- const graphicData = findDeep(el, "a:graphicData")[0];
5805
+ const graphicData = findFirst(el, "a:graphicData");
5845
5806
  if (!graphicData) return void 0;
5846
5807
  const uri = attr(graphicData, "uri") ?? "";
5847
5808
  if (uri.includes("/chart")) return parseChartDrawing(el, ctx);
@@ -5907,8 +5868,8 @@ function readGrpSpLocks(cNvGrpSpPr) {
5907
5868
  * Returns `null` when the drawing has neither wrapper.
5908
5869
  */
5909
5870
  function parseAnchorOrInline(el) {
5910
- const inline = findDeep(el, "wp:inline")[0];
5911
- const anchor = inline ? void 0 : findDeep(el, "wp:anchor")[0];
5871
+ const inline = findFirst(el, "wp:inline");
5872
+ const anchor = inline ? void 0 : findFirst(el, "wp:anchor");
5912
5873
  const parent = inline ?? anchor;
5913
5874
  if (!parent) return null;
5914
5875
  const info = {};
@@ -5987,7 +5948,7 @@ function parseAnchorOrInline(el) {
5987
5948
  function parseImageRun(el, ctx) {
5988
5949
  const info = parseAnchorOrInline(el);
5989
5950
  if (!info) return void 0;
5990
- const blip = findDeep(el, "a:blip")[0];
5951
+ const blip = findFirst(el, "a:blip");
5991
5952
  if (!blip) return void 0;
5992
5953
  const rEmbed = attr(blip, "r:embed");
5993
5954
  if (!rEmbed) return void 0;
@@ -6007,14 +5968,14 @@ function parseImageRun(el, ctx) {
6007
5968
  if (info.altText) imageOpts.altText = info.altText;
6008
5969
  if (info.floating) imageOpts.floating = info.floating;
6009
5970
  if (info.graphicFrameLocks !== void 0) imageOpts.graphicFrameLocks = info.graphicFrameLocks;
6010
- const blipFill = findDeep(el, "pic:blipFill")[0];
5971
+ const blipFill = findFirst(el, "pic:blipFill");
6011
5972
  if (blipFill) {
6012
5973
  const srcRect = readSourceRectangle(blipFill);
6013
5974
  if (srcRect) imageOpts.sourceRectangle = srcRect;
6014
5975
  }
6015
5976
  const cNvPr = readPicCnvPr(el);
6016
5977
  if (cNvPr) imageOpts.nonVisualProperties = cNvPr;
6017
- const picSpPr = findDeep(el, "pic:spPr")[0];
5978
+ const picSpPr = findFirst(el, "pic:spPr");
6018
5979
  if (picSpPr) {
6019
5980
  const fill = readShapeFill(picSpPr, ctx);
6020
5981
  if (fill) imageOpts.fill = fill;
@@ -6065,7 +6026,7 @@ function readSourceRectangle(parent) {
6065
6026
  * undefined when there is no non-visual properties block.
6066
6027
  */
6067
6028
  function readPicCnvPr(el) {
6068
- const nvPicPr = findDeep(el, "pic:nvPicPr")[0];
6029
+ const nvPicPr = findFirst(el, "pic:nvPicPr");
6069
6030
  if (!nvPicPr) return void 0;
6070
6031
  const result = {};
6071
6032
  const cNvPr = findChild(nvPicPr, "pic:cNvPr");
@@ -6090,7 +6051,7 @@ function readPicCnvPr(el) {
6090
6051
  * through the shared descriptor.
6091
6052
  */
6092
6053
  function readShapeFill(parent, ctx) {
6093
- if (!(findChild(parent, "a:noFill") ?? findChild(parent, "a:solidFill") ?? findChild(parent, "a:gradFill") ?? findChild(parent, "a:pattFill") ?? findChild(parent, "a:grpFill"))) return void 0;
6054
+ if (!(findChild(parent, "a:noFill") ?? findChild(parent, "a:solidFill") ?? findChild(parent, "a:gradFill") ?? findChild(parent, "a:pattFill") ?? findChild(parent, "a:grpFill") ?? findChild(parent, "a:blipFill"))) return void 0;
6094
6055
  return fillDesc.parse(parent, ctx);
6095
6056
  }
6096
6057
  /**
@@ -6129,7 +6090,7 @@ function parseShapeStyle(styleEl, ctx) {
6129
6090
  */
6130
6091
  function parseWpsShapeCore(wspEl, ctx) {
6131
6092
  const result = {};
6132
- const txbxContent = findDeep(wspEl, "w:txbxContent")[0];
6093
+ const txbxContent = findFirst(wspEl, "w:txbxContent");
6133
6094
  const children = [];
6134
6095
  if (txbxContent) {
6135
6096
  for (const child of txbxContent.elements ?? []) if (child.name === "w:p") children.push(parseParagraph(child, ctx));
@@ -6165,9 +6126,15 @@ function parseWpsShapeCore(wspEl, ctx) {
6165
6126
  if (effectLst) result.effects = effectListDesc.parse(effectLst, ctx);
6166
6127
  const custGeom = findChild(spPr, "a:custGeom");
6167
6128
  if (custGeom) result.customGeometry = customGeometryDesc.parse(custGeom, ctx);
6129
+ const prstGeom = findChild(spPr, "a:prstGeom");
6130
+ if (prstGeom) result.presetGeometry = presetGeometryDesc.parse(prstGeom, ctx);
6131
+ const scene3d = findChild(spPr, "a:scene3d");
6132
+ if (scene3d) result.scene3d = scene3DDesc.parse(scene3d, ctx);
6133
+ const sp3d = findChild(spPr, "a:sp3d");
6134
+ if (sp3d) result.shape3d = shape3DDesc.parse(sp3d, ctx);
6168
6135
  }
6169
6136
  const bodyPr = findChild(wspEl, "wps:bodyPr");
6170
- if (bodyPr) result.bodyProperties = parseBodyProperties(bodyPr);
6137
+ if (bodyPr) result.bodyProperties = parseBodyProperties(bodyPr, ctx);
6171
6138
  const styleEl = findChild(wspEl, "wps:style");
6172
6139
  if (styleEl) result.style = parseShapeStyle(styleEl, ctx);
6173
6140
  return result;
@@ -6249,7 +6216,7 @@ function parseWpsChildMediaData(wspEl, ctx) {
6249
6216
  * to the same image collapse to one media entry.
6250
6217
  */
6251
6218
  function parsePicChildMediaData(picEl, ctx) {
6252
- const blip = findDeep(picEl, "a:blip")[0];
6219
+ const blip = findFirst(picEl, "a:blip");
6253
6220
  if (!blip) return void 0;
6254
6221
  const rEmbed = attr(blip, "r:embed");
6255
6222
  if (!rEmbed) return void 0;
@@ -6283,7 +6250,7 @@ function parsePicChildMediaData(picEl, ctx) {
6283
6250
  * Parse a standalone wps shape drawing (graphicData URI wordprocessingShape).
6284
6251
  */
6285
6252
  function parseWpsShapeDrawing(el, ctx) {
6286
- const wsp = findDeep(el, "wps:wsp")[0];
6253
+ const wsp = findFirst(el, "wps:wsp");
6287
6254
  if (!wsp) return void 0;
6288
6255
  const info = parseAnchorOrInline(el) ?? {};
6289
6256
  const shape = {
@@ -6303,7 +6270,7 @@ function parseWpsShapeDrawing(el, ctx) {
6303
6270
  * Parse a wpg group drawing (graphicData URI wordprocessingGroup).
6304
6271
  */
6305
6272
  function parseWpgGroupDrawing(el, ctx) {
6306
- const wgp = findDeep(el, "wpg:wgp")[0];
6273
+ const wgp = findFirst(el, "wpg:wgp");
6307
6274
  if (!wgp) return void 0;
6308
6275
  const info = parseAnchorOrInline(el) ?? {};
6309
6276
  const grpSpPr = findChild(wgp, "wpg:grpSpPr");
@@ -6432,8 +6399,8 @@ function readWrap(anchor) {
6432
6399
  }
6433
6400
  }
6434
6401
  function getDrawingExtent(el) {
6435
- const inline = findDeep(el, "wp:inline")[0];
6436
- const anchor = inline ? void 0 : findDeep(el, "wp:anchor")[0];
6402
+ const inline = findFirst(el, "wp:inline");
6403
+ const anchor = inline ? void 0 : findFirst(el, "wp:anchor");
6437
6404
  const parent = inline ?? anchor;
6438
6405
  if (!parent) return {};
6439
6406
  const extent = findChild(parent, "wp:extent");
@@ -6456,7 +6423,7 @@ function lookupRId(map, rId) {
6456
6423
  if (rId.startsWith("rIdrId")) return map.get(rId.slice(3));
6457
6424
  }
6458
6425
  function parseChartDrawing(el, ctx) {
6459
- const chartRef = findDeep(el, "c:chart")[0];
6426
+ const chartRef = findFirst(el, "c:chart");
6460
6427
  if (!chartRef) return void 0;
6461
6428
  const rId = attr(chartRef, "r:id");
6462
6429
  const chartPath = lookupRId(ctx.docx.partRefs.charts, rId);
@@ -6478,9 +6445,9 @@ function parseChartXml(el) {
6478
6445
  const opts = {};
6479
6446
  const titleEl = findChild(chart, "c:title");
6480
6447
  if (titleEl) {
6481
- const rich = findDeep(titleEl, "c:rich")[0];
6448
+ const rich = findFirst(titleEl, "c:rich");
6482
6449
  if (rich) {
6483
- const t = findDeep(rich, "a:t")[0];
6450
+ const t = findFirst(rich, "a:t");
6484
6451
  if (t) {
6485
6452
  const title = textOf(t);
6486
6453
  if (title) opts.title = title;
@@ -6549,7 +6516,7 @@ function parseChartXml(el) {
6549
6516
  function extractStrCache(parent, containerName) {
6550
6517
  const container = findChild(parent, containerName);
6551
6518
  if (!container) return [];
6552
- const cache = findDeep(container, "c:strCache")[0];
6519
+ const cache = findFirst(container, "c:strCache");
6553
6520
  if (!cache) return [];
6554
6521
  const values = [];
6555
6522
  for (const pt of cache.elements ?? []) {
@@ -6565,7 +6532,7 @@ function extractStrCache(parent, containerName) {
6565
6532
  function extractNumCache(parent) {
6566
6533
  const valEl = findChild(parent, "c:val");
6567
6534
  if (!valEl) return [];
6568
- const cache = findDeep(valEl, "c:numCache")[0];
6535
+ const cache = findFirst(valEl, "c:numCache");
6569
6536
  if (!cache) return [];
6570
6537
  const values = [];
6571
6538
  for (const pt of cache.elements ?? []) {
@@ -6579,7 +6546,7 @@ function extractNumCache(parent) {
6579
6546
  return values;
6580
6547
  }
6581
6548
  function parseSmartArtDrawing(el, ctx) {
6582
- const relIds = findDeep(el, "dgm:relIds")[0];
6549
+ const relIds = findFirst(el, "dgm:relIds");
6583
6550
  if (!relIds) return void 0;
6584
6551
  const rId = attr(relIds, "r:dm");
6585
6552
  const dataPath = lookupRId(ctx.docx.partRefs.diagramData, rId);
@@ -6618,7 +6585,7 @@ function parseSmartArtDataXml(el) {
6618
6585
  if (color) opts.color = color;
6619
6586
  }
6620
6587
  } else if (type === "node" && modelId) {
6621
- const t = findDeep(pt, "a:t")[0];
6588
+ const t = findFirst(pt, "a:t");
6622
6589
  nodeMap.set(modelId, t ? textOf(t) ?? "" : "");
6623
6590
  }
6624
6591
  }
@@ -6829,8 +6796,9 @@ function stringifyWpsShape(opts, ctx) {
6829
6796
  rotation: transform.rotation
6830
6797
  }, NOOP_CTX) ?? "");
6831
6798
  if (opts.customGeometry) spPrParts.push(customGeometryDesc$1.stringify(opts.customGeometry, NOOP_CTX) ?? "");
6799
+ else if (opts.presetGeometry) spPrParts.push(presetGeometryDesc$1.stringify(opts.presetGeometry, NOOP_CTX) ?? "");
6832
6800
  else spPrParts.push("<a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom>");
6833
- if (opts.fill) spPrParts.push(fillDesc$1.stringify(opts.fill, NOOP_CTX) ?? "");
6801
+ if (opts.fill) spPrParts.push(fillDesc$1.stringify(opts.fill, ctx) ?? "");
6834
6802
  if (opts.outline) spPrParts.push(outlineDesc$1.stringify(opts.outline, NOOP_CTX) ?? "");
6835
6803
  if (opts.effectDag) spPrParts.push(createEffectDag(opts.effectDag));
6836
6804
  else if (opts.effects) spPrParts.push(effectListDesc$1.stringify(opts.effects, NOOP_CTX) ?? "");
@@ -6877,7 +6845,7 @@ function stringifyWpgGroup(opts, ctx) {
6877
6845
  const transform = opts.transformation;
6878
6846
  const grpSpPrParts = [];
6879
6847
  grpSpPrParts.push(stringifyGroupTransform2D(transform, opts.childOffset, opts.childExtent));
6880
- if (opts.fill) grpSpPrParts.push(fillDesc$1.stringify(opts.fill, NOOP_CTX) ?? "");
6848
+ if (opts.fill) grpSpPrParts.push(fillDesc$1.stringify(opts.fill, ctx) ?? "");
6881
6849
  if (opts.effects) grpSpPrParts.push(effectListDesc$1.stringify(opts.effects, NOOP_CTX) ?? "");
6882
6850
  const childXml = opts.children.map((child) => stringifyGroupChild(child, ctx)).join("");
6883
6851
  return "<wpg:wgp>" + stringifyCnvGrpSpPr(opts.groupShapeLocks) + `<wpg:grpSpPr>${grpSpPrParts.join("")}</wpg:grpSpPr>` + childXml + "</wpg:wgp>";
@@ -6917,7 +6885,7 @@ function stringifyGroupChild(child, ctx) {
6917
6885
  function stringifyNestedGroup(grp, ctx) {
6918
6886
  const grpSpPrParts = [];
6919
6887
  grpSpPrParts.push(stringifyGroupTransform2D(grp.transformation, grp.childOffset, grp.childExtent));
6920
- if (grp.fill) grpSpPrParts.push(fillDesc$1.stringify(grp.fill, NOOP_CTX) ?? "");
6888
+ if (grp.fill) grpSpPrParts.push(fillDesc$1.stringify(grp.fill, ctx) ?? "");
6921
6889
  if (grp.effects) grpSpPrParts.push(effectListDesc$1.stringify(grp.effects, NOOP_CTX) ?? "");
6922
6890
  return "<wpg:grpSp><wpg:cNvPr id=\"0\" name=\"\"/>" + stringifyCnvGrpSpPr(grp.groupShapeLocks) + `<wpg:grpSpPr>${grpSpPrParts.join("")}</wpg:grpSpPr>` + grp.children.map((c) => stringifyGroupChild(c, ctx)).join("") + "</wpg:grpSp>";
6923
6891
  }
@@ -7083,24 +7051,6 @@ function stringifyAnchor(opts, hlIds, ctx) {
7083
7051
  const drawingDesc = {
7084
7052
  kind: "custom",
7085
7053
  stringify(opts, ctx) {
7086
- if (opts.fill) {
7087
- const media = extractBlipFillMedia(opts.fill, (type) => ctx.file.media.nextMediaName(type));
7088
- if (media) ctx.file.media.addImage(media.fileName, {
7089
- data: media.data,
7090
- fileName: media.fileName,
7091
- type: media.type,
7092
- transformation: {
7093
- pixels: {
7094
- x: 0,
7095
- y: 0
7096
- },
7097
- emus: {
7098
- x: 0,
7099
- y: 0
7100
- }
7101
- }
7102
- });
7103
- }
7104
7054
  const hlIds = registerHyperlinks(opts.docProperties?.hyperlink, ctx);
7105
7055
  if (opts.floating) return stringifyAnchor(opts, hlIds, ctx);
7106
7056
  return stringifyInline(opts, hlIds, ctx);
@@ -7295,15 +7245,10 @@ function registerVmlFallbackMedia(opts, ctx) {
7295
7245
  if (!opts.vmlFallbackMedia) return;
7296
7246
  for (const m of opts.vmlFallbackMedia) {
7297
7247
  const data = toUint8Array(m.data);
7298
- const existing = ctx.file.media.findByContent(data);
7299
- if (existing) {
7300
- if (opts.vmlFallback) opts.vmlFallback = opts.vmlFallback.split(`{${m.fileName}}`).join(`{${existing}}`);
7301
- continue;
7302
- }
7303
- ctx.file.media.addImage(m.fileName, {
7248
+ const entry = ctx.file.media.addMedia(data, m.type, (fileName) => ({
7304
7249
  type: m.type,
7305
7250
  data,
7306
- fileName: m.fileName,
7251
+ fileName,
7307
7252
  transformation: {
7308
7253
  emus: {
7309
7254
  x: 0,
@@ -7314,12 +7259,109 @@ function registerVmlFallbackMedia(opts, ctx) {
7314
7259
  y: 0
7315
7260
  }
7316
7261
  }
7317
- });
7262
+ }), m.fileName);
7263
+ if (entry.fileName !== m.fileName && opts.vmlFallback) opts.vmlFallback = opts.vmlFallback.split(`{${m.fileName}}`).join(`{${entry.fileName}}`);
7318
7264
  }
7319
7265
  }
7320
7266
  /**
7321
7267
  * Build the rPr XML for a break/tab run from its structured run properties.
7322
7268
  */
7269
+ /** Shared attribute string for CT_MarkupRange end markers (commentRange, move range end). */
7270
+ function buildMarkupRangeAttrs(m) {
7271
+ const a = [`w:id="${m.id}"`];
7272
+ if (m.displacedByCustomXml) a.push(`w:displacedByCustomXml="${m.displacedByCustomXml}"`);
7273
+ return a.join(" ");
7274
+ }
7275
+ /** Shared attribute string for w:bookmarkStart (CT_Bookmark). */
7276
+ function buildBookmarkStartAttrs(bs) {
7277
+ const a = [`w:id="${bs.id}"`, `w:name="${escapeXml(bs.name)}"`];
7278
+ if (bs.displacedByCustomXml) a.push(`w:displacedByCustomXml="${bs.displacedByCustomXml}"`);
7279
+ if (bs.colFirst !== void 0) a.push(`w:colFirst="${bs.colFirst}"`);
7280
+ if (bs.colLast !== void 0) a.push(`w:colLast="${bs.colLast}"`);
7281
+ return a.join(" ");
7282
+ }
7283
+ /** Shared attribute string for w:moveFromRangeStart / w:moveToRangeStart (CT_MoveBookmark). */
7284
+ function buildMoveRangeStartAttrs(m) {
7285
+ const a = [`w:id="${m.id}"`];
7286
+ if (m.name) a.push(`w:name="${escapeXml(m.name)}"`);
7287
+ if (m.author) a.push(`w:author="${escapeXml(m.author)}"`);
7288
+ if (m.date) a.push(`w:date="${m.date}"`);
7289
+ if (m.displacedByCustomXml) a.push(`w:displacedByCustomXml="${m.displacedByCustomXml}"`);
7290
+ if (m.colFirst !== void 0) a.push(`w:colFirst="${m.colFirst}"`);
7291
+ if (m.colLast !== void 0) a.push(`w:colLast="${m.colLast}"`);
7292
+ return a.join(" ");
7293
+ }
7294
+ /** Stringify inline run/text content — the `wrap` shared by every sugar child. */
7295
+ function stringifyInlineWrap(wrap, ctx) {
7296
+ const parts = [];
7297
+ for (const item of wrap ?? []) parts.push(typeof item === "string" ? stringifyRunInline({ text: item }, ctx) : stringifyRunInline(item, ctx));
7298
+ return parts.join("");
7299
+ }
7300
+ /**
7301
+ * Expand a `{ comment }` sugar child: allocate the comment id, register the
7302
+ * comment entry (side effect, consumed when word/comments.xml is stringified),
7303
+ * and emit the range markers + anchored content + reference with one shared id.
7304
+ *
7305
+ * The caller never supplies an id — the library owns id allocation and pairing.
7306
+ */
7307
+ function stringifyCommentChild(c, ctx) {
7308
+ const id = ctx.file.comments.nextId++;
7309
+ ctx.file.comments.entries.push({
7310
+ id,
7311
+ author: c.author,
7312
+ initials: c.initials,
7313
+ date: c.date,
7314
+ children: c.children
7315
+ });
7316
+ return `<w:commentRangeStart w:id="${id}"/>` + stringifyInlineWrap(c.wrap, ctx) + `<w:commentRangeEnd w:id="${id}"/><w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="${id}"/></w:r>`;
7317
+ }
7318
+ /**
7319
+ * Expand a `{ bookmark }` sugar child: allocate the bookmark id and emit the
7320
+ * paired bookmarkStart/bookmarkEnd with the anchored content between them.
7321
+ * Bookmarks are pure markup — the only effect is the two markers.
7322
+ */
7323
+ function stringifyBookmarkChild(b, ctx) {
7324
+ const id = ctx.file.markupIds.rangeNext++;
7325
+ const startAttrs = buildBookmarkStartAttrs({
7326
+ id,
7327
+ name: b.name,
7328
+ displacedByCustomXml: b.displacedByCustomXml,
7329
+ colFirst: b.colFirst,
7330
+ colLast: b.colLast
7331
+ });
7332
+ const endAttrs = buildMarkupRangeAttrs({
7333
+ id,
7334
+ displacedByCustomXml: b.displacedByCustomXml
7335
+ });
7336
+ return `<w:bookmarkStart ${startAttrs}/>${stringifyInlineWrap(b.wrap, ctx)}<w:bookmarkEnd ${endAttrs}/>`;
7337
+ }
7338
+ /**
7339
+ * Expand a `{ moveFrom }` / `{ moveTo }` sugar child: allocate the range id and
7340
+ * the move-run id, then emit the paired range markers with the moved run between
7341
+ * them. The move run (CT_TrackChange) carries the moved content.
7342
+ */
7343
+ function stringifyMoveRangeChild(kind, opts, ctx) {
7344
+ const rangeId = ctx.file.markupIds.rangeNext++;
7345
+ const runId = ctx.file.markupIds.moveRunNext++;
7346
+ const isMoveFrom = kind === "moveFrom";
7347
+ const startTag = isMoveFrom ? "w:moveFromRangeStart" : "w:moveToRangeStart";
7348
+ const endTag = isMoveFrom ? "w:moveFromRangeEnd" : "w:moveToRangeEnd";
7349
+ const runTag = isMoveFrom ? "w:moveFrom" : "w:moveTo";
7350
+ const rangeStartAttrs = buildMoveRangeStartAttrs({
7351
+ id: rangeId,
7352
+ name: opts.name,
7353
+ author: opts.author,
7354
+ date: opts.date,
7355
+ displacedByCustomXml: opts.displacedByCustomXml,
7356
+ colFirst: opts.colFirst,
7357
+ colLast: opts.colLast
7358
+ });
7359
+ const endAttrs = buildMarkupRangeAttrs({
7360
+ id: rangeId,
7361
+ displacedByCustomXml: opts.displacedByCustomXml
7362
+ });
7363
+ return `<${startTag} ${rangeStartAttrs}/><${runTag} w:id="${runId}" w:author="${escapeXml(opts.author)}" w:date="${opts.date}">${stringifyInlineWrap(opts.wrap, ctx)}</${runTag}><${endTag} ${endAttrs}/>`;
7364
+ }
7323
7365
  function runPropertiesXml(child) {
7324
7366
  return stringifyRunProperties(child) ?? "";
7325
7367
  }
@@ -7335,19 +7377,13 @@ function stringifyChildDispatch(child, ctx) {
7335
7377
  const ref = child.endnoteReference;
7336
7378
  return `<w:r><w:rPr><w:rStyle w:val="EndnoteReference"/></w:rPr><w:endnoteReference w:id="${typeof ref === "number" ? ref : ref.id}"${typeof ref === "object" && ref.customMarkFollows ? " w:customMarkFollows=\"true\"" : ""}/></w:r>`;
7337
7379
  }
7338
- if ("commentRangeStart" in child) return `<w:commentRangeStart w:id="${child.commentRangeStart}"/>`;
7339
- if ("commentRangeEnd" in child) return `<w:commentRangeEnd w:id="${child.commentRangeEnd}"/>`;
7380
+ if ("comment" in child) return stringifyCommentChild(child.comment, ctx);
7381
+ if ("commentRangeStart" in child) return `<w:commentRangeStart ${buildMarkupRangeAttrs(child.commentRangeStart)}/>`;
7382
+ if ("commentRangeEnd" in child) return `<w:commentRangeEnd ${buildMarkupRangeAttrs(child.commentRangeEnd)}/>`;
7340
7383
  if ("commentReference" in child) return `<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="${child.commentReference}"/></w:r>`;
7341
- if ("bookmarkStart" in child) {
7342
- const bs = child.bookmarkStart;
7343
- const bsDisp = bs.displacedByCustomXml ? ` w:displacedByCustomXml="${bs.displacedByCustomXml}"` : "";
7344
- return `<w:bookmarkStart w:id="${bs.id}" w:name="${bs.name}"${bsDisp}/>`;
7345
- }
7346
- if ("bookmarkEnd" in child) {
7347
- const be = child.bookmarkEnd;
7348
- const beDisp = be.displacedByCustomXml ? ` w:displacedByCustomXml="${be.displacedByCustomXml}"` : "";
7349
- return `<w:bookmarkEnd w:id="${be.id}"${beDisp}/>`;
7350
- }
7384
+ if ("bookmarkStart" in child) return `<w:bookmarkStart ${buildBookmarkStartAttrs(child.bookmarkStart)}/>`;
7385
+ if ("bookmarkEnd" in child) return `<w:bookmarkEnd ${buildMarkupRangeAttrs(child.bookmarkEnd)}/>`;
7386
+ if ("bookmark" in child) return stringifyBookmarkChild(child.bookmark, ctx);
7351
7387
  if ("symbolRun" in child) {
7352
7388
  const opts = child.symbolRun;
7353
7389
  return `<w:r>${stringifyRunProperties(opts) ?? ""}<w:sym w:char="${opts.char}" w:font="${opts.symbolfont ?? "Wingdings"}"/></w:r>`;
@@ -7374,27 +7410,29 @@ function stringifyChildDispatch(child, ctx) {
7374
7410
  }
7375
7411
  if ("image" in child) {
7376
7412
  const opts = child.image;
7377
- const key = ctx.file.media.nextMediaName(opts.type);
7378
7413
  const rawData = toUint8Array(opts.data);
7379
7414
  let mediaData;
7380
7415
  if (opts.type === "svg") {
7381
7416
  const fallbackData = toUint8Array(opts.fallback.data);
7382
- mediaData = {
7417
+ const fallbackType = opts.fallback.type;
7418
+ const fallback = ctx.file.media.addMedia(fallbackData, fallbackType, (fileName) => ({
7419
+ type: fallbackType,
7420
+ ...createImageData(fallbackData, opts.transformation, fileName)
7421
+ }));
7422
+ mediaData = ctx.file.media.addMedia(rawData, "svg", (fileName) => ({
7383
7423
  type: "svg",
7384
- ...createImageData(rawData, opts.transformation, key, opts.sourceRectangle, opts.nonVisualProperties),
7424
+ ...createImageData(rawData, opts.transformation, fileName, opts.sourceRectangle, opts.nonVisualProperties),
7385
7425
  useLocalDpi: opts.useLocalDpi,
7386
- fallback: {
7387
- type: opts.fallback.type,
7388
- ...createImageData(fallbackData, opts.transformation, ctx.file.media.nextMediaName(opts.fallback.type))
7389
- }
7390
- };
7391
- } else mediaData = {
7392
- type: opts.type,
7393
- ...createImageData(rawData, opts.transformation, key, opts.sourceRectangle, opts.nonVisualProperties),
7394
- useLocalDpi: opts.useLocalDpi
7395
- };
7396
- ctx.file.media.addImage(mediaData.fileName, mediaData);
7397
- if (mediaData.type === "svg") ctx.file.media.addImage(mediaData.fallback.fileName, mediaData.fallback);
7426
+ fallback
7427
+ }));
7428
+ } else {
7429
+ const type = opts.type;
7430
+ mediaData = ctx.file.media.addMedia(rawData, type, (fileName) => ({
7431
+ type,
7432
+ ...createImageData(rawData, opts.transformation, fileName, opts.sourceRectangle, opts.nonVisualProperties),
7433
+ useLocalDpi: opts.useLocalDpi
7434
+ }));
7435
+ }
7398
7436
  return wrapDrawingRun(drawingDesc.stringify({
7399
7437
  mediaData,
7400
7438
  docProperties: opts.altText,
@@ -7496,7 +7534,7 @@ function stringifyChildDispatch(child, ctx) {
7496
7534
  registerMedia(c.children);
7497
7535
  continue;
7498
7536
  }
7499
- ctx.file.media.addImage(c.fileName, c);
7537
+ ctx.file.media.addMedia(c.data, c.type, () => c, c.fileName);
7500
7538
  }
7501
7539
  };
7502
7540
  registerMedia(opts.children);
@@ -7542,6 +7580,7 @@ function stringifyChildDispatch(child, ctx) {
7542
7580
  if ("hyperlink" in child) {
7543
7581
  const hl = child.hyperlink;
7544
7582
  const childParts = [];
7583
+ if (child.text !== void 0) childParts.push(stringifyRunInline({ text: child.text }, ctx));
7545
7584
  if (hl.children) for (const rc of hl.children) if (typeof rc === "string") childParts.push(stringifyRunInline({ text: rc }, ctx));
7546
7585
  else childParts.push(stringifyRunInline(rc, ctx));
7547
7586
  const body = childParts.join("");
@@ -7580,24 +7619,12 @@ function stringifyChildDispatch(child, ctx) {
7580
7619
  return `<w:permStart ${a.join(" ")}/>`;
7581
7620
  }
7582
7621
  if ("permEnd" in child) return `<w:permEnd w:id="${child.permEnd}"/>`;
7583
- if ("moveFromRangeStart" in child) {
7584
- const m = child.moveFromRangeStart;
7585
- const a = [`w:id="${m.id}"`];
7586
- if (m.name) a.push(`w:name="${escapeXml(m.name)}"`);
7587
- if (m.author) a.push(`w:author="${escapeXml(m.author)}"`);
7588
- if (m.date) a.push(`w:date="${m.date}"`);
7589
- return `<w:moveFromRangeStart ${a.join(" ")}/>`;
7590
- }
7591
- if ("moveFromRangeEnd" in child) return `<w:moveFromRangeEnd w:id="${child.moveFromRangeEnd}"/>`;
7592
- if ("moveToRangeStart" in child) {
7593
- const m = child.moveToRangeStart;
7594
- const a = [`w:id="${m.id}"`];
7595
- if (m.name) a.push(`w:name="${escapeXml(m.name)}"`);
7596
- if (m.author) a.push(`w:author="${escapeXml(m.author)}"`);
7597
- if (m.date) a.push(`w:date="${m.date}"`);
7598
- return `<w:moveToRangeStart ${a.join(" ")}/>`;
7599
- }
7600
- if ("moveToRangeEnd" in child) return `<w:moveToRangeEnd w:id="${child.moveToRangeEnd}"/>`;
7622
+ if ("moveFromRangeStart" in child) return `<w:moveFromRangeStart ${buildMoveRangeStartAttrs(child.moveFromRangeStart)}/>`;
7623
+ if ("moveFromRangeEnd" in child) return `<w:moveFromRangeEnd ${buildMarkupRangeAttrs(child.moveFromRangeEnd)}/>`;
7624
+ if ("moveToRangeStart" in child) return `<w:moveToRangeStart ${buildMoveRangeStartAttrs(child.moveToRangeStart)}/>`;
7625
+ if ("moveToRangeEnd" in child) return `<w:moveToRangeEnd ${buildMarkupRangeAttrs(child.moveToRangeEnd)}/>`;
7626
+ if ("moveFrom" in child) return stringifyMoveRangeChild("moveFrom", child.moveFrom, ctx);
7627
+ if ("moveTo" in child) return stringifyMoveRangeChild("moveTo", child.moveTo, ctx);
7601
7628
  if ("movedFrom" in child) {
7602
7629
  const { id, author, date, children } = child.movedFrom;
7603
7630
  const body = children.map((c) => stringifyRunInline(typeof c === "string" ? { text: c } : c, ctx)).join("");
@@ -9819,10 +9846,6 @@ const HeaderFooterType = {
9819
9846
  const createHeaderFooterReference = (type, options) => `<${type} r:id="rId${options.id}" w:type="${options.type || HeaderFooterReferenceType.DEFAULT}"/>`;
9820
9847
  //#endregion
9821
9848
  //#region src/parts/styles/factory.ts
9822
- /** Escape special XML characters. */
9823
- function esc(s) {
9824
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
9825
- }
9826
9849
  /**
9827
9850
  * Build CT_Style style-level children (name…rsid), shared by paragraph/character/table styles.
9828
9851
  * Order follows CT_Style sequence: name, aliases, basedOn, next, link, autoRedefine, hidden,
@@ -9830,11 +9853,11 @@ function esc(s) {
9830
9853
  * personalReply, rsid.
9831
9854
  */
9832
9855
  function stringifyStyleLevelChildren(opts) {
9833
- const parts = [`<w:name w:val="${esc(opts.name ?? opts.id ?? "")}"/>`];
9834
- if (opts.aliases) parts.push(`<w:aliases w:val="${esc(opts.aliases)}"/>`);
9835
- if (opts.basedOn) parts.push(`<w:basedOn w:val="${esc(opts.basedOn)}"/>`);
9836
- if (opts.next) parts.push(`<w:next w:val="${esc(opts.next)}"/>`);
9837
- if (opts.link) parts.push(`<w:link w:val="${esc(opts.link)}"/>`);
9856
+ const parts = [`<w:name w:val="${escapeXml(opts.name ?? opts.id ?? "")}"/>`];
9857
+ if (opts.aliases) parts.push(`<w:aliases w:val="${escapeXml(opts.aliases)}"/>`);
9858
+ if (opts.basedOn) parts.push(`<w:basedOn w:val="${escapeXml(opts.basedOn)}"/>`);
9859
+ if (opts.next) parts.push(`<w:next w:val="${escapeXml(opts.next)}"/>`);
9860
+ if (opts.link) parts.push(`<w:link w:val="${escapeXml(opts.link)}"/>`);
9838
9861
  if (opts.autoRedefine) parts.push("<w:autoRedefine/>");
9839
9862
  if (opts.hidden) parts.push("<w:hidden/>");
9840
9863
  if (opts.uiPriority !== void 0) parts.push(`<w:uiPriority w:val="${opts.uiPriority}"/>`);
@@ -9848,6 +9871,17 @@ function stringifyStyleLevelChildren(opts) {
9848
9871
  if (opts.rsid) parts.push(`<w:rsid w:val="${opts.rsid}"/>`);
9849
9872
  return parts.join("");
9850
9873
  }
9874
+ /**
9875
+ * Build the `<w:style>` opening tag: type/styleId plus the optional w:default
9876
+ * and w:customStyle element attributes (CT_Style). Shared by paragraph/
9877
+ * character/table styles.
9878
+ */
9879
+ function styleOpenTag(type, opts) {
9880
+ let attrs = ` w:type="${type}" w:styleId="${escapeXml(opts.id ?? "")}"`;
9881
+ if (opts.default) attrs += " w:default=\"1\"";
9882
+ if (opts.customStyle) attrs += " w:customStyle=\"1\"";
9883
+ return `<w:style${attrs}>`;
9884
+ }
9851
9885
  /** Build `<w:style>` XML for a paragraph style. */
9852
9886
  function stringifyParagraphStyle(opts) {
9853
9887
  const children = [stringifyStyleLevelChildren(opts)];
@@ -9855,14 +9889,14 @@ function stringifyParagraphStyle(opts) {
9855
9889
  if (pPr) children.push(pPr);
9856
9890
  const rPr = stringifyRunProperties(opts.run);
9857
9891
  if (rPr) children.push(rPr);
9858
- return `<w:style w:type="paragraph" w:styleId="${esc(opts.id)}">${children.join("")}</w:style>`;
9892
+ return `${styleOpenTag("paragraph", opts)}${children.join("")}</w:style>`;
9859
9893
  }
9860
9894
  /** Build `<w:style>` XML for a character style. */
9861
9895
  function stringifyCharacterStyle(opts) {
9862
9896
  const children = [stringifyStyleLevelChildren(opts)];
9863
9897
  const rPr = stringifyRunProperties(opts.run);
9864
9898
  if (rPr) children.push(rPr);
9865
- return `<w:style w:type="character" w:styleId="${esc(opts.id)}">${children.join("")}</w:style>`;
9899
+ return `${styleOpenTag("character", opts)}${children.join("")}</w:style>`;
9866
9900
  }
9867
9901
  /** Build `<w:tblStylePr>` XML for a conditional table style format. */
9868
9902
  function stringifyConditionalTableStyle(opts) {
@@ -9905,7 +9939,16 @@ function stringifyTableStyle(opts) {
9905
9939
  if (tcPr) children.push(tcPr);
9906
9940
  }
9907
9941
  for (const cf of opts.conditionalFormats ?? []) children.push(stringifyConditionalTableStyle(cf));
9908
- return `<w:style w:type="table" w:styleId="${esc(opts.id)}">${children.join("")}</w:style>`;
9942
+ return `${styleOpenTag("table", opts)}${children.join("")}</w:style>`;
9943
+ }
9944
+ /** Build `<w:style type="numbering">` XML for a numbering style. */
9945
+ function stringifyNumberingStyle(opts) {
9946
+ const children = [stringifyStyleLevelChildren(opts)];
9947
+ const pPr = stringifyParagraphProperties(opts.paragraph).xml;
9948
+ if (pPr) children.push(pPr);
9949
+ const rPr = stringifyRunProperties(opts.run);
9950
+ if (rPr) children.push(rPr);
9951
+ return `${styleOpenTag("numbering", opts)}${children.join("")}</w:style>`;
9909
9952
  }
9910
9953
  /** Resolve a user override for heading level N (1-9) from default styles options. */
9911
9954
  function headingOverride(options, level) {
@@ -9922,45 +9965,6 @@ function headingOverride(options, level) {
9922
9965
  default: return;
9923
9966
  }
9924
9967
  }
9925
- /**
9926
- * Maps DefaultStylesOptions override fields to every built-in styleId the
9927
- * factory (re)emits when that field is provided — the main style plus its
9928
- * linked character style (e.g. heading1 -> Heading1 + Heading1Char).
9929
- */
9930
- const DEFAULT_STYLE_FIELDS = [
9931
- ["title", ["Title", "TitleChar"]],
9932
- ["subtitle", ["Subtitle", "SubtitleChar"]],
9933
- ["heading1", ["Heading1", "Heading1Char"]],
9934
- ["heading2", ["Heading2", "Heading2Char"]],
9935
- ["heading3", ["Heading3", "Heading3Char"]],
9936
- ["heading4", ["Heading4", "Heading4Char"]],
9937
- ["heading5", ["Heading5", "Heading5Char"]],
9938
- ["heading6", ["Heading6", "Heading6Char"]],
9939
- ["heading7", ["Heading7", "Heading7Char"]],
9940
- ["heading8", ["Heading8", "Heading8Char"]],
9941
- ["heading9", ["Heading9", "Heading9Char"]],
9942
- ["listParagraph", ["ListParagraph"]],
9943
- ["quote", ["Quote", "QuoteChar"]],
9944
- ["strong", ["Strong"]],
9945
- ["emphasis", ["Emphasis"]]
9946
- ];
9947
- /**
9948
- * Reverse map: main built-in styleId -> the DefaultStylesOptions field that
9949
- * overrides it. Linked char ids (Heading1Char, TitleChar, ...) are excluded —
9950
- * they ride along with their main style.
9951
- */
9952
- const STYLE_ID_TO_DEFAULT_FIELD = Object.fromEntries(DEFAULT_STYLE_FIELDS.map(([field, [mainId]]) => [mainId, field]));
9953
- /**
9954
- * Collect every styleId the factory (re)emits for the default-styles fields the
9955
- * user explicitly provided — including linked character styles, so the
9956
- * round-trip path drops the matching verbatim entries (no duplicate styleId).
9957
- */
9958
- function collectDefaultOverrideIds(defaultOpts) {
9959
- const ids = /* @__PURE__ */ new Set();
9960
- if (!defaultOpts) return ids;
9961
- for (const [field, styleIds] of DEFAULT_STYLE_FIELDS) if (defaultOpts[field] !== void 0) for (const id of styleIds) ids.add(id);
9962
- return ids;
9963
- }
9964
9968
  /** Build `<w:docDefaults>` XML matching Word's default settings. */
9965
9969
  function stringifyDocDefaults(opts) {
9966
9970
  const children = [];
@@ -9989,6 +9993,10 @@ var DefaultStylesFactory = class {
9989
9993
  }
9990
9994
  build(options) {
9991
9995
  const importedStyles = [];
9996
+ const paragraphStyles = [];
9997
+ const characterStyles = [];
9998
+ const tableStyles = [];
9999
+ const numberingStyles = [];
9992
10000
  const initialAttributes = {
9993
10001
  "xmlns:mc": "http://schemas.openxmlformats.org/markup-compatibility/2006",
9994
10002
  "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
@@ -9999,70 +10007,76 @@ var DefaultStylesFactory = class {
9999
10007
  };
10000
10008
  importedStyles.push({ _raw: stringifyDocDefaults(options.document ?? {}) });
10001
10009
  importedStyles.push({ _raw: "<w:latentStyles w:defLockedState=\"0\" w:defUIPriority=\"99\" w:defSemiHidden=\"0\" w:defUnhideWhenUsed=\"0\" w:defQFormat=\"0\" w:count=\"376\"><w:lsdException w:name=\"Normal\" w:uiPriority=\"0\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 1\" w:uiPriority=\"9\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 2\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 3\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 4\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 5\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 6\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 7\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 8\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"heading 9\" w:semiHidden=\"1\" w:uiPriority=\"9\" w:unhideWhenUsed=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"Default Paragraph Font\" w:semiHidden=\"1\" w:uiPriority=\"1\" w:unhideWhenUsed=\"1\"/><w:lsdException w:name=\"Normal Table\" w:semiHidden=\"1\" w:uiPriority=\"99\" w:unhideWhenUsed=\"1\"/><w:lsdException w:name=\"No List\" w:semiHidden=\"1\" w:uiPriority=\"99\" w:unhideWhenUsed=\"1\"/><w:lsdException w:name=\"Subtitle\" w:uiPriority=\"11\" w:qFormat=\"1\"/><w:lsdException w:name=\"Strong\" w:uiPriority=\"22\" w:qFormat=\"1\"/><w:lsdException w:name=\"Emphasis\" w:uiPriority=\"20\" w:qFormat=\"1\"/><w:lsdException w:name=\"Hyperlink\" w:semiHidden=\"1\" w:unhideWhenUsed=\"1\"/><w:lsdException w:name=\"FollowedHyperlink\" w:semiHidden=\"1\" w:unhideWhenUsed=\"1\"/><w:lsdException w:name=\"No Spacing\" w:uiPriority=\"1\" w:qFormat=\"1\"/><w:lsdException w:name=\"Revision\" w:semiHidden=\"1\"/></w:latentStyles>" });
10002
- importedStyles.push({ _raw: "<w:style w:type=\"paragraph\" w:default=\"1\" w:styleId=\"Normal\"><w:name w:val=\"Normal\"/><w:qFormat/><w:pPr><w:widowControl w:val=\"0\"/></w:pPr></w:style>" });
10010
+ paragraphStyles.push({
10011
+ id: "Normal",
10012
+ name: "Normal",
10013
+ default: true,
10014
+ quickFormat: true,
10015
+ paragraph: { widowControl: false }
10016
+ });
10003
10017
  const headings = [
10004
10018
  {
10005
10019
  id: "Heading1",
10006
10020
  name: "heading 1",
10007
10021
  link: "Heading1Char",
10008
- sz: "48",
10009
- before: "480",
10010
- after: "80",
10011
- outlineLvl: "0"
10022
+ sz: 48,
10023
+ before: 480,
10024
+ after: 80,
10025
+ outlineLvl: 0
10012
10026
  },
10013
10027
  {
10014
10028
  id: "Heading2",
10015
10029
  name: "heading 2",
10016
10030
  link: "Heading2Char",
10017
- sz: "40",
10018
- before: "160",
10019
- after: "80",
10020
- outlineLvl: "1"
10031
+ sz: 40,
10032
+ before: 160,
10033
+ after: 80,
10034
+ outlineLvl: 1
10021
10035
  },
10022
10036
  {
10023
10037
  id: "Heading3",
10024
10038
  name: "heading 3",
10025
10039
  link: "Heading3Char",
10026
- sz: "32",
10027
- before: "160",
10028
- after: "80",
10029
- outlineLvl: "2"
10040
+ sz: 32,
10041
+ before: 160,
10042
+ after: 80,
10043
+ outlineLvl: 2
10030
10044
  },
10031
10045
  {
10032
10046
  id: "Heading4",
10033
10047
  name: "heading 4",
10034
10048
  link: "Heading4Char",
10035
- sz: "28",
10036
- before: "80",
10037
- after: "40",
10038
- outlineLvl: "3"
10049
+ sz: 28,
10050
+ before: 80,
10051
+ after: 40,
10052
+ outlineLvl: 3
10039
10053
  },
10040
10054
  {
10041
10055
  id: "Heading5",
10042
10056
  name: "heading 5",
10043
10057
  link: "Heading5Char",
10044
- sz: "24",
10045
- before: "80",
10046
- after: "40",
10047
- outlineLvl: "4"
10058
+ sz: 24,
10059
+ before: 80,
10060
+ after: 40,
10061
+ outlineLvl: 4
10048
10062
  },
10049
10063
  {
10050
10064
  id: "Heading6",
10051
10065
  name: "heading 6",
10052
10066
  link: "Heading6Char",
10053
10067
  sz: void 0,
10054
- before: "40",
10055
- after: "0",
10056
- outlineLvl: "5"
10068
+ before: 40,
10069
+ after: 0,
10070
+ outlineLvl: 5
10057
10071
  },
10058
10072
  {
10059
10073
  id: "Heading7",
10060
10074
  name: "heading 7",
10061
10075
  link: "Heading7Char",
10062
10076
  sz: void 0,
10063
- before: "40",
10064
- after: "0",
10065
- outlineLvl: "6"
10077
+ before: 40,
10078
+ after: 0,
10079
+ outlineLvl: 6
10066
10080
  },
10067
10081
  {
10068
10082
  id: "Heading8",
@@ -10070,8 +10084,8 @@ var DefaultStylesFactory = class {
10070
10084
  link: "Heading8Char",
10071
10085
  sz: void 0,
10072
10086
  before: void 0,
10073
- after: "0",
10074
- outlineLvl: "7"
10087
+ after: 0,
10088
+ outlineLvl: 7
10075
10089
  },
10076
10090
  {
10077
10091
  id: "Heading9",
@@ -10079,15 +10093,16 @@ var DefaultStylesFactory = class {
10079
10093
  link: "Heading9Char",
10080
10094
  sz: void 0,
10081
10095
  before: void 0,
10082
- after: "0",
10083
- outlineLvl: "8"
10096
+ after: 0,
10097
+ outlineLvl: 8
10084
10098
  }
10085
10099
  ];
10086
10100
  for (let headingIdx = 0; headingIdx < headings.length; headingIdx++) {
10087
10101
  const h = headings[headingIdx];
10102
+ const outlineLvl = h.outlineLvl;
10088
10103
  const headingOverrideOpts = headingOverride(options, headingIdx + 1);
10089
10104
  if (headingOverrideOpts) {
10090
- importedStyles.push({ _raw: stringifyParagraphStyle({
10105
+ paragraphStyles.push({
10091
10106
  id: h.id,
10092
10107
  name: headingOverrideOpts.name ?? h.name,
10093
10108
  basedOn: headingOverrideOpts.basedOn ?? "Normal",
@@ -10102,42 +10117,124 @@ var DefaultStylesFactory = class {
10102
10117
  ...headingOverrideOpts.paragraph
10103
10118
  },
10104
10119
  run: headingOverrideOpts.run
10105
- }) });
10106
- importedStyles.push({ _raw: stringifyCharacterStyle({
10120
+ });
10121
+ characterStyles.push({
10107
10122
  id: h.link,
10108
10123
  name: `${h.name} Char`,
10109
10124
  basedOn: "DefaultParagraphFont",
10110
10125
  link: h.id,
10111
10126
  run: headingOverrideOpts.run
10112
- }) });
10127
+ });
10113
10128
  continue;
10114
10129
  }
10115
- const pPrParts = [`<w:keepNext/>`, `<w:keepLines/>`];
10116
- if (h.before || h.after) {
10117
- const sp = [];
10118
- if (h.before) sp.push(`w:before="${h.before}"`);
10119
- if (h.after) sp.push(`w:after="${h.after}"`);
10120
- pPrParts.push(`<w:spacing ${sp.join(" ")}/>`);
10130
+ const accentRange = outlineLvl < 6;
10131
+ const runProps = {
10132
+ font: accentRange ? {
10133
+ asciiTheme: "majorHAnsi",
10134
+ eastAsiaTheme: "majorEastAsia",
10135
+ hAnsiTheme: "majorHAnsi",
10136
+ cstheme: "majorBidi"
10137
+ } : { cstheme: "majorBidi" },
10138
+ color: accentRange ? {
10139
+ val: "0F4761",
10140
+ themeColor: "accent1",
10141
+ themeShade: "BF"
10142
+ } : {
10143
+ val: "595959",
10144
+ themeColor: "text1",
10145
+ themeTint: "A6"
10146
+ }
10147
+ };
10148
+ if (h.sz) {
10149
+ const sizePt = h.sz / 2;
10150
+ runProps.size = sizePt;
10151
+ runProps.sizeComplexScript = sizePt;
10121
10152
  }
10122
- pPrParts.push(`<w:outlineLvl w:val="${h.outlineLvl}"/>`);
10123
- const rPrParts = [];
10124
- if (parseInt(h.outlineLvl) < 6) {
10125
- rPrParts.push(`<w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/>`);
10126
- rPrParts.push(`<w:color w:val="0F4761" w:themeColor="accent1" w:themeShade="BF"/>`);
10127
- } else {
10128
- rPrParts.push(`<w:rFonts w:cstheme="majorBidi"/>`);
10129
- rPrParts.push(`<w:color w:val="595959" w:themeColor="text1" w:themeTint="A6"/>`);
10153
+ if (outlineLvl >= 5) {
10154
+ runProps.bold = true;
10155
+ runProps.boldComplexScript = true;
10156
+ }
10157
+ paragraphStyles.push({
10158
+ id: h.id,
10159
+ name: h.name,
10160
+ basedOn: "Normal",
10161
+ next: "Normal",
10162
+ link: h.link,
10163
+ uiPriority: 9,
10164
+ semiHidden: outlineLvl > 0,
10165
+ unhideWhenUsed: outlineLvl > 0,
10166
+ quickFormat: true,
10167
+ paragraph: {
10168
+ keepNext: true,
10169
+ keepLines: true,
10170
+ spacing: {
10171
+ before: h.before,
10172
+ after: h.after
10173
+ },
10174
+ outlineLevel: outlineLvl
10175
+ },
10176
+ run: runProps
10177
+ });
10178
+ characterStyles.push({
10179
+ id: h.link,
10180
+ name: `${h.name} Char`,
10181
+ basedOn: "DefaultParagraphFont",
10182
+ link: h.id,
10183
+ uiPriority: 9,
10184
+ semiHidden: outlineLvl > 0,
10185
+ run: runProps
10186
+ });
10187
+ }
10188
+ characterStyles.push({
10189
+ id: "DefaultParagraphFont",
10190
+ name: "Default Paragraph Font",
10191
+ default: true,
10192
+ uiPriority: 1,
10193
+ semiHidden: true,
10194
+ unhideWhenUsed: true
10195
+ });
10196
+ tableStyles.push({
10197
+ id: "NormalTable",
10198
+ name: "Normal Table",
10199
+ default: true,
10200
+ uiPriority: 99,
10201
+ semiHidden: true,
10202
+ unhideWhenUsed: true,
10203
+ table: {
10204
+ indent: {
10205
+ size: 0,
10206
+ type: WidthType.DXA
10207
+ },
10208
+ cellMargin: {
10209
+ top: {
10210
+ size: 0,
10211
+ type: WidthType.DXA
10212
+ },
10213
+ left: {
10214
+ size: 108,
10215
+ type: WidthType.DXA
10216
+ },
10217
+ bottom: {
10218
+ size: 0,
10219
+ type: WidthType.DXA
10220
+ },
10221
+ right: {
10222
+ size: 108,
10223
+ type: WidthType.DXA
10224
+ }
10225
+ }
10130
10226
  }
10131
- if (h.sz) rPrParts.push(`<w:sz w:val="${h.sz}"/><w:szCs w:val="${h.sz}"/>`);
10132
- if (parseInt(h.outlineLvl) >= 5) rPrParts.push(`<w:b/><w:bCs/>`);
10133
- importedStyles.push({ _raw: `<w:style w:type="paragraph" w:styleId="${h.id}"><w:name w:val="${h.name}"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:link w:val="${h.link}"/><w:uiPriority w:val="9"/>` + (parseInt(h.outlineLvl) > 0 ? `<w:semiHidden/><w:unhideWhenUsed/>` : "") + `<w:qFormat/><w:pPr>${pPrParts.join("")}</w:pPr><w:rPr>${rPrParts.join("")}</w:rPr></w:style>` });
10134
- importedStyles.push({ _raw: `<w:style w:type="character" w:styleId="${h.link}"><w:name w:val="${h.name} Char"/><w:basedOn w:val="DefaultParagraphFont"/><w:link w:val="${h.id}"/><w:uiPriority w:val="9"/>` + (parseInt(h.outlineLvl) > 0 ? `<w:semiHidden/>` : "") + `<w:rPr>${rPrParts.join("")}</w:rPr></w:style>` });
10135
- }
10136
- importedStyles.push({ _raw: "<w:style w:type=\"character\" w:default=\"1\" w:styleId=\"DefaultParagraphFont\"><w:name w:val=\"Default Paragraph Font\"/><w:uiPriority w:val=\"1\"/><w:semiHidden/><w:unhideWhenUsed/></w:style>" });
10137
- importedStyles.push({ _raw: "<w:style w:type=\"table\" w:default=\"1\" w:styleId=\"NormalTable\"><w:name w:val=\"Normal Table\"/><w:uiPriority w:val=\"99\"/><w:semiHidden/><w:unhideWhenUsed/><w:tblPr><w:tblInd w:w=\"0\" w:type=\"dxa\"/><w:tblCellMar><w:top w:w=\"0\" w:type=\"dxa\"/><w:left w:w=\"108\" w:type=\"dxa\"/><w:bottom w:w=\"0\" w:type=\"dxa\"/><w:right w:w=\"108\" w:type=\"dxa\"/></w:tblCellMar></w:tblPr></w:style>" });
10138
- importedStyles.push({ _raw: "<w:style w:type=\"numbering\" w:default=\"1\" w:styleId=\"NoList\"><w:name w:val=\"No List\"/><w:uiPriority w:val=\"99\"/><w:semiHidden/><w:unhideWhenUsed/></w:style>" });
10227
+ });
10228
+ numberingStyles.push({
10229
+ id: "NoList",
10230
+ name: "No List",
10231
+ default: true,
10232
+ uiPriority: 99,
10233
+ semiHidden: true,
10234
+ unhideWhenUsed: true
10235
+ });
10139
10236
  if (options.title) {
10140
- importedStyles.push({ _raw: stringifyParagraphStyle({
10237
+ paragraphStyles.push({
10141
10238
  id: "Title",
10142
10239
  name: options.title.name ?? "Title",
10143
10240
  basedOn: options.title.basedOn ?? "Normal",
@@ -10147,20 +10244,57 @@ var DefaultStylesFactory = class {
10147
10244
  quickFormat: options.title.quickFormat ?? true,
10148
10245
  paragraph: options.title.paragraph,
10149
10246
  run: options.title.run
10150
- }) });
10151
- importedStyles.push({ _raw: stringifyCharacterStyle({
10247
+ });
10248
+ characterStyles.push({
10152
10249
  id: "TitleChar",
10153
10250
  name: "Title Char",
10154
10251
  basedOn: "DefaultParagraphFont",
10155
10252
  link: "Title",
10156
10253
  run: options.title.run
10157
- }) });
10254
+ });
10158
10255
  } else {
10159
- importedStyles.push({ _raw: "<w:style w:type=\"paragraph\" w:styleId=\"Title\"><w:name w:val=\"Title\"/><w:basedOn w:val=\"Normal\"/><w:next w:val=\"Normal\"/><w:link w:val=\"TitleChar\"/><w:uiPriority w:val=\"10\"/><w:qFormat/><w:pPr><w:spacing w:after=\"80\" w:line=\"240\" w:lineRule=\"auto\"/><w:contextualSpacing/><w:jc w:val=\"center\"/></w:pPr><w:rPr><w:rFonts w:asciiTheme=\"majorHAnsi\" w:eastAsiaTheme=\"majorEastAsia\" w:hAnsiTheme=\"majorHAnsi\" w:cstheme=\"majorBidi\"/><w:spacing w:val=\"-10\"/><w:kern w:val=\"28\"/><w:sz w:val=\"56\"/><w:szCs w:val=\"56\"/></w:rPr></w:style>" });
10160
- importedStyles.push({ _raw: "<w:style w:type=\"character\" w:styleId=\"TitleChar\"><w:name w:val=\"Title Char\"/><w:basedOn w:val=\"DefaultParagraphFont\"/><w:link w:val=\"Title\"/><w:uiPriority w:val=\"10\"/><w:rPr><w:rFonts w:asciiTheme=\"majorHAnsi\" w:eastAsiaTheme=\"majorEastAsia\" w:hAnsiTheme=\"majorHAnsi\" w:cstheme=\"majorBidi\"/><w:spacing w:val=\"-10\"/><w:kern w:val=\"28\"/><w:sz w:val=\"56\"/><w:szCs w:val=\"56\"/></w:rPr></w:style>" });
10256
+ const titleRun = {
10257
+ font: {
10258
+ asciiTheme: "majorHAnsi",
10259
+ eastAsiaTheme: "majorEastAsia",
10260
+ hAnsiTheme: "majorHAnsi",
10261
+ cstheme: "majorBidi"
10262
+ },
10263
+ characterSpacing: -10,
10264
+ kern: 28,
10265
+ size: 28,
10266
+ sizeComplexScript: 28
10267
+ };
10268
+ paragraphStyles.push({
10269
+ id: "Title",
10270
+ name: "Title",
10271
+ basedOn: "Normal",
10272
+ next: "Normal",
10273
+ link: "TitleChar",
10274
+ uiPriority: 10,
10275
+ quickFormat: true,
10276
+ paragraph: {
10277
+ spacing: {
10278
+ after: 80,
10279
+ line: 240,
10280
+ lineRule: "auto"
10281
+ },
10282
+ contextualSpacing: true,
10283
+ alignment: AlignmentType.CENTER
10284
+ },
10285
+ run: titleRun
10286
+ });
10287
+ characterStyles.push({
10288
+ id: "TitleChar",
10289
+ name: "Title Char",
10290
+ basedOn: "DefaultParagraphFont",
10291
+ link: "Title",
10292
+ uiPriority: 10,
10293
+ run: titleRun
10294
+ });
10161
10295
  }
10162
10296
  if (options.subtitle) {
10163
- importedStyles.push({ _raw: stringifyParagraphStyle({
10297
+ paragraphStyles.push({
10164
10298
  id: "Subtitle",
10165
10299
  name: options.subtitle.name ?? "Subtitle",
10166
10300
  basedOn: options.subtitle.basedOn ?? "Normal",
@@ -10170,19 +10304,52 @@ var DefaultStylesFactory = class {
10170
10304
  quickFormat: options.subtitle.quickFormat ?? true,
10171
10305
  paragraph: options.subtitle.paragraph,
10172
10306
  run: options.subtitle.run
10173
- }) });
10174
- importedStyles.push({ _raw: stringifyCharacterStyle({
10307
+ });
10308
+ characterStyles.push({
10175
10309
  id: "SubtitleChar",
10176
10310
  name: "Subtitle Char",
10177
10311
  basedOn: "DefaultParagraphFont",
10178
10312
  link: "Subtitle",
10179
10313
  run: options.subtitle.run
10180
- }) });
10314
+ });
10181
10315
  } else {
10182
- importedStyles.push({ _raw: "<w:style w:type=\"paragraph\" w:styleId=\"Subtitle\"><w:name w:val=\"Subtitle\"/><w:basedOn w:val=\"Normal\"/><w:next w:val=\"Normal\"/><w:link w:val=\"SubtitleChar\"/><w:uiPriority w:val=\"11\"/><w:qFormat/><w:pPr><w:jc w:val=\"center\"/></w:pPr><w:rPr><w:rFonts w:asciiTheme=\"majorHAnsi\" w:eastAsiaTheme=\"majorEastAsia\" w:hAnsiTheme=\"majorHAnsi\" w:cstheme=\"majorBidi\"/><w:color w:val=\"595959\" w:themeColor=\"text1\" w:themeTint=\"A6\"/><w:spacing w:val=\"15\"/><w:sz w:val=\"28\"/><w:szCs w:val=\"28\"/></w:rPr></w:style>" });
10183
- importedStyles.push({ _raw: "<w:style w:type=\"character\" w:styleId=\"SubtitleChar\"><w:name w:val=\"Subtitle Char\"/><w:basedOn w:val=\"DefaultParagraphFont\"/><w:link w:val=\"Subtitle\"/><w:uiPriority w:val=\"11\"/><w:rPr><w:rFonts w:asciiTheme=\"majorHAnsi\" w:eastAsiaTheme=\"majorEastAsia\" w:hAnsiTheme=\"majorHAnsi\" w:cstheme=\"majorBidi\"/><w:color w:val=\"595959\" w:themeColor=\"text1\" w:themeTint=\"A6\"/><w:spacing w:val=\"15\"/><w:sz w:val=\"28\"/><w:szCs w:val=\"28\"/></w:rPr></w:style>" });
10316
+ const subtitleRun = {
10317
+ font: {
10318
+ asciiTheme: "majorHAnsi",
10319
+ eastAsiaTheme: "majorEastAsia",
10320
+ hAnsiTheme: "majorHAnsi",
10321
+ cstheme: "majorBidi"
10322
+ },
10323
+ color: {
10324
+ val: "595959",
10325
+ themeColor: "text1",
10326
+ themeTint: "A6"
10327
+ },
10328
+ characterSpacing: 15,
10329
+ size: 14,
10330
+ sizeComplexScript: 14
10331
+ };
10332
+ paragraphStyles.push({
10333
+ id: "Subtitle",
10334
+ name: "Subtitle",
10335
+ basedOn: "Normal",
10336
+ next: "Normal",
10337
+ link: "SubtitleChar",
10338
+ uiPriority: 11,
10339
+ quickFormat: true,
10340
+ paragraph: { alignment: AlignmentType.CENTER },
10341
+ run: subtitleRun
10342
+ });
10343
+ characterStyles.push({
10344
+ id: "SubtitleChar",
10345
+ name: "Subtitle Char",
10346
+ basedOn: "DefaultParagraphFont",
10347
+ link: "Subtitle",
10348
+ uiPriority: 11,
10349
+ run: subtitleRun
10350
+ });
10184
10351
  }
10185
- if (options.listParagraph) importedStyles.push({ _raw: stringifyParagraphStyle({
10352
+ if (options.listParagraph) paragraphStyles.push({
10186
10353
  id: "ListParagraph",
10187
10354
  name: options.listParagraph.name ?? "List Paragraph",
10188
10355
  basedOn: options.listParagraph.basedOn ?? "Normal",
@@ -10190,9 +10357,19 @@ var DefaultStylesFactory = class {
10190
10357
  quickFormat: options.listParagraph.quickFormat ?? true,
10191
10358
  paragraph: options.listParagraph.paragraph,
10192
10359
  run: options.listParagraph.run
10193
- }) });
10194
- else importedStyles.push({ _raw: "<w:style w:type=\"paragraph\" w:styleId=\"ListParagraph\"><w:name w:val=\"List Paragraph\"/><w:basedOn w:val=\"Normal\"/><w:uiPriority w:val=\"34\"/><w:qFormat/><w:pPr><w:ind w:left=\"720\"/><w:contextualSpacing/></w:pPr></w:style>" });
10195
- if (options.strong) importedStyles.push({ _raw: stringifyParagraphStyle({
10360
+ });
10361
+ else paragraphStyles.push({
10362
+ id: "ListParagraph",
10363
+ name: "List Paragraph",
10364
+ basedOn: "Normal",
10365
+ uiPriority: 34,
10366
+ quickFormat: true,
10367
+ paragraph: {
10368
+ indent: { left: 720 },
10369
+ contextualSpacing: true
10370
+ }
10371
+ });
10372
+ if (options.strong) paragraphStyles.push({
10196
10373
  id: "Strong",
10197
10374
  name: options.strong.name ?? "Strong",
10198
10375
  basedOn: options.strong.basedOn ?? "Normal",
@@ -10200,8 +10377,8 @@ var DefaultStylesFactory = class {
10200
10377
  quickFormat: options.strong.quickFormat ?? true,
10201
10378
  paragraph: options.strong.paragraph,
10202
10379
  run: options.strong.run
10203
- }) });
10204
- if (options.emphasis) importedStyles.push({ _raw: stringifyParagraphStyle({
10380
+ });
10381
+ if (options.emphasis) paragraphStyles.push({
10205
10382
  id: "Emphasis",
10206
10383
  name: options.emphasis.name ?? "Emphasis",
10207
10384
  basedOn: options.emphasis.basedOn ?? "Normal",
@@ -10209,9 +10386,18 @@ var DefaultStylesFactory = class {
10209
10386
  quickFormat: options.emphasis.quickFormat ?? true,
10210
10387
  paragraph: options.emphasis.paragraph,
10211
10388
  run: options.emphasis.run
10212
- }) });
10389
+ });
10390
+ const quoteRun = {
10391
+ italic: true,
10392
+ italicComplexScript: true,
10393
+ color: {
10394
+ val: "404040",
10395
+ themeColor: "text1",
10396
+ themeTint: "BF"
10397
+ }
10398
+ };
10213
10399
  if (options.quote) {
10214
- importedStyles.push({ _raw: stringifyParagraphStyle({
10400
+ paragraphStyles.push({
10215
10401
  id: "Quote",
10216
10402
  name: options.quote.name ?? "Quote",
10217
10403
  basedOn: options.quote.basedOn ?? "Normal",
@@ -10221,21 +10407,89 @@ var DefaultStylesFactory = class {
10221
10407
  quickFormat: options.quote.quickFormat ?? true,
10222
10408
  paragraph: options.quote.paragraph,
10223
10409
  run: options.quote.run
10224
- }) });
10225
- importedStyles.push({ _raw: stringifyCharacterStyle({
10410
+ });
10411
+ characterStyles.push({
10226
10412
  id: "QuoteChar",
10227
10413
  name: "Quote Char",
10228
10414
  basedOn: "DefaultParagraphFont",
10229
10415
  link: "Quote",
10230
10416
  run: options.quote.run
10231
- }) });
10417
+ });
10232
10418
  } else {
10233
- importedStyles.push({ _raw: "<w:style w:type=\"paragraph\" w:styleId=\"Quote\"><w:name w:val=\"Quote\"/><w:basedOn w:val=\"Normal\"/><w:next w:val=\"Normal\"/><w:link w:val=\"QuoteChar\"/><w:uiPriority w:val=\"29\"/><w:qFormat/><w:pPr><w:spacing w:before=\"160\"/><w:jc w:val=\"center\"/></w:pPr><w:rPr><w:i/><w:iCs/><w:color w:val=\"404040\" w:themeColor=\"text1\" w:themeTint=\"BF\"/></w:rPr></w:style>" });
10234
- importedStyles.push({ _raw: "<w:style w:type=\"character\" w:styleId=\"QuoteChar\"><w:name w:val=\"Quote Char\"/><w:basedOn w:val=\"DefaultParagraphFont\"/><w:link w:val=\"Quote\"/><w:uiPriority w:val=\"29\"/><w:rPr><w:i/><w:iCs/><w:color w:val=\"404040\" w:themeColor=\"text1\" w:themeTint=\"BF\"/></w:rPr></w:style>" });
10419
+ paragraphStyles.push({
10420
+ id: "Quote",
10421
+ name: "Quote",
10422
+ basedOn: "Normal",
10423
+ next: "Normal",
10424
+ link: "QuoteChar",
10425
+ uiPriority: 29,
10426
+ quickFormat: true,
10427
+ paragraph: {
10428
+ spacing: { before: 160 },
10429
+ alignment: AlignmentType.CENTER
10430
+ },
10431
+ run: quoteRun
10432
+ });
10433
+ characterStyles.push({
10434
+ id: "QuoteChar",
10435
+ name: "Quote Char",
10436
+ basedOn: "DefaultParagraphFont",
10437
+ link: "Quote",
10438
+ uiPriority: 29,
10439
+ run: quoteRun
10440
+ });
10235
10441
  }
10236
- importedStyles.push({ _raw: "<w:style w:type=\"paragraph\" w:styleId=\"IntenseQuote\"><w:name w:val=\"Intense Quote\"/><w:basedOn w:val=\"Normal\"/><w:next w:val=\"Normal\"/><w:link w:val=\"IntenseQuoteChar\"/><w:uiPriority w:val=\"30\"/><w:qFormat/><w:pPr><w:pBdr><w:top w:val=\"single\" w:sz=\"4\" w:space=\"10\" w:color=\"0F4761\" w:themeColor=\"accent1\" w:themeShade=\"BF\"/><w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"10\" w:color=\"0F4761\" w:themeColor=\"accent1\" w:themeShade=\"BF\"/></w:pBdr><w:spacing w:before=\"360\" w:after=\"360\"/><w:ind w:left=\"864\" w:right=\"864\"/><w:jc w:val=\"center\"/></w:pPr><w:rPr><w:i/><w:iCs/><w:color w:val=\"0F4761\" w:themeColor=\"accent1\" w:themeShade=\"BF\"/></w:rPr></w:style>" });
10237
- importedStyles.push({ _raw: "<w:style w:type=\"character\" w:styleId=\"IntenseQuoteChar\"><w:name w:val=\"Intense Quote Char\"/><w:basedOn w:val=\"DefaultParagraphFont\"/><w:link w:val=\"IntenseQuote\"/><w:uiPriority w:val=\"30\"/><w:rPr><w:i/><w:iCs/><w:color w:val=\"0F4761\" w:themeColor=\"accent1\" w:themeShade=\"BF\"/></w:rPr></w:style>" });
10238
- importedStyles.push({ _raw: stringifyCharacterStyle({
10442
+ const intenseQuoteRun = {
10443
+ italic: true,
10444
+ italicComplexScript: true,
10445
+ color: {
10446
+ val: "0F4761",
10447
+ themeColor: "accent1",
10448
+ themeShade: "BF"
10449
+ }
10450
+ };
10451
+ const intenseQuoteBorder = {
10452
+ style: BorderStyle.SINGLE,
10453
+ size: 4,
10454
+ space: 10,
10455
+ color: "0F4761",
10456
+ themeColor: "accent1",
10457
+ themeShade: "BF"
10458
+ };
10459
+ paragraphStyles.push({
10460
+ id: "IntenseQuote",
10461
+ name: "Intense Quote",
10462
+ basedOn: "Normal",
10463
+ next: "Normal",
10464
+ link: "IntenseQuoteChar",
10465
+ uiPriority: 30,
10466
+ quickFormat: true,
10467
+ paragraph: {
10468
+ border: {
10469
+ top: intenseQuoteBorder,
10470
+ bottom: intenseQuoteBorder
10471
+ },
10472
+ spacing: {
10473
+ before: 360,
10474
+ after: 360
10475
+ },
10476
+ indent: {
10477
+ left: 864,
10478
+ right: 864
10479
+ },
10480
+ alignment: AlignmentType.CENTER
10481
+ },
10482
+ run: intenseQuoteRun
10483
+ });
10484
+ characterStyles.push({
10485
+ id: "IntenseQuoteChar",
10486
+ name: "Intense Quote Char",
10487
+ basedOn: "DefaultParagraphFont",
10488
+ link: "IntenseQuote",
10489
+ uiPriority: 30,
10490
+ run: intenseQuoteRun
10491
+ });
10492
+ characterStyles.push({
10239
10493
  id: "Hyperlink",
10240
10494
  name: "Hyperlink",
10241
10495
  basedOn: "DefaultParagraphFont",
@@ -10246,8 +10500,8 @@ var DefaultStylesFactory = class {
10246
10500
  underline: { type: "single" }
10247
10501
  },
10248
10502
  ...options.hyperlink
10249
- }) });
10250
- importedStyles.push({ _raw: stringifyCharacterStyle({
10503
+ });
10504
+ characterStyles.push({
10251
10505
  id: "FootnoteReference",
10252
10506
  name: "footnote reference",
10253
10507
  basedOn: "DefaultParagraphFont",
@@ -10255,8 +10509,8 @@ var DefaultStylesFactory = class {
10255
10509
  unhideWhenUsed: true,
10256
10510
  run: { superScript: true },
10257
10511
  ...options.footnoteReference
10258
- }) });
10259
- importedStyles.push({ _raw: stringifyParagraphStyle({
10512
+ });
10513
+ paragraphStyles.push({
10260
10514
  id: "FootnoteText",
10261
10515
  name: "footnote text",
10262
10516
  basedOn: "Normal",
@@ -10271,8 +10525,8 @@ var DefaultStylesFactory = class {
10271
10525
  } },
10272
10526
  run: { size: 20 },
10273
10527
  ...options.footnoteText
10274
- }) });
10275
- importedStyles.push({ _raw: stringifyCharacterStyle({
10528
+ });
10529
+ characterStyles.push({
10276
10530
  id: "FootnoteTextChar",
10277
10531
  name: "Footnote Text Char",
10278
10532
  basedOn: "DefaultParagraphFont",
@@ -10280,8 +10534,8 @@ var DefaultStylesFactory = class {
10280
10534
  semiHidden: true,
10281
10535
  run: { size: 20 },
10282
10536
  ...options.footnoteTextChar
10283
- }) });
10284
- importedStyles.push({ _raw: stringifyCharacterStyle({
10537
+ });
10538
+ characterStyles.push({
10285
10539
  id: "EndnoteReference",
10286
10540
  name: "endnote reference",
10287
10541
  basedOn: "DefaultParagraphFont",
@@ -10289,8 +10543,8 @@ var DefaultStylesFactory = class {
10289
10543
  unhideWhenUsed: true,
10290
10544
  run: { superScript: true },
10291
10545
  ...options.endnoteReference
10292
- }) });
10293
- importedStyles.push({ _raw: stringifyParagraphStyle({
10546
+ });
10547
+ paragraphStyles.push({
10294
10548
  id: "EndnoteText",
10295
10549
  name: "endnote text",
10296
10550
  basedOn: "Normal",
@@ -10305,8 +10559,8 @@ var DefaultStylesFactory = class {
10305
10559
  } },
10306
10560
  run: { size: 20 },
10307
10561
  ...options.endnoteText
10308
- }) });
10309
- importedStyles.push({ _raw: stringifyCharacterStyle({
10562
+ });
10563
+ characterStyles.push({
10310
10564
  id: "EndnoteTextChar",
10311
10565
  name: "Endnote Text Char",
10312
10566
  basedOn: "DefaultParagraphFont",
@@ -10314,10 +10568,31 @@ var DefaultStylesFactory = class {
10314
10568
  semiHidden: true,
10315
10569
  run: { size: 20 },
10316
10570
  ...options.endnoteTextChar
10317
- }) });
10318
- importedStyles.push({ _raw: "<w:style w:type=\"character\" w:styleId=\"IntenseReference\"><w:name w:val=\"Intense Reference\"/><w:basedOn w:val=\"DefaultParagraphFont\"/><w:uiPriority w:val=\"32\"/><w:qFormat/><w:rPr><w:b/><w:bCs/><w:smallCaps/><w:color w:val=\"0F4761\" w:themeColor=\"accent1\" w:themeShade=\"BF\"/><w:spacing w:val=\"5\"/></w:rPr></w:style>" });
10571
+ });
10572
+ characterStyles.push({
10573
+ id: "IntenseReference",
10574
+ name: "Intense Reference",
10575
+ basedOn: "DefaultParagraphFont",
10576
+ uiPriority: 32,
10577
+ quickFormat: true,
10578
+ run: {
10579
+ bold: true,
10580
+ boldComplexScript: true,
10581
+ smallCaps: true,
10582
+ color: {
10583
+ val: "0F4761",
10584
+ themeColor: "accent1",
10585
+ themeShade: "BF"
10586
+ },
10587
+ characterSpacing: 5
10588
+ }
10589
+ });
10319
10590
  return {
10320
10591
  importedStyles,
10592
+ paragraphStyles,
10593
+ characterStyles,
10594
+ tableStyles,
10595
+ numberingStyles,
10321
10596
  initialAttributes
10322
10597
  };
10323
10598
  }
@@ -10367,42 +10642,10 @@ var Styles = class {
10367
10642
  }
10368
10643
  this.parts.push(style._raw);
10369
10644
  }
10370
- if (options.paragraphStyles) for (const style of options.paragraphStyles) this.parts.push(stringifyParagraphStyle({
10371
- id: style.id,
10372
- name: style.name ?? style.id,
10373
- aliases: style.aliases,
10374
- basedOn: style.basedOn,
10375
- next: style.next,
10376
- link: style.link,
10377
- autoRedefine: style.autoRedefine,
10378
- quickFormat: style.quickFormat,
10379
- semiHidden: style.semiHidden,
10380
- uiPriority: style.uiPriority,
10381
- unhideWhenUsed: style.unhideWhenUsed,
10382
- locked: style.locked,
10383
- personal: style.personal,
10384
- personalCompose: style.personalCompose,
10385
- personalReply: style.personalReply,
10386
- paragraph: style.paragraph,
10387
- run: style.run
10388
- }));
10389
- if (options.characterStyles) for (const style of options.characterStyles) this.parts.push(stringifyCharacterStyle({
10390
- id: style.id,
10391
- name: style.name ?? style.id,
10392
- aliases: style.aliases,
10393
- basedOn: style.basedOn,
10394
- link: style.link,
10395
- autoRedefine: style.autoRedefine,
10396
- semiHidden: style.semiHidden,
10397
- uiPriority: style.uiPriority,
10398
- unhideWhenUsed: style.unhideWhenUsed,
10399
- locked: style.locked,
10400
- personal: style.personal,
10401
- personalCompose: style.personalCompose,
10402
- personalReply: style.personalReply,
10403
- run: style.run
10404
- }));
10645
+ if (options.paragraphStyles) for (const style of options.paragraphStyles) this.parts.push(stringifyParagraphStyle(style));
10646
+ if (options.characterStyles) for (const style of options.characterStyles) this.parts.push(stringifyCharacterStyle(style));
10405
10647
  if (options.tableStyles) for (const style of options.tableStyles) this.parts.push(stringifyTableStyle(style));
10648
+ if (options.numberingStyles) for (const style of options.numberingStyles) this.parts.push(stringifyNumberingStyle(style));
10406
10649
  }
10407
10650
  /**
10408
10651
  * Serialize to word/styles.xml content (with XML declaration).
@@ -10413,25 +10656,6 @@ var Styles = class {
10413
10656
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:styles${attrParts.join("")}>${this.parts.join("")}</w:styles>`;
10414
10657
  }
10415
10658
  };
10416
- /** Style IDs generated by DefaultStylesFactory — skip these during parsing. */
10417
- const BUILTIN_STYLE_IDS = new Set([
10418
- "Title",
10419
- "Heading1",
10420
- "Heading2",
10421
- "Heading3",
10422
- "Heading4",
10423
- "Heading5",
10424
- "Heading6",
10425
- "Strong",
10426
- "ListParagraph",
10427
- "Hyperlink",
10428
- "FootnoteText",
10429
- "FootnoteTextChar",
10430
- "EndnoteText",
10431
- "EndnoteTextChar",
10432
- "FootnoteReference",
10433
- "EndnoteReference"
10434
- ]);
10435
10659
  /**
10436
10660
  * Build a cache of style elements keyed by styleId.
10437
10661
  */
@@ -10469,6 +10693,7 @@ function parseStyleDefinitions(el, parseParagraphProperties, ctx) {
10469
10693
  const paragraphStyles = [];
10470
10694
  const characterStyles = [];
10471
10695
  const tableStyles = [];
10696
+ const numberingStyles = [];
10472
10697
  for (const child of el.elements ?? []) if (child.name === "w:docDefaults") {
10473
10698
  const defOpts = parseDocDefaults(child, parseParagraphProperties, ctx);
10474
10699
  if (defOpts) opts.default = defOpts;
@@ -10477,28 +10702,18 @@ function parseStyleDefinitions(el, parseParagraphProperties, ctx) {
10477
10702
  else if (child.name === "w:style") {
10478
10703
  const styleOpts = parseStyleElement(child, parseParagraphProperties, ctx);
10479
10704
  if (!styleOpts?._type || !styleOpts.id) continue;
10480
- if (styleOpts._type === "table") {
10481
- delete styleOpts._type;
10482
- tableStyles.push(styleOpts);
10483
- continue;
10484
- }
10485
- (opts.importedStyles ??= []).push({ _raw: stringifyElement(child) });
10486
- const defaultField = STYLE_ID_TO_DEFAULT_FIELD[styleOpts.id];
10487
- if (defaultField) {
10488
- const { _type: _omitType, id: _omitId, ...rest } = styleOpts;
10489
- opts.default ??= {};
10490
- opts.default[defaultField] = rest;
10491
- continue;
10492
- }
10493
- if (BUILTIN_STYLE_IDS.has(styleOpts.id)) continue;
10494
10705
  const type = styleOpts._type;
10495
10706
  delete styleOpts._type;
10496
- if (type === "paragraph") paragraphStyles.push(styleOpts);
10707
+ if (type === "table") tableStyles.push(styleOpts);
10708
+ else if (type === "numbering") numberingStyles.push(styleOpts);
10709
+ else if (type === "paragraph") paragraphStyles.push(styleOpts);
10497
10710
  else if (type === "character") characterStyles.push(styleOpts);
10498
10711
  }
10499
10712
  if (paragraphStyles.length > 0) opts.paragraphStyles = paragraphStyles;
10500
10713
  if (characterStyles.length > 0) opts.characterStyles = characterStyles;
10501
10714
  if (tableStyles.length > 0) opts.tableStyles = tableStyles;
10715
+ if (numberingStyles.length > 0) opts.numberingStyles = numberingStyles;
10716
+ opts.roundTripped = true;
10502
10717
  return Object.keys(opts).length > 0 ? opts : void 0;
10503
10718
  }
10504
10719
  function parseDocDefaults(el, parseParagraphProperties, ctx) {
@@ -10528,7 +10743,7 @@ function parseStyleElement(el, parseParagraphProperties, ctx) {
10528
10743
  const id = attr(el, "w:styleId");
10529
10744
  if (id) opts.id = id;
10530
10745
  if (attrBool(el, "w:default")) opts.default = true;
10531
- if (attrBool(el, "w:customStyle")) opts.customStyle = "1";
10746
+ if (attrBool(el, "w:customStyle")) opts.customStyle = true;
10532
10747
  const nameEl = findChild(el, "w:name");
10533
10748
  if (nameEl) {
10534
10749
  const name = attr(nameEl, "w:val");
@@ -10645,9 +10860,6 @@ function parseStyleElement(el, parseParagraphProperties, ctx) {
10645
10860
  *
10646
10861
  * @module
10647
10862
  */
10648
- function escapeAttr$1(s) {
10649
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
10650
- }
10651
10863
  /** Derive the namespace-prefixed val attribute from the element tag. */
10652
10864
  function valAttr(tag) {
10653
10865
  return `${tag.split(":")[0]}:val`;
@@ -10659,12 +10871,12 @@ function numVal(tag, val) {
10659
10871
  return val !== void 0 ? `<${tag} ${valAttr(tag)}="${val}"/>` : "";
10660
10872
  }
10661
10873
  function strVal(tag, val) {
10662
- return val !== void 0 ? `<${tag} ${valAttr(tag)}="${escapeAttr$1(val)}"/>` : "";
10874
+ return val !== void 0 ? `<${tag} ${valAttr(tag)}="${escapeXml(val)}"/>` : "";
10663
10875
  }
10664
10876
  /** Build attribute string from key-value pairs, skipping undefined. */
10665
10877
  function attrStr(attrs) {
10666
10878
  const parts = [];
10667
- for (const [k, v] of Object.entries(attrs)) if (v !== void 0) parts.push(`${k}="${escapeAttr$1(String(v))}"`);
10879
+ for (const [k, v] of Object.entries(attrs)) if (v !== void 0) parts.push(`${k}="${escapeXml(String(v))}"`);
10668
10880
  return parts.join(" ");
10669
10881
  }
10670
10882
  /** Self-closing element with attributes only. */
@@ -10674,7 +10886,7 @@ function attrEl(tag, attrs) {
10674
10886
  }
10675
10887
  function compatSetting(name, val, uri) {
10676
10888
  const u = uri ?? "http://schemas.microsoft.com/office/word";
10677
- return `<w:compatSetting w:name="${escapeAttr$1(name)}" w:uri="${u}" w:val="${val}"/>`;
10889
+ return `<w:compatSetting w:name="${escapeXml(name)}" w:uri="${u}" w:val="${val}"/>`;
10678
10890
  }
10679
10891
  /** Read a CT_OnOff child as boolean (presence true unless val is explicitly false). */
10680
10892
  function readOnOff(el) {
@@ -12444,9 +12656,6 @@ const fontTableDesc = {
12444
12656
  };
12445
12657
  //#endregion
12446
12658
  //#region src/parts/bibliography.ts
12447
- function escapeXml$1(s) {
12448
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12449
- }
12450
12659
  const SOURCE_FIELDS = [
12451
12660
  ["SourceType", "type"],
12452
12661
  ["Title", "title"],
@@ -12469,13 +12678,13 @@ const bibliographyDesc = {
12469
12678
  kind: "custom",
12470
12679
  stringify(opts, _ctx) {
12471
12680
  const attrParts = ["xmlns:b=\"http://schemas.openxmlformats.org/officeDocument/2006/bibliography\""];
12472
- if (opts.styleName !== void 0) attrParts.push(`StyleName="${escapeXml$1(opts.styleName)}"`);
12681
+ if (opts.styleName !== void 0) attrParts.push(`StyleName="${escapeXml(opts.styleName)}"`);
12473
12682
  const parts = [`<b:Sources ${attrParts.join(" ")}>`];
12474
12683
  for (const source of opts.sources) {
12475
12684
  const sourceParts = [];
12476
12685
  for (const [tagName, key] of SOURCE_FIELDS) {
12477
12686
  const value = source[key];
12478
- if (value !== void 0) sourceParts.push(`<b:${tagName}>${escapeXml$1(value)}</b:${tagName}>`);
12687
+ if (value !== void 0) sourceParts.push(`<b:${tagName}>${escapeXml(value)}</b:${tagName}>`);
12479
12688
  }
12480
12689
  parts.push(`<b:Source>${sourceParts.join("")}</b:Source>`);
12481
12690
  }
@@ -12562,15 +12771,12 @@ const DocPartBehavior = {
12562
12771
  PAGE: "pg"
12563
12772
  };
12564
12773
  const GLOSSARY_NS = "xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
12565
- function glossaryEscapeAttr(text) {
12566
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12567
- }
12568
12774
  function docPartPrXml(part) {
12569
12775
  const prParts = [];
12570
- prParts.push(`<w:name w:val="${glossaryEscapeAttr(part.name)}"${part.decorated ? " w:decorated=\"1\"" : ""}/>`);
12776
+ prParts.push(`<w:name w:val="${escapeXml(part.name)}"${part.decorated ? " w:decorated=\"1\"" : ""}/>`);
12571
12777
  if (part.category || part.gallery) {
12572
12778
  const catParts = [];
12573
- if (part.category) catParts.push(`<w:name w:val="${glossaryEscapeAttr(part.category)}"/>`);
12779
+ if (part.category) catParts.push(`<w:name w:val="${escapeXml(part.category)}"/>`);
12574
12780
  catParts.push(`<w:gallery w:val="${part.gallery}"/>`);
12575
12781
  prParts.push(`<w:category>${catParts.join("")}</w:category>`);
12576
12782
  }
@@ -12583,8 +12789,8 @@ function docPartPrXml(part) {
12583
12789
  const behaviorXml = part.behaviors.map((b) => `<w:behavior w:val="${b}"/>`).join("");
12584
12790
  prParts.push(`<w:behaviors>${behaviorXml}</w:behaviors>`);
12585
12791
  }
12586
- if (part.description) prParts.push(`<w:description w:val="${glossaryEscapeAttr(part.description)}"/>`);
12587
- if (part.guid) prParts.push(`<w:guid w:val="${glossaryEscapeAttr(part.guid)}"/>`);
12792
+ if (part.description) prParts.push(`<w:description w:val="${escapeXml(part.description)}"/>`);
12793
+ if (part.guid) prParts.push(`<w:guid w:val="${escapeXml(part.guid)}"/>`);
12588
12794
  return `<w:docPartPr>${prParts.join("")}</w:docPartPr>`;
12589
12795
  }
12590
12796
  const glossaryDesc = {
@@ -12660,18 +12866,15 @@ const glossaryDesc = {
12660
12866
  };
12661
12867
  //#endregion
12662
12868
  //#region src/parts/comments.ts
12663
- function escapeAttr(s) {
12664
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12665
- }
12666
12869
  const COMMENTS_NS = "xmlns:aink=\"http://schemas.microsoft.com/office/drawing/2016/ink\" xmlns:am3d=\"http://schemas.microsoft.com/office/drawing/2017/model3d\" xmlns:cx=\"http://schemas.microsoft.com/office/drawing/2014/chartex\" xmlns:cx1=\"http://schemas.microsoft.com/office/drawing/2015/9/8/chartex\" xmlns:cx2=\"http://schemas.microsoft.com/office/drawing/2015/10/21/chartex\" xmlns:cx3=\"http://schemas.microsoft.com/office/drawing/2016/5/9/chartex\" xmlns:cx4=\"http://schemas.microsoft.com/office/drawing/2016/5/10/chartex\" xmlns:cx5=\"http://schemas.microsoft.com/office/drawing/2016/5/11/chartex\" xmlns:cx6=\"http://schemas.microsoft.com/office/drawing/2016/5/12/chartex\" xmlns:cx7=\"http://schemas.microsoft.com/office/drawing/2016/5/13/chartex\" xmlns:cx8=\"http://schemas.microsoft.com/office/drawing/2016/5/14/chartex\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:w16=\"http://schemas.microsoft.com/office/word/2018/wordml\" xmlns:w16cex=\"http://schemas.microsoft.com/office/word/2018/wordml/cex\" xmlns:w16cid=\"http://schemas.microsoft.com/office/word/2016/wordml/cid\" xmlns:w16sdtdh=\"http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash\" xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\" xmlns:wne=\"http://schemas.openxmlformats.org/office/word/2006/wordml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\"";
12667
12870
  function stringifyComment(opts, ctx) {
12668
12871
  const dateStr = typeof opts.date === "string" ? opts.date : (opts.date ?? /* @__PURE__ */ new Date()).toISOString();
12669
12872
  const attrs = [
12670
12873
  `w:id="${opts.id}"`,
12671
- `w:author="${escapeAttr(opts.author ?? "")}"`,
12672
- `w:date="${escapeAttr(dateStr)}"`
12874
+ `w:author="${escapeXml(opts.author ?? "")}"`,
12875
+ `w:date="${escapeXml(dateStr)}"`
12673
12876
  ];
12674
- if (opts.initials !== void 0) attrs.push(`w:initials="${escapeAttr(opts.initials)}"`);
12877
+ if (opts.initials !== void 0) attrs.push(`w:initials="${escapeXml(opts.initials)}"`);
12675
12878
  const parts = [];
12676
12879
  for (const child of opts.children) parts.push(stringifyParagraphInline(child, ctx));
12677
12880
  return `<w:comment ${attrs.join(" ")}>${parts.join("")}</w:comment>`;
@@ -12908,8 +13111,26 @@ function buildContentTypesFromRegistry(facts, dynamic = {}) {
12908
13111
  partName: sd.path.startsWith("/") ? sd.path : `/${sd.path}`,
12909
13112
  contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
12910
13113
  });
13114
+ const defaults = [{
13115
+ extension: "rels",
13116
+ contentType: "application/vnd.openxmlformats-package.relationships+xml"
13117
+ }, {
13118
+ extension: "xml",
13119
+ contentType: "application/xml"
13120
+ }];
13121
+ const haveExt = new Set(["rels", "xml"]);
13122
+ for (const ac of dynamic.altChunks ?? []) {
13123
+ const ext = (ac.path.split(".").pop() ?? "").toLowerCase();
13124
+ if (ext && !haveExt.has(ext) && ALTCHUNK_DEFAULTS[ext]) {
13125
+ defaults.push({
13126
+ extension: ext,
13127
+ contentType: ALTCHUNK_DEFAULTS[ext]
13128
+ });
13129
+ haveExt.add(ext);
13130
+ }
13131
+ }
12911
13132
  return {
12912
- defaults: [...STANDARD_DEFAULTS],
13133
+ defaults,
12913
13134
  overrides
12914
13135
  };
12915
13136
  }
@@ -13032,14 +13253,11 @@ function wsOnOff(tag, val) {
13032
13253
  return `<${tag} w:val="${val ? "true" : "false"}"/>`;
13033
13254
  }
13034
13255
  function wsStringVal(tag, val) {
13035
- return `<${tag} w:val="${wsEscapeAttr(val)}"/>`;
13256
+ return `<${tag} w:val="${escapeXml(val)}"/>`;
13036
13257
  }
13037
13258
  function wsNumVal(tag, val) {
13038
13259
  return `<${tag} w:val="${val}"/>`;
13039
13260
  }
13040
- function wsEscapeAttr(s) {
13041
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13042
- }
13043
13261
  function parseFramesetEl(el) {
13044
13262
  const opts = {};
13045
13263
  const sz = findChild(el, "w:sz");
@@ -13199,8 +13417,8 @@ function wsDivBorderXml(b) {
13199
13417
  ];
13200
13418
  for (const [tag, side] of sides) {
13201
13419
  if (!side) continue;
13202
- const attrParts = [`w:val="${wsEscapeAttr(side.style)}"`];
13203
- if (side.color) attrParts.push(`w:color="${wsEscapeAttr(side.color)}"`);
13420
+ const attrParts = [`w:val="${escapeXml(side.style)}"`];
13421
+ if (side.color) attrParts.push(`w:color="${escapeXml(side.color)}"`);
13204
13422
  if (side.size !== void 0) attrParts.push(`w:sz="${side.size}"`);
13205
13423
  parts.push(`<${tag} ${attrParts.join(" ")}/>`);
13206
13424
  }
@@ -13247,13 +13465,13 @@ function frameXml(f) {
13247
13465
  if (f.size !== void 0) parts.push(wsStringVal("w:sz", f.size));
13248
13466
  if (f.name !== void 0) parts.push(wsStringVal("w:name", f.name));
13249
13467
  if (f.title !== void 0) parts.push(wsStringVal("w:title", f.title));
13250
- if (f.sourceRId !== void 0) parts.push(`<w:sourceFileName r:id="${wsEscapeAttr(f.sourceRId)}"/>`);
13468
+ if (f.sourceRId !== void 0) parts.push(`<w:sourceFileName r:id="${escapeXml(f.sourceRId)}"/>`);
13251
13469
  if (f.marginWidth !== void 0) parts.push(wsNumVal("w:marW", f.marginWidth));
13252
13470
  if (f.marginHeight !== void 0) parts.push(wsNumVal("w:marH", f.marginHeight));
13253
13471
  if (f.scrollbar !== void 0) parts.push(`<w:scrollbar w:val="${f.scrollbar}"/>`);
13254
13472
  if (f.noResizeAllowed) parts.push("<w:noResizeAllowed/>");
13255
13473
  if (f.linkedToFile) parts.push("<w:linkedToFile/>");
13256
- if (f.longDescRId !== void 0) parts.push(`<w:longDesc r:id="${wsEscapeAttr(f.longDescRId)}"/>`);
13474
+ if (f.longDescRId !== void 0) parts.push(`<w:longDesc r:id="${escapeXml(f.longDescRId)}"/>`);
13257
13475
  parts.push("</w:frame>");
13258
13476
  return parts.join("");
13259
13477
  }
@@ -13273,7 +13491,7 @@ const webSettingsDesc = {
13273
13491
  if (typeof ob === "boolean") p.push(wsOnOff("w:optimizeForBrowser", ob));
13274
13492
  else {
13275
13493
  const valAttr = ob.value === false ? " w:val=\"false\"" : "";
13276
- const targetAttr = ob.target ? ` w:target="${wsEscapeAttr(ob.target)}"` : "";
13494
+ const targetAttr = ob.target ? ` w:target="${escapeXml(ob.target)}"` : "";
13277
13495
  p.push(`<w:optimizeForBrowser${valAttr}${targetAttr}/>`);
13278
13496
  }
13279
13497
  }
@@ -13338,6 +13556,6 @@ const webSettingsDesc = {
13338
13556
  }
13339
13557
  };
13340
13558
  //#endregion
13341
- export { PageBorderZOrder as $, stringifyCustomXmlShell as $t, settingsDesc as A, createBodyProperties as An, sectionPageSizeDefaults as At, stringifyConditionalTableStyle as B, TextAlignmentType as Bn, NumberFormat as Bt, footnotesDesc as C, EmphasisMarkType as Cn, parseSdtBlock as Ct, SdtDateMappingType as D, TextVertOverflowType as Dn, sectionPropertiesDesc as Dt, parseTocFieldInstruction as E, TextHorzOverflowType as En, parseSectionPropertiesEl as Et, parseStyleDefinitions as F, createTransformation as Fn, createVerticalPosition as Ft, createHeaderFooterReference as G, TextWrappingSide as Gt, stringifyTableStyle as H, HeadingLevel as Hn, VerticalPositionAlign as Ht, DefaultStylesFactory as I, HighlightColor as In, createHorizontalPosition as It, LineNumberRestartFormat as J, checkboxSymbolRunInner as Jt, SectionType as K, TextWrappingType as Kt, STYLE_ID_TO_DEFAULT_FIELD as L, TextEffect as Ln, HorizontalPositionRelativeFrom as Lt, buildNumberingCache as M, createImageData$1 as Mn, PageOrientation as Mt, buildStyleCache as N, WORKAROUND2 as Nn, PageNumberSeparator as Nt, SdtLock as O, TextVerticalType as On, stringifySectionPropertiesXml as Ot, extractStyleId as P, Media as Pn, createPageNumberType as Pt, PageBorderOffsetFrom as Q, setBodyParseChild as Qt, collectDefaultOverrideIds as R, PageNumber as Rn, VerticalPositionRelativeFrom as Rt, endnotesDesc as S, PositionalTabRelativeTo as Sn, stringifyTableOfContents as St, parseTocFieldFromElements as T, TextBodyWrappingType as Tn, FontWrapper as Tt, HeaderFooterReferenceType as U, LineRuleType as Un, createWrapThrough as Ut, stringifyParagraphStyle as V, TextboxTightWrapType as Vn, SpaceType as Vt, HeaderFooterType as W, AlignmentType as Wn, createWrapTight as Wt, createPageMargin as X, parseCustomXmlProperties as Xt, createLineNumberType as Y, customXmlBlockDesc as Yt, PageBorderDisplay as Z, sdtBlockDesc as Zt, glossaryDesc as _, createFormFieldData as _n, parseParagraph as _t, appPropertiesDesc as a, WidthType as an, LevelFormat as at, CharacterSet as b, PositionalTabAlignment as bn, stringifyDocumentXml as bt, relationshipsDesc as c, TableLayoutType as cn, parseTablePropertiesEl as ct, withAltChunkOverrides as d, RelativeVerticalPosition as dn, tableDesc as dt, stringifySdtPr as en, DocumentGridType as et, withMediaDefaults as f, TableAnchorType as fn, stringifyChildDispatch as ft, DocPartType as g, FormFieldTextType as gn, resetDrawingIdGen as gt, DocPartGallery as h, ProofErrorType as hn, drawingDesc as ht, webSettingsDesc as i, objectDesc as in, parseNumberingDefinitions as it, Styles as j, parseBodyProperties as jn, PageTextDirectionType as jt, StyleLevel as k, VerticalAnchor as kn, sectionMarginDefaults as kt, buildContentTypesFromRegistry as l, OverlapType as ln, parseTableRowPropertiesEl as lt, DocPartBehavior as m, VerticalMergeType as mn, stringifyRunInline as mt, frameXml as n, subDocDesc as nn, DocumentAttributeNamespaces as nt, customPropertiesDesc as o, TABLE_BORDERS_NONE as on, LevelSuffix as ot, commentsDesc as p, TextDirection as pn, stringifyParagraphInline as pt, createSectionType as q, altChunkDesc as qt, framesetXml as r, stringifyElement as rn, Numbering as rt, corePropertiesDesc as s, BorderStyle as sn, parseTableCellPropertiesEl as st, TargetScreenSize as t, stringifySdtShell as tn, createDocumentGrid as tt, contentTypesDesc as u, RelativeHorizontalPosition as un, setTableParseChild as ut, bibliographyDesc as v, parseFormFieldData as vn, parseParagraphProperties as vt, parseToc as w, UnderlineType as wn, parseSdtProperties as wt, EditGroupType as x, PositionalTabLeader as xn, replaceRelsWithPlaceholders as xt, fontTableDesc as y, RubyAlign as yn, stringifyBodyChild as yt, stringifyCharacterStyle as z, breakXml as zn, HorizontalPositionAlign as zt };
13559
+ export { DocumentGridType as $, stringifySdtPr as $t, settingsDesc as A, parseBodyProperties as An, PageTextDirectionType as At, stringifyParagraphStyle as B, HeadingLevel as Bn, SpaceType as Bt, footnotesDesc as C, UnderlineType as Cn, parseSdtProperties as Ct, SdtDateMappingType as D, TextVerticalType as Dn, stringifySectionPropertiesXml as Dt, parseTocFieldInstruction as E, TextVertOverflowType as En, sectionPropertiesDesc as Et, parseStyleDefinitions as F, TextEffect as Fn, createHorizontalPosition as Ft, SectionType as G, TextWrappingType as Gt, HeaderFooterReferenceType as H, AlignmentType as Hn, createWrapThrough as Ht, DefaultStylesFactory as I, PageNumber as In, HorizontalPositionRelativeFrom as It, createLineNumberType as J, customXmlBlockDesc as Jt, createSectionType as K, altChunkDesc as Kt, stringifyCharacterStyle as L, breakXml as Ln, VerticalPositionRelativeFrom as Lt, buildNumberingCache as M, Media as Mn, PageNumberSeparator as Mt, buildStyleCache as N, createTransformation as Nn, createPageNumberType as Nt, SdtLock as O, VerticalAnchor as On, sectionMarginDefaults as Ot, extractStyleId as P, HighlightColor as Pn, createVerticalPosition as Pt, PageBorderZOrder as Q, stringifyCustomXmlShell as Qt, stringifyConditionalTableStyle as R, TextAlignmentType as Rn, HorizontalPositionAlign as Rt, endnotesDesc as S, EmphasisMarkType as Sn, parseSdtBlock as St, parseTocFieldFromElements as T, TextHorzOverflowType as Tn, parseSectionPropertiesEl as Tt, HeaderFooterType as U, createWrapTight as Ut, stringifyTableStyle as V, LineRuleType as Vn, VerticalPositionAlign as Vt, createHeaderFooterReference as W, TextWrappingSide as Wt, PageBorderDisplay as X, sdtBlockDesc as Xt, createPageMargin as Y, parseCustomXmlProperties as Yt, PageBorderOffsetFrom as Z, setBodyParseChild as Zt, glossaryDesc as _, parseFormFieldData as _n, parseParagraphProperties as _t, appPropertiesDesc as a, TABLE_BORDERS_NONE as an, LevelSuffix as at, CharacterSet as b, PositionalTabLeader as bn, replaceRelsWithPlaceholders as bt, relationshipsDesc as c, OverlapType as cn, parseTableRowPropertiesEl as ct, withAltChunkOverrides as d, TableAnchorType as dn, stringifyChildDispatch as dt, stringifySdtShell as en, createDocumentGrid as et, withMediaDefaults as f, TextDirection as fn, stringifyParagraphInline as ft, DocPartType as g, createFormFieldData as gn, parseParagraph as gt, DocPartGallery as h, FormFieldTextType as hn, resetDrawingIdGen as ht, webSettingsDesc as i, WidthType as in, LevelFormat as it, Styles as j, createImageData$1 as jn, PageOrientation as jt, StyleLevel as k, createBodyProperties as kn, sectionPageSizeDefaults as kt, buildContentTypesFromRegistry as l, RelativeHorizontalPosition as ln, setTableParseChild as lt, DocPartBehavior as m, ProofErrorType as mn, drawingDesc as mt, frameXml as n, stringifyElement as nn, Numbering as nt, customPropertiesDesc as o, BorderStyle as on, parseTableCellPropertiesEl as ot, commentsDesc as p, VerticalMergeType as pn, stringifyRunInline as pt, LineNumberRestartFormat as q, checkboxSymbolRunInner as qt, framesetXml as r, objectDesc as rn, parseNumberingDefinitions as rt, corePropertiesDesc as s, TableLayoutType as sn, parseTablePropertiesEl as st, TargetScreenSize as t, subDocDesc as tn, DocumentAttributeNamespaces as tt, contentTypesDesc as u, RelativeVerticalPosition as un, tableDesc as ut, bibliographyDesc as v, RubyAlign as vn, stringifyBodyChild as vt, parseToc as w, TextBodyWrappingType as wn, FontWrapper as wt, EditGroupType as x, PositionalTabRelativeTo as xn, stringifyTableOfContents as xt, fontTableDesc as y, PositionalTabAlignment as yn, stringifyDocumentXml as yt, stringifyNumberingStyle as z, TextboxTightWrapType as zn, NumberFormat as zt };
13342
13560
 
13343
- //# sourceMappingURL=parts-DVpfsxSR.mjs.map
13561
+ //# sourceMappingURL=parts-BXGYKB-u.mjs.map