@shbernal/ts-xlsx 2.1.0 → 3.1.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 (225) hide show
  1. package/README.md +4 -1
  2. package/dist/bytes.d.ts +7 -0
  3. package/dist/bytes.js +22 -0
  4. package/dist/core/address.d.ts +60 -2
  5. package/dist/core/address.js +40 -24
  6. package/dist/core/autofilter.d.ts +5 -4
  7. package/dist/core/autofilter.js +34 -35
  8. package/dist/core/axis-handle.d.ts +10 -0
  9. package/dist/core/axis-handle.js +17 -0
  10. package/dist/core/cell.d.ts +25 -0
  11. package/dist/core/cell.js +9 -3
  12. package/dist/core/clone.d.ts +29 -0
  13. package/dist/core/clone.js +24 -0
  14. package/dist/core/color-resolution.js +2 -4
  15. package/dist/core/column.d.ts +5 -1
  16. package/dist/core/column.js +34 -35
  17. package/dist/core/comment-thread.js +2 -1
  18. package/dist/core/conditional-formatting-overlay.d.ts +2 -1
  19. package/dist/core/conditional-formatting-overlay.js +2 -2
  20. package/dist/core/conditional-formatting.d.ts +14 -6
  21. package/dist/core/conditional-formatting.js +45 -43
  22. package/dist/core/containers.d.ts +12 -0
  23. package/dist/core/containers.js +5 -0
  24. package/dist/core/data-validation-overlay.d.ts +2 -1
  25. package/dist/core/data-validation-overlay.js +4 -4
  26. package/dist/core/data-validation.d.ts +9 -3
  27. package/dist/core/data-validation.js +21 -18
  28. package/dist/core/date-format.d.ts +20 -0
  29. package/dist/core/date-format.js +160 -0
  30. package/dist/core/date.d.ts +43 -8
  31. package/dist/core/date.js +18 -2
  32. package/dist/core/formula.d.ts +26 -0
  33. package/dist/core/formula.js +20 -4
  34. package/dist/core/grid-edits.d.ts +2 -3
  35. package/dist/core/grid-edits.js +69 -70
  36. package/dist/core/grid-shift.d.ts +58 -9
  37. package/dist/core/grid-shift.js +26 -4
  38. package/dist/core/image.d.ts +14 -10
  39. package/dist/core/image.js +9 -9
  40. package/dist/core/internal.d.ts +8 -2
  41. package/dist/core/limits.d.ts +23 -0
  42. package/dist/core/limits.js +4 -0
  43. package/dist/core/merge-index.d.ts +31 -0
  44. package/dist/core/merge-index.js +60 -0
  45. package/dist/core/merge.d.ts +5 -14
  46. package/dist/core/merge.js +18 -27
  47. package/dist/core/page-setup.d.ts +72 -2
  48. package/dist/core/page-setup.js +34 -8
  49. package/dist/core/pivot-table.d.ts +1 -1
  50. package/dist/core/pivot-table.js +67 -53
  51. package/dist/core/protection.js +2 -11
  52. package/dist/core/range.js +34 -30
  53. package/dist/core/row-input.js +2 -2
  54. package/dist/core/row.d.ts +5 -1
  55. package/dist/core/row.js +22 -23
  56. package/dist/core/style.d.ts +134 -75
  57. package/dist/core/style.js +112 -53
  58. package/dist/core/table-style.d.ts +1 -1
  59. package/dist/core/table-style.js +4 -4
  60. package/dist/core/table.d.ts +28 -10
  61. package/dist/core/table.js +54 -39
  62. package/dist/core/theme.js +6 -5
  63. package/dist/core/used-extent.d.ts +44 -0
  64. package/dist/core/used-extent.js +102 -0
  65. package/dist/core/value.d.ts +9 -0
  66. package/dist/core/value.js +36 -34
  67. package/dist/core/workbook-media.d.ts +34 -0
  68. package/dist/core/workbook-media.js +44 -0
  69. package/dist/core/workbook-styles.d.ts +67 -1
  70. package/dist/core/workbook-vba.js +3 -2
  71. package/dist/core/workbook.d.ts +23 -2
  72. package/dist/core/workbook.js +24 -40
  73. package/dist/core/worksheet-comments.d.ts +2 -1
  74. package/dist/core/worksheet-comments.js +20 -13
  75. package/dist/core/worksheet-merges.d.ts +44 -0
  76. package/dist/core/worksheet-merges.js +59 -0
  77. package/dist/core/worksheet-model.d.ts +9 -1
  78. package/dist/core/worksheet-model.js +24 -9
  79. package/dist/core/worksheet.d.ts +72 -12
  80. package/dist/core/worksheet.js +68 -70
  81. package/dist/customui/ribbon.js +6 -7
  82. package/dist/entries/core.d.ts +18 -13
  83. package/dist/entries/core.js +12 -6
  84. package/dist/entries/xlsx.d.ts +1 -1
  85. package/dist/errors.d.ts +64 -0
  86. package/dist/errors.js +22 -0
  87. package/dist/hex.d.ts +8 -0
  88. package/dist/hex.js +3 -0
  89. package/dist/io/csv/delimiter.d.ts +9 -0
  90. package/dist/io/csv/delimiter.js +6 -0
  91. package/dist/io/csv/read.js +11 -4
  92. package/dist/io/csv/write.d.ts +9 -2
  93. package/dist/io/csv/write.js +9 -38
  94. package/dist/io/opc/inflate.js +15 -1
  95. package/dist/io/opc/namespaces.d.ts +16 -0
  96. package/dist/io/opc/namespaces.js +4 -0
  97. package/dist/io/opc/part-paths.d.ts +10 -0
  98. package/dist/io/opc/part-paths.js +16 -1
  99. package/dist/io/opc/read-opc.d.ts +69 -10
  100. package/dist/io/opc/read-opc.js +49 -55
  101. package/dist/io/opc/read-options.d.ts +5 -1
  102. package/dist/io/opc/rels.d.ts +1 -6
  103. package/dist/io/opc/rels.js +1 -4
  104. package/dist/io/opc/sniff-format.d.ts +3 -3
  105. package/dist/io/opc/sniff-format.js +2 -2
  106. package/dist/io/style/xf-style.d.ts +48 -2
  107. package/dist/io/style/xf-style.js +14 -0
  108. package/dist/io/xlsb/formula.d.ts +2 -2
  109. package/dist/io/xlsb/formula.js +49 -34
  110. package/dist/io/xlsb/primitives.js +8 -14
  111. package/dist/io/xlsb/ptg-functions.d.ts +19 -10
  112. package/dist/io/xlsb/ptg-functions.js +385 -596
  113. package/dist/io/xlsb/read-styles.js +50 -83
  114. package/dist/io/xlsb/read-worksheet.d.ts +20 -1
  115. package/dist/io/xlsb/read-worksheet.js +73 -89
  116. package/dist/io/xlsb/read.d.ts +6 -3
  117. package/dist/io/xlsb/read.js +47 -29
  118. package/dist/io/xlsb/record-stream.d.ts +30 -0
  119. package/dist/io/xlsb/record-stream.js +20 -0
  120. package/dist/io/xlsb/record-types.d.ts +1 -5
  121. package/dist/io/xlsb/record-types.js +1 -5
  122. package/dist/io/xlsx/cell-accumulator.d.ts +9 -2
  123. package/dist/io/xlsx/cell-accumulator.js +32 -9
  124. package/dist/io/xlsx/cell-style-resolution.d.ts +25 -0
  125. package/dist/io/xlsx/cell-style-resolution.js +29 -0
  126. package/dist/io/xlsx/cell-value.d.ts +5 -3
  127. package/dist/io/xlsx/cell-value.js +13 -15
  128. package/dist/io/xlsx/color-xml.js +3 -2
  129. package/dist/io/xlsx/column-budget.d.ts +26 -0
  130. package/dist/io/xlsx/column-budget.js +22 -0
  131. package/dist/io/xlsx/comments.d.ts +6 -2
  132. package/dist/io/xlsx/comments.js +36 -31
  133. package/dist/io/xlsx/conditional-formatting.d.ts +9 -5
  134. package/dist/io/xlsx/conditional-formatting.js +51 -46
  135. package/dist/io/xlsx/data-validation.d.ts +9 -7
  136. package/dist/io/xlsx/data-validation.js +38 -35
  137. package/dist/io/xlsx/edit-vba.d.ts +7 -2
  138. package/dist/io/xlsx/edit-vba.js +15 -29
  139. package/dist/io/xlsx/font-xml.d.ts +7 -0
  140. package/dist/io/xlsx/font-xml.js +104 -0
  141. package/dist/io/xlsx/hyperlinks.d.ts +41 -7
  142. package/dist/io/xlsx/hyperlinks.js +40 -28
  143. package/dist/io/xlsx/images.js +24 -25
  144. package/dist/io/xlsx/namespaces.d.ts +16 -0
  145. package/dist/io/xlsx/namespaces.js +7 -0
  146. package/dist/io/xlsx/package-plan.d.ts +23 -3
  147. package/dist/io/xlsx/package-plan.js +66 -25
  148. package/dist/io/xlsx/part-names.d.ts +41 -0
  149. package/dist/io/xlsx/part-names.js +46 -0
  150. package/dist/io/xlsx/pivot.js +8 -7
  151. package/dist/io/xlsx/read-parts.d.ts +59 -0
  152. package/dist/io/xlsx/read-parts.js +252 -0
  153. package/dist/io/xlsx/read-pivot.js +3 -1
  154. package/dist/io/xlsx/read-repair.d.ts +26 -0
  155. package/dist/io/xlsx/read-repair.js +39 -0
  156. package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +1 -1
  157. package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +7 -3
  158. package/dist/io/xlsx/read-rows.d.ts +18 -5
  159. package/dist/io/xlsx/read-rows.js +50 -37
  160. package/dist/io/xlsx/read-shared-strings.js +5 -3
  161. package/dist/io/xlsx/read-styles.d.ts +1 -6
  162. package/dist/io/xlsx/read-styles.js +65 -109
  163. package/dist/io/xlsx/read-workbook-xml.d.ts +36 -0
  164. package/dist/io/xlsx/read-workbook-xml.js +170 -0
  165. package/dist/io/xlsx/read-worksheet.d.ts +11 -1
  166. package/dist/io/xlsx/read-worksheet.js +51 -193
  167. package/dist/io/xlsx/read.d.ts +5 -13
  168. package/dist/io/xlsx/read.js +111 -436
  169. package/dist/io/xlsx/rich-text.js +1 -1
  170. package/dist/io/xlsx/row-position.d.ts +18 -0
  171. package/dist/io/xlsx/row-position.js +11 -0
  172. package/dist/io/xlsx/row-xml.d.ts +128 -0
  173. package/dist/io/xlsx/row-xml.js +203 -0
  174. package/dist/io/xlsx/shared-formulas.js +2 -2
  175. package/dist/io/xlsx/sheet-properties.d.ts +10 -1
  176. package/dist/io/xlsx/sheet-properties.js +166 -37
  177. package/dist/io/xlsx/style-elements.d.ts +43 -0
  178. package/dist/io/xlsx/style-elements.js +156 -0
  179. package/dist/io/xlsx/styles.d.ts +12 -3
  180. package/dist/io/xlsx/styles.js +5 -204
  181. package/dist/io/xlsx/tables.js +11 -14
  182. package/dist/io/xlsx/theme-xml.d.ts +26 -4
  183. package/dist/io/xlsx/theme-xml.js +107 -69
  184. package/dist/io/xlsx/threaded-comments.d.ts +8 -10
  185. package/dist/io/xlsx/threaded-comments.js +3 -1
  186. package/dist/io/xlsx/workbook-xml.d.ts +54 -4
  187. package/dist/io/xlsx/workbook-xml.js +84 -57
  188. package/dist/io/xlsx/worksheet-xml.d.ts +23 -70
  189. package/dist/io/xlsx/worksheet-xml.js +59 -242
  190. package/dist/io/xlsx/write-stream.d.ts +71 -16
  191. package/dist/io/xlsx/write-stream.js +79 -41
  192. package/dist/io/xlsx/write.d.ts +6 -2
  193. package/dist/io/xlsx/write.js +217 -153
  194. package/dist/rel-type.d.ts +16 -0
  195. package/dist/rel-type.js +6 -0
  196. package/dist/token-set.d.ts +28 -0
  197. package/dist/token-set.js +7 -0
  198. package/dist/vba/bytes.d.ts +14 -5
  199. package/dist/vba/bytes.js +16 -6
  200. package/dist/vba/cfb-format.d.ts +32 -0
  201. package/dist/vba/cfb-format.js +13 -0
  202. package/dist/vba/cfb-writer.d.ts +9 -0
  203. package/dist/vba/cfb-writer.js +28 -25
  204. package/dist/vba/cfb.d.ts +13 -1
  205. package/dist/vba/cfb.js +73 -57
  206. package/dist/vba/codepage.js +2 -1
  207. package/dist/vba/errors.d.ts +7 -0
  208. package/dist/vba/ms-ovba.js +79 -23
  209. package/dist/vba/project-editor.js +35 -40
  210. package/dist/vba/project.d.ts +11 -1
  211. package/dist/vba/project.js +40 -21
  212. package/dist/vba/vba-encoding.js +5 -6
  213. package/dist/xml/xml-attrs.d.ts +37 -0
  214. package/dist/xml/xml-attrs.js +30 -0
  215. package/dist/xml/xml-chars.d.ts +40 -0
  216. package/dist/xml/xml-chars.js +12 -0
  217. package/dist/xml/xml-namespaces.d.ts +31 -0
  218. package/dist/xml/xml-namespaces.js +50 -0
  219. package/dist/xml/xml-read.d.ts +128 -81
  220. package/dist/xml/xml-read.js +161 -178
  221. package/dist/xml/xml-scan.d.ts +78 -0
  222. package/dist/xml/xml-scan.js +180 -0
  223. package/dist/xml/xml.d.ts +29 -28
  224. package/dist/xml/xml.js +24 -24
  225. package/package.json +13 -9
