@js-ak/excel-toolbox 1.8.3 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/build/cjs/lib/template/template-fs.js +2 -1
  2. package/build/cjs/lib/template/template-memory.js +2 -1
  3. package/build/cjs/lib/template/utils/column-letter-to-index.js +15 -0
  4. package/build/cjs/lib/template/utils/index.js +1 -1
  5. package/build/cjs/lib/template/utils/prepare-row-to-cells.js +2 -2
  6. package/build/cjs/lib/template/utils/validate-worksheet-xml.js +19 -9
  7. package/build/cjs/lib/utils/index.js +2 -0
  8. package/build/cjs/lib/utils/trim-and-join-multiline.js +32 -0
  9. package/build/cjs/lib/workbook-builder/default/border.js +18 -0
  10. package/build/cjs/lib/workbook-builder/default/cell-xf.js +15 -0
  11. package/build/cjs/lib/workbook-builder/default/fill.js +18 -0
  12. package/build/cjs/lib/workbook-builder/default/font.js +19 -0
  13. package/build/cjs/lib/workbook-builder/default/index.js +21 -0
  14. package/build/cjs/lib/workbook-builder/default/sheet-name.js +10 -0
  15. package/build/cjs/lib/workbook-builder/index.js +18 -0
  16. package/build/cjs/lib/workbook-builder/merge-cells/add.js +72 -0
  17. package/build/cjs/lib/workbook-builder/merge-cells/helpers/index.js +18 -0
  18. package/build/cjs/lib/workbook-builder/merge-cells/helpers/ranges-equal.js +17 -0
  19. package/build/cjs/lib/workbook-builder/merge-cells/helpers/ranges-intersect.js +17 -0
  20. package/build/cjs/lib/workbook-builder/merge-cells/index.js +18 -0
  21. package/build/cjs/lib/workbook-builder/merge-cells/remove.js +60 -0
  22. package/build/cjs/lib/workbook-builder/shared-string-ref/add.js +24 -0
  23. package/build/cjs/lib/workbook-builder/shared-string-ref/index.js +19 -0
  24. package/build/cjs/lib/workbook-builder/shared-string-ref/remove-all-from-sheet.js +66 -0
  25. package/build/cjs/lib/workbook-builder/shared-string-ref/remove.js +66 -0
  26. package/build/cjs/lib/workbook-builder/style-ref/add-or-get.js +94 -0
  27. package/build/cjs/lib/workbook-builder/style-ref/helpers/add-num-fmt.js +25 -0
  28. package/build/cjs/lib/workbook-builder/style-ref/helpers/border-to-xml.js +49 -0
  29. package/build/cjs/lib/workbook-builder/style-ref/helpers/fill-to-xml.js +51 -0
  30. package/build/cjs/lib/workbook-builder/style-ref/helpers/font-to-xml.js +112 -0
  31. package/build/cjs/lib/workbook-builder/style-ref/helpers/index.js +21 -0
  32. package/build/cjs/lib/workbook-builder/style-ref/helpers/reindex-style-map-after-removal.js +30 -0
  33. package/build/cjs/lib/workbook-builder/style-ref/index.js +19 -0
  34. package/build/cjs/lib/workbook-builder/style-ref/remove-all-from-sheet.js +26 -0
  35. package/build/cjs/lib/workbook-builder/style-ref/remove.js +52 -0
  36. package/build/cjs/lib/workbook-builder/types/app-xml-options.js +2 -0
  37. package/build/cjs/lib/workbook-builder/types/border-style.js +2 -0
  38. package/build/cjs/lib/workbook-builder/types/cell-data.js +2 -0
  39. package/build/cjs/lib/workbook-builder/types/cell-style.js +2 -0
  40. package/build/cjs/lib/workbook-builder/types/cell-type.js +2 -0
  41. package/build/cjs/lib/workbook-builder/types/cell-value.js +2 -0
  42. package/build/cjs/lib/workbook-builder/types/cell-xf.js +2 -0
  43. package/build/cjs/lib/workbook-builder/types/index.js +27 -0
  44. package/build/cjs/lib/workbook-builder/types/merge-cell.js +2 -0
  45. package/build/cjs/lib/workbook-builder/types/row-data.js +2 -0
  46. package/build/cjs/lib/workbook-builder/types/sheet-data.js +2 -0
  47. package/build/cjs/lib/workbook-builder/types/xml-node.js +2 -0
  48. package/build/cjs/lib/workbook-builder/utils/build-app-xml.js +51 -0
  49. package/build/cjs/lib/workbook-builder/utils/build-cell-children.js +59 -0
  50. package/build/cjs/lib/workbook-builder/utils/build-content-types-xml.js +42 -0
  51. package/build/cjs/lib/workbook-builder/utils/build-core-xml.js +27 -0
  52. package/build/cjs/lib/workbook-builder/utils/build-rels-xml.js +19 -0
  53. package/build/cjs/lib/workbook-builder/utils/build-shared-strings-xml.js +39 -0
  54. package/build/cjs/lib/workbook-builder/utils/build-styles-xml.js +178 -0
  55. package/build/cjs/lib/workbook-builder/utils/build-theme-xml.js +609 -0
  56. package/build/cjs/lib/workbook-builder/utils/build-workbook-rels-xml.js +58 -0
  57. package/build/cjs/lib/workbook-builder/utils/build-workbook-xml.js +26 -0
  58. package/build/cjs/lib/workbook-builder/utils/build-worksheet-xml.js +66 -0
  59. package/build/cjs/lib/workbook-builder/utils/build-xml.js +72 -0
  60. package/build/cjs/lib/workbook-builder/utils/constants.js +55 -0
  61. package/build/cjs/lib/workbook-builder/utils/date-to-excel-serial.js +16 -0
  62. package/build/cjs/lib/workbook-builder/utils/index.js +34 -0
  63. package/build/cjs/lib/workbook-builder/utils/initialize-files.js +40 -0
  64. package/build/cjs/lib/workbook-builder/utils/sheet.js +144 -0
  65. package/build/cjs/lib/workbook-builder/utils/write-shared-strings-xml.js +49 -0
  66. package/build/cjs/lib/workbook-builder/utils/write-styles-xml.js +196 -0
  67. package/build/cjs/lib/workbook-builder/utils/write-worksheet-xml.js +209 -0
  68. package/build/cjs/lib/workbook-builder/utils/write-xml.js +37 -0
  69. package/build/cjs/lib/workbook-builder/workbook-builder.js +414 -0
  70. package/build/esm/lib/template/template-fs.js +2 -1
  71. package/build/esm/lib/template/template-memory.js +2 -1
  72. package/build/esm/lib/template/utils/column-letter-to-index.js +12 -0
  73. package/build/esm/lib/template/utils/index.js +1 -1
  74. package/build/esm/lib/template/utils/prepare-row-to-cells.js +1 -1
  75. package/build/esm/lib/template/utils/validate-worksheet-xml.js +19 -9
  76. package/build/esm/lib/utils/index.js +2 -0
  77. package/build/esm/lib/utils/trim-and-join-multiline.js +29 -0
  78. package/build/esm/lib/workbook-builder/default/border.js +14 -0
  79. package/build/esm/lib/workbook-builder/default/cell-xf.js +11 -0
  80. package/build/esm/lib/workbook-builder/default/fill.js +14 -0
  81. package/build/esm/lib/workbook-builder/default/font.js +15 -0
  82. package/build/esm/lib/workbook-builder/default/index.js +5 -0
  83. package/build/esm/lib/workbook-builder/default/sheet-name.js +6 -0
  84. package/build/esm/lib/workbook-builder/index.js +2 -0
  85. package/build/esm/lib/workbook-builder/merge-cells/add.js +36 -0
  86. package/build/esm/lib/workbook-builder/merge-cells/helpers/index.js +2 -0
  87. package/build/esm/lib/workbook-builder/merge-cells/helpers/ranges-equal.js +14 -0
  88. package/build/esm/lib/workbook-builder/merge-cells/helpers/ranges-intersect.js +14 -0
  89. package/build/esm/lib/workbook-builder/merge-cells/index.js +2 -0
  90. package/build/esm/lib/workbook-builder/merge-cells/remove.js +24 -0
  91. package/build/esm/lib/workbook-builder/shared-string-ref/add.js +21 -0
  92. package/build/esm/lib/workbook-builder/shared-string-ref/index.js +3 -0
  93. package/build/esm/lib/workbook-builder/shared-string-ref/remove-all-from-sheet.js +63 -0
  94. package/build/esm/lib/workbook-builder/shared-string-ref/remove.js +63 -0
  95. package/build/esm/lib/workbook-builder/style-ref/add-or-get.js +58 -0
  96. package/build/esm/lib/workbook-builder/style-ref/helpers/add-num-fmt.js +21 -0
  97. package/build/esm/lib/workbook-builder/style-ref/helpers/border-to-xml.js +45 -0
  98. package/build/esm/lib/workbook-builder/style-ref/helpers/fill-to-xml.js +47 -0
  99. package/build/esm/lib/workbook-builder/style-ref/helpers/font-to-xml.js +75 -0
  100. package/build/esm/lib/workbook-builder/style-ref/helpers/index.js +5 -0
  101. package/build/esm/lib/workbook-builder/style-ref/helpers/reindex-style-map-after-removal.js +26 -0
  102. package/build/esm/lib/workbook-builder/style-ref/index.js +3 -0
  103. package/build/esm/lib/workbook-builder/style-ref/remove-all-from-sheet.js +23 -0
  104. package/build/esm/lib/workbook-builder/style-ref/remove.js +49 -0
  105. package/build/esm/lib/workbook-builder/types/app-xml-options.js +1 -0
  106. package/build/esm/lib/workbook-builder/types/border-style.js +1 -0
  107. package/build/esm/lib/workbook-builder/types/cell-data.js +1 -0
  108. package/build/esm/lib/workbook-builder/types/cell-style.js +1 -0
  109. package/build/esm/lib/workbook-builder/types/cell-type.js +1 -0
  110. package/build/esm/lib/workbook-builder/types/cell-value.js +1 -0
  111. package/build/esm/lib/workbook-builder/types/cell-xf.js +1 -0
  112. package/build/esm/lib/workbook-builder/types/index.js +11 -0
  113. package/build/esm/lib/workbook-builder/types/merge-cell.js +1 -0
  114. package/build/esm/lib/workbook-builder/types/row-data.js +1 -0
  115. package/build/esm/lib/workbook-builder/types/sheet-data.js +1 -0
  116. package/build/esm/lib/workbook-builder/types/xml-node.js +1 -0
  117. package/build/esm/lib/workbook-builder/utils/build-app-xml.js +48 -0
  118. package/build/esm/lib/workbook-builder/utils/build-cell-children.js +56 -0
  119. package/build/esm/lib/workbook-builder/utils/build-content-types-xml.js +39 -0
  120. package/build/esm/lib/workbook-builder/utils/build-core-xml.js +24 -0
  121. package/build/esm/lib/workbook-builder/utils/build-rels-xml.js +16 -0
  122. package/build/esm/lib/workbook-builder/utils/build-shared-strings-xml.js +36 -0
  123. package/build/esm/lib/workbook-builder/utils/build-styles-xml.js +142 -0
  124. package/build/esm/lib/workbook-builder/utils/build-theme-xml.js +606 -0
  125. package/build/esm/lib/workbook-builder/utils/build-workbook-rels-xml.js +55 -0
  126. package/build/esm/lib/workbook-builder/utils/build-workbook-xml.js +23 -0
  127. package/build/esm/lib/workbook-builder/utils/build-worksheet-xml.js +63 -0
  128. package/build/esm/lib/workbook-builder/utils/build-xml.js +69 -0
  129. package/build/esm/lib/workbook-builder/utils/constants.js +52 -0
  130. package/build/esm/lib/workbook-builder/utils/date-to-excel-serial.js +13 -0
  131. package/build/esm/lib/workbook-builder/utils/index.js +18 -0
  132. package/build/esm/lib/workbook-builder/utils/initialize-files.js +36 -0
  133. package/build/esm/lib/workbook-builder/utils/sheet.js +141 -0
  134. package/build/esm/lib/workbook-builder/utils/write-shared-strings-xml.js +43 -0
  135. package/build/esm/lib/workbook-builder/utils/write-styles-xml.js +157 -0
  136. package/build/esm/lib/workbook-builder/utils/write-worksheet-xml.js +203 -0
  137. package/build/esm/lib/workbook-builder/utils/write-xml.js +34 -0
  138. package/build/esm/lib/workbook-builder/workbook-builder.js +374 -0
  139. package/build/types/lib/template/utils/column-letter-to-index.d.ts +1 -0
  140. package/build/types/lib/template/utils/index.d.ts +1 -1
  141. package/build/types/lib/utils/index.d.ts +2 -0
  142. package/build/types/lib/utils/trim-and-join-multiline.d.ts +23 -0
  143. package/build/types/lib/workbook-builder/default/border.d.ts +7 -0
  144. package/build/types/lib/workbook-builder/default/cell-xf.d.ts +7 -0
  145. package/build/types/lib/workbook-builder/default/fill.d.ts +7 -0
  146. package/build/types/lib/workbook-builder/default/font.d.ts +21 -0
  147. package/build/types/lib/workbook-builder/default/index.d.ts +5 -0
  148. package/build/types/lib/workbook-builder/default/sheet-name.d.ts +6 -0
  149. package/build/types/lib/workbook-builder/index.d.ts +2 -0
  150. package/build/types/lib/workbook-builder/merge-cells/add.d.ts +15 -0
  151. package/build/types/lib/workbook-builder/merge-cells/helpers/index.d.ts +2 -0
  152. package/build/types/lib/workbook-builder/merge-cells/helpers/ranges-equal.d.ts +10 -0
  153. package/build/types/lib/workbook-builder/merge-cells/helpers/ranges-intersect.d.ts +10 -0
  154. package/build/types/lib/workbook-builder/merge-cells/index.d.ts +2 -0
  155. package/build/types/lib/workbook-builder/merge-cells/remove.d.ts +15 -0
  156. package/build/types/lib/workbook-builder/shared-string-ref/add.d.ts +13 -0
  157. package/build/types/lib/workbook-builder/shared-string-ref/index.d.ts +3 -0
  158. package/build/types/lib/workbook-builder/shared-string-ref/remove-all-from-sheet.d.ts +10 -0
  159. package/build/types/lib/workbook-builder/shared-string-ref/remove.d.ts +13 -0
  160. package/build/types/lib/workbook-builder/style-ref/add-or-get.d.ts +16 -0
  161. package/build/types/lib/workbook-builder/style-ref/helpers/add-num-fmt.d.ts +17 -0
  162. package/build/types/lib/workbook-builder/style-ref/helpers/border-to-xml.d.ts +16 -0
  163. package/build/types/lib/workbook-builder/style-ref/helpers/fill-to-xml.d.ts +17 -0
  164. package/build/types/lib/workbook-builder/style-ref/helpers/font-to-xml.d.ts +18 -0
  165. package/build/types/lib/workbook-builder/style-ref/helpers/index.d.ts +5 -0
  166. package/build/types/lib/workbook-builder/style-ref/helpers/reindex-style-map-after-removal.d.ts +15 -0
  167. package/build/types/lib/workbook-builder/style-ref/index.d.ts +3 -0
  168. package/build/types/lib/workbook-builder/style-ref/remove-all-from-sheet.d.ts +4 -0
  169. package/build/types/lib/workbook-builder/style-ref/remove.d.ts +18 -0
  170. package/build/types/lib/workbook-builder/types/app-xml-options.d.ts +9 -0
  171. package/build/types/lib/workbook-builder/types/border-style.d.ts +5 -0
  172. package/build/types/lib/workbook-builder/types/cell-data.d.ts +10 -0
  173. package/build/types/lib/workbook-builder/types/cell-style.d.ts +32 -0
  174. package/build/types/lib/workbook-builder/types/cell-type.d.ts +11 -0
  175. package/build/types/lib/workbook-builder/types/cell-value.d.ts +2 -0
  176. package/build/types/lib/workbook-builder/types/cell-xf.d.ts +13 -0
  177. package/build/types/lib/workbook-builder/types/index.d.ts +11 -0
  178. package/build/types/lib/workbook-builder/types/merge-cell.d.ts +6 -0
  179. package/build/types/lib/workbook-builder/types/row-data.d.ts +5 -0
  180. package/build/types/lib/workbook-builder/types/sheet-data.d.ts +13 -0
  181. package/build/types/lib/workbook-builder/types/xml-node.d.ts +11 -0
  182. package/build/types/lib/workbook-builder/utils/build-app-xml.d.ts +2 -0
  183. package/build/types/lib/workbook-builder/utils/build-cell-children.d.ts +9 -0
  184. package/build/types/lib/workbook-builder/utils/build-content-types-xml.d.ts +1 -0
  185. package/build/types/lib/workbook-builder/utils/build-core-xml.d.ts +1 -0
  186. package/build/types/lib/workbook-builder/utils/build-rels-xml.d.ts +1 -0
  187. package/build/types/lib/workbook-builder/utils/build-shared-strings-xml.d.ts +10 -0
  188. package/build/types/lib/workbook-builder/utils/build-styles-xml.d.ts +23 -0
  189. package/build/types/lib/workbook-builder/utils/build-theme-xml.d.ts +1 -0
  190. package/build/types/lib/workbook-builder/utils/build-workbook-rels-xml.d.ts +9 -0
  191. package/build/types/lib/workbook-builder/utils/build-workbook-xml.d.ts +3 -0
  192. package/build/types/lib/workbook-builder/utils/build-worksheet-xml.d.ts +2 -0
  193. package/build/types/lib/workbook-builder/utils/build-xml.d.ts +50 -0
  194. package/build/types/lib/workbook-builder/utils/constants.d.ts +47 -0
  195. package/build/types/lib/workbook-builder/utils/date-to-excel-serial.d.ts +9 -0
  196. package/build/types/lib/workbook-builder/utils/index.d.ts +18 -0
  197. package/build/types/lib/workbook-builder/utils/initialize-files.d.ts +13 -0
  198. package/build/types/lib/workbook-builder/utils/sheet.d.ts +21 -0
  199. package/build/types/lib/workbook-builder/utils/write-shared-strings-xml.d.ts +11 -0
  200. package/build/types/lib/workbook-builder/utils/write-styles-xml.d.ts +24 -0
  201. package/build/types/lib/workbook-builder/utils/write-worksheet-xml.d.ts +14 -0
  202. package/build/types/lib/workbook-builder/utils/write-xml.d.ts +3 -0
  203. package/build/types/lib/workbook-builder/workbook-builder.d.ts +110 -0
  204. package/package.json +1 -1
  205. /package/build/cjs/lib/{template/utils → utils}/escape-xml.js +0 -0
  206. /package/build/esm/lib/{template/utils → utils}/escape-xml.js +0 -0
  207. /package/build/types/lib/{template/utils → utils}/escape-xml.d.ts +0 -0
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.writeStylesXml = writeStylesXml;
40
+ const node_fs_1 = __importDefault(require("node:fs"));
41
+ const promises_1 = __importDefault(require("node:fs/promises"));
42
+ const node_path_1 = __importDefault(require("node:path"));
43
+ const Default = __importStar(require("../default/index.js"));
44
+ const constants_js_1 = require("./constants.js");
45
+ const write_xml_js_1 = require("./write-xml.js");
46
+ /**
47
+ * Writes the `styles.xml` part to a file at the given destination using a write stream.
48
+ * Falls back to default font/fill/border collections when none are provided.
49
+ *
50
+ * @param destination - Absolute or relative file path to write
51
+ * @param data - Style collections used to construct the stylesheet
52
+ * @param data.borders - Array of border XmlNodes
53
+ * @param data.cellXfs - Array of cell format records
54
+ * @param data.fills - Array of fill XmlNodes
55
+ * @param data.fonts - Array of font XmlNodes
56
+ * @param data.numFmts - Array of custom number formats (formatCode and id)
57
+ * @returns Promise that resolves when the write stream finishes
58
+ */
59
+ async function writeStylesXml(destination, data) {
60
+ // Ensure destination folder exists
61
+ await promises_1.default.mkdir(node_path_1.default.dirname(destination), { recursive: true });
62
+ const stream = node_fs_1.default.createWriteStream(destination, { encoding: "utf-8" });
63
+ try {
64
+ const { borders = [], cellXfs = [], fills = [], fonts = [], numFmts = [], } = data || {};
65
+ const children = [];
66
+ if (numFmts.length) {
67
+ children.push({
68
+ attrs: { count: String(numFmts.length) },
69
+ children: numFmts.map(nf => ({
70
+ attrs: {
71
+ formatCode: nf.formatCode,
72
+ numFmtId: String(nf.id),
73
+ },
74
+ tag: "numFmt",
75
+ })),
76
+ tag: "numFmts",
77
+ });
78
+ }
79
+ if (fonts.length) {
80
+ children.push({
81
+ attrs: { count: String(fonts.length) },
82
+ children: fonts,
83
+ tag: "fonts",
84
+ });
85
+ }
86
+ else {
87
+ children.push({
88
+ attrs: { count: "1" },
89
+ children: [Default.font()],
90
+ tag: "fonts",
91
+ });
92
+ }
93
+ if (fills.length) {
94
+ children.push({
95
+ attrs: { count: String(fills.length) },
96
+ children: fills,
97
+ tag: "fills",
98
+ });
99
+ }
100
+ else {
101
+ children.push({
102
+ attrs: { count: "1" },
103
+ children: [Default.fill()],
104
+ tag: "fills",
105
+ });
106
+ }
107
+ if (borders.length) {
108
+ children.push({
109
+ attrs: { count: String(borders.length) },
110
+ children: borders,
111
+ tag: "borders",
112
+ });
113
+ }
114
+ else {
115
+ children.push({
116
+ attrs: { count: "1" },
117
+ children: [Default.border()],
118
+ tag: "borders",
119
+ });
120
+ }
121
+ children.push({
122
+ attrs: { count: "1" },
123
+ children: [{
124
+ attrs: { borderId: "0", fillId: "0", fontId: "0", numFmtId: "0" },
125
+ tag: "xf",
126
+ }],
127
+ tag: "cellStyleXfs",
128
+ });
129
+ if (cellXfs.length) {
130
+ children.push({
131
+ attrs: { count: String(cellXfs.length) },
132
+ children: cellXfs.map((xf, i) => {
133
+ const isBaseXf = i === 0;
134
+ const hasAlignment = !!xf.alignment;
135
+ const xfChildren = [];
136
+ if (hasAlignment) {
137
+ xfChildren.push({
138
+ attrs: {
139
+ ...(xf.alignment?.horizontal ? { horizontal: xf.alignment.horizontal } : {}),
140
+ ...(xf.alignment?.vertical ? { vertical: xf.alignment.vertical } : {}),
141
+ ...(xf.alignment?.wrapText ? { wrapText: "1" } : {}),
142
+ ...(xf.alignment?.indent !== undefined ? { indent: String(xf.alignment.indent) } : {}),
143
+ },
144
+ tag: "alignment",
145
+ });
146
+ }
147
+ return {
148
+ attrs: {
149
+ ...(isBaseXf
150
+ ? {}
151
+ : {
152
+ applyBorder: "1",
153
+ applyFill: "1",
154
+ applyFont: "1",
155
+ applyNumberFormat: xf.numFmtId ? "1" : "0",
156
+ }),
157
+ ...(hasAlignment ? { applyAlignment: "1" } : {}),
158
+ borderId: String(xf.borderId),
159
+ fillId: String(xf.fillId),
160
+ fontId: String(xf.fontId),
161
+ numFmtId: String(xf.numFmtId ?? 0),
162
+ xfId: "0",
163
+ },
164
+ children: xfChildren,
165
+ tag: "xf",
166
+ };
167
+ }),
168
+ tag: "cellXfs",
169
+ });
170
+ }
171
+ else {
172
+ // Base style without fill
173
+ children.push({
174
+ attrs: { count: "1" },
175
+ children: [
176
+ { attrs: { borderId: "0", fillId: "0", fontId: "0", numFmtId: "0", xfId: "0" }, tag: "xf" },
177
+ ],
178
+ tag: "cellXfs",
179
+ });
180
+ }
181
+ // XML declaration
182
+ stream.write(constants_js_1.XML_DECLARATION + "\n");
183
+ await (0, write_xml_js_1.writeXml)({
184
+ attrs: { xmlns: constants_js_1.XML_NAMESPACES.SPREADSHEET_ML },
185
+ children,
186
+ tag: "styleSheet",
187
+ }, stream);
188
+ }
189
+ finally {
190
+ stream.end();
191
+ }
192
+ return new Promise((resolve, reject) => {
193
+ stream.on("error", reject);
194
+ stream.on("finish", resolve);
195
+ });
196
+ }
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.writeWorksheetXml = writeWorksheetXml;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const promises_1 = __importDefault(require("node:fs/promises"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_readline_1 = __importDefault(require("node:readline"));
11
+ const constants_js_1 = require("./constants.js");
12
+ const column_index_to_letter_js_1 = require("../../template/utils/column-index-to-letter.js");
13
+ const column_letter_to_index_js_1 = require("../../template/utils/column-letter-to-index.js");
14
+ /**
15
+ * Writes a worksheet XML file to the given destination using a streaming approach.
16
+ *
17
+ * - Streams rows and cells to minimize memory usage
18
+ * - Tracks the worksheet dimension (min/max rows/cols) while streaming
19
+ * - Updates the <dimension> ref at the end by rewriting the file in a buffered pass
20
+ *
21
+ * @param destination - Absolute or relative file path for the worksheet XML
22
+ * @param rows - Map of rowIndex -> RowData with cells
23
+ * @param merges - Merge ranges to append after <sheetData>
24
+ * @returns Promise that resolves when the file is fully written and dimension updated
25
+ */
26
+ async function writeWorksheetXml(destination, rows = new Map(), merges = []) {
27
+ // ensure folder exists
28
+ await promises_1.default.mkdir(node_path_1.default.dirname(destination), { recursive: true });
29
+ const stream = node_fs_1.default.createWriteStream(destination, { encoding: "utf-8" });
30
+ // Track dimension incrementally while streaming
31
+ let minRow = Number.POSITIVE_INFINITY;
32
+ let maxRow = 0;
33
+ let minCol = Number.POSITIVE_INFINITY;
34
+ let maxCol = 0;
35
+ try {
36
+ // header
37
+ stream.write(constants_js_1.XML_DECLARATION + "\n");
38
+ stream.write(`<worksheet xmlns="${constants_js_1.XML_NAMESPACES.SPREADSHEET_ML}" xmlns:r="${constants_js_1.XML_NAMESPACES.OFFICE_DOCUMENT}">\n`);
39
+ // dimension
40
+ stream.write(" <dimension ref=\"A1:A1\"/>\n");
41
+ // sheetViews
42
+ stream.write(" <sheetViews>\n");
43
+ stream.write(" <sheetView workbookViewId=\"0\"/>\n");
44
+ stream.write(" </sheetViews>\n");
45
+ // sheetFormatPr
46
+ stream.write(" <sheetFormatPr defaultRowHeight=\"15\"/>\n");
47
+ // sheetData start
48
+ stream.write(" <sheetData>\n");
49
+ // rows (stream, without accumulation)
50
+ const typeSetSkipping = new Set(["n"]);
51
+ let processedRows = 0;
52
+ for (const [rowNumber, row] of rows) {
53
+ if (row.cells.size > 0) {
54
+ if (rowNumber < minRow)
55
+ minRow = rowNumber;
56
+ if (rowNumber > maxRow)
57
+ maxRow = rowNumber;
58
+ }
59
+ // Build the row string
60
+ const rowStart = ` <row r="${rowNumber}">\n`;
61
+ const rowEnd = " </row>\n";
62
+ // write to stream with backpressure control
63
+ if (!stream.write(rowStart)) {
64
+ await new Promise(resolve => stream.once("drain", () => resolve()));
65
+ }
66
+ // if you need to stream cells, you can do so as well:
67
+ for (const [colNumber, cellData] of row.cells) {
68
+ const colIndex = (0, column_letter_to_index_js_1.columnLetterToIndex)(colNumber) - 1;
69
+ if (colIndex < minCol)
70
+ minCol = colIndex;
71
+ if (colIndex > maxCol)
72
+ maxCol = colIndex;
73
+ const attrT = cellData.type && typeSetSkipping.has(cellData.type)
74
+ ? ""
75
+ : ` t="${cellData.type}"`;
76
+ const attrS = cellData.style?.index
77
+ ? ` s="${cellData.style?.index}"`
78
+ : "";
79
+ let cellXml = "";
80
+ if (cellData.isFormula) {
81
+ cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><f>${cellData.value}</f></c>\n`;
82
+ }
83
+ else {
84
+ switch (cellData.type) {
85
+ case "b": {
86
+ cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><v>${cellData.value ? "1" : "0"}</v></c>\n`;
87
+ break;
88
+ }
89
+ case "inlineStr": {
90
+ cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><is><t>${cellData.value}</t></is></c>\n`;
91
+ break;
92
+ }
93
+ default: {
94
+ cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><v>${cellData.value}</v></c>\n`;
95
+ break;
96
+ }
97
+ }
98
+ }
99
+ stream.write(cellXml);
100
+ // if (!stream.write(cellXml)) {
101
+ // await new Promise<void>(resolve => stream.once("drain", () => resolve()));
102
+ // }
103
+ }
104
+ if (!stream.write(rowEnd)) {
105
+ await new Promise(resolve => stream.once("drain", () => resolve()));
106
+ }
107
+ // Unload the event loop every 100 rows
108
+ processedRows++;
109
+ if (processedRows % 100 === 0) {
110
+ await new Promise(resolve => setImmediate(resolve));
111
+ }
112
+ // Unload the event loop every 100 rows
113
+ // rows.delete(rowNumber);
114
+ }
115
+ // sheetData end
116
+ stream.write(" </sheetData>\n");
117
+ // mergeCells
118
+ if (merges.length > 0) {
119
+ stream.write(` <mergeCells count="${merges.length}">\n`);
120
+ for (const merge of merges) {
121
+ if (merge.startCol < minCol)
122
+ minCol = merge.startCol;
123
+ if (merge.endCol > maxCol)
124
+ maxCol = merge.endCol;
125
+ if (merge.startRow < minRow)
126
+ minRow = merge.startRow;
127
+ if (merge.endRow > maxRow)
128
+ maxRow = merge.endRow;
129
+ const ref = `${(0, column_index_to_letter_js_1.columnIndexToLetter)(merge.startCol)}${merge.startRow}:${(0, column_index_to_letter_js_1.columnIndexToLetter)(merge.endCol)}${merge.endRow}`;
130
+ stream.write(` <mergeCell ref="${ref}"/>\n`);
131
+ }
132
+ stream.write(" </mergeCells>\n");
133
+ }
134
+ // close worksheet
135
+ stream.write("</worksheet>\n");
136
+ }
137
+ finally {
138
+ stream.end();
139
+ }
140
+ let finalDimensionRef = "A1:A1";
141
+ if (Number.isFinite(minCol) && Number.isFinite(minRow) && maxCol >= 0 && maxRow > 0) {
142
+ finalDimensionRef = `${(0, column_index_to_letter_js_1.columnIndexToLetter)(minCol)}${minRow}:${(0, column_index_to_letter_js_1.columnIndexToLetter)(maxCol)}${maxRow}`;
143
+ }
144
+ await new Promise((resolve, reject) => {
145
+ stream.on("error", reject);
146
+ stream.on("finish", resolve);
147
+ });
148
+ await updateWorksheetDimensionInFile(destination, finalDimensionRef);
149
+ return;
150
+ }
151
+ // async function updateWorksheetDimensionInFile(destination: string, dimensionRef: string): Promise<void> {
152
+ // const tempPath = `${destination}.tmp`;
153
+ // const readStream = fs.createReadStream(destination, { encoding: "utf-8" });
154
+ // const rl = readline.createInterface({ crlfDelay: Infinity, input: readStream });
155
+ // const writeStream = fs.createWriteStream(tempPath, { encoding: "utf-8" });
156
+ // let updated = false;
157
+ // const rlClosed = new Promise<void>(resolve => rl.once("close", resolve));
158
+ // for await (const line of rl) {
159
+ // let outLine = line;
160
+ // if (!updated && line.includes("<dimension")) {
161
+ // outLine = line.replace(/(<dimension[^>]*ref=")[^"]*("[^>]*\/>)/, `$1${dimensionRef}$2`);
162
+ // updated = true;
163
+ // }
164
+ // if (!writeStream.write(outLine + "\n")) {
165
+ // await new Promise<void>(resolve => writeStream.once("drain", resolve));
166
+ // }
167
+ // }
168
+ // await rlClosed;
169
+ // writeStream.end();
170
+ // await new Promise<void>(resolve => writeStream.once("finish", resolve));
171
+ // await fsPromises.rename(tempPath, destination);
172
+ // }
173
+ /**
174
+ * Updates the <dimension> ref attribute in an existing worksheet XML file.
175
+ * Performs a buffered line-by-line rewrite to a temporary file, then renames it in place.
176
+ *
177
+ * @param destination - Path to the worksheet XML file to update
178
+ * @param dimensionRef - Final dimension reference, e.g., "A1:C25"
179
+ */
180
+ async function updateWorksheetDimensionInFile(destination, dimensionRef) {
181
+ const tempPath = `${destination}.tmp`;
182
+ const readStream = node_fs_1.default.createReadStream(destination, { encoding: "utf-8" });
183
+ const rl = node_readline_1.default.createInterface({ crlfDelay: Infinity, input: readStream });
184
+ const writeStream = node_fs_1.default.createWriteStream(tempPath, { encoding: "utf-8" });
185
+ let updated = false;
186
+ let buffer = "";
187
+ const BUFFER_SIZE = 64 * 1024; // 64 KB
188
+ for await (const line of rl) {
189
+ let outLine = line;
190
+ if (!updated && line.includes("<dimension")) {
191
+ outLine = line.replace(/(<dimension[^>]*ref=")[^"]*("[^>]*\/>)/, `$1${dimensionRef}$2`);
192
+ updated = true;
193
+ }
194
+ buffer += outLine + "\n";
195
+ if (buffer.length >= BUFFER_SIZE) {
196
+ if (!writeStream.write(buffer)) {
197
+ await new Promise(resolve => writeStream.once("drain", resolve));
198
+ }
199
+ buffer = "";
200
+ }
201
+ }
202
+ // Write remaining buffer
203
+ if (buffer)
204
+ writeStream.write(buffer);
205
+ // Close streams
206
+ await new Promise(resolve => writeStream.end(resolve));
207
+ // Replace original file
208
+ await promises_1.default.rename(tempPath, destination);
209
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeXml = writeXml;
4
+ async function writeXml(node, stream, level = 0, chunkSize = 100) {
5
+ const { attrs = {}, children = [], tag } = node;
6
+ const attrStr = Object.entries(attrs)
7
+ .filter(([, v]) => v !== undefined && v !== null)
8
+ .map(([k, v]) => ` ${k}="${v}"`)
9
+ .join("");
10
+ const gap = " ".repeat(level);
11
+ // No children → self-closing tag
12
+ if (!children.length) {
13
+ stream.write(`${gap}<${tag}${attrStr}/>\n`);
14
+ return;
15
+ }
16
+ // Single text child → inline formatting
17
+ if (children.length === 1 && typeof children[0] === "string" && !children[0].includes("<")) {
18
+ stream.write(`${gap}<${tag}${attrStr}>${children[0]}</${tag}>\n`);
19
+ return;
20
+ }
21
+ // Has children → recursive streaming
22
+ stream.write(`${gap}<${tag}${attrStr}>\n`);
23
+ let processed = 0;
24
+ for (const c of children) {
25
+ if (typeof c === "string") {
26
+ stream.write(`${" ".repeat(level + 1)}${c}\n`);
27
+ }
28
+ else {
29
+ await writeXml(c, stream, level + 1, chunkSize);
30
+ }
31
+ processed++;
32
+ if (processed % chunkSize === 0) {
33
+ await new Promise(resolve => setImmediate(resolve));
34
+ }
35
+ }
36
+ stream.write(`${gap}</${tag}>\n`);
37
+ }