@cj-tech-master/excelts 9.5.0 → 9.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/browser/modules/pdf/excel-bridge.js +27 -1
  2. package/dist/browser/modules/pdf/render/layout-engine.js +74 -9
  3. package/dist/browser/modules/pdf/render/style-converter.d.ts +1 -1
  4. package/dist/browser/modules/pdf/render/style-converter.js +98 -1
  5. package/dist/browser/modules/pdf/types.d.ts +1 -0
  6. package/dist/browser/modules/word/color-utils.d.ts +18 -0
  7. package/dist/browser/modules/word/color-utils.js +94 -0
  8. package/dist/browser/modules/word/content-types.d.ts +15 -15
  9. package/dist/browser/modules/word/content-types.js +39 -43
  10. package/dist/browser/modules/word/crypto.d.ts +17 -0
  11. package/dist/browser/modules/word/crypto.js +18 -0
  12. package/dist/browser/modules/word/document-io.d.ts +58 -0
  13. package/dist/browser/modules/word/document-io.js +239 -0
  14. package/dist/browser/modules/word/document.d.ts +64 -135
  15. package/dist/browser/modules/word/document.js +207 -469
  16. package/dist/browser/modules/word/docx-packager.js +90 -90
  17. package/dist/browser/modules/word/html-renderer.js +1 -1
  18. package/dist/browser/modules/word/html.d.ts +13 -0
  19. package/dist/browser/modules/word/html.js +12 -0
  20. package/dist/browser/modules/word/index.base.d.ts +6 -9
  21. package/dist/browser/modules/word/index.base.js +7 -10
  22. package/dist/browser/modules/word/namespaces.d.ts +159 -0
  23. package/dist/browser/modules/word/namespaces.js +189 -0
  24. package/dist/browser/modules/word/relationships.d.ts +15 -16
  25. package/dist/browser/modules/word/relationships.js +37 -45
  26. package/dist/cjs/modules/pdf/excel-bridge.js +27 -1
  27. package/dist/cjs/modules/pdf/render/layout-engine.js +74 -9
  28. package/dist/cjs/modules/pdf/render/style-converter.js +98 -1
  29. package/dist/cjs/modules/word/color-utils.js +97 -0
  30. package/dist/cjs/modules/word/content-types.js +44 -45
  31. package/dist/cjs/modules/word/crypto.js +34 -0
  32. package/dist/cjs/modules/word/document-io.js +244 -0
  33. package/dist/cjs/modules/word/document.js +209 -473
  34. package/dist/cjs/modules/word/docx-packager.js +88 -88
  35. package/dist/cjs/modules/word/html-renderer.js +2 -2
  36. package/dist/cjs/modules/word/html.js +16 -0
  37. package/dist/cjs/modules/word/index.base.js +17 -27
  38. package/dist/cjs/modules/word/namespaces.js +192 -0
  39. package/dist/cjs/modules/word/relationships.js +42 -47
  40. package/dist/esm/modules/pdf/excel-bridge.js +27 -1
  41. package/dist/esm/modules/pdf/render/layout-engine.js +74 -9
  42. package/dist/esm/modules/pdf/render/style-converter.js +98 -1
  43. package/dist/esm/modules/word/color-utils.js +94 -0
  44. package/dist/esm/modules/word/content-types.js +39 -43
  45. package/dist/esm/modules/word/crypto.js +18 -0
  46. package/dist/esm/modules/word/document-io.js +239 -0
  47. package/dist/esm/modules/word/document.js +207 -469
  48. package/dist/esm/modules/word/docx-packager.js +90 -90
  49. package/dist/esm/modules/word/html-renderer.js +1 -1
  50. package/dist/esm/modules/word/html.js +12 -0
  51. package/dist/esm/modules/word/index.base.js +7 -10
  52. package/dist/esm/modules/word/namespaces.js +189 -0
  53. package/dist/esm/modules/word/relationships.js +37 -45
  54. package/dist/iife/excelts.iife.js +153 -11
  55. package/dist/iife/excelts.iife.js.map +1 -1
  56. package/dist/iife/excelts.iife.min.js +4 -4
  57. package/dist/types/modules/pdf/render/style-converter.d.ts +1 -1
  58. package/dist/types/modules/pdf/types.d.ts +1 -0
  59. package/dist/types/modules/word/color-utils.d.ts +18 -0
  60. package/dist/types/modules/word/content-types.d.ts +15 -15
  61. package/dist/types/modules/word/crypto.d.ts +17 -0
  62. package/dist/types/modules/word/document-io.d.ts +58 -0
  63. package/dist/types/modules/word/document.d.ts +64 -135
  64. package/dist/types/modules/word/html.d.ts +13 -0
  65. package/dist/types/modules/word/index.base.d.ts +6 -9
  66. package/dist/types/modules/word/namespaces.d.ts +159 -0
  67. package/dist/types/modules/word/relationships.d.ts +15 -16
  68. package/package.json +1 -1
@@ -5,9 +5,12 @@
5
5
  * High-level fluent API for constructing DOCX documents programmatically.
6
6
  * Provides convenience methods for common operations including comments,
