@rowsncolumns/toolkit 24.4.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 (456) hide show
  1. package/LICENSE.md +100 -0
  2. package/Readme.md +27 -0
  3. package/dist/cjs/autofilter-condition.d.ts +43 -0
  4. package/dist/cjs/autofilter-condition.d.ts.map +1 -0
  5. package/dist/cjs/autofilter-condition.js +155 -0
  6. package/dist/cjs/csv-export.d.ts +49 -0
  7. package/dist/cjs/csv-export.d.ts.map +1 -0
  8. package/dist/cjs/csv-export.js +142 -0
  9. package/dist/cjs/csv-import-worker.d.ts +16 -0
  10. package/dist/cjs/csv-import-worker.d.ts.map +1 -0
  11. package/dist/cjs/csv-import-worker.js +60 -0
  12. package/dist/cjs/csv-import.d.ts +38 -0
  13. package/dist/cjs/csv-import.d.ts.map +1 -0
  14. package/dist/cjs/csv-import.js +166 -0
  15. package/dist/cjs/csv-parser/helpers.d.ts +14 -0
  16. package/dist/cjs/csv-parser/helpers.d.ts.map +1 -0
  17. package/dist/cjs/csv-parser/helpers.js +145 -0
  18. package/dist/cjs/csv-parser/types.d.ts +66 -0
  19. package/dist/cjs/csv-parser/types.d.ts.map +1 -0
  20. package/dist/cjs/csv-parser/types.js +14 -0
  21. package/dist/cjs/csv-parser/worker.d.ts +2 -0
  22. package/dist/cjs/csv-parser/worker.d.ts.map +1 -0
  23. package/dist/cjs/csv-parser/worker.js +200 -0
  24. package/dist/cjs/excel-export.d.ts +11 -0
  25. package/dist/cjs/excel-export.d.ts.map +1 -0
  26. package/dist/cjs/excel-export.js +22 -0
  27. package/dist/cjs/excel-import-session.d.ts +51 -0
  28. package/dist/cjs/excel-import-session.d.ts.map +1 -0
  29. package/dist/cjs/excel-import-session.js +307 -0
  30. package/dist/cjs/excel-import-worker.d.ts +7 -0
  31. package/dist/cjs/excel-import-worker.d.ts.map +1 -0
  32. package/dist/cjs/excel-import-worker.js +119 -0
  33. package/dist/cjs/excel-parser/builtin-numfmts.d.ts +24 -0
  34. package/dist/cjs/excel-parser/builtin-numfmts.d.ts.map +1 -0
  35. package/dist/cjs/excel-parser/builtin-numfmts.js +63 -0
  36. package/dist/cjs/excel-parser/cfb-decryptor.d.ts +53 -0
  37. package/dist/cjs/excel-parser/cfb-decryptor.d.ts.map +1 -0
  38. package/dist/cjs/excel-parser/cfb-decryptor.js +553 -0
  39. package/dist/cjs/excel-parser/cfb-encryptor.d.ts +23 -0
  40. package/dist/cjs/excel-parser/cfb-encryptor.d.ts.map +1 -0
  41. package/dist/cjs/excel-parser/cfb-encryptor.js +200 -0
  42. package/dist/cjs/excel-parser/dv-cell-stamp.d.ts +29 -0
  43. package/dist/cjs/excel-parser/dv-cell-stamp.d.ts.map +1 -0
  44. package/dist/cjs/excel-parser/dv-cell-stamp.js +239 -0
  45. package/dist/cjs/excel-parser/helpers.d.ts +28 -0
  46. package/dist/cjs/excel-parser/helpers.d.ts.map +1 -0
  47. package/dist/cjs/excel-parser/helpers.js +188 -0
  48. package/dist/cjs/excel-parser/interface.d.ts +179 -0
  49. package/dist/cjs/excel-parser/interface.d.ts.map +1 -0
  50. package/dist/cjs/excel-parser/interface.js +1 -0
  51. package/dist/cjs/excel-parser/plugins/base/index.d.ts +31 -0
  52. package/dist/cjs/excel-parser/plugins/base/index.d.ts.map +1 -0
  53. package/dist/cjs/excel-parser/plugins/base/index.js +101 -0
  54. package/dist/cjs/excel-parser/plugins/ods/conditional-formatting.d.ts +16 -0
  55. package/dist/cjs/excel-parser/plugins/ods/conditional-formatting.d.ts.map +1 -0
  56. package/dist/cjs/excel-parser/plugins/ods/conditional-formatting.js +488 -0
  57. package/dist/cjs/excel-parser/plugins/ods/data-validations.d.ts +15 -0
  58. package/dist/cjs/excel-parser/plugins/ods/data-validations.d.ts.map +1 -0
  59. package/dist/cjs/excel-parser/plugins/ods/data-validations.js +353 -0
  60. package/dist/cjs/excel-parser/plugins/ods/formula.d.ts +8 -0
  61. package/dist/cjs/excel-parser/plugins/ods/formula.d.ts.map +1 -0
  62. package/dist/cjs/excel-parser/plugins/ods/formula.js +82 -0
  63. package/dist/cjs/excel-parser/plugins/ods/index.d.ts +122 -0
  64. package/dist/cjs/excel-parser/plugins/ods/index.d.ts.map +1 -0
  65. package/dist/cjs/excel-parser/plugins/ods/index.js +3642 -0
  66. package/dist/cjs/excel-parser/plugins/ods/sparklines.d.ts +25 -0
  67. package/dist/cjs/excel-parser/plugins/ods/sparklines.d.ts.map +1 -0
  68. package/dist/cjs/excel-parser/plugins/ods/sparklines.js +221 -0
  69. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts +60 -0
  70. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts.map +1 -0
  71. package/dist/cjs/excel-parser/plugins/ods/styles.js +808 -0
  72. package/dist/cjs/excel-parser/plugins/ods/types.d.ts +7 -0
  73. package/dist/cjs/excel-parser/plugins/ods/types.d.ts.map +1 -0
  74. package/dist/cjs/excel-parser/plugins/ods/types.js +1 -0
  75. package/dist/cjs/excel-parser/plugins/xls/index.d.ts +5 -0
  76. package/dist/cjs/excel-parser/plugins/xls/index.d.ts.map +1 -0
  77. package/dist/cjs/excel-parser/plugins/xls/index.js +19 -0
  78. package/dist/cjs/excel-parser/plugins/xlsb/biff-record-reader.d.ts +13 -0
  79. package/dist/cjs/excel-parser/plugins/xlsb/biff-record-reader.d.ts.map +1 -0
  80. package/dist/cjs/excel-parser/plugins/xlsb/biff-record-reader.js +49 -0
  81. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts +117 -0
  82. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts.map +1 -0
  83. package/dist/cjs/excel-parser/plugins/xlsb/index.js +2972 -0
  84. package/dist/cjs/excel-parser/plugins/xlsb/rgce-parser.d.ts +18 -0
  85. package/dist/cjs/excel-parser/plugins/xlsb/rgce-parser.d.ts.map +1 -0
  86. package/dist/cjs/excel-parser/plugins/xlsb/rgce-parser.js +527 -0
  87. package/dist/cjs/excel-parser/plugins/xlsm/index.d.ts +5 -0
  88. package/dist/cjs/excel-parser/plugins/xlsm/index.d.ts.map +1 -0
  89. package/dist/cjs/excel-parser/plugins/xlsm/index.js +10 -0
  90. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts +60 -0
  91. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts.map +1 -0
  92. package/dist/cjs/excel-parser/plugins/xlsx/charts.js +2178 -0
  93. package/dist/cjs/excel-parser/plugins/xlsx/conditional-formatting.d.ts +18 -0
  94. package/dist/cjs/excel-parser/plugins/xlsx/conditional-formatting.d.ts.map +1 -0
  95. package/dist/cjs/excel-parser/plugins/xlsx/conditional-formatting.js +620 -0
  96. package/dist/cjs/excel-parser/plugins/xlsx/data-validations.d.ts +4 -0
  97. package/dist/cjs/excel-parser/plugins/xlsx/data-validations.d.ts.map +1 -0
  98. package/dist/cjs/excel-parser/plugins/xlsx/data-validations.js +515 -0
  99. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts +39 -0
  100. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -0
  101. package/dist/cjs/excel-parser/plugins/xlsx/drawing.js +941 -0
  102. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +320 -0
  103. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -0
  104. package/dist/cjs/excel-parser/plugins/xlsx/index.js +6056 -0
  105. package/dist/cjs/excel-parser/plugins/xlsx/numfmt.d.ts +2 -0
  106. package/dist/cjs/excel-parser/plugins/xlsx/numfmt.d.ts.map +1 -0
  107. package/dist/cjs/excel-parser/plugins/xlsx/numfmt.js +3 -0
  108. package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts +40 -0
  109. package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -0
  110. package/dist/cjs/excel-parser/plugins/xlsx/pivots.js +342 -0
  111. package/dist/cjs/excel-parser/plugins/xlsx/relationships.d.ts +8 -0
  112. package/dist/cjs/excel-parser/plugins/xlsx/relationships.d.ts.map +1 -0
  113. package/dist/cjs/excel-parser/plugins/xlsx/relationships.js +26 -0
  114. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts +26 -0
  115. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -0
  116. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.js +59 -0
  117. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts +44 -0
  118. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts.map +1 -0
  119. package/dist/cjs/excel-parser/plugins/xlsx/styles.js +1377 -0
  120. package/dist/cjs/excel-parser/plugins/xlsx/theme.d.ts +50 -0
  121. package/dist/cjs/excel-parser/plugins/xlsx/theme.d.ts.map +1 -0
  122. package/dist/cjs/excel-parser/plugins/xlsx/theme.js +150 -0
  123. package/dist/cjs/excel-parser/plugins/xlsx/threaded-comments.d.ts +47 -0
  124. package/dist/cjs/excel-parser/plugins/xlsx/threaded-comments.d.ts.map +1 -0
  125. package/dist/cjs/excel-parser/plugins/xlsx/threaded-comments.js +141 -0
  126. package/dist/cjs/excel-parser/plugins/xlsx/value-type-detection.d.ts +44 -0
  127. package/dist/cjs/excel-parser/plugins/xlsx/value-type-detection.d.ts.map +1 -0
  128. package/dist/cjs/excel-parser/plugins/xlsx/value-type-detection.js +407 -0
  129. package/dist/cjs/excel-parser/registry.d.ts +5 -0
  130. package/dist/cjs/excel-parser/registry.d.ts.map +1 -0
  131. package/dist/cjs/excel-parser/registry.js +21 -0
  132. package/dist/cjs/excel-parser/style-registry.d.ts +51 -0
  133. package/dist/cjs/excel-parser/style-registry.d.ts.map +1 -0
  134. package/dist/cjs/excel-parser/style-registry.js +175 -0
  135. package/dist/cjs/excel-parser/theme-default.d.ts +3 -0
  136. package/dist/cjs/excel-parser/theme-default.d.ts.map +1 -0
  137. package/dist/cjs/excel-parser/theme-default.js +19 -0
  138. package/dist/cjs/excel-parser/types.d.ts +365 -0
  139. package/dist/cjs/excel-parser/types.d.ts.map +1 -0
  140. package/dist/cjs/excel-parser/types.js +59 -0
  141. package/dist/cjs/excel-parser/utils.d.ts +6 -0
  142. package/dist/cjs/excel-parser/utils.d.ts.map +1 -0
  143. package/dist/cjs/excel-parser/utils.js +30 -0
  144. package/dist/cjs/excel-parser/workbook.d.ts +51 -0
  145. package/dist/cjs/excel-parser/workbook.d.ts.map +1 -0
  146. package/dist/cjs/excel-parser/workbook.js +317 -0
  147. package/dist/cjs/excel-parser/worker.d.ts +2 -0
  148. package/dist/cjs/excel-parser/worker.d.ts.map +1 -0
  149. package/dist/cjs/excel-parser/worker.js +1149 -0
  150. package/dist/cjs/excel-parser/zip-parser-streaming.d.ts +13 -0
  151. package/dist/cjs/excel-parser/zip-parser-streaming.d.ts.map +1 -0
  152. package/dist/cjs/excel-parser/zip-parser-streaming.js +200 -0
  153. package/dist/cjs/excel-parser/zip-parser.d.ts +11 -0
  154. package/dist/cjs/excel-parser/zip-parser.d.ts.map +1 -0
  155. package/dist/cjs/excel-parser/zip-parser.js +49 -0
  156. package/dist/cjs/exporter/invalid-data-validation.d.ts +19 -0
  157. package/dist/cjs/exporter/invalid-data-validation.d.ts.map +1 -0
  158. package/dist/cjs/exporter/invalid-data-validation.js +39 -0
  159. package/dist/cjs/exporter/ods/ods-export.d.ts +26 -0
  160. package/dist/cjs/exporter/ods/ods-export.d.ts.map +1 -0
  161. package/dist/cjs/exporter/ods/ods-export.js +3714 -0
  162. package/dist/cjs/exporter/ods/sparkline-builder.d.ts +33 -0
  163. package/dist/cjs/exporter/ods/sparkline-builder.d.ts.map +1 -0
  164. package/dist/cjs/exporter/ods/sparkline-builder.js +221 -0
  165. package/dist/cjs/exporter/xlsx/chart-builder.d.ts +3 -0
  166. package/dist/cjs/exporter/xlsx/chart-builder.d.ts.map +1 -0
  167. package/dist/cjs/exporter/xlsx/chart-builder.js +1901 -0
  168. package/dist/cjs/exporter/xlsx/chart-templates.d.ts +1781 -0
  169. package/dist/cjs/exporter/xlsx/chart-templates.d.ts.map +1 -0
  170. package/dist/cjs/exporter/xlsx/chart-templates.js +1798 -0
  171. package/dist/cjs/exporter/xlsx/future-functions.d.ts +10 -0
  172. package/dist/cjs/exporter/xlsx/future-functions.d.ts.map +1 -0
  173. package/dist/cjs/exporter/xlsx/future-functions.js +264 -0
  174. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts +58 -0
  175. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts.map +1 -0
  176. package/dist/cjs/exporter/xlsx/pivot-builder.js +277 -0
  177. package/dist/cjs/exporter/xlsx/power-query-builder.d.ts +26 -0
  178. package/dist/cjs/exporter/xlsx/power-query-builder.d.ts.map +1 -0
  179. package/dist/cjs/exporter/xlsx/power-query-builder.js +306 -0
  180. package/dist/cjs/exporter/xlsx/slicer-builder.d.ts +11 -0
  181. package/dist/cjs/exporter/xlsx/slicer-builder.d.ts.map +1 -0
  182. package/dist/cjs/exporter/xlsx/slicer-builder.js +87 -0
  183. package/dist/cjs/exporter/xlsx/sparkline-builder.d.ts +61 -0
  184. package/dist/cjs/exporter/xlsx/sparkline-builder.d.ts.map +1 -0
  185. package/dist/cjs/exporter/xlsx/sparkline-builder.js +489 -0
  186. package/dist/cjs/exporter/xlsx/style-builder.d.ts +93 -0
  187. package/dist/cjs/exporter/xlsx/style-builder.d.ts.map +1 -0
  188. package/dist/cjs/exporter/xlsx/style-builder.js +813 -0
  189. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts +58 -0
  190. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -0
  191. package/dist/cjs/exporter/xlsx/threaded-comments-builder.js +189 -0
  192. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts +121 -0
  193. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts.map +1 -0
  194. package/dist/cjs/exporter/xlsx/xlsx-export.js +4596 -0
  195. package/dist/cjs/helpers/theme-xml-generator.d.ts +8 -0
  196. package/dist/cjs/helpers/theme-xml-generator.d.ts.map +1 -0
  197. package/dist/cjs/helpers/theme-xml-generator.js +33 -0
  198. package/dist/cjs/helpers.d.ts +34 -0
  199. package/dist/cjs/helpers.d.ts.map +1 -0
  200. package/dist/cjs/helpers.js +189 -0
  201. package/dist/cjs/index.d.ts +16 -0
  202. package/dist/cjs/index.d.ts.map +1 -0
  203. package/dist/cjs/index.js +15 -0
  204. package/dist/cjs/indexed-colors.d.ts +2 -0
  205. package/dist/cjs/indexed-colors.d.ts.map +1 -0
  206. package/dist/cjs/indexed-colors.js +75 -0
  207. package/dist/cjs/ods-export.d.ts +24 -0
  208. package/dist/cjs/ods-export.d.ts.map +1 -0
  209. package/dist/cjs/ods-export.js +23 -0
  210. package/dist/cjs/parse.d.ts +24 -0
  211. package/dist/cjs/parse.d.ts.map +1 -0
  212. package/dist/cjs/parse.js +68 -0
  213. package/dist/cjs/power-query.d.ts +41 -0
  214. package/dist/cjs/power-query.d.ts.map +1 -0
  215. package/dist/cjs/power-query.js +22 -0
  216. package/dist/cjs/server.d.ts +9 -0
  217. package/dist/cjs/server.d.ts.map +1 -0
  218. package/dist/cjs/server.js +8 -0
  219. package/dist/cjs/theme1.d.ts +3 -0
  220. package/dist/cjs/theme1.d.ts.map +1 -0
  221. package/dist/cjs/theme1.js +2 -0
  222. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  223. package/dist/cjs/types.d.ts +14 -0
  224. package/dist/cjs/types.d.ts.map +1 -0
  225. package/dist/cjs/types.js +14 -0
  226. package/dist/cjs/vitest.config.d.ts +3 -0
  227. package/dist/cjs/vitest.config.d.ts.map +1 -0
  228. package/dist/cjs/vitest.config.js +16 -0
  229. package/dist/esm/autofilter-condition.d.ts +43 -0
  230. package/dist/esm/autofilter-condition.d.ts.map +1 -0
  231. package/dist/esm/autofilter-condition.js +145 -0
  232. package/dist/esm/csv-export.d.ts +49 -0
  233. package/dist/esm/csv-export.d.ts.map +1 -0
  234. package/dist/esm/csv-export.js +126 -0
  235. package/dist/esm/csv-import-worker.d.ts +16 -0
  236. package/dist/esm/csv-import-worker.d.ts.map +1 -0
  237. package/dist/esm/csv-import-worker.js +60 -0
  238. package/dist/esm/csv-import.d.ts +38 -0
  239. package/dist/esm/csv-import.d.ts.map +1 -0
  240. package/dist/esm/csv-import.js +132 -0
  241. package/dist/esm/csv-parser/helpers.d.ts +14 -0
  242. package/dist/esm/csv-parser/helpers.d.ts.map +1 -0
  243. package/dist/esm/csv-parser/helpers.js +0 -0
  244. package/dist/esm/csv-parser/types.d.ts +66 -0
  245. package/dist/esm/csv-parser/types.d.ts.map +1 -0
  246. package/dist/esm/csv-parser/types.js +14 -0
  247. package/dist/esm/csv-parser/worker.d.ts +2 -0
  248. package/dist/esm/csv-parser/worker.d.ts.map +1 -0
  249. package/dist/esm/csv-parser/worker.js +154 -0
  250. package/dist/esm/excel-export.d.ts +11 -0
  251. package/dist/esm/excel-export.d.ts.map +1 -0
  252. package/dist/esm/excel-export.js +13 -0
  253. package/dist/esm/excel-import-session.d.ts +51 -0
  254. package/dist/esm/excel-import-session.d.ts.map +1 -0
  255. package/dist/esm/excel-import-session.js +255 -0
  256. package/dist/esm/excel-import-worker.d.ts +7 -0
  257. package/dist/esm/excel-import-worker.d.ts.map +1 -0
  258. package/dist/esm/excel-import-worker.js +116 -0
  259. package/dist/esm/excel-parser/builtin-numfmts.d.ts +24 -0
  260. package/dist/esm/excel-parser/builtin-numfmts.d.ts.map +1 -0
  261. package/dist/esm/excel-parser/builtin-numfmts.js +59 -0
  262. package/dist/esm/excel-parser/cfb-decryptor.d.ts +53 -0
  263. package/dist/esm/excel-parser/cfb-decryptor.d.ts.map +1 -0
  264. package/dist/esm/excel-parser/cfb-decryptor.js +493 -0
  265. package/dist/esm/excel-parser/cfb-encryptor.d.ts +23 -0
  266. package/dist/esm/excel-parser/cfb-encryptor.d.ts.map +1 -0
  267. package/dist/esm/excel-parser/cfb-encryptor.js +181 -0
  268. package/dist/esm/excel-parser/dv-cell-stamp.d.ts +29 -0
  269. package/dist/esm/excel-parser/dv-cell-stamp.d.ts.map +1 -0
  270. package/dist/esm/excel-parser/dv-cell-stamp.js +155 -0
  271. package/dist/esm/excel-parser/helpers.d.ts +28 -0
  272. package/dist/esm/excel-parser/helpers.d.ts.map +1 -0
  273. package/dist/esm/excel-parser/helpers.js +160 -0
  274. package/dist/esm/excel-parser/interface.d.ts +179 -0
  275. package/dist/esm/excel-parser/interface.d.ts.map +1 -0
  276. package/dist/esm/excel-parser/interface.js +1 -0
  277. package/dist/esm/excel-parser/plugins/base/index.d.ts +31 -0
  278. package/dist/esm/excel-parser/plugins/base/index.d.ts.map +1 -0
  279. package/dist/esm/excel-parser/plugins/base/index.js +64 -0
  280. package/dist/esm/excel-parser/plugins/ods/conditional-formatting.d.ts +16 -0
  281. package/dist/esm/excel-parser/plugins/ods/conditional-formatting.d.ts.map +1 -0
  282. package/dist/esm/excel-parser/plugins/ods/conditional-formatting.js +405 -0
  283. package/dist/esm/excel-parser/plugins/ods/data-validations.d.ts +15 -0
  284. package/dist/esm/excel-parser/plugins/ods/data-validations.d.ts.map +1 -0
  285. package/dist/esm/excel-parser/plugins/ods/data-validations.js +331 -0
  286. package/dist/esm/excel-parser/plugins/ods/formula.d.ts +8 -0
  287. package/dist/esm/excel-parser/plugins/ods/formula.d.ts.map +1 -0
  288. package/dist/esm/excel-parser/plugins/ods/formula.js +82 -0
  289. package/dist/esm/excel-parser/plugins/ods/index.d.ts +122 -0
  290. package/dist/esm/excel-parser/plugins/ods/index.d.ts.map +1 -0
  291. package/dist/esm/excel-parser/plugins/ods/index.js +2896 -0
  292. package/dist/esm/excel-parser/plugins/ods/sparklines.d.ts +25 -0
  293. package/dist/esm/excel-parser/plugins/ods/sparklines.d.ts.map +1 -0
  294. package/dist/esm/excel-parser/plugins/ods/sparklines.js +188 -0
  295. package/dist/esm/excel-parser/plugins/ods/styles.d.ts +60 -0
  296. package/dist/esm/excel-parser/plugins/ods/styles.d.ts.map +1 -0
  297. package/dist/esm/excel-parser/plugins/ods/styles.js +732 -0
  298. package/dist/esm/excel-parser/plugins/ods/types.d.ts +7 -0
  299. package/dist/esm/excel-parser/plugins/ods/types.d.ts.map +1 -0
  300. package/dist/esm/excel-parser/plugins/ods/types.js +1 -0
  301. package/dist/esm/excel-parser/plugins/xls/index.d.ts +5 -0
  302. package/dist/esm/excel-parser/plugins/xls/index.d.ts.map +1 -0
  303. package/dist/esm/excel-parser/plugins/xls/index.js +7 -0
  304. package/dist/esm/excel-parser/plugins/xlsb/biff-record-reader.d.ts +13 -0
  305. package/dist/esm/excel-parser/plugins/xlsb/biff-record-reader.d.ts.map +1 -0
  306. package/dist/esm/excel-parser/plugins/xlsb/biff-record-reader.js +48 -0
  307. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts +117 -0
  308. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts.map +1 -0
  309. package/dist/esm/excel-parser/plugins/xlsb/index.js +2339 -0
  310. package/dist/esm/excel-parser/plugins/xlsb/rgce-parser.d.ts +18 -0
  311. package/dist/esm/excel-parser/plugins/xlsb/rgce-parser.d.ts.map +1 -0
  312. package/dist/esm/excel-parser/plugins/xlsb/rgce-parser.js +522 -0
  313. package/dist/esm/excel-parser/plugins/xlsm/index.d.ts +5 -0
  314. package/dist/esm/excel-parser/plugins/xlsm/index.d.ts.map +1 -0
  315. package/dist/esm/excel-parser/plugins/xlsm/index.js +6 -0
  316. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts +60 -0
  317. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts.map +1 -0
  318. package/dist/esm/excel-parser/plugins/xlsx/charts.js +2036 -0
  319. package/dist/esm/excel-parser/plugins/xlsx/conditional-formatting.d.ts +18 -0
  320. package/dist/esm/excel-parser/plugins/xlsx/conditional-formatting.d.ts.map +1 -0
  321. package/dist/esm/excel-parser/plugins/xlsx/conditional-formatting.js +621 -0
  322. package/dist/esm/excel-parser/plugins/xlsx/data-validations.d.ts +4 -0
  323. package/dist/esm/excel-parser/plugins/xlsx/data-validations.d.ts.map +1 -0
  324. package/dist/esm/excel-parser/plugins/xlsx/data-validations.js +493 -0
  325. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts +39 -0
  326. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -0
  327. package/dist/esm/excel-parser/plugins/xlsx/drawing.js +905 -0
  328. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +320 -0
  329. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -0
  330. package/dist/esm/excel-parser/plugins/xlsx/index.js +4654 -0
  331. package/dist/esm/excel-parser/plugins/xlsx/numfmt.d.ts +2 -0
  332. package/dist/esm/excel-parser/plugins/xlsx/numfmt.d.ts.map +1 -0
  333. package/dist/esm/excel-parser/plugins/xlsx/numfmt.js +3 -0
  334. package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts +40 -0
  335. package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -0
  336. package/dist/esm/excel-parser/plugins/xlsx/pivots.js +254 -0
  337. package/dist/esm/excel-parser/plugins/xlsx/relationships.d.ts +8 -0
  338. package/dist/esm/excel-parser/plugins/xlsx/relationships.d.ts.map +1 -0
  339. package/dist/esm/excel-parser/plugins/xlsx/relationships.js +13 -0
  340. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts +26 -0
  341. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -0
  342. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.js +64 -0
  343. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts +44 -0
  344. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts.map +1 -0
  345. package/dist/esm/excel-parser/plugins/xlsx/styles.js +1365 -0
  346. package/dist/esm/excel-parser/plugins/xlsx/theme.d.ts +50 -0
  347. package/dist/esm/excel-parser/plugins/xlsx/theme.d.ts.map +1 -0
  348. package/dist/esm/excel-parser/plugins/xlsx/theme.js +127 -0
  349. package/dist/esm/excel-parser/plugins/xlsx/threaded-comments.d.ts +47 -0
  350. package/dist/esm/excel-parser/plugins/xlsx/threaded-comments.d.ts.map +1 -0
  351. package/dist/esm/excel-parser/plugins/xlsx/threaded-comments.js +103 -0
  352. package/dist/esm/excel-parser/plugins/xlsx/value-type-detection.d.ts +44 -0
  353. package/dist/esm/excel-parser/plugins/xlsx/value-type-detection.d.ts.map +1 -0
  354. package/dist/esm/excel-parser/plugins/xlsx/value-type-detection.js +399 -0
  355. package/dist/esm/excel-parser/registry.d.ts +5 -0
  356. package/dist/esm/excel-parser/registry.d.ts.map +1 -0
  357. package/dist/esm/excel-parser/registry.js +20 -0
  358. package/dist/esm/excel-parser/style-registry.d.ts +51 -0
  359. package/dist/esm/excel-parser/style-registry.d.ts.map +1 -0
  360. package/dist/esm/excel-parser/style-registry.js +163 -0
  361. package/dist/esm/excel-parser/theme-default.d.ts +3 -0
  362. package/dist/esm/excel-parser/theme-default.d.ts.map +1 -0
  363. package/dist/esm/excel-parser/theme-default.js +19 -0
  364. package/dist/esm/excel-parser/types.d.ts +365 -0
  365. package/dist/esm/excel-parser/types.d.ts.map +1 -0
  366. package/dist/esm/excel-parser/types.js +59 -0
  367. package/dist/esm/excel-parser/utils.d.ts +6 -0
  368. package/dist/esm/excel-parser/utils.d.ts.map +1 -0
  369. package/dist/esm/excel-parser/utils.js +25 -0
  370. package/dist/esm/excel-parser/workbook.d.ts +51 -0
  371. package/dist/esm/excel-parser/workbook.d.ts.map +1 -0
  372. package/dist/esm/excel-parser/workbook.js +192 -0
  373. package/dist/esm/excel-parser/worker.d.ts +2 -0
  374. package/dist/esm/excel-parser/worker.d.ts.map +1 -0
  375. package/dist/esm/excel-parser/worker.js +862 -0
  376. package/dist/esm/excel-parser/zip-parser-streaming.d.ts +13 -0
  377. package/dist/esm/excel-parser/zip-parser-streaming.d.ts.map +1 -0
  378. package/dist/esm/excel-parser/zip-parser-streaming.js +119 -0
  379. package/dist/esm/excel-parser/zip-parser.d.ts +11 -0
  380. package/dist/esm/excel-parser/zip-parser.d.ts.map +1 -0
  381. package/dist/esm/excel-parser/zip-parser.js +43 -0
  382. package/dist/esm/exporter/invalid-data-validation.d.ts +19 -0
  383. package/dist/esm/exporter/invalid-data-validation.d.ts.map +1 -0
  384. package/dist/esm/exporter/invalid-data-validation.js +37 -0
  385. package/dist/esm/exporter/ods/ods-export.d.ts +26 -0
  386. package/dist/esm/exporter/ods/ods-export.d.ts.map +1 -0
  387. package/dist/esm/exporter/ods/ods-export.js +3238 -0
  388. package/dist/esm/exporter/ods/sparkline-builder.d.ts +33 -0
  389. package/dist/esm/exporter/ods/sparkline-builder.d.ts.map +1 -0
  390. package/dist/esm/exporter/ods/sparkline-builder.js +165 -0
  391. package/dist/esm/exporter/xlsx/chart-builder.d.ts +3 -0
  392. package/dist/esm/exporter/xlsx/chart-builder.d.ts.map +1 -0
  393. package/dist/esm/exporter/xlsx/chart-builder.js +1805 -0
  394. package/dist/esm/exporter/xlsx/chart-templates.d.ts +1781 -0
  395. package/dist/esm/exporter/xlsx/chart-templates.d.ts.map +1 -0
  396. package/dist/esm/exporter/xlsx/chart-templates.js +1798 -0
  397. package/dist/esm/exporter/xlsx/future-functions.d.ts +10 -0
  398. package/dist/esm/exporter/xlsx/future-functions.d.ts.map +1 -0
  399. package/dist/esm/exporter/xlsx/future-functions.js +264 -0
  400. package/dist/esm/exporter/xlsx/pivot-builder.d.ts +58 -0
  401. package/dist/esm/exporter/xlsx/pivot-builder.d.ts.map +1 -0
  402. package/dist/esm/exporter/xlsx/pivot-builder.js +230 -0
  403. package/dist/esm/exporter/xlsx/power-query-builder.d.ts +26 -0
  404. package/dist/esm/exporter/xlsx/power-query-builder.d.ts.map +1 -0
  405. package/dist/esm/exporter/xlsx/power-query-builder.js +257 -0
  406. package/dist/esm/exporter/xlsx/slicer-builder.d.ts +11 -0
  407. package/dist/esm/exporter/xlsx/slicer-builder.d.ts.map +1 -0
  408. package/dist/esm/exporter/xlsx/slicer-builder.js +84 -0
  409. package/dist/esm/exporter/xlsx/sparkline-builder.d.ts +61 -0
  410. package/dist/esm/exporter/xlsx/sparkline-builder.d.ts.map +1 -0
  411. package/dist/esm/exporter/xlsx/sparkline-builder.js +437 -0
  412. package/dist/esm/exporter/xlsx/style-builder.d.ts +93 -0
  413. package/dist/esm/exporter/xlsx/style-builder.d.ts.map +1 -0
  414. package/dist/esm/exporter/xlsx/style-builder.js +795 -0
  415. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts +58 -0
  416. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -0
  417. package/dist/esm/exporter/xlsx/threaded-comments-builder.js +175 -0
  418. package/dist/esm/exporter/xlsx/xlsx-export.d.ts +121 -0
  419. package/dist/esm/exporter/xlsx/xlsx-export.d.ts.map +1 -0
  420. package/dist/esm/exporter/xlsx/xlsx-export.js +4062 -0
  421. package/dist/esm/helpers/theme-xml-generator.d.ts +8 -0
  422. package/dist/esm/helpers/theme-xml-generator.d.ts.map +1 -0
  423. package/dist/esm/helpers/theme-xml-generator.js +33 -0
  424. package/dist/esm/helpers.d.ts +34 -0
  425. package/dist/esm/helpers.d.ts.map +1 -0
  426. package/dist/esm/helpers.js +182 -0
  427. package/dist/esm/index.d.ts +16 -0
  428. package/dist/esm/index.d.ts.map +1 -0
  429. package/dist/esm/index.js +15 -0
  430. package/dist/esm/indexed-colors.d.ts +2 -0
  431. package/dist/esm/indexed-colors.d.ts.map +1 -0
  432. package/dist/esm/indexed-colors.js +75 -0
  433. package/dist/esm/ods-export.d.ts +24 -0
  434. package/dist/esm/ods-export.d.ts.map +1 -0
  435. package/dist/esm/ods-export.js +12 -0
  436. package/dist/esm/parse.d.ts +24 -0
  437. package/dist/esm/parse.d.ts.map +1 -0
  438. package/dist/esm/parse.js +55 -0
  439. package/dist/esm/power-query.d.ts +41 -0
  440. package/dist/esm/power-query.d.ts.map +1 -0
  441. package/dist/esm/power-query.js +19 -0
  442. package/dist/esm/server.d.ts +9 -0
  443. package/dist/esm/server.d.ts.map +1 -0
  444. package/dist/esm/server.js +8 -0
  445. package/dist/esm/theme1.d.ts +3 -0
  446. package/dist/esm/theme1.d.ts.map +1 -0
  447. package/dist/esm/theme1.js +2 -0
  448. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  449. package/dist/esm/types.d.ts +14 -0
  450. package/dist/esm/types.d.ts.map +1 -0
  451. package/dist/esm/types.js +14 -0
  452. package/dist/esm/vitest.config.d.ts +3 -0
  453. package/dist/esm/vitest.config.d.ts.map +1 -0
  454. package/dist/esm/vitest.config.js +16 -0
  455. package/package.json +62 -0
  456. package/xlsx.d.ts +52 -0
