@shbernal/ts-xlsx 1.0.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 (223) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +230 -0
  3. package/dist/core/address.d.ts +49 -0
  4. package/dist/core/address.js +125 -0
  5. package/dist/core/autofilter.d.ts +55 -0
  6. package/dist/core/autofilter.js +48 -0
  7. package/dist/core/cell.d.ts +132 -0
  8. package/dist/core/cell.js +249 -0
  9. package/dist/core/color-resolution.d.ts +58 -0
  10. package/dist/core/color-resolution.js +170 -0
  11. package/dist/core/column.d.ts +87 -0
  12. package/dist/core/column.js +167 -0
  13. package/dist/core/comment-thread.d.ts +116 -0
  14. package/dist/core/comment-thread.js +62 -0
  15. package/dist/core/conditional-formatting-overlay.d.ts +15 -0
  16. package/dist/core/conditional-formatting-overlay.js +24 -0
  17. package/dist/core/conditional-formatting.d.ts +70 -0
  18. package/dist/core/conditional-formatting.js +35 -0
  19. package/dist/core/containers.d.ts +2 -0
  20. package/dist/core/containers.js +25 -0
  21. package/dist/core/data-validation-overlay.d.ts +28 -0
  22. package/dist/core/data-validation-overlay.js +56 -0
  23. package/dist/core/data-validation.d.ts +38 -0
  24. package/dist/core/data-validation.js +13 -0
  25. package/dist/core/date.d.ts +25 -0
  26. package/dist/core/date.js +58 -0
  27. package/dist/core/formula.d.ts +49 -0
  28. package/dist/core/formula.js +319 -0
  29. package/dist/core/grid-edits.d.ts +22 -0
  30. package/dist/core/grid-edits.js +206 -0
  31. package/dist/core/image.d.ts +76 -0
  32. package/dist/core/image.js +65 -0
  33. package/dist/core/internal.d.ts +11 -0
  34. package/dist/core/internal.js +29 -0
  35. package/dist/core/merge.d.ts +13 -0
  36. package/dist/core/merge.js +26 -0
  37. package/dist/core/modern-functions.d.ts +1 -0
  38. package/dist/core/modern-functions.js +165 -0
  39. package/dist/core/page-setup.d.ts +94 -0
  40. package/dist/core/page-setup.js +6 -0
  41. package/dist/core/pivot-table.d.ts +113 -0
  42. package/dist/core/pivot-table.js +249 -0
  43. package/dist/core/preserved.d.ts +58 -0
  44. package/dist/core/preserved.js +5 -0
  45. package/dist/core/protection.d.ts +67 -0
  46. package/dist/core/protection.js +68 -0
  47. package/dist/core/range.d.ts +112 -0
  48. package/dist/core/range.js +283 -0
  49. package/dist/core/row.d.ts +73 -0
  50. package/dist/core/row.js +135 -0
  51. package/dist/core/style.d.ts +246 -0
  52. package/dist/core/style.js +125 -0
  53. package/dist/core/table-style.d.ts +67 -0
  54. package/dist/core/table-style.js +90 -0
  55. package/dist/core/table.d.ts +194 -0
  56. package/dist/core/table.js +291 -0
  57. package/dist/core/theme.d.ts +90 -0
  58. package/dist/core/theme.js +272 -0
  59. package/dist/core/value.d.ts +115 -0
  60. package/dist/core/value.js +144 -0
  61. package/dist/core/workbook-protection.d.ts +27 -0
  62. package/dist/core/workbook-protection.js +25 -0
  63. package/dist/core/workbook.d.ts +528 -0
  64. package/dist/core/workbook.js +732 -0
  65. package/dist/core/worksheet-model.d.ts +34 -0
  66. package/dist/core/worksheet-model.js +100 -0
  67. package/dist/core/worksheet.d.ts +647 -0
  68. package/dist/core/worksheet.js +1025 -0
  69. package/dist/customui/errors.d.ts +15 -0
  70. package/dist/customui/errors.js +15 -0
  71. package/dist/customui/index.d.ts +2 -0
  72. package/dist/customui/index.js +7 -0
  73. package/dist/customui/ribbon.d.ts +86 -0
  74. package/dist/customui/ribbon.js +180 -0
  75. package/dist/entries/core.d.ts +23 -0
  76. package/dist/entries/core.js +20 -0
  77. package/dist/entries/csv.d.ts +2 -0
  78. package/dist/entries/csv.js +6 -0
  79. package/dist/entries/customui.d.ts +1 -0
  80. package/dist/entries/customui.js +3 -0
  81. package/dist/entries/errors.d.ts +7 -0
  82. package/dist/entries/errors.js +20 -0
  83. package/dist/entries/vba.d.ts +2 -0
  84. package/dist/entries/vba.js +7 -0
  85. package/dist/entries/xlsb.d.ts +1 -0
  86. package/dist/entries/xlsb.js +7 -0
  87. package/dist/entries/xlsx.d.ts +5 -0
  88. package/dist/entries/xlsx.js +18 -0
  89. package/dist/errors.d.ts +65 -0
  90. package/dist/errors.js +66 -0
  91. package/dist/index.d.ts +7 -0
  92. package/dist/index.js +19 -0
  93. package/dist/io/csv/read.d.ts +15 -0
  94. package/dist/io/csv/read.js +113 -0
  95. package/dist/io/csv/write.d.ts +28 -0
  96. package/dist/io/csv/write.js +124 -0
  97. package/dist/io/opc/errors.d.ts +46 -0
  98. package/dist/io/opc/errors.js +49 -0
  99. package/dist/io/opc/inflate.d.ts +15 -0
  100. package/dist/io/opc/inflate.js +91 -0
  101. package/dist/io/opc/namespaces.d.ts +18 -0
  102. package/dist/io/opc/namespaces.js +18 -0
  103. package/dist/io/opc/part-paths.d.ts +4 -0
  104. package/dist/io/opc/part-paths.js +35 -0
  105. package/dist/io/opc/read-opc.d.ts +24 -0
  106. package/dist/io/opc/read-opc.js +153 -0
  107. package/dist/io/opc/read-options.d.ts +10 -0
  108. package/dist/io/opc/read-options.js +7 -0
  109. package/dist/io/opc/rels.d.ts +15 -0
  110. package/dist/io/opc/rels.js +28 -0
  111. package/dist/io/opc/sniff-format.d.ts +27 -0
  112. package/dist/io/opc/sniff-format.js +92 -0
  113. package/dist/io/style/xf-style.d.ts +47 -0
  114. package/dist/io/style/xf-style.js +95 -0
  115. package/dist/io/xlsb/errors.d.ts +15 -0
  116. package/dist/io/xlsb/errors.js +15 -0
  117. package/dist/io/xlsb/formula.d.ts +48 -0
  118. package/dist/io/xlsb/formula.js +398 -0
  119. package/dist/io/xlsb/primitives.d.ts +86 -0
  120. package/dist/io/xlsb/primitives.js +230 -0
  121. package/dist/io/xlsb/ptg-functions.d.ts +16 -0
  122. package/dist/io/xlsb/ptg-functions.js +659 -0
  123. package/dist/io/xlsb/read-shared-strings.d.ts +2 -0
  124. package/dist/io/xlsb/read-shared-strings.js +22 -0
  125. package/dist/io/xlsb/read-styles.d.ts +4 -0
  126. package/dist/io/xlsb/read-styles.js +386 -0
  127. package/dist/io/xlsb/read-worksheet.d.ts +9 -0
  128. package/dist/io/xlsb/read-worksheet.js +301 -0
  129. package/dist/io/xlsb/read.d.ts +20 -0
  130. package/dist/io/xlsb/read.js +199 -0
  131. package/dist/io/xlsb/record-stream.d.ts +14 -0
  132. package/dist/io/xlsb/record-stream.js +56 -0
  133. package/dist/io/xlsb/record-types.d.ts +55 -0
  134. package/dist/io/xlsb/record-types.js +73 -0
  135. package/dist/io/xlsx/cell-accumulator.d.ts +25 -0
  136. package/dist/io/xlsx/cell-accumulator.js +172 -0
  137. package/dist/io/xlsx/cell-value.d.ts +32 -0
  138. package/dist/io/xlsx/cell-value.js +85 -0
  139. package/dist/io/xlsx/comments.d.ts +74 -0
  140. package/dist/io/xlsx/comments.js +243 -0
  141. package/dist/io/xlsx/conditional-formatting.d.ts +32 -0
  142. package/dist/io/xlsx/conditional-formatting.js +464 -0
  143. package/dist/io/xlsx/data-validation.d.ts +20 -0
  144. package/dist/io/xlsx/data-validation.js +258 -0
  145. package/dist/io/xlsx/edit-vba.d.ts +23 -0
  146. package/dist/io/xlsx/edit-vba.js +139 -0
  147. package/dist/io/xlsx/errors.d.ts +17 -0
  148. package/dist/io/xlsx/errors.js +17 -0
  149. package/dist/io/xlsx/hyperlinks.d.ts +42 -0
  150. package/dist/io/xlsx/hyperlinks.js +139 -0
  151. package/dist/io/xlsx/images.d.ts +34 -0
  152. package/dist/io/xlsx/images.js +218 -0
  153. package/dist/io/xlsx/namespaces.d.ts +55 -0
  154. package/dist/io/xlsx/namespaces.js +55 -0
  155. package/dist/io/xlsx/package-plan.d.ts +103 -0
  156. package/dist/io/xlsx/package-plan.js +168 -0
  157. package/dist/io/xlsx/pivot-read.d.ts +5 -0
  158. package/dist/io/xlsx/pivot-read.js +134 -0
  159. package/dist/io/xlsx/pivot.d.ts +12 -0
  160. package/dist/io/xlsx/pivot.js +141 -0
  161. package/dist/io/xlsx/read-rows.d.ts +85 -0
  162. package/dist/io/xlsx/read-rows.js +286 -0
  163. package/dist/io/xlsx/read-styles.d.ts +8 -0
  164. package/dist/io/xlsx/read-styles.js +551 -0
  165. package/dist/io/xlsx/read-worksheet.d.ts +4 -0
  166. package/dist/io/xlsx/read-worksheet.js +528 -0
  167. package/dist/io/xlsx/read.d.ts +32 -0
  168. package/dist/io/xlsx/read.js +680 -0
  169. package/dist/io/xlsx/relationships.d.ts +33 -0
  170. package/dist/io/xlsx/relationships.js +47 -0
  171. package/dist/io/xlsx/rich-runs.d.ts +13 -0
  172. package/dist/io/xlsx/rich-runs.js +59 -0
  173. package/dist/io/xlsx/rich-text.d.ts +7 -0
  174. package/dist/io/xlsx/rich-text.js +23 -0
  175. package/dist/io/xlsx/shared-formulas.d.ts +6 -0
  176. package/dist/io/xlsx/shared-formulas.js +52 -0
  177. package/dist/io/xlsx/shared-strings-read.d.ts +2 -0
  178. package/dist/io/xlsx/shared-strings-read.js +70 -0
  179. package/dist/io/xlsx/shared-strings.d.ts +17 -0
  180. package/dist/io/xlsx/shared-strings.js +50 -0
  181. package/dist/io/xlsx/sheet-properties.d.ts +13 -0
  182. package/dist/io/xlsx/sheet-properties.js +211 -0
  183. package/dist/io/xlsx/styles.d.ts +138 -0
  184. package/dist/io/xlsx/styles.js +821 -0
  185. package/dist/io/xlsx/tables.d.ts +9 -0
  186. package/dist/io/xlsx/tables.js +208 -0
  187. package/dist/io/xlsx/threaded-comments.d.ts +102 -0
  188. package/dist/io/xlsx/threaded-comments.js +308 -0
  189. package/dist/io/xlsx/workbook-xml.d.ts +12 -0
  190. package/dist/io/xlsx/workbook-xml.js +353 -0
  191. package/dist/io/xlsx/worksheet-xml.d.ts +86 -0
  192. package/dist/io/xlsx/worksheet-xml.js +643 -0
  193. package/dist/io/xlsx/write-stream.d.ts +171 -0
  194. package/dist/io/xlsx/write-stream.js +399 -0
  195. package/dist/io/xlsx/write.d.ts +81 -0
  196. package/dist/io/xlsx/write.js +396 -0
  197. package/dist/io/xlsx/x14-ext.d.ts +9 -0
  198. package/dist/io/xlsx/x14-ext.js +12 -0
  199. package/dist/vba/cfb-writer.d.ts +19 -0
  200. package/dist/vba/cfb-writer.js +277 -0
  201. package/dist/vba/cfb.d.ts +16 -0
  202. package/dist/vba/cfb.js +324 -0
  203. package/dist/vba/codepage.d.ts +18 -0
  204. package/dist/vba/codepage.js +87 -0
  205. package/dist/vba/errors.d.ts +24 -0
  206. package/dist/vba/errors.js +24 -0
  207. package/dist/vba/index.d.ts +5 -0
  208. package/dist/vba/index.js +15 -0
  209. package/dist/vba/ms-ovba.d.ts +12 -0
  210. package/dist/vba/ms-ovba.js +176 -0
  211. package/dist/vba/project-editor.d.ts +62 -0
  212. package/dist/vba/project-editor.js +377 -0
  213. package/dist/vba/project.d.ts +45 -0
  214. package/dist/vba/project.js +160 -0
  215. package/dist/vba/vba-encoding.d.ts +14 -0
  216. package/dist/vba/vba-encoding.js +39 -0
  217. package/dist/xml/errors.d.ts +15 -0
  218. package/dist/xml/errors.js +15 -0
  219. package/dist/xml/xml-read.d.ts +107 -0
  220. package/dist/xml/xml-read.js +283 -0
  221. package/dist/xml/xml.d.ts +41 -0
  222. package/dist/xml/xml.js +86 -0
  223. package/package.json +117 -0
