@cj-tech-master/excelts 9.2.1 → 9.3.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 (383) hide show
  1. package/README.md +25 -2
  2. package/README_zh.md +29 -6
  3. package/dist/browser/index.browser.d.ts +1 -1
  4. package/dist/browser/index.browser.js +4 -0
  5. package/dist/browser/index.d.ts +1 -1
  6. package/dist/browser/index.js +4 -0
  7. package/dist/browser/modules/excel/cell.d.ts +17 -3
  8. package/dist/browser/modules/excel/cell.js +170 -22
  9. package/dist/browser/modules/excel/defined-names.d.ts +96 -1
  10. package/dist/browser/modules/excel/defined-names.js +411 -21
  11. package/dist/browser/modules/excel/image.d.ts +11 -0
  12. package/dist/browser/modules/excel/image.js +24 -1
  13. package/dist/browser/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
  14. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +14 -0
  15. package/dist/browser/modules/excel/stream/workbook-reader.d.ts +2 -1
  16. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
  17. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +48 -1
  18. package/dist/browser/modules/excel/stream/workbook-writer.d.ts +3 -2
  19. package/dist/browser/modules/excel/stream/worksheet-reader.js +17 -1
  20. package/dist/browser/modules/excel/stream/worksheet-writer.d.ts +39 -6
  21. package/dist/browser/modules/excel/stream/worksheet-writer.js +45 -5
  22. package/dist/browser/modules/excel/table.js +15 -2
  23. package/dist/browser/modules/excel/types.d.ts +133 -2
  24. package/dist/browser/modules/excel/utils/col-cache.d.ts +1 -0
  25. package/dist/browser/modules/excel/utils/col-cache.js +15 -0
  26. package/dist/browser/modules/excel/utils/drawing-utils.d.ts +3 -3
  27. package/dist/browser/modules/excel/utils/drawing-utils.js +4 -0
  28. package/dist/browser/modules/excel/utils/external-link-formula.d.ts +76 -0
  29. package/dist/browser/modules/excel/utils/external-link-formula.js +208 -0
  30. package/dist/browser/modules/excel/utils/iterate-stream.d.ts +9 -3
  31. package/dist/browser/modules/excel/utils/iterate-stream.js +3 -1
  32. package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +19 -0
  33. package/dist/browser/modules/excel/utils/ooxml-paths.js +37 -2
  34. package/dist/browser/modules/excel/utils/shared-strings.d.ts +8 -3
  35. package/dist/browser/modules/excel/utils/shared-strings.js +21 -2
  36. package/dist/browser/modules/excel/utils/workbook-protection.d.ts +30 -0
  37. package/dist/browser/modules/excel/utils/workbook-protection.js +30 -0
  38. package/dist/browser/modules/excel/workbook.browser.d.ts +257 -6
  39. package/dist/browser/modules/excel/workbook.browser.js +318 -34
  40. package/dist/browser/modules/excel/workbook.d.ts +1 -1
  41. package/dist/browser/modules/excel/worksheet.d.ts +3 -1
  42. package/dist/browser/modules/excel/worksheet.js +21 -2
  43. package/dist/browser/modules/excel/xlsx/rel-type.d.ts +15 -0
  44. package/dist/browser/modules/excel/xlsx/rel-type.js +16 -1
  45. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
  46. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  47. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
  48. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
  49. package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
  50. package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
  51. package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
  52. package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  53. package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
  54. package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
  55. package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  56. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
  57. package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
  58. package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
  59. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
  60. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
  61. package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  62. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  63. package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
  64. package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  65. package/dist/browser/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  66. package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
  67. package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
  68. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  69. package/dist/browser/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  70. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
  71. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +410 -20
  72. package/dist/browser/modules/excel/xlsx/xlsx.d.ts +7 -4
  73. package/dist/browser/modules/excel/xlsx/xlsx.js +4 -5
  74. package/dist/browser/modules/formula/compile/address-utils.d.ts +62 -0
  75. package/dist/browser/modules/formula/compile/address-utils.js +83 -0
  76. package/dist/browser/modules/formula/compile/binder.d.ts +42 -0
  77. package/dist/browser/modules/formula/compile/binder.js +487 -0
  78. package/dist/browser/modules/formula/compile/bound-ast.d.ts +230 -0
  79. package/dist/browser/modules/formula/compile/bound-ast.js +80 -0
  80. package/dist/browser/modules/formula/compile/compiled-formula.d.ts +137 -0
  81. package/dist/browser/modules/formula/compile/compiled-formula.js +383 -0
  82. package/dist/browser/modules/formula/compile/dependency-analysis.d.ts +93 -0
  83. package/dist/browser/modules/formula/compile/dependency-analysis.js +432 -0
  84. package/dist/browser/modules/formula/compile/structured-ref-utils.d.ts +93 -0
  85. package/dist/browser/modules/formula/compile/structured-ref-utils.js +136 -0
  86. package/dist/browser/modules/formula/default-syntax-probe.d.ts +79 -0
  87. package/dist/browser/modules/formula/default-syntax-probe.js +83 -0
  88. package/dist/browser/modules/formula/functions/_date-context.d.ts +4 -0
  89. package/dist/browser/modules/formula/functions/_date-context.js +29 -0
  90. package/dist/browser/modules/formula/functions/_shared.d.ts +121 -0
  91. package/dist/browser/modules/formula/functions/_shared.js +381 -0
  92. package/dist/browser/modules/formula/functions/conditional.d.ts +27 -0
  93. package/dist/browser/modules/formula/functions/conditional.js +343 -0
  94. package/dist/browser/modules/formula/functions/database.d.ts +37 -0
  95. package/dist/browser/modules/formula/functions/database.js +274 -0
  96. package/dist/browser/modules/formula/functions/date.d.ts +61 -0
  97. package/dist/browser/modules/formula/functions/date.js +855 -0
  98. package/dist/browser/modules/formula/functions/dynamic-array.d.ts +23 -0
  99. package/dist/browser/modules/formula/functions/dynamic-array.js +860 -0
  100. package/dist/browser/modules/formula/functions/engineering.d.ts +57 -0
  101. package/dist/browser/modules/formula/functions/engineering.js +1128 -0
  102. package/dist/browser/modules/formula/functions/financial.d.ts +202 -0
  103. package/dist/browser/modules/formula/functions/financial.js +2296 -0
  104. package/dist/browser/modules/formula/functions/lookup.d.ts +18 -0
  105. package/dist/browser/modules/formula/functions/lookup.js +886 -0
  106. package/dist/browser/modules/formula/functions/math.d.ts +114 -0
  107. package/dist/browser/modules/formula/functions/math.js +1406 -0
  108. package/dist/browser/modules/formula/functions/statistical.d.ts +193 -0
  109. package/dist/browser/modules/formula/functions/statistical.js +3390 -0
  110. package/dist/browser/modules/formula/functions/text.d.ts +86 -0
  111. package/dist/browser/modules/formula/functions/text.js +1845 -0
  112. package/dist/browser/modules/formula/host-registry.d.ts +53 -0
  113. package/dist/browser/modules/formula/host-registry.js +69 -0
  114. package/dist/browser/modules/formula/index.d.ts +39 -0
  115. package/dist/browser/modules/formula/index.js +49 -0
  116. package/dist/browser/modules/formula/install.d.ts +62 -0
  117. package/dist/browser/modules/formula/install.js +88 -0
  118. package/dist/browser/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
  119. package/dist/browser/modules/formula/integration/apply-writeback-plan.js +210 -0
  120. package/dist/browser/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
  121. package/dist/browser/modules/formula/integration/calculate-formulas-impl.js +616 -0
  122. package/dist/browser/modules/formula/integration/calculate-formulas.d.ts +67 -0
  123. package/dist/browser/modules/formula/integration/calculate-formulas.js +68 -0
  124. package/dist/browser/modules/formula/integration/formula-instance.d.ts +64 -0
  125. package/dist/browser/modules/formula/integration/formula-instance.js +79 -0
  126. package/dist/browser/modules/formula/integration/workbook-adapter.d.ts +26 -0
  127. package/dist/browser/modules/formula/integration/workbook-adapter.js +324 -0
  128. package/dist/browser/modules/formula/integration/workbook-snapshot.d.ts +267 -0
  129. package/dist/browser/modules/formula/integration/workbook-snapshot.js +77 -0
  130. package/dist/browser/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
  131. package/dist/browser/modules/formula/materialize/build-writeback-plan.js +473 -0
  132. package/dist/browser/modules/formula/materialize/spill-engine.d.ts +9 -0
  133. package/dist/browser/modules/formula/materialize/spill-engine.js +38 -0
  134. package/dist/browser/modules/formula/materialize/types.d.ts +179 -0
  135. package/dist/browser/modules/formula/materialize/types.js +29 -0
  136. package/dist/browser/modules/formula/materialize/writeback-plan.d.ts +167 -0
  137. package/dist/browser/modules/formula/materialize/writeback-plan.js +27 -0
  138. package/dist/browser/modules/formula/runtime/evaluator.d.ts +151 -0
  139. package/dist/browser/modules/formula/runtime/evaluator.js +2291 -0
  140. package/dist/browser/modules/formula/runtime/function-registry.d.ts +47 -0
  141. package/dist/browser/modules/formula/runtime/function-registry.js +840 -0
  142. package/dist/browser/modules/formula/runtime/values.d.ts +211 -0
  143. package/dist/browser/modules/formula/runtime/values.js +385 -0
  144. package/dist/browser/modules/formula/syntax/ast.d.ts +129 -0
  145. package/dist/browser/modules/formula/syntax/ast.js +28 -0
  146. package/dist/browser/modules/formula/syntax/parser.d.ts +18 -0
  147. package/dist/browser/modules/formula/syntax/parser.js +439 -0
  148. package/dist/browser/modules/formula/syntax/token-types.d.ts +153 -0
  149. package/dist/browser/modules/formula/syntax/token-types.js +59 -0
  150. package/dist/browser/modules/formula/syntax/tokenizer.d.ts +10 -0
  151. package/dist/browser/modules/formula/syntax/tokenizer.js +1074 -0
  152. package/dist/browser/modules/pdf/excel-bridge.js +9 -0
  153. package/dist/cjs/index.js +4 -0
  154. package/dist/cjs/modules/excel/cell.js +170 -22
  155. package/dist/cjs/modules/excel/defined-names.js +411 -21
  156. package/dist/cjs/modules/excel/image.js +24 -1
  157. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +14 -0
  158. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +48 -1
  159. package/dist/cjs/modules/excel/stream/worksheet-reader.js +17 -1
  160. package/dist/cjs/modules/excel/stream/worksheet-writer.js +45 -5
  161. package/dist/cjs/modules/excel/table.js +15 -2
  162. package/dist/cjs/modules/excel/utils/col-cache.js +15 -0
  163. package/dist/cjs/modules/excel/utils/drawing-utils.js +4 -0
  164. package/dist/cjs/modules/excel/utils/external-link-formula.js +212 -0
  165. package/dist/cjs/modules/excel/utils/iterate-stream.js +3 -1
  166. package/dist/cjs/modules/excel/utils/ooxml-paths.js +42 -2
  167. package/dist/cjs/modules/excel/utils/shared-strings.js +21 -2
  168. package/dist/cjs/modules/excel/utils/workbook-protection.js +33 -0
  169. package/dist/cjs/modules/excel/workbook.browser.js +318 -34
  170. package/dist/cjs/modules/excel/worksheet.js +20 -1
  171. package/dist/cjs/modules/excel/xlsx/rel-type.js +16 -1
  172. package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  173. package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +333 -0
  174. package/dist/cjs/modules/excel/xlsx/xform/book/external-reference-xform.js +27 -0
  175. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  176. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-protection-xform.js +69 -0
  177. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  178. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +18 -0
  179. package/dist/cjs/modules/excel/xlsx/xform/core/metadata-xform.js +161 -0
  180. package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +108 -0
  181. package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  182. package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  183. package/dist/cjs/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  184. package/dist/cjs/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  185. package/dist/cjs/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +83 -0
  186. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  187. package/dist/cjs/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  188. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +408 -18
  189. package/dist/cjs/modules/excel/xlsx/xlsx.js +4 -5
  190. package/dist/cjs/modules/formula/compile/address-utils.js +89 -0
  191. package/dist/cjs/modules/formula/compile/binder.js +489 -0
  192. package/dist/cjs/modules/formula/compile/bound-ast.js +68 -0
  193. package/dist/cjs/modules/formula/compile/compiled-formula.js +387 -0
  194. package/dist/cjs/modules/formula/compile/dependency-analysis.js +437 -0
  195. package/dist/cjs/modules/formula/compile/structured-ref-utils.js +141 -0
  196. package/dist/cjs/modules/formula/default-syntax-probe.js +87 -0
  197. package/dist/cjs/modules/formula/functions/_date-context.js +33 -0
  198. package/dist/cjs/modules/formula/functions/_shared.js +396 -0
  199. package/dist/cjs/modules/formula/functions/conditional.js +354 -0
  200. package/dist/cjs/modules/formula/functions/database.js +288 -0
  201. package/dist/cjs/modules/formula/functions/date.js +883 -0
  202. package/dist/cjs/modules/formula/functions/dynamic-array.js +881 -0
  203. package/dist/cjs/modules/formula/functions/engineering.js +1183 -0
  204. package/dist/cjs/modules/formula/functions/financial.js +2348 -0
  205. package/dist/cjs/modules/formula/functions/lookup.js +902 -0
  206. package/dist/cjs/modules/formula/functions/math.js +1487 -0
  207. package/dist/cjs/modules/formula/functions/statistical.js +3488 -0
  208. package/dist/cjs/modules/formula/functions/text.js +1889 -0
  209. package/dist/cjs/modules/formula/host-registry.js +75 -0
  210. package/dist/cjs/modules/formula/index.js +58 -0
  211. package/dist/cjs/modules/formula/install.js +93 -0
  212. package/dist/cjs/modules/formula/integration/apply-writeback-plan.js +213 -0
  213. package/dist/cjs/modules/formula/integration/calculate-formulas-impl.js +619 -0
  214. package/dist/cjs/modules/formula/integration/calculate-formulas.js +71 -0
  215. package/dist/cjs/modules/formula/integration/formula-instance.js +82 -0
  216. package/dist/cjs/modules/formula/integration/workbook-adapter.js +327 -0
  217. package/dist/cjs/modules/formula/integration/workbook-snapshot.js +84 -0
  218. package/dist/cjs/modules/formula/materialize/build-writeback-plan.js +475 -0
  219. package/dist/cjs/modules/formula/materialize/spill-engine.js +42 -0
  220. package/dist/cjs/modules/formula/materialize/types.js +32 -0
  221. package/dist/cjs/modules/formula/materialize/writeback-plan.js +28 -0
  222. package/dist/cjs/modules/formula/runtime/evaluator.js +2298 -0
  223. package/dist/cjs/modules/formula/runtime/function-registry.js +846 -0
  224. package/dist/cjs/modules/formula/runtime/values.js +385 -0
  225. package/dist/cjs/modules/formula/syntax/ast.js +8 -0
  226. package/dist/cjs/modules/formula/syntax/parser.js +440 -0
  227. package/dist/cjs/modules/formula/syntax/token-types.js +32 -0
  228. package/dist/cjs/modules/formula/syntax/tokenizer.js +1076 -0
  229. package/dist/cjs/modules/pdf/excel-bridge.js +9 -0
  230. package/dist/esm/index.browser.js +4 -0
  231. package/dist/esm/index.js +4 -0
  232. package/dist/esm/modules/excel/cell.js +170 -22
  233. package/dist/esm/modules/excel/defined-names.js +411 -21
  234. package/dist/esm/modules/excel/image.js +24 -1
  235. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +14 -0
  236. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +48 -1
  237. package/dist/esm/modules/excel/stream/worksheet-reader.js +17 -1
  238. package/dist/esm/modules/excel/stream/worksheet-writer.js +45 -5
  239. package/dist/esm/modules/excel/table.js +15 -2
  240. package/dist/esm/modules/excel/utils/col-cache.js +15 -0
  241. package/dist/esm/modules/excel/utils/drawing-utils.js +4 -0
  242. package/dist/esm/modules/excel/utils/external-link-formula.js +208 -0
  243. package/dist/esm/modules/excel/utils/iterate-stream.js +3 -1
  244. package/dist/esm/modules/excel/utils/ooxml-paths.js +37 -2
  245. package/dist/esm/modules/excel/utils/shared-strings.js +21 -2
  246. package/dist/esm/modules/excel/utils/workbook-protection.js +30 -0
  247. package/dist/esm/modules/excel/workbook.browser.js +318 -34
  248. package/dist/esm/modules/excel/worksheet.js +21 -2
  249. package/dist/esm/modules/excel/xlsx/rel-type.js +16 -1
  250. package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  251. package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
  252. package/dist/esm/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
  253. package/dist/esm/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  254. package/dist/esm/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
  255. package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  256. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
  257. package/dist/esm/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
  258. package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
  259. package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  260. package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  261. package/dist/esm/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  262. package/dist/esm/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  263. package/dist/esm/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
  264. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  265. package/dist/esm/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  266. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +410 -20
  267. package/dist/esm/modules/excel/xlsx/xlsx.js +4 -5
  268. package/dist/esm/modules/formula/compile/address-utils.js +83 -0
  269. package/dist/esm/modules/formula/compile/binder.js +487 -0
  270. package/dist/esm/modules/formula/compile/bound-ast.js +80 -0
  271. package/dist/esm/modules/formula/compile/compiled-formula.js +383 -0
  272. package/dist/esm/modules/formula/compile/dependency-analysis.js +432 -0
  273. package/dist/esm/modules/formula/compile/structured-ref-utils.js +136 -0
  274. package/dist/esm/modules/formula/default-syntax-probe.js +83 -0
  275. package/dist/esm/modules/formula/functions/_date-context.js +29 -0
  276. package/dist/esm/modules/formula/functions/_shared.js +381 -0
  277. package/dist/esm/modules/formula/functions/conditional.js +343 -0
  278. package/dist/esm/modules/formula/functions/database.js +274 -0
  279. package/dist/esm/modules/formula/functions/date.js +855 -0
  280. package/dist/esm/modules/formula/functions/dynamic-array.js +860 -0
  281. package/dist/esm/modules/formula/functions/engineering.js +1128 -0
  282. package/dist/esm/modules/formula/functions/financial.js +2296 -0
  283. package/dist/esm/modules/formula/functions/lookup.js +886 -0
  284. package/dist/esm/modules/formula/functions/math.js +1406 -0
  285. package/dist/esm/modules/formula/functions/statistical.js +3390 -0
  286. package/dist/esm/modules/formula/functions/text.js +1845 -0
  287. package/dist/esm/modules/formula/host-registry.js +69 -0
  288. package/dist/esm/modules/formula/index.js +49 -0
  289. package/dist/esm/modules/formula/install.js +88 -0
  290. package/dist/esm/modules/formula/integration/apply-writeback-plan.js +210 -0
  291. package/dist/esm/modules/formula/integration/calculate-formulas-impl.js +616 -0
  292. package/dist/esm/modules/formula/integration/calculate-formulas.js +68 -0
  293. package/dist/esm/modules/formula/integration/formula-instance.js +79 -0
  294. package/dist/esm/modules/formula/integration/workbook-adapter.js +324 -0
  295. package/dist/esm/modules/formula/integration/workbook-snapshot.js +77 -0
  296. package/dist/esm/modules/formula/materialize/build-writeback-plan.js +473 -0
  297. package/dist/esm/modules/formula/materialize/spill-engine.js +38 -0
  298. package/dist/esm/modules/formula/materialize/types.js +29 -0
  299. package/dist/esm/modules/formula/materialize/writeback-plan.js +27 -0
  300. package/dist/esm/modules/formula/runtime/evaluator.js +2291 -0
  301. package/dist/esm/modules/formula/runtime/function-registry.js +840 -0
  302. package/dist/esm/modules/formula/runtime/values.js +385 -0
  303. package/dist/esm/modules/formula/syntax/ast.js +28 -0
  304. package/dist/esm/modules/formula/syntax/parser.js +439 -0
  305. package/dist/esm/modules/formula/syntax/token-types.js +59 -0
  306. package/dist/esm/modules/formula/syntax/tokenizer.js +1074 -0
  307. package/dist/esm/modules/pdf/excel-bridge.js +9 -0
  308. package/dist/iife/excelts.iife.js +2302 -373
  309. package/dist/iife/excelts.iife.js.map +1 -1
  310. package/dist/iife/excelts.iife.min.js +34 -34
  311. package/dist/types/index.browser.d.ts +1 -1
  312. package/dist/types/index.d.ts +1 -1
  313. package/dist/types/modules/excel/cell.d.ts +17 -3
  314. package/dist/types/modules/excel/defined-names.d.ts +96 -1
  315. package/dist/types/modules/excel/image.d.ts +11 -0
  316. package/dist/types/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
  317. package/dist/types/modules/excel/stream/workbook-reader.d.ts +2 -1
  318. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
  319. package/dist/types/modules/excel/stream/workbook-writer.d.ts +3 -2
  320. package/dist/types/modules/excel/stream/worksheet-writer.d.ts +39 -6
  321. package/dist/types/modules/excel/types.d.ts +133 -2
  322. package/dist/types/modules/excel/utils/col-cache.d.ts +1 -0
  323. package/dist/types/modules/excel/utils/drawing-utils.d.ts +3 -3
  324. package/dist/types/modules/excel/utils/external-link-formula.d.ts +76 -0
  325. package/dist/types/modules/excel/utils/iterate-stream.d.ts +9 -3
  326. package/dist/types/modules/excel/utils/ooxml-paths.d.ts +19 -0
  327. package/dist/types/modules/excel/utils/shared-strings.d.ts +8 -3
  328. package/dist/types/modules/excel/utils/workbook-protection.d.ts +30 -0
  329. package/dist/types/modules/excel/workbook.browser.d.ts +257 -6
  330. package/dist/types/modules/excel/workbook.d.ts +1 -1
  331. package/dist/types/modules/excel/worksheet.d.ts +3 -1
  332. package/dist/types/modules/excel/xlsx/rel-type.d.ts +15 -0
  333. package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
  334. package/dist/types/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
  335. package/dist/types/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
  336. package/dist/types/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
  337. package/dist/types/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
  338. package/dist/types/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
  339. package/dist/types/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
  340. package/dist/types/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
  341. package/dist/types/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
  342. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
  343. package/dist/types/modules/excel/xlsx/xlsx.d.ts +7 -4
  344. package/dist/types/modules/formula/compile/address-utils.d.ts +62 -0
  345. package/dist/types/modules/formula/compile/binder.d.ts +42 -0
  346. package/dist/types/modules/formula/compile/bound-ast.d.ts +230 -0
  347. package/dist/types/modules/formula/compile/compiled-formula.d.ts +137 -0
  348. package/dist/types/modules/formula/compile/dependency-analysis.d.ts +93 -0
  349. package/dist/types/modules/formula/compile/structured-ref-utils.d.ts +93 -0
  350. package/dist/types/modules/formula/default-syntax-probe.d.ts +79 -0
  351. package/dist/types/modules/formula/functions/_date-context.d.ts +4 -0
  352. package/dist/types/modules/formula/functions/_shared.d.ts +121 -0
  353. package/dist/types/modules/formula/functions/conditional.d.ts +27 -0
  354. package/dist/types/modules/formula/functions/database.d.ts +37 -0
  355. package/dist/types/modules/formula/functions/date.d.ts +61 -0
  356. package/dist/types/modules/formula/functions/dynamic-array.d.ts +23 -0
  357. package/dist/types/modules/formula/functions/engineering.d.ts +57 -0
  358. package/dist/types/modules/formula/functions/financial.d.ts +202 -0
  359. package/dist/types/modules/formula/functions/lookup.d.ts +18 -0
  360. package/dist/types/modules/formula/functions/math.d.ts +114 -0
  361. package/dist/types/modules/formula/functions/statistical.d.ts +193 -0
  362. package/dist/types/modules/formula/functions/text.d.ts +86 -0
  363. package/dist/types/modules/formula/host-registry.d.ts +53 -0
  364. package/dist/types/modules/formula/index.d.ts +39 -0
  365. package/dist/types/modules/formula/install.d.ts +62 -0
  366. package/dist/types/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
  367. package/dist/types/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
  368. package/dist/types/modules/formula/integration/calculate-formulas.d.ts +67 -0
  369. package/dist/types/modules/formula/integration/formula-instance.d.ts +64 -0
  370. package/dist/types/modules/formula/integration/workbook-adapter.d.ts +26 -0
  371. package/dist/types/modules/formula/integration/workbook-snapshot.d.ts +267 -0
  372. package/dist/types/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
  373. package/dist/types/modules/formula/materialize/spill-engine.d.ts +9 -0
  374. package/dist/types/modules/formula/materialize/types.d.ts +179 -0
  375. package/dist/types/modules/formula/materialize/writeback-plan.d.ts +167 -0
  376. package/dist/types/modules/formula/runtime/evaluator.d.ts +151 -0
  377. package/dist/types/modules/formula/runtime/function-registry.d.ts +47 -0
  378. package/dist/types/modules/formula/runtime/values.d.ts +211 -0
  379. package/dist/types/modules/formula/syntax/ast.d.ts +129 -0
  380. package/dist/types/modules/formula/syntax/parser.d.ts +18 -0
  381. package/dist/types/modules/formula/syntax/token-types.d.ts +153 -0
  382. package/dist/types/modules/formula/syntax/tokenizer.d.ts +10 -0
  383. package/package.json +28 -28
