@shbernal/ts-xlsx 3.0.0 → 3.2.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 (277) hide show
  1. package/README.md +34 -24
  2. package/dist/bytes.d.ts +10 -2
  3. package/dist/bytes.js +22 -0
  4. package/dist/core/address.d.ts +96 -2
  5. package/dist/core/address.js +87 -33
  6. package/dist/core/array-formula-ranges.d.ts +33 -0
  7. package/dist/core/array-formula-ranges.js +62 -0
  8. package/dist/core/autofilter.d.ts +4 -3
  9. package/dist/core/autofilter.js +31 -30
  10. package/dist/core/axis-handle.d.ts +2 -0
  11. package/dist/core/axis-handle.js +5 -2
  12. package/dist/core/cell.d.ts +4 -3
  13. package/dist/core/cell.js +4 -6
  14. package/dist/core/clone.d.ts +29 -0
  15. package/dist/core/clone.js +24 -0
  16. package/dist/core/color-resolution.js +4 -6
  17. package/dist/core/column.d.ts +1 -0
  18. package/dist/core/column.js +6 -2
  19. package/dist/core/comment-thread.d.ts +7 -3
  20. package/dist/core/comment-thread.js +2 -1
  21. package/dist/core/conditional-formatting-overlay.d.ts +11 -1
  22. package/dist/core/conditional-formatting-overlay.js +30 -3
  23. package/dist/core/conditional-formatting.d.ts +107 -11
  24. package/dist/core/conditional-formatting.js +76 -19
  25. package/dist/core/containers.d.ts +12 -0
  26. package/dist/core/containers.js +5 -0
  27. package/dist/core/data-validation-overlay.d.ts +7 -1
  28. package/dist/core/data-validation-overlay.js +19 -4
  29. package/dist/core/data-validation.d.ts +22 -0
  30. package/dist/core/data-validation.js +30 -4
  31. package/dist/core/date-format.d.ts +20 -0
  32. package/dist/core/date-format.js +170 -0
  33. package/dist/core/date.d.ts +43 -8
  34. package/dist/core/date.js +19 -3
  35. package/dist/core/formula-references.d.ts +26 -0
  36. package/dist/core/formula-references.js +173 -0
  37. package/dist/core/formula-scan.d.ts +2 -0
  38. package/dist/core/formula-scan.js +58 -0
  39. package/dist/core/formula.d.ts +76 -17
  40. package/dist/core/formula.js +87 -80
  41. package/dist/core/function-values.d.ts +4 -0
  42. package/dist/core/function-values.js +58 -0
  43. package/dist/core/future-functions.d.ts +3 -0
  44. package/dist/core/{modern-functions.js → future-functions.js} +119 -88
  45. package/dist/core/grid-edits.d.ts +30 -3
  46. package/dist/core/grid-edits.js +248 -81
  47. package/dist/core/grid-shift.d.ts +58 -9
  48. package/dist/core/grid-shift.js +26 -4
  49. package/dist/core/hyperlink.d.ts +39 -0
  50. package/dist/core/hyperlink.js +88 -0
  51. package/dist/core/image.d.ts +49 -14
  52. package/dist/core/image.js +16 -5
  53. package/dist/core/internal.d.ts +10 -2
  54. package/dist/core/limits.d.ts +25 -0
  55. package/dist/core/limits.js +4 -0
  56. package/dist/core/merge.d.ts +18 -4
  57. package/dist/core/merge.js +33 -20
  58. package/dist/core/page-setup.d.ts +26 -11
  59. package/dist/core/pivot-table.d.ts +49 -10
  60. package/dist/core/pivot-table.js +112 -60
  61. package/dist/core/protection.d.ts +66 -4
  62. package/dist/core/protection.js +6 -11
  63. package/dist/core/range.js +34 -30
  64. package/dist/core/row-input.js +2 -2
  65. package/dist/core/row.d.ts +1 -0
  66. package/dist/core/row.js +6 -2
  67. package/dist/core/structured-reference.d.ts +7 -0
  68. package/dist/core/structured-reference.js +7 -0
  69. package/dist/core/style.d.ts +85 -70
  70. package/dist/core/style.js +92 -28
  71. package/dist/core/table-style.d.ts +1 -1
  72. package/dist/core/table-style.js +4 -4
  73. package/dist/core/table.d.ts +64 -16
  74. package/dist/core/table.js +87 -40
  75. package/dist/core/theme.d.ts +2 -0
  76. package/dist/core/theme.js +9 -5
  77. package/dist/core/value.d.ts +60 -28
  78. package/dist/core/value.js +48 -43
  79. package/dist/core/workbook-media.d.ts +34 -0
  80. package/dist/core/workbook-media.js +44 -0
  81. package/dist/core/workbook-styles.d.ts +83 -1
  82. package/dist/core/workbook-styles.js +4 -0
  83. package/dist/core/workbook-theme.js +5 -3
  84. package/dist/core/workbook-vba.js +3 -2
  85. package/dist/core/workbook.d.ts +41 -3
  86. package/dist/core/workbook.js +46 -41
  87. package/dist/core/worksheet-comments.d.ts +2 -1
  88. package/dist/core/worksheet-comments.js +20 -13
  89. package/dist/core/worksheet-merges.d.ts +49 -0
  90. package/dist/core/worksheet-merges.js +65 -0
  91. package/dist/core/worksheet-model.d.ts +10 -2
  92. package/dist/core/worksheet-model.js +28 -9
  93. package/dist/core/worksheet-pictures.d.ts +3 -3
  94. package/dist/core/worksheet-pictures.js +7 -6
  95. package/dist/core/worksheet.d.ts +165 -27
  96. package/dist/core/worksheet.js +206 -89
  97. package/dist/customui/ribbon.js +2 -1
  98. package/dist/entries/core.d.ts +21 -14
  99. package/dist/entries/core.js +14 -7
  100. package/dist/entries/errors.d.ts +1 -0
  101. package/dist/entries/errors.js +1 -0
  102. package/dist/entries/xlsx.d.ts +1 -1
  103. package/dist/errors.d.ts +64 -0
  104. package/dist/errors.js +22 -0
  105. package/dist/hex.d.ts +8 -0
  106. package/dist/hex.js +3 -0
  107. package/dist/io/cell-metadata/metadata.d.ts +42 -0
  108. package/dist/io/cell-metadata/metadata.js +35 -0
  109. package/dist/io/cell-metadata/rich-values.d.ts +11 -0
  110. package/dist/io/cell-metadata/rich-values.js +80 -0
  111. package/dist/io/csv/delimiter.d.ts +21 -0
  112. package/dist/io/csv/delimiter.js +18 -0
  113. package/dist/io/csv/errors.d.ts +14 -0
  114. package/dist/io/csv/errors.js +5 -0
  115. package/dist/io/csv/read.d.ts +6 -1
  116. package/dist/io/csv/read.js +51 -22
  117. package/dist/io/csv/write.d.ts +19 -5
  118. package/dist/io/csv/write.js +24 -44
  119. package/dist/io/opc/inflate.js +14 -0
  120. package/dist/io/opc/namespaces.d.ts +16 -0
  121. package/dist/io/opc/namespaces.js +4 -0
  122. package/dist/io/opc/part-paths.d.ts +9 -0
  123. package/dist/io/opc/part-paths.js +5 -5
  124. package/dist/io/opc/read-opc.d.ts +58 -14
  125. package/dist/io/opc/read-opc.js +49 -21
  126. package/dist/io/opc/read-options.d.ts +5 -1
  127. package/dist/io/opc/sniff-format.d.ts +3 -3
  128. package/dist/io/opc/sniff-format.js +2 -2
  129. package/dist/io/opc/strict-relationships.d.ts +2 -0
  130. package/dist/io/opc/strict-relationships.js +12 -0
  131. package/dist/io/read-policy/column-budget.d.ts +26 -0
  132. package/dist/io/read-policy/column-budget.js +18 -0
  133. package/dist/io/read-policy/read-repair.d.ts +74 -0
  134. package/dist/io/read-policy/read-repair.js +119 -0
  135. package/dist/io/style/cell-style-resolution.d.ts +25 -0
  136. package/dist/io/style/cell-style-resolution.js +30 -0
  137. package/dist/io/style/xf-style.d.ts +23 -1
  138. package/dist/io/style/xf-style.js +8 -0
  139. package/dist/io/xlsb/formula.d.ts +2 -2
  140. package/dist/io/xlsb/formula.js +52 -35
  141. package/dist/io/xlsb/primitives.js +8 -14
  142. package/dist/io/xlsb/ptg-functions.d.ts +19 -10
  143. package/dist/io/xlsb/ptg-functions.js +495 -596
  144. package/dist/io/xlsb/read-metadata.d.ts +7 -0
  145. package/dist/io/xlsb/read-metadata.js +69 -0
  146. package/dist/io/xlsb/read-styles.js +45 -81
  147. package/dist/io/xlsb/read-worksheet.d.ts +26 -1
  148. package/dist/io/xlsb/read-worksheet.js +148 -106
  149. package/dist/io/xlsb/read.d.ts +6 -3
  150. package/dist/io/xlsb/read.js +70 -31
  151. package/dist/io/xlsb/record-stream.d.ts +30 -0
  152. package/dist/io/xlsb/record-stream.js +20 -0
  153. package/dist/io/xlsb/record-types.d.ts +14 -5
  154. package/dist/io/xlsb/record-types.js +14 -5
  155. package/dist/io/xlsb/sheet-protection.d.ts +20 -0
  156. package/dist/io/xlsb/sheet-protection.js +60 -0
  157. package/dist/io/xlsx/cell-accumulator.d.ts +24 -9
  158. package/dist/io/xlsx/cell-accumulator.js +74 -21
  159. package/dist/io/xlsx/cell-metadata.d.ts +39 -0
  160. package/dist/io/xlsx/cell-metadata.js +162 -0
  161. package/dist/io/xlsx/cell-value.d.ts +19 -5
  162. package/dist/io/xlsx/cell-value.js +45 -30
  163. package/dist/io/xlsx/color-xml.js +3 -2
  164. package/dist/io/xlsx/column-span.d.ts +11 -0
  165. package/dist/io/xlsx/column-span.js +9 -0
  166. package/dist/io/xlsx/comments.d.ts +9 -30
  167. package/dist/io/xlsx/comments.js +25 -83
  168. package/dist/io/xlsx/conditional-formatting.d.ts +43 -23
  169. package/dist/io/xlsx/conditional-formatting.js +437 -138
  170. package/dist/io/xlsx/data-validation.d.ts +12 -7
  171. package/dist/io/xlsx/data-validation.js +67 -53
  172. package/dist/io/xlsx/edit-vba.d.ts +7 -2
  173. package/dist/io/xlsx/edit-vba.js +52 -52
  174. package/dist/io/xlsx/font-xml.d.ts +7 -0
  175. package/dist/io/xlsx/font-xml.js +104 -0
  176. package/dist/io/xlsx/hyperlinks.d.ts +19 -21
  177. package/dist/io/xlsx/hyperlinks.js +12 -32
  178. package/dist/io/xlsx/images.d.ts +49 -16
  179. package/dist/io/xlsx/images.js +149 -50
  180. package/dist/io/xlsx/namespaces.d.ts +24 -0
  181. package/dist/io/xlsx/namespaces.js +11 -0
  182. package/dist/io/xlsx/package-plan.d.ts +60 -15
  183. package/dist/io/xlsx/package-plan.js +83 -18
  184. package/dist/io/xlsx/part-names.d.ts +6 -8
  185. package/dist/io/xlsx/part-names.js +3 -7
  186. package/dist/io/xlsx/pivot.d.ts +5 -5
  187. package/dist/io/xlsx/pivot.js +26 -24
  188. package/dist/io/xlsx/preserved-splices.d.ts +6 -0
  189. package/dist/io/xlsx/preserved-splices.js +74 -0
  190. package/dist/io/xlsx/read-comments.d.ts +29 -0
  191. package/dist/io/xlsx/read-comments.js +75 -0
  192. package/dist/io/xlsx/read-parts.d.ts +59 -0
  193. package/dist/io/xlsx/read-parts.js +259 -0
  194. package/dist/io/xlsx/read-pivot.js +11 -4
  195. package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +8 -5
  196. package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +24 -4
  197. package/dist/io/xlsx/read-rows.d.ts +35 -11
  198. package/dist/io/xlsx/read-rows.js +73 -49
  199. package/dist/io/xlsx/read-shared-strings.js +3 -2
  200. package/dist/io/xlsx/read-styles.d.ts +0 -30
  201. package/dist/io/xlsx/read-styles.js +45 -105
  202. package/dist/io/xlsx/read-workbook-xml.d.ts +42 -0
  203. package/dist/io/xlsx/read-workbook-xml.js +175 -0
  204. package/dist/io/xlsx/read-worksheet.d.ts +9 -3
  205. package/dist/io/xlsx/read-worksheet.js +70 -177
  206. package/dist/io/xlsx/read.d.ts +3 -14
  207. package/dist/io/xlsx/read.js +74 -411
  208. package/dist/io/xlsx/relationships.d.ts +3 -0
  209. package/dist/io/xlsx/relationships.js +4 -0
  210. package/dist/io/xlsx/rich-text.js +1 -1
  211. package/dist/io/xlsx/row-position.d.ts +20 -0
  212. package/dist/io/xlsx/row-position.js +11 -0
  213. package/dist/io/xlsx/row-xml.d.ts +139 -0
  214. package/dist/io/xlsx/row-xml.js +222 -0
  215. package/dist/io/xlsx/shared-formulas.js +2 -2
  216. package/dist/io/xlsx/sheet-properties.d.ts +10 -1
  217. package/dist/io/xlsx/sheet-properties.js +182 -20
  218. package/dist/io/xlsx/strict-parts.d.ts +7 -0
  219. package/dist/io/xlsx/strict-parts.js +171 -0
  220. package/dist/io/xlsx/style-elements.d.ts +41 -0
  221. package/dist/io/xlsx/style-elements.js +136 -0
  222. package/dist/io/xlsx/styles.d.ts +17 -3
  223. package/dist/io/xlsx/styles.js +13 -209
  224. package/dist/io/xlsx/tables.d.ts +10 -2
  225. package/dist/io/xlsx/tables.js +55 -52
  226. package/dist/io/xlsx/theme-xml.d.ts +32 -4
  227. package/dist/io/xlsx/theme-xml.js +106 -71
  228. package/dist/io/xlsx/threaded-comments.d.ts +14 -11
  229. package/dist/io/xlsx/threaded-comments.js +16 -8
  230. package/dist/io/xlsx/workbook-xml.d.ts +45 -6
  231. package/dist/io/xlsx/workbook-xml.js +62 -54
  232. package/dist/io/xlsx/worksheet-xml.d.ts +26 -70
  233. package/dist/io/xlsx/worksheet-xml.js +69 -282
  234. package/dist/io/xlsx/write-stream.d.ts +90 -19
  235. package/dist/io/xlsx/write-stream.js +80 -25
  236. package/dist/io/xlsx/write.d.ts +12 -6
  237. package/dist/io/xlsx/write.js +226 -123
  238. package/dist/rel-type.d.ts +25 -0
  239. package/dist/rel-type.js +9 -0
  240. package/dist/token-set.d.ts +13 -0
  241. package/dist/token-set.js +4 -1
  242. package/dist/vba/bytes.d.ts +16 -5
  243. package/dist/vba/bytes.js +27 -6
  244. package/dist/vba/cfb-format.d.ts +55 -0
  245. package/dist/vba/cfb-format.js +35 -0
  246. package/dist/vba/cfb-writer.d.ts +8 -0
  247. package/dist/vba/cfb-writer.js +40 -40
  248. package/dist/vba/cfb.d.ts +21 -4
  249. package/dist/vba/cfb.js +124 -90
  250. package/dist/vba/codepage.js +2 -1
  251. package/dist/vba/dir-records.d.ts +6 -0
  252. package/dist/vba/dir-records.js +10 -2
  253. package/dist/vba/errors.d.ts +11 -4
  254. package/dist/vba/index.d.ts +0 -2
  255. package/dist/vba/index.js +0 -2
  256. package/dist/vba/ms-ovba.d.ts +6 -2
  257. package/dist/vba/ms-ovba.js +66 -22
  258. package/dist/vba/project-editor.js +129 -119
  259. package/dist/vba/project.d.ts +15 -1
  260. package/dist/vba/project.js +38 -13
  261. package/dist/vba/vba-encoding.d.ts +4 -10
  262. package/dist/vba/vba-encoding.js +3 -17
  263. package/dist/xml/xml-attrs.d.ts +37 -0
  264. package/dist/xml/xml-attrs.js +30 -0
  265. package/dist/xml/xml-chars.d.ts +40 -0
  266. package/dist/xml/xml-chars.js +12 -0
  267. package/dist/xml/xml-namespaces.d.ts +31 -0
  268. package/dist/xml/xml-namespaces.js +50 -0
  269. package/dist/xml/xml-read.d.ts +101 -11
  270. package/dist/xml/xml-read.js +150 -18
  271. package/dist/xml/xml-scan.d.ts +25 -34
  272. package/dist/xml/xml-scan.js +69 -46
  273. package/dist/xml/xml.d.ts +59 -26
  274. package/dist/xml/xml.js +45 -23
  275. package/package.json +15 -9
  276. package/skills/ts-xlsx-upstream/SKILL.md +21 -13
  277. package/dist/core/modern-functions.d.ts +0 -1