@@ -1,8 +1,11 @@
1
1
  import { isCfValueObjectType, isConditionalFormattingOperator, isConditionalFormattingType, isIconSetType, isCfTimePeriod, } from '../../core/conditional-formatting.js';
2
- import { boolPresent, boolStrict, coerceNumericLiteral, enumToken, localName, numFinite, numInteger, parseXml, TextCapture, } from '../../xml/xml-read.js';
3
- import { boolAttr, checkedToken, escapeAttr, escapeText, numberText, stripFormulaEquals, textAttr, } from '../../xml/xml.js';
2
+ import { stripFormulaEquals } from '../../core/formula.js';
3
+ import { coerceNumericLiteral, enumToken, numFinite, numInteger } from '../../xml/xml-attrs.js';
4
+ import { elementSubtrees, TextCapture, } from '../../xml/xml-read.js';
5
+ import { boolPresent, boolStrict, localName } from '../../xml/xml-scan.js';
6
+ import { boolAttr, checkedToken, escapeAttr, escapeText, numberText, textAttr, } from '../../xml/xml.js';
4
7
  import { colorAttrs, parseColor } from './color-xml.js';
5
- import { CF_EXT_URI, DATABAR_LINK_EXT_URI, XM_NS } from './namespaces.js';
8
+ import { CF_EXT_URI, DATABAR_LINK_EXT_URI, isExtensionElement, XM_NS } from './namespaces.js';
6
9
  import { x14Ext } from './x14-ext.js';