7
7
  * track changes, TOC, math, text boxes, checkboxes, and custom properties.
8
+ *
9
+ * This file has NO static imports from docx-packager or docx-reader,
10
+ * ensuring that importing builder helpers does not pull in archive/xml code.
8
11
  */
9
12
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.DocumentBuilder = void 0;
13
+ exports.resolveThemeColor = exports.Document = void 0;
11
14
  exports.text = text;
12
15
  exports.bold = bold;
13
16
  exports.italic = italic;
@@ -103,7 +106,6 @@ exports.cell = cell;
103
106
  exports.row = row;
104
107
  exports.table = table;
105
108
  exports.simpleTable = simpleTable;
106
- exports.resolveThemeColor = resolveThemeColor;
107
109
  exports.paragraphCount = paragraphCount;
108
110
  exports.countWords = countWords;
109
111
  exports.getHeadings = getHeadings;
@@ -117,10 +119,6 @@ exports.extractText = extractText;
117
119
  exports.searchText = searchText;
118
120
  exports.replaceText = replaceText;
119
121
  exports.mailMerge = mailMerge;
120
- exports.patchDocument = patchDocument;
121
- const docx_packager_1 = require("./docx-packager");
122
- const docx_reader_1 = require("./docx-reader");
123
- const internal_utils_1 = require("./internal-utils");
124
122
  // =============================================================================
125
123
  // Helper Builders
126
124
  // =============================================================================
@@ -759,88 +757,91 @@ function simpleTable(data, options) {
759
757
  borders: opts.borders ? gridBorders() : undefined
760
758
  }, opts.columnWidths);
761
759
  }
762
- // =============================================================================
763
- // Document Builder Class
764
- // =============================================================================
760
+ /** Cast internal state to opaque handle. */
761
+ function _toHandle(state) {
762
+ return state;
763
+ }
764
+ /** Cast opaque handle back to internal state. */
765
+ function _toState(handle) {
766
+ return handle;
767
+ }
765
768
  /**
766
- * Fluent builder for constructing DOCX documents.
769
+ * Namespace of free functions for building DOCX documents.
770
+ *
771
+ * Replaces the former `DocumentBuilder` class with tree-shakeable free functions.
772
+ * Each function operates on an opaque `DocumentHandle`.
767
773
  *
768
774
  * @example
769
775
  * ```ts
770
- * const doc = new DocumentBuilder()
771
- * .addHeading("Hello World", 1)
772
- * .addParagraph("This is a paragraph.")
773
- * .addTable([["Name", "Age"], ["Alice", "30"]])
774
- * .build();
775
- *
776
- * const bytes = await doc.toBuffer();
776
+ * const doc = Document.create();
777
+ * Document.addHeading(doc, "Hello World", 1);
778
+ * Document.addParagraph(doc, "This is a paragraph.");
779
+ * Document.addTable(doc, [["Name", "Age"], ["Alice", "30"]]);
780
+ * const bytes = await Document.toBuffer(doc);
777
781
  * ```
778
782
  */