@@ -0,0 +1,139 @@
1
+ import type { FormulaPlacement } from '../../core/array-formula-ranges.ts';
2
+ import { type Cell } from '../../core/cell.ts';
3
+ import { type DateEpoch } from '../../core/date.ts';
4
+ import type { ColumnProperties, RowProperties, Worksheet } from '../../core/worksheet.ts';
5
+ import type { WorkbookMetadataTable } from './cell-metadata.ts';
6
+ import type { CommentCell } from './comments.ts';
7
+ import type { SharedFormulaRole } from './shared-formulas.ts';
8
+ import type { SharedStringTable } from './shared-strings.ts';
9
+ import type { StyleRegistry } from './styles.ts';
10
+ /**
11
+ * The used-cell extent of a sheet: the top-left/bottom-right grid bounds that fold into the
12
+ * `<dimension>`. Rows carrying only formatting (a row height, an outline level) do not extend the
13
+ * used range, matching how Excel records `<dimension>`, so {@link add} ignores them. A fresh extent
14
+ * holds the `Infinity`/`-Infinity` sentinels; {@link isEmpty} reports that no used cell has been seen.
15
+ */
16
+ export declare class Extent {
17
+ top: number;
18
+ left: number;
19
+ bottom: number;
20
+ right: number;
21
+ constructor(seed?: Extent);
22
+ /** Whether no used cell has been folded in yet, in which case the dimension is the lone cell `A1`. */
23
+ get isEmpty(): boolean;
24
+ /** Fold a rendered row's used-column span into the extent. `minCol` is `Infinity` when the row
25
+ * carried no cells (only formatting), which extends nothing. */
26
+ add(row: number, minCol: number, maxCol: number): void;
27
+ }
28
+ /**
29
+ * A row the streaming writer already serialised, kept with the attribute string it was built from.
30
+ *
31
+ * The attributes are carried rather than re-read out of `xml`, and that is the whole point of the
32
+ * field. `collapsed="1"` is decided after the row is gone (see {@link FlushedSheet.rowOutline}), so
33
+ * the summary row has to be patched, and the patcher used to ask `xml.includes(' collapsed="1"')`
34
+ * whether the attribute was already there. The `<row>` tag's shape is known, but the *cell text*
35
+ * embedded in it is not: `escapeText` leaves a double quote verbatim, so a cell whose value was the
36
+ * literal string ` collapsed="1"` answered that question for the row and left the outline group
37
+ * rendering expanded. A file cannot forge a field.
38
+ */
39
+ export interface FlushedRow {
40
+ readonly number: number;
41
+ readonly xml: string;
42
+ /** The `<row>` element's own attributes, exactly as {@link renderRow} emitted them. */
43
+ readonly attrs: string;
44
+ }
45
+ /**
46
+ * A worksheet's eagerly-serialised rows: each row's `<row>` XML tagged with its number (so it merges
47
+ * into ascending order with the sheet's remaining live rows, whatever order it was committed in), plus
48
+ * the used-cell {@link Extent} they span. The buffered pass folds that extent into the sheet's dimension.
49
+ */
50
+ export interface FlushedSheet {
51
+ readonly rows: readonly FlushedRow[];
52
+ readonly extent: Extent;
53
+ /**
54
+ * Each flushed row's outline level and hidden flag. Carried across the eviction because both feed
55
+ * whole-sheet derivations made long after the row is gone from the model: `<sheetFormatPr
56
+ * outlineLevelRow>` is the deepest level on the sheet, and `collapsed="1"` rides a summary row only
57
+ * when its whole detail group is hidden, which is a question about *other* rows.
58
+ *
59
+ * Carried as the two inputs rather than the derived flag, because the derivation is a look-ahead a
60
+ * row being finalised cannot do, while its inputs are per-row and known exactly when the row flushes.
61
+ */
62
+ readonly rowOutline: ReadonlyMap<number, {
63
+ readonly outlineLevel: number;
64
+ readonly hidden: boolean;
65
+ }>;
66
+ /**
67
+ * The notes the flushed rows carried, on the same terms and for the same reason. A note is
68
+ * serialised outside the `<row>`, into the comments and VML parts, and the buffered pass gathers
69
+ * notes by walking the sheet's rows at commit time, which finds nothing on a row whose cells have
70
+ * already been evicted. A hyperlink needs no such record: it lives beside the grid, on the sheet.
71
+ */
72
+ readonly notes: readonly CommentCell[];
73
+ /**
74
+ * The formulas the flushed rows carried, on the same terms again: whether an array formula's range
75
+ * holds another formula, or shares a cell with another's, is a question about other rows, and the
76
+ * writer asks it of the whole sheet at commit.
77
+ */
78
+ readonly formulas: readonly FormulaPlacement[];
79
+ }
80
+ /**
81
+ * A column's style facets are defaults its cells inherit unless they override them; the writer
82
+ * composes each cell's full style up front (cell over row over column, per facet) so a cell that
83
+ * overrides one facet still carries the column's others, rather than silently dropping them. Frozen
84
+ * once by the streaming writer at its first flush so every eagerly-rendered row sees the same defaults.
85
+ */
86
+ export declare function buildColumnDefaults(sheet: Worksheet): Map<number, ColumnProperties>;
87
+ /** The whole-sheet context a single row needs to serialise: the column defaults it inherits, the
88
+ * style/string tables it interns into, the shared-formula roles its cells play, and the collapsed
89
+ * outline summaries whose toggle it must stamp. The streaming writer supplies empty shared-formula
90
+ * and collapsed-summary sets, since those are whole-sheet derivations a flushed row cannot join. */
91
+ export interface RowRenderContext {
92
+ readonly columnDefaults: ReadonlyMap<number, ColumnProperties>;
93
+ readonly styles: StyleRegistry;
94
+ readonly sharedStrings: SharedStringTable | null;
95
+ readonly sharedRoles: ReadonlyMap<string, SharedFormulaRole>;
96
+ readonly collapsedSummaries: ReadonlySet<number>;
97
+ /** The workbook's date system, which is what a `Date` cell's serial counts from. */
98
+ readonly dateEpoch: DateEpoch;
99
+ /** The defined names a bare name in this sheet's formulas resolves to, as `formulaNamesInScope`
100
+ * gives them: a function passed as a value is written bare where one of them captures its name. */
101
+ readonly formulaNames: ReadonlySet<string>;
102
+ /** The workbook's metadata, which a dynamic-array formula's cell and a rich-value error's cell point
103
+ * into. Shared by every row of every sheet, since the parts it becomes are the workbook's. */
104
+ readonly cellMetadata: WorkbookMetadataTable;
105
+ }
106
+ /**
107
+ * Serialise one row to its `<row>` element, or '' when the row has neither data nor its own
108
+ * formatting. Returns the used-column bounds (`Infinity`/`-Infinity` when nothing was rendered) so a
109
+ * caller can fold them into the sheet dimension, and the attribute string separately, so a later pass
110
+ * can ask what this row declared without reading it back out of markup that also holds cell text.
111
+ * Shared by the buffered sheet pass and the streaming writer's eager flush, so both emit
112
+ * byte-identical rows.
113
+ */
114
+ export declare function renderRow(entry: {
115
+ readonly number: number;
116
+ readonly cells: readonly Cell[];
117
+ readonly properties: RowProperties | undefined;
118
+ }, ctx: RowRenderContext): {
119
+ xml: string;
120
+ attrs: string;
121
+ minCol: number;
122
+ maxCol: number;
123
+ };
124
+ /**
125
+ * The `<row>` element's opening tag up to its first attribute: the one thing a later pass may rely on
126
+ * about a rendered row's shape, spelled here so it is the emitter's own string rather than a
127
+ * re-parse of the emitter's output.
128
+ */
129
+ export declare function rowOpenTag(number: number): string;
130
+ /**
131
+ * Refuse an outline depth that is not a non-negative integer, naming what carried it.
132
+ *
133
+ * `xsd:unsignedInt` is the attribute's type, so this is what the schema already says. It is asserted
134
+ * rather than clamped because a negative level is also a hang: the writer finds a group's end by
135
+ * walking outwards while the neighbouring level exceeds the summary's, and every unmapped row
136
+ * answers `0`, which exceeds `-1` for as long as there are rows to walk.
137
+ */
138
+ export declare function assertWritableLevel(name: string, level: number): void;
139
+ export declare function outlineAttr(name: string, level: number | undefined): string;
@@ -0,0 +1,222 @@
1
+ import { encodeRange, tryDecodeAnchoredRange } from '../../core/address.js';
2
+ import { cellHasOwnStyle } from '../../core/cell.js';
3
+ import { DEFAULT_DATE_NUMFMT, dateToSerial } from '../../core/date.js';
4
+ import { mangleFormula } from '../../core/formula.js';
5
+ import { NAMED_STYLE_ID } from '../../core/internal.js';
6
+ import { CELL_STYLE_FACETS } from '../../core/style.js';
7
+ import { detectValueType, isArrayFormulaValue, isDataTableFormulaValue, isErrorCode, isErrorValue, isFormulaValue, isRichTextValue, isSharedFormulaValue, } from '../../core/value.js';
8
+ import { AuthoringError, InternalError, quoted } from '../../errors.js';
9
+ import { boolAttr, checkedToken, escapeAttr, escapeSpreadsheetText, escapeText, numberText, nonDefaultNumAttr, textAttr, textElement, } from '../../xml/xml.js';
10
+ import { richTextRunsXml } from './rich-text.js';
11
+ export class Extent {
12
+ top = Infinity;
13
+ left = Infinity;
14
+ bottom = -Infinity;
15
+ right = -Infinity;
16
+ constructor(seed) {
17
+ if (seed) {
18
+ this.top = seed.top;
19
+ this.left = seed.left;
20
+ this.bottom = seed.bottom;
21
+ this.right = seed.right;
22
+ }
23
+ }
24
+ get isEmpty() {
25
+ return this.bottom === -Infinity;
26
+ }
27
+ add(row, minCol, maxCol) {
28
+ if (minCol === Infinity)
29
+ return;
30
+ if (row < this.top)
31
+ this.top = row;
32
+ if (row > this.bottom)
33
+ this.bottom = row;
34
+ if (minCol < this.left)
35
+ this.left = minCol;
36
+ if (maxCol > this.right)
37
+ this.right = maxCol;
38
+ }
39
+ }
40
+ export function buildColumnDefaults(sheet) {
41
+ const columnDefaults = new Map();
42
+ for (const { index, properties } of sheet.columns())
43
+ columnDefaults.set(index, properties ?? {});
44
+ return columnDefaults;
45
+ }
46
+ export function renderRow(entry, ctx) {
47
+ const { number, cells, properties } = entry;
48
+ const rendered = cells.filter((cell) => cell.value !== null || cellHasOwnStyle(cell));
49
+ const attrs = rowAttrs(properties, ctx.styles, ctx.collapsedSummaries.has(number));
50
+ if (rendered.length === 0 && attrs === '') {
51
+ return { xml: '', attrs: '', minCol: Infinity, maxCol: -Infinity };
52
+ }
53
+ const rowFill = properties?.fill;
54
+ const cellsXml = rendered
55
+ .map((cell) => {
56
+ const style = ctx.styles.styleId(composeCellStyle(cell, rowFill, ctx.columnDefaults.get(cell.col)));
57
+ return cellXml(cell, style, ctx.sharedRoles.get(cell.address), ctx);
58
+ })
59
+ .join('');
60
+ let minCol = Infinity;
61
+ let maxCol = -Infinity;
62
+ for (const cell of rendered) {
63
+ if (cell.col < minCol)
64
+ minCol = cell.col;
65
+ if (cell.col > maxCol)
66
+ maxCol = cell.col;
67
+ }
68
+ return { xml: `${rowOpenTag(number)}${attrs}>${cellsXml}</row>`, attrs, minCol, maxCol };
69
+ }
70
+ export function rowOpenTag(number) {
71
+ return `<row r="${number}"`;
72
+ }
73
+ function composeCellStyle(cell, rowFill, colDef) {
74
+ const style = {};
75
+ for (const facet of CELL_STYLE_FACETS)
76
+ inheritFacet(style, facet, cell, colDef);
77
+ style.fill = cell.fill ?? rowFill ?? colDef?.fill;
78
+ style.numFmt = cell.numFmt ?? colDef?.numFmt ?? dateDefaultNumFmt(cell.value);
79
+ if (cell.quotePrefix !== undefined)
80
+ style.quotePrefix = cell.quotePrefix;
81
+ const xfId = cell[NAMED_STYLE_ID];
82
+ if (xfId !== undefined)
83
+ style.xfId = xfId;
84
+ return style;
85
+ }
86
+ function inheritFacet(target, key, cell, colDef) {
87
+ target[key] = cell[key] ?? colDef?.[key];
88
+ }
89
+ function rowAttrs(properties, styles, collapsedSummary) {
90
+ if (properties === undefined)
91
+ return collapsedSummary ? ' collapsed="1"' : '';
92
+ let attrs = '';
93
+ if (properties.height !== undefined)
94
+ attrs += ` ht="${numberText(properties.height)}" customHeight="1"`;
95
+ if (properties.hidden)
96
+ attrs += ' hidden="1"';
97
+ attrs += outlineAttr('outlineLevel', properties.outlineLevel);
98
+ if (properties.collapsed || collapsedSummary)
99
+ attrs += ' collapsed="1"';
100
+ const style = styles.styleId({ fill: properties.fill });
101
+ if (style !== 0)
102
+ attrs += ` s="${style}" customFormat="1"`;
103
+ return attrs;
104
+ }
105
+ function dateDefaultNumFmt(value) {
106
+ const date = value instanceof Date
107
+ ? value
108
+ : (isFormulaValue(value) || isSharedFormulaValue(value) || isArrayFormulaValue(value)) &&
109
+ value.result instanceof Date
110
+ ? value.result
111
+ : undefined;
112
+ return date !== undefined && !Number.isNaN(date.getTime()) ? DEFAULT_DATE_NUMFMT : undefined;
113
+ }
114
+ function cellElement(ref, s, type, body, cm = '', vm = '') {
115
+ const attrs = `${s}${type === '' ? '' : ` t="${type}"`}${cm}${vm}`;
116
+ return body === '' ? `<c r="${ref}"${attrs}/>` : `<c r="${ref}"${attrs}>${body}</c>`;
117
+ }
118
+ const UNWRITABLE = { type: '', v: null };
119
+ const vElement = (v) => (v === null ? '' : `<v>${v}</v>`);
120
+ function valueBody(value, ctx) {
121
+ if (typeof value === 'number') {
122
+ return Number.isFinite(value) ? { type: '', v: numberText(value) } : UNWRITABLE;
123
+ }
124
+ if (typeof value === 'boolean')
125
+ return { type: 'b', v: value ? '1' : '0' };
126
+ if (value instanceof Date) {
127
+ return Number.isNaN(value.getTime())
128
+ ? UNWRITABLE
129
+ : { type: '', v: numberText(dateToSerial(value, ctx.dateEpoch)) };
130
+ }
131
+ if (isErrorValue(value)) {
132
+ checkedToken(value.error, isErrorCode, 'cell error value');
133
+ const vm = ctx.cellMetadata.markRichValueError(value.error);
134
+ return vm === undefined
135
+ ? { type: 'e', v: value.error }
136
+ : { type: 'e', v: '#VALUE!', vm: ` vm="${vm}"` };
137
+ }
138
+ return undefined;
139
+ }
140
+ function cellXml(cell, style, shared, ctx) {
141
+ const { sharedStrings } = ctx;
142
+ const ref = cell.address;
143
+ const value = cell.value;
144
+ const s = style !== 0 ? ` s="${style}"` : '';
145
+ const formula = cellFormulaXml(cell, s, shared, ctx);
146
+ if (formula !== undefined)
147
+ return formula;
148
+ const body = valueBody(value, ctx);
149
+ if (body !== undefined)
150
+ return cellElement(ref, s, body.type, vElement(body.v), '', body.vm);
151
+ if (typeof value === 'string' || isRichTextValue(value)) {
152
+ if (sharedStrings !== null) {
153
+ return cellElement(ref, s, 's', vElement(`${sharedStrings.intern(value)}`));
154
+ }
155
+ const inline = typeof value === 'string' ? textElement(value) : richTextRunsXml(value.richText);
156
+ return cellElement(ref, s, 'inlineStr', `<is>${inline}</is>`);
157
+ }
158
+ if (value === null)
159
+ return cellElement(ref, s, '', '');
160
+ throw new InternalError(`writing a ${detectValueType(value)} cell value has no arm: every CellValue kind is handled above`);
161
+ }
162
+ function cellFormulaXml(cell, s, shared, ctx) {
163
+ const { formulaNames } = ctx;
164
+ const { address: ref, value } = cell;
165
+ if (shared !== undefined) {
166
+ if (shared.ref !== undefined && isFormulaValue(value)) {
167
+ const f = `<f t="shared" ref="${shared.ref}" si="${shared.si}">${escapeText(mangleFormula(value.formula, formulaNames))}</f>`;
168
+ return formulaBodyXml(ref, s, f, value.result, ctx);
169
+ }
170
+ const result = isSharedFormulaValue(value) ? value.result : undefined;
171
+ return formulaBodyXml(ref, s, `<f t="shared" si="${shared.si}"/>`, result, ctx);
172
+ }
173
+ if (isDataTableFormulaValue(value)) {
174
+ const attrs = `ref="${escapeAttr(value.ref)}"` +
175
+ boolAttr('dt2D', value.dataTable2D) +
176
+ boolAttr('dtr', value.dataTableRow) +
177
+ (value.r1Deleted === true ? ' del1="1"' : '') +
178
+ (value.r2Deleted === true ? ' del2="1"' : '') +
179
+ textAttr('r1', value.r1) +
180
+ textAttr('r2', value.r2);
181
+ return formulaBodyXml(ref, s, `<f t="dataTable" ${attrs}/>`, value.result, ctx);
182
+ }
183
+ if (isArrayFormulaValue(value)) {
184
+ const cm = value.dynamic === true ? ` cm="${ctx.cellMetadata.markDynamicArray()}"` : '';
185
+ const f = `<f t="array" ref="${arrayFormulaRange(cell, value.ref)}">${escapeText(mangleFormula(value.formula, formulaNames))}</f>`;
186
+ return formulaBodyXml(ref, s, f, value.result, ctx, cm);
187
+ }
188
+ if (isFormulaValue(value)) {
189
+ return formulaBodyXml(ref, s, `<f>${escapeText(mangleFormula(value.formula, formulaNames))}</f>`, value.result, ctx);
190
+ }
191
+ return undefined;
192
+ }
193
+ function arrayFormulaRange(cell, ref) {
194
+ const range = tryDecodeAnchoredRange(ref, cell.col, cell.row);
195
+ if (range === undefined) {
196
+ throw new AuthoringError(`the array formula in ${cell.address} fills ${quoted(ref)}, which is not a range starting at ${cell.address}`);
197
+ }
198
+ return encodeRange(range);
199
+ }
200
+ function formulaBodyXml(ref, s, f, result, ctx, cm = '') {
201
+ if (result === undefined)
202
+ return cellElement(ref, s, '', f, cm);
203
+ const body = valueBody(result, ctx);
204
+ if (body !== undefined) {
205
+ return cellElement(ref, s, body.type, f + vElement(body.v), cm, body.vm);
206
+ }
207
+ if (typeof result === 'string') {
208
+ return cellElement(ref, s, 'str', f + vElement(escapeSpreadsheetText(result)), cm);
209
+ }
210
+ throw new InternalError('writing a non-primitive formula result has no arm: every FormulaResult kind is handled above');
211
+ }
212
+ export function assertWritableLevel(name, level) {
213
+ if (Number.isInteger(level) && level >= 0)
214
+ return;
215
+ throw new AuthoringError(`${name} must be a non-negative integer, not ${level}`);
216
+ }
217
+ export function outlineAttr(name, level) {
218
+ if (level === undefined)
219
+ return '';
220
+ assertWritableLevel(name, level);
221
+ return nonDefaultNumAttr(name, level, 0);
222
+ }
@@ -1,4 +1,4 @@
1
- import { encodeAddress } from '../../core/address.js';
1
+ import { encodeRect } from '../../core/address.js';
2
2
  import { isFormulaValue, isSharedFormulaValue } from '../../core/value.js';