7
10
  const DEFAULT_DATABAR_CFVO = [{ type: 'min' }, { type: 'max' }];
8
11
  const DEFAULT_DATABAR_COLOR = { argb: 'FF638EC6' };
@@ -14,7 +17,7 @@ function needsDataBarExt(rule) {
14
17
  function dataBarExtGuid(index) {
15
18
  return `{00000000-0000-0000-0000-${String(index + 1).padStart(12, '0')}}`;
16
19
  }
17
- function dataBarExtLinks(formattings) {
20
+ export function dataBarExtLinks(formattings) {
18
21
  const links = new Map();
19
22
  let index = 0;
20
23
  for (const cf of formattings) {
@@ -27,15 +30,13 @@ function dataBarExtLinks(formattings) {
27
30
  }
28
31
  const SCALE_KINDS = ['dataBar', 'colorScale', 'iconSet'];
29
32
  const SCALE_TYPES = new Set(SCALE_KINDS);
30
- export function conditionalFormattingsXml(formattings, styles) {
33
+ export function conditionalFormattingsXml(formattings, styles, extLinks) {
31
34
  if (formattings.length === 0)
32
35
  return '';
33
36
  const priority = { next: 1 };
34
- const extLinks = dataBarExtLinks(formattings);
35
37
  return formattings.map((cf) => blockXml(cf, styles, priority, extLinks)).join('');
36
38
  }
37
- export function conditionalFormattingsExtXml(formattings) {
38
- const extLinks = dataBarExtLinks(formattings);
39
+ export function conditionalFormattingsExtXml(formattings, extLinks) {
39
40
  const items = [];
40
41
  for (const cf of formattings) {
41
42
  for (const rule of cf.rules) {
@@ -49,8 +50,7 @@ export function conditionalFormattingsExtXml(formattings) {
49
50
  return x14Ext(CF_EXT_URI, `<x14:conditionalFormattings>${items.join('')}</x14:conditionalFormattings>`);
50
51
  }
51
52
  function x14DataBarXml(ref, rule, guid) {
52
- const cfvo = rule.cfvo && rule.cfvo.length > 0 ? rule.cfvo : DEFAULT_DATABAR_CFVO;
53
- const anchors = cfvo.map(x14CfvoXml).join('');
53
+ const anchors = dataBarAnchors(rule).map(x14Cfvo).join('');
54
54
  const gradient = boolAttr('gradient', rule.gradient);
55
55
  const negative = rule.negativeFillColor !== undefined
56
56
  ? `<x14:negativeFillColor ${colorAttrs(rule.negativeFillColor)}/>`
@@ -61,12 +61,23 @@ function x14DataBarXml(ref, rule, guid) {
61
61
  `<x14:dataBar${gradient}>${anchors}${negative}${axis}</x14:dataBar>` +
62
62
  `</x14:cfRule><xm:sqref>${escapeText(ref)}</xm:sqref></x14:conditionalFormatting>`);
63
63
  }
64
- function x14CfvoXml(cfvo) {
65
- const type = checkedToken(cfvo.type, isCfValueObjectType, 'conditional format value type');
66
- if (cfvo.value === undefined)
67
- return `<x14:cfvo type="${type}"/>`;
68
- return `<x14:cfvo type="${type}"><xm:f>${escapeText(String(cfvo.value))}</xm:f></x14:cfvo>`;
64
+ function dataBarAnchors(rule) {
65
+ return rule.cfvo && rule.cfvo.length > 0 ? rule.cfvo : DEFAULT_DATABAR_CFVO;
69
66
  }
67
+ function cfvoWriter(form) {
68
+ return (cfvo) => {
69
+ const type = checkedToken(cfvo.type, isCfValueObjectType, 'conditional format value type');
70
+ const tag = form === 'classic' ? 'cfvo' : 'x14:cfvo';
71
+ if (cfvo.value === undefined)
72
+ return `<${tag} type="${type}"/>`;
73
+ const value = String(cfvo.value);
74
+ return form === 'classic'
75
+ ? `<${tag} type="${type}"${textAttr('val', value)}/>`
76
+ : `<${tag} type="${type}"><xm:f>${escapeText(value)}</xm:f></${tag}>`;
77
+ };
78
+ }
79
+ const cfvoXml = cfvoWriter('classic');
80
+ const x14Cfvo = cfvoWriter('x14');
70
81
  function cfRuleExtLinkXml(guid) {
71
82
  return `<extLst>${x14Ext(DATABAR_LINK_EXT_URI, `<x14:id>${guid}</x14:id>`)}</extLst>`;
72
83
  }
@@ -139,9 +150,8 @@ function scaleXml(rule) {
139
150
  return iconSetXml(rule);
140
151
  }
141
152
  function dataBarXml(rule) {
142
- const cfvo = rule.cfvo && rule.cfvo.length > 0 ? rule.cfvo : DEFAULT_DATABAR_CFVO;
143
153
  const color = rule.color ?? DEFAULT_DATABAR_COLOR;
144
- const anchors = cfvo.map(cfvoXml).join('');
154
+ const anchors = dataBarAnchors(rule).map(cfvoXml).join('');
145
155
  return `<dataBar>${anchors}<color ${colorAttrs(color)}/></dataBar>`;
146
156
  }
147
157
  function colorScaleXml(rule) {
@@ -156,12 +166,7 @@ function iconSetXml(rule) {
156
166
  const anchors = (rule.cfvo ?? []).map(cfvoXml).join('');
157
167
  return `<iconSet${name}>${anchors}</iconSet>`;
158
168
  }
159
- function cfvoXml(cfvo) {
160
- const type = checkedToken(cfvo.type, isCfValueObjectType, 'conditional format value type');
161
- const val = cfvo.value === undefined ? '' : textAttr('val', String(cfvo.value));
162
- return `<cfvo type="${type}"${val}/>`;
163
- }
164
- export function parseConditionalFormattings(xml) {
169
+ export function conditionalFormattingPass() {
165
170
  const blocks = [];
166
171
  let block;
167
172
  let draft;
@@ -172,10 +177,10 @@ export function parseConditionalFormattings(xml) {
172
177
  let x14Ext;
173
178
  let x14ExtId;
174
179
  const x14IdCapture = new TextCapture('id');
175
- parseXml(xml, {
176
- onOpen(name, attrs, selfClosing) {
180
+ const handlers = {
181
+ onOpen(name, attrs, selfClosing, scope) {
177
182
  const ln = localName(name);
178
- if (name.includes(':')) {
183
+ if (isExtensionElement(scope, name)) {
179
184
  if (ln === 'id' && draft !== undefined) {
180
185
  x14IdCapture.open(ln, selfClosing);
181
186
  }
@@ -232,9 +237,9 @@ export function parseConditionalFormattings(xml) {
232
237
  formulaCapture.text(chunk);
233
238
  x14IdCapture.text(chunk);
234
239
  },
235
- onClose(name) {
240
+ onClose(name, scope) {
236
241
  const ln = localName(name);
237
- if (name.includes(':')) {
242
+ if (isExtensionElement(scope, name)) {
238
243
  const id = x14IdCapture.close(ln);
239
244
  if (id !== undefined) {
240
245
  if (draft !== undefined)
@@ -270,29 +275,29 @@ export function parseConditionalFormattings(xml) {
270
275
  block = undefined;
271
276
  }
272
277
  },
273
- });
274
- for (const { rule, id } of linked) {
275
- const ext = extById.get(id);
276
- if (ext === undefined)
277
- continue;
278
- if (ext.gradient !== undefined)
279
- rule.gradient = ext.gradient;
280
- if (ext.negativeFillColor !== undefined)
281
- rule.negativeFillColor = ext.negativeFillColor;
282
- if (ext.axisColor !== undefined)
283
- rule.axisColor = ext.axisColor;
284
- }
285
- return blocks;
278
+ };
279
+ const result = () => {
280
+ for (const { rule, id } of linked) {
281
+ const ext = extById.get(id);
282
+ if (ext === undefined)
283
+ continue;
284
+ if (ext.gradient !== undefined)
285
+ rule.gradient = ext.gradient;
286
+ if (ext.negativeFillColor !== undefined)
287
+ rule.negativeFillColor = ext.negativeFillColor;
288
+ if (ext.axisColor !== undefined)
289
+ rule.axisColor = ext.axisColor;
290
+ }
291
+ return blocks;
292
+ };
293
+ return { handlers, result };
286
294
  }
287
295
  function emptyExt() {
288
296
  return { gradient: undefined, negativeFillColor: undefined, axisColor: undefined };
289
297
  }
290
298
  export function parseDxfs(stylesXml) {
291
- const block = /<dxfs\b[^>]*>([\s\S]*?)<\/dxfs>/.exec(stylesXml);
292
- if (block === null)
293
- return [];
294
- const inner = block[1] ?? '';
295
- return [...inner.matchAll(/<dxf\b[^>]*>[\s\S]*?<\/dxf>|<dxf\b[^>]*\/>/g)].map((m) => m[0] ?? '');
299
+ const { fragments } = elementSubtrees(stylesXml, new Map([['dxfs', 'dxf']]));
300
+ return [...(fragments.get('dxfs') ?? [])];
296
301
  }
297
302
  function newDraft(attrs) {
298
303
  return {
@@ -1,5 +1,6 @@
1
1
  import { type DataValidationEntry } from '../../core/data-validation.ts';
2
2
  import type { Worksheet } from '../../core/worksheet.ts';
3
+ import { type CollectingPass } from '../../xml/xml-read.ts';
3
4
  /** The standard `<dataValidations>` element for the rules stored in the legacy form, or '' when the
4
5
  * sheet has none of them, so a sheet with only extended (or no) validations stays byte-clean here.
5
6
  * The extended rules are emitted separately by {@link dataValidationsExtXml}. */
@@ -8,13 +9,14 @@ export declare function dataValidationsXml(entries: readonly DataValidationEntry
8
9
  * none. Emitted bare (no `<extLst>` wrapper) so the worksheet serialiser can gather it into a single
9
10
  * `<extLst>` beside the conditional-formatting extension: a worksheet may carry at most one. */
10
11
  export declare function dataValidationsExtXml(entries: readonly DataValidationEntry[]): string;
11
- /** Parse every standard `<dataValidation>` out of a worksheet part into range-bound rules. */
12
- export declare function parseDataValidations(xml: string): DataValidationEntry[];
13
- /** Parse every extended `<x14:dataValidation>` out of a worksheet's `<extLst>` into range-bound
14
- * rules tagged `extended`, so a cross-sheet or whole-column list validation Excel stored only in the
15
- * 2009 extension form is read back rather than dropped. The standard parser ignores these (they are
16
- * prefixed); this one, symmetrically, handles only the prefixed elements. */
17
- export declare function parseExtendedDataValidations(xml: string): DataValidationEntry[];
12
+ /** A pass gathering the standard `<dataValidation>` elements of a worksheet part, for a caller
13
+ * reading the part alongside its other readers in one parse. */
14
+ export declare function dataValidationPass(): CollectingPass<DataValidationEntry[]>;
15
+ /** A pass gathering the extended `<x14:dataValidation>` elements of a worksheet's `<extLst>`, so a
16
+ * cross-sheet or whole-column list validation Excel stored only in the 2009 extension form is read
17
+ * back rather than dropped. The standard pass ignores these (they are prefixed); this one,
18
+ * symmetrically, handles only the prefixed elements. */
19
+ export declare function extendedDataValidationPass(): CollectingPass<DataValidationEntry[]>;
18
20
  /** Fold parsed validations onto a sheet, each bound to its original range and carrying its form: an
19
21
  * `extended` entry is re-attached as extended so a round-trip writes it back to the x14 block. */
20
22
  export declare function applyDataValidations(sheet: Worksheet, entries: readonly DataValidationEntry[]): void;
@@ -1,8 +1,12 @@
1
1
  import { isDataValidationErrorStyle, isDataValidationOperator, isDataValidationType, } from '../../core/data-validation.js';
2
+ import { stripFormulaEquals } from '../../core/formula.js';
2
3
  import { decodeSqrefRects } from '../../core/merge.js';
3
- import { boolStrict, coerceNumericLiteral, localName, parseXml, TextCapture, } from '../../xml/xml-read.js';
4
- import { checkedToken, escapeAttr, escapeText, stripFormulaEquals, textAttr } from '../../xml/xml.js';
5
- import { DATA_VALIDATION_EXT_URI, XM_NS } from './namespaces.js';
4
+ import { coerceNumericLiteral } from '../../xml/xml-attrs.js';
5
+ import { TextCapture } from '../../xml/xml-read.js';
6
+ import { boolStrict, localName } from '../../xml/xml-scan.js';
7
+ import { checkedToken, escapeAttr, escapeText, textAttr } from '../../xml/xml.js';
8
+ import { DATA_VALIDATION_EXT_URI, isExtensionElement, isMainNamespaceElement, XM_NS, } from './namespaces.js';
9
+ import { admitting } from './read-repair.js';
6
10
  import { x14Ext } from './x14-ext.js';
7
11
  const TYPED = new Set(['whole', 'decimal', 'date', 'time', 'textLength']);
8
12
  export function dataValidationsXml(entries) {
@@ -57,34 +61,30 @@ function extendedDataValidationXml(sqref, rule) {
57
61
  `<xm:sqref>${escapeText(sqref)}</xm:sqref>`;
58
62
  return `<x14:dataValidation${ruleAttrs(rule)}>${body}</x14:dataValidation>`;
59
63
  }
60
- export function parseDataValidations(xml) {
64
+ const FORMULA_ELEMENTS = new Set(['formula1', 'formula2']);
65
+ export function dataValidationPass() {
61
66
  const entries = [];
62
67
  let current;
63
- let slot;
64
- parseXml(xml, {
65
- onOpen(name, attrs) {
68
+ const formula = new TextCapture(FORMULA_ELEMENTS);
69
+ const handlers = {
70
+ onOpen(name, attrs, selfClosing, scope) {
66
71
  const ln = localName(name);
67
- if (ln === 'dataValidation' && !name.includes(':')) {
72
+ if (ln === 'dataValidation' && isMainNamespaceElement(scope, name)) {
68
73
  current = { attrs, formulae: [] };
69
74
  }
70
- else if (current !== undefined && ln === 'formula1') {
71
- slot = 0;
72
- current.formulae[0] = '';
73
- }
74
- else if (current !== undefined && ln === 'formula2') {
75
- slot = 1;
76
- current.formulae[1] = '';
75
+ else if (current !== undefined) {
76
+ formula.open(ln, selfClosing);
77
77
  }
78
78
  },
79
79
  onText(text) {
80
- if (current !== undefined && slot !== undefined) {
81
- current.formulae[slot] = (current.formulae[slot] ?? '') + text;
82
- }
80
+ formula.text(text);
83
81
  },
84
82
  onClose(name) {
85
83
  const ln = localName(name);
86
- if (ln === 'formula1' || ln === 'formula2') {
87
- slot = undefined;
84
+ const text = formula.close(ln);
85
+ if (text !== undefined) {
86
+ if (current !== undefined)
87
+ current.formulae[ln === 'formula1' ? 0 : 1] = text;
88
88
  return;
89
89
  }
90
90
  if (ln === 'dataValidation' && current !== undefined) {
@@ -94,8 +94,8 @@ export function parseDataValidations(xml) {
94
94
  current = undefined;
95
95
  }
96
96
  },
97
- });
98
- return entries;
97
+ };
98
+ return { handlers, result: () => entries };
99
99
  }
100
100
  function buildEntry(attrs, formulae) {
101
101
  const { sqref } = attrs;
@@ -139,22 +139,22 @@ function buildRule(attrs, formulae) {
139
139
  rule.formulae = parsed;
140
140
  return rule;
141
141
  }
142
- export function parseExtendedDataValidations(xml) {
142
+ export function extendedDataValidationPass() {
143
143
  const entries = [];
144
144
  let current;
145
145
  let slot;
146
146
  const capture = new TextCapture(['f', 'sqref']);
147
- parseXml(xml, {
148
- onOpen(name, attrs, selfClosing) {
147
+ const handlers = {
148
+ onOpen(name, attrs, selfClosing, scope) {
149
149
  const ln = localName(name);
150
- const prefixed = name.includes(':');
151
- if (ln === 'dataValidation' && prefixed) {
150
+ const extension = isExtensionElement(scope, name);
151
+ if (ln === 'dataValidation' && extension) {
152
152
  current = { attrs, formulae: [], sqref: '' };
153
153
  }
154
- else if (current !== undefined && prefixed && ln === 'formula1') {
154
+ else if (current !== undefined && extension && ln === 'formula1') {
155
155
  slot = 0;
156
156
  }
157
- else if (current !== undefined && prefixed && ln === 'formula2') {
157
+ else if (current !== undefined && extension && ln === 'formula2') {
158
158
  slot = 1;
159
159
  }
160
160
  else if (current !== undefined) {
@@ -164,8 +164,9 @@ export function parseExtendedDataValidations(xml) {
164
164
  onText(chunk) {
165
165
  capture.text(chunk);
166
166
  },
167
- onClose(name) {
167
+ onClose(name, scope) {
168
168
  const ln = localName(name);
169
+ const extension = isExtensionElement(scope, name);
169
170
  const text = capture.close(ln);
170
171
  if (text !== undefined) {
171
172
  if (ln === 'f') {
@@ -176,18 +177,18 @@ export function parseExtendedDataValidations(xml) {
176
177
  current.sqref = text;
177
178
  }
178
179
  }
179
- else if ((ln === 'formula1' || ln === 'formula2') && name.includes(':')) {
180
+ else if ((ln === 'formula1' || ln === 'formula2') && extension) {
180
181
  slot = undefined;
181
182
  }
182
- else if (ln === 'dataValidation' && name.includes(':') && current !== undefined) {
183
+ else if (ln === 'dataValidation' && extension && current !== undefined) {
183
184
  const built = buildExtendedEntry(current.attrs, current.formulae, current.sqref);
184
185
  if (built !== undefined)
185
186
  entries.push(built);
186
187
  current = undefined;
187
188
  }
188
189
  },
189
- });
190
- return entries;
190
+ };
191
+ return { handlers, result: () => entries };
191
192
  }
192
193
  function buildExtendedEntry(attrs, formulae, sqref) {
193
194
  if (sqref === '')
@@ -199,6 +200,8 @@ export function applyDataValidations(sheet, entries) {
199
200
  for (const { sqref, rule, extended } of entries) {
200
201
  if (decodeSqrefRects(sqref).length === 0)
201
202
  continue;
202
- sheet.addDataValidation(sqref, rule, extended ? { extended: true } : {});
203
+ admitting(() => {
204
+ sheet.addDataValidation(sqref, rule, extended ? { extended: true } : {});
205
+ });
203
206
  }
204
207
  }
@@ -1,4 +1,5 @@
1
1
  import { type VbaLibraryReference } from '../../vba/project-editor.ts';
2
+ import { type ReadPackageOptions } from '../opc/read-options.ts';
2
3
  /**
3
4
  * Remove a standard module from an existing macro-enabled package's VBA project, returning new package
4
5
  * bytes. Every part but `xl/vbaProject.bin` is preserved byte-for-byte (see {@link removeVbaModule} for
@@ -8,8 +9,10 @@ import { type VbaLibraryReference } from '../../vba/project-editor.ts';
8
9
  * @throws {VbaAuthorError} if the package carries no VBA project, `name` is not in the project, or names
9
10
  * a `document`/`designer` module.
10
11
  * @throws {VbaParseError} if the attached `vbaProject.bin` is malformed.
12
+ * @throws {PackageReadError} if the input is not a readable ZIP, or exceeds the inflate bound
13
+ * ({@link ReadPackageOptions.maxUncompressedBytes}, defaulting as `readXlsx` does).
11
14
  */
12
- export declare function editXlsxVbaRemoveModule(xlsx: Uint8Array, name: string): Uint8Array;
15
+ export declare function editXlsxVbaRemoveModule(xlsx: Uint8Array, name: string, options?: ReadPackageOptions): Uint8Array;
13
16
  /**
14
17
  * Add a registered (COM type-library) reference to an existing macro-enabled package's VBA project,
15
18
  * returning new package bytes. Every part but `xl/vbaProject.bin` is preserved byte-for-byte (see
@@ -19,5 +22,7 @@ export declare function editXlsxVbaRemoveModule(xlsx: Uint8Array, name: string):
19
22
  * @throws {VbaAuthorError} if the package carries no VBA project, or any field of `ref` is invalid (see
20
23
  * {@link VbaLibraryReference}).
21
24
  * @throws {VbaParseError} if the attached `vbaProject.bin` is malformed.
25
+ * @throws {PackageReadError} if the input is not a readable ZIP, or exceeds the inflate bound
26
+ * ({@link ReadPackageOptions.maxUncompressedBytes}, defaulting as `readXlsx` does).
22
27
  */
23
- export declare function editXlsxVbaAddReference(xlsx: Uint8Array, ref: VbaLibraryReference): Uint8Array;
28
+ export declare function editXlsxVbaAddReference(xlsx: Uint8Array, ref: VbaLibraryReference, options?: ReadPackageOptions): Uint8Array;
@@ -1,20 +1,22 @@
1
- import { strFromU8, strToU8, unzipSync, zipSync } from 'fflate';
1
+ import { strFromU8, strToU8, zipSync } from 'fflate';
2
2
  import { VbaAuthorError } from '../../vba/errors.js';
3
3
  import { addVbaReference, removeVbaModule, } from '../../vba/project-editor.js';
4
- import { relsPathFor } from '../opc/part-paths.js';
5
- import { parseRelationshipRecords, relationshipTargetByType, resolveRelativePart, resolveWorkbookPart, } from '../opc/read-opc.js';
4
+ import { relsPathFor, resolveRelativePart } from '../opc/part-paths.js';
5
+ import { parseRelationshipRecords, readPartRelationships } from '../opc/read-opc.js';
6
+ import { DEFAULT_MAX_UNCOMPRESSED } from '../opc/read-options.js';
7
+ import { inflateSpreadsheetPackage } from '../opc/sniff-format.js';
6
8
  import { FIXED_ENTRY_MTIME } from '../opc/zip-mtime.js';
7
9
  const OFFICE_DOCUMENT_REL = 'officeDocument';
8
10
  const VBA_PROJECT_REL = 'vbaProject';
9
11
  const VBA_SIGNATURE_REL_INFIX = 'vbaProjectSignature';
10
- export function editXlsxVbaRemoveModule(xlsx, name) {
11
- return applyToVbaProjectPart(xlsx, (bin) => removeVbaModule(bin, name));
12
+ export function editXlsxVbaRemoveModule(xlsx, name, options = {}) {
13
+ return applyToVbaProjectPart(xlsx, options, (bin) => removeVbaModule(bin, name));
12
14
  }
13
- export function editXlsxVbaAddReference(xlsx, ref) {
14
- return applyToVbaProjectPart(xlsx, (bin) => addVbaReference(bin, ref));
15
+ export function editXlsxVbaAddReference(xlsx, ref, options = {}) {
16
+ return applyToVbaProjectPart(xlsx, options, (bin) => addVbaReference(bin, ref));
15
17
  }
16
- function applyToVbaProjectPart(xlsx, apply) {
17
- const files = unzipSync(xlsx);
18
+ function applyToVbaProjectPart(xlsx, options, apply) {
19
+ const files = inflateSpreadsheetPackage(xlsx, options.maxUncompressedBytes ?? DEFAULT_MAX_UNCOMPRESSED);
18
20
  const binPath = locateVbaProjectPart(files);
19
21
  const bin = binPath === undefined ? undefined : files[binPath];
20
22
  if (binPath === undefined || bin === undefined) {
@@ -25,27 +27,11 @@ function applyToVbaProjectPart(xlsx, apply) {
25
27
  return zipSync(files, { mtime: FIXED_ENTRY_MTIME });
26
28
  }
27
29
  function locateVbaProjectPart(files) {
28
- const rootRels = textPart(files, '_rels/.rels');
29
- if (rootRels === undefined)
30
+ const partText = (path) => textPart(files, path);
31
+ const workbookPath = readPartRelationships('', partText).targetPath(OFFICE_DOCUMENT_REL);
32
+ if (workbookPath === undefined)
30
33
  return undefined;
31
- const workbookTarget = relationshipTargetByType(rootRels, OFFICE_DOCUMENT_REL);
32
- if (workbookTarget === undefined)
33
- return undefined;
34
- const workbookPath = resolveRelativePart('', workbookTarget);
35
- const workbookRels = textPart(files, relsPathFor(workbookPath));
36
- if (workbookRels === undefined)
37
- return undefined;
38
- const vbaTarget = relationshipTargetByType(workbookRels, VBA_PROJECT_REL);
39
- if (vbaTarget === undefined)
40
- return undefined;
41
- return resolveVbaTarget(workbookPath, vbaTarget);
42
- }
43
- function resolveVbaTarget(workbookPath, target) {
44
- if (target.startsWith('/'))
45
- return target.slice(1);
46
- if (workbookPath.startsWith('xl/'))
47
- return resolveWorkbookPart(target);
48
- return resolveRelativePart(workbookPath, target);
34
+ return readPartRelationships(workbookPath, partText).targetPath(VBA_PROJECT_REL);
49
35
  }
50
36
  function dropStaleSignature(files, binPath) {
51
37
  const binRelsPath = relsPathFor(binPath);
@@ -0,0 +1,7 @@
1
+ import { type Font } from '../../core/style.ts';
2
+ import { type XmlAttributes } from '../../xml/xml-scan.ts';
3
+ export type FontDraft = {
4
+ -readonly [K in keyof Font]?: Font[K];
5
+ };
6
+ export declare function applyFontChild(draft: FontDraft, local: string, attrs: XmlAttributes): void;
7
+ export declare function fontXml(font: Font, nameTag?: 'name' | 'rFont'): string;
@@ -0,0 +1,104 @@
1
+ import { isFontScheme, isFontVerticalAlignment, isNamedUnderlineStyle, } from '../../core/style.js';
2
+ import { numFinite, numInteger } from '../../xml/xml-attrs.js';
3
+ import { boolPresent } from '../../xml/xml-scan.js';
4
+ import { checkedToken, escapeAttr, numberText } from '../../xml/xml.js';
5
+ import { colorAttrs, parseColor } from './color-xml.js';
6
+ export function applyFontChild(draft, local, attrs) {
7
+ switch (local) {
8
+ case 'b':
9
+ draft.bold = boolPresent(attrs.val);
10
+ break;
11
+ case 'i':
12
+ draft.italic = boolPresent(attrs.val);
13
+ break;
14
+ case 'strike':
15
+ draft.strike = boolPresent(attrs.val);
16
+ break;
17
+ case 'outline':
18
+ draft.outline = boolPresent(attrs.val);
19
+ break;
20
+ case 'u':
21
+ draft.underline =
22
+ attrs.val === undefined
23
+ ? true
24
+ : attrs.val === 'none'
25
+ ? false
26
+ : isNamedUnderlineStyle(attrs.val)
27
+ ? attrs.val
28
+ : true;
29
+ break;
30
+ case 'vertAlign':
31
+ if (attrs.val !== undefined && isFontVerticalAlignment(attrs.val))
32
+ draft.vertAlign = attrs.val;
33
+ break;
34
+ case 'sz': {
35
+ const size = numFinite(attrs.val);
36
+ if (size !== undefined)
37
+ draft.size = size;
38
+ break;
39
+ }
40
+ case 'color':
41
+ draft.color = parseColor(attrs);
42
+ break;
43
+ case 'name':
44
+ case 'rFont':
45
+ if (attrs.val !== undefined)
46
+ draft.name = attrs.val;
47
+ break;
48
+ case 'family': {
49
+ const family = numInteger(attrs.val);
50
+ if (family !== undefined)
51
+ draft.family = family;
52
+ break;
53
+ }
54
+ case 'charset': {
55
+ const charset = numInteger(attrs.val);
56
+ if (charset !== undefined)
57
+ draft.charset = charset;
58
+ break;
59
+ }
60
+ case 'scheme':
61
+ if (attrs.val !== undefined && isFontScheme(attrs.val))
62
+ draft.scheme = attrs.val;
63
+ break;
64
+ default:
65
+ break;
66
+ }
67
+ }
68
+ export function fontXml(font, nameTag = 'name') {
69
+ const parts = [];
70
+ if (font.bold)
71
+ parts.push('<b/>');
72
+ if (font.italic)
73
+ parts.push('<i/>');
74
+ if (font.strike)
75
+ parts.push('<strike/>');
76
+ if (font.outline)
77
+ parts.push('<outline/>');
78
+ const underline = underlineXml(font.underline);
79
+ if (underline !== '')
80
+ parts.push(underline);
81
+ if (font.vertAlign !== undefined) {
82
+ parts.push(`<vertAlign val="${checkedToken(font.vertAlign, isFontVerticalAlignment, 'font vertical alignment')}"/>`);
83
+ }
84
+ if (font.size !== undefined)
85
+ parts.push(`<sz val="${numberText(font.size)}"/>`);
86
+ if (font.color !== undefined)
87
+ parts.push(`<color ${colorAttrs(font.color)}/>`);
88
+ if (font.name !== undefined)
89
+ parts.push(`<${nameTag} val="${escapeAttr(font.name)}"/>`);
90
+ if (font.family !== undefined)
91
+ parts.push(`<family val="${numberText(font.family)}"/>`);
92
+ if (font.charset !== undefined)
93
+ parts.push(`<charset val="${numberText(font.charset)}"/>`);
94
+ if (font.scheme !== undefined && font.scheme !== 'none')
95
+ parts.push(`<scheme val="${checkedToken(font.scheme, isFontScheme, 'font scheme')}"/>`);
96
+ return parts.join('');
97
+ }
98
+ function underlineXml(underline) {
99
+ if (underline === undefined || underline === false || underline === 'none')
100
+ return '';
101
+ if (underline === true || underline === 'single')
102
+ return '<u/>';
103
+ return `<u val="${checkedToken(underline, isNamedUnderlineStyle, 'underline style')}"/>`;
104
+ }
@@ -1,9 +1,18 @@
1
+ import type { Cell } from '../../core/cell.ts';
1
2
  import type { Worksheet } from '../../core/worksheet.ts';
2
- import type { SheetRelIds } from './package-plan.ts';
3
+ import { type CollectingPass } from '../../xml/xml-read.ts';
4
+ import type { RelIdAllocator } from './package-plan.ts';
3
5
  /** A hyperlink gathered from a sheet for serialisation: the cell it sits on, its target, and an
4
- * optional tooltip. The visible label is the cell's own value and is serialised as that value. */
6
+ * optional tooltip. The visible label is the cell's own value and is serialised as that value.
7
+ *
8
+ * `row`/`col` are the anchor's position, kept so links gathered from separate passes (the sheet's live
9
+ * rows, and the rows the streaming writer already flushed and evicted) can be merged back into the
10
+ * row-major order Excel writes them in. They are not serialised; `ref` is.
11
+ */
5
12
  export interface CollectedHyperlink {
6
13
  readonly ref: string;
14
+ readonly row: number;
15
+ readonly col: number;
7
16
  readonly target: string;
8
17
  readonly tooltip?: string;
9
18
  }
@@ -17,12 +26,36 @@ export interface HyperlinkPlan {
17
26
  readonly location?: string;
18
27
  readonly tooltip?: string;
19
28
  }
20
- /** Gather every hyperlink cell on a sheet, in row-major order. */
21
- export declare function collectHyperlinks(sheet: Worksheet): CollectedHyperlink[];
29
+ /**
30
+ * Gather every hyperlink among a run of cells.
31
+ *
32
+ * Takes the cells rather than the sheet, because the streaming writer has to ask this question of a
33
+ * row at the moment it commits: after that the row's cells are evicted, and a post-hoc walk of
34
+ * `sheet.rows()` finds nothing. Both writers therefore ask the same function, over whatever cells
35
+ * they still hold.
36
+ */
37
+ export declare function collectHyperlinks(cells: Iterable<Cell>): CollectedHyperlink[];
38
+ /** Every cell a sheet still holds, row-major: the live half of what a writer must gather. */
39
+ export declare function liveCells(sheet: Worksheet): Generator<Cell, void, undefined>;
40
+ /** An external hyperlink: the two fields a `TargetMode="External"` relationship needs, both present. */
41
+ export type ExternalHyperlinkPlan = HyperlinkPlan & {
42
+ readonly relId: string;
43
+ readonly target: string;
44
+ };
45
+ /**
46
+ * Whether a planned hyperlink is the external kind, narrowing it so the relationship writer reads
47
+ * `relId` and `target` as the strings they are.
48
+ *
49
+ * A predicate rather than a filter plus two casts: the filter already proved both fields present, and
50
+ * a cast repeating that proof one line later is a claim the compiler cannot check against the filter
51
+ * it is supposed to be echoing. `planHyperlinks` sets exactly one of `relId`/`location`, so testing
52
+ * either field is testing the kind.
53
+ */
54
+ export declare function isExternalHyperlink(link: HyperlinkPlan): link is ExternalHyperlinkPlan;
22
55
  /** Split collected links into internal (location, no rel) and external (relationship) forms, drawing
23
56
  * each external link's relationship id from the sheet's allocator so external ids follow every other
24
57
  * sheet-local relationship in canonical order. An internal ('#'-prefixed) link consumes no id. */
25
- export declare function planHyperlinks(links: readonly CollectedHyperlink[], rels: SheetRelIds): HyperlinkPlan[];
58
+ export declare function planHyperlinks(links: readonly CollectedHyperlink[], rels: RelIdAllocator): HyperlinkPlan[];
26
59
  /** The `<hyperlinks>` element, or '' when the sheet has none. Attribute order follows CT_Hyperlink:
27
60
  * `ref`, `r:id`, `location`, `tooltip`. */
28
61
  export declare function hyperlinksXml(links: readonly HyperlinkPlan[]): string;
@@ -34,8 +67,9 @@ interface ParsedHyperlink {
34
67
  readonly location?: string;
35
68
  readonly tooltip?: string;
36
69
  }
37
- /** Parse every `<hyperlink>` element out of a worksheet part. */
38
- export declare function parseSheetHyperlinks(xml: string): ParsedHyperlink[];
70
+ /** A pass gathering every `<hyperlink>` element of a worksheet part, for a caller reading the part
71
+ * alongside its other readers in one parse. */
72
+ export declare function sheetHyperlinkPass(): CollectingPass<ParsedHyperlink[]>;
39
73
  /** Fold parsed hyperlinks onto a sheet's cells, wrapping each cell's existing value (its visible
40
74
  * label) into a {@link HyperlinkValue}. `targetOf` resolves a relationship id to its raw Target: a
41
75
  * URL for the external links hyperlinks almost always are, so it must stay unresolved against the