779
- class DocumentBuilder {
780
- constructor() {
781
- this._body = [];
782
- this._styles = [];
783
- this._abstractNumberings = [];
784
- this._numberingInstances = [];
785
- this._headers = new Map();
786
- this._footers = new Map();
787
- this._footnotes = [];
788
- this._endnotes = [];
789
- this._images = [];
790
- this._fonts = [];
791
- this._comments = [];
792
- this._customProperties = [];
793
- this._nextImageId = 1;
794
- this._nextFootnoteId = 1;
795
- this._nextEndnoteId = 1;
796
- this._nextBookmarkId = 0;
797
- this._nextAbstractNumId = 0;
798
- this._nextNumId = 1;
799
- this._nextDrawingId = 1;
800
- this._nextCommentId = 0;
801
- }
783
+ exports.Document = {
784
+ /** Create a new document handle. */
785
+ create() {
786
+ return _toHandle({
787
+ body: [],
788
+ styles: [],
789
+ abstractNumberings: [],
790
+ numberingInstances: [],
791
+ headers: new Map(),
792
+ footers: new Map(),
793
+ footnotes: [],
794
+ endnotes: [],
795
+ images: [],
796
+ fonts: [],
797
+ comments: [],
798
+ customProperties: [],
799
+ nextImageId: 1,
800
+ nextFootnoteId: 1,
801
+ nextEndnoteId: 1,
802
+ nextBookmarkId: 0,
803
+ nextAbstractNumId: 0,
804
+ nextNumId: 1,
805
+ nextDrawingId: 1,
806
+ nextCommentId: 0
807
+ });
808
+ },
802
809
  /** Add raw body content. */
803
- addContent(content) {
804
- this._body.push(content);
805
- return this;
806
- }
810
+ addContent(doc, content) {
811
+ _toState(doc).body.push(content);
812
+ },
807
813
  /** Add a paragraph with runs. */
808
- addParagraphElement(para) {
809
- this._body.push(para);
810
- return this;
811
- }
814
+ addParagraphElement(doc, para) {
815
+ _toState(doc).body.push(para);
816
+ },
812
817
  /** Add a simple text paragraph. */
813
- addParagraph(content, properties) {
814
- this._body.push(textParagraph(content, properties));
815
- return this;
816
- }
818
+ addParagraph(doc, content, properties) {
819
+ _toState(doc).body.push(textParagraph(content, properties));
820
+ },
817
821
  /** Add a heading. */
818
- addHeading(content, level = 1) {
819
- this._body.push(heading(content, level));
820
- return this;
821
- }
822
+ addHeading(doc, content, level = 1) {
823
+ _toState(doc).body.push(heading(content, level));
824
+ },
822
825
  /** Add a page break. */
823
- addPageBreak() {
824
- this._body.push(paragraph([pageBreak()]));
825
- return this;
826
- }
826
+ addPageBreak(doc) {
827
+ _toState(doc).body.push(paragraph([pageBreak()]));
828
+ },
827
829
  /** Add a table from a 2D array. */
828
- addTable(data, options) {
829
- this._body.push(simpleTable(data, options));
830
- return this;
831
- }
830
+ addTable(doc, data, options) {
831
+ _toState(doc).body.push(simpleTable(data, options));
832
+ },
832
833
  /** Add a table element. */
833
- addTableElement(tbl) {
834
- this._body.push(tbl);
835
- return this;
836
- }
834
+ addTableElement(doc, tbl) {
835
+ _toState(doc).body.push(tbl);
836
+ },
837
837
  /** Add an inline image. Returns the image relationship ID and drawing ID. */
838
- addImage(data, mediaType, width, height, options) {
839
- const fileName = `image${this._nextImageId}.${mediaType}`;
840
- const rId = `__img_${this._nextImageId}`;
841
- const drawingId = this._nextDrawingId++;
842
- this._images.push({ data, mediaType, fileName, rId });
843
- this._body.push(paragraph([
838
+ addImage(doc, data, mediaType, width, height, options) {
839
+ const s = _toState(doc);
840
+ const fileName = `image${s.nextImageId}.${mediaType}`;
841
+ const rId = `__img_${s.nextImageId}`;
842
+ const drawingId = s.nextDrawingId++;
843
+ s.images.push({ data, mediaType, fileName, rId });
844
+ s.body.push(paragraph([
844
845
  {
845
846
  content: [
846
847
  {
@@ -849,26 +850,27 @@ class DocumentBuilder {
849
850
  width,
850
851
  height,
851
852
  altText: options?.altText,
852
- name: options?.name ?? `Picture ${this._nextImageId}`,
853
+ name: options?.name ?? `Picture ${s.nextImageId}`,
853
854
  drawingId
854
855
  }
855
856
  ]
856
857
  }
857
858
  ]));
858
- this._nextImageId++;
859
+ s.nextImageId++;
859
860
  return { rId, drawingId };
860
- }
861
+ },
861
862
  /** Add a floating image. Returns the image relationship ID. */
862
- addFloatingImage(data, mediaType, width, height, options) {
863
- const fileName = `image${this._nextImageId}.${mediaType}`;
864
- const rId = `__img_${this._nextImageId}`;
865
- this._images.push({ data, mediaType, fileName, rId });
866
- this._body.push(floatingImage({
863
+ addFloatingImage(doc, data, mediaType, width, height, options) {
864
+ const s = _toState(doc);
865
+ const fileName = `image${s.nextImageId}.${mediaType}`;
866
+ const rId = `__img_${s.nextImageId}`;
867
+ s.images.push({ data, mediaType, fileName, rId });
868
+ s.body.push(floatingImage({
867
869
  rId,
868
870
  width,
869
871
  height,
870
872
  altText: options?.altText,
871
- name: options?.name ?? `Picture ${this._nextImageId}`,
873
+ name: options?.name ?? `Picture ${s.nextImageId}`,
872
874
  horizontalPosition: options?.horizontalPosition,
873
875
  verticalPosition: options?.verticalPosition,
874
876
  wrap: options?.wrap,
@@ -884,38 +886,39 @@ class DocumentBuilder {
884
886
  flipHorizontal: options?.flipHorizontal,
885
887
  flipVertical: options?.flipVertical
886
888
  }));
887
- this._nextImageId++;
889
+ s.nextImageId++;
888
890
  return rId;
889
- }
891
+ },
890
892
  /** Add a custom font definition. */
891
- addFont(font) {
892
- this._fonts.push(font);
893
- return this;
894
- }
893
+ addFont(doc, font) {
894
+ _toState(doc).fonts.push(font);
895
+ },
895
896
  /** Set a text watermark on the document. */
896
- setWatermark(watermark) {
897
- this._watermark = watermark;
898
- return this;
899
- }
897
+ setWatermark(doc, watermark) {
898
+ _toState(doc).watermark = watermark;
899
+ },
900
900
  /** Add a footnote. Returns the footnote ID. */
901
- addFootnote(content) {
902
- const id = this._nextFootnoteId++;
901
+ addFootnote(doc, content) {
902
+ const s = _toState(doc);
903
+ const id = s.nextFootnoteId++;
903
904
  const paras = typeof content === "string" ? [textParagraph(content)] : content;
904
- this._footnotes.push({ id, content: paras });
905
+ s.footnotes.push({ id, content: paras });
905
906
  return id;
906
- }
907
+ },
907
908
  /** Add an endnote. Returns the endnote ID. */
908
- addEndnote(content) {
909
- const id = this._nextEndnoteId++;
909
+ addEndnote(doc, content) {
910
+ const s = _toState(doc);
911
+ const id = s.nextEndnoteId++;
910
912
  const paras = typeof content === "string" ? [textParagraph(content)] : content;
911
- this._endnotes.push({ id, content: paras });
913
+ s.endnotes.push({ id, content: paras });
912
914
  return id;
913
- }
915
+ },
914
916
  /** Add a comment. Returns the comment ID. */
915
- addComment(author, content, options) {
916
- const id = this._nextCommentId++;
917
+ addComment(doc, author, content, options) {
918
+ const s = _toState(doc);
919
+ const id = s.nextCommentId++;
917
920
  const paras = typeof content === "string" ? [textParagraph(content)] : content;
918
- this._comments.push({
921
+ s.comments.push({
919
922
  id,
920
923
  author,
921
924
  date: options?.date,
@@ -923,26 +926,24 @@ class DocumentBuilder {
923
926
  content: paras
924
927
  });
925
928
  return id;
926
- }
929
+ },
927
930
  /** Add a Table of Contents. */
928
- addTableOfContents(options) {
929
- this._body.push({
931
+ addTableOfContents(doc, options) {
932
+ _toState(doc).body.push({
930
933
  type: "tableOfContents",
931
934
  headingStyleRange: options?.headingStyleRange ?? "1-3",
932
935
  hyperlink: options?.hyperlink ?? true,
933
936
  ...options
934
937
  });
935
- return this;
936
- }
938
+ },
937
939
  /** Add a math equation block. */
938
- addMath(content) {
939
- this._body.push(mathBlock(content));
940
- return this;
941
- }
940
+ addMath(doc, content) {
941
+ _toState(doc).body.push(mathBlock(content));
942
+ },
942
943
  /** Add a text box. */
943
- addTextBox(content, options) {
944
+ addTextBox(doc, content, options) {
944
945
  const paras = typeof content === "string" ? [textParagraph(content)] : content;
945
- this._body.push({
946
+ _toState(doc).body.push({
946
947
  type: "textBox",
947
948
  content: paras,
948
949
  width: options?.width,
@@ -950,15 +951,15 @@ class DocumentBuilder {
950
951
  stroke: options?.stroke,
951
952
  fill: options?.fill
952
953
  });
953
- return this;
954
- }
954
+ },
955
955
  /** Add a bullet list. */
956
- addBulletList(items, level = 0) {
956
+ addBulletList(doc, items, level = 0) {
957
+ const s = _toState(doc);
957
958
  // Create abstract numbering for bullets if not exists
958
- let bulletAbsId = this._abstractNumberings.find(a => a.levels[0]?.format === "bullet")?.abstractNumId;
959
+ let bulletAbsId = s.abstractNumberings.find(a => a.levels[0]?.format === "bullet")?.abstractNumId;
959
960
  if (bulletAbsId === undefined) {
960
- bulletAbsId = this._nextAbstractNumId++;
961
- this._abstractNumberings.push({
961
+ bulletAbsId = s.nextAbstractNumId++;
962
+ s.abstractNumberings.push({
962
963
  abstractNumId: bulletAbsId,
963
964
  multiLevelType: "hybridMultilevel",
964
965
  levels: [
@@ -991,23 +992,23 @@ class DocumentBuilder {
991
992
  }
992
993
  ]
993
994
  });
994
- this._numberingInstances.push({
995
- numId: this._nextNumId++,
995
+ s.numberingInstances.push({
996
+ numId: s.nextNumId++,
996
997
  abstractNumId: bulletAbsId
997
998
  });
998
999
  }
999
- const numId = this._numberingInstances.find(n => n.abstractNumId === bulletAbsId).numId;
1000
+ const numId = s.numberingInstances.find(n => n.abstractNumId === bulletAbsId).numId;
1000
1001
  for (const item of items) {
1001
- this._body.push(textParagraph(item, { numbering: { numId, level } }));
1002
+ s.body.push(textParagraph(item, { numbering: { numId, level } }));
1002
1003
  }
1003
- return this;
1004
- }
1004
+ },
1005
1005
  /** Add a numbered list. */
1006
- addNumberedList(items, level = 0) {
1007
- let numAbsId = this._abstractNumberings.find(a => a.levels[0]?.format === "decimal")?.abstractNumId;
1006
+ addNumberedList(doc, items, level = 0) {
1007
+ const s = _toState(doc);
1008
+ let numAbsId = s.abstractNumberings.find(a => a.levels[0]?.format === "decimal")?.abstractNumId;
1008
1009
  if (numAbsId === undefined) {
1009
- numAbsId = this._nextAbstractNumId++;
1010
- this._abstractNumberings.push({
1010
+ numAbsId = s.nextAbstractNumId++;
1011
+ s.abstractNumberings.push({
1011
1012
  abstractNumId: numAbsId,
1012
1013
  multiLevelType: "hybridMultilevel",
1013
1014
  levels: [
@@ -1037,35 +1038,32 @@ class DocumentBuilder {
1037
1038
  }
1038
1039
  ]
1039
1040
  });
1040
- this._numberingInstances.push({
1041
- numId: this._nextNumId++,
1041
+ s.numberingInstances.push({
1042
+ numId: s.nextNumId++,
1042
1043
  abstractNumId: numAbsId
1043
1044
  });
1044
1045
  }
1045
- const numId = this._numberingInstances.find(n => n.abstractNumId === numAbsId).numId;
1046
+ const numId = s.numberingInstances.find(n => n.abstractNumId === numAbsId).numId;
1046
1047
  for (const item of items) {
1047
- this._body.push(textParagraph(item, { numbering: { numId, level } }));
1048
+ s.body.push(textParagraph(item, { numbering: { numId, level } }));
1048
1049
  }
1049
- return this;
1050
- }
1050
+ },
1051
1051
  /** Set section properties (page size, margins, etc.). */
1052
- setSectionProperties(props) {
1053
- this._sectionProperties = props;
1054
- return this;
1055
- }
1052
+ setSectionProperties(doc, props) {
1053
+ _toState(doc).sectionProperties = props;
1054
+ },
1056
1055
  /** Set document defaults. */
1057
- setDocDefaults(defaults) {
1058
- this._docDefaults = defaults;
1059
- return this;
1060
- }
1056
+ setDocDefaults(doc, defaults) {
1057
+ _toState(doc).docDefaults = defaults;
1058
+ },
1061
1059
  /** Add a style definition. */
1062
- addStyle(style) {
1063
- this._styles.push(style);
1064
- return this;
1065
- }
1060
+ addStyle(doc, style) {
1061
+ _toState(doc).styles.push(style);
1062
+ },
1066
1063
  /** Set default styles (Normal, Heading1-6, Hyperlink, etc.). */
1067
- useDefaultStyles() {
1068
- this._docDefaults = {
1064
+ useDefaultStyles(doc) {
1065
+ const s = _toState(doc);
1066
+ s.docDefaults = {
1069
1067
  runProperties: {
1070
1068
  font: { ascii: "Calibri", hAnsi: "Calibri", eastAsia: "SimSun", cs: "Times New Roman" },
1071
1069
  size: 22,
@@ -1076,7 +1074,7 @@ class DocumentBuilder {
1076
1074
  spacing: { after: 160, line: 259, lineRule: "auto" }
1077
1075
  }
1078
1076
  };
1079
- this._styles.push({ type: "paragraph", styleId: "Normal", name: "Normal", isDefault: true, qFormat: true }, {
1077
+ s.styles.push({ type: "paragraph", styleId: "Normal", name: "Normal", isDefault: true, qFormat: true }, {
1080
1078
  type: "paragraph",
1081
1079
  styleId: "Heading1",
1082
1080
  name: "heading 1",
@@ -1124,193 +1122,91 @@ class DocumentBuilder {
1124
1122
  uiPriority: 39,
1125
1123
  tableProperties: { borders: gridBorders(4, "auto") }
1126
1124
  });
1127
- return this;
1128
- }
1125
+ },
1129
1126
  /** Set a header for the given type. */
1130
- setHeader(type, content) {
1131
- this._headers.set(type, { content });
1132
- return this;
1133
- }
1127
+ setHeader(doc, type, content) {
1128
+ _toState(doc).headers.set(type, { content });
1129
+ },
1134
1130
  /** Set a footer for the given type. */
1135
- setFooter(type, content) {
1136
- this._footers.set(type, { content });
1137
- return this;
1138
- }
1131
+ setFooter(doc, type, content) {
1132
+ _toState(doc).footers.set(type, { content });
1133
+ },
1139
1134
  /** Set document settings. */
1140
- setSettings(settings) {
1141
- this._settings = settings;
1142
- return this;
1143
- }
1135
+ setSettings(doc, settings) {
1136
+ _toState(doc).settings = settings;
1137
+ },
1144
1138
  /** Set core properties (metadata). */
1145
- setCoreProperties(props) {
1146
- this._coreProperties = props;
1147
- return this;
1148
- }
1139
+ setCoreProperties(doc, props) {
1140
+ _toState(doc).coreProperties = props;
1141
+ },
1149
1142
  /** Set application properties. */
1150
- setAppProperties(props) {
1151
- this._appProperties = props;
1152
- return this;
1153
- }
1143
+ setAppProperties(doc, props) {
1144
+ _toState(doc).appProperties = props;
1145
+ },
1154
1146
  /** Set document background. */
1155
- setBackground(background) {
1156
- this._background = background;
1157
- return this;
1158
- }
1147
+ setBackground(doc, background) {
1148
+ _toState(doc).background = background;
1149
+ },
1159
1150
  /** Add a custom document property. */
1160
- addCustomProperty(name, value) {
1161
- this._customProperties.push({ name, value });
1162
- return this;
1163
- }
1151
+ addCustomProperty(doc, name, value) {
1152
+ _toState(doc).customProperties.push({ name, value });
1153
+ },
1164
1154
  /** Add a section break with properties. */
1165
- addSectionBreak(props) {
1155
+ addSectionBreak(doc, props) {
1156
+ const s = _toState(doc);
1166
1157
  // Insert as the last paragraph's section properties
1167
- if (this._body.length > 0) {
1168
- const last = this._body[this._body.length - 1];
1158
+ if (s.body.length > 0) {
1159
+ const last = s.body[s.body.length - 1];
1169
1160
  if (last.type === "paragraph") {
1170
1161
  const existingProps = last.properties ?? {};
1171
- this._body[this._body.length - 1] = {
1162
+ s.body[s.body.length - 1] = {
1172
1163
  ...last,
1173
1164
  properties: { ...existingProps, sectionProperties: props }
1174
1165
  };
1175
- return this;
1166
+ return;
1176
1167
  }
1177
1168
  }
1178
1169
  // If no previous paragraph, add an empty one with section properties
1179
- this._body.push(paragraph([], { sectionProperties: props }));
1180
- return this;
1181
- }
1170
+ s.body.push(paragraph([], { sectionProperties: props }));
1171
+ },
1182
1172
  /** Get next available bookmark ID. */
1183
- nextBookmarkId() {
1184
- return this._nextBookmarkId++;
1185
- }
1186
- /** Build the DocxDocument model. */
1187
- build() {
1173
+ nextBookmarkId(doc) {
1174
+ return _toState(doc).nextBookmarkId++;
1175
+ },
1176
+ /** Build the DocxDocument model from the handle. */
1177
+ build(doc) {
1178
+ const s = _toState(doc);
1188
1179
  return {
1189
- body: this._body,
1190
- sectionProperties: this._sectionProperties ?? {
1180
+ body: s.body,
1181
+ sectionProperties: s.sectionProperties ?? {
1191
1182
  pageSize: { width: 12240, height: 15840 },
1192
1183
  margins: { top: 1440, right: 1440, bottom: 1440, left: 1440 }
1193
1184
  },
1194
- styles: this._styles.length > 0 ? this._styles : undefined,
1195
- docDefaults: this._docDefaults,
1196
- abstractNumberings: this._abstractNumberings.length > 0 ? this._abstractNumberings : undefined,
1197
- numberingInstances: this._numberingInstances.length > 0 ? this._numberingInstances : undefined,
1198
- headers: this._headers.size > 0 ? this._headers : undefined,
1199
- footers: this._footers.size > 0 ? this._footers : undefined,
1200
- footnotes: this._footnotes.length > 0 ? this._footnotes : undefined,
1201
- endnotes: this._endnotes.length > 0 ? this._endnotes : undefined,
1202
- images: this._images.length > 0 ? this._images : undefined,
1203
- fonts: this._fonts.length > 0 ? this._fonts : undefined,
1204
- settings: this._settings,
1205
- coreProperties: this._coreProperties,
1206
- appProperties: this._appProperties,
1207
- comments: this._comments.length > 0 ? this._comments : undefined,
1208
- background: this._background,
1209
- customProperties: this._customProperties.length > 0 ? this._customProperties : undefined,
1210
- watermark: this._watermark
1185
+ styles: s.styles.length > 0 ? s.styles : undefined,
1186
+ docDefaults: s.docDefaults,
1187
+ abstractNumberings: s.abstractNumberings.length > 0 ? s.abstractNumberings : undefined,
1188
+ numberingInstances: s.numberingInstances.length > 0 ? s.numberingInstances : undefined,
1189
+ headers: s.headers.size > 0 ? s.headers : undefined,
1190
+ footers: s.footers.size > 0 ? s.footers : undefined,
1191
+ footnotes: s.footnotes.length > 0 ? s.footnotes : undefined,
1192
+ endnotes: s.endnotes.length > 0 ? s.endnotes : undefined,
1193
+ images: s.images.length > 0 ? s.images : undefined,
1194
+ fonts: s.fonts.length > 0 ? s.fonts : undefined,
1195
+ settings: s.settings,
1196
+ coreProperties: s.coreProperties,
1197
+ appProperties: s.appProperties,
1198
+ comments: s.comments.length > 0 ? s.comments : undefined,
1199
+ background: s.background,
1200
+ customProperties: s.customProperties.length > 0 ? s.customProperties : undefined,
1201
+ watermark: s.watermark
1211
1202
  };
1212
1203
  }
1213
- /** Build and package to DOCX bytes. */
1214
- async toBuffer(compressionLevel) {
1215
- return (0, docx_packager_1.packageDocx)(this.build(), compressionLevel);
1216
- }
1217
- /** Build and package to base64 string. */
1218
- async toBase64(compressionLevel) {
1219
- const bytes = await this.toBuffer(compressionLevel);
1220
- return (0, internal_utils_1.bytesToBase64)(bytes);
1221
- }
1222
- }
1223
- exports.DocumentBuilder = DocumentBuilder;
1204
+ };
1224
1205
  // =============================================================================
1225
- // Theme Color Resolution
1206
+ // Theme Color Resolution (re-export from color-utils for backward compat)
1226
1207
  // =============================================================================
1227
- /**
1228
- * Map OOXML theme color attribute names to theme color scheme keys.
1229
- * Word uses different names in run/paragraph properties vs the theme XML.
1230
- */
1231
- const THEME_COLOR_MAP = {
1232
- dark1: "dk1",
1233
- light1: "lt1",
1234
- dark2: "dk2",
1235
- light2: "lt2",
1236
- accent1: "accent1",
1237
- accent2: "accent2",
1238
- accent3: "accent3",
1239
- accent4: "accent4",
1240
- accent5: "accent5",
1241
- accent6: "accent6",
1242
- hyperlink: "hlink",
1243
- followedHyperlink: "folHlink",
1244
- // Direct names also work
1245
- dk1: "dk1",
1246
- lt1: "lt1",
1247
- dk2: "dk2",
1248
- lt2: "lt2",
1249
- hlink: "hlink",
1250
- folHlink: "folHlink"
1251
- };
1252
- /**
1253
- * Resolve a ColorSpec to an actual hex RGB color using the document theme.
1254
- *
1255
- * Applies theme color lookup + tint/shade transformations per OOXML spec.
1256
- *
1257
- * @param color - The color value (HexColor string or ColorSpec).
1258
- * @param theme - The document theme (from `doc.theme`).
1259
- * @returns Resolved hex color string (6 chars, no #), or undefined if unresolvable.
1260
- */
1261
- function resolveThemeColor(color, theme) {
1262
- if (color === undefined) {
1263
- return undefined;
1264
- }
1265
- if (typeof color === "string") {
1266
- return color;
1267
- }
1268
- // ColorSpec with val — use directly
1269
- if (color.val && color.val !== "auto") {
1270
- return color.val;
1271
- }
1272
- // Resolve via theme
1273
- if (!color.themeColor || !theme) {
1274
- return color.val;
1275
- }
1276
- const key = THEME_COLOR_MAP[color.themeColor] ?? color.themeColor;
1277
- const base = theme.colorScheme.colors[key];
1278
- if (!base) {
1279
- return color.val;
1280
- }
1281
- // Apply tint or shade
1282
- if (color.themeTint) {
1283
- return applyTint(base, parseInt(color.themeTint, 16) / 255);
1284
- }
1285
- if (color.themeShade) {
1286
- return applyShade(base, parseInt(color.themeShade, 16) / 255);
1287
- }
1288
- return base;
1289
- }
1290
- /** Apply tint to a hex color. tint=1 → white, tint=0 → original. */
1291
- function applyTint(hex, tint) {
1292
- const r = parseInt(hex.slice(0, 2), 16);
1293
- const g = parseInt(hex.slice(2, 4), 16);
1294
- const b = parseInt(hex.slice(4, 6), 16);
1295
- const nr = Math.round(r + (255 - r) * tint);
1296
- const ng = Math.round(g + (255 - g) * tint);
1297
- const nb = Math.round(b + (255 - b) * tint);
1298
- return toHex2(nr) + toHex2(ng) + toHex2(nb);
1299
- }
1300
- /** Apply shade to a hex color. shade=1 → original, shade=0 → black. */
1301
- function applyShade(hex, shade) {
1302
- const r = parseInt(hex.slice(0, 2), 16);
1303
- const g = parseInt(hex.slice(2, 4), 16);
1304
- const b = parseInt(hex.slice(4, 6), 16);
1305
- const nr = Math.round(r * shade);
1306
- const ng = Math.round(g * shade);
1307
- const nb = Math.round(b * shade);
1308
- return toHex2(nr) + toHex2(ng) + toHex2(nb);
1309
- }
1310
- function toHex2(n) {
1311
- const h = Math.max(0, Math.min(255, n)).toString(16);
1312
- return h.length < 2 ? "0" + h : h;
1313
- }
1208
+ var color_utils_1 = require("./color-utils");
1209
+ Object.defineProperty(exports, "resolveThemeColor", { enumerable: true, get: function () { return color_utils_1.resolveThemeColor; } });
1314
1210
  /** Extract concatenated plain text from a paragraph's runs. */
1315
1211
  function paragraphText(para) {
1316
1212
  let text = "";
@@ -1747,163 +1643,3 @@ function countOccurrences(str, search) {
1747
1643
  }
1748
1644
  return str.split(search).length - 1;
1749
1645
  }
1750
- /**
1751
- * Read an existing DOCX file, replace placeholders with content, and produce a new DOCX.
1752
- *
1753
- * Placeholders are strings like `{{name}}` embedded in the document text.
1754
- * They may span across multiple runs — the patcher handles cross-run matching.
1755
- *
1756
- * Supported patch content types:
1757
- * - `text` — simple text replacement (preserves formatting of the first run)
1758
- * - `paragraph` — replaces the entire paragraph containing the placeholder
1759
- * - `table` — replaces the entire paragraph with a table
1760
- * - `image` — replaces the placeholder with an inline image
1761
- *
1762
- * @param buffer - The source DOCX file as a Uint8Array.
1763
- * @param patches - Array of patch operations to apply.
1764
- * @param options - Optional compression settings.
1765
- * @returns New DOCX file as a Uint8Array.
1766
- */
1767
- async function patchDocument(buffer, patches, options) {
1768
- const doc = await (0, docx_reader_1.readDocx)(buffer);
1769
- // Build lookup map for quick placeholder matching
1770
- const patchMap = new Map();
1771
- for (const patch of patches) {
1772
- patchMap.set(patch.placeholder, patch);
1773
- }
1774
- // Process body content
1775
- const newBody = [];
1776
- for (const block of doc.body) {
1777
- if (block.type === "paragraph") {
1778
- const result = patchParagraph(block, patchMap);
1779
- if (result) {
1780
- if (Array.isArray(result)) {
1781
- newBody.push(...result);
1782
- }
1783
- else {
1784
- newBody.push(result);
1785
- }
1786
- }
1787
- }
1788
- else if (block.type === "table") {
1789
- patchTable(block, patchMap);
1790
- newBody.push(block);
1791
- }
1792
- else {
1793
- newBody.push(block);
1794
- }
1795
- }
1796
- // Patch headers
1797
- if (doc.headers) {
1798
- for (const [, headerDef] of doc.headers) {
1799
- patchHeaderFooterContent(headerDef.content, patchMap);
1800
- }
1801
- }
1802
- // Patch footers
1803
- if (doc.footers) {
1804
- for (const [, footerDef] of doc.footers) {
1805
- patchHeaderFooterContent(footerDef.content, patchMap);
1806
- }
1807
- }
1808
- // Add any new images from patches
1809
- const images = doc.images ? [...doc.images] : [];
1810
- for (const patch of patches) {
1811
- if (patch.content.type === "image") {
1812
- const imgContent = patch.content;
1813
- const existing = images.find(i => i.fileName === imgContent.image.fileName);
1814
- if (!existing) {
1815
- images.push(imgContent.image);
1816
- }
1817
- }
1818
- }
1819
- const patched = {
1820
- ...doc,
1821
- body: newBody,
1822
- images: images.length > 0 ? images : undefined
1823
- };
1824
- return (0, docx_packager_1.packageDocx)(patched, options?.compressionLevel);
1825
- }
1826
- /** Patch a paragraph — returns replacement content or null to remove. */
1827
- function patchParagraph(para, patchMap) {
1828
- const text = paragraphText(para);
1829
- for (const [placeholder, patch] of patchMap) {
1830
- if (!text.includes(placeholder)) {
1831
- continue;
1832
- }
1833
- switch (patch.content.type) {
1834
- case "text": {
1835
- replaceInParagraph(para, placeholder, patch.content.text);
1836
- return para;
1837
- }
1838
- case "paragraph": {
1839
- return patch.content.children;
1840
- }
1841
- case "table": {
1842
- return patch.content.table;
1843
- }
1844
- case "image": {
1845
- const img = patch.content.image;
1846
- const rId = img.rId ?? `rId_img_${img.fileName}`;
1847
- const imgContent = {
1848
- type: "image",
1849
- rId,
1850
- width: patch.content.width,
1851
- height: patch.content.height,
1852
- altText: img.fileName,
1853
- name: img.fileName
1854
- };
1855
- const newPara = {
1856
- type: "paragraph",
1857
- properties: para.properties,
1858
- children: [{ content: [imgContent] }]
1859
- };
1860
- return newPara;
1861
- }
1862
- }
1863
- }
1864
- return para;
1865
- }
1866
- /** Patch text inside table cells recursively. */
1867
- function patchTable(table, patchMap) {
1868
- for (const row of table.rows) {
1869
- for (const cell of row.cells) {
1870
- const newContent = [];
1871
- for (const block of cell.content) {
1872
- if (block.type === "paragraph") {
1873
- const result = patchParagraph(block, patchMap);
1874
- if (result) {
1875
- if (Array.isArray(result)) {
1876
- newContent.push(...result);
1877
- }
1878
- else {
1879
- newContent.push(result);
1880
- }
1881
- }
1882
- }
1883
- else if (block.type === "table") {
1884
- patchTable(block, patchMap);
1885
- newContent.push(block);
1886
- }
1887
- else {
1888
- newContent.push(block);
1889
- }
1890
- }
1891
- cell.content = newContent;
1892
- }
1893
- }
1894
- }
1895
- /** Patch text in header/footer content. */
1896
- function patchHeaderFooterContent(content, patchMap) {
1897
- for (const child of content.children) {
1898
- if (child.type === "paragraph") {
1899
- for (const [placeholder, patch] of patchMap) {
1900
- if (patch.content.type === "text") {
1901
- const text = paragraphText(child);
1902
- if (text.includes(placeholder)) {
1903
- replaceInParagraph(child, placeholder, patch.content.text);
1904
- }
1905
- }
1906
- }
1907
- }
1908
- }
1909
- }