@beyondwork/docx-react-component 1.0.29 → 1.0.30

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 (381) hide show
  1. package/package.json +65 -96
  2. package/src/README.md +85 -0
  3. package/src/api/README.md +26 -0
  4. package/src/api/public-types.ts +1952 -0
  5. package/src/api/session-state.ts +62 -0
  6. package/src/compare/diff-engine.ts +623 -0
  7. package/src/compare/export-redlines.ts +280 -0
  8. package/src/compare/index.ts +25 -0
  9. package/src/compare/snapshot.ts +97 -0
  10. package/src/component-inventory.md +99 -0
  11. package/src/core/README.md +10 -0
  12. package/src/core/commands/README.md +3 -0
  13. package/{dist/chunk-TJBP2K4T.js → src/core/commands/formatting-commands.ts} +536 -196
  14. package/src/core/commands/image-commands.ts +373 -0
  15. package/src/core/commands/index.ts +1879 -0
  16. package/src/core/commands/list-commands.ts +565 -0
  17. package/src/core/commands/paragraph-layout-commands.ts +339 -0
  18. package/src/core/commands/review-commands.ts +108 -0
  19. package/{dist/core/commands/section-layout-commands.cjs → src/core/commands/section-layout-commands.ts} +340 -137
  20. package/src/core/commands/structural-helpers.ts +309 -0
  21. package/{dist/core/commands/style-commands.cjs → src/core/commands/style-commands.ts} +113 -65
  22. package/src/core/commands/table-structure-commands.ts +854 -0
  23. package/{dist/chunk-UZXBISGO.js → src/core/commands/text-commands.ts} +142 -86
  24. package/src/core/schema/README.md +3 -0
  25. package/src/core/schema/text-schema.ts +516 -0
  26. package/src/core/search/search-text.ts +357 -0
  27. package/src/core/selection/README.md +3 -0
  28. package/src/core/selection/mapping.ts +289 -0
  29. package/src/core/selection/review-anchors.ts +183 -0
  30. package/src/core/state/README.md +3 -0
  31. package/src/core/state/editor-state.ts +892 -0
  32. package/src/core/state/text-transaction.ts +869 -0
  33. package/src/formats/xlsx/io/parse-shared-strings.ts +41 -0
  34. package/src/formats/xlsx/io/parse-sheet.ts +459 -0
  35. package/src/formats/xlsx/io/parse-styles.ts +59 -0
  36. package/src/formats/xlsx/io/parse-workbook.ts +75 -0
  37. package/src/formats/xlsx/io/serialize-shared-strings.ts +72 -0
  38. package/src/formats/xlsx/io/serialize-sheet.ts +333 -0
  39. package/src/formats/xlsx/io/serialize-styles.ts +98 -0
  40. package/src/formats/xlsx/io/serialize-workbook.ts +429 -0
  41. package/src/formats/xlsx/io/xlsx-session.ts +314 -0
  42. package/src/formats/xlsx/model/cell.ts +189 -0
  43. package/src/formats/xlsx/model/sheet.ts +326 -0
  44. package/src/formats/xlsx/model/styles.ts +118 -0
  45. package/src/formats/xlsx/model/workbook.ts +453 -0
  46. package/src/formats/xlsx/runtime/cell-commands.ts +567 -0
  47. package/src/formats/xlsx/runtime/sheet-commands.ts +206 -0
  48. package/src/formats/xlsx/runtime/workbook-runtime.ts +177 -0
  49. package/src/formats/xlsx/runtime/workbook-transaction.ts +822 -0
  50. package/src/index.ts +142 -0
  51. package/src/io/README.md +10 -0
  52. package/src/io/docx-session.ts +3175 -0
  53. package/src/io/export/README.md +3 -0
  54. package/src/io/export/export-session.ts +220 -0
  55. package/src/io/export/minimal-docx.ts +115 -0
  56. package/src/io/export/reattach-preserved-parts.ts +54 -0
  57. package/src/io/export/serialize-comments.ts +947 -0
  58. package/src/io/export/serialize-footnotes.ts +394 -0
  59. package/src/io/export/serialize-headers-footers.ts +368 -0
  60. package/src/io/export/serialize-main-document.ts +1342 -0
  61. package/src/io/export/serialize-numbering.ts +218 -0
  62. package/src/io/export/serialize-revisions.ts +389 -0
  63. package/src/io/export/serialize-runtime-revisions.ts +463 -0
  64. package/src/io/export/serialize-tables.ts +174 -0
  65. package/src/io/export/split-review-boundaries.ts +356 -0
  66. package/src/io/export/split-story-blocks-for-runtime-revisions.ts +252 -0
  67. package/src/io/export/table-properties-xml.ts +318 -0
  68. package/src/io/normalize/README.md +3 -0
  69. package/src/io/normalize/normalize-text.ts +670 -0
  70. package/src/io/ooxml/README.md +3 -0
  71. package/src/io/ooxml/highlight-colors.ts +39 -0
  72. package/src/io/ooxml/numbering-sentinels.ts +44 -0
  73. package/src/io/ooxml/parse-comments.ts +852 -0
  74. package/src/io/ooxml/parse-complex-content.ts +287 -0
  75. package/src/io/ooxml/parse-fields.ts +834 -0
  76. package/src/io/ooxml/parse-footnotes.ts +952 -0
  77. package/src/io/ooxml/parse-headers-footers.ts +1212 -0
  78. package/src/io/ooxml/parse-inline-media.ts +461 -0
  79. package/src/io/ooxml/parse-main-document.ts +2947 -0
  80. package/src/io/ooxml/parse-numbering.ts +747 -0
  81. package/src/io/ooxml/parse-revisions.ts +1045 -0
  82. package/src/io/ooxml/parse-settings.ts +184 -0
  83. package/src/io/ooxml/parse-shapes.ts +296 -0
  84. package/src/io/ooxml/parse-styles.ts +639 -0
  85. package/src/io/ooxml/parse-tables.ts +627 -0
  86. package/src/io/ooxml/parse-theme.ts +346 -0
  87. package/src/io/ooxml/part-manifest.ts +136 -0
  88. package/src/io/ooxml/revision-boundaries.ts +475 -0
  89. package/src/io/ooxml/workflow-payload.ts +544 -0
  90. package/src/io/opc/README.md +3 -0
  91. package/src/io/opc/corrupt-package.ts +166 -0
  92. package/src/io/opc/docx-package.ts +74 -0
  93. package/src/io/opc/package-reader.ts +325 -0
  94. package/src/io/opc/package-writer.ts +273 -0
  95. package/src/io/source-package-provenance.ts +241 -0
  96. package/{dist/chunk-RMH72RZI.js → src/legal/bookmarks.ts} +130 -44
  97. package/src/legal/cross-references.ts +414 -0
  98. package/src/legal/defined-terms.ts +203 -0
  99. package/src/legal/index.ts +32 -0
  100. package/src/legal/signature-blocks.ts +259 -0
  101. package/src/model/README.md +3 -0
  102. package/src/model/canonical-document.ts +2722 -0
  103. package/src/model/cds-1.0.0.ts +212 -0
  104. package/src/model/snapshot.ts +760 -0
  105. package/src/preservation/README.md +3 -0
  106. package/src/preservation/markup-compatibility.ts +48 -0
  107. package/src/preservation/opaque-fragment-store.ts +89 -0
  108. package/src/preservation/opaque-region.ts +233 -0
  109. package/src/preservation/package-preservation.ts +113 -0
  110. package/src/preservation/preserved-part-manifest.ts +56 -0
  111. package/src/preservation/relationship-retention.ts +57 -0
  112. package/src/preservation/store.ts +255 -0
  113. package/src/review/README.md +16 -0
  114. package/src/review/store/README.md +3 -0
  115. package/src/review/store/comment-anchors.ts +70 -0
  116. package/src/review/store/comment-remapping.ts +154 -0
  117. package/src/review/store/comment-store.ts +349 -0
  118. package/src/review/store/comment-thread.ts +109 -0
  119. package/src/review/store/revision-actions.ts +423 -0
  120. package/src/review/store/revision-store.ts +323 -0
  121. package/src/review/store/revision-types.ts +182 -0
  122. package/src/review/store/runtime-comment-store.ts +43 -0
  123. package/src/runtime/README.md +3 -0
  124. package/src/runtime/ai-action-policy.ts +764 -0
  125. package/src/runtime/context-analytics.ts +824 -0
  126. package/src/runtime/document-layout.ts +332 -0
  127. package/src/runtime/document-locations.ts +521 -0
  128. package/src/runtime/document-navigation.ts +616 -0
  129. package/src/runtime/document-outline.ts +440 -0
  130. package/src/runtime/document-runtime.ts +4055 -0
  131. package/src/runtime/document-search.ts +145 -0
  132. package/src/runtime/event-refresh-hints.ts +137 -0
  133. package/src/runtime/numbering-prefix.ts +244 -0
  134. package/src/runtime/page-layout-estimation.ts +305 -0
  135. package/src/runtime/read-only-diagnostics-runtime.ts +241 -0
  136. package/src/runtime/resolved-numbering-geometry.ts +293 -0
  137. package/src/runtime/review-runtime.ts +44 -0
  138. package/src/runtime/revision-runtime.ts +107 -0
  139. package/src/runtime/session-capabilities.ts +192 -0
  140. package/src/runtime/story-context.ts +164 -0
  141. package/src/runtime/story-targeting.ts +162 -0
  142. package/src/runtime/suggestions-snapshot.ts +137 -0
  143. package/src/runtime/surface-projection.ts +1553 -0
  144. package/src/runtime/table-commands.ts +173 -0
  145. package/src/runtime/table-schema.ts +309 -0
  146. package/src/runtime/table-style-resolver.ts +409 -0
  147. package/src/runtime/view-state.ts +493 -0
  148. package/src/runtime/virtualized-rendering.ts +258 -0
  149. package/src/runtime/workflow-markup.ts +393 -0
  150. package/src/ui/README.md +30 -0
  151. package/src/ui/WordReviewEditor.tsx +5268 -0
  152. package/src/ui/browser-export.ts +52 -0
  153. package/src/ui/comments/README.md +3 -0
  154. package/src/ui/compatibility/README.md +3 -0
  155. package/src/ui/editor-command-bag.ts +127 -0
  156. package/src/ui/editor-runtime-boundary.ts +1558 -0
  157. package/src/ui/editor-shell-view.tsx +144 -0
  158. package/src/ui/editor-surface/README.md +3 -0
  159. package/src/ui/editor-surface-controller.tsx +66 -0
  160. package/src/ui/headless/comment-decoration-model.ts +124 -0
  161. package/src/ui/headless/preserve-editor-selection.ts +5 -0
  162. package/src/ui/headless/revision-decoration-model.ts +128 -0
  163. package/src/ui/headless/selection-helpers.ts +54 -0
  164. package/src/ui/headless/selection-tool-context.ts +19 -0
  165. package/src/ui/headless/selection-tool-resolver.ts +752 -0
  166. package/src/ui/headless/selection-tool-types.ts +129 -0
  167. package/src/ui/headless/selection-toolbar-model.ts +11 -0
  168. package/src/ui/headless/use-editor-keyboard.ts +103 -0
  169. package/src/ui/review/README.md +3 -0
  170. package/src/ui/runtime-shortcut-dispatch.ts +365 -0
  171. package/src/ui/runtime-snapshot-selectors.ts +197 -0
  172. package/src/ui/shared/revision-filters.ts +31 -0
  173. package/src/ui/status/README.md +3 -0
  174. package/src/ui/theme/README.md +3 -0
  175. package/src/ui/toolbar/README.md +3 -0
  176. package/src/ui/workflow-surface-blocked-rails.ts +94 -0
  177. package/src/ui-tailwind/chrome/chrome-preset-model.ts +107 -0
  178. package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +15 -0
  179. package/src/ui-tailwind/chrome/review-queue-bar.tsx +97 -0
  180. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +64 -0
  181. package/src/ui-tailwind/chrome/tw-context-analytics-summary.tsx +122 -0
  182. package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +121 -0
  183. package/src/ui-tailwind/chrome/tw-layout-panel.tsx +114 -0
  184. package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +30 -0
  185. package/src/ui-tailwind/chrome/tw-page-ruler.tsx +365 -0
  186. package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +23 -0
  187. package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +35 -0
  188. package/src/ui-tailwind/chrome/tw-selection-tool-formatting.tsx +37 -0
  189. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +298 -0
  190. package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +116 -0
  191. package/src/ui-tailwind/chrome/tw-selection-tool-suggestion.tsx +29 -0
  192. package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +27 -0
  193. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +186 -0
  194. package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +139 -0
  195. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +200 -0
  196. package/src/ui-tailwind/chrome/tw-unsaved-modal.tsx +58 -0
  197. package/src/ui-tailwind/chrome/use-before-unload.ts +20 -0
  198. package/src/ui-tailwind/editor-surface/perf-probe.ts +179 -0
  199. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +189 -0
  200. package/src/ui-tailwind/editor-surface/pm-contextual-ui.ts +31 -0
  201. package/src/ui-tailwind/editor-surface/pm-decorations.ts +411 -0
  202. package/src/ui-tailwind/editor-surface/pm-position-map.ts +123 -0
  203. package/src/ui-tailwind/editor-surface/pm-schema.ts +927 -0
  204. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +567 -0
  205. package/src/ui-tailwind/editor-surface/search-plugin.ts +168 -0
  206. package/src/ui-tailwind/editor-surface/surface-build-keys.ts +65 -0
  207. package/src/ui-tailwind/editor-surface/tw-caret.tsx +12 -0
  208. package/src/ui-tailwind/editor-surface/tw-editor-surface.tsx +150 -0
  209. package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +129 -0
  210. package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +58 -0
  211. package/src/ui-tailwind/editor-surface/tw-paragraph-block.tsx +151 -0
  212. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +1047 -0
  213. package/src/ui-tailwind/editor-surface/tw-segment-view.tsx +111 -0
  214. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +503 -0
  215. package/src/ui-tailwind/index.ts +62 -0
  216. package/src/ui-tailwind/page-chrome-model.ts +27 -0
  217. package/src/ui-tailwind/review/tw-comment-sidebar.tsx +406 -0
  218. package/src/ui-tailwind/review/tw-health-panel.tsx +149 -0
  219. package/src/ui-tailwind/review/tw-review-rail.tsx +122 -0
  220. package/src/ui-tailwind/review/tw-revision-sidebar.tsx +164 -0
  221. package/src/ui-tailwind/status/tw-status-bar.tsx +65 -0
  222. package/{dist → src}/ui-tailwind/theme/editor-theme.css +58 -40
  223. package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +52 -0
  224. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +1133 -0
  225. package/src/ui-tailwind/tw-review-workspace.tsx +1460 -0
  226. package/src/validation/README.md +3 -0
  227. package/src/validation/compatibility-engine.ts +878 -0
  228. package/src/validation/compatibility-report.ts +161 -0
  229. package/src/validation/diagnostics.ts +204 -0
  230. package/src/validation/docx-comment-proof.ts +720 -0
  231. package/src/validation/import-diagnostics.ts +128 -0
  232. package/src/validation/low-priority-word-surfaces.ts +373 -0
  233. package/dist/canonical-document-BLEbzL2J.d.cts +0 -844
  234. package/dist/canonical-document-BLEbzL2J.d.ts +0 -844
  235. package/dist/chunk-2FJS5GZM.js +0 -763
  236. package/dist/chunk-2FJS5GZM.js.map +0 -1
  237. package/dist/chunk-2OQBZS3F.js +0 -446
  238. package/dist/chunk-2OQBZS3F.js.map +0 -1
  239. package/dist/chunk-2S7W4KFO.js +0 -127
  240. package/dist/chunk-2S7W4KFO.js.map +0 -1
  241. package/dist/chunk-2TG72QSW.js +0 -3874
  242. package/dist/chunk-2TG72QSW.js.map +0 -1
  243. package/dist/chunk-36QNIZBO.js +0 -532
  244. package/dist/chunk-36QNIZBO.js.map +0 -1
  245. package/dist/chunk-4AQOYAW4.js +0 -3069
  246. package/dist/chunk-4AQOYAW4.js.map +0 -1
  247. package/dist/chunk-4D5EWJ3P.js +0 -77
  248. package/dist/chunk-4D5EWJ3P.js.map +0 -1
  249. package/dist/chunk-5FN54NDH.js +0 -2257
  250. package/dist/chunk-5FN54NDH.js.map +0 -1
  251. package/dist/chunk-BOYGQYRQ.js +0 -7306
  252. package/dist/chunk-BOYGQYRQ.js.map +0 -1
  253. package/dist/chunk-CN3XMECL.js +0 -212
  254. package/dist/chunk-CN3XMECL.js.map +0 -1
  255. package/dist/chunk-EBI3BX6U.js +0 -164
  256. package/dist/chunk-EBI3BX6U.js.map +0 -1
  257. package/dist/chunk-EILUG3VB.js +0 -1275
  258. package/dist/chunk-EILUG3VB.js.map +0 -1
  259. package/dist/chunk-FUDY333O.js +0 -70
  260. package/dist/chunk-FUDY333O.js.map +0 -1
  261. package/dist/chunk-GBVOWFIK.js +0 -1237
  262. package/dist/chunk-GBVOWFIK.js.map +0 -1
  263. package/dist/chunk-H4TQ3H3Y.js +0 -262
  264. package/dist/chunk-H4TQ3H3Y.js.map +0 -1
  265. package/dist/chunk-JGB3IXZO.js +0 -189
  266. package/dist/chunk-JGB3IXZO.js.map +0 -1
  267. package/dist/chunk-KD2QRQPY.js +0 -4342
  268. package/dist/chunk-KD2QRQPY.js.map +0 -1
  269. package/dist/chunk-KLMXQVYK.js +0 -369
  270. package/dist/chunk-KLMXQVYK.js.map +0 -1
  271. package/dist/chunk-KZUG5KFQ.js +0 -214
  272. package/dist/chunk-KZUG5KFQ.js.map +0 -1
  273. package/dist/chunk-QDAQ4CJU.js +0 -345
  274. package/dist/chunk-QDAQ4CJU.js.map +0 -1
  275. package/dist/chunk-RMH72RZI.js.map +0 -1
  276. package/dist/chunk-SWKWQZXM.js +0 -117
  277. package/dist/chunk-SWKWQZXM.js.map +0 -1
  278. package/dist/chunk-TJBP2K4T.js.map +0 -1
  279. package/dist/chunk-TLCEAQDQ.js +0 -542
  280. package/dist/chunk-TLCEAQDQ.js.map +0 -1
  281. package/dist/chunk-UZXBISGO.js.map +0 -1
  282. package/dist/chunk-WGBAKP3Q.js +0 -3220
  283. package/dist/chunk-WGBAKP3Q.js.map +0 -1
  284. package/dist/compare/index.cjs +0 -5475
  285. package/dist/compare/index.cjs.map +0 -1
  286. package/dist/compare/index.d.cts +0 -114
  287. package/dist/compare/index.d.ts +0 -114
  288. package/dist/compare/index.js +0 -731
  289. package/dist/compare/index.js.map +0 -1
  290. package/dist/core/commands/formatting-commands.cjs +0 -828
  291. package/dist/core/commands/formatting-commands.cjs.map +0 -1
  292. package/dist/core/commands/formatting-commands.d.cts +0 -63
  293. package/dist/core/commands/formatting-commands.d.ts +0 -63
  294. package/dist/core/commands/formatting-commands.js +0 -37
  295. package/dist/core/commands/formatting-commands.js.map +0 -1
  296. package/dist/core/commands/image-commands.cjs +0 -2023
  297. package/dist/core/commands/image-commands.cjs.map +0 -1
  298. package/dist/core/commands/image-commands.d.cts +0 -58
  299. package/dist/core/commands/image-commands.d.ts +0 -58
  300. package/dist/core/commands/image-commands.js +0 -18
  301. package/dist/core/commands/image-commands.js.map +0 -1
  302. package/dist/core/commands/section-layout-commands.cjs.map +0 -1
  303. package/dist/core/commands/section-layout-commands.d.cts +0 -62
  304. package/dist/core/commands/section-layout-commands.d.ts +0 -62
  305. package/dist/core/commands/section-layout-commands.js +0 -21
  306. package/dist/core/commands/section-layout-commands.js.map +0 -1
  307. package/dist/core/commands/style-commands.cjs.map +0 -1
  308. package/dist/core/commands/style-commands.d.cts +0 -13
  309. package/dist/core/commands/style-commands.d.ts +0 -13
  310. package/dist/core/commands/style-commands.js +0 -9
  311. package/dist/core/commands/style-commands.js.map +0 -1
  312. package/dist/core/commands/table-structure-commands.cjs +0 -1883
  313. package/dist/core/commands/table-structure-commands.cjs.map +0 -1
  314. package/dist/core/commands/table-structure-commands.d.cts +0 -59
  315. package/dist/core/commands/table-structure-commands.d.ts +0 -59
  316. package/dist/core/commands/table-structure-commands.js +0 -12
  317. package/dist/core/commands/table-structure-commands.js.map +0 -1
  318. package/dist/core/commands/text-commands.cjs +0 -2391
  319. package/dist/core/commands/text-commands.cjs.map +0 -1
  320. package/dist/core/commands/text-commands.d.cts +0 -24
  321. package/dist/core/commands/text-commands.d.ts +0 -24
  322. package/dist/core/commands/text-commands.js +0 -28
  323. package/dist/core/commands/text-commands.js.map +0 -1
  324. package/dist/core/selection/mapping.cjs +0 -200
  325. package/dist/core/selection/mapping.cjs.map +0 -1
  326. package/dist/core/selection/mapping.d.cts +0 -2
  327. package/dist/core/selection/mapping.d.ts +0 -2
  328. package/dist/core/selection/mapping.js +0 -31
  329. package/dist/core/selection/mapping.js.map +0 -1
  330. package/dist/core/state/editor-state.cjs +0 -2278
  331. package/dist/core/state/editor-state.cjs.map +0 -1
  332. package/dist/core/state/editor-state.d.cts +0 -2
  333. package/dist/core/state/editor-state.d.ts +0 -2
  334. package/dist/core/state/editor-state.js +0 -26
  335. package/dist/core/state/editor-state.js.map +0 -1
  336. package/dist/index.cjs +0 -38553
  337. package/dist/index.cjs.map +0 -1
  338. package/dist/index.d.cts +0 -15
  339. package/dist/index.d.ts +0 -15
  340. package/dist/index.js +0 -7856
  341. package/dist/index.js.map +0 -1
  342. package/dist/io/docx-session.cjs +0 -16236
  343. package/dist/io/docx-session.cjs.map +0 -1
  344. package/dist/io/docx-session.d.cts +0 -21
  345. package/dist/io/docx-session.d.ts +0 -21
  346. package/dist/io/docx-session.js +0 -18
  347. package/dist/io/docx-session.js.map +0 -1
  348. package/dist/legal/index.cjs +0 -3900
  349. package/dist/legal/index.cjs.map +0 -1
  350. package/dist/legal/index.d.cts +0 -86
  351. package/dist/legal/index.d.ts +0 -86
  352. package/dist/legal/index.js +0 -616
  353. package/dist/legal/index.js.map +0 -1
  354. package/dist/public-types-7ZL_94cz.d.ts +0 -1573
  355. package/dist/public-types-CeMaDueh.d.cts +0 -1573
  356. package/dist/public-types.cjs +0 -19
  357. package/dist/public-types.cjs.map +0 -1
  358. package/dist/public-types.d.cts +0 -2
  359. package/dist/public-types.d.ts +0 -2
  360. package/dist/public-types.js +0 -1
  361. package/dist/public-types.js.map +0 -1
  362. package/dist/runtime/document-runtime.cjs +0 -11140
  363. package/dist/runtime/document-runtime.cjs.map +0 -1
  364. package/dist/runtime/document-runtime.d.cts +0 -231
  365. package/dist/runtime/document-runtime.d.ts +0 -231
  366. package/dist/runtime/document-runtime.js +0 -21
  367. package/dist/runtime/document-runtime.js.map +0 -1
  368. package/dist/structural-helpers-CilgOVhh.d.cts +0 -10
  369. package/dist/structural-helpers-q0Gd-eBN.d.ts +0 -10
  370. package/dist/ui-tailwind/editor-surface/search-plugin.cjs +0 -313
  371. package/dist/ui-tailwind/editor-surface/search-plugin.cjs.map +0 -1
  372. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +0 -67
  373. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +0 -67
  374. package/dist/ui-tailwind/editor-surface/search-plugin.js +0 -23
  375. package/dist/ui-tailwind/editor-surface/search-plugin.js.map +0 -1
  376. package/dist/ui-tailwind/index.cjs +0 -4833
  377. package/dist/ui-tailwind/index.cjs.map +0 -1
  378. package/dist/ui-tailwind/index.d.cts +0 -617
  379. package/dist/ui-tailwind/index.d.ts +0 -617
  380. package/dist/ui-tailwind/index.js +0 -575
  381. package/dist/ui-tailwind/index.js.map +0 -1
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Parses xl/sharedStrings.xml and returns the shared string table as an ordered array.
3
+ *
4
+ * Handles both simple text (<si><t>...</t></si>) and rich text runs
5
+ * (<si><r><t>...</t></r></si>) by concatenating all <t> content within each <si>.
6
+ */
7
+ export function parseSharedStringsXml(xml: string): string[] {
8
+ const result: string[] = [];
9
+ const siPattern = /<si>([\s\S]*?)<\/si>/g;
10
+ let siMatch: RegExpExecArray | null;
11
+
12
+ while ((siMatch = siPattern.exec(xml)) !== null) {
13
+ const siContent = siMatch[1] ?? "";
14
+ result.push(extractSharedStringText(siContent));
15
+ }
16
+
17
+ return result;
18
+ }
19
+
20
+ function extractSharedStringText(siContent: string): string {
21
+ // Collect text from all <t> elements (handles plain and rich text runs).
22
+ // The xml:space="preserve" attribute is not significant for the string value.
23
+ const tPattern = /<t(?:\s[^>]*)?>([^<]*)<\/t>/g;
24
+ const parts: string[] = [];
25
+ let tMatch: RegExpExecArray | null;
26
+
27
+ while ((tMatch = tPattern.exec(siContent)) !== null) {
28
+ parts.push(decodeXmlEntities(tMatch[1] ?? ""));
29
+ }
30
+
31
+ return parts.join("");
32
+ }
33
+
34
+ export function decodeXmlEntities(value: string): string {
35
+ return value
36
+ .replace(/&quot;/g, '"')
37
+ .replace(/&apos;/g, "'")
38
+ .replace(/&lt;/g, "<")
39
+ .replace(/&gt;/g, ">")
40
+ .replace(/&amp;/g, "&");
41
+ }
@@ -0,0 +1,459 @@
1
+ import { decodeXmlEntities } from "./parse-shared-strings.ts";
2
+ import { parseXmlAttributes } from "./parse-styles.ts";
3
+
4
+ // Re-export for external use
5
+ export { decodeXmlEntities };
6
+
7
+ /**
8
+ * A parsed cell from a SpreadsheetML worksheet.
9
+ *
10
+ * Row and col are zero-based indices. The value discriminated union covers all
11
+ * SpreadsheetML cell type codes: s (shared string), inlineStr, n/absent (number),
12
+ * b (boolean), e (error), str (formula string result), and blank.
13
+ */
14
+ export type XlsxParsedCellValue =
15
+ | { type: "blank" }
16
+ | { type: "text"; value: string; fromSharedString: boolean }
17
+ | { type: "number"; value: number }
18
+ | { type: "boolean"; value: boolean }
19
+ | {
20
+ type: "formula";
21
+ formula: string;
22
+ referenceTokens: string[];
23
+ cachedValue: XlsxParsedFormulaCachedValue | null;
24
+ }
25
+ | { type: "error"; errorCode: string };
26
+
27
+ export type XlsxParsedFormulaCachedValue =
28
+ | { type: "blank" }
29
+ | { type: "text"; value: string }
30
+ | { type: "number"; value: number }
31
+ | { type: "boolean"; value: boolean }
32
+ | { type: "error"; errorCode: string };
33
+
34
+ export interface XlsxParsedCell {
35
+ row: number;
36
+ col: number;
37
+ value: XlsxParsedCellValue;
38
+ styleIndex: number | null;
39
+ }
40
+
41
+ /**
42
+ * A parsed merge range from the <mergeCells> section.
43
+ * All indices are zero-based.
44
+ */
45
+ export interface XlsxParsedMerge {
46
+ startRow: number;
47
+ startCol: number;
48
+ endRow: number;
49
+ endCol: number;
50
+ }
51
+
52
+ export interface XlsxParsedDimension {
53
+ startRow: number;
54
+ startCol: number;
55
+ endRow: number;
56
+ endCol: number;
57
+ }
58
+
59
+ export interface SheetParseResult {
60
+ cells: XlsxParsedCell[];
61
+ merges: XlsxParsedMerge[];
62
+ dimension: XlsxParsedDimension | null;
63
+ }
64
+
65
+ /**
66
+ * Parses xl/worksheets/sheetN.xml.
67
+ *
68
+ * @param xml - Raw XML string of the worksheet part.
69
+ * @param sharedStrings - The shared string table from parseSharedStringsXml.
70
+ */
71
+ export function parseSheetXml(
72
+ xml: string,
73
+ sharedStrings: readonly string[],
74
+ ): SheetParseResult {
75
+ const cells: XlsxParsedCell[] = [];
76
+ const merges: XlsxParsedMerge[] = [];
77
+ const dimension = parseSheetDimension(xml);
78
+
79
+ const sheetDataMatch = /<sheetData>([\s\S]*?)<\/sheetData>/i.exec(xml);
80
+ if (sheetDataMatch) {
81
+ parseSheetData(sheetDataMatch[1] ?? "", sharedStrings, cells);
82
+ }
83
+
84
+ const mergeCellsMatch = /<mergeCells\b[^>]*>([\s\S]*?)<\/mergeCells>/i.exec(xml);
85
+ if (mergeCellsMatch) {
86
+ parseMergeCells(mergeCellsMatch[1] ?? "", merges);
87
+ }
88
+
89
+ return { cells, merges, dimension };
90
+ }
91
+
92
+ function parseSheetData(
93
+ sheetDataXml: string,
94
+ sharedStrings: readonly string[],
95
+ out: XlsxParsedCell[],
96
+ ): void {
97
+ // Match non-empty rows (<row ...>...</row>)
98
+ const rowPattern = /<row\b([^>]*)>([\s\S]*?)<\/row>/g;
99
+ let rowMatch: RegExpExecArray | null;
100
+
101
+ while ((rowMatch = rowPattern.exec(sheetDataXml)) !== null) {
102
+ const rowContent = rowMatch[2] ?? "";
103
+ parseRowCells(rowContent, sharedStrings, out);
104
+ }
105
+ }
106
+
107
+ function parseRowCells(
108
+ rowXml: string,
109
+ sharedStrings: readonly string[],
110
+ out: XlsxParsedCell[],
111
+ ): void {
112
+ // Match cells: both non-empty (<c ...>...</c>) and self-closing (<c .../>)
113
+ const cellPattern = /<c\b([^>]*)(?:>([\s\S]*?)<\/c>|\/>)/g;
114
+ let cellMatch: RegExpExecArray | null;
115
+
116
+ while ((cellMatch = cellPattern.exec(rowXml)) !== null) {
117
+ const attrs = parseXmlAttributes(cellMatch[1] ?? "");
118
+ const content = cellMatch[2] ?? "";
119
+ const cell = parseCell(attrs, content, sharedStrings);
120
+ if (cell !== null) {
121
+ out.push(cell);
122
+ }
123
+ }
124
+ }
125
+
126
+ function parseCell(
127
+ attrs: Record<string, string>,
128
+ content: string,
129
+ sharedStrings: readonly string[],
130
+ ): XlsxParsedCell | null {
131
+ const ref = attrs["r"];
132
+ if (!ref) {
133
+ return null;
134
+ }
135
+
136
+ const cellRef = parseCellRef(ref);
137
+ if (cellRef === null) {
138
+ return null;
139
+ }
140
+
141
+ const styleIndexAttr = attrs["s"];
142
+ const styleIndex =
143
+ styleIndexAttr !== undefined ? parseInt(styleIndexAttr, 10) : null;
144
+
145
+ const typeCode = attrs["t"] ?? "n";
146
+ const rawValue = extractTextContent(content, "v");
147
+ const formulaText = extractTextContent(content, "f");
148
+ const inlineText = extractInlineStringText(content);
149
+
150
+ const value = resolveCellValue(typeCode, rawValue, formulaText, inlineText, sharedStrings);
151
+
152
+ return {
153
+ row: cellRef.row,
154
+ col: cellRef.col,
155
+ value,
156
+ styleIndex: styleIndex !== null && !Number.isNaN(styleIndex) ? styleIndex : null,
157
+ };
158
+ }
159
+
160
+ function resolveCellValue(
161
+ typeCode: string,
162
+ rawValue: string | null,
163
+ formulaText: string | null,
164
+ inlineText: string | null,
165
+ sharedStrings: readonly string[],
166
+ ): XlsxParsedCellValue {
167
+ // Formula cells may have any result type; store formula + cached value.
168
+ if (formulaText !== null) {
169
+ const decodedFormula = decodeXmlEntities(formulaText);
170
+ return {
171
+ type: "formula",
172
+ formula: decodedFormula,
173
+ referenceTokens: extractFormulaReferenceTokens(decodedFormula),
174
+ cachedValue: resolveFormulaCachedValue(typeCode, rawValue, inlineText, sharedStrings),
175
+ };
176
+ }
177
+
178
+ switch (typeCode) {
179
+ case "s": {
180
+ // Shared string reference
181
+ const index = rawValue !== null ? parseInt(rawValue, 10) : NaN;
182
+ const text =
183
+ !Number.isNaN(index) && index >= 0 && index < sharedStrings.length
184
+ ? (sharedStrings[index] ?? "")
185
+ : "";
186
+ return { type: "text", value: text, fromSharedString: true };
187
+ }
188
+
189
+ case "inlineStr": {
190
+ return { type: "text", value: inlineText ?? "", fromSharedString: false };
191
+ }
192
+
193
+ case "str": {
194
+ // Formula result is a string; formula text would have been captured above.
195
+ // Here the cell carries only the cached string value (no formula tag).
196
+ return {
197
+ type: "text",
198
+ value: rawValue !== null ? decodeXmlEntities(rawValue) : "",
199
+ fromSharedString: false,
200
+ };
201
+ }
202
+
203
+ case "b": {
204
+ return { type: "boolean", value: rawValue === "1" };
205
+ }
206
+
207
+ case "e": {
208
+ return {
209
+ type: "error",
210
+ errorCode:
211
+ rawValue !== null ? decodeXmlEntities(rawValue) : "#ERROR!",
212
+ };
213
+ }
214
+
215
+ default: {
216
+ // "n" or absent — numeric value
217
+ if (rawValue === null || rawValue === "") {
218
+ return { type: "blank" };
219
+ }
220
+
221
+ const numericValue = parseFloat(rawValue);
222
+ return Number.isNaN(numericValue)
223
+ ? { type: "blank" }
224
+ : { type: "number", value: numericValue };
225
+ }
226
+ }
227
+ }
228
+
229
+ function resolveFormulaCachedValue(
230
+ typeCode: string,
231
+ rawValue: string | null,
232
+ inlineText: string | null,
233
+ sharedStrings: readonly string[],
234
+ ): XlsxParsedFormulaCachedValue | null {
235
+ switch (typeCode) {
236
+ case "s": {
237
+ const index = rawValue !== null ? parseInt(rawValue, 10) : NaN;
238
+ return {
239
+ type: "text",
240
+ value:
241
+ !Number.isNaN(index) && index >= 0 && index < sharedStrings.length
242
+ ? (sharedStrings[index] ?? "")
243
+ : "",
244
+ };
245
+ }
246
+
247
+ case "inlineStr":
248
+ return { type: "text", value: inlineText ?? "" };
249
+
250
+ case "str":
251
+ return rawValue === null
252
+ ? { type: "blank" }
253
+ : { type: "text", value: decodeXmlEntities(rawValue) };
254
+
255
+ case "b":
256
+ return rawValue === null
257
+ ? { type: "blank" }
258
+ : { type: "boolean", value: rawValue === "1" };
259
+
260
+ case "e":
261
+ return rawValue === null
262
+ ? { type: "blank" }
263
+ : { type: "error", errorCode: decodeXmlEntities(rawValue) };
264
+
265
+ default: {
266
+ if (rawValue === null || rawValue === "") {
267
+ return { type: "blank" };
268
+ }
269
+
270
+ const numericValue = Number(rawValue);
271
+ if (!Number.isNaN(numericValue)) {
272
+ return { type: "number", value: numericValue };
273
+ }
274
+
275
+ if (rawValue === "TRUE" || rawValue === "FALSE") {
276
+ return { type: "boolean", value: rawValue === "TRUE" };
277
+ }
278
+
279
+ return { type: "text", value: decodeXmlEntities(rawValue) };
280
+ }
281
+ }
282
+ }
283
+
284
+ function extractTextContent(xml: string, tagName: string): string | null {
285
+ const pattern = new RegExp(`<${tagName}(?:\\s[^>]*)?>([^<]*)</${tagName}>`, "i");
286
+ const match = pattern.exec(xml);
287
+ return match ? (match[1] ?? null) : null;
288
+ }
289
+
290
+ function extractInlineStringText(cellContent: string): string | null {
291
+ // <is> contains rich text identical to shared string runs
292
+ const isMatch = /<is>([\s\S]*?)<\/is>/i.exec(cellContent);
293
+ if (!isMatch) {
294
+ return null;
295
+ }
296
+
297
+ const tPattern = /<t(?:\s[^>]*)?>([^<]*)<\/t>/g;
298
+ const parts: string[] = [];
299
+ let tMatch: RegExpExecArray | null;
300
+
301
+ while ((tMatch = tPattern.exec(isMatch[1] ?? "")) !== null) {
302
+ parts.push(decodeXmlEntities(tMatch[1] ?? ""));
303
+ }
304
+
305
+ return parts.join("");
306
+ }
307
+
308
+ function parseMergeCells(mergeCellsXml: string, out: XlsxParsedMerge[]): void {
309
+ const mergePattern = /<mergeCell\b([^>]*?)(?:\/>|>[\s\S]*?<\/mergeCell>)/g;
310
+ let match: RegExpExecArray | null;
311
+
312
+ while ((match = mergePattern.exec(mergeCellsXml)) !== null) {
313
+ const attrs = parseXmlAttributes(match[1] ?? "");
314
+ const ref = attrs["ref"] ?? "";
315
+ const merge = parseMergeRef(ref);
316
+ if (merge !== null) {
317
+ out.push(merge);
318
+ }
319
+ }
320
+ }
321
+
322
+ function parseMergeRef(ref: string): XlsxParsedMerge | null {
323
+ const parts = ref.split(":");
324
+ if (parts.length !== 2) {
325
+ return null;
326
+ }
327
+
328
+ const start = parseCellRef(parts[0] ?? "");
329
+ const end = parseCellRef(parts[1] ?? "");
330
+ if (start === null || end === null) {
331
+ return null;
332
+ }
333
+
334
+ return {
335
+ startRow: start.row,
336
+ startCol: start.col,
337
+ endRow: end.row,
338
+ endCol: end.col,
339
+ };
340
+ }
341
+
342
+ function parseSheetDimension(xml: string): XlsxParsedDimension | null {
343
+ const dimensionMatch = /<dimension\b([^>]*?)(?:\/>|>)/i.exec(xml);
344
+ if (!dimensionMatch) {
345
+ return null;
346
+ }
347
+
348
+ const attrs = parseXmlAttributes(dimensionMatch[1] ?? "");
349
+ const ref = attrs["ref"];
350
+ if (!ref) {
351
+ return null;
352
+ }
353
+
354
+ return parseDimensionRef(ref);
355
+ }
356
+
357
+ const SHEET_PREFIX_PATTERN =
358
+ "(?:'(?:[^']|'')+'|[A-Za-z_][A-Za-z0-9_.]*)!";
359
+ const CELL_REFERENCE_PATTERN = "\\$?[A-Z]{1,3}\\$?[1-9][0-9]*";
360
+ const RANGE_REFERENCE_PATTERN =
361
+ `${CELL_REFERENCE_PATTERN}(?::${CELL_REFERENCE_PATTERN})?`;
362
+ const FORMULA_REFERENCE_PATTERN = new RegExp(
363
+ String.raw`(?<![A-Za-z0-9_.$])(?:${SHEET_PREFIX_PATTERN})?${RANGE_REFERENCE_PATTERN}(?![A-Za-z0-9_])`,
364
+ "g",
365
+ );
366
+
367
+ function extractFormulaReferenceTokens(formula: string): string[] {
368
+ const maskedFormula = maskQuotedFormulaStrings(formula);
369
+ const tokens: string[] = [];
370
+ const seen = new Set<string>();
371
+
372
+ for (const match of maskedFormula.matchAll(FORMULA_REFERENCE_PATTERN)) {
373
+ const index = match.index ?? -1;
374
+ if (index < 0) {
375
+ continue;
376
+ }
377
+ const token = formula.slice(index, index + match[0].length);
378
+ if (seen.has(token)) {
379
+ continue;
380
+ }
381
+ seen.add(token);
382
+ tokens.push(token);
383
+ }
384
+
385
+ return tokens;
386
+ }
387
+
388
+ function maskQuotedFormulaStrings(formula: string): string {
389
+ let output = "";
390
+ let inString = false;
391
+
392
+ for (let index = 0; index < formula.length; index += 1) {
393
+ const char = formula[index];
394
+ const next = formula[index + 1];
395
+
396
+ if (char === "\"") {
397
+ output += char;
398
+ if (inString && next === "\"") {
399
+ output += " ";
400
+ index += 1;
401
+ continue;
402
+ }
403
+ inString = !inString;
404
+ continue;
405
+ }
406
+
407
+ output += inString ? " " : char;
408
+ }
409
+
410
+ return output;
411
+ }
412
+
413
+ function parseDimensionRef(ref: string): XlsxParsedDimension | null {
414
+ const [startRef, endRef = startRef] = ref.split(":");
415
+ if (!startRef || !endRef) {
416
+ return null;
417
+ }
418
+
419
+ const start = parseCellRef(startRef);
420
+ const end = parseCellRef(endRef);
421
+ if (start === null || end === null) {
422
+ return null;
423
+ }
424
+
425
+ return {
426
+ startRow: start.row,
427
+ startCol: start.col,
428
+ endRow: end.row,
429
+ endCol: end.col,
430
+ };
431
+ }
432
+
433
+ function parseCellRef(ref: string): { row: number; col: number } | null {
434
+ const match = /^([A-Z]+)([0-9]+)$/i.exec(ref.trim());
435
+ if (!match) {
436
+ return null;
437
+ }
438
+
439
+ return {
440
+ col: colLettersToIndex(match[1] ?? ""),
441
+ row: parseInt(match[2] ?? "1", 10) - 1,
442
+ };
443
+ }
444
+
445
+ /**
446
+ * Converts a column letter sequence to a zero-based column index.
447
+ * "A" -> 0, "Z" -> 25, "AA" -> 26, "AZ" -> 51, "BA" -> 52.
448
+ */
449
+ function colLettersToIndex(letters: string): number {
450
+ let result = 0;
451
+
452
+ for (const char of letters.toUpperCase()) {
453
+ result = result * 26 + (char.charCodeAt(0) - 64);
454
+ }
455
+
456
+ return result - 1;
457
+ }
458
+
459
+ export { parseCellRef, colLettersToIndex };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Parses xl/styles.xml for the cellXfs table (cell format entries).
3
+ *
4
+ * Each entry provides style references (numFmtId, fontId, fillId, borderId)
5
+ * that cells reference by zero-based index via the s= attribute.
6
+ */
7
+ export interface XlsxStyleEntry {
8
+ numFmtId: number;
9
+ fontId: number;
10
+ fillId: number;
11
+ borderId: number;
12
+ rawAttributes: Record<string, string>;
13
+ }
14
+
15
+ export function parseStylesXml(xml: string): XlsxStyleEntry[] {
16
+ const cellXfsMatch = /<cellXfs\b[^>]*>([\s\S]*?)<\/cellXfs>/i.exec(xml);
17
+ if (!cellXfsMatch) {
18
+ return [];
19
+ }
20
+
21
+ const cellXfsContent = cellXfsMatch[1] ?? "";
22
+ const xfPattern = /<xf\b([^>]*?)(?:\/>|>[\s\S]*?<\/xf>)/g;
23
+ const entries: XlsxStyleEntry[] = [];
24
+ let xfMatch: RegExpExecArray | null;
25
+
26
+ while ((xfMatch = xfPattern.exec(cellXfsContent)) !== null) {
27
+ const attrs = parseXmlAttributes(xfMatch[1] ?? "");
28
+ entries.push({
29
+ numFmtId: parseIntAttr(attrs["numFmtId"], 0),
30
+ fontId: parseIntAttr(attrs["fontId"], 0),
31
+ fillId: parseIntAttr(attrs["fillId"], 0),
32
+ borderId: parseIntAttr(attrs["borderId"], 0),
33
+ rawAttributes: attrs,
34
+ });
35
+ }
36
+
37
+ return entries;
38
+ }
39
+
40
+ function parseIntAttr(value: string | undefined, defaultValue: number): number {
41
+ if (value === undefined || value === "") {
42
+ return defaultValue;
43
+ }
44
+
45
+ const parsed = parseInt(value, 10);
46
+ return Number.isNaN(parsed) ? defaultValue : parsed;
47
+ }
48
+
49
+ export function parseXmlAttributes(rawAttributes: string): Record<string, string> {
50
+ const attributes: Record<string, string> = {};
51
+ const attributePattern = /([A-Za-z_][\w:.-]*)="([^"]*)"/g;
52
+ let match: RegExpExecArray | null;
53
+
54
+ while ((match = attributePattern.exec(rawAttributes)) !== null) {
55
+ attributes[match[1]] = match[2];
56
+ }
57
+
58
+ return attributes;
59
+ }
@@ -0,0 +1,75 @@
1
+ import { parseXmlAttributes } from "./parse-styles.ts";
2
+
3
+ /**
4
+ * Represents a single sheet entry from the workbook's sheet registry.
5
+ */
6
+ export interface WorkbookSheetEntry {
7
+ /** Human-readable sheet name. */
8
+ name: string;
9
+ /** Workbook-internal numeric sheet ID string. */
10
+ sheetId: string;
11
+ /** Relationship ID used to look up the sheet part path. */
12
+ relationshipId: string;
13
+ /** Visibility state; defaults to "visible" when absent. */
14
+ state: "visible" | "hidden" | "veryHidden";
15
+ }
16
+
17
+ export interface WorkbookParseResult {
18
+ sheets: WorkbookSheetEntry[];
19
+ /**
20
+ * Whether the workbook uses the 1904 date base.
21
+ * Most xlsx files use 1900 (false). Mac-originated files may use 1904 (true).
22
+ */
23
+ date1904: boolean;
24
+ }
25
+
26
+ /**
27
+ * Parses xl/workbook.xml and returns the ordered sheet registry.
28
+ *
29
+ * The r:id attribute in <sheet> elements uses the XML namespace prefix r.
30
+ * The attribute parser handles namespace-prefixed names (e.g. "r:id") correctly.
31
+ */
32
+ export function parseWorkbookXml(xml: string): WorkbookParseResult {
33
+ const sheets: WorkbookSheetEntry[] = [];
34
+ const sheetPattern = /<sheet\b([^>]*?)(?:\/>|>[\s\S]*?<\/sheet>)/g;
35
+ let match: RegExpExecArray | null;
36
+
37
+ while ((match = sheetPattern.exec(xml)) !== null) {
38
+ const attrs = parseXmlAttributes(match[1] ?? "");
39
+ const name = attrs["name"] ?? "";
40
+ const sheetId = attrs["sheetId"] ?? "";
41
+ const relationshipId = attrs["r:id"] ?? attrs["id"] ?? "";
42
+
43
+ if (!name || !sheetId || !relationshipId) {
44
+ continue;
45
+ }
46
+
47
+ const stateAttr = attrs["state"];
48
+ const state: WorkbookSheetEntry["state"] =
49
+ stateAttr === "hidden"
50
+ ? "hidden"
51
+ : stateAttr === "veryHidden"
52
+ ? "veryHidden"
53
+ : "visible";
54
+
55
+ sheets.push({ name, sheetId, relationshipId, state });
56
+ }
57
+
58
+ const date1904 = parseDate1904(xml);
59
+
60
+ return { sheets, date1904 };
61
+ }
62
+
63
+ /**
64
+ * Extracts the date1904 flag from the <workbookPr> element.
65
+ * Returns false (1900 base) if the attribute is absent or not "1" or "true".
66
+ */
67
+ function parseDate1904(xml: string): boolean {
68
+ const workbookPrMatch = /<workbookPr\b([^>]*?)(?:\/>|>)/i.exec(xml);
69
+ if (!workbookPrMatch) {
70
+ return false;
71
+ }
72
+ const attrs = parseXmlAttributes(workbookPrMatch[1] ?? "");
73
+ const val = attrs["date1904"];
74
+ return val === "1" || val === "true";
75
+ }
@@ -0,0 +1,72 @@
1
+ import type { CanonicalWorkbook } from "../model/workbook.ts";
2
+ import { listSheets } from "../model/workbook.ts";
3
+
4
+ const SHARED_STRINGS_NAMESPACE = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
5
+
6
+ export interface SharedStringTableSerialization {
7
+ xml: string;
8
+ strings: string[];
9
+ indexByValue: Map<string, number>;
10
+ totalCount: number;
11
+ }
12
+
13
+ export function buildSharedStringsTable(
14
+ workbook: CanonicalWorkbook,
15
+ ): SharedStringTableSerialization {
16
+ const strings: string[] = [];
17
+ const indexByValue = new Map<string, number>();
18
+ let totalCount = 0;
19
+
20
+ for (const sheet of listSheets(workbook)) {
21
+ for (const cell of sheet.cells.values()) {
22
+ if (cell.kind !== "text") {
23
+ continue;
24
+ }
25
+
26
+ totalCount += 1;
27
+
28
+ if (!indexByValue.has(cell.value)) {
29
+ indexByValue.set(cell.value, strings.length);
30
+ strings.push(cell.value);
31
+ }
32
+ }
33
+ }
34
+
35
+ return {
36
+ xml: serializeSharedStringsXml(strings, totalCount),
37
+ strings,
38
+ indexByValue,
39
+ totalCount,
40
+ };
41
+ }
42
+
43
+ export function serializeSharedStringsXml(
44
+ strings: readonly string[],
45
+ totalCount: number = strings.length,
46
+ ): string {
47
+ const items = strings.map(serializeSharedStringItem);
48
+ const body = items.length > 0 ? `\n${items.join("\n")}\n` : "";
49
+
50
+ return [
51
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`,
52
+ `<sst xmlns="${SHARED_STRINGS_NAMESPACE}" count="${totalCount}" uniqueCount="${strings.length}">${body}</sst>`,
53
+ ].join("\n");
54
+ }
55
+
56
+ function serializeSharedStringItem(value: string): string {
57
+ const preserveSpace = requiresPreservedSpace(value) ? ` xml:space="preserve"` : "";
58
+ return ` <si><t${preserveSpace}>${escapeXml(value)}</t></si>`;
59
+ }
60
+
61
+ function requiresPreservedSpace(value: string): boolean {
62
+ return /^\s/.test(value) || /\s$/.test(value);
63
+ }
64
+
65
+ function escapeXml(value: string): string {
66
+ return value
67
+ .replace(/&/g, "&amp;")
68
+ .replace(/"/g, "&quot;")
69
+ .replace(/</g, "&lt;")
70
+ .replace(/>/g, "&gt;")
71
+ .replace(/'/g, "&apos;");
72
+ }