3
3
  import { AuthoringError } from '../../errors.js';
4
4
  export function planSharedFormulas(sheet) {
@@ -35,7 +35,7 @@ export function planSharedFormulas(sheet) {
35
35
  }
36
36
  roles.set(masterAddress, {
37
37
  si,
38
- ref: `${encodeAddress(master.col, master.row)}:${encodeAddress(maxCol, maxRow)}`,
38
+ ref: encodeRect({ top: master.row, left: master.col, bottom: maxRow, right: maxCol }),
39
39
  });
40
40
  for (const clone of clones)
41
41
  roles.set(clone.address, { si });
@@ -1,7 +1,8 @@
1
- import type { AutoFilter } from '../../core/autofilter.ts';
1
+ import { type AutoFilter } from '../../core/autofilter.ts';
2
2
  import { type HeaderFooter, type PageBreak, type PageMargins, type PageSetup, type PrintOptions } from '../../core/page-setup.ts';
3
3
  import { type SheetProtection } from '../../core/protection.ts';
4
4
  import type { SheetView, Worksheet } from '../../core/worksheet.ts';
5
+ import { type XmlAttributes } from '../../xml/xml-scan.ts';
5
6
  export declare function sheetViewsXml(view: SheetView, active: boolean): string;
6
7
  export declare function sheetPrXml(sheet: Worksheet): string;
7
8
  export declare function sheetProtectionXml(protection: SheetProtection | undefined): string;
@@ -11,3 +12,11 @@ export declare function printOptionsXml(printOptions: PrintOptions): string;
11
12
  export declare function pageMarginsXml(margins: PageMargins): string;
12
13
  export declare function pageSetupXml(pageSetup: PageSetup, printerSettingsRelId: string | null): string;
13
14
  export declare function pageBreaksXml(breaks: readonly PageBreak[], element: 'rowBreaks' | 'colBreaks'): string;
15
+ export declare function parseSheetProtection(attrs: XmlAttributes): SheetProtection | undefined;
16
+ export declare class PageBreakAccumulator {
17
+ #private;
18
+ begin(target: PageBreak[]): void;
19
+ end(): void;
20
+ add(attrs: XmlAttributes): void;
21
+ }
22
+ export declare function applySheetProperties(local: string, attrs: XmlAttributes, sheet: Worksheet): void;
@@ -1,16 +1,22 @@
1
- import { encodeAddress } from '../../core/address.js';
1
+ import { encodeAddress, MAX_COLUMN, MAX_ROW } from '../../core/address.js';
2
+ import { isCustomFilterOperator, } from '../../core/autofilter.js';
2
3
  import { HEADER_FOOTER_ELEMENTS, MARGIN_SIDES, PAGE_SETUP_FACETS, PRINT_OPTION_FLAGS, } from '../../core/page-setup.js';
3
- import { SHEET_PROTECTION_FLAGS } from '../../core/protection.js';
4
+ import { isLegacyPasswordHash, SHEET_PROTECTION_FLAGS, } from '../../core/protection.js';
5
+ import { assertWritableNumber, AuthoringError } from '../../errors.js';
6
+ import { numFinite, numInteger } from '../../xml/xml-attrs.js';
7
+ import { boolStrict, boolTristate } from '../../xml/xml-scan.js';
4
8
  import { boolAttr, checkedToken, escapeAttr, escapeSpreadsheetText, numAttr, numberText, } from '../../xml/xml.js';
5
- import { colorAttrs } from './color-xml.js';
9
+ import { colorAttrs, parseColor } from './color-xml.js';
6
10
  export function sheetViewsXml(view, active) {
7
11
  const selected = active ? ' tabSelected="1"' : '';
8
12
  const gridLines = view.showGridLines === false ? ' showGridLines="0"' : '';
9
- const xSplit = view.xSplit ?? 0;
10
- const ySplit = view.ySplit ?? 0;
11
- if (view.state !== 'frozen' || (xSplit === 0 && ySplit === 0)) {
12
- return `<sheetViews><sheetView${gridLines}${selected} workbookViewId="0"/></sheetViews>`;
13
- }
13
+ const normal = `<sheetViews><sheetView${gridLines}${selected} workbookViewId="0"/></sheetViews>`;
14
+ if (view.state !== 'frozen')
15
+ return normal;
16
+ const xSplit = frozenSplit('xSplit', view.xSplit, MAX_COLUMN);
17
+ const ySplit = frozenSplit('ySplit', view.ySplit, MAX_ROW);
18
+ if (xSplit === 0 && ySplit === 0)
19
+ return normal;
14
20
  const topLeftCell = view.topLeftCell ?? encodeAddress(xSplit + 1, ySplit + 1);
15
21
  const activePane = xSplit > 0 && ySplit > 0 ? 'bottomRight' : xSplit > 0 ? 'topRight' : 'bottomLeft';
16
22
  const pane = '<pane' +
@@ -20,11 +26,23 @@ export function sheetViewsXml(view, active) {
20
26
  const selection = `<selection pane="${activePane}" activeCell="${escapeAttr(topLeftCell)}" sqref="${escapeAttr(topLeftCell)}"/>`;
21
27
  return `<sheetViews><sheetView${gridLines}${selected} workbookViewId="0">${pane}${selection}</sheetView></sheetViews>`;
22
28
  }
29
+ function frozenSplit(name, value, lines) {
30
+ if (value === undefined)
31
+ return 0;
32
+ assertWritableNumber(value);
33
+ if (!Number.isInteger(value) || value < 0 || value >= lines) {
34
+ throw new AuthoringError(`cannot write ${name}="${value}": a frozen split is a whole count from 0 to ${lines - 1}`);
35
+ }
36
+ return value;
37
+ }
23
38
  export function sheetPrXml(sheet) {
39
+ const attrs = sheet.codeName === undefined ? '' : ` codeName="${escapeAttr(sheet.codeName)}"`;
24
40
  const children = (sheet.tabColor !== undefined ? `<tabColor ${colorAttrs(sheet.tabColor)}/>` : '') +
25
41
  outlinePrXml(sheet.outline) +
26
42
  pageSetUpPrXml(sheet.pageSetup);
27
- return children === '' ? '' : `<sheetPr>${children}</sheetPr>`;
43
+ if (attrs === '' && children === '')
44
+ return '';
45
+ return children === '' ? `<sheetPr${attrs}/>` : `<sheetPr${attrs}>${children}</sheetPr>`;
28
46
  }
29
47
  function pageSetUpPrXml(pageSetup) {
30
48
  return pageSetup.fitToPage ? '<pageSetUpPr fitToPage="1"/>' : '';
@@ -36,14 +54,17 @@ function outlinePrXml(outline) {
36
54
  export function sheetProtectionXml(protection) {
37
55
  if (protection === undefined)
38
56
  return '';
39
- const { flags, credential } = protection;
57
+ const { flags, credential, legacyPasswordHash } = protection;
40
58
  let attrs = '';
59
+ if (legacyPasswordHash !== undefined) {
60
+ attrs += ` password="${checkedToken(legacyPasswordHash, isLegacyPasswordHash, 'legacy sheet password hash')}"`;
61
+ }
41
62
  if (credential !== undefined) {
42
63
  attrs +=
43
- ` algorithmName="${credential.algorithmName}"` +
44
- ` hashValue="${credential.hashValue}"` +
45
- ` saltValue="${credential.saltValue}"` +
46
- ` spinCount="${credential.spinCount}"`;
64
+ ` algorithmName="${escapeAttr(credential.algorithmName)}"` +
65
+ ` hashValue="${escapeAttr(credential.hashValue)}"` +
66
+ ` saltValue="${escapeAttr(credential.saltValue)}"` +
67
+ numAttr('spinCount', credential.spinCount);
47
68
  }
48
69
  attrs += ' sheet="1"';
49
70
  for (const { key, defaultForbidden } of SHEET_PROTECTION_FLAGS) {
@@ -66,7 +87,7 @@ export function autoFilterXml(filter) {
66
87
  return `<autoFilter ref="${ref}">${filter.columns.map(filterColumnXml).join('')}</autoFilter>`;
67
88
  }
68
89
  function filterColumnXml(column) {
69
- return `<filterColumn colId="${column.colId}">${filterCriteriaXml(column.criteria)}</filterColumn>`;
90
+ return `<filterColumn colId="${numberText(column.colId)}">${filterCriteriaXml(column.criteria)}</filterColumn>`;
70
91
  }
71
92
  function filterCriteriaXml(criteria) {
72
93
  if (criteria.kind === 'values') {
@@ -76,7 +97,7 @@ function filterCriteriaXml(criteria) {
76
97
  }
77
98
  const andAttr = criteria.and ? ' and="1"' : '';
78
99
  const predicates = criteria.predicates
79
- .map((p) => `<customFilter operator="${p.operator}" val="${escapeAttr(p.val)}"/>`)
100
+ .map((p) => `<customFilter operator="${checkedToken(p.operator, isCustomFilterOperator, 'custom filter operator')}" val="${escapeAttr(p.val)}"/>`)
80
101
  .join('');
81
102
  return `<customFilters${andAttr}>${predicates}</customFilters>`;
82
103
  }
@@ -137,10 +158,151 @@ export function pageSetupXml(pageSetup, printerSettingsRelId) {
137
158
  export function pageBreaksXml(breaks, element) {
138
159
  if (breaks.length === 0)
139
160
  return '';
161
+ const manual = breaks.filter((brk) => brk.man !== false).length;
140
162
  const brks = breaks
141
- .map((brk) => {
142
- return `<brk${numAttr('id', brk.id)}${numAttr('max', brk.max)} man="1"/>`;
143
- })
163
+ .map((brk) => `<brk${numAttr('id', brk.id)}${numAttr('min', brk.min)}${numAttr('max', brk.max)}` +
164
+ `${brk.man === false ? '' : ' man="1"'}/>`)
144
165
  .join('');
145
- return `<${element} count="${breaks.length}" manualBreakCount="${breaks.length}">${brks}</${element}>`;
166
+ return `<${element} count="${breaks.length}" manualBreakCount="${manual}">${brks}</${element}>`;
167
+ }
168
+ export function parseSheetProtection(attrs) {
169
+ if (!boolStrict(attrs.sheet))
170
+ return undefined;
171
+ const flags = {};
172
+ for (const { key } of SHEET_PROTECTION_FLAGS) {
173
+ const raw = attrs[key];
174
+ if (raw !== undefined)
175
+ flags[key] = !boolStrict(raw);
176
+ }
177
+ const { algorithmName, hashValue, saltValue, spinCount } = attrs;
178
+ const spin = numInteger(spinCount, 0);
179
+ if (algorithmName !== undefined &&
180
+ hashValue !== undefined &&
181
+ saltValue !== undefined &&
182
+ spin !== undefined) {
183
+ const credential = {
184
+ algorithmName,
185
+ hashValue,
186
+ saltValue,
187
+ spinCount: spin,
188
+ };
189
+ return { flags, credential, ...legacyHash(attrs.password) };
190
+ }
191
+ return { flags, ...legacyHash(attrs.password) };
192
+ }
193
+ function legacyHash(password) {
194
+ return password !== undefined && isLegacyPasswordHash(password)
195
+ ? { legacyPasswordHash: password }
196
+ : {};
197
+ }
198
+ export class PageBreakAccumulator {
199
+ #target = null;
200
+ begin(target) {
201
+ this.#target = target;
202
+ }
203
+ end() {
204
+ this.#target = null;
205
+ }
206
+ add(attrs) {
207
+ if (this.#target === null)
208
+ return;
209
+ const id = numInteger(attrs.id, 1);
210
+ if (id === undefined)
211
+ return;
212
+ const brk = {
213
+ id,
214
+ man: boolStrict(attrs.man),
215
+ };
216
+ const min = numInteger(attrs.min, 0);
217
+ if (min !== undefined)
218
+ brk.min = min;
219
+ const max = numInteger(attrs.max, 0);
220
+ if (max !== undefined)
221
+ brk.max = max;
222
+ this.#target.push(brk);
223
+ }
224
+ }
225
+ export function applySheetProperties(local, attrs, sheet) {
226
+ switch (local) {
227
+ case 'sheetPr':
228
+ if (attrs.codeName !== undefined)
229
+ sheet.codeName = attrs.codeName;
230
+ break;
231
+ case 'tabColor':
232
+ sheet.tabColor = parseColor(attrs);
233
+ break;
234
+ case 'outlinePr':
235
+ for (const flag of ['summaryBelow', 'summaryRight']) {
236
+ const value = boolTristate(attrs[flag]);
237
+ if (value !== undefined)
238
+ sheet.outline[flag] = value;
239
+ }
240
+ break;
241
+ case 'sheetView':
242
+ if (boolTristate(attrs.showGridLines) === false) {
243
+ sheet.view.showGridLines = false;
244
+ }
245
+ break;
246
+ case 'pane':
247
+ if (attrs.state === 'frozen' || attrs.state === 'frozenSplit') {
248
+ sheet.view.state = 'frozen';
249
+ const xSplit = numInteger(attrs.xSplit, 0);
250
+ const ySplit = numInteger(attrs.ySplit, 0);
251
+ if (xSplit !== undefined && xSplit < MAX_COLUMN)
252
+ sheet.view.xSplit = xSplit;
253
+ if (ySplit !== undefined && ySplit < MAX_ROW)
254
+ sheet.view.ySplit = ySplit;
255
+ if (attrs.topLeftCell !== undefined)
256
+ sheet.view.topLeftCell = attrs.topLeftCell;
257
+ }
258
+ break;
259
+ case 'pageSetUpPr':
260
+ if (boolTristate(attrs.fitToPage) !== undefined) {
261
+ sheet.pageSetup.fitToPage = boolStrict(attrs.fitToPage);
262
+ }
263
+ break;
264
+ case 'printOptions':
265
+ applyPrintOptions(sheet.printOptions, attrs);
266
+ break;
267
+ case 'pageMargins':
268
+ applyMargins(sheet.pageMargins, attrs);
269
+ break;
270
+ case 'pageSetup':
271
+ applyPageSetup(sheet.pageSetup, attrs);
272
+ break;
273
+ }
274
+ }
275
+ function applyPrintOptions(printOptions, attrs) {
276
+ for (const flag of PRINT_OPTION_FLAGS) {
277
+ const value = boolTristate(attrs[flag]);
278
+ if (value !== undefined)
279
+ printOptions[flag] = value;
280
+ }
281
+ }
282
+ function applyMargins(margins, attrs) {
283
+ for (const side of MARGIN_SIDES) {
284
+ const value = numFinite(attrs[side]);
285
+ if (value !== undefined)
286
+ margins[side] = value;
287
+ }
288
+ }
289
+ function applyPageSetup(pageSetup, attrs) {
290
+ for (const facet of PAGE_SETUP_FACETS) {
291
+ const raw = attrs[facet.key];
292
+ if (facet.kind === 'count') {
293
+ const value = numInteger(raw, 0);
294
+ if (value !== undefined)
295
+ pageSetup[facet.key] = value;
296
+ }
297
+ else if (raw === undefined) {
298
+ continue;
299
+ }
300
+ else if (facet.key === 'pageOrder') {
301
+ if (facet.isValid(raw))
302
+ pageSetup.pageOrder = raw;
303
+ }
304
+ else if (facet.isValid(raw)) {
305
+ pageSetup.orientation = raw;
306
+ }
307
+ }
146
308
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A package part's bytes in Transitional: an XML part declaring a Strict namespace has its
3
+ * declarations and its percentages translated, and any other part is handed back as the same bytes.
4
+ * Only the opening tags that change are re-rendered, so everything else in the part rides through byte
5
+ * for byte. A part the scanner cannot read is left as it came, as it would have been carried.
6
+ */
7
+ export declare function transitionalPart(bytes: Uint8Array, contentType: string): Uint8Array;