@office-open/core 0.6.4 → 0.6.6

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,11 +1,11 @@
1
- import { _ as XmlAttributeComponent, a as BuilderElement, b as XmlComponent, c as chartAttr, d as onOffObj, f as stringContainerObj, g as NextAttributeComponent, h as wrapEl, i as convertToXmlComponent, l as hpsMeasureObj, m as stringValObj, n as ImportedRootElementAttributes, o as EmptyElement, p as stringEnumValObj, r as ImportedXmlComponent, s as attrObj, t as InitializableXmlComponent, u as numberValObj, v as EMPTY_OBJECT, x as BaseXmlComponent, y as IgnoreIfEmptyXmlComponent } from "./xml-components-CADgke8j.mjs";
2
- import { ThemeColor, ThemeFont, dateTimeValue, decimalNumber, eighthPointMeasureValue, hexBinary, hexColorValue, hpsMeasureValue, longHexNumber, measurementOrPercentValue, percentageValue, pointMeasureValue, positiveUniversalMeasureValue, shortHexNumber, signedHpsMeasureValue, signedTwipsMeasureValue, twipsMeasureValue, uCharHexNumber, universalMeasureValue, unsignedDecimalNumber } from "./values.mjs";
3
- import { A as convertPointsToEmu, C as convertEmuToInches, D as convertInchesToTwip, E as convertInchesToEmu, O as convertMillimetersToTwip, S as uniqueUuid, T as convertEmuToPoints, _ as xsdUnderlineStyle, a as xsdLineCap, b as uniqueId, c as xsdPathFillMode, d as xsdPresetShadow, f as xsdRectAlignment, g as xsdTextCaps, h as xsdTextAnchor, i as xsdEffectContainer, k as convertPixelsToEmu, l as xsdPattern, m as xsdTextAlign, n as xsdBlendMode, o as xsdLineEndSize, p as xsdStrikeStyle, r as xsdCompoundLine, s as xsdMaterialType, t as invertMap, u as xsdPenAlignment, v as xsdVerticalMergeRev, w as convertEmuToPixels, x as uniqueNumericIdCreator, y as hashedId } from "./xsd-mappings-BiTj9yJn.mjs";
4
- import { a as DataModel, c as getColorXml, d as COLOR_CATEGORIES, f as LAYOUT_CATEGORIES, i as TransPoint, l as getLayoutXml, n as SmartArtCollection, o as Connection, p as STYLE_CATEGORIES, r as Point, s as DEFAULT_DRAWING_XML, t as createDataModel, u as getStyleXml } from "./smartart-DBQ_rRfK.mjs";
5
- import { elementToXml, findRel, findRelsByType, getImageType, listFiles, parseRels, readAllXmlParts, readBinaryFromZip, readTextFromZip, readXmlFromZip, uint8ToBase64, unzipToMap, zipToBuffer } from "./archive.mjs";
6
- import { js2xml, textOf, xml2js } from "@office-open/xml";
7
- import { AsyncZipDeflate, Zip, ZipPassThrough, strFromU8, strFromU8 as strFromU8$1, strToU8, unzipSync, zip, zipSync } from "fflate";
8
- import { Readable } from "stream";
1
+ import { _ as XmlAttributeComponent, a as BuilderElement, b as XmlComponent, c as chartAttr, d as onOffObj, f as stringContainerObj, g as NextAttributeComponent, h as wrapEl, i as convertToXmlComponent, l as hpsMeasureObj, m as stringValObj, n as ImportedRootElementAttributes, o as EmptyElement, p as stringEnumValObj, r as ImportedXmlComponent, s as attrObj, t as InitializableXmlComponent, u as numberValObj, v as EMPTY_OBJECT, x as BaseXmlComponent, y as IgnoreIfEmptyXmlComponent } from "./xml-components-SxPlKGms.js";
2
+ import { ThemeColor, ThemeFont, dateTimeValue, decimalNumber, eighthPointMeasureValue, hexBinary, hexColorValue, hpsMeasureValue, longHexNumber, measurementOrPercentValue, percentageValue, pointMeasureValue, positiveUniversalMeasureValue, shortHexNumber, signedHpsMeasureValue, signedTwipsMeasureValue, twipsMeasureValue, uCharHexNumber, universalMeasureValue, unsignedDecimalNumber } from "./values.js";
3
+ import { $ as xsdCompoundLine, A as LineJoin, At as hashedId, B as createNoFill, Bt as convertPixelsToEmu, C as createOuterShadowEffect, Ct as createSchemeColor, D as createFillOverlayEffect, Dt as createPresetColor, E as BlendMode, Et as PresetColor, F as LineEndType, Ft as convertEmuToPixels, G as PathShadeType, H as extractBlipFillMedia, I as LineEndWidth, It as convertEmuToPoints, J as createGradientStop, K as TileFlipMode, L as createLineEnd, Lt as convertInchesToEmu, M as PresetDash, Mt as uniqueNumericIdCreator, N as createOutline, Nt as uniqueUuid, O as CompoundLine, Ot as createHslColor, P as LineEndLength, Pt as convertEmuToInches, Q as xsdBlendMode, R as createCustomDash, Rt as convertInchesToTwip, S as RectAlignment, St as SchemeColor, T as createGlowEffect, Tt as createRgbColor, U as PresetPattern, V as buildFill, Vt as convertPointsToEmu, W as createPatternFill, X as createTileInfo, Y as TileAlignment, Z as invertMap, _ as createEffectList, _t as createBlipEffects, a as createBlip, at as xsdPattern, b as PresetShadowVal, bt as SystemColor, c as PresetGeometry, ct as xsdRectAlignment, d as createShape3D, dt as xsdTextAnchor, et as xsdEffectContainer, f as BevelPresetType, ft as xsdTextCaps, g as createEffectDag, gt as createSourceRectangle, h as createScene3D, ht as Stretch, i as createBlipFill, it as xsdPathFillMode, j as PenAlignment, jt as uniqueId, k as LineCap, kt as createColorTransforms, l as createAdjustmentValues, lt as xsdStrikeStyle, m as createBottomBevel, mt as xsdVerticalMergeRev, n as createGroupTransform2D, nt as xsdLineEndSize, o as createExtentionList, ot as xsdPenAlignment, p as createBevel, pt as xsdUnderlineStyle, q as createGradientFill, r as createTransform2D, rt as xsdMaterialType, s as createCustomGeometry, st as xsdPresetShadow, t as createTransformation, tt as xsdLineCap, u as PresetMaterialType, ut as xsdTextAlign, v as createSoftEdgeEffect, vt as createColorElement, w as createInnerShadowEffect, wt as createScRgbColor, x as createPresetShadowEffect, xt as createSystemColor, y as createReflectionEffect, yt as createSolidFill, z as createGroupFill, zt as convertMillimetersToTwip } from "./drawingml-DG6euH0k.js";
4
+ import { a as DataModel, c as getColorXml, d as COLOR_CATEGORIES, f as LAYOUT_CATEGORIES, i as TransPoint, l as getLayoutXml, n as SmartArtCollection, o as Connection, p as STYLE_CATEGORIES, r as Point, s as DEFAULT_DRAWING_XML, t as createDataModel, u as getStyleXml } from "./smartart-DGNfjKA9.js";
5
+ import { a as ScatterChart, c as BarChart, d as createStrRef, f as CatAx, i as createChartType, l as AreaChart, n as ChartSpace, o as PieChart, p as ValAx, r as ChartTitle, s as LineChart, t as ChartCollection, u as createNumRef } from "./chart-BUlAcF2k.js";
6
+ import { a as createTraverser, c as TokenNotFoundError, d as getFirstLevelElements, f as patchSpaceAttribute, h as PPTX_NS, i as createReplacer, l as createSplitInject, m as DOCX_NS, n as getNextRelationshipIndex, o as createRunRenderer, p as toJson, r as appendContentType, s as createTokenReplacer, t as appendRelationship, u as createTextElementContents } from "./patch-BWan_fhF.js";
7
+ import { escapeXml, js2xml, textOf, xml2js } from "@office-open/xml";
8
+ import { AsyncZipDeflate, Zip, ZipPassThrough, strFromU8, strFromU8 as strFromU8$1, strToU8, unzipSync, unzipSync as unzipSync$1, zip, zipSync } from "fflate";
9
9
  //#region src/output-type.ts