@@ -39,6 +39,60 @@ function getEffectiveCellType(cell) {
39
39
  return cell.type;
40
40
  }
41
41
  }
42
+ /**
43
+ * Extract the display form of a hyperlink cell value that came either from
44
+ * a shared-string rich-text payload (`{ richText: [...] }`) or from a
45
+ * plain scalar.
46
+ *
47
+ * Input comes from the XML parser (`raw: unknown`), so every nested value is
48
+ * treated defensively — the public `RichText` shape is only produced after
49
+ * runtime validation, never asserted.
50
+ *
51
+ * Returns:
52
+ * - `text`: always a string (flattened rich-text or `String(raw)`)
53
+ * - `richText`: preserved if the source was a rich-text payload, else undefined
54
+ *
55
+ * This keeps the CellHyperlinkValue.text: string public contract intact while
56
+ * also letting the Hyperlink value class retain the formatted runs
57
+ * (see https://github.com/cjnoname/excelts/issues/142).
58
+ */
59
+ function extractHyperlinkDisplay(raw) {
60
+ if (raw === null || raw === undefined) {
61
+ return { text: "" };
62
+ }
63
+ if (typeof raw === "string") {
64
+ return { text: raw };
65
+ }
66
+ if (typeof raw === "number" || typeof raw === "boolean") {
67
+ return { text: String(raw) };
68
+ }
69
+ if (typeof raw === "object") {
70
+ const obj = raw;
71
+ if (Array.isArray(obj.richText)) {
72
+ // Empty runs array carries no content — emit empty display text rather
73
+ // than falling through to `String(raw)` which would produce
74
+ // "[object Object]".
75
+ if (obj.richText.length === 0) {
76
+ return { text: "" };
77
+ }
78
+ const runs = obj.richText.map(rawRun => {
79
+ const run = rawRun;
80
+ const normalized = {
81
+ text: typeof run?.text === "string" ? run.text : ""
82
+ };
83
+ if (run?.font !== null && typeof run?.font === "object") {
84
+ normalized.font = run.font;
85
+ }
86
+ return normalized;
87
+ });
88
+ return { text: runs.map(r => r.text).join(""), richText: runs };
89
+ }
90
+ if (typeof obj.error === "string") {
91
+ return { text: obj.error };
92
+ }
93
+ }
94
+ return { text: String(raw) };
95
+ }
42
96
  class CellXform extends BaseXform {
43
97
  constructor() {
44
98
  super();
@@ -68,8 +122,15 @@ class CellXform extends BaseXform {
68
122
  }
69
123
  break;
70
124
  case Enums.ValueType.Hyperlink:
71
- if (options.sharedStrings && model.text !== undefined && model.text !== null) {
72
- model.ssId = options.sharedStrings.add(model.text);
125
+ if (options.sharedStrings) {
126
+ // Prefer rich-text payload when present so formatted display
127
+ // survives a write. Fall back to plain text otherwise.
128
+ if (Array.isArray(model.richText) && model.richText.length > 0) {
129
+ model.ssId = options.sharedStrings.add({ richText: model.richText });
130
+ }
131
+ else if (model.text !== undefined && model.text !== null) {
132
+ model.ssId = options.sharedStrings.add(model.text);
133
+ }
73
134
  }
74
135
  options.hyperlinks.push({
75
136
  address: model.address,
@@ -85,6 +146,22 @@ class CellXform extends BaseXform {
85
146
  // in case valueType is date
86
147
  model.date1904 = true;
87
148
  }
149
+ // Convert isDynamicArray flag to cm attribute for XML rendering.
150
+ // All dynamic array cells share cm=1 pointing to a single XLDAPR metadata record.
151
+ if (model.isDynamicArray) {
152
+ model.cm = 1;
153
+ }
154
+ // A formula cell may also carry an attached hyperlink (e.g. when the
155
+ // model came from another writer or was constructed without going
156
+ // through the load-side reconcile that promotes type=Formula to
157
+ // type=Hyperlink). Re-emit the <hyperlink> element so it survives.
158
+ if (model.hyperlink) {
159
+ options.hyperlinks.push({
160
+ address: model.address,
161
+ target: model.hyperlink,
162
+ tooltip: model.tooltip
163
+ });
164
+ }
88
165
  if (model.shareType === "shared") {
89
166
  model.si = options.siFormulae++;
90
167
  }
@@ -180,6 +257,10 @@ class CellXform extends BaseXform {
180
257
  if (model.styleId) {
181
258
  xmlStream.addAttribute("s", model.styleId);
182
259
  }
260
+ // Dynamic array formulas require the cm attribute linking to xl/metadata.xml
261
+ if (model.cm) {
262
+ xmlStream.addAttribute("cm", model.cm);
263
+ }
183
264
  switch (model.type) {
184
265
  case Enums.ValueType.Null:
185
266
  break;
@@ -222,10 +303,28 @@ class CellXform extends BaseXform {
222
303
  xmlStream.leafNode("v", null, dateToExcel(model.value, model.date1904));
223
304
  break;
224
305
  case Enums.ValueType.Hyperlink:
225
- if (model.ssId !== undefined) {
306
+ // A hyperlink cell may also carry a formula (loaded from XLSX where
307
+ // a `<hyperlink>` entry shares its address with a formula `<c>`).
308
+ // Render the formula in that case so the underlying expression
309
+ // survives the round-trip; the <hyperlink> element is emitted
310
+ // separately via options.hyperlinks (collected in prepare).
311
+ if (model.formula || model.sharedFormula) {
312
+ this.renderFormula(xmlStream, model);
313
+ }
314
+ else if (model.ssId !== undefined) {
226
315
  xmlStream.addAttribute("t", "s");
227
316
  xmlStream.leafNode("v", null, model.ssId);
228
317
  }
318
+ else if (Array.isArray(model.richText) && model.richText.length > 0) {
319
+ // Inline rich-text representation — used when shared strings are
320
+ // disabled (some streaming configurations).
321
+ xmlStream.addAttribute("t", "inlineStr");
322
+ xmlStream.openNode("is");
323
+ model.richText.forEach(text => {
324
+ this.richTextXform.render(xmlStream, text);
325
+ });
326
+ xmlStream.closeNode("is");
327
+ }
229
328
  else {
230
329
  xmlStream.addAttribute("t", "str");
231
330
  xmlStream.leafNode("v", null, model.text);
@@ -257,6 +356,9 @@ class CellXform extends BaseXform {
257
356
  if (node.attributes.s) {
258
357
  this.model.styleId = parseInt(node.attributes.s, 10);
259
358
  }
359
+ if (node.attributes.cm) {
360
+ this.model.cm = parseInt(node.attributes.cm, 10);
361
+ }
260
362
  return true;
261
363
  case "f":
262
364
  this.currentNode = "f";
@@ -386,6 +488,9 @@ class CellXform extends BaseXform {
386
488
  case "r":
387
489
  this.model.value = this.model.value || {};
388
490
  this.model.value.richText = this.model.value.richText ?? [];
491
+ // `this.parser` is guaranteed by parseOpen("r"), which instantiates
492
+ // a RichTextXform. A missing parser here means malformed XML that
493
+ // should surface as a parse error rather than silently swallow.
389
494
  this.model.value.richText.push(this.parser.model);
390
495
  this.parser = undefined;
391
496
  this.currentNode = undefined;
@@ -409,11 +514,28 @@ class CellXform extends BaseXform {
409
514
  switch (model.type) {
410
515
  case Enums.ValueType.String:
411
516
  if (typeof model.value === "number") {
517
+ // A numeric value on a String-typed cell is a sharedStrings index
518
+ // (originated from t="s" in parseClose).
519
+ //
520
+ // Two malformed-file cases to consider:
521
+ // 1. sharedStrings table missing entirely — degrade gracefully
522
+ // (consistent with the "missing-bits.xlsx" graceful-loading
523
+ // contract); leave value as the raw index so worksheets still
524
+ // load.
525
+ // 2. sharedStrings table present but the specific index is out of
526
+ // range — this is the case that previously crashed with
527
+ // `TypeError: cannot access property "richText"`. Fail loudly
528
+ // with a typed ExcelError so callers get file-corruption
529
+ // context.
412
530
  if (options.sharedStrings) {
413
- model.value = options.sharedStrings.getString(model.value);
531
+ const ssIndex = model.value;
532
+ model.value = options.sharedStrings.getString(ssIndex);
533
+ if (model.value === undefined) {
534
+ throw new ExcelError(`Invalid shared string index ${ssIndex} in cell ${model.address}: the xlsx file appears to be corrupted`);
535
+ }
414
536
  }
415
537
  }
416
- if (model.value.richText) {
538
+ if (model.value && model.value.richText) {
417
539
  model.type = Enums.ValueType.RichText;
418
540
  }
419
541
  break;
@@ -444,6 +566,24 @@ class CellXform extends BaseXform {
444
566
  }
445
567
  delete model.si;
446
568
  }
569
+ // Convert cm metadata index into isDynamicArray flag.
570
+ // The cm attribute (1-indexed) links to a cellMetadata record in
571
+ // xl/metadata.xml. We use the precise dynamicArrayCmIndices set
572
+ // (built by MetadataXform) to check whether this specific cm value
573
+ // maps to an XLDAPR metadataType. Falls back to the coarser
574
+ // hasDynamicArrayMetadata boolean for backwards compatibility.
575
+ // We strip cm from the model — it will be reassigned during write prepare.
576
+ if (model.cm) {
577
+ if (options.dynamicArrayCmIndices) {
578
+ if (options.dynamicArrayCmIndices.has(model.cm)) {
579
+ model.isDynamicArray = true;
580
+ }
581
+ }
582
+ else if (options.hasDynamicArrayMetadata) {
583
+ model.isDynamicArray = true;
584
+ }
585
+ }
586
+ delete model.cm;
447
587
  break;
448
588
  default:
449
589
  break;
@@ -451,14 +591,32 @@ class CellXform extends BaseXform {
451
591
  // look for hyperlink
452
592
  const hyperlink = options.hyperlinkMap[model.address];
453
593
  if (hyperlink) {
594
+ // CellHyperlinkValue.text is typed as string; if the shared-string
595
+ // resolution produced a rich-text payload ({ richText: [...] }) we must
596
+ // flatten it for `text` AND preserve the runs on `richText` so formatted
597
+ // display survives round-trip. (See issue #142.)
598
+ let source;
454
599
  if (model.type === Enums.ValueType.Formula) {
455
- model.text = model.result;
456
- model.result = undefined;
600
+ // Formula + hyperlink: surface as a Hyperlink cell whose display is
601
+ // the formula's evaluated result, but keep `model.formula` (and the
602
+ // original result) on the model so write-time can re-emit both the
603
+ // formula <c> and the <hyperlink> entry. The cell value layer ignores
604
+ // unknown model fields, so the public Hyperlink shape stays clean
605
+ // while round-trip data is preserved internally.
606
+ source = model.result;
457
607
  }
458
608
  else {
459
- model.text = model.value;
609
+ source = model.value;
460
610
  model.value = undefined;
461
611
  }
612
+ const display = extractHyperlinkDisplay(source);
613
+ model.text = display.text;
614
+ if (display.richText) {
615
+ model.richText = display.richText;
616
+ }
617
+ else {
618
+ delete model.richText;
619
+ }
462
620
  model.type = Enums.ValueType.Hyperlink;
463
621
  model.hyperlink = hyperlink;
464
622
  }
@@ -57,7 +57,7 @@ function optimiseDataValidations(model) {
57
57
  dataValidation,
58
58
  marked: false
59
59
  }))
60
- .sort((a, b) => a.address.localeCompare(b.address));
60
+ .sort((a, b) => colCache.compareAddress(a.address, b.address));
61
61
  const dvMap = Object.fromEntries(dvList.map(dv => [dv.address, dv]));
62
62
  const matchCol = (addr, height, col) => {
63
63
  for (let i = 0; i < height; i++) {
@@ -0,0 +1,80 @@
1
+ import { BaseXform } from "../base-xform.js";
2
+ /**
3
+ * Boolean attribute names supported on <ignoredError> elements.
4
+ * These correspond to the OOXML spec CT_IgnoredError attributes.
5
+ */
6
+ const BOOL_ATTRS = [
7
+ "numberStoredAsText",
8
+ "formula",
9
+ "formulaRange",
10
+ "unlockedFormula",
11
+ "emptyCellReference",
12
+ "listDataValidation",
13
+ "calculatedColumn",
14
+ "evalError",
15
+ "twoDigitTextYear"
16
+ ];
17
+ /**
18
+ * Xform for the <ignoredErrors> element in a worksheet.
19
+ *
20
+ * Renders:
21
+ * ```xml
22
+ * <ignoredErrors>
23
+ * <ignoredError sqref="A1:B10" numberStoredAsText="1" />
24
+ * </ignoredErrors>
25
+ * ```
26
+ */
27
+ class IgnoredErrorsXform extends BaseXform {
28
+ get tag() {
29
+ return "ignoredErrors";
30
+ }
31
+ render(xmlStream, model) {
32
+ if (!model || model.length === 0) {
33
+ return;
34
+ }
35
+ xmlStream.openNode("ignoredErrors");
36
+ for (const entry of model) {
37
+ const attrs = { sqref: entry.ref };
38
+ for (const attr of BOOL_ATTRS) {
39
+ if (entry[attr]) {
40
+ attrs[attr] = 1;
41
+ }
42
+ }
43
+ xmlStream.leafNode("ignoredError", attrs);
44
+ }
45
+ xmlStream.closeNode();
46
+ }
47
+ parseOpen(node) {
48
+ switch (node.name) {
49
+ case "ignoredErrors":
50
+ this.model = [];
51
+ return true;
52
+ case "ignoredError": {
53
+ const entry = {
54
+ ref: node.attributes.sqref ?? ""
55
+ };
56
+ for (const attr of BOOL_ATTRS) {
57
+ if (node.attributes[attr] === "1" || node.attributes[attr] === "true") {
58
+ entry[attr] = true;
59
+ }
60
+ }
61
+ this.model.push(entry);
62
+ return true;
63
+ }
64
+ default:
65
+ return true;
66
+ }
67
+ }
68
+ parseText() {
69
+ // no text content
70
+ }
71
+ parseClose(name) {
72
+ switch (name) {
73
+ case "ignoredErrors":
74
+ return false;
75
+ default:
76
+ return true;
77
+ }
78
+ }
79
+ }
80
+ export { IgnoredErrorsXform };
@@ -14,6 +14,7 @@ import { DrawingXform } from "./drawing-xform.js";
14
14
  import { ExtLstXform } from "./ext-lst-xform.js";
15
15
  import { HeaderFooterXform } from "./header-footer-xform.js";
16
16
  import { isInternalLink, HyperlinkXform } from "./hyperlink-xform.js";
17
+ import { IgnoredErrorsXform } from "./ignored-errors-xform.js";
17
18
  import { MergeCellXform } from "./merge-cell-xform.js";
18
19
  import { Merges } from "./merges.js";
19
20
  import { PageMarginsXform } from "./page-margins-xform.js";
@@ -131,7 +132,8 @@ class WorkSheetXform extends BaseXform {
131
132
  childXform: new TablePartXform()
132
133
  }),
133
134
  conditionalFormatting: new ConditionalFormattingsXform(),
134
- extLst: new ExtLstXform()
135
+ extLst: new ExtLstXform(),
136
+ ignoredErrors: new IgnoredErrorsXform()
135
137
  };
136
138
  }
137
139
  prepare(model, options) {
@@ -608,7 +610,9 @@ class WorkSheetXform extends BaseXform {
608
610
  xmlStream.leafNode("mc:Fallback");
609
611
  xmlStream.closeNode();
610
612
  }
611
- // Table parts must come after <controls> in worksheet element order.
613
+ // ignoredErrors must come after controls, before tableParts (OOXML schema order).
614
+ this.map.ignoredErrors.render(xmlStream, model.ignoredErrors);
615
+ // tableParts must come after ignoredErrors.
612
616
  this.map.tableParts.render(xmlStream, model.tables);
613
617
  // extLst should be the last element in the worksheet.
614
618
  this.map.extLst.render(xmlStream, model);
@@ -677,7 +681,8 @@ class WorkSheetXform extends BaseXform {
677
681
  tables: this.map.tableParts.model,
678
682
  conditionalFormattings,
679
683
  rowBreaks: this.map.rowBreaks.model ?? [],
680
- colBreaks: this.map.colBreaks.model ?? []
684
+ colBreaks: this.map.colBreaks.model ?? [],
685
+ ignoredErrors: this.map.ignoredErrors.model ?? []
681
686
  };
682
687
  if (this.map.autoFilter.model) {
683
688
  this.model.autoFilter = this.map.autoFilter.model;
@@ -769,7 +774,7 @@ class WorkSheetXform extends BaseXform {
769
774
  name: drawingName,
770
775
  rels: options.drawingRels?.[drawingName] ?? drawing.rels ?? []
771
776
  };
772
- // Also extract images to model.media for backward compatibility
777
+ // Also extract images to model.media for backward compatibility.
773
778
  drawing.anchors.forEach(anchor => {
774
779
  if (anchor.medium) {
775
780
  // Detect overlay watermarks: drawings that carry alphaModFix
@@ -167,13 +167,15 @@ class BorderXform extends BaseXform {
167
167
  return true;
168
168
  }
169
169
  if (name === "border") {
170
- const model = (this.model = {});
170
+ const model = {};
171
+ let hasContent = false;
171
172
  const add = (key, edgeModel, extensions) => {
172
173
  if (edgeModel) {
173
174
  if (extensions) {
174
175
  Object.assign(edgeModel, extensions);
175
176
  }
176
177
  model[key] = edgeModel;
178
+ hasContent = true;
177
179
  }
178
180
  };
179
181
  add("left", this.map.left.model);
@@ -181,6 +183,7 @@ class BorderXform extends BaseXform {
181
183
  add("top", this.map.top.model);
182
184
  add("bottom", this.map.bottom.model);
183
185
  add("diagonal", this.map.diagonal.model, { up: this.diagonalUp, down: this.diagonalDown });
186
+ this.model = hasContent ? model : undefined;
184
187
  }
185
188
  return false;
186
189
  }