@office-kit/xlsx 0.8.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 (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +319 -0
  3. package/THIRD_PARTY_NOTICES.md +56 -0
  4. package/dist/cell/cell.d.ts +234 -0
  5. package/dist/cell/index.d.ts +4 -0
  6. package/dist/cell/rich-text.d.ts +37 -0
  7. package/dist/cell-D9CaNKnU.mjs +320 -0
  8. package/dist/cell-D9CaNKnU.mjs.map +1 -0
  9. package/dist/cell-style-BEDjMX1y.mjs +1579 -0
  10. package/dist/cell-style-BEDjMX1y.mjs.map +1 -0
  11. package/dist/cell.mjs +2 -0
  12. package/dist/chart/chart-xml.d.ts +16 -0
  13. package/dist/chart/chart.d.ts +735 -0
  14. package/dist/chart/cx/chartex-xml.d.ts +6 -0
  15. package/dist/chart/cx/chartex.d.ts +279 -0
  16. package/dist/chart/index.d.ts +6 -0
  17. package/dist/chart/user-shapes-xml.d.ts +4 -0
  18. package/dist/chart/user-shapes.d.ts +61 -0
  19. package/dist/chart.mjs +232 -0
  20. package/dist/chart.mjs.map +1 -0
  21. package/dist/chartsheet/chartsheet-xml.d.ts +17 -0
  22. package/dist/chartsheet/chartsheet.d.ts +121 -0
  23. package/dist/chartsheet/index.d.ts +2 -0
  24. package/dist/chartsheet-C3-tqkPy.mjs +23 -0
  25. package/dist/chartsheet-C3-tqkPy.mjs.map +1 -0
  26. package/dist/chartsheet.mjs +2 -0
  27. package/dist/colors-ovWAwnZI.mjs +67 -0
  28. package/dist/colors-ovWAwnZI.mjs.map +1 -0
  29. package/dist/compat/numbers.d.ts +14 -0
  30. package/dist/coordinate-96Ecci4d.mjs +276 -0
  31. package/dist/coordinate-96Ecci4d.mjs.map +1 -0
  32. package/dist/datetime-B2ySVlXt.mjs +71 -0
  33. package/dist/datetime-B2ySVlXt.mjs.map +1 -0
  34. package/dist/defined-names-CviWmtQg.mjs +89 -0
  35. package/dist/defined-names-CviWmtQg.mjs.map +1 -0
  36. package/dist/differential-D4dg-qtZ.mjs +37 -0
  37. package/dist/differential-D4dg-qtZ.mjs.map +1 -0
  38. package/dist/drawing/anchor.d.ts +63 -0
  39. package/dist/drawing/dml/colors.d.ts +109 -0
  40. package/dist/drawing/dml/dml-xml.d.ts +35 -0
  41. package/dist/drawing/dml/effect.d.ts +92 -0
  42. package/dist/drawing/dml/fill.d.ts +115 -0
  43. package/dist/drawing/dml/geometry.d.ts +113 -0
  44. package/dist/drawing/dml/line.d.ts +41 -0
  45. package/dist/drawing/dml/shape-properties.d.ts +33 -0
  46. package/dist/drawing/dml/text.d.ts +218 -0
  47. package/dist/drawing/drawing-xml.d.ts +5 -0
  48. package/dist/drawing/drawing.d.ts +117 -0
  49. package/dist/drawing/image.d.ts +40 -0
  50. package/dist/drawing/index.d.ts +14 -0
  51. package/dist/drawing-BxzLuryn.mjs +415 -0
  52. package/dist/drawing-BxzLuryn.mjs.map +1 -0
  53. package/dist/drawing.mjs +119 -0
  54. package/dist/drawing.mjs.map +1 -0
  55. package/dist/escape-DFTE7ZJc.mjs +51 -0
  56. package/dist/escape-DFTE7ZJc.mjs.map +1 -0
  57. package/dist/exceptions-D-CFwxgm.mjs +37 -0
  58. package/dist/exceptions-D-CFwxgm.mjs.map +1 -0
  59. package/dist/formula/tokenizer.d.ts +61 -0
  60. package/dist/formula/translate.d.ts +67 -0
  61. package/dist/inference-B3ES3KEJ.mjs +42 -0
  62. package/dist/inference-B3ES3KEJ.mjs.map +1 -0
  63. package/dist/io/browser.d.ts +41 -0
  64. package/dist/io/index.d.ts +7 -0
  65. package/dist/io/load.d.ts +46 -0
  66. package/dist/io/node-fs.d.ts +62 -0
  67. package/dist/io/node-save.d.ts +3 -0
  68. package/dist/io/node.d.ts +17 -0
  69. package/dist/io/save.d.ts +14 -0
  70. package/dist/io/sink.d.ts +54 -0
  71. package/dist/io/source.d.ts +14 -0
  72. package/dist/io.mjs +212 -0
  73. package/dist/io.mjs.map +1 -0
  74. package/dist/load-D5cbhoGx.mjs +1069 -0
  75. package/dist/load-D5cbhoGx.mjs.map +1 -0
  76. package/dist/manifest-Dps1-OpP.mjs +801 -0
  77. package/dist/manifest-Dps1-OpP.mjs.map +1 -0
  78. package/dist/node.d.ts +3 -0
  79. package/dist/node.mjs +308 -0
  80. package/dist/node.mjs.map +1 -0
  81. package/dist/packaging/core.d.ts +45 -0
  82. package/dist/packaging/custom.d.ts +62 -0
  83. package/dist/packaging/extended.d.ts +45 -0
  84. package/dist/packaging/index.d.ts +10 -0
  85. package/dist/packaging/manifest.d.ts +24 -0
  86. package/dist/packaging/relationships.d.ts +30 -0
  87. package/dist/packaging.mjs +2 -0
  88. package/dist/parser-DuLejQy1.mjs +156 -0
  89. package/dist/parser-DuLejQy1.mjs.map +1 -0
  90. package/dist/reader-D1fNW9k1.mjs +534 -0
  91. package/dist/reader-D1fNW9k1.mjs.map +1 -0
  92. package/dist/save-RohQtgEZ.mjs +745 -0
  93. package/dist/save-RohQtgEZ.mjs.map +1 -0
  94. package/dist/schema/core.d.ts +133 -0
  95. package/dist/schema/index.d.ts +3 -0
  96. package/dist/schema/serialize.d.ts +6 -0
  97. package/dist/schema.mjs +2 -0
  98. package/dist/serialize-55EnT30e.mjs +254 -0
  99. package/dist/serialize-55EnT30e.mjs.map +1 -0
  100. package/dist/serializer-BwbgHYJV.mjs +116 -0
  101. package/dist/serializer-BwbgHYJV.mjs.map +1 -0
  102. package/dist/streaming/index.d.ts +2 -0
  103. package/dist/streaming/read-only.d.ts +38 -0
  104. package/dist/streaming/write-only.d.ts +47 -0
  105. package/dist/streaming.mjs +612 -0
  106. package/dist/streaming.mjs.map +1 -0
  107. package/dist/styles/alignment.d.ts +33 -0
  108. package/dist/styles/alignment.schema.d.ts +3 -0
  109. package/dist/styles/borders.d.ts +40 -0
  110. package/dist/styles/borders.schema.d.ts +4 -0
  111. package/dist/styles/cell-style.d.ts +270 -0
  112. package/dist/styles/colors.d.ts +128 -0
  113. package/dist/styles/colors.schema.d.ts +3 -0
  114. package/dist/styles/differential.d.ts +41 -0
  115. package/dist/styles/fills.d.ts +54 -0
  116. package/dist/styles/fills.schema.d.ts +6 -0
  117. package/dist/styles/fonts.d.ts +44 -0
  118. package/dist/styles/fonts.schema.d.ts +3 -0
  119. package/dist/styles/index.d.ts +21 -0
  120. package/dist/styles/named-styles.d.ts +52 -0
  121. package/dist/styles/numbers.d.ts +39 -0
  122. package/dist/styles/numbers.schema.d.ts +3 -0
  123. package/dist/styles/protection.d.ts +9 -0
  124. package/dist/styles/protection.schema.d.ts +3 -0
  125. package/dist/styles/stylesheet-reader.d.ts +7 -0
  126. package/dist/styles/stylesheet-writer.d.ts +3 -0
  127. package/dist/styles/stylesheet.d.ts +95 -0
  128. package/dist/styles.mjs +4 -0
  129. package/dist/stylesheet-writer-C2eRmn22.mjs +8624 -0
  130. package/dist/stylesheet-writer-C2eRmn22.mjs.map +1 -0
  131. package/dist/table-DkX6UniA.mjs +113 -0
  132. package/dist/table-DkX6UniA.mjs.map +1 -0
  133. package/dist/tree-Bbs1C8Rc.mjs +192 -0
  134. package/dist/tree-Bbs1C8Rc.mjs.map +1 -0
  135. package/dist/units-rOMQqXh2.mjs +41 -0
  136. package/dist/units-rOMQqXh2.mjs.map +1 -0
  137. package/dist/user-shapes-DfmCGKB0.mjs +252 -0
  138. package/dist/user-shapes-DfmCGKB0.mjs.map +1 -0
  139. package/dist/utf8-D91g1XTG.mjs +143 -0
  140. package/dist/utf8-D91g1XTG.mjs.map +1 -0
  141. package/dist/utils/coordinate.d.ts +103 -0
  142. package/dist/utils/css.d.ts +18 -0
  143. package/dist/utils/datetime.d.ts +38 -0
  144. package/dist/utils/escape.d.ts +34 -0
  145. package/dist/utils/exceptions.d.ts +34 -0
  146. package/dist/utils/index.d.ts +11 -0
  147. package/dist/utils/inference.d.ts +24 -0
  148. package/dist/utils/stable-stringify.d.ts +7 -0
  149. package/dist/utils/units.d.ts +14 -0
  150. package/dist/utils/utf8.d.ts +1 -0
  151. package/dist/utils.mjs +39 -0
  152. package/dist/utils.mjs.map +1 -0
  153. package/dist/workbook/calc-properties.d.ts +47 -0
  154. package/dist/workbook/defined-names.d.ts +121 -0
  155. package/dist/workbook/file-recovery.d.ts +11 -0
  156. package/dist/workbook/file-sharing.d.ts +14 -0
  157. package/dist/workbook/file-version.d.ts +13 -0
  158. package/dist/workbook/function-groups.d.ts +10 -0
  159. package/dist/workbook/index.d.ts +24 -0
  160. package/dist/workbook/protection.d.ts +35 -0
  161. package/dist/workbook/shared-strings.d.ts +57 -0
  162. package/dist/workbook/smart-tags.d.ts +13 -0
  163. package/dist/workbook/views.d.ts +89 -0
  164. package/dist/workbook/workbook-properties.d.ts +57 -0
  165. package/dist/workbook/workbook.d.ts +643 -0
  166. package/dist/workbook-HGYNRBlV.mjs +636 -0
  167. package/dist/workbook-HGYNRBlV.mjs.map +1 -0
  168. package/dist/workbook.mjs +58 -0
  169. package/dist/workbook.mjs.map +1 -0
  170. package/dist/worksheet/auto-filter.d.ts +34 -0
  171. package/dist/worksheet/cell-range.d.ts +121 -0
  172. package/dist/worksheet/comments-xml.d.ts +24 -0
  173. package/dist/worksheet/comments.d.ts +13 -0
  174. package/dist/worksheet/conditional-formatting.d.ts +150 -0
  175. package/dist/worksheet/custom-sheet-views.d.ts +43 -0
  176. package/dist/worksheet/data-consolidate.d.ts +29 -0
  177. package/dist/worksheet/data-validations.d.ts +72 -0
  178. package/dist/worksheet/dimensions.d.ts +40 -0
  179. package/dist/worksheet/errors.d.ts +40 -0
  180. package/dist/worksheet/hyperlinks.d.ts +42 -0
  181. package/dist/worksheet/index.d.ts +46 -0
  182. package/dist/worksheet/ole-objects.d.ts +37 -0
  183. package/dist/worksheet/page-setup.d.ts +173 -0
  184. package/dist/worksheet/phonetic.d.ts +11 -0
  185. package/dist/worksheet/properties.d.ts +34 -0
  186. package/dist/worksheet/protected-ranges.d.ts +19 -0
  187. package/dist/worksheet/protection.d.ts +44 -0
  188. package/dist/worksheet/reader.d.ts +38 -0
  189. package/dist/worksheet/scenarios.d.ts +36 -0
  190. package/dist/worksheet/smart-tags.d.ts +23 -0
  191. package/dist/worksheet/sort-state.d.ts +28 -0
  192. package/dist/worksheet/table-xml.d.ts +5 -0
  193. package/dist/worksheet/table.d.ts +80 -0
  194. package/dist/worksheet/views.d.ts +47 -0
  195. package/dist/worksheet/web-publish.d.ts +21 -0
  196. package/dist/worksheet/worksheet.d.ts +935 -0
  197. package/dist/worksheet/writer.d.ts +72 -0
  198. package/dist/worksheet-CmCNoIgD.mjs +1726 -0
  199. package/dist/worksheet-CmCNoIgD.mjs.map +1 -0
  200. package/dist/worksheet.mjs +247 -0
  201. package/dist/worksheet.mjs.map +1 -0
  202. package/dist/writer-DspzfkNA.mjs +221 -0
  203. package/dist/writer-DspzfkNA.mjs.map +1 -0
  204. package/dist/xml/index.d.ts +10 -0
  205. package/dist/xml/iterparse.d.ts +22 -0
  206. package/dist/xml/namespaces.d.ts +91 -0
  207. package/dist/xml/parser.d.ts +7 -0
  208. package/dist/xml/serializer.d.ts +14 -0
  209. package/dist/xml/stream-writer.d.ts +39 -0
  210. package/dist/xml/tree.d.ts +37 -0
  211. package/dist/xml.mjs +140 -0
  212. package/dist/xml.mjs.map +1 -0
  213. package/dist/zip/decompression-guard.d.ts +70 -0
  214. package/dist/zip/index.d.ts +6 -0
  215. package/dist/zip/random-access-reader.d.ts +16 -0
  216. package/dist/zip/reader.d.ts +45 -0
  217. package/dist/zip/writer.d.ts +65 -0
  218. package/dist/zip/zip64-patch.d.ts +12 -0
  219. package/dist/zip.mjs +3 -0
  220. package/package.json +147 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datetime-B2ySVlXt.mjs","names":[],"sources":["../src/utils/datetime.ts"],"sourcesContent":["// Excel <-> JavaScript Date conversions. Mirrors\n// openpyxl/openpyxl/utils/datetime.py.\n//\n// Excel stores datetimes as fractional \"serial days\" since an epoch. Two epochs\n// are in use:\n// * Windows (\"1900 date system\", default): epoch 1899-12-30 with the\n// well-known 1900 leap-year bug — Excel treats 1900-02-29 as a\n// valid day even though it isn't. We collapse that phantom day\n// onto 1900-02-28 (the openpyxl approach), so date math past\n// March 1, 1900 stays consistent without leaking the bug.\n// * Mac (\"1904 date system\"): epoch 1904-01-01, no leap bug.\n//\n// Dates stay as numeric serials on the worksheet hot path; conversion to a JS\n// Date happens lazily only when callers ask. JS Dates are interpreted in UTC\n// throughout to avoid timezone drift between read and write.\n\nimport { OpenXmlSchemaError } from './exceptions';\n\n/** Excel epoch identifier. */\nexport type ExcelEpoch = 'windows' | 'mac';\n\n/** 1899-12-30 (UTC) — the Windows / 1900-system epoch in ms. */\nexport const WINDOWS_EPOCH_MS = Date.UTC(1899, 11, 30);\n/** 1904-01-01 (UTC) — the Mac / 1904-system epoch in ms. */\nexport const MAC_EPOCH_MS = Date.UTC(1904, 0, 1);\n\nconst MS_PER_DAY = 86_400_000;\n/** Serial day index of the phantom 1900-02-29; absorbed onto 1900-02-28. */\nconst LEAP_DUPLICATE_DAY = 60;\n\nconst epochMs = (e: ExcelEpoch | undefined): number => (e === 'mac' ? MAC_EPOCH_MS : WINDOWS_EPOCH_MS);\n\n/**\n * Convert an Excel serial date into a JS `Date` (UTC). The fractional part is\n * treated as a fraction of a day. For Windows 1900 the leap-bug compensation\n * kicks in for serials in [0, 60).\n */\nexport function excelToDate(serial: number, opts?: { epoch?: ExcelEpoch }): Date {\n if (!Number.isFinite(serial)) {\n throw new OpenXmlSchemaError(`excelToDate: serial \"${serial}\" is not finite`);\n }\n const epoch = epochMs(opts?.epoch);\n const day = Math.floor(serial);\n const fraction = serial - day;\n const isWindows = epoch === WINDOWS_EPOCH_MS;\n // Windows quirk: bump days [0, 60) by one so the day count lines up with\n // Excel's serial numbering through the phantom Feb 29 1900.\n const dayAdjusted = isWindows && serial >= 0 && serial < LEAP_DUPLICATE_DAY ? day + 1 : day;\n const ms = epoch + dayAdjusted * MS_PER_DAY + Math.round(fraction * MS_PER_DAY);\n return new Date(ms);\n}\n\n/**\n * Convert a JS `Date` into an Excel serial. The Date is read in UTC. On Windows\n * 1900, dates ≤ 1900-02-28 get a -1 day correction to account for Excel's\n * phantom leap day.\n */\nexport function dateToExcel(date: Date, opts?: { epoch?: ExcelEpoch }): number {\n const t = date.getTime();\n if (!Number.isFinite(t)) {\n throw new OpenXmlSchemaError('dateToExcel: invalid Date');\n }\n const epoch = epochMs(opts?.epoch);\n const dayStartMs = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());\n const days = Math.round((dayStartMs - epoch) / MS_PER_DAY);\n const subDay = (t - dayStartMs) / MS_PER_DAY;\n const isWindows = epoch === WINDOWS_EPOCH_MS;\n const daysAdjusted = isWindows && days <= LEAP_DUPLICATE_DAY ? days - 1 : days;\n return daysAdjusted + subDay;\n}\n\n/** Excel duration serial (fraction of a day) → milliseconds. */\nexport function excelToDuration(serial: number): number {\n if (!Number.isFinite(serial)) {\n throw new OpenXmlSchemaError(`excelToDuration: serial \"${serial}\" is not finite`);\n }\n return Math.round(serial * MS_PER_DAY);\n}\n\n/** Milliseconds → Excel duration serial (fraction of a day). */\nexport function durationToExcel(ms: number): number {\n if (!Number.isFinite(ms)) {\n throw new OpenXmlSchemaError(`durationToExcel: ms \"${ms}\" is not finite`);\n }\n return ms / MS_PER_DAY;\n}\n\n// ---- ISO 8601 helpers ------------------------------------------------------\n\n/**\n * Parse an ISO-8601 / W3CDTF datetime string into a `Date`. Same grammar as\n * `new Date(string)`; the wrapper just adds typed error reporting and a\n * stricter \"must be a recognised ISO\" guard.\n */\nexport function fromIso8601(s: string): Date {\n if (typeof s !== 'string' || s.length === 0) {\n throw new OpenXmlSchemaError(`fromIso8601: empty input`);\n }\n const d = new Date(s);\n if (Number.isNaN(d.getTime())) {\n throw new OpenXmlSchemaError(`fromIso8601: invalid datetime \"${s}\"`);\n }\n return d;\n}\n\n/**\n * Format a `Date` as ISO-8601 with second precision in UTC. Trims the\n * millisecond fragment that `Date.toISOString()` always produces, so the output\n * matches Excel / openpyxl's W3CDTF style.\n */\nexport function toIso8601(d: Date): string {\n if (Number.isNaN(d.getTime())) {\n throw new OpenXmlSchemaError('toIso8601: invalid Date');\n }\n return d.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n"],"mappings":";;;AAsBA,MAAa,mBAAmB,KAAK,IAAI,MAAM,IAAI,EAAE;;AAErD,MAAa,eAAe,KAAK,IAAI,MAAM,GAAG,CAAC;AAE/C,MAAM,aAAa;;AAEnB,MAAM,qBAAqB;AAE3B,MAAM,WAAW,MAAuC,MAAM,QAAQ,eAAe;;;;;;AAOrF,SAAgB,YAAY,QAAgB,MAAqC;CAC/E,IAAI,CAAC,OAAO,SAAS,MAAM,GACzB,MAAM,IAAI,mBAAmB,wBAAwB,OAAO,gBAAgB;CAE9E,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,MAAM,MAAM,KAAK,MAAM,MAAM;CAC7B,MAAM,WAAW,SAAS;CAK1B,MAAM,KAAK,SAJO,UAAU,oBAGK,UAAU,KAAK,SAAS,qBAAqB,MAAM,IAAI,OACvD,aAAa,KAAK,MAAM,WAAW,UAAU;CAC9E,OAAO,IAAI,KAAK,EAAE;AACpB;;;;;;AAOA,SAAgB,YAAY,MAAY,MAAuC;CAC7E,MAAM,IAAI,KAAK,QAAQ;CACvB,IAAI,CAAC,OAAO,SAAS,CAAC,GACpB,MAAM,IAAI,mBAAmB,2BAA2B;CAE1D,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,MAAM,aAAa,KAAK,IAAI,KAAK,eAAe,GAAG,KAAK,YAAY,GAAG,KAAK,WAAW,CAAC;CACxF,MAAM,OAAO,KAAK,OAAO,aAAa,SAAS,UAAU;CACzD,MAAM,UAAU,IAAI,cAAc;CAGlC,QAFkB,UAAU,oBACM,QAAQ,qBAAqB,OAAO,IAAI,QACpD;AACxB;;AAGA,SAAgB,gBAAgB,QAAwB;CACtD,IAAI,CAAC,OAAO,SAAS,MAAM,GACzB,MAAM,IAAI,mBAAmB,4BAA4B,OAAO,gBAAgB;CAElF,OAAO,KAAK,MAAM,SAAS,UAAU;AACvC;;AAGA,SAAgB,gBAAgB,IAAoB;CAClD,IAAI,CAAC,OAAO,SAAS,EAAE,GACrB,MAAM,IAAI,mBAAmB,wBAAwB,GAAG,gBAAgB;CAE1E,OAAO,KAAK;AACd;;;;;;AASA,SAAgB,YAAY,GAAiB;CAC3C,IAAI,OAAO,MAAM,YAAY,EAAE,WAAW,GACxC,MAAM,IAAI,mBAAmB,0BAA0B;CAEzD,MAAM,IAAI,IAAI,KAAK,CAAC;CACpB,IAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,GAC1B,MAAM,IAAI,mBAAmB,kCAAkC,EAAE,EAAE;CAErE,OAAO;AACT;;;;;;AAOA,SAAgB,UAAU,GAAiB;CACzC,IAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,GAC1B,MAAM,IAAI,mBAAmB,yBAAyB;CAExD,OAAO,EAAE,YAAY,EAAE,QAAQ,aAAa,GAAG;AACjD"}
@@ -0,0 +1,89 @@
1
+ import { m as parseSheetRange } from "./coordinate-96Ecci4d.mjs";
2
+ //#region src/workbook/defined-names.ts
3
+ function makeDefinedName(opts) {
4
+ return {
5
+ name: opts.name,
6
+ value: opts.value,
7
+ ...opts.scope !== void 0 ? { scope: opts.scope } : {},
8
+ ...opts.hidden !== void 0 ? { hidden: opts.hidden } : {},
9
+ ...opts.comment !== void 0 ? { comment: opts.comment } : {}
10
+ };
11
+ }
12
+ /**
13
+ * Add a workbook-scope or sheet-scope defined name. If a defined name with the
14
+ * same `name` (and `scope`) already exists, it's replaced — Excel allows one
15
+ * workbook-scope and one per-sheet-scope name, but not two with the same scope.
16
+ * Returns the resulting `DefinedName`.
17
+ */
18
+ const addDefinedName = (wb, opts) => {
19
+ const dn = makeDefinedName(opts);
20
+ const idx = wb.definedNames.findIndex((d) => d.name === dn.name && d.scope === dn.scope);
21
+ if (idx >= 0) wb.definedNames[idx] = dn;
22
+ else wb.definedNames.push(dn);
23
+ return dn;
24
+ };
25
+ /** Look up a defined name by identifier and (optional) sheet scope. */
26
+ const getDefinedName = (wb, name, scope) => wb.definedNames.find((d) => d.name === name && d.scope === scope);
27
+ /**
28
+ * Resolve a defined name's `value` into one or more {@link DefinedNameTarget}s.
29
+ * Comma-separated values (e.g. `_xlnm.Print_Titles` typically sets
30
+ * `Sheet!$1:$1,Sheet!$A:$A`) yield one entry per leg; a plain `Sheet!A1:B5`
31
+ * yields a single-element array.
32
+ *
33
+ * Returns `undefined` when the name doesn't exist; throws when the value can't
34
+ * be parsed (e.g. a constant or a non-range formula — defined names are
35
+ * sometimes used for things like `=42` or `=SUM(A:A)` which aren't ranges).
36
+ */
37
+ const getDefinedNameTarget = (wb, name, scope) => {
38
+ const dn = getDefinedName(wb, name, scope);
39
+ if (!dn) return void 0;
40
+ const legs = [];
41
+ let current = "";
42
+ let inQuote = false;
43
+ for (let i = 0; i < dn.value.length; i++) {
44
+ const c = dn.value[i];
45
+ if (c === "'") {
46
+ if (inQuote && dn.value[i + 1] === "'") {
47
+ current += "''";
48
+ i++;
49
+ continue;
50
+ }
51
+ inQuote = !inQuote;
52
+ current += c;
53
+ continue;
54
+ }
55
+ if (c === "," && !inQuote) {
56
+ legs.push(current);
57
+ current = "";
58
+ continue;
59
+ }
60
+ current += c;
61
+ }
62
+ if (current.length > 0) legs.push(current);
63
+ return legs.map((leg) => parseSheetRange(leg));
64
+ };
65
+ /**
66
+ * Remove a defined name by identifier + scope. Returns true if any entry was
67
+ * removed.
68
+ */
69
+ const removeDefinedName = (wb, name, scope) => {
70
+ const idx = wb.definedNames.findIndex((d) => d.name === name && d.scope === scope);
71
+ if (idx < 0) return false;
72
+ wb.definedNames.splice(idx, 1);
73
+ return true;
74
+ };
75
+ /**
76
+ * Read-only snapshot of every defined name. Pass `{ scope }` to narrow to
77
+ * workbook-scope (`scope: undefined`) or one specific sheet (`scope: 0`) — omit
78
+ * the option entirely to list all.
79
+ */
80
+ const listDefinedNames = (wb, opts = {}) => {
81
+ const scope = opts.scope ?? "all";
82
+ if (scope === "all") return wb.definedNames;
83
+ if (scope === "workbook") return wb.definedNames.filter((d) => d.scope === void 0);
84
+ return wb.definedNames.filter((d) => d.scope === scope);
85
+ };
86
+ //#endregion
87
+ export { makeDefinedName as a, listDefinedNames as i, getDefinedName as n, removeDefinedName as o, getDefinedNameTarget as r, addDefinedName as t };
88
+
89
+ //# sourceMappingURL=defined-names-CviWmtQg.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defined-names-CviWmtQg.mjs","names":[],"sources":["../src/workbook/defined-names.ts"],"sourcesContent":["// Workbook-level defined names. Models the OOXML schema's `<definedName>` element.\n//\n// A defined name binds an identifier to a formula-style value (`'Sheet\n// 1'!$A$1:$B$10`, `SUM(A:A)`, etc). Workbook-scope names omit `localSheetId`;\n// sheet-scope names use the 0-based sheet index. Excel reserves a handful of\n// names with the `_xlnm.` prefix for built-in uses (Print_Area, Print_Titles,\n// Sheet_Title, etc) — those round-trip here as plain DefinedName entries since\n// the value semantics are the same.\n\nimport { OpenXmlSchemaError } from '../utils/exceptions';\n\nexport interface DefinedName {\n /** Identifier — `_xlnm.Print_Area` for built-ins, otherwise user-chosen. */\n name: string;\n /** The formula expression the name points at. */\n value: string;\n /** 0-based sheet index for sheet-scope names; undefined → workbook-scope. */\n scope?: number;\n /** Hidden from the Name Manager when true. */\n hidden?: boolean;\n /** Optional human-readable description. */\n comment?: string;\n}\n\nexport function makeDefinedName(opts: Partial<DefinedName> & { name: string; value: string }): DefinedName {\n return {\n name: opts.name,\n value: opts.value,\n ...(opts.scope !== undefined ? { scope: opts.scope } : {}),\n ...(opts.hidden !== undefined ? { hidden: opts.hidden } : {}),\n ...(opts.comment !== undefined ? { comment: opts.comment } : {}),\n };\n}\n\n// ---- Workbook ergonomic helpers -----------------------------------------\n\nimport { type CellRangeBoundaries, parseSheetRange } from '../utils/coordinate';\nimport type { Worksheet } from '../worksheet/worksheet';\nimport { getRangeAddress } from '../worksheet/worksheet';\nimport type { Workbook } from './workbook';\n\n/**\n * One parsed leg of a defined name's value. Defined-name values can be\n * comma-separated multi-range expressions (e.g. `_xlnm.Print_Titles` sets\n * `Sheet!$1:$1,Sheet!$A:$A`); this represents one such leg.\n */\nexport interface DefinedNameTarget {\n sheet: string;\n range: string;\n bounds: CellRangeBoundaries;\n}\n\n/**\n * Add a workbook-scope or sheet-scope defined name. If a defined name with the\n * same `name` (and `scope`) already exists, it's replaced — Excel allows one\n * workbook-scope and one per-sheet-scope name, but not two with the same scope.\n * Returns the resulting `DefinedName`.\n */\nexport const addDefinedName = (\n wb: Workbook,\n opts: Partial<DefinedName> & { name: string; value: string },\n): DefinedName => {\n const dn = makeDefinedName(opts);\n // Replace any existing entry with the same name + scope.\n const idx = wb.definedNames.findIndex((d) => d.name === dn.name && d.scope === dn.scope);\n if (idx >= 0) {\n wb.definedNames[idx] = dn;\n } else {\n wb.definedNames.push(dn);\n }\n return dn;\n};\n\n/**\n * High-level: register a defined name pointing at a worksheet range. Combines\n * {@link getRangeAddress} (sheet-qualified, properly quoted) with {@link\n * addDefinedName}, so the caller doesn't have to assemble the formula string by\n * hand.\n *\n * Pass `opts.localToSheet: true` to scope the name to the worksheet (instead of\n * the workbook). Re-using the same `name` + scope replaces the previous entry\n * (Excel's per-scope-uniqueness rule).\n *\n * Throws when `localToSheet: true` is set but the worksheet isn't on\n * `wb.sheets` — that would be a stale Worksheet reference.\n */\nexport const addDefinedNameForRange = (\n wb: Workbook,\n name: string,\n ws: Worksheet,\n range: string,\n opts: { localToSheet?: boolean; hidden?: boolean; comment?: string } = {},\n): DefinedName => {\n const value = getRangeAddress(ws, range);\n let scope: number | undefined;\n if (opts.localToSheet) {\n const idx = wb.sheets.findIndex((s) => s.sheet === ws);\n if (idx < 0) {\n throw new OpenXmlSchemaError(\n `addDefinedNameForRange: worksheet \"${ws.title}\" is not registered on this workbook`,\n );\n }\n scope = idx;\n }\n return addDefinedName(wb, {\n name,\n value,\n ...(scope !== undefined ? { scope } : {}),\n ...(opts.hidden !== undefined ? { hidden: opts.hidden } : {}),\n ...(opts.comment !== undefined ? { comment: opts.comment } : {}),\n });\n};\n\n/** Look up a defined name by identifier and (optional) sheet scope. */\nexport const getDefinedName = (\n wb: Workbook,\n name: string,\n scope?: number,\n): DefinedName | undefined => wb.definedNames.find((d) => d.name === name && d.scope === scope);\n\n/**\n * Resolve a defined name's `value` into one or more {@link DefinedNameTarget}s.\n * Comma-separated values (e.g. `_xlnm.Print_Titles` typically sets\n * `Sheet!$1:$1,Sheet!$A:$A`) yield one entry per leg; a plain `Sheet!A1:B5`\n * yields a single-element array.\n *\n * Returns `undefined` when the name doesn't exist; throws when the value can't\n * be parsed (e.g. a constant or a non-range formula — defined names are\n * sometimes used for things like `=42` or `=SUM(A:A)` which aren't ranges).\n */\nexport const getDefinedNameTarget = (\n wb: Workbook,\n name: string,\n scope?: number,\n): DefinedNameTarget[] | undefined => {\n const dn = getDefinedName(wb, name, scope);\n if (!dn) return undefined;\n // Defined-name values use `,` as the leg separator. Sheet titles can\n // themselves contain commas inside `'...'` quotes — split on commas that\n // aren't inside an unbalanced single-quoted segment.\n const legs: string[] = [];\n let current = '';\n let inQuote = false;\n for (let i = 0; i < dn.value.length; i++) {\n const c = dn.value[i];\n if (c === \"'\") {\n // Doubled `''` inside a quoted run is the escape for a literal apostrophe\n // — skip the second one without flipping the state.\n if (inQuote && dn.value[i + 1] === \"'\") {\n current += \"''\";\n i++;\n continue;\n }\n inQuote = !inQuote;\n current += c;\n continue;\n }\n if (c === ',' && !inQuote) {\n legs.push(current);\n current = '';\n continue;\n }\n current += c;\n }\n if (current.length > 0) legs.push(current);\n return legs.map((leg) => parseSheetRange(leg));\n};\n\n/**\n * Remove a defined name by identifier + scope. Returns true if any entry was\n * removed.\n */\nexport const removeDefinedName = (wb: Workbook, name: string, scope?: number): boolean => {\n const idx = wb.definedNames.findIndex((d) => d.name === name && d.scope === scope);\n if (idx < 0) return false;\n wb.definedNames.splice(idx, 1);\n return true;\n};\n\n/**\n * Read-only snapshot of every defined name. Pass `{ scope }` to narrow to\n * workbook-scope (`scope: undefined`) or one specific sheet (`scope: 0`) — omit\n * the option entirely to list all.\n */\nexport const listDefinedNames = (\n wb: Workbook,\n opts: { scope?: number | 'workbook' | 'all' } = {},\n): ReadonlyArray<DefinedName> => {\n const scope = opts.scope ?? 'all';\n if (scope === 'all') return wb.definedNames;\n if (scope === 'workbook') return wb.definedNames.filter((d) => d.scope === undefined);\n return wb.definedNames.filter((d) => d.scope === scope);\n};\n\n/**\n * Bulk-remove every defined name matching `predicate`. Returns the count\n * removed. Mirrors {@link removeDataValidations} on worksheets.\n */\nexport const removeDefinedNames = (\n wb: Workbook,\n predicate: (d: DefinedName) => boolean,\n): number => {\n const before = wb.definedNames.length;\n wb.definedNames = wb.definedNames.filter((d) => !predicate(d));\n return before - wb.definedNames.length;\n};\n\n/**\n * Rename a defined name, scoped or workbook-scope. Returns `true` when an entry\n * was renamed. Throws when `newName` is already taken with the same scope\n * (Excel forbids duplicates within a scope).\n */\nexport const renameDefinedName = (\n wb: Workbook,\n oldName: string,\n newName: string,\n scope?: number,\n): boolean => {\n const idx = wb.definedNames.findIndex((d) => d.name === oldName && d.scope === scope);\n if (idx < 0) return false;\n const conflict = wb.definedNames.findIndex((d, i) => i !== idx && d.name === newName && d.scope === scope);\n if (conflict >= 0) {\n throw new OpenXmlSchemaError(`renameDefinedName: \"${newName}\" is already in use at the same scope`);\n }\n const existing = wb.definedNames[idx];\n if (!existing) return false;\n wb.definedNames[idx] = { ...existing, name: newName };\n return true;\n};\n\n/**\n * Read-only snapshot of every `_xlnm.Print_Area` defined name. Each entry is\n * the raw DefinedName carrying `scope` (sheet index) and `value` (the\n * print-area expression like `'Sheet1'!$A$1:$D$10`).\n */\nexport const listPrintAreas = (wb: Workbook): ReadonlyArray<DefinedName> =>\n wb.definedNames.filter((d) => d.name === '_xlnm.Print_Area');\n\n/**\n * Read-only snapshot of every `_xlnm.Print_Titles` defined name. Each entry's\n * `value` is the title-row / title-col expression Excel re-uses on every\n * printed page.\n */\nexport const listPrintTitles = (wb: Workbook): ReadonlyArray<DefinedName> =>\n wb.definedNames.filter((d) => d.name === '_xlnm.Print_Titles');\n\n/**\n * Define the print-area for a given sheet. Excel uses the built-in\n * `_xlnm.Print_Area` defined name with sheet scope.\n */\nexport const setPrintArea = (wb: Workbook, sheetIndex: number, ref: string): DefinedName => {\n return addDefinedName(wb, {\n name: '_xlnm.Print_Area',\n value: ref,\n scope: sheetIndex,\n });\n};\n\n/**\n * Define print-title rows / columns on a sheet. Excel uses the\n * `_xlnm.Print_Titles` defined name. Pass `rows` (\"$1:$1\") to repeat row 1 on\n * every printed page; `cols` (\"$A:$A\") to repeat column A.\n */\nexport const setPrintTitles = (\n wb: Workbook,\n sheetIndex: number,\n opts: { rows?: string; cols?: string; sheetName: string },\n): DefinedName => {\n const parts: string[] = [];\n // The wire form is \"Sheet!$1:$1,Sheet!$A:$A\"; both refs share the sheet\n // prefix.\n if (opts.cols !== undefined) parts.push(`'${opts.sheetName}'!${opts.cols}`);\n if (opts.rows !== undefined) parts.push(`'${opts.sheetName}'!${opts.rows}`);\n if (parts.length === 0) {\n throw new OpenXmlSchemaError('setPrintTitles: at least one of rows or cols must be set');\n }\n return addDefinedName(wb, {\n name: '_xlnm.Print_Titles',\n value: parts.join(','),\n scope: sheetIndex,\n });\n};\n"],"mappings":";;AAwBA,SAAgB,gBAAgB,MAA2E;CACzG,OAAO;EACL,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,GAAI,KAAK,UAAU,KAAA,IAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;EACxD,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;EAC3D,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;CAChE;AACF;;;;;;;AA0BA,MAAa,kBACX,IACA,SACgB;CAChB,MAAM,KAAK,gBAAgB,IAAI;CAE/B,MAAM,MAAM,GAAG,aAAa,WAAW,MAAM,EAAE,SAAS,GAAG,QAAQ,EAAE,UAAU,GAAG,KAAK;CACvF,IAAI,OAAO,GACT,GAAG,aAAa,OAAO;MAEvB,GAAG,aAAa,KAAK,EAAE;CAEzB,OAAO;AACT;;AA2CA,MAAa,kBACX,IACA,MACA,UAC4B,GAAG,aAAa,MAAM,MAAM,EAAE,SAAS,QAAQ,EAAE,UAAU,KAAK;;;;;;;;;;;AAY9F,MAAa,wBACX,IACA,MACA,UACoC;CACpC,MAAM,KAAK,eAAe,IAAI,MAAM,KAAK;CACzC,IAAI,CAAC,IAAI,OAAO,KAAA;CAIhB,MAAM,OAAiB,CAAC;CACxB,IAAI,UAAU;CACd,IAAI,UAAU;CACd,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,MAAM,QAAQ,KAAK;EACxC,MAAM,IAAI,GAAG,MAAM;EACnB,IAAI,MAAM,KAAK;GAGb,IAAI,WAAW,GAAG,MAAM,IAAI,OAAO,KAAK;IACtC,WAAW;IACX;IACA;GACF;GACA,UAAU,CAAC;GACX,WAAW;GACX;EACF;EACA,IAAI,MAAM,OAAO,CAAC,SAAS;GACzB,KAAK,KAAK,OAAO;GACjB,UAAU;GACV;EACF;EACA,WAAW;CACb;CACA,IAAI,QAAQ,SAAS,GAAG,KAAK,KAAK,OAAO;CACzC,OAAO,KAAK,KAAK,QAAQ,gBAAgB,GAAG,CAAC;AAC/C;;;;;AAMA,MAAa,qBAAqB,IAAc,MAAc,UAA4B;CACxF,MAAM,MAAM,GAAG,aAAa,WAAW,MAAM,EAAE,SAAS,QAAQ,EAAE,UAAU,KAAK;CACjF,IAAI,MAAM,GAAG,OAAO;CACpB,GAAG,aAAa,OAAO,KAAK,CAAC;CAC7B,OAAO;AACT;;;;;;AAOA,MAAa,oBACX,IACA,OAAgD,CAAC,MAClB;CAC/B,MAAM,QAAQ,KAAK,SAAS;CAC5B,IAAI,UAAU,OAAO,OAAO,GAAG;CAC/B,IAAI,UAAU,YAAY,OAAO,GAAG,aAAa,QAAQ,MAAM,EAAE,UAAU,KAAA,CAAS;CACpF,OAAO,GAAG,aAAa,QAAQ,MAAM,EAAE,UAAU,KAAK;AACxD"}
@@ -0,0 +1,37 @@
1
+ import { Zt as stableStringify } from "./cell-style-BEDjMX1y.mjs";
2
+ //#region src/styles/differential.ts
3
+ function makeDifferentialStyle(opts = {}) {
4
+ const out = {};
5
+ if (opts.font !== void 0) out.font = opts.font;
6
+ if (opts.fill !== void 0) out.fill = opts.fill;
7
+ if (opts.border !== void 0) out.border = opts.border;
8
+ if (opts.alignment !== void 0) out.alignment = opts.alignment;
9
+ if (opts.protection !== void 0) out.protection = opts.protection;
10
+ if (opts.numFmt !== void 0) out.numFmt = opts.numFmt;
11
+ return Object.freeze(out);
12
+ }
13
+ /**
14
+ * Add a DifferentialStyle to the stylesheet's `dxfs` pool. Returns
15
+ * the 0-based index. Idempotent on structural equality (via
16
+ * stableStringify).
17
+ */
18
+ function addDxf(ss, dxf) {
19
+ const w = ss;
20
+ if (w.dxfs === void 0) w.dxfs = [];
21
+ if (w._dxfIdByKey === void 0) w._dxfIdByKey = /* @__PURE__ */ new Map();
22
+ const key = stableStringify(dxf);
23
+ const cached = w._dxfIdByKey.get(key);
24
+ if (cached !== void 0) return cached;
25
+ const id = w.dxfs.length;
26
+ w.dxfs.push(dxf);
27
+ w._dxfIdByKey.set(key, id);
28
+ return id;
29
+ }
30
+ /** Read-only access to the dxfs pool. Returns `[]` when none registered. */
31
+ function getDxfs(ss) {
32
+ return ss.dxfs ?? [];
33
+ }
34
+ //#endregion
35
+ export { getDxfs as n, makeDifferentialStyle as r, addDxf as t };
36
+
37
+ //# sourceMappingURL=differential-D4dg-qtZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differential-D4dg-qtZ.mjs","names":[],"sources":["../src/styles/differential.ts"],"sourcesContent":["// DifferentialStyle (DXF) — partial style overlay used by conditional\n// formatting and Excel-table style elements. Mirrors\n// openpyxl/openpyxl/styles/differential.py.\n//\n// Where a NamedStyle / CellXf carries a *complete* style snapshot, a\n// DifferentialStyle carries only the components that override the base.\n// The Stylesheet keeps DXFs in their own pool (`dxfs`) and conditional-\n// formatting rules / table-style elements reference them by index.\n\nimport { stableStringify } from '../utils/stable-stringify';\nimport type { Alignment } from './alignment';\nimport type { Border } from './borders';\nimport type { Fill } from './fills';\nimport type { Font } from './fonts';\nimport type { NumberFormat } from './numbers';\nimport type { Protection } from './protection';\nimport type { Stylesheet } from './stylesheet';\n\n/**\n * Differential (\"partial\") style. Every component is optional; only\n * the set fields override the base style of whatever the DXF is\n * applied to.\n */\nexport interface DifferentialStyle {\n readonly font?: Font;\n readonly fill?: Fill;\n readonly border?: Border;\n readonly alignment?: Alignment;\n readonly protection?: Protection;\n /**\n * NumberFormat carries both the id and the format code so DXFs can\n * reference custom user-defined number formats without ambiguity.\n */\n readonly numFmt?: NumberFormat;\n}\n\nexport function makeDifferentialStyle(opts: Partial<DifferentialStyle> = {}): DifferentialStyle {\n const out: { -readonly [K in keyof DifferentialStyle]: DifferentialStyle[K] } = {};\n if (opts.font !== undefined) out.font = opts.font;\n if (opts.fill !== undefined) out.fill = opts.fill;\n if (opts.border !== undefined) out.border = opts.border;\n if (opts.alignment !== undefined) out.alignment = opts.alignment;\n if (opts.protection !== undefined) out.protection = opts.protection;\n if (opts.numFmt !== undefined) out.numFmt = opts.numFmt;\n return Object.freeze(out);\n}\n\n/**\n * Stylesheet pool extension. The DXF list is allocated lazily on first\n * use so empty stylesheets stay slim.\n */\nexport interface StylesheetWithDxfs extends Stylesheet {\n dxfs?: DifferentialStyle[];\n _dxfIdByKey?: Map<string, number>;\n}\n\n/**\n * Add a DifferentialStyle to the stylesheet's `dxfs` pool. Returns\n * the 0-based index. Idempotent on structural equality (via\n * stableStringify).\n */\nexport function addDxf(ss: Stylesheet, dxf: DifferentialStyle): number {\n const w = ss as StylesheetWithDxfs;\n if (w.dxfs === undefined) w.dxfs = [];\n if (w._dxfIdByKey === undefined) w._dxfIdByKey = new Map();\n const key = stableStringify(dxf);\n const cached = w._dxfIdByKey.get(key);\n if (cached !== undefined) return cached;\n const id = w.dxfs.length;\n w.dxfs.push(dxf);\n w._dxfIdByKey.set(key, id);\n return id;\n}\n\n/** Read-only access to the dxfs pool. Returns `[]` when none registered. */\nexport function getDxfs(ss: Stylesheet): ReadonlyArray<DifferentialStyle> {\n return (ss as StylesheetWithDxfs).dxfs ?? [];\n}\n"],"mappings":";;AAoCA,SAAgB,sBAAsB,OAAmC,CAAC,GAAsB;CAC9F,MAAM,MAA0E,CAAC;CACjF,IAAI,KAAK,SAAS,KAAA,GAAW,IAAI,OAAO,KAAK;CAC7C,IAAI,KAAK,SAAS,KAAA,GAAW,IAAI,OAAO,KAAK;CAC7C,IAAI,KAAK,WAAW,KAAA,GAAW,IAAI,SAAS,KAAK;CACjD,IAAI,KAAK,cAAc,KAAA,GAAW,IAAI,YAAY,KAAK;CACvD,IAAI,KAAK,eAAe,KAAA,GAAW,IAAI,aAAa,KAAK;CACzD,IAAI,KAAK,WAAW,KAAA,GAAW,IAAI,SAAS,KAAK;CACjD,OAAO,OAAO,OAAO,GAAG;AAC1B;;;;;;AAgBA,SAAgB,OAAO,IAAgB,KAAgC;CACrE,MAAM,IAAI;CACV,IAAI,EAAE,SAAS,KAAA,GAAW,EAAE,OAAO,CAAC;CACpC,IAAI,EAAE,gBAAgB,KAAA,GAAW,EAAE,8BAAc,IAAI,IAAI;CACzD,MAAM,MAAM,gBAAgB,GAAG;CAC/B,MAAM,SAAS,EAAE,YAAY,IAAI,GAAG;CACpC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,KAAK,EAAE,KAAK;CAClB,EAAE,KAAK,KAAK,GAAG;CACf,EAAE,YAAY,IAAI,KAAK,EAAE;CACzB,OAAO;AACT;;AAGA,SAAgB,QAAQ,IAAkD;CACxE,OAAQ,GAA0B,QAAQ,CAAC;AAC7C"}
@@ -0,0 +1,63 @@
1
+ /** EMU = English Metric Units. Drawing coordinates are stored in EMU on the wire. */
2
+ export interface Point2D {
3
+ /** Horizontal offset in EMU. */
4
+ x: number;
5
+ /** Vertical offset in EMU. */
6
+ y: number;
7
+ }
8
+ export interface PositiveSize2D {
9
+ cx: number;
10
+ cy: number;
11
+ }
12
+ /**
13
+ * `from` / `to` corners reference a cell by 0-based column + row index plus an
14
+ * EMU offset within the cell. Excel's wire format is 0-based here even though
15
+ * cell references in formulas / sheetData are 1-based.
16
+ */
17
+ export interface AnchorMarker {
18
+ col: number;
19
+ colOff: number;
20
+ row: number;
21
+ rowOff: number;
22
+ }
23
+ export type DrawingAnchor = {
24
+ kind: 'absolute';
25
+ pos: Point2D;
26
+ ext: PositiveSize2D;
27
+ } | {
28
+ kind: 'oneCell';
29
+ from: AnchorMarker;
30
+ ext: PositiveSize2D;
31
+ } | {
32
+ kind: 'twoCell';
33
+ from: AnchorMarker;
34
+ to: AnchorMarker;
35
+ editAs?: 'twoCell' | 'oneCell' | 'absolute';
36
+ };
37
+ /**
38
+ * Convert a cell ref ("A1", "C5") to a 0-based AnchorMarker with `colOff =
39
+ * rowOff = 0`. Throws on malformed refs.
40
+ */
41
+ export declare function anchorMarkerFromCellRef(ref: string): AnchorMarker;
42
+ /** Build an absolute anchor from an (x, y, cx, cy) EMU bundle. */
43
+ export declare function makeAbsoluteAnchor(opts: {
44
+ x: number;
45
+ y: number;
46
+ cx: number;
47
+ cy: number;
48
+ }): DrawingAnchor;
49
+ /** Build a one-cell anchor pinned at `from` with an explicit pixel extent. */
50
+ export declare function makeOneCellAnchor(opts: {
51
+ from: string | AnchorMarker;
52
+ widthPx: number;
53
+ heightPx: number;
54
+ }): DrawingAnchor;
55
+ /**
56
+ * Build a two-cell anchor from cell-ref pairs (or pre-built markers). Defaults
57
+ * to `editAs='twoCell'` — drag both corners with the cells.
58
+ */
59
+ export declare function makeTwoCellAnchor(opts: {
60
+ from: string | AnchorMarker;
61
+ to: string | AnchorMarker;
62
+ editAs?: 'twoCell' | 'oneCell' | 'absolute';
63
+ }): DrawingAnchor;
@@ -0,0 +1,109 @@
1
+ /** ECMA-376 scheme-color names (`<a:schemeClr val="...">`). */
2
+ export type SchemeColorName = 'bg1' | 'tx1' | 'bg2' | 'tx2' | 'accent1' | 'accent2' | 'accent3' | 'accent4' | 'accent5' | 'accent6' | 'hlink' | 'folHlink' | 'phClr' | 'dk1' | 'lt1' | 'dk2' | 'lt2';
3
+ export declare const SCHEME_COLOR_NAMES: ReadonlyArray<SchemeColorName>;
4
+ export type DmlColor = {
5
+ kind: 'srgb';
6
+ value: string;
7
+ } | {
8
+ kind: 'sysClr';
9
+ value: string;
10
+ lastClr?: string;
11
+ } | {
12
+ kind: 'schemeClr';
13
+ value: SchemeColorName;
14
+ } | {
15
+ kind: 'prstClr';
16
+ value: string;
17
+ } | {
18
+ kind: 'hslClr';
19
+ hue: number;
20
+ sat: number;
21
+ lum: number;
22
+ } | {
23
+ kind: 'scrgbClr';
24
+ r: number;
25
+ g: number;
26
+ b: number;
27
+ };
28
+ export type ColorMod = {
29
+ kind: 'lumMod';
30
+ val: number;
31
+ } | {
32
+ kind: 'lumOff';
33
+ val: number;
34
+ } | {
35
+ kind: 'satMod';
36
+ val: number;
37
+ } | {
38
+ kind: 'satOff';
39
+ val: number;
40
+ } | {
41
+ kind: 'hueMod';
42
+ val: number;
43
+ } | {
44
+ kind: 'hueOff';
45
+ val: number;
46
+ } | {
47
+ kind: 'tint';
48
+ val: number;
49
+ } | {
50
+ kind: 'shade';
51
+ val: number;
52
+ } | {
53
+ kind: 'alpha';
54
+ val: number;
55
+ } | {
56
+ kind: 'alphaMod';
57
+ val: number;
58
+ } | {
59
+ kind: 'alphaOff';
60
+ val: number;
61
+ } | {
62
+ kind: 'red';
63
+ val: number;
64
+ } | {
65
+ kind: 'green';
66
+ val: number;
67
+ } | {
68
+ kind: 'blue';
69
+ val: number;
70
+ } | {
71
+ kind: 'redMod';
72
+ val: number;
73
+ } | {
74
+ kind: 'greenMod';
75
+ val: number;
76
+ } | {
77
+ kind: 'blueMod';
78
+ val: number;
79
+ } | {
80
+ kind: 'redOff';
81
+ val: number;
82
+ } | {
83
+ kind: 'greenOff';
84
+ val: number;
85
+ } | {
86
+ kind: 'blueOff';
87
+ val: number;
88
+ } | {
89
+ kind: 'gray';
90
+ } | {
91
+ kind: 'comp';
92
+ } | {
93
+ kind: 'inv';
94
+ } | {
95
+ kind: 'invGamma';
96
+ } | {
97
+ kind: 'gamma';
98
+ };
99
+ /** Color mod kinds that take no `val` attribute (their elements are empty). */
100
+ export declare const VALUELESS_COLOR_MOD_KINDS: ReadonlyArray<ColorMod['kind']>;
101
+ /** Color mod kinds that carry a numeric `val` attribute. */
102
+ export declare const VALUED_COLOR_MOD_KINDS: ReadonlyArray<ColorMod['kind']>;
103
+ export interface DmlColorWithMods {
104
+ base: DmlColor;
105
+ mods: ColorMod[];
106
+ }
107
+ export declare const makeSrgbColor: (rrggbb: string) => DmlColor;
108
+ export declare const makeSchemeColor: (name: SchemeColorName) => DmlColor;
109
+ export declare const makeColor: (base: DmlColor, mods?: ColorMod[]) => DmlColorWithMods;
@@ -0,0 +1,35 @@
1
+ import { type XmlNode } from '../../xml/tree';
2
+ import { type DmlColorWithMods } from './colors';
3
+ import type { EffectsRef } from './effect';
4
+ import type { Fill } from './fill';
5
+ import type { Geometry } from './geometry';
6
+ import type { LineProperties } from './line';
7
+ import type { ShapeProperties } from './shape-properties';
8
+ import type { TextBody, TextBodyProperties } from './text';
9
+ /** Parse the first known color base element (with its mods) found inside `parent`. */
10
+ export declare const parseDmlColor: (parent: XmlNode) => DmlColorWithMods | undefined;
11
+ /** Serialize a color directly (without an enclosing wrapper). */
12
+ export declare const serializeDmlColor: (c: DmlColorWithMods) => string;
13
+ /** Parse the first fill element under `parent` (any of the 6 kinds). */
14
+ export declare const parseFill: (parent: XmlNode) => Fill | undefined;
15
+ export declare const serializeFill: (f: Fill) => string;
16
+ export declare const parseLine: (el: XmlNode) => LineProperties;
17
+ export declare const serializeLine: (ln: LineProperties) => string;
18
+ export declare const parseGeometry: (parent: XmlNode) => Geometry | undefined;
19
+ export declare const serializeGeometry: (g: Geometry) => string;
20
+ export declare const parseEffects: (parent: XmlNode) => EffectsRef | undefined;
21
+ export declare const serializeEffects: (e: EffectsRef) => string;
22
+ export declare const parseTextBodyProperties: (el: XmlNode) => TextBodyProperties;
23
+ export declare const serializeTextBodyProperties: (tag: string, p: TextBodyProperties) => string;
24
+ /** Parse an `<a:txBody>` (or `<c:txPr>` / `<cdr:txBody>`) element. */
25
+ export declare const parseTextBody: (el: XmlNode) => TextBody;
26
+ /** Serialise a TextBody. Wrapper defaults to `<c:txPr>` to match chart usage. */
27
+ export declare const serializeTextBody: (body: TextBody, wrapperTag?: string) => string;
28
+ /**
29
+ * Parse a `<spPr>` (or `<c:spPr>` / `<cdr:spPr>`) element. Caller provides the
30
+ * element directly — we don't filter by tag name so the helper works for any
31
+ * namespace prefix.
32
+ */
33
+ export declare const parseShapeProperties: (el: XmlNode) => ShapeProperties;
34
+ /** Serialize a ShapeProperties as `<wrapper>...</wrapper>`. Wrapper defaults to `<c:spPr>`. */
35
+ export declare const serializeShapeProperties: (sp: ShapeProperties, wrapperTag?: string) => string;
@@ -0,0 +1,92 @@
1
+ import type { DmlColorWithMods } from './colors';
2
+ import type { Fill } from './fill';
3
+ export type FillBlendMode = 'over' | 'mult' | 'screen' | 'darken' | 'lighten';
4
+ export type ShadowAlign = 'tl' | 't' | 'tr' | 'l' | 'ctr' | 'r' | 'bl' | 'b' | 'br';
5
+ /** Preset-shadow names (`<a:prstShdw prst="shdwN"/>`, 20 entries). */
6
+ export type PresetShadowName = 'shdw1' | 'shdw2' | 'shdw3' | 'shdw4' | 'shdw5' | 'shdw6' | 'shdw7' | 'shdw8' | 'shdw9' | 'shdw10' | 'shdw11' | 'shdw12' | 'shdw13' | 'shdw14' | 'shdw15' | 'shdw16' | 'shdw17' | 'shdw18' | 'shdw19' | 'shdw20';
7
+ export declare const PRESET_SHADOW_NAMES: ReadonlyArray<PresetShadowName>;
8
+ export type Effect = {
9
+ kind: 'blur';
10
+ rad: number;
11
+ grow?: boolean;
12
+ } | {
13
+ kind: 'fillOverlay';
14
+ blend: FillBlendMode;
15
+ fill: Fill;
16
+ } | {
17
+ kind: 'glow';
18
+ rad: number;
19
+ color: DmlColorWithMods;
20
+ } | {
21
+ kind: 'innerShdw';
22
+ blurRad?: number;
23
+ dist?: number;
24
+ dir?: number;
25
+ color: DmlColorWithMods;
26
+ } | {
27
+ kind: 'outerShdw';
28
+ blurRad?: number;
29
+ dist?: number;
30
+ dir?: number;
31
+ sx?: number;
32
+ sy?: number;
33
+ kx?: number;
34
+ ky?: number;
35
+ algn?: ShadowAlign;
36
+ rotWithShape?: boolean;
37
+ color: DmlColorWithMods;
38
+ } | {
39
+ kind: 'prstShdw';
40
+ prst: PresetShadowName;
41
+ dist?: number;
42
+ dir?: number;
43
+ color: DmlColorWithMods;
44
+ } | {
45
+ kind: 'reflection';
46
+ blurRad?: number;
47
+ stA?: number;
48
+ stPos?: number;
49
+ endA?: number;
50
+ endPos?: number;
51
+ dist?: number;
52
+ dir?: number;
53
+ fadeDir?: number;
54
+ sx?: number;
55
+ sy?: number;
56
+ kx?: number;
57
+ ky?: number;
58
+ algn?: ShadowAlign;
59
+ rotWithShape?: boolean;
60
+ } | {
61
+ kind: 'softEdge';
62
+ rad: number;
63
+ };
64
+ /** `<a:effectLst>` — ordered list of effect leaves. */
65
+ export interface EffectList {
66
+ list: Effect[];
67
+ }
68
+ /**
69
+ * Inner `<a:cont type="tree|sib">` node. Lives inside `<a:effectDag>` or inside
70
+ * another `<a:cont>`. Children may be effect leaves or further containers.
71
+ */
72
+ export interface EffectContainer {
73
+ /** Compose children sequentially (`sib`) or as a tree (`tree`). */
74
+ type: 'tree' | 'sib';
75
+ /** Optional name for cross-referencing other DAG nodes. */
76
+ name?: string;
77
+ children: Array<Effect | EffectContainer>;
78
+ }
79
+ /**
80
+ * Either `<a:effectLst>` or `<a:effectDag>`. The dag root has no `type`
81
+ * attribute in ECMA-376; only its `<a:cont>` children do, hence we model the
82
+ * dag as a flat list of children rather than a single EffectContainer.
83
+ */
84
+ export type EffectsRef = {
85
+ kind: 'lst';
86
+ list: EffectList;
87
+ } | {
88
+ kind: 'dag';
89
+ children: Array<Effect | EffectContainer>;
90
+ };
91
+ export declare const makeEffectList: (list: Effect[]) => EffectList;
92
+ export declare const makeEffectContainer: (type: "tree" | "sib", children: Array<Effect | EffectContainer>, name?: string) => EffectContainer;
@@ -0,0 +1,115 @@
1
+ import type { DmlColor, DmlColorWithMods } from './colors';
2
+ /** Relative rectangle (0..100000-thousandths). */
3
+ export interface RelativeRect {
4
+ l?: number;
5
+ t?: number;
6
+ r?: number;
7
+ b?: number;
8
+ }
9
+ export interface GradientStop {
10
+ /** Position along the gradient (0..100000). */
11
+ pos: number;
12
+ color: DmlColorWithMods;
13
+ }
14
+ export type GradientLineDir = {
15
+ kind: 'lin';
16
+ ang: number;
17
+ scaled?: boolean;
18
+ } | {
19
+ kind: 'path';
20
+ pathType: 'shape' | 'circle' | 'rect';
21
+ tileRect?: RelativeRect;
22
+ };
23
+ export type TileFlip = 'x' | 'y' | 'xy' | 'none';
24
+ export interface TileFill {
25
+ tx?: number;
26
+ ty?: number;
27
+ sx?: number;
28
+ sy?: number;
29
+ flip?: TileFlip;
30
+ algn?: 'tl' | 't' | 'tr' | 'l' | 'ctr' | 'r' | 'bl' | 'b' | 'br';
31
+ }
32
+ /** Blip-source effects. The full ECMA-376 list is preserved here; `kind` discriminates. */
33
+ export type BlipEffect = {
34
+ kind: 'biLevel';
35
+ thresh: number;
36
+ } | {
37
+ kind: 'blur';
38
+ rad: number;
39
+ grow?: boolean;
40
+ } | {
41
+ kind: 'clrChange';
42
+ useA?: boolean;
43
+ clrFrom: DmlColor;
44
+ clrTo: DmlColor;
45
+ } | {
46
+ kind: 'clrRepl';
47
+ color: DmlColor;
48
+ } | {
49
+ kind: 'duotone';
50
+ colors: [DmlColor, DmlColor];
51
+ } | {
52
+ kind: 'grayscl';
53
+ } | {
54
+ kind: 'lum';
55
+ bright?: number;
56
+ contrast?: number;
57
+ } | {
58
+ kind: 'tint';
59
+ hue?: number;
60
+ amt?: number;
61
+ } | {
62
+ kind: 'alphaModFix';
63
+ amt: number;
64
+ };
65
+ export interface Blip {
66
+ embedRId?: string;
67
+ linkRId?: string;
68
+ cstate?: 'email' | 'screen' | 'print' | 'hqprint';
69
+ effects?: BlipEffect[];
70
+ }
71
+ /** Discriminated union for any fill that can attach to a shape. */
72
+ export type Fill = {
73
+ kind: 'noFill';
74
+ } | {
75
+ kind: 'solidFill';
76
+ color: DmlColorWithMods;
77
+ } | {
78
+ kind: 'gradFill';
79
+ flip?: TileFlip;
80
+ rotWithShape?: boolean;
81
+ stops: GradientStop[];
82
+ lineDir?: GradientLineDir;
83
+ } | {
84
+ kind: 'blipFill';
85
+ blip: Blip;
86
+ tile?: TileFill;
87
+ stretch?: {
88
+ fillRect?: RelativeRect;
89
+ };
90
+ srcRect?: RelativeRect;
91
+ dpi?: number;
92
+ rotWithShape?: boolean;
93
+ } | {
94
+ kind: 'pattFill';
95
+ preset: string;
96
+ fgClr?: DmlColorWithMods;
97
+ bgClr?: DmlColorWithMods;
98
+ } | {
99
+ kind: 'grpFill';
100
+ };
101
+ export declare const makeNoFill: () => Fill;
102
+ export declare const makeSolidFill: (color: DmlColorWithMods) => Fill;
103
+ export declare const makeGradientFill: (opts: {
104
+ stops: GradientStop[];
105
+ flip?: TileFlip;
106
+ rotWithShape?: boolean;
107
+ lineDir?: GradientLineDir;
108
+ }) => Fill;
109
+ export declare const makePatternFill: (opts: {
110
+ preset: string;
111
+ fgClr?: DmlColorWithMods;
112
+ bgClr?: DmlColorWithMods;
113
+ }) => Fill;
114
+ /** Excel's preset pattern names (54 entries, ECMA-376 §20.1.10.50; matches openpyxl). */
115
+ export declare const PRESET_PATTERN_NAMES: ReadonlyArray<string>;