@@ -0,0 +1,795 @@
1
+ import { getCellEffectiveFormat, getCellUserEnteredFormat, } from "@rowsncolumns/utils";
2
+ import { BUILTIN_NUMFMT_BY_PATTERN } from "../../excel-parser/builtin-numfmts";
3
+ const isStyleReference = (value) => !!value && typeof value === "object" && "sid" in value;
4
+ // Built-in number-format dictionary is shared with the importer — see
5
+ // `excel-parser/builtin-numfmts.ts`. Pattern strings are the canonical
6
+ // Excel-writer form (quoted "$" for currency/accounting, `mmss.0` for
7
+ // numFmtId 47 per ECMA-376). Re-aliased for backwards compat with the
8
+ // previous local name in this file.
9
+ const BUILT_IN_NUMFMT_BY_PATTERN = BUILTIN_NUMFMT_BY_PATTERN;
10
+ export class StyleBuilder {
11
+ numberFormats = [];
12
+ fonts = [
13
+ {
14
+ name: "Calibri",
15
+ size: 11,
16
+ },
17
+ ];
18
+ fills = [{ pattern: "none" }, { pattern: "gray125" }];
19
+ borders = [{}];
20
+ namedCellStyles = [
21
+ { name: "Normal", xfId: 0, builtinId: 0 },
22
+ ];
23
+ customTableStyles = [];
24
+ /**
25
+ * Replace the named-cell-styles list emitted in `<cellStyles>`.
26
+ * Used for round-tripping the OOXML Heading 1 / Accent / Total /
27
+ * Good-Bad-Neutral gallery — the importer parses these from
28
+ * `xl/styles.xml` and exposes them on `workbook.workbookStyles.
29
+ * namedCellStyles`; hosts can forward that list back here.
30
+ *
31
+ * Excel requires at least a "Normal" entry pointing at xfId=0,
32
+ * builtinId=0 — when the supplied list doesn't contain one, we
33
+ * keep the default at the head of the list rather than risk
34
+ * emitting a file Excel rejects.
35
+ */
36
+ setNamedCellStyles(entries) {
37
+ if (!entries || entries.length === 0)
38
+ return;
39
+ const hasNormal = entries.some((e) => e.builtinId === 0 || e.name === "Normal");
40
+ this.namedCellStyles = hasNormal
41
+ ? entries.slice()
42
+ : [{ name: "Normal", xfId: 0, builtinId: 0 }, ...entries];
43
+ }
44
+ /**
45
+ * Replace the user-authored table-style list emitted in the
46
+ * `<tableStyles>` block. The exporter registers each element's
47
+ * format as a dxf at `toXml()` time, so callers pass self-contained
48
+ * records (no dxfIds to manage). Used for round-tripping the
49
+ * OOXML custom-table-style list from
50
+ * `workbook.workbookStyles.getCustomTableStyleExports()`.
51
+ */
52
+ setCustomTableStyles(entries) {
53
+ if (!entries || entries.length === 0) {
54
+ this.customTableStyles = [];
55
+ return;
56
+ }
57
+ this.customTableStyles = entries.slice();
58
+ }
59
+ cellXfs = [
60
+ {
61
+ numFmtId: 0,
62
+ fontId: 0,
63
+ fillId: 0,
64
+ borderId: 0,
65
+ },
66
+ ];
67
+ fontMap = new Map();
68
+ fillMap = new Map();
69
+ borderMap = new Map();
70
+ formatMap = new Map();
71
+ xfMap = new Map();
72
+ dxfs = [];
73
+ dxfMap = new Map();
74
+ constructor() {
75
+ this.fontMap.set(this.serializeFont(this.fonts[0]), 0);
76
+ this.fillMap.set(this.serializeFill(this.fills[0]), 0);
77
+ this.fillMap.set(this.serializeFill(this.fills[1]), 1);
78
+ this.borderMap.set(this.serializeBorder(this.borders[0]), 0);
79
+ this.xfMap.set(serializeXf(this.cellXfs[0]), 0);
80
+ }
81
+ /**
82
+ * Replace the workbook default font (font id 0 — what every cell without
83
+ * an explicit font inherits). Callers pass the source workbook's parsed
84
+ * default (`WorkBook.getDefaultFont()`) so an imported workbook keeps its
85
+ * default typeface/size instead of the hardcoded Calibri 11. Must be
86
+ * called before any cell registration: cells explicitly styled with the
87
+ * old default must not collapse into font id 0.
88
+ */
89
+ setDefaultFont(format) {
90
+ if (this.fonts.length > 1)
91
+ return;
92
+ const record = this.buildFontRecord(format);
93
+ if (!record)
94
+ return;
95
+ this.fonts[0] = record;
96
+ this.fontMap.clear();
97
+ this.fontMap.set(this.serializeFont(record), 0);
98
+ }
99
+ registerCell(cell, cellXfs,
100
+ /**
101
+ * Number format to use when the cell itself has none. Used by the
102
+ * exporter to layer in the precedent-derived number format on formula
103
+ * cells so Excel displays them correctly without requiring a recalc.
104
+ */
105
+ derivedNumberFormat) {
106
+ if (!cell)
107
+ return 0;
108
+ // Match Excel's model: persist only the user-entered format. Auto-
109
+ // derived alignment / pattern color / formula precedent format are
110
+ // recomputed at render time and never serialized to disk. Legacy `ef`
111
+ // is still read as a fallback so old files continue to export with the
112
+ // formatting they originally had.
113
+ const userEnteredFormat = normalizeFormat(getCellUserEnteredFormat(cell), cellXfs);
114
+ let effectiveFormat = userEnteredFormat ??
115
+ normalizeFormat(getCellEffectiveFormat(cell), cellXfs) ??
116
+ undefined;
117
+ // Layer in the derived number format only when the cell's own format
118
+ // has nothing in that slot. User-set formats always win.
119
+ if (derivedNumberFormat && !effectiveFormat?.numberFormat) {
120
+ effectiveFormat = {
121
+ ...(effectiveFormat ?? {}),
122
+ numberFormat: derivedNumberFormat,
123
+ };
124
+ }
125
+ const numberFormatId = this.getNumberFormatId(effectiveFormat);
126
+ const fontId = this.getFontId(effectiveFormat?.textFormat);
127
+ const fillId = this.getFillId(effectiveFormat);
128
+ const borderId = this.getBorderId(effectiveFormat?.borders);
129
+ const xfRecord = {
130
+ numFmtId: numberFormatId,
131
+ fontId,
132
+ fillId,
133
+ borderId,
134
+ wrapText: effectiveFormat?.wrapStrategy === "wrap",
135
+ horizontalAlignment: normalizeHorizontalAlignment(effectiveFormat?.horizontalAlignment),
136
+ verticalAlignment: normalizeVerticalAlignment(effectiveFormat?.verticalAlignment),
137
+ indent: effectiveFormat?.indent ?? undefined,
138
+ relativeIndent: effectiveFormat?.relativeIndent ?? undefined,
139
+ textRotation: effectiveFormat?.textRotation ?? undefined,
140
+ shrinkToFit: effectiveFormat?.shrinkToFit ?? undefined,
141
+ // Protection lives top-level on the cell (not on the format) — read
142
+ // it off the cell directly. The xf still carries the flags because
143
+ // that's where Excel persists them; we synthesize a unique xf per
144
+ // protection variant via the cache key below.
145
+ protectionLocked: cell?.protection?.locked === false ? false : undefined,
146
+ protectionHidden: cell?.protection?.hidden === true ? true : undefined,
147
+ };
148
+ const key = serializeXf(xfRecord);
149
+ const existing = this.xfMap.get(key);
150
+ if (typeof existing === "number") {
151
+ return existing;
152
+ }
153
+ const nextId = this.cellXfs.length;
154
+ this.cellXfs.push(xfRecord);
155
+ this.xfMap.set(key, nextId);
156
+ return nextId;
157
+ }
158
+ registerDifferentialFormat(format) {
159
+ if (!format)
160
+ return undefined;
161
+ const record = {};
162
+ if (format.backgroundColor) {
163
+ record.fill = {
164
+ color: format.backgroundColor,
165
+ };
166
+ }
167
+ const font = this.buildFontRecord(format.textFormat);
168
+ if (font) {
169
+ record.font = font;
170
+ }
171
+ if (!record.fill && !record.font) {
172
+ return undefined;
173
+ }
174
+ const key = this.serializeDxf(record);
175
+ const existing = this.dxfMap.get(key);
176
+ if (typeof existing === "number") {
177
+ return existing;
178
+ }
179
+ const nextId = this.dxfs.length;
180
+ this.dxfs.push(record);
181
+ this.dxfMap.set(key, nextId);
182
+ return nextId;
183
+ }
184
+ getNumberFormatId(effectiveFormat) {
185
+ const pattern = effectiveFormat?.numberFormat?.pattern;
186
+ if (!pattern)
187
+ return 0;
188
+ // Preserve trailing whitespace in the pattern verbatim — number-format
189
+ // strings legitimately end with significant `\xa0` (non-breaking space)
190
+ // chars for column-aligned currency/accounting formats. Trimming here
191
+ // mangled those formats on round-trip and broke comparator equality
192
+ // against the source `<numFmts>` table. We still dedupe via the map
193
+ // using the raw pattern as key.
194
+ const normalizedPattern = pattern;
195
+ // Try Excel's built-in numFmtId table (0–49). When our pattern matches
196
+ // a built-in exactly, emit that ID — Excel and other readers render
197
+ // identically and we avoid bloating <numFmts> with a redundant
198
+ // custom entry.
199
+ const builtInId = BUILT_IN_NUMFMT_BY_PATTERN.get(normalizedPattern);
200
+ if (typeof builtInId === "number") {
201
+ return builtInId;
202
+ }
203
+ const existing = this.formatMap.get(normalizedPattern);
204
+ if (typeof existing === "number") {
205
+ return existing;
206
+ }
207
+ // ECMA-376 §18.8.30: built-in numFmtIds occupy 0–163. Custom IDs
208
+ // start at 164 by convention (Excel's own writer does the same).
209
+ const nextId = 164 + this.numberFormats.length;
210
+ this.numberFormats.push({
211
+ id: nextId,
212
+ format: normalizedPattern,
213
+ });
214
+ this.formatMap.set(normalizedPattern, nextId);
215
+ return nextId;
216
+ }
217
+ getFontId(format) {
218
+ const record = this.buildFontRecord(format);
219
+ if (!record)
220
+ return 0;
221
+ const key = this.serializeFont(record);
222
+ const existing = this.fontMap.get(key);
223
+ if (typeof existing === "number") {
224
+ return existing;
225
+ }
226
+ const nextId = this.fonts.length;
227
+ this.fonts.push(record);
228
+ this.fontMap.set(key, nextId);
229
+ return nextId;
230
+ }
231
+ getFillId(format) {
232
+ const fillPattern = format?.fillPattern ?? undefined;
233
+ const fgColor = format?.foregroundColor ?? undefined;
234
+ const bgColor = format?.backgroundColor ?? undefined;
235
+ const gradient = format?.gradient ?? undefined;
236
+ // Gradient fill takes precedence over pattern — Excel's UI treats
237
+ // them as mutually exclusive on a single cell.
238
+ if (gradient && gradient.stops?.length) {
239
+ const record = { gradient };
240
+ const key = this.serializeFill(record);
241
+ const existing = this.fillMap.get(key);
242
+ if (typeof existing === "number")
243
+ return existing;
244
+ const nextId = this.fills.length;
245
+ this.fills.push(record);
246
+ this.fillMap.set(key, nextId);
247
+ return nextId;
248
+ }
249
+ // Patterned (non-solid) fill: `color` carries the foreground (pattern)
250
+ // color and `bgColor` carries the under-layer that shows through the
251
+ // pattern gaps. Solid fill keeps the legacy single-color path.
252
+ if (fillPattern &&
253
+ fillPattern !== "none" &&
254
+ fillPattern !== "solid") {
255
+ const record = {
256
+ color: fgColor ?? bgColor,
257
+ bgColor: fgColor ? bgColor : undefined,
258
+ pattern: fillPattern,
259
+ };
260
+ const key = this.serializeFill(record);
261
+ const existing = this.fillMap.get(key);
262
+ if (typeof existing === "number")
263
+ return existing;
264
+ const nextId = this.fills.length;
265
+ this.fills.push(record);
266
+ this.fillMap.set(key, nextId);
267
+ return nextId;
268
+ }
269
+ // Solid fill: prefer explicit foregroundColor, fall back to
270
+ // backgroundColor for the common authored-as-bg case.
271
+ const color = fgColor ?? bgColor;
272
+ const record = {
273
+ color,
274
+ pattern: color ? "solid" : "none",
275
+ };
276
+ const key = this.serializeFill(record);
277
+ const existing = this.fillMap.get(key);
278
+ if (typeof existing === "number") {
279
+ return existing;
280
+ }
281
+ const nextId = this.fills.length;
282
+ this.fills.push(record);
283
+ this.fillMap.set(key, nextId);
284
+ return nextId;
285
+ }
286
+ getBorderId(borders) {
287
+ // OOXML uses a single <diagonal> child plus diagonalUp/diagonalDown
288
+ // attributes. If both diagonals are present and identically styled the
289
+ // first non-null one defines the edge; otherwise each flag is set
290
+ // independently and both share the same painted style. This matches
291
+ // how Excel collapses diagonal pairs.
292
+ const diagonalEdge = convertBorderEdge(borders?.diagonalUp ?? borders?.diagonalDown);
293
+ const record = {
294
+ top: convertBorderEdge(borders?.top),
295
+ bottom: convertBorderEdge(borders?.bottom),
296
+ left: convertBorderEdge(borders?.left),
297
+ right: convertBorderEdge(borders?.right),
298
+ diagonal: diagonalEdge,
299
+ diagonalUp: !!borders?.diagonalUp,
300
+ diagonalDown: !!borders?.diagonalDown,
301
+ };
302
+ const key = this.serializeBorder(record);
303
+ const existing = this.borderMap.get(key);
304
+ if (typeof existing === "number") {
305
+ return existing;
306
+ }
307
+ const nextId = this.borders.length;
308
+ this.borders.push(record);
309
+ this.borderMap.set(key, nextId);
310
+ return nextId;
311
+ }
312
+ serializeFont(font) {
313
+ return [
314
+ font.name ?? "",
315
+ font.size ?? "",
316
+ font.bold ? "1" : "",
317
+ font.italic ? "1" : "",
318
+ font.underline ? "1" : "",
319
+ font.strike ? "1" : "",
320
+ serializeColor(font.color),
321
+ font.vertAlign ?? "",
322
+ ].join("|");
323
+ }
324
+ buildFontRecord(format) {
325
+ if (!format?.bold &&
326
+ !format?.italic &&
327
+ !format?.underline &&
328
+ !format?.strikethrough &&
329
+ !format?.fontSize &&
330
+ !format?.fontFamily &&
331
+ !format?.color &&
332
+ !format?.baselineOffset) {
333
+ return undefined;
334
+ }
335
+ const vertAlign = format?.baselineOffset === "superscript" ||
336
+ format?.baselineOffset === "subscript"
337
+ ? format.baselineOffset
338
+ : undefined;
339
+ return {
340
+ bold: format?.bold ?? undefined,
341
+ italic: format?.italic ?? undefined,
342
+ underline: format?.underline ?? undefined,
343
+ strike: format?.strikethrough ?? undefined,
344
+ size: format?.fontSize ?? undefined,
345
+ name: format?.fontFamily ?? undefined,
346
+ color: format?.color ?? undefined,
347
+ vertAlign,
348
+ };
349
+ }
350
+ buildFontXml(font) {
351
+ const color = serializeColorXml(font.color);
352
+ const name = sanitizeFontName(font.name);
353
+ return `<font>${font.size ? `<sz val="${font.size}"/>` : ""}${name ? `<name val="${escapeXml(name)}"/>` : ""}${font.bold ? "<b/>" : ""}${font.italic ? "<i/>" : ""}${font.underline ? "<u/>" : ""}${font.strike ? "<strike/>" : ""}${font.vertAlign ? `<vertAlign val="${font.vertAlign}"/>` : ""}${color ? `<color ${color}/>` : ""}</font>`;
354
+ }
355
+ buildFillXml(fill, forDxf = false) {
356
+ // Gradient fill — emits `<gradientFill>` with `<stop>` children.
357
+ // Excel accepts gradients in cell fills (not dxf), so when this is
358
+ // requested for a dxf record we degrade to a solid using the first
359
+ // stop's color so the conditional format still has SOMETHING to paint.
360
+ if (fill.gradient && fill.gradient.stops?.length) {
361
+ if (forDxf) {
362
+ const first = fill.gradient.stops[0].color;
363
+ const fallback = serializeColorXml(first);
364
+ if (fallback) {
365
+ return `<fill><patternFill patternType="solid"><fgColor ${fallback}/><bgColor ${fallback}/></patternFill></fill>`;
366
+ }
367
+ return `<fill><patternFill patternType="none"/></fill>`;
368
+ }
369
+ return this.buildGradientFillXml(fill.gradient);
370
+ }
371
+ const pattern = fill.pattern ?? (fill.color ? "solid" : "none");
372
+ if (pattern === "gray125" && !fill.color) {
373
+ return `<fill><patternFill patternType="gray125"/></fill>`;
374
+ }
375
+ const color = serializeColorXml(fill.color);
376
+ if (pattern === "none" || !color) {
377
+ return `<fill><patternFill patternType="none"/></fill>`;
378
+ }
379
+ if (pattern === "solid") {
380
+ if (forDxf) {
381
+ return `<fill><patternFill patternType="solid"><fgColor ${color}/><bgColor ${color}/></patternFill></fill>`;
382
+ }
383
+ return `<fill><patternFill patternType="solid"><fgColor ${color}/><bgColor indexed="64"/></patternFill></fill>`;
384
+ }
385
+ // True patterned fill — emit both fg and bg if available.
386
+ const bgColor = serializeColorXml(fill.bgColor);
387
+ const bgAttr = bgColor ? `<bgColor ${bgColor}/>` : `<bgColor indexed="64"/>`;
388
+ return `<fill><patternFill patternType="${pattern}"><fgColor ${color}/>${bgAttr}</patternFill></fill>`;
389
+ }
390
+ buildGradientFillXml(gradient) {
391
+ const stopsXml = gradient.stops
392
+ .map((s) => {
393
+ const color = serializeColorXml(s.color);
394
+ return `<stop position="${s.position}">${color ? `<color ${color}/>` : ""}</stop>`;
395
+ })
396
+ .join("");
397
+ const attrs = [];
398
+ if (gradient.type === "path") {
399
+ attrs.push('type="path"');
400
+ if (gradient.left != null)
401
+ attrs.push(`left="${gradient.left}"`);
402
+ if (gradient.right != null)
403
+ attrs.push(`right="${gradient.right}"`);
404
+ if (gradient.top != null)
405
+ attrs.push(`top="${gradient.top}"`);
406
+ if (gradient.bottom != null)
407
+ attrs.push(`bottom="${gradient.bottom}"`);
408
+ }
409
+ else if (gradient.degree != null && gradient.degree !== 0) {
410
+ attrs.push(`degree="${gradient.degree}"`);
411
+ }
412
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
413
+ return `<fill><gradientFill${attrStr}>${stopsXml}</gradientFill></fill>`;
414
+ }
415
+ serializeFill(fill) {
416
+ const gradientKey = fill.gradient
417
+ ? `G:${fill.gradient.type}:${fill.gradient.degree ?? ""}:${fill.gradient.left ?? ""}:${fill.gradient.right ?? ""}:${fill.gradient.top ?? ""}:${fill.gradient.bottom ?? ""}:${fill.gradient.stops
418
+ .map((s) => `${s.position},${s.color}`)
419
+ .join("|")}`
420
+ : "";
421
+ return `${fill.pattern ?? ""}:${serializeColor(fill.color)}:${serializeColor(fill.bgColor)}:${gradientKey}`;
422
+ }
423
+ serializeBorder(border) {
424
+ return [
425
+ serializeBorderEdge(border.top),
426
+ serializeBorderEdge(border.bottom),
427
+ serializeBorderEdge(border.left),
428
+ serializeBorderEdge(border.right),
429
+ serializeBorderEdge(border.diagonal),
430
+ border.diagonalUp ? "1" : "",
431
+ border.diagonalDown ? "1" : "",
432
+ ].join("|");
433
+ }
434
+ serializeDxf(dxf) {
435
+ return `${dxf.fill ? this.serializeFill(dxf.fill) : ""}|${dxf.font ? this.serializeFont(dxf.font) : ""}`;
436
+ }
437
+ toXml() {
438
+ const numFmtXml = this.numberFormats.length
439
+ ? `<numFmts count="${this.numberFormats.length}">${this.numberFormats
440
+ .map((fmt) => `<numFmt numFmtId="${fmt.id}" formatCode="${escapeXml(fmt.format)}"/>`)
441
+ .join("")}</numFmts>`
442
+ : `<numFmts count="0"/>`;
443
+ const fontXml = `<fonts count="${this.fonts.length}">${this.fonts
444
+ .map((font) => this.buildFontXml(font))
445
+ .join("")}</fonts>`;
446
+ const fillXml = `<fills count="${this.fills.length}">${this.fills
447
+ .map((fill) => this.buildFillXml(fill, false))
448
+ .join("")}</fills>`;
449
+ const borderXml = `<borders count="${this.borders.length}">${this.borders
450
+ .map((border) => {
451
+ const top = serializeBorderEdgeXml(border.top, "top");
452
+ const bottom = serializeBorderEdgeXml(border.bottom, "bottom");
453
+ const left = serializeBorderEdgeXml(border.left, "left");
454
+ const right = serializeBorderEdgeXml(border.right, "right");
455
+ const diagonal = border.diagonal
456
+ ? serializeBorderEdgeXml(border.diagonal, "diagonal")
457
+ : "<diagonal/>";
458
+ const diagonalAttrs = `${border.diagonalUp ? ` diagonalUp="1"` : ""}${border.diagonalDown ? ` diagonalDown="1"` : ""}`;
459
+ return `<border${diagonalAttrs}>${left}${right}${top}${bottom}${diagonal}</border>`;
460
+ })
461
+ .join("")}</borders>`;
462
+ const cellXfsXml = `<cellXfs count="${this.cellXfs.length}">${this.cellXfs
463
+ .map((record) => {
464
+ const alignment = serializeAlignment(record);
465
+ const protection = serializeProtection(record);
466
+ // ECMA-376 §18.8.45: `applyX="1"` signals that this xf overrides
467
+ // the named-style parent (xfId=0) for that aspect. Excel tolerates
468
+ // missing applyX, but stricter readers (older LibreOffice, some
469
+ // headless engines) honor only the parent's value when applyX is
470
+ // absent. Emit each flag when the corresponding id deviates from
471
+ // the parent's defaults (0 across the board) or when alignment is
472
+ // present.
473
+ const applyNumberFormat = record.numFmtId !== 0 ? ` applyNumberFormat="1"` : "";
474
+ const applyFont = record.fontId !== 0 ? ` applyFont="1"` : "";
475
+ const applyFill = record.fillId !== 0 ? ` applyFill="1"` : "";
476
+ const applyBorder = record.borderId !== 0 ? ` applyBorder="1"` : "";
477
+ const applyAlignment = alignment ? ` applyAlignment="1"` : "";
478
+ const applyProtection = protection ? ` applyProtection="1"` : "";
479
+ return `<xf numFmtId="${record.numFmtId}" fontId="${record.fontId}" fillId="${record.fillId}" borderId="${record.borderId}" xfId="0"${applyNumberFormat}${applyFont}${applyFill}${applyBorder}${applyAlignment}${applyProtection}>${alignment}${protection}</xf>`;
480
+ })
481
+ .join("")}</cellXfs>`;
482
+ const resolvedTableStyles = this.customTableStyles.map((style) => {
483
+ const resolvedElements = [];
484
+ for (const el of style.elements) {
485
+ const dxfId = this.registerDifferentialFormat({
486
+ ...(el.backgroundColor
487
+ ? { backgroundColor: el.backgroundColor }
488
+ : {}),
489
+ ...(el.textColor || el.bold || el.italic
490
+ ? {
491
+ textFormat: {
492
+ ...(el.textColor ? { color: el.textColor } : {}),
493
+ ...(el.bold ? { bold: true } : {}),
494
+ ...(el.italic ? { italic: true } : {}),
495
+ },
496
+ }
497
+ : {}),
498
+ });
499
+ // Drop elements that didn't contribute any recognized format —
500
+ // an undefined dxfId means `registerDifferentialFormat` saw
501
+ // an empty record. (dxfId === 0 is the valid first-slot
502
+ // entry, so we explicitly exclude only `undefined`.)
503
+ if (dxfId === undefined)
504
+ continue;
505
+ resolvedElements.push({
506
+ type: el.type,
507
+ dxfId,
508
+ ...(el.size != null ? { size: el.size } : {}),
509
+ });
510
+ }
511
+ return {
512
+ name: style.name,
513
+ pivot: style.pivot,
514
+ elements: resolvedElements,
515
+ };
516
+ });
517
+ const dxfsXml = this.dxfs.length
518
+ ? `<dxfs count="${this.dxfs.length}">${this.dxfs
519
+ .map((dxf) => {
520
+ const font = dxf.font ? this.buildFontXml(dxf.font) : "";
521
+ const fill = dxf.fill ? this.buildFillXml(dxf.fill, true) : "";
522
+ return `<dxf>${font}${fill}</dxf>`;
523
+ })
524
+ .join("")}</dxfs>`
525
+ : `<dxfs count="0"/>`;
526
+ const cellStylesXml = `<cellStyles count="${this.namedCellStyles.length}">${this.namedCellStyles
527
+ .map((s) => {
528
+ const parts = [`name="${escapeXml(s.name)}"`];
529
+ parts.push(`xfId="${s.xfId}"`);
530
+ if (s.builtinId != null)
531
+ parts.push(`builtinId="${s.builtinId}"`);
532
+ if (s.iLevel != null)
533
+ parts.push(`iLevel="${s.iLevel}"`);
534
+ if (s.hidden)
535
+ parts.push(`hidden="1"`);
536
+ if (s.customBuiltin)
537
+ parts.push(`customBuiltin="1"`);
538
+ return `<cellStyle ${parts.join(" ")}/>`;
539
+ })
540
+ .join("")}</cellStyles>`;
541
+ // Emit user-authored table styles. Excel REQUIRES the
542
+ // `defaultTableStyle` + `defaultPivotStyle` attributes to be the
543
+ // names of built-in styles (or styles defined here) — we keep
544
+ // the built-in defaults regardless of whether any custom styles
545
+ // are present.
546
+ const customTableStylesXml = resolvedTableStyles
547
+ .filter((s) => s.elements.length > 0)
548
+ .map((s) => {
549
+ const pivotAttr = s.pivot ? ` pivot="1"` : ` pivot="0"`;
550
+ const elementsXml = s.elements
551
+ .map((el) => {
552
+ const sizeAttr = el.size != null ? ` size="${el.size}"` : "";
553
+ return `<tableStyleElement type="${escapeXml(el.type)}" dxfId="${el.dxfId}"${sizeAttr}/>`;
554
+ })
555
+ .join("");
556
+ return `<tableStyle name="${escapeXml(s.name)}"${pivotAttr} count="${s.elements.length}">${elementsXml}</tableStyle>`;
557
+ })
558
+ .join("");
559
+ const tableStylesXml = `<tableStyles count="${resolvedTableStyles.filter((s) => s.elements.length > 0).length}" defaultTableStyle="TableStyleMedium2" defaultPivotStyle="PivotStyleLight16">${customTableStylesXml}</tableStyles>`;
560
+ const styleXml = `${XML_DECLARATION}<styleSheet xmlns="${WORKSHEET_NS}">${numFmtXml}${fontXml}${fillXml}${borderXml}<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>${cellXfsXml}${cellStylesXml}${dxfsXml}${tableStylesXml}</styleSheet>`;
561
+ return styleXml;
562
+ }
563
+ }
564
+ const convertBorderEdge = (border) => {
565
+ if (!border || !border.style)
566
+ return undefined;
567
+ return {
568
+ style: mapBorderStyle(border.style),
569
+ color: border.color ?? undefined,
570
+ };
571
+ };
572
+ const mapBorderStyle = (style) => {
573
+ switch (style) {
574
+ case "dashed":
575
+ return "dashed";
576
+ case "dotted":
577
+ return "dotted";
578
+ case "double":
579
+ return "double";
580
+ case "solid_medium":
581
+ return "medium";
582
+ case "solid_thick":
583
+ return "thick";
584
+ case "hair":
585
+ return "hair";
586
+ case "mediumDashed":
587
+ return "mediumDashed";
588
+ case "mediumDashDot":
589
+ return "mediumDashDot";
590
+ case "dashDot":
591
+ return "dashDot";
592
+ case "dashDotDot":
593
+ return "dashDotDot";
594
+ case "slantDashDot":
595
+ return "slantDashDot";
596
+ case "thin":
597
+ // openpyxl/Excel's "thin" is the regular 1px border. The previous
598
+ // mapping returned Excel's "hair" (the lightest sub-1px border),
599
+ // which produced near-invisible borders for any caller — including
600
+ // athena-openpyxl — that explicitly asks for `Side(style="thin")`.
601
+ return "thin";
602
+ case "solid":
603
+ default:
604
+ // rowsncolumns' generic "solid" remains aliased to Excel's "thin"
605
+ // (the regular 1px border) when no explicit thickness is requested.
606
+ return "thin";
607
+ }
608
+ };
609
+ const serializeBorderEdge = (edge) => {
610
+ if (!edge)
611
+ return "";
612
+ return `${edge.style || ""}:${serializeColor(edge.color)}`;
613
+ };
614
+ const serializeBorderEdgeXml = (edge, side) => {
615
+ if (!edge?.style) {
616
+ return `<${side}/>`;
617
+ }
618
+ const color = serializeColorXml(edge.color);
619
+ return `<${side} style="${edge.style}">${color ? `<color ${color}/>` : ""}</${side}>`;
620
+ };
621
+ const serializeColor = (color) => {
622
+ if (!color)
623
+ return "";
624
+ if (typeof color === "string") {
625
+ return normalizeHex(color) ?? "";
626
+ }
627
+ return `theme${color.theme}:${color.tint ?? ""}`;
628
+ };
629
+ const serializeColorXml = (color) => {
630
+ if (!color)
631
+ return undefined;
632
+ if (typeof color === "string") {
633
+ const hex = normalizeHex(color);
634
+ return hex ? `rgb="${hex}"` : undefined;
635
+ }
636
+ const tintAttr = typeof color.tint === "number" ? ` tint="${color.tint}"` : "";
637
+ return `theme="${color.theme}"${tintAttr}`;
638
+ };
639
+ // Excel <name val=""/> expects a single font family ≤31 chars. CSS font stacks
640
+ // (`InterVariable, system-ui, sans-serif`) make Excel reject the entire styles
641
+ // part. Take the first family and strip surrounding quotes.
642
+ const sanitizeFontName = (name) => {
643
+ if (!name || typeof name !== "string")
644
+ return undefined;
645
+ const first = name.split(",")[0].trim().replace(/^['"]|['"]$/g, "");
646
+ if (!first)
647
+ return undefined;
648
+ return first.length > 31 ? first.slice(0, 31) : first;
649
+ };
650
+ const HEX6_RE = /^[0-9A-Fa-f]{6}$/;
651
+ const HEX8_RE = /^[0-9A-Fa-f]{8}$/;
652
+ const RGB_FUNC_RE = /^rgba?\s*\(\s*(\d+)\s*[, ]\s*(\d+)\s*[, ]\s*(\d+)(?:\s*[, /]\s*([\d.]+))?\s*\)$/i;
653
+ // Returns AARRGGBB hex for any recognized color string; undefined otherwise.
654
+ // Excel rejects the whole styles.xml if rgb="" contains non-hex or unescaped
655
+ // quotes (which CSS strings like `font-family:"Times New Roman"` would produce).
656
+ const normalizeHex = (color) => {
657
+ if (typeof color !== "string")
658
+ return undefined;
659
+ const trimmed = color.trim();
660
+ if (!trimmed)
661
+ return undefined;
662
+ const noHash = trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
663
+ if (HEX8_RE.test(noHash))
664
+ return noHash.toUpperCase();
665
+ if (HEX6_RE.test(noHash))
666
+ return `FF${noHash.toUpperCase()}`;
667
+ const m = RGB_FUNC_RE.exec(trimmed);
668
+ if (m) {
669
+ const toHex = (s) => {
670
+ const n = Math.max(0, Math.min(255, parseInt(s, 10) | 0));
671
+ return n.toString(16).padStart(2, "0").toUpperCase();
672
+ };
673
+ const alpha = m[4] != null
674
+ ? Math.max(0, Math.min(255, Math.round(parseFloat(m[4]) * 255)))
675
+ .toString(16)
676
+ .padStart(2, "0")
677
+ .toUpperCase()
678
+ : "FF";
679
+ return `${alpha}${toHex(m[1])}${toHex(m[2])}${toHex(m[3])}`;
680
+ }
681
+ return undefined;
682
+ };
683
+ const serializeAlignment = (record) => {
684
+ const attrs = [];
685
+ if (record.horizontalAlignment) {
686
+ attrs.push(`horizontal="${record.horizontalAlignment}"`);
687
+ }
688
+ if (record.verticalAlignment) {
689
+ attrs.push(`vertical="${record.verticalAlignment}"`);
690
+ }
691
+ if (record.wrapText) {
692
+ attrs.push(`wrapText="1"`);
693
+ }
694
+ if (typeof record.indent === "number" &&
695
+ Number.isFinite(record.indent) &&
696
+ record.indent > 0) {
697
+ attrs.push(`indent="${record.indent}"`);
698
+ }
699
+ if (typeof record.relativeIndent === "number" &&
700
+ Number.isFinite(record.relativeIndent) &&
701
+ record.relativeIndent !== 0) {
702
+ attrs.push(`relativeIndent="${record.relativeIndent}"`);
703
+ }
704
+ if (record.textRotation !== undefined && record.textRotation !== null) {
705
+ // Excel encodes "vertical (stacked)" text as the magic value 255.
706
+ const rotation = record.textRotation === "vertical" ? 255 : record.textRotation;
707
+ if (Number.isFinite(rotation) && rotation !== 0) {
708
+ attrs.push(`textRotation="${rotation}"`);
709
+ }
710
+ }
711
+ if (record.shrinkToFit) {
712
+ attrs.push(`shrinkToFit="1"`);
713
+ }
714
+ if (!attrs.length)
715
+ return "";
716
+ return `<alignment ${attrs.join(" ")}/>`;
717
+ };
718
+ const serializeXf = (record) => {
719
+ return [
720
+ record.numFmtId,
721
+ record.fontId,
722
+ record.fillId,
723
+ record.borderId,
724
+ record.wrapText ? 1 : 0,
725
+ record.horizontalAlignment ?? "",
726
+ record.verticalAlignment ?? "",
727
+ record.indent ?? "",
728
+ record.relativeIndent ?? "",
729
+ record.textRotation ?? "",
730
+ record.shrinkToFit ? 1 : 0,
731
+ record.protectionLocked === false ? 0 : "",
732
+ record.protectionHidden === true ? 1 : "",
733
+ ].join(":");
734
+ };
735
+ const serializeProtection = (record) => {
736
+ const attrs = [];
737
+ // Only emit when the value deviates from Excel's defaults (locked=true,
738
+ // hidden=false) — otherwise we'd flag every xf as having protection.
739
+ if (record.protectionLocked === false) {
740
+ attrs.push(`locked="0"`);
741
+ }
742
+ if (record.protectionHidden === true) {
743
+ attrs.push(`hidden="1"`);
744
+ }
745
+ if (!attrs.length)
746
+ return "";
747
+ return `<protection ${attrs.join(" ")}/>`;
748
+ };
749
+ const normalizeHorizontalAlignment = (value) => {
750
+ const allowed = new Set([
751
+ "general",
752
+ "left",
753
+ "center",
754
+ "right",
755
+ "fill",
756
+ "justify",
757
+ "centerContinuous",
758
+ "distributed",
759
+ ]);
760
+ if (!value)
761
+ return undefined;
762
+ return allowed.has(value) ? value : undefined;
763
+ };
764
+ const normalizeVerticalAlignment = (value) => {
765
+ if (!value)
766
+ return undefined;
767
+ if (value === "middle")
768
+ return "center";
769
+ const allowed = new Set([
770
+ "top",
771
+ "center",
772
+ "bottom",
773
+ "justify",
774
+ "distributed",
775
+ ]);
776
+ return allowed.has(value) ? value : undefined;
777
+ };
778
+ const XML_DECLARATION = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`;
779
+ const WORKSHEET_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
780
+ const normalizeFormat = (format, cellXfs) => {
781
+ if (format && isStyleReference(format)) {
782
+ const styleId = format.sid ?? format.styleId;
783
+ if (styleId) {
784
+ return cellXfs?.get(styleId);
785
+ }
786
+ return undefined;
787
+ }
788
+ return format ?? undefined;
789
+ };
790
+ const escapeXml = (value) => value
791
+ .replace(/&/g, "&amp;")
792
+ .replace(/</g, "&lt;")
793
+ .replace(/>/g, "&gt;")
794
+ .replace(/"/g, "&quot;")
795
+ .replace(/'/g, "&apos;");