@@ -0,0 +1,34 @@
1
+ import { type AnchorPoint, type Extent, type ImageAnchor, type ImageEditAs } from '../../core/image.ts';
2
+ /** The content type for a media part's `<Default Extension>` entry in `[Content_Types].xml`. */
3
+ export declare function imageContentType(extension: string): string;
4
+ /** One image placed in a drawing: where it sits and the drawing-local relationship id that ties it
5
+ * to its media bytes. */
6
+ export interface DrawingImage {
7
+ readonly anchor: ImageAnchor;
8
+ /** The `r:embed` id referencing this image's entry in the drawing's own `.rels`. */
9
+ readonly embedId: string;
10
+ }
11
+ /** The `xl/drawings/drawing{n}.xml` part: one anchor per image, two-cell or one-cell by its shape. */
12
+ export declare function drawingXml(images: readonly DrawingImage[]): string;
13
+ /** The drawing's `_rels/drawing{n}.xml.rels`: one image relationship per anchor, in `embedId` order
14
+ * (`rId1`, `rId2`, …), each pointing at the media part the anchor shows. */
15
+ export declare function drawingRelsXml(mediaTargets: readonly string[]): string;
16
+ /** An image anchor parsed from a drawing part, with the `r:embed` id that names its media. A two-cell
17
+ * anchor carries `to` (and may carry `editAs`); a one-cell anchor carries `ext` instead. */
18
+ export interface ParsedImageAnchor {
19
+ readonly from: AnchorPoint;
20
+ readonly to?: AnchorPoint;
21
+ readonly ext?: Extent;
22
+ readonly editAs?: ImageEditAs;
23
+ readonly rotation?: number;
24
+ readonly embed: string;
25
+ }
26
+ /** Parse a drawing part into its image anchors (both `<xdr:twoCellAnchor>` and `<xdr:oneCellAnchor>`).
27
+ * Anchors that are not pictures (a chart, a shape) carry no `<a:blip r:embed>` and are skipped, so a
28
+ * mixed drawing yields only its images. */
29
+ export declare function parseDrawing(xml: string): ParsedImageAnchor[];
30
+ /** Whether a drawing part holds anchor content beyond plain pictures — a chart, shape, connector, or
31
+ * group. Excel packs every one of a sheet's anchors into a single drawing part, so a sheet with both a
32
+ * picture and a chart yields a mixed drawing; modeling only its pictures and re-serialising from them
33
+ * would drop the chart. The reader uses this to fall back to whole-drawing byte-preservation instead. */
34
+ export declare function drawingHasUnmodeledContent(xml: string): boolean;
@@ -0,0 +1,218 @@
1
+ // Anchored images on the wire: the `xl/drawings/drawing{n}.xml` part (a DrawingML two-cell anchor
2
+ // per image), the drawing's own relationships to the `xl/media/` bytes, and the reader that turns a
3
+ // drawing back into anchors. The image bytes themselves are opaque here — the writer copies them
4
+ // verbatim into a media part and the reader hands them back untouched.
5
+ import { isOneCellAnchor, } from "../../core/image.js";
6
+ import { XML_DECLARATION } from "../../xml/xml.js";
7
+ import { localName, parseXml } from "../../xml/xml-read.js";
8
+ import { RELATIONSHIPS_NS } from "../opc/namespaces.js";
9
+ import { relationship, relationshipsPart } from "../opc/rels.js";
10
+ import { DRAWINGML_NS, XDR_NS } from "./namespaces.js";
11
+ const IMAGE_REL_TYPE = `${RELATIONSHIPS_NS}/image`;
12
+ // The content type Excel expects for each image kind, keyed by lower-case extension. An unlisted
13
+ // extension falls back to `image/<ext>`, which is what a well-behaved consumer infers anyway.
14
+ const IMAGE_CONTENT_TYPES = {
15
+ png: 'image/png',
16
+ jpg: 'image/jpeg',
17
+ jpeg: 'image/jpeg',
18
+ gif: 'image/gif',
19
+ bmp: 'image/bmp',
20
+ tif: 'image/tiff',
21
+ tiff: 'image/tiff',
22
+ emf: 'image/x-emf',
23
+ wmf: 'image/x-wmf',
24
+ svg: 'image/svg+xml',
25
+ };
26
+ /** The content type for a media part's `<Default Extension>` entry in `[Content_Types].xml`. */
27
+ export function imageContentType(extension) {
28
+ const ext = extension.toLowerCase();
29
+ return IMAGE_CONTENT_TYPES[ext] ?? `image/${ext}`;
30
+ }
31
+ /** The `xl/drawings/drawing{n}.xml` part: one anchor per image, two-cell or one-cell by its shape. */
32
+ export function drawingXml(images) {
33
+ const anchors = images.map((image, i) => anchorXml(image, i + 1)).join('');
34
+ return (XML_DECLARATION +
35
+ `<xdr:wsDr xmlns:xdr="${XDR_NS}" xmlns:a="${DRAWINGML_NS}" xmlns:r="${RELATIONSHIPS_NS}">` +
36
+ anchors +
37
+ '</xdr:wsDr>');
38
+ }
39
+ function anchorXml(image, id) {
40
+ const { anchor } = image;
41
+ return isOneCellAnchor(anchor)
42
+ ? oneCellAnchorXml(anchor.from, anchor.ext, anchor.rotation, image.embedId, id)
43
+ : twoCellAnchorXml(anchor.from, anchor.to, anchor.editAs ?? 'oneCell', anchor.rotation, image.embedId, id);
44
+ }
45
+ // A picture anchored between two grid points. The geometry lives entirely in <xdr:from>/<xdr:to>, so
46
+ // the picture carries no absolute <a:xfrm> — a zeroed one would override the anchor and collapse the
47
+ // image to nothing in strict viewers (LibreOffice), while a non-zero one would fight the anchor. A
48
+ // rotation is the one transform kept: it can't be derived from the anchor, so it rides a rot-only xfrm.
49
+ function twoCellAnchorXml(from, to, editAs, rotation, embedId, id) {
50
+ return (`<xdr:twoCellAnchor editAs="${editAs}">` +
51
+ `<xdr:from>${anchorPointXml(from)}</xdr:from>` +
52
+ `<xdr:to>${anchorPointXml(to)}</xdr:to>` +
53
+ picXml(embedId, id, rotation) +
54
+ '<xdr:clientData/>' +
55
+ '</xdr:twoCellAnchor>');
56
+ }
57
+ // A picture pinned at one grid point with a fixed EMU extent. editAs is a two-cell-only attribute and
58
+ // the schema forbids it here, so a one-cell anchor never carries one.
59
+ function oneCellAnchorXml(from, ext, rotation, embedId, id) {
60
+ return ('<xdr:oneCellAnchor>' +
61
+ `<xdr:from>${anchorPointXml(from)}</xdr:from>` +
62
+ `<xdr:ext cx="${ext.cx}" cy="${ext.cy}"/>` +
63
+ picXml(embedId, id, rotation) +
64
+ '<xdr:clientData/>' +
65
+ '</xdr:oneCellAnchor>');
66
+ }
67
+ function picXml(embedId, id, rotation) {
68
+ const xfrm = rotation !== undefined ? `<a:xfrm rot="${rotation}"/>` : '';
69
+ return ('<xdr:pic>' +
70
+ `<xdr:nvPicPr><xdr:cNvPr id="${id}" name="Picture ${id}"/>` +
71
+ '<xdr:cNvPicPr><a:picLocks noChangeAspect="1"/></xdr:cNvPicPr></xdr:nvPicPr>' +
72
+ `<xdr:blipFill><a:blip r:embed="${embedId}"/>` +
73
+ '<a:stretch><a:fillRect/></a:stretch></xdr:blipFill>' +
74
+ `<xdr:spPr>${xfrm}<a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr>` +
75
+ '</xdr:pic>');
76
+ }
77
+ function anchorPointXml(point) {
78
+ return (`<xdr:col>${point.col}</xdr:col><xdr:colOff>${point.colOff ?? 0}</xdr:colOff>` +
79
+ `<xdr:row>${point.row}</xdr:row><xdr:rowOff>${point.rowOff ?? 0}</xdr:rowOff>`);
80
+ }
81
+ /** The drawing's `_rels/drawing{n}.xml.rels`: one image relationship per anchor, in `embedId` order
82
+ * (`rId1`, `rId2`, …), each pointing at the media part the anchor shows. */
83
+ export function drawingRelsXml(mediaTargets) {
84
+ return relationshipsPart(mediaTargets.map((target, i) => relationship(`rId${i + 1}`, IMAGE_REL_TYPE, target)));
85
+ }
86
+ function blankPoint() {
87
+ return { col: 0, row: 0, colOff: 0, rowOff: 0 };
88
+ }
89
+ const EDIT_AS = new Set(['oneCell', 'twoCell', 'absolute']);
90
+ /** Parse a drawing part into its image anchors (both `<xdr:twoCellAnchor>` and `<xdr:oneCellAnchor>`).
91
+ * Anchors that are not pictures (a chart, a shape) carry no `<a:blip r:embed>` and are skipped, so a
92
+ * mixed drawing yields only its images. */
93
+ export function parseDrawing(xml) {
94
+ const anchors = [];
95
+ let from = null;
96
+ let to = null;
97
+ let ext;
98
+ let editAs;
99
+ let rotation;
100
+ let embed;
101
+ // The point (<xdr:from> or <xdr:to>) whose coordinate children are currently streaming in.
102
+ let target = null;
103
+ // Depth inside <xdr:pic>, so the anchor-level <xdr:ext> is not confused with the <a:ext> nested in
104
+ // a picture's spPr transform (both have local name "ext").
105
+ let picDepth = 0;
106
+ // Which coordinate child is open, so its text lands on the right field; '' between children.
107
+ let coord = '';
108
+ let text = '';
109
+ parseXml(xml, {
110
+ onOpen(name, attrs) {
111
+ const local = localName(name);
112
+ if (local === 'twoCellAnchor' || local === 'oneCellAnchor') {
113
+ from = blankPoint();
114
+ to = local === 'twoCellAnchor' ? blankPoint() : null;
115
+ ext = undefined;
116
+ rotation = undefined;
117
+ embed = undefined;
118
+ const mode = attrs.editAs;
119
+ editAs = mode !== undefined && EDIT_AS.has(mode) ? mode : undefined;
120
+ }
121
+ else if (local === 'pic') {
122
+ picDepth++;
123
+ }
124
+ else if (local === 'xfrm' && picDepth > 0) {
125
+ // The picture's own rotation — the one spPr transform that can't be derived from the anchor.
126
+ const rot = Number(attrs.rot);
127
+ if (Number.isFinite(rot) && rot !== 0)
128
+ rotation = rot;
129
+ }
130
+ else if (local === 'from') {
131
+ target = from;
132
+ }
133
+ else if (local === 'to') {
134
+ target = to;
135
+ }
136
+ else if (local === 'ext' && picDepth === 0) {
137
+ const cx = Number(attrs.cx);
138
+ const cy = Number(attrs.cy);
139
+ if (Number.isFinite(cx) && Number.isFinite(cy))
140
+ ext = { cx, cy };
141
+ }
142
+ else if (local === 'blip') {
143
+ const value = attrs['r:embed'] ?? attrs.embed;
144
+ if (value !== undefined)
145
+ embed = value;
146
+ }
147
+ else if (target !== null && COORDINATES.has(local)) {
148
+ coord = local;
149
+ text = '';
150
+ }
151
+ },
152
+ onText(chunk) {
153
+ if (coord !== '')
154
+ text += chunk;
155
+ },
156
+ onClose(name) {
157
+ const local = localName(name);
158
+ if (target !== null && coord === local && COORDINATES.has(local)) {
159
+ const value = Number(text);
160
+ if (Number.isFinite(value))
161
+ setCoordinate(target, local, value);
162
+ coord = '';
163
+ }
164
+ else if (local === 'from' || local === 'to') {
165
+ target = null;
166
+ }
167
+ else if (local === 'pic') {
168
+ picDepth--;
169
+ }
170
+ else if (local === 'twoCellAnchor' || local === 'oneCellAnchor') {
171
+ if (from !== null && embed !== undefined) {
172
+ const rot = rotation !== undefined ? { rotation } : {};
173
+ if (to !== null) {
174
+ const mode = editAs !== undefined ? { editAs } : {};
175
+ anchors.push({ from: { ...from }, to: { ...to }, ...mode, ...rot, embed });
176
+ }
177
+ else if (ext !== undefined) {
178
+ anchors.push({ from: { ...from }, ext, ...rot, embed });
179
+ }
180
+ }
181
+ from = null;
182
+ to = null;
183
+ ext = undefined;
184
+ }
185
+ },
186
+ });
187
+ return anchors;
188
+ }
189
+ // Anchor content a drawing can hold that the image model does not interpret: a chart
190
+ // (`<xdr:graphicFrame>`), a shape or text box (`<xdr:sp>`), a connector (`<xdr:cxnSp>`), or a group
191
+ // (`<xdr:grpSp>`). A drawing carrying any of these is preserved whole rather than modeled, so it is
192
+ // not re-serialised from its pictures alone (which would silently drop the chart/shape).
193
+ const UNMODELED_DRAWING_CONTENT = new Set(['graphicFrame', 'sp', 'cxnSp', 'grpSp']);
194
+ /** Whether a drawing part holds anchor content beyond plain pictures — a chart, shape, connector, or
195
+ * group. Excel packs every one of a sheet's anchors into a single drawing part, so a sheet with both a
196
+ * picture and a chart yields a mixed drawing; modeling only its pictures and re-serialising from them
197
+ * would drop the chart. The reader uses this to fall back to whole-drawing byte-preservation instead. */
198
+ export function drawingHasUnmodeledContent(xml) {
199
+ let found = false;
200
+ parseXml(xml, {
201
+ onOpen(name) {
202
+ if (!found && UNMODELED_DRAWING_CONTENT.has(localName(name)))
203
+ found = true;
204
+ },
205
+ });
206
+ return found;
207
+ }
208
+ const COORDINATES = new Set(['col', 'colOff', 'row', 'rowOff']);
209
+ function setCoordinate(point, coord, value) {
210
+ if (coord === 'col')
211
+ point.col = value;
212
+ else if (coord === 'colOff')
213
+ point.colOff = value;
214
+ else if (coord === 'row')
215
+ point.row = value;
216
+ else
217
+ point.rowOff = value;
218
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Canonical SpreadsheetML namespace URIs and well-known extension GUIDs.
3
+ *
4
+ * These are wire-format constants: Excel keys its parsing off the exact URI or
5
+ * GUID, so a producer must reproduce each one byte-for-byte. Centralizing them
6
+ * keeps the writer and reader from drifting apart and retires the
7
+ * `NS_MAIN`/`MAIN_NS`/`main` naming fork that had grown across the io modules.
8
+ *
9
+ * The package-level URIs (`.rels`, content types, the relationship vocabulary) describe the
10
+ * container rather than the spreadsheet inside it, and live in `../opc/namespaces.ts`.
11
+ */
12
+ /**
13
+ * SpreadsheetML main namespace — the default `xmlns` of the workbook,
14
+ * worksheet, styles, sharedStrings, comments, table and pivot parts.
15
+ */
16
+ export declare const SPREADSHEETML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
17
+ /**
18
+ * Markup-compatibility namespace (`mc:`), whose `mc:Ignorable` attribute lists the prefixes a
19
+ * consumer that does not know them may skip rather than reject the part over.
20
+ */
21
+ export declare const MARKUP_COMPATIBILITY_NS = "http://schemas.openxmlformats.org/markup-compatibility/2006";
22
+ /**
23
+ * The 2014 revision namespace (`xr:`), which scopes the `xr:uid` Excel stamps on a comment. Declared
24
+ * `mc:Ignorable` wherever it appears, so a consumer that ignores it still reads the part.
25
+ */
26
+ export declare const REVISION_NS = "http://schemas.microsoft.com/office/spreadsheetml/2014/revision";
27
+ /**
28
+ * The 2018 threaded-comments namespace, shared by both parts of the feature — a sheet's
29
+ * `threadedComment{n}.xml` and the workbook's `person.xml`. Note the plural `threadedcomments`, all
30
+ * lower-case: Excel matches the URI exactly and reads neither part under any other spelling.
31
+ */
32
+ export declare const THREADED_COMMENTS_NS = "http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments";
33
+ /** DrawingML shared graphics namespace (`a:`). */
34
+ export declare const DRAWINGML_NS = "http://schemas.openxmlformats.org/drawingml/2006/main";
35
+ /** Spreadsheet-drawing anchor namespace (`xdr:`) used by the worksheet drawing part. */
36
+ export declare const XDR_NS = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing";
37
+ /**
38
+ * The 2009 Microsoft extension namespace. `x14` scopes the feature elements
39
+ * Excel tucks inside `<ext>` blocks (conditional formatting, data validation,
40
+ * slicers); it is declared inline on those elements exactly as Excel writes
41
+ * them, so a worksheet root never needs an extra namespace declaration.
42
+ */
43
+ export declare const X14_NS = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main";
44
+ /** Scopes the `<xm:sqref>`/`<xm:f>` references the x14 feature elements carry. */
45
+ export declare const XM_NS = "http://schemas.microsoft.com/office/excel/2006/main";
46
+ /**
47
+ * Well-known `<ext uri=…>` GUIDs. Each `<ext>` block is opaque to a consumer
48
+ * that does not recognize its GUID, so a producer must emit these exact values
49
+ * for Excel to rediscover the feature.
50
+ */
51
+ export declare const CF_EXT_URI = "{78C0D931-6437-407d-A8EE-F0AAD7539E65}";
52
+ export declare const DATABAR_LINK_EXT_URI = "{B025F937-C7B1-47D3-B67F-A62EFF666E3E}";
53
+ export declare const DATA_VALIDATION_EXT_URI = "{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}";
54
+ export declare const SLICER_LIST_EXT_URI = "{A8765BA9-456A-4dab-B4F3-ACF838C121DE}";
55
+ export declare const SLICER_CACHES_EXT_URI = "{BBE1A952-AA13-448e-AADC-164F8A28A991}";
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Canonical SpreadsheetML namespace URIs and well-known extension GUIDs.
3
+ *
4
+ * These are wire-format constants: Excel keys its parsing off the exact URI or
5
+ * GUID, so a producer must reproduce each one byte-for-byte. Centralizing them
6
+ * keeps the writer and reader from drifting apart and retires the
7
+ * `NS_MAIN`/`MAIN_NS`/`main` naming fork that had grown across the io modules.
8
+ *
9
+ * The package-level URIs (`.rels`, content types, the relationship vocabulary) describe the
10
+ * container rather than the spreadsheet inside it, and live in `../opc/namespaces.ts`.
11
+ */
12
+ /**
13
+ * SpreadsheetML main namespace — the default `xmlns` of the workbook,
14
+ * worksheet, styles, sharedStrings, comments, table and pivot parts.
15
+ */
16
+ export const SPREADSHEETML_NS = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';
17
+ /**
18
+ * Markup-compatibility namespace (`mc:`), whose `mc:Ignorable` attribute lists the prefixes a
19
+ * consumer that does not know them may skip rather than reject the part over.
20
+ */
21
+ export const MARKUP_COMPATIBILITY_NS = 'http://schemas.openxmlformats.org/markup-compatibility/2006';
22
+ /**
23
+ * The 2014 revision namespace (`xr:`), which scopes the `xr:uid` Excel stamps on a comment. Declared
24
+ * `mc:Ignorable` wherever it appears, so a consumer that ignores it still reads the part.
25
+ */
26
+ export const REVISION_NS = 'http://schemas.microsoft.com/office/spreadsheetml/2014/revision';
27
+ /**
28
+ * The 2018 threaded-comments namespace, shared by both parts of the feature — a sheet's
29
+ * `threadedComment{n}.xml` and the workbook's `person.xml`. Note the plural `threadedcomments`, all
30
+ * lower-case: Excel matches the URI exactly and reads neither part under any other spelling.
31
+ */
32
+ export const THREADED_COMMENTS_NS = 'http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments';
33
+ /** DrawingML shared graphics namespace (`a:`). */
34
+ export const DRAWINGML_NS = 'http://schemas.openxmlformats.org/drawingml/2006/main';
35
+ /** Spreadsheet-drawing anchor namespace (`xdr:`) used by the worksheet drawing part. */
36
+ export const XDR_NS = 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing';
37
+ /**
38
+ * The 2009 Microsoft extension namespace. `x14` scopes the feature elements
39
+ * Excel tucks inside `<ext>` blocks (conditional formatting, data validation,
40
+ * slicers); it is declared inline on those elements exactly as Excel writes
41
+ * them, so a worksheet root never needs an extra namespace declaration.
42
+ */
43
+ export const X14_NS = 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main';
44
+ /** Scopes the `<xm:sqref>`/`<xm:f>` references the x14 feature elements carry. */
45
+ export const XM_NS = 'http://schemas.microsoft.com/office/excel/2006/main';
46
+ /**
47
+ * Well-known `<ext uri=…>` GUIDs. Each `<ext>` block is opaque to a consumer
48
+ * that does not recognize its GUID, so a producer must emit these exact values
49
+ * for Excel to rediscover the feature.
50
+ */
51
+ export const CF_EXT_URI = '{78C0D931-6437-407d-A8EE-F0AAD7539E65}';
52
+ export const DATABAR_LINK_EXT_URI = '{B025F937-C7B1-47D3-B67F-A62EFF666E3E}';
53
+ export const DATA_VALIDATION_EXT_URI = '{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}';
54
+ export const SLICER_LIST_EXT_URI = '{A8765BA9-456A-4dab-B4F3-ACF838C121DE}';
55
+ export const SLICER_CACHES_EXT_URI = '{BBE1A952-AA13-448e-AADC-164F8A28A991}';
@@ -0,0 +1,103 @@
1
+ import type { CommentThread } from '../../core/comment-thread.ts';
2
+ import type { PivotTable } from '../../core/pivot-table.ts';
3
+ import type { Table } from '../../core/table.ts';
4
+ import type { Workbook } from '../../core/workbook.ts';
5
+ import type { Worksheet } from '../../core/worksheet.ts';
6
+ import type { CommentCell } from './comments.ts';
7
+ import type { DrawingImage } from './images.ts';
8
+ export declare class SheetRelIds {
9
+ #private;
10
+ /** The next relationship id (`rId1`, `rId2`, …), advancing the counter. */
11
+ next(): string;
12
+ }
13
+ export interface PivotPlan {
14
+ readonly number: number;
15
+ readonly cacheId: string;
16
+ readonly table: PivotTable;
17
+ readonly sheetRelId: string;
18
+ workbookRelId: string;
19
+ }
20
+ export interface CommentPlan {
21
+ readonly number: number;
22
+ readonly comments: readonly CommentCell[];
23
+ readonly vmlRelId: string;
24
+ readonly commentsRelId: string;
25
+ }
26
+ export interface ThreadedCommentPlan {
27
+ readonly number: number;
28
+ readonly threads: readonly CommentThread[];
29
+ readonly relId: string;
30
+ }
31
+ export interface PrinterSettingsPlan {
32
+ readonly number: number;
33
+ readonly data: Uint8Array;
34
+ readonly relId: string;
35
+ }
36
+ export interface TablePlan {
37
+ readonly table: Table;
38
+ readonly number: number;
39
+ readonly relId: string;
40
+ }
41
+ export interface BackgroundPlan {
42
+ readonly relId: string;
43
+ readonly mediaNumber: number;
44
+ readonly extension: string;
45
+ }
46
+ export interface PreservedPartPlan {
47
+ readonly path: string;
48
+ readonly bytes: Uint8Array;
49
+ readonly contentType: string;
50
+ readonly relsPath: string | null;
51
+ readonly relsXml: string | null;
52
+ }
53
+ export interface ResolvedPreservedReference {
54
+ readonly element: 'drawing' | 'legacyDrawingHF' | undefined;
55
+ readonly relType: string;
56
+ readonly entryPath: string;
57
+ }
58
+ export interface PreservedReferencePlan extends ResolvedPreservedReference {
59
+ readonly relId: string;
60
+ }
61
+ export interface PreservedWorkbookReferencePlan {
62
+ readonly relType: string;
63
+ readonly entryPath: string;
64
+ readonly pivotCacheId: string | undefined;
65
+ readonly externalReferenceIndex: number | undefined;
66
+ }
67
+ export interface PreservedRootReferencePlan {
68
+ readonly relType: string;
69
+ readonly entryPath: string;
70
+ }
71
+ export interface PreservedPlan {
72
+ readonly perSheet: readonly (readonly ResolvedPreservedReference[])[];
73
+ readonly workbook: readonly PreservedWorkbookReferencePlan[];
74
+ readonly root: readonly PreservedRootReferencePlan[];
75
+ readonly parts: readonly PreservedPartPlan[];
76
+ /**
77
+ * Whether a source theme rides in {@link parts} at {@link THEME_PART_PATH}. The theme relationship
78
+ * and content-type override are emitted unconditionally either way; this only tells the writer
79
+ * whether to *also* generate its default theme body, which would otherwise clobber the preserved one.
80
+ */
81
+ readonly themeEmitted: boolean;
82
+ }
83
+ export interface DrawingPlan {
84
+ readonly number: number;
85
+ readonly relId: string;
86
+ readonly images: readonly ImagePlan[];
87
+ }
88
+ export interface ImagePlan extends DrawingImage {
89
+ readonly mediaNumber: number;
90
+ readonly extension: string;
91
+ }
92
+ export interface MediaPart {
93
+ readonly number: number;
94
+ readonly extension: string;
95
+ readonly data: Uint8Array;
96
+ }
97
+ export interface MediaPlan {
98
+ readonly parts: readonly MediaPart[];
99
+ readonly numberById: ReadonlyMap<number, number>;
100
+ readonly extensions: readonly string[];
101
+ }
102
+ export declare function planMedia(workbook: Workbook, sheets: readonly Worksheet[]): MediaPlan;
103
+ export declare function planPreservedParts(workbook: Workbook, generatedDrawingCount: number, generatedMediaCount: number): PreservedPlan;
@@ -0,0 +1,168 @@
1
+ // The plan layer of the writer: pure graph resolution that turns a Workbook model into the numbered,
2
+ // cross-referenced set of parts an `.xlsx` package needs — media, preserved (verbatim-carried) parts,
3
+ // and the sheet-/workbook-local relationship ids that wire them — before any XML is serialised.
4
+ import { AuthoringError } from "../../errors.js";
5
+ import { extensionOf, relativePartPath, relsPathFor, THEME_PART_PATH } from "../opc/part-paths.js";
6
+ import { preservedRelsXml } from "../opc/rels.js";
7
+ // A sheet's relationship-id allocator: hands out `rId1`, `rId2`, … in the one canonical order the
8
+ // package wires a sheet's parts (tables, drawing, comments, threaded comments, printer settings, external
9
+ // hyperlinks, background, preserved references, pivot tables). Every sheet-local id is drawn from here in
10
+ // sequence, so no plan step re-derives its starting offset by summing the counts of the steps before
11
+ // it — the arithmetic that, open-coded once per step with subtly different prefixes, could silently
12
+ // hand two parts the same id and corrupt the package. Monotonic by construction, so collisions cannot
13
+ // arise however the steps grow. One fresh allocator per sheet; the ids it yields are sheet-local.
14
+ export class SheetRelIds {
15
+ #next = 1;
16
+ /** The next relationship id (`rId1`, `rId2`, …), advancing the counter. */
17
+ next() {
18
+ return `rId${this.#next++}`;
19
+ }
20
+ }
21
+ // Gather the workbook images actually referenced by some sheet — either anchored in a drawing or set
22
+ // as a sheet background (an unreferenced image is not written) — number them in first-use order, and
23
+ // record the extensions in play. A sheet referencing an id with no registered image is a programming
24
+ // error the writer surfaces rather than emitting a dangling relationship.
25
+ export function planMedia(workbook, sheets) {
26
+ const usedIds = [];
27
+ const seen = new Set();
28
+ const use = (id) => {
29
+ if (!seen.has(id)) {
30
+ seen.add(id);
31
+ usedIds.push(id);
32
+ }
33
+ };
34
+ for (const sheet of sheets) {
35
+ for (const image of sheet.images)
36
+ use(image.imageId);
37
+ if (sheet.backgroundImageId !== undefined)
38
+ use(sheet.backgroundImageId);
39
+ }
40
+ const parts = [];
41
+ const numberById = new Map();
42
+ const extensions = new Set();
43
+ usedIds.forEach((id, i) => {
44
+ const image = workbook.getImage(id);
45
+ if (image === undefined) {
46
+ throw new AuthoringError(`a worksheet anchors image id ${id}, which is not registered on the workbook`);
47
+ }
48
+ const number = i + 1;
49
+ parts.push({ number, extension: image.extension, data: image.data });
50
+ numberById.set(id, number);
51
+ extensions.add(image.extension);
52
+ });
53
+ return { parts, numberById, extensions: [...extensions] };
54
+ }
55
+ // Resolve every sheet's verbatim-preserved worksheet references (a vector-shape drawing, a
56
+ // header/footer image) into the parts to emit and the per-sheet reference data that wires them. Each
57
+ // reference's captured part closure is re-numbered onto collision-proof `preservedP{n}` paths — so
58
+ // preserved content never clobbers a generated drawing/VML/media part — with the closure's internal
59
+ // relationships rewritten to the new sibling paths. Part numbering is the only cross-sheet concern
60
+ // here; each reference's sheet-local relationship id is assigned by the caller from the sheet's
61
+ // {@link SheetRelIds} allocator, so this function stays free of the sheet-local id arithmetic.
62
+ export function planPreservedParts(workbook, generatedDrawingCount, generatedMediaCount) {
63
+ const sheets = workbook.worksheets;
64
+ // The writer generates drawings, VML, and media of its own, so a preserved part of one of those
65
+ // kinds is re-numbered past the generated ones (a preserved drawing never clobbers an anchored
66
+ // drawing, a preserved VML never clobbers a comment's VML). Comment VML is numbered by sheet index,
67
+ // so `sheets.length` bounds it. Every other kind (pivot tables, caches, slicers, charts) the writer
68
+ // never generates, so those keep their original path — see {@link preservedPartPath}.
69
+ const numbering = {
70
+ drawing: generatedDrawingCount,
71
+ vml: sheets.length,
72
+ media: generatedMediaCount,
73
+ };
74
+ // One package-wide remap and one emitted-parts map: a part reached through more than one reference
75
+ // (a pivot cache reached both from its pivot table and from the workbook) is numbered once and
76
+ // emitted once, so overlapping closures collapse instead of duplicating parts.
77
+ const remap = new Map();
78
+ // A preserved theme rides the same closure machinery as every other verbatim part — it can carry
79
+ // relationships of its own (a picture used as a themed fill) that need the same renumbering and
80
+ // rewiring. Its entry is pinned to the fixed theme path rather than left to {@link preservedPartPath},
81
+ // because the workbook's theme relationship and the content-type override name that path
82
+ // unconditionally; a source package that called its part `theme2.xml` would otherwise land it
83
+ // somewhere neither points.
84
+ const theme = workbook.themePart;
85
+ if (theme !== undefined)
86
+ remap.set(theme.entryPath, THEME_PART_PATH);
87
+ const allReferences = [
88
+ ...sheets.flatMap((sheet) => sheet.preservedReferences),
89
+ ...workbook.preservedReferences,
90
+ ...workbook.preservedRootReferences,
91
+ ...(theme === undefined ? [] : [theme]),
92
+ ];
93
+ for (const reference of allReferences) {
94
+ for (const part of reference.parts) {
95
+ if (!remap.has(part.path))
96
+ remap.set(part.path, preservedPartPath(part.path, numbering));
97
+ }
98
+ }
99
+ const emitted = new Map();
100
+ for (const reference of allReferences) {
101
+ for (const part of reference.parts) {
102
+ const newPath = remap.get(part.path);
103
+ if (emitted.has(newPath))
104
+ continue;
105
+ const rels = part.rels.flatMap((rel) => {
106
+ // An external relationship (a linked workbook) is emitted verbatim — its target is outside the
107
+ // package, so it is neither in the remap nor expressed relative to the new path.
108
+ if (rel.external) {
109
+ return [{ id: rel.id, type: rel.type, target: rel.targetPath, external: true }];
110
+ }
111
+ const target = remap.get(rel.targetPath);
112
+ return target === undefined
113
+ ? []
114
+ : [{ id: rel.id, type: rel.type, target: relativePartPath(newPath, target) }];
115
+ });
116
+ // The one preserved part whose *bytes* can change: a theme the caller authored over is
117
+ // regenerated from the source part (see `Workbook.authoredThemeXml`) rather than carried
118
+ // verbatim, so the format scheme, the unauthored slots' encoding, and the relationships below
119
+ // all still ride through — only the authored elements differ.
120
+ const authoredTheme = newPath === THEME_PART_PATH ? workbook.authoredThemeXml() : undefined;
121
+ emitted.set(newPath, {
122
+ path: newPath,
123
+ bytes: authoredTheme === undefined ? part.bytes : new TextEncoder().encode(authoredTheme),
124
+ contentType: part.contentType,
125
+ relsPath: rels.length === 0 ? null : relsPathFor(newPath),
126
+ relsXml: rels.length === 0 ? null : preservedRelsXml(rels),
127
+ });
128
+ }
129
+ }
130
+ const perSheet = sheets.map((sheet) => sheet.preservedReferences.map((reference) => ({
131
+ element: reference.element,
132
+ relType: reference.relType,
133
+ entryPath: remap.get(reference.entryPath),
134
+ })));
135
+ const workbookRefs = workbook.preservedReferences.map((reference) => ({
136
+ relType: reference.relType,
137
+ entryPath: remap.get(reference.entryPath),
138
+ pivotCacheId: reference.pivotCacheId,
139
+ externalReferenceIndex: reference.externalReferenceIndex,
140
+ }));
141
+ const rootRefs = workbook.preservedRootReferences.map((reference) => ({
142
+ relType: reference.relType,
143
+ entryPath: remap.get(reference.entryPath),
144
+ }));
145
+ return {
146
+ perSheet,
147
+ workbook: workbookRefs,
148
+ root: rootRefs,
149
+ parts: [...emitted.values()],
150
+ themeEmitted: theme !== undefined,
151
+ };
152
+ }
153
+ // The path a preserved part is emitted at. A kind the writer generates of its own — a drawing, a VML,
154
+ // a media image — is re-numbered past the generated parts of that kind (see {@link planPreservedParts})
155
+ // so it never clobbers one. Every other kind (a pivot table, a pivot/slicer cache, a slicer, a chart)
156
+ // the writer never generates, so it keeps its original path — leaving the package's standard part
157
+ // names intact and letting overlapping closures agree on a single path for a shared part.
158
+ function preservedPartPath(originalPath, numbering) {
159
+ const ext = extensionOf(originalPath);
160
+ if (ext.toLowerCase() === 'vml')
161
+ return `xl/drawings/vmlDrawing${++numbering.vml}.vml`;
162
+ if (originalPath.startsWith('xl/media/'))
163
+ return `xl/media/image${++numbering.media}.${ext}`;
164
+ if (originalPath.startsWith('xl/drawings/') && ext.toLowerCase() === 'xml') {
165
+ return `xl/drawings/drawing${++numbering.drawing}.xml`;
166
+ }
167
+ return originalPath;
168
+ }
@@ -0,0 +1,5 @@
1
+ import { type ParsedPivotTable } from '../../core/pivot-table.ts';
2
+ /** Reconstruct a pivot's semantic model from its two definition parts. The records part is not
3
+ * consulted: the cache's field catalogue and the table's field roles fully describe the pivot's
4
+ * shape, and the aggregated values are Excel's to compute on refresh. */
5
+ export declare function parsePivotTable(tableXml: string, cacheXml: string): ParsedPivotTable;