10
10
  /**
11
11
  * Output type definitions for OOXML document export.
@@ -14,7 +14,8 @@ import { Readable } from "stream";
14
14
  */
15
15
  const OoxmlMimeType = {
16
16
  DOCX: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
17
- PPTX: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
17
+ PPTX: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
18
+ XLSX: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
18
19
  };
19
20
  const convertOutput = (data, type, mimeType = OoxmlMimeType.DOCX) => {
20
21
  switch (type) {
@@ -37,13 +38,6 @@ const convertOutput = (data, type, mimeType = OoxmlMimeType.DOCX) => {
37
38
  *
38
39
  * @module
39
40
  */
40
- const PrettifyType = {
41
- NONE: "",
42
- WITH_2_BLANKS: " ",
43
- WITH_4_BLANKS: " ",
44
- WITH_TAB: " "
45
- };
46
- const convertPrettifyType = (prettify) => prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? void 0 : prettify;
47
41
  /** Default DEFLATE compression level matching Microsoft Office behavior. */
48
42
  const ZIP_DEFLATE_LEVEL = 6;
49
43
  /** STORE level for already-compressed media formats (JPEG, PNG, GIF, etc.). */
@@ -57,7 +51,10 @@ const ZIP_STORED_LEVEL = 0;
57
51
  */
58
52
  const zipAndConvert = async (files, type, mimeType, level = 6) => {
59
53
  return convertOutput(await new Promise((resolve, reject) => {
60
- zip(files, { level }, (err, data) => {
54
+ zip(files, {
55
+ level,
56
+ consume: true
57
+ }, (err, data) => {
61
58
  if (err) reject(err);
62
59
  else resolve(data);
63
60
  });
@@ -73,35 +70,35 @@ const zipSyncAndConvert = (files, type, mimeType, level = 6) => {
73
70
  return convertOutput(zipSync(files, { level }), type, mimeType);
74
71
  };
75
72
  /**
76
- * Create a Node.js Readable stream from compressed file entries.
73
+ * Create a `ReadableStream<Uint8Array>` from compressed file entries.
77
74
  *
78
- * Uses fflate's AsyncZipDeflate for non-blocking DEFLATE compression via
79
- * Web Workers. STORED entries (media) pass through synchronously.
80
- * Chunks are emitted asynchronously as each file's compression completes.
75
+ * Uses fflate's `AsyncZipDeflate` for non-blocking DEFLATE compression.
76
+ * `STORED` entries (media) pass through synchronously.
77
+ * Works in both Node.js and browsers (Web Streams API).
81
78
  */
82
79
  const createZipStream = (files) => {
83
- const stream = new Readable({ read() {} });
84
- try {
85
- const zip = new Zip((err, chunk, final) => {
86
- if (err) {
87
- stream.destroy(err);
88
- return;
80
+ return new ReadableStream({ start(controller) {
81
+ try {
82
+ const zip = new Zip((err, chunk, _final) => {
83
+ if (err) {
84
+ controller.error(err);
85
+ return;
86
+ }
87
+ controller.enqueue(chunk);
88
+ if (_final) controller.close();
89
+ });
90
+ for (const [name, data] of Object.entries(files)) {
91
+ const raw = Array.isArray(data) ? data[0] : data;
92
+ const level = Array.isArray(data) ? data[1].level ?? 6 : 6;
93
+ const entry = level === 0 ? new ZipPassThrough(name) : new AsyncZipDeflate(name, { level });
94
+ zip.add(entry);
95
+ entry.push(raw, true);
89
96
  }
90
- if (!stream.destroyed) stream.push(Buffer.from(chunk));
91
- if (final) stream.push(null);
92
- });
93
- for (const [name, data] of Object.entries(files)) {
94
- const raw = Array.isArray(data) ? data[0] : data;
95
- const level = Array.isArray(data) ? data[1].level ?? 6 : 6;
96
- const entry = level === 0 ? new ZipPassThrough(name) : new AsyncZipDeflate(name, { level });
97
- zip.add(entry);
98
- entry.push(raw, true);
97
+ zip.end();
98
+ } catch (err) {
99
+ controller.error(err instanceof Error ? err : new Error(String(err)));
99
100
  }
100
- zip.end();
101
- } catch (err) {
102
- stream.destroy(err instanceof Error ? err : new Error(String(err)));
103
- }
104
- return stream;
101
+ } });
105
102
  };
106
103
  /**
107
104
  * Create a Packer object with all output format methods.
@@ -112,33 +109,33 @@ const createZipStream = (files) => {
112
109
  */
113
110
  const createPacker = (options) => {
114
111
  const { compile, mimeType } = options;
115
- const compileFiles = (file, prettify, overrides = []) => compile(file, convertPrettifyType(prettify), overrides);
116
- const pack = async (file, type, prettify, overrides) => {
117
- return zipAndConvert(compileFiles(file, prettify, overrides), type, mimeType);
112
+ const compileFiles = (file, overrides = []) => compile(file, overrides);
113
+ const pack = async (file, type, overrides) => {
114
+ return zipAndConvert(compileFiles(file, overrides), type, mimeType);
118
115
  };
119
- const toBytes = (file, prettify, overrides) => pack(file, "uint8array", prettify, overrides);
120
- const toString = (file, prettify, overrides) => pack(file, "string", prettify, overrides);
121
- const toBuffer = (file, prettify, overrides) => pack(file, "nodebuffer", prettify, overrides);
122
- const toBase64String = (file, prettify, overrides) => pack(file, "base64", prettify, overrides);
123
- const toBlob = (file, prettify, overrides) => pack(file, "blob", prettify, overrides);
124
- const toArrayBuffer = (file, prettify, overrides) => pack(file, "arraybuffer", prettify, overrides);
125
- const packSync = (file, type, prettify, overrides) => {
126
- return zipSyncAndConvert(compileFiles(file, prettify, overrides), type, mimeType);
116
+ const toBytes = (file, overrides) => pack(file, "uint8array", overrides);
117
+ const toString = (file, overrides) => pack(file, "string", overrides);
118
+ const toBuffer = (file, overrides) => pack(file, "nodebuffer", overrides);
119
+ const toBase64String = (file, overrides) => pack(file, "base64", overrides);
120
+ const toBlob = (file, overrides) => pack(file, "blob", overrides);
121
+ const toArrayBuffer = (file, overrides) => pack(file, "arraybuffer", overrides);
122
+ const packSync = (file, type, overrides) => {
123
+ return zipSyncAndConvert(compileFiles(file, overrides), type, mimeType);
127
124
  };
128
- const toBytesSync = (file, prettify, overrides) => packSync(file, "uint8array", prettify, overrides);
129
- const toStringSync = (file, prettify, overrides) => packSync(file, "string", prettify, overrides);
130
- const toBufferSync = (file, prettify, overrides) => packSync(file, "nodebuffer", prettify, overrides);
131
- const toBase64StringSync = (file, prettify, overrides) => packSync(file, "base64", prettify, overrides);
132
- const toBlobSync = (file, prettify, overrides) => packSync(file, "blob", prettify, overrides);
133
- const toArrayBufferSync = (file, prettify, overrides) => packSync(file, "arraybuffer", prettify, overrides);
134
- const toStream = (file, prettify, overrides) => {
125
+ const toBytesSync = (file, overrides) => packSync(file, "uint8array", overrides);
126
+ const toStringSync = (file, overrides) => packSync(file, "string", overrides);
127
+ const toBufferSync = (file, overrides) => packSync(file, "nodebuffer", overrides);
128
+ const toBase64StringSync = (file, overrides) => packSync(file, "base64", overrides);
129
+ const toBlobSync = (file, overrides) => packSync(file, "blob", overrides);
130
+ const toArrayBufferSync = (file, overrides) => packSync(file, "arraybuffer", overrides);
131
+ const toStream = (file, overrides) => {
135
132
  let files;
136
133
  try {
137
- files = compileFiles(file, prettify, overrides);
134
+ files = compileFiles(file, overrides);
138
135
  } catch (err) {
139
- const errorStream = new Readable({ read() {} });
140
- errorStream.destroy(err instanceof Error ? err : new Error(String(err)));
141
- return errorStream;
136
+ return new ReadableStream({ start(controller) {
137
+ controller.error(err instanceof Error ? err : new Error(String(err)));
138
+ } });
142
139
  }
143
140
  return createZipStream(files);
144
141
  };
@@ -193,6 +190,19 @@ var Relationships = class extends BaseXmlComponent {
193
190
  get relationshipCount() {
194
191
  return this.entries.length;
195
192
  }
193
+ /**
194
+ * Zero-allocation fast path: directly concatenate XML string.
195
+ * Bypasses the IXmlableObject intermediate tree entirely.
196
+ */
197
+ toXml(_context) {
198
+ const p = ["<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">"];
199
+ for (const e of this.entries) {
200
+ const tm = e.targetMode ? ` TargetMode="${escapeXml(e.targetMode)}"` : "";
201
+ p.push(`<Relationship Id="${escapeXml(e.id)}" Type="${escapeXml(e.type)}" Target="${escapeXml(e.target)}"${tm}/>`);
202
+ }
203
+ p.push("</Relationships>");
204
+ return p.join("");
205
+ }
196
206
  prepForXml(_context) {
197
207
  const children = [RELS_ATTRS];
198
208
  for (const e of this.entries) {
@@ -256,7 +266,7 @@ const createOverride = (contentType, partName) => new BuilderElement({
256
266
  //#region src/formatter.ts
257
267
  const XML_DECL = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
258
268
  /**
259
- * Converts an XmlComponent tree into a serializable XML object.
269
+ * Converts an XmlComponent tree into a serializable XML object or string.
260
270
  */
261
271
  var Formatter = class {
262
272
  format(input, context = { stack: [] }) {
@@ -264,9 +274,14 @@ var Formatter = class {
264
274
  if (output) return output;
265
275
  throw new Error("XMLComponent did not format correctly");
266
276
  }
277
+ /**
278
+ * Serialize a component directly to XML string via the toXml() fast path.
279
+ */
267
280
  formatToXml(input, context, declaration) {
268
- const str = input.toXml(context);
269
- return declaration ? XML_DECL + str : str;
281
+ const body = input.toXml(context);
282
+ if (!body) return "";
283
+ if (declaration) return (declaration === true ? XML_DECL : `<?xml version="1.0" encoding="${declaration.encoding || "UTF-8"}"${declaration.standalone ? ` standalone="${declaration.standalone}"` : ""}?>`) + body;
284
+ return body;
270
285
  }
271
286
  };
272
287
  //#endregion
@@ -297,11 +312,6 @@ const FIELD_MAP = [
297
312
  key: "lastModifiedBy"
298
313
  }
299
314
  ];
300
- function parseCoreProperties(zip) {
301
- const xml = readXmlFromZip(zip, "docProps/core.xml");
302
- if (!xml) return {};
303
- return parseCorePropsElement(xml);
304
- }
305
315
  /**
306
316
  * Parse core properties from an already-parsed XML element.
307
317
  * Shared by docx and pptx to extract Dublin Core metadata.
@@ -359,17 +369,17 @@ const XML_PARSE_OPTIONS = {
359
369
  captureSpacesBetweenElements: true
360
370
  };
361
371
  /**
362
- * Parsed OOXML document backed by an unzipped ZIP map.
372
+ * Parsed OOXML archive backed by an unzipped ZIP map.
363
373
  *
364
374
  * Provides unstorage-style API (get/set/getRaw/setRaw/remove/has/keys)
365
375
  * for reading and modifying individual parts, then serializing back to a ZIP buffer.
366
376
  */
367
- var ParsedDocument = class {
377
+ var ParsedArchive = class {
368
378
  zip;
369
379
  modified = /* @__PURE__ */ new Map();
370
380
  wrapperCache = /* @__PURE__ */ new Map();
371
- constructor(zip) {
372
- this.zip = zip;
381
+ constructor(data) {
382
+ this.zip = new Map(Object.entries(unzipSync$1(data)));
373
383
  }
374
384
  /** Read an XML part as an Element tree. */
375
385
  get(path) {
@@ -429,15 +439,19 @@ var ParsedDocument = class {
429
439
  }
430
440
  /** Serialize back to a ZIP buffer, merging original zip + modifications. */
431
441
  save() {
432
- const files = /* @__PURE__ */ new Map();
433
- for (const [path, data] of this.zip) if (!this.modified.has(path)) files.set(path, data);
434
- for (const [path, data] of this.modified) files.set(path, data);
435
- return zipToBuffer(files);
442
+ const files = {};
443
+ for (const [path, data] of this.zip) if (!this.modified.has(path)) files[path] = MEDIA_PATTERN.test(path) ? [data, { level: MEDIA_STORED_LEVEL }] : data;
444
+ for (const [path, data] of this.modified) files[path] = MEDIA_PATTERN.test(path) ? [data, { level: MEDIA_STORED_LEVEL }] : data;
445
+ return zipSync(files);
436
446
  }
437
447
  };
438
- /** Parse an OOXML archive (.docx, .pptx, .xlsx) into a ParsedDocument. */
448
+ /** Regex to detect already-compressed media file extensions. */
449
+ const MEDIA_PATTERN = /\.(png|jpe?g|gif|wmf|emf|tiff?|avi|mp4|mp3|wav)$/i;
450
+ /** STORE level for already-compressed media formats. */
451
+ const MEDIA_STORED_LEVEL = 0;
452
+ /** Parse an OOXML archive (.docx, .pptx, .xlsx) into a ParsedArchive. */
439
453
  function parseArchive(data) {
440
- return new ParsedDocument(unzipToMap(data));
454
+ return new ParsedArchive(data);
441
455
  }
442
456
  //#endregion
443
457
  //#region src/raw-passthrough.ts
@@ -545,4 +559,22 @@ function addSmartArtRelationships(keys, addRel, baseOffset, globalStartIndex, op
545
559
  });
546
560
  }
547
561
  //#endregion
548
- export { AppProperties, BaseXmlComponent, BuilderElement, COLOR_CATEGORIES, Connection, DEFAULT_DRAWING_XML, DataModel, EMPTY_OBJECT, EmptyElement, Formatter, IgnoreIfEmptyXmlComponent, ImportedRootElementAttributes, ImportedXmlComponent, InitializableXmlComponent, LAYOUT_CATEGORIES, NextAttributeComponent, OoxmlMimeType, ParsedDocument, Point, PrettifyType, RawPassthrough, Relationships, STYLE_CATEGORIES, SmartArtCollection, TargetModeType, ThemeColor, ThemeFont, TransPoint, XmlAttributeComponent, XmlComponent, ZIP_DEFLATE_LEVEL, ZIP_STORED_LEVEL, addSmartArtRelationships, attrObj, buildCorePropertiesXml, chartAttr, collectPlaceholderKeys, convertEmuToInches, convertEmuToPixels, convertEmuToPoints, convertInchesToEmu, convertInchesToTwip, convertMillimetersToTwip, convertOutput, convertPixelsToEmu, convertPointsToEmu, convertPrettifyType, convertToXmlComponent, createDataModel, createDefault, createOverride, createPacker, createZipStream, dateTimeValue, decimalNumber, eighthPointMeasureValue, elementToCompact, elementToXml, escapeRegex, findRel, findRelsByType, formatId, getColorXml, getImageType, getLayoutXml, getReferencedMedia, getStyleXml, hasPlaceholders, hashedId, hexBinary, hexColorValue, hpsMeasureObj, hpsMeasureValue, invertMap, listFiles, longHexNumber, measurementOrPercentValue, numberValObj, onOffObj, parseArchive, parseCoreProperties, parseCorePropsElement, parseRels, percentageValue, pointMeasureValue, positiveUniversalMeasureValue, readAllXmlParts, readBinaryFromZip, readTextFromZip, readXmlFromZip, replaceChartPlaceholders, replaceImagePlaceholders, replaceSmartArtPlaceholders, shortHexNumber, signedHpsMeasureValue, signedTwipsMeasureValue, strFromU8, stringContainerObj, stringEnumValObj, stringValObj, twipsMeasureValue, uCharHexNumber, uint8ToBase64, uniqueId, uniqueNumericIdCreator, uniqueUuid, universalMeasureValue, unsignedDecimalNumber, unzipSync, unzipToMap, wrapEl, xsdBlendMode, xsdCompoundLine, xsdEffectContainer, xsdLineCap, xsdLineEndSize, xsdMaterialType, xsdPathFillMode, xsdPattern, xsdPenAlignment, xsdPresetShadow, xsdRectAlignment, xsdStrikeStyle, xsdTextAlign, xsdTextAnchor, xsdTextCaps, xsdUnderlineStyle, xsdVerticalMergeRev, zipAndConvert, zipSyncAndConvert, zipToBuffer };
562
+ //#region src/compiler-utils.ts
563
+ /** Default STORE level for already-compressed media formats. */
564
+ const ZIP_STORED_LEVEL$1 = 0;
565
+ /** Reusable TextEncoder instance (stateless, safe to share). */
566
+ const encoder = new TextEncoder();
567
+ /**
568
+ * Convert a mapping of XML files + overrides + media into a Zippable structure.
569
+ *
570
+ * Centralises the mapping→Zippable conversion shared by all three compilers.
571
+ */
572
+ function compileMapping(mapping, overrides, media) {
573
+ const files = {};
574
+ for (const entry of Object.values(mapping)) files[entry.path] = encoder.encode(entry.data);
575
+ if (overrides) for (const o of overrides) files[o.path] = typeof o.data === "string" ? encoder.encode(o.data) : o.data;
576
+ if (media) for (const m of media) files[m.path] = [m.data, { level: ZIP_STORED_LEVEL$1 }];
577
+ return files;
578
+ }
579
+ //#endregion
580
+ export { AppProperties, AreaChart, BarChart, BaseXmlComponent, BevelPresetType, BlendMode, BuilderElement, COLOR_CATEGORIES, CatAx, ChartCollection, ChartSpace, ChartTitle, CompoundLine, Connection, DEFAULT_DRAWING_XML, DOCX_NS, DataModel, EMPTY_OBJECT, EmptyElement, Formatter, IgnoreIfEmptyXmlComponent, ImportedRootElementAttributes, ImportedXmlComponent, InitializableXmlComponent, LAYOUT_CATEGORIES, LineCap, LineChart, LineEndLength, LineEndType, LineEndWidth, LineJoin, NextAttributeComponent, OoxmlMimeType, PPTX_NS, ParsedArchive, PathShadeType, PenAlignment, PieChart, Point, PresetColor, PresetDash, PresetGeometry, PresetMaterialType, PresetPattern, PresetShadowVal, RawPassthrough, RectAlignment, Relationships, STYLE_CATEGORIES, ScatterChart, SchemeColor, SmartArtCollection, Stretch, SystemColor, TargetModeType, ThemeColor, ThemeFont, TileAlignment, TileFlipMode, TokenNotFoundError, TransPoint, ValAx, XmlAttributeComponent, XmlComponent, ZIP_DEFLATE_LEVEL, ZIP_STORED_LEVEL, addSmartArtRelationships, appendContentType, appendRelationship, attrObj, buildCorePropertiesXml, buildFill, chartAttr, collectPlaceholderKeys, compileMapping, convertEmuToInches, convertEmuToPixels, convertEmuToPoints, convertInchesToEmu, convertInchesToTwip, convertMillimetersToTwip, convertOutput, convertPixelsToEmu, convertPointsToEmu, convertToXmlComponent, createAdjustmentValues, createBevel, createBlip, createBlipEffects, createBlipFill, createBottomBevel, createChartType, createColorElement, createColorTransforms, createCustomDash, createCustomGeometry, createDataModel, createDefault, createEffectDag, createEffectList, createExtentionList, createFillOverlayEffect, createGlowEffect, createGradientFill, createGradientStop, createGroupFill, createGroupTransform2D, createHslColor, createInnerShadowEffect, createLineEnd, createNoFill, createNumRef, createOuterShadowEffect, createOutline, createOverride, createPacker, createPatternFill, createPresetColor, createPresetShadowEffect, createReflectionEffect, createReplacer, createRgbColor, createRunRenderer, createScRgbColor, createScene3D, createSchemeColor, createShape3D, createSoftEdgeEffect, createSolidFill, createSourceRectangle, createSplitInject, createStrRef, createSystemColor, createTextElementContents, createTileInfo, createTokenReplacer, createTransform2D, createTransformation, createTraverser, createZipStream, dateTimeValue, decimalNumber, eighthPointMeasureValue, elementToCompact, escapeRegex, extractBlipFillMedia, formatId, getColorXml, getFirstLevelElements, getLayoutXml, getNextRelationshipIndex, getReferencedMedia, getStyleXml, hasPlaceholders, hashedId, hexBinary, hexColorValue, hpsMeasureObj, hpsMeasureValue, invertMap, longHexNumber, measurementOrPercentValue, numberValObj, onOffObj, parseArchive, parseCorePropsElement, patchSpaceAttribute, percentageValue, pointMeasureValue, positiveUniversalMeasureValue, replaceChartPlaceholders, replaceImagePlaceholders, replaceSmartArtPlaceholders, shortHexNumber, signedHpsMeasureValue, signedTwipsMeasureValue, strFromU8, stringContainerObj, stringEnumValObj, stringValObj, toJson, twipsMeasureValue, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid, universalMeasureValue, unsignedDecimalNumber, unzipSync, wrapEl, xsdBlendMode, xsdCompoundLine, xsdEffectContainer, xsdLineCap, xsdLineEndSize, xsdMaterialType, xsdPathFillMode, xsdPattern, xsdPenAlignment, xsdPresetShadow, xsdRectAlignment, xsdStrikeStyle, xsdTextAlign, xsdTextAnchor, xsdTextCaps, xsdUnderlineStyle, xsdVerticalMergeRev, zipAndConvert, zipSyncAndConvert };
@@ -0,0 +1,2 @@
1
+ import { _ as PPTX_NS, a as getFirstLevelElements, c as TokenNotFoundError, d as createTraverser, f as RenderedParagraphNode, g as DOCX_NS, h as createReplacer, i as createTextElementContents, l as createSplitInject, m as ReplacerConfig, n as getNextRelationshipIndex, o as patchSpaceAttribute, p as createRunRenderer, r as appendContentType, s as toJson, t as appendRelationship, u as createTokenReplacer, v as XmlNamespaceConfig } from "../index-NK0k2I-R.js";
2
+ export { DOCX_NS, PPTX_NS, RenderedParagraphNode, ReplacerConfig, TokenNotFoundError, XmlNamespaceConfig, appendContentType, appendRelationship, createReplacer, createRunRenderer, createSplitInject, createTextElementContents, createTokenReplacer, createTraverser, getFirstLevelElements, getNextRelationshipIndex, patchSpaceAttribute, toJson };
@@ -0,0 +1,2 @@
1
+ import { a as createTraverser, c as TokenNotFoundError, d as getFirstLevelElements, f as patchSpaceAttribute, h as PPTX_NS, i as createReplacer, l as createSplitInject, m as DOCX_NS, n as getNextRelationshipIndex, o as createRunRenderer, p as toJson, r as appendContentType, s as createTokenReplacer, t as appendRelationship, u as createTextElementContents } from "../patch-BWan_fhF.js";
2
+ export { DOCX_NS, PPTX_NS, TokenNotFoundError, appendContentType, appendRelationship, createReplacer, createRunRenderer, createSplitInject, createTextElementContents, createTokenReplacer, createTraverser, getFirstLevelElements, getNextRelationshipIndex, patchSpaceAttribute, toJson };
@@ -0,0 +1,337 @@
1
+ import { xml2js } from "@office-open/xml";
2
+ //#region src/patch/xml-namespace.ts
3
+ const DOCX_NS = {
4
+ paragraph: "w:p",
5
+ run: "w:r",
6
+ text: "w:t",
7
+ runProperties: "w:rPr"
8
+ };
9
+ const PPTX_NS = {
10
+ paragraph: "a:p",
11
+ run: "a:r",
12
+ text: "a:t",
13
+ runProperties: "a:rPr"
14
+ };
15
+ //#endregion
16
+ //#region src/patch/xml-patch-utils.ts
17
+ /**
18
+ * XML utility functions for patch operations.
19
+ */
20
+ const toJson = (xmlData) => {
21
+ return xml2js(xmlData, {
22
+ captureSpacesBetweenElements: true,
23
+ compact: false
24
+ });
25
+ };
26
+ /**
27
+ * Creates the inner content of a text element (`w:t` / `a:t`).
28
+ *
29
+ * Returns `[{ type: "text", text }]` for non-empty text, `[]` for empty.
30
+ * The `xml:space` attribute is handled separately by `patchSpaceAttribute`.
31
+ */
32
+ const createTextElementContents = (text) => text === "" ? [] : [{
33
+ text,
34
+ type: "text"
35
+ }];
36
+ const patchSpaceAttribute = (element) => ({
37
+ ...element,
38
+ attributes: { "xml:space": "preserve" }
39
+ });
40
+ const getFirstLevelElements = (relationships, id) => relationships.elements?.filter((e) => e.name === id)[0].elements ?? [];
41
+ //#endregion
42
+ //#region src/patch/paragraph-split-inject.ts
43
+ var TokenNotFoundError = class extends Error {
44
+ constructor(token) {
45
+ super(`Token ${token} not found`);
46
+ this.name = "TokenNotFoundError";
47
+ }
48
+ };
49
+ function createSplitInject(ns, createTextElementContents, options) {
50
+ const preserveSpace = options?.preserveSpace ?? true;
51
+ const findRunElementIndexWithToken = (paragraphElement, token) => {
52
+ for (let i = 0; i < (paragraphElement.elements ?? []).length; i++) {
53
+ const element = paragraphElement.elements[i];
54
+ if (element.type === "element" && element.name === ns.run) {
55
+ const textElement = (element.elements ?? []).filter((e) => e.type === "element" && e.name === ns.text);
56
+ for (const text of textElement) {
57
+ if (!text.elements?.[0]) continue;
58
+ if (text.elements[0].text?.includes(token)) return i;
59
+ }
60
+ }
61
+ }
62
+ throw new TokenNotFoundError(token);
63
+ };
64
+ const splitRunElement = (runElement, token) => {
65
+ let splitIndex = -1;
66
+ const splitElements = runElement.elements?.map((e, i) => {
67
+ if (splitIndex !== -1) return e;
68
+ if (e.type === "element" && e.name === ns.text) {
69
+ const splitText = (e.elements?.[0]?.text ?? "").split(token);
70
+ const newElements = splitText.map((t) => ({
71
+ ...e,
72
+ ...preserveSpace ? patchSpaceAttribute(e) : {},
73
+ elements: createTextElementContents(t)
74
+ }));
75
+ if (splitText.length > 1) splitIndex = i;
76
+ return newElements;
77
+ } else return e;
78
+ }).flat() ?? [];
79
+ return {
80
+ left: {
81
+ ...structuredClone(runElement),
82
+ elements: splitElements.slice(0, splitIndex + 1)
83
+ },
84
+ right: {
85
+ ...structuredClone(runElement),
86
+ elements: splitElements.slice(splitIndex + 1)
87
+ }
88
+ };
89
+ };
90
+ return {
91
+ findRunElementIndexWithToken,
92
+ splitRunElement
93
+ };
94
+ }
95
+ //#endregion
96
+ //#region src/patch/paragraph-token-replacer.ts
97
+ const ReplaceMode = {
98
+ START: 0,
99
+ MIDDLE: 1,
100
+ END: 2
101
+ };
102
+ function createTokenReplacer(createTextElementContents, options) {
103
+ const preserveSpace = options?.preserveSpace ?? true;
104
+ const patchTextElement = (element, text) => {
105
+ element.elements = createTextElementContents(text);
106
+ return element;
107
+ };
108
+ return ({ paragraphElement, renderedParagraph, originalText, replacementText }) => {
109
+ const startIndex = renderedParagraph.text.indexOf(originalText);
110
+ const endIndex = startIndex + originalText.length - 1;
111
+ let replaceMode = ReplaceMode.START;
112
+ for (const run of renderedParagraph.runs) for (const { text, index, start, end } of run.parts) switch (replaceMode) {
113
+ case ReplaceMode.START:
114
+ if (startIndex >= start && startIndex <= end) {
115
+ const offsetStartIndex = startIndex - start;
116
+ const offsetEndIndex = Math.min(endIndex, end) - start;
117
+ const partToReplace = text.substring(offsetStartIndex, offsetEndIndex + 1);
118
+ if (partToReplace === "") continue;
119
+ const firstPart = text.replace(partToReplace, replacementText);
120
+ patchTextElement(paragraphElement.elements[run.index].elements[index], firstPart);
121
+ replaceMode = ReplaceMode.MIDDLE;
122
+ continue;
123
+ }
124
+ break;
125
+ case ReplaceMode.MIDDLE:
126
+ if (endIndex <= end) {
127
+ const lastPart = text.substring(endIndex - start + 1);
128
+ patchTextElement(paragraphElement.elements[run.index].elements[index], lastPart);
129
+ const currentElement = paragraphElement.elements[run.index].elements[index];
130
+ paragraphElement.elements[run.index].elements[index] = preserveSpace ? patchSpaceAttribute(currentElement) : currentElement;
131
+ replaceMode = ReplaceMode.END;
132
+ } else patchTextElement(paragraphElement.elements[run.index].elements[index], "");
133
+ break;
134
+ }
135
+ return paragraphElement;
136
+ };
137
+ }
138
+ //#endregion
139
+ //#region src/patch/run-renderer.ts
140
+ function createRunRenderer(ns) {
141
+ const renderParagraphNode = (node) => {
142
+ if (node.element.name !== ns.paragraph) throw new Error(`Invalid node type: ${node.element.name}`);
143
+ if (!node.element.elements) return {
144
+ index: -1,
145
+ pathToParagraph: [],
146
+ runs: [],
147
+ text: ""
148
+ };
149
+ let currentRunStringLength = 0;
150
+ const runs = node.element.elements.map((element, i) => ({
151
+ element,
152
+ i
153
+ })).filter(({ element }) => element.name === ns.run).map(({ element, i }) => {
154
+ const renderedRunNode = renderRunNode(element, i, currentRunStringLength);
155
+ currentRunStringLength += renderedRunNode.text.length;
156
+ return renderedRunNode;
157
+ }).filter((e) => Boolean(e));
158
+ const text = runs.reduce((acc, curr) => acc + curr.text, "");
159
+ return {
160
+ index: node.index,
161
+ pathToParagraph: buildNodePath(node),
162
+ runs,
163
+ text
164
+ };
165
+ };
166
+ const renderRunNode = (node, index, currentRunStringIndex) => {
167
+ if (!node.elements) return {
168
+ end: currentRunStringIndex,
169
+ index: -1,
170
+ parts: [],
171
+ start: currentRunStringIndex,
172
+ text: ""
173
+ };
174
+ let currentTextStringIndex = currentRunStringIndex;
175
+ const parts = node.elements.map((element, i) => element.name === ns.text && element.elements && element.elements.length > 0 ? (() => {
176
+ const partStart = currentTextStringIndex;
177
+ currentTextStringIndex += (element.elements[0].text?.toString() ?? "").length;
178
+ return {
179
+ end: currentTextStringIndex - 1,
180
+ index: i,
181
+ start: partStart,
182
+ text: element.elements[0].text?.toString() ?? ""
183
+ };
184
+ })() : void 0).filter((e) => Boolean(e)).map((e) => e);
185
+ const text = parts.reduce((acc, curr) => acc + curr.text, "");
186
+ return {
187
+ end: currentTextStringIndex - 1,
188
+ index,
189
+ parts,
190
+ start: currentRunStringIndex,
191
+ text
192
+ };
193
+ };
194
+ return renderParagraphNode;
195
+ }
196
+ const buildNodePath = (node) => node.parent ? [...buildNodePath(node.parent), node.index] : [node.index];
197
+ //#endregion
198
+ //#region src/patch/xml-traverser.ts
199
+ const elementsToWrapper = (wrapper) => wrapper.element.elements?.map((e, i) => ({
200
+ element: e,
201
+ index: i,
202
+ parent: wrapper
203
+ })) ?? [];
204
+ function createTraverser(ns) {
205
+ const renderParagraphNode = createRunRenderer(ns);
206
+ const traverse = (node) => {
207
+ let renderedParagraphs = [];
208
+ const queue = [...elementsToWrapper({
209
+ element: node,
210
+ index: 0,
211
+ parent: void 0
212
+ })];
213
+ let currentNode;
214
+ while (queue.length > 0) {
215
+ currentNode = queue.shift();
216
+ if (currentNode.element.name === ns.paragraph) renderedParagraphs = [...renderedParagraphs, renderParagraphNode(currentNode)];
217
+ queue.push(...elementsToWrapper(currentNode));
218
+ }
219
+ return renderedParagraphs;
220
+ };
221
+ const findLocationOfText = (node, text) => traverse(node).filter((p) => p.text.includes(text));
222
+ return {
223
+ traverse,
224
+ findLocationOfText
225
+ };
226
+ }
227
+ //#endregion
228
+ //#region src/patch/xml-replacer.ts
229
+ const SPLIT_TOKEN = "ɵ";
230
+ function createReplacer(config) {
231
+ const { ns, formatChild } = config;
232
+ const { findLocationOfText } = createTraverser(ns);
233
+ const replaceTokenInParagraphElement = createTokenReplacer(createTextElementContents, { preserveSpace: config.preserveSpace });
234
+ const { findRunElementIndexWithToken, splitRunElement } = createSplitInject(ns, createTextElementContents, { preserveSpace: config.preserveSpace });
235
+ const replacer = ({ json, patch, patchText, context, keepOriginalStyles = true }) => {
236
+ const renderedParagraphs = findLocationOfText(json, patchText);
237
+ if (renderedParagraphs.length === 0) return {
238
+ didFindOccurrence: false,
239
+ element: json
240
+ };
241
+ for (const renderedParagraph of renderedParagraphs) {
242
+ const textJson = patch.children.flatMap((c) => formatChild(c, context));
243
+ switch (patch.type) {
244
+ case "file": {
245
+ const parentElement = goToParentElementFromPath(json, renderedParagraph.pathToParagraph);
246
+ const elementIndex = getLastElementIndexFromPath(renderedParagraph.pathToParagraph);
247
+ parentElement.elements.splice(elementIndex, 1, ...textJson);
248
+ break;
249
+ }
250
+ default: {
251
+ const paragraphElement = goToElementFromPath(json, renderedParagraph.pathToParagraph);
252
+ replaceTokenInParagraphElement({
253
+ originalText: patchText,
254
+ paragraphElement,
255
+ renderedParagraph,
256
+ replacementText: SPLIT_TOKEN
257
+ });
258
+ const index = findRunElementIndexWithToken(paragraphElement, SPLIT_TOKEN);
259
+ const runElementToBeReplaced = paragraphElement.elements[index];
260
+ const { left, right } = splitRunElement(runElementToBeReplaced, SPLIT_TOKEN);
261
+ let newRunElements = textJson;
262
+ let patchedRightElement = right;
263
+ if (keepOriginalStyles) {
264
+ const runElementNonTextualElements = runElementToBeReplaced.elements.filter((e) => e.type === "element" && e.name === ns.runProperties);
265
+ newRunElements = textJson.map((e) => {
266
+ if (e.type !== "element" || e.name !== ns.run || e.elements?.some((c) => c.type === "element" && c.name === ns.runProperties)) return e;
267
+ return {
268
+ ...e,
269
+ elements: [...runElementNonTextualElements, ...e.elements ?? []]
270
+ };
271
+ });
272
+ patchedRightElement = {
273
+ ...right,
274
+ elements: [...runElementNonTextualElements, ...right.elements]
275
+ };
276
+ }
277
+ paragraphElement.elements.splice(index, 1, left, ...newRunElements, patchedRightElement);
278
+ break;
279
+ }
280
+ }
281
+ }
282
+ return {
283
+ didFindOccurrence: true,
284
+ element: json
285
+ };
286
+ };
287
+ return replacer;
288
+ }
289
+ const goToElementFromPath = (json, path) => {
290
+ let element = json;
291
+ for (let i = 1; i < path.length; i++) {
292
+ const index = path[i];
293
+ element = element.elements[index];
294
+ }
295
+ return element;
296
+ };
297
+ const goToParentElementFromPath = (json, path) => goToElementFromPath(json, path.slice(0, -1));
298
+ const getLastElementIndexFromPath = (path) => path[path.length - 1];
299
+ //#endregion
300
+ //#region src/patch/content-types-manager.ts
301
+ const appendContentType = (element, contentType, extension) => {
302
+ const relationshipElements = getFirstLevelElements(element, "Types");
303
+ if (relationshipElements.some((el) => el.type === "element" && el.name === "Default" && el?.attributes?.ContentType === contentType && el?.attributes?.Extension === extension)) return;
304
+ relationshipElements.push({
305
+ attributes: {
306
+ ContentType: contentType,
307
+ Extension: extension
308
+ },
309
+ name: "Default",
310
+ type: "element"
311
+ });
312
+ };
313
+ //#endregion
314
+ //#region src/patch/relationship-manager.ts
315
+ const getIdFromRelationshipId = (relationshipId) => {
316
+ const output = parseInt(relationshipId.substring(3), 10);
317
+ return isNaN(output) ? 0 : output;
318
+ };
319
+ const getNextRelationshipIndex = (relationships) => {
320
+ return getFirstLevelElements(relationships, "Relationships").map((e) => getIdFromRelationshipId(e.attributes?.Id?.toString() ?? "")).reduce((acc, curr) => Math.max(acc, curr), 0) + 1;
321
+ };
322
+ const appendRelationship = (relationships, id, type, target, targetMode) => {
323
+ const relationshipElements = getFirstLevelElements(relationships, "Relationships");
324
+ relationshipElements.push({
325
+ attributes: {
326
+ Id: `rId${id}`,
327
+ Target: target,
328
+ TargetMode: targetMode,
329
+ Type: type
330
+ },
331
+ name: "Relationship",
332
+ type: "element"
333
+ });
334
+ return relationshipElements;
335
+ };
336
+ //#endregion
337
+ export { createTraverser as a, TokenNotFoundError as c, getFirstLevelElements as d, patchSpaceAttribute as f, PPTX_NS as h, createReplacer as i, createSplitInject as l, DOCX_NS as m, getNextRelationshipIndex as n, createRunRenderer as o, toJson as p, appendContentType as r, createTokenReplacer as s, appendRelationship as t, createTextElementContents as u };