@qvac/harness 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +70 -1
- package/NOTICE.md +16 -0
- package/dist-lib/lib/capabilities/completion.d.ts +1 -0
- package/dist-lib/lib/capabilities/completion.js +46 -8
- package/dist-lib/lib/capabilities/tool-turns.d.ts +3 -0
- package/dist-lib/lib/capabilities/tool-turns.js +7 -0
- package/dist-lib/lib/context-window.js +2 -2
- package/dist-lib/lib/helpers/run-outcome.d.ts +4 -1
- package/dist-lib/lib/helpers/run-outcome.js +14 -8
- package/dist-lib/lib/helpers/tool-call-markup.js +4 -4
- package/dist-lib/lib/hooks/built-in/arg-repair.js +7 -0
- package/dist-lib/lib/office/engine/codes.d.ts +62 -0
- package/dist-lib/lib/office/engine/codes.js +61 -0
- package/dist-lib/lib/office/engine/docx/document.d.ts +216 -0
- package/dist-lib/lib/office/engine/docx/document.js +1152 -0
- package/dist-lib/lib/office/engine/docx/index.d.ts +7 -0
- package/dist-lib/lib/office/engine/docx/index.js +8 -0
- package/dist-lib/lib/office/engine/docx/styles.d.ts +31 -0
- package/dist-lib/lib/office/engine/docx/styles.js +173 -0
- package/dist-lib/lib/office/engine/docx/template.d.ts +18 -0
- package/dist-lib/lib/office/engine/docx/template.js +133 -0
- package/dist-lib/lib/office/engine/docx/text.d.ts +55 -0
- package/dist-lib/lib/office/engine/docx/text.js +538 -0
- package/dist-lib/lib/office/engine/drawingml/chart.d.ts +63 -0
- package/dist-lib/lib/office/engine/drawingml/chart.js +539 -0
- package/dist-lib/lib/office/engine/drawingml/text.d.ts +35 -0
- package/dist-lib/lib/office/engine/drawingml/text.js +352 -0
- package/dist-lib/lib/office/engine/errors.d.ts +6 -0
- package/dist-lib/lib/office/engine/errors.js +12 -0
- package/dist-lib/lib/office/engine/image.d.ts +8 -0
- package/dist-lib/lib/office/engine/image.js +48 -0
- package/dist-lib/lib/office/engine/index.d.ts +12 -0
- package/dist-lib/lib/office/engine/index.js +7 -0
- package/dist-lib/lib/office/engine/opc/content-types.d.ts +17 -0
- package/dist-lib/lib/office/engine/opc/content-types.js +74 -0
- package/dist-lib/lib/office/engine/opc/media.d.ts +13 -0
- package/dist-lib/lib/office/engine/opc/media.js +11 -0
- package/dist-lib/lib/office/engine/opc/package.d.ts +51 -0
- package/dist-lib/lib/office/engine/opc/package.js +324 -0
- package/dist-lib/lib/office/engine/opc/paths.d.ts +7 -0
- package/dist-lib/lib/office/engine/opc/paths.js +46 -0
- package/dist-lib/lib/office/engine/opc/properties.d.ts +7 -0
- package/dist-lib/lib/office/engine/opc/properties.js +75 -0
- package/dist-lib/lib/office/engine/opc/relationships.d.ts +23 -0
- package/dist-lib/lib/office/engine/opc/relationships.js +65 -0
- package/dist-lib/lib/office/engine/opc/zip.d.ts +15 -0
- package/dist-lib/lib/office/engine/opc/zip.js +264 -0
- package/dist-lib/lib/office/engine/pptx/fit.d.ts +12 -0
- package/dist-lib/lib/office/engine/pptx/fit.js +37 -0
- package/dist-lib/lib/office/engine/pptx/index.d.ts +8 -0
- package/dist-lib/lib/office/engine/pptx/index.js +8 -0
- package/dist-lib/lib/office/engine/pptx/inherit.d.ts +29 -0
- package/dist-lib/lib/office/engine/pptx/inherit.js +155 -0
- package/dist-lib/lib/office/engine/pptx/notes.d.ts +5 -0
- package/dist-lib/lib/office/engine/pptx/notes.js +85 -0
- package/dist-lib/lib/office/engine/pptx/presentation.d.ts +54 -0
- package/dist-lib/lib/office/engine/pptx/presentation.js +749 -0
- package/dist-lib/lib/office/engine/pptx/read.d.ts +9 -0
- package/dist-lib/lib/office/engine/pptx/read.js +66 -0
- package/dist-lib/lib/office/engine/pptx/shapes.d.ts +52 -0
- package/dist-lib/lib/office/engine/pptx/shapes.js +276 -0
- package/dist-lib/lib/office/engine/pptx/slides.d.ts +27 -0
- package/dist-lib/lib/office/engine/pptx/slides.js +123 -0
- package/dist-lib/lib/office/engine/pptx/template.d.ts +20 -0
- package/dist-lib/lib/office/engine/pptx/template.js +391 -0
- package/dist-lib/lib/office/engine/pptx/types.d.ts +120 -0
- package/dist-lib/lib/office/engine/pptx/types.js +1 -0
- package/dist-lib/lib/office/engine/units.d.ts +3 -0
- package/dist-lib/lib/office/engine/units.js +12 -0
- package/dist-lib/lib/office/engine/utf8.d.ts +2 -0
- package/dist-lib/lib/office/engine/utf8.js +103 -0
- package/dist-lib/lib/office/engine/xlsx/formula.d.ts +49 -0
- package/dist-lib/lib/office/engine/xlsx/formula.js +381 -0
- package/dist-lib/lib/office/engine/xlsx/index.d.ts +8 -0
- package/dist-lib/lib/office/engine/xlsx/index.js +8 -0
- package/dist-lib/lib/office/engine/xlsx/refs.d.ts +22 -0
- package/dist-lib/lib/office/engine/xlsx/refs.js +82 -0
- package/dist-lib/lib/office/engine/xlsx/reshape.d.ts +21 -0
- package/dist-lib/lib/office/engine/xlsx/reshape.js +424 -0
- package/dist-lib/lib/office/engine/xlsx/sheet.d.ts +108 -0
- package/dist-lib/lib/office/engine/xlsx/sheet.js +662 -0
- package/dist-lib/lib/office/engine/xlsx/strings.d.ts +15 -0
- package/dist-lib/lib/office/engine/xlsx/strings.js +93 -0
- package/dist-lib/lib/office/engine/xlsx/styles.d.ts +38 -0
- package/dist-lib/lib/office/engine/xlsx/styles.js +369 -0
- package/dist-lib/lib/office/engine/xlsx/template.d.ts +7 -0
- package/dist-lib/lib/office/engine/xlsx/template.js +54 -0
- package/dist-lib/lib/office/engine/xlsx/workbook.d.ts +161 -0
- package/dist-lib/lib/office/engine/xlsx/workbook.js +850 -0
- package/dist-lib/lib/office/engine/xlsx/write.d.ts +2 -0
- package/dist-lib/lib/office/engine/xlsx/write.js +42 -0
- package/dist-lib/lib/office/engine/xml.d.ts +45 -0
- package/dist-lib/lib/office/engine/xml.js +258 -0
- package/dist-lib/lib/tools/exec/scope.d.ts +2 -0
- package/dist-lib/lib/tools/exec/scope.js +33 -2
- package/dist-lib/lib/tools/pdf/build.d.ts +43 -0
- package/dist-lib/lib/tools/pdf/build.js +150 -0
- package/dist-lib/lib/tools/pdf/images.d.ts +7 -0
- package/dist-lib/lib/tools/pdf/images.js +82 -0
- package/dist-lib/lib/tools/pdf/request.d.ts +63 -0
- package/dist-lib/lib/tools/pdf/request.js +335 -0
- package/dist-lib/lib/tools/pdf.d.ts +6 -0
- package/dist-lib/lib/tools/pdf.js +302 -0
- package/dist-lib/lib/tools/skill.js +14 -0
- package/dist-lib/lib/tools/weather-lookup/geocode.d.ts +26 -0
- package/dist-lib/lib/tools/weather-lookup/geocode.js +110 -0
- package/dist-lib/lib/tools/weather-lookup/place.js +5 -1
- package/dist-lib/lib/tools/weather-lookup.d.ts +2 -1
- package/dist-lib/lib/tools/weather-lookup.js +115 -84
- package/package.json +29 -1
- package/worker/harness-sidecar.mjs +3 -1
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import * as xml from '../xml.js';
|
|
2
|
+
import * as refs from './refs.js';
|
|
3
|
+
import * as formula from './formula.js';
|
|
4
|
+
const X = xml.ns.x;
|
|
5
|
+
const XDR = xml.ns.xdr;
|
|
6
|
+
const XM = 'http://schemas.microsoft.com/office/excel/2006/main';
|
|
7
|
+
const PIVOT_CACHE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml';
|
|
8
|
+
const COMMENTS_REL = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments';
|
|
9
|
+
const TABLE_REL = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/table';
|
|
10
|
+
const PIVOT_TABLE_REL = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable';
|
|
11
|
+
export function formulaElements(doc) {
|
|
12
|
+
return [
|
|
13
|
+
...xml.descendants(doc, X, 'f'),
|
|
14
|
+
...xml.descendants(doc, X, 'formula'),
|
|
15
|
+
...xml.descendants(doc, X, 'formula1'),
|
|
16
|
+
...xml.descendants(doc, X, 'formula2'),
|
|
17
|
+
...xml.descendants(doc, XM, 'f')
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
export function tableNames(pkg, sheetPart) {
|
|
21
|
+
return pkg.related(sheetPart, TABLE_REL).map((part) => {
|
|
22
|
+
const root = pkg.root(part);
|
|
23
|
+
return root.getAttribute('displayName') || root.getAttribute('name') || part;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function tables(host, sheet) {
|
|
27
|
+
return host.package.related(sheet.part, TABLE_REL).map((part) => {
|
|
28
|
+
const root = host.package.root(part);
|
|
29
|
+
return {
|
|
30
|
+
part,
|
|
31
|
+
root,
|
|
32
|
+
area: refs.parseRange(root.getAttribute('ref') || 'A1'),
|
|
33
|
+
header: root.hasAttribute('headerRowCount') ? Number(root.getAttribute('headerRowCount')) : 1,
|
|
34
|
+
totals: root.hasAttribute('totalsRowCount') ? Number(root.getAttribute('totalsRowCount')) : 0,
|
|
35
|
+
name: root.getAttribute('displayName') || root.getAttribute('name') || part
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function sqref(value, change) {
|
|
40
|
+
const parts = value
|
|
41
|
+
.trim()
|
|
42
|
+
.split(/\s+/)
|
|
43
|
+
.map((part) => formula.adjustRange(part, change))
|
|
44
|
+
.filter((part) => part !== null);
|
|
45
|
+
return parts.length ? parts.join(' ') : null;
|
|
46
|
+
}
|
|
47
|
+
function tableBlockers(host, sheet, change) {
|
|
48
|
+
const reasons = [];
|
|
49
|
+
const end = change.at + change.count - 1;
|
|
50
|
+
const hits = (lo, hi) => lo <= hi && change.at <= hi && end >= lo;
|
|
51
|
+
for (const table of tables(host, sheet)) {
|
|
52
|
+
const { top, bottom } = table.area;
|
|
53
|
+
const dataTop = top + table.header;
|
|
54
|
+
const dataBottom = bottom - table.totals;
|
|
55
|
+
if (hits(top, dataTop - 1) || hits(dataBottom + 1, bottom)) {
|
|
56
|
+
reasons.push(`the header or totals row of table ${table.name}`);
|
|
57
|
+
}
|
|
58
|
+
else if (change.at <= dataTop && end >= dataBottom && dataTop <= dataBottom) {
|
|
59
|
+
reasons.push(`every data row of table ${table.name}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return reasons;
|
|
63
|
+
}
|
|
64
|
+
export function renamePivotSources(pkg, from, to) {
|
|
65
|
+
const wanted = from.toLowerCase();
|
|
66
|
+
for (const name of pkg.names().filter((n) => pkg.contentType(n) === PIVOT_CACHE)) {
|
|
67
|
+
const sources = xml
|
|
68
|
+
.descendants(pkg.xml(name), X, 'worksheetSource')
|
|
69
|
+
.filter((src) => (src.getAttribute('sheet') || '').toLowerCase() === wanted);
|
|
70
|
+
for (const src of sources) {
|
|
71
|
+
src.setAttribute('sheet', to);
|
|
72
|
+
}
|
|
73
|
+
if (sources.length) {
|
|
74
|
+
pkg.touch(name);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function hasPivot(host, sheet) {
|
|
79
|
+
if (host.package.related(sheet.part, PIVOT_TABLE_REL).length) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
const target = sheet.name.toLowerCase();
|
|
83
|
+
return host.package.names().some((name) => {
|
|
84
|
+
if (host.package.contentType(name) !== PIVOT_CACHE)
|
|
85
|
+
return false;
|
|
86
|
+
return xml
|
|
87
|
+
.descendants(host.package.xml(name), X, 'worksheetSource')
|
|
88
|
+
.some((src) => (src.getAttribute('sheet') || '').toLowerCase() === target);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function straddles(area, change) {
|
|
92
|
+
const lo = change.axis === 'row' ? area.top : area.left;
|
|
93
|
+
const hi = change.axis === 'row' ? area.bottom : area.right;
|
|
94
|
+
if (change.kind === 'insert') {
|
|
95
|
+
return change.at > lo && change.at <= hi;
|
|
96
|
+
}
|
|
97
|
+
const past = change.at + change.count;
|
|
98
|
+
return change.at <= hi && past > lo && !(change.at <= lo && past > hi);
|
|
99
|
+
}
|
|
100
|
+
function formulaBlocker(sheet, change) {
|
|
101
|
+
for (const f of xml.descendants(sheet.doc, X, 'f')) {
|
|
102
|
+
const kind = f.getAttribute('t');
|
|
103
|
+
if (kind === 'dataTable') {
|
|
104
|
+
return 'data tables';
|
|
105
|
+
}
|
|
106
|
+
const ref = f.getAttribute('ref');
|
|
107
|
+
if (kind !== 'array' || !ref) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (straddles(refs.parseRange(ref), change)) {
|
|
111
|
+
return `an array formula over ${ref}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
export function blockers(host, sheet, change) {
|
|
117
|
+
const reasons = [];
|
|
118
|
+
const root = sheet.root;
|
|
119
|
+
if (change.axis === 'col' && xml.child(root, X, 'tableParts')) {
|
|
120
|
+
reasons.push('tables');
|
|
121
|
+
}
|
|
122
|
+
if (change.axis === 'row' && change.kind === 'delete') {
|
|
123
|
+
reasons.push(...tableBlockers(host, sheet, change));
|
|
124
|
+
}
|
|
125
|
+
if (xml.child(root, X, 'legacyDrawing') ||
|
|
126
|
+
host.package.related(sheet.part, COMMENTS_REL).length) {
|
|
127
|
+
reasons.push('comments');
|
|
128
|
+
}
|
|
129
|
+
if (hasPivot(host, sheet)) {
|
|
130
|
+
reasons.push('pivot tables');
|
|
131
|
+
}
|
|
132
|
+
const blocker = formulaBlocker(sheet, change);
|
|
133
|
+
if (blocker) {
|
|
134
|
+
reasons.push(blocker);
|
|
135
|
+
}
|
|
136
|
+
return reasons;
|
|
137
|
+
}
|
|
138
|
+
export function expandShared(sheet) {
|
|
139
|
+
const shared = xml.descendants(sheet.doc, X, 'f').filter((f) => f.getAttribute('t') === 'shared');
|
|
140
|
+
if (!shared.length) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const texts = new Map();
|
|
144
|
+
for (const f of shared) {
|
|
145
|
+
const cell = f.parentNode;
|
|
146
|
+
texts.set(f, xml.isElement(cell) ? sheet.formula(cell) : null);
|
|
147
|
+
}
|
|
148
|
+
for (const f of shared) {
|
|
149
|
+
const text = texts.get(f);
|
|
150
|
+
for (const attr of ['t', 'ref', 'si']) {
|
|
151
|
+
f.removeAttribute(attr);
|
|
152
|
+
}
|
|
153
|
+
if (text) {
|
|
154
|
+
xml.setText(f, text.replace(/^=/, ''));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
sheet.resetMasters();
|
|
158
|
+
sheet.touch();
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
function needsExpansion(sheet, target) {
|
|
162
|
+
return xml
|
|
163
|
+
.descendants(sheet.doc, X, 'f')
|
|
164
|
+
.some((f) => f.getAttribute('t') === 'shared' &&
|
|
165
|
+
!!xml.text(f) &&
|
|
166
|
+
formula.references(xml.text(f), sheet.name, target));
|
|
167
|
+
}
|
|
168
|
+
function adjustText(el, ownSheet, change) {
|
|
169
|
+
const text = xml.text(el);
|
|
170
|
+
if (!text) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
const next = formula.adjust(text, ownSheet, change);
|
|
174
|
+
if (next === text) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
xml.setText(el, next);
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
function adjustCellFormula(sheet, f, change) {
|
|
181
|
+
let touched = adjustText(f, sheet.name, change);
|
|
182
|
+
const ref = f.getAttribute('ref');
|
|
183
|
+
if (sheet.name === change.sheet && ref) {
|
|
184
|
+
const next = formula.adjustRange(ref, change);
|
|
185
|
+
if (next && next !== ref) {
|
|
186
|
+
f.setAttribute('ref', next);
|
|
187
|
+
touched = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const cell = f.parentNode;
|
|
191
|
+
if (xml.isElement(cell) && formula.references(xml.text(f), sheet.name, change.sheet)) {
|
|
192
|
+
for (const v of xml.children(cell, X, 'v')) {
|
|
193
|
+
xml.remove(v);
|
|
194
|
+
}
|
|
195
|
+
cell.removeAttribute('t');
|
|
196
|
+
touched = true;
|
|
197
|
+
}
|
|
198
|
+
return touched;
|
|
199
|
+
}
|
|
200
|
+
function adjustFormulas(sheet, change) {
|
|
201
|
+
let touched = false;
|
|
202
|
+
for (const f of xml.descendants(sheet.doc, X, 'f')) {
|
|
203
|
+
if (adjustCellFormula(sheet, f, change)) {
|
|
204
|
+
touched = true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const rules = formulaElements(sheet.doc).filter((el) => el.namespaceURI !== X || el.localName !== 'f');
|
|
208
|
+
for (const el of rules) {
|
|
209
|
+
if (adjustText(el, sheet.name, change)) {
|
|
210
|
+
touched = true;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return touched;
|
|
214
|
+
}
|
|
215
|
+
function adjustList(list, entry, change) {
|
|
216
|
+
if (!list)
|
|
217
|
+
return;
|
|
218
|
+
for (const el of xml.children(list, X, entry)) {
|
|
219
|
+
const next = formula.adjustRange(xml.attr(el, 'ref'), change);
|
|
220
|
+
const keep = entry === 'mergeCell' ? !!next && next.includes(':') : next !== null;
|
|
221
|
+
if (!keep || next === null) {
|
|
222
|
+
xml.remove(el);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
el.setAttribute('ref', next);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const count = xml.children(list, X, entry).length;
|
|
229
|
+
if (!count) {
|
|
230
|
+
xml.remove(list);
|
|
231
|
+
}
|
|
232
|
+
else if (entry === 'mergeCell') {
|
|
233
|
+
list.setAttribute('count', String(count));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function adjustSqrefs(sheet, change) {
|
|
237
|
+
for (const local of ['conditionalFormatting', 'dataValidation']) {
|
|
238
|
+
for (const el of xml.descendants(sheet.doc, X, local)) {
|
|
239
|
+
const value = el.getAttribute('sqref');
|
|
240
|
+
if (value === null) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const next = sqref(value, change);
|
|
244
|
+
if (next === null) {
|
|
245
|
+
xml.remove(el);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
el.setAttribute('sqref', next);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const validations = xml.child(sheet.root, X, 'dataValidations');
|
|
253
|
+
if (validations) {
|
|
254
|
+
const count = xml.children(validations, X, 'dataValidation').length;
|
|
255
|
+
if (count) {
|
|
256
|
+
validations.setAttribute('count', String(count));
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
xml.remove(validations);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
for (const el of xml.descendants(sheet.doc, XM, 'sqref')) {
|
|
263
|
+
const next = sqref(xml.text(el), change);
|
|
264
|
+
if (next !== null) {
|
|
265
|
+
xml.setText(el, next);
|
|
266
|
+
}
|
|
267
|
+
else if (el.parentNode?.parentNode) {
|
|
268
|
+
xml.remove(el.parentNode);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function adjustFilterColumns(el, move) {
|
|
273
|
+
const { change } = move;
|
|
274
|
+
if (change.axis !== 'col') {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const left = refs.parseRange(move.from).left;
|
|
278
|
+
const nextLeft = refs.parseRange(move.to).left;
|
|
279
|
+
for (const column of xml.children(el, X, 'filterColumn')) {
|
|
280
|
+
const moved = formula.moveIndex(left + Number(column.getAttribute('colId')), change);
|
|
281
|
+
if (moved === null) {
|
|
282
|
+
xml.remove(column);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
column.setAttribute('colId', String(moved - nextLeft));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function adjustFilters(sheet, change) {
|
|
290
|
+
for (const local of ['autoFilter', 'sortState', 'sortCondition']) {
|
|
291
|
+
for (const el of xml.descendants(sheet.doc, X, local)) {
|
|
292
|
+
const ref = el.getAttribute('ref');
|
|
293
|
+
if (ref === null) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
const next = formula.adjustRange(ref, change);
|
|
297
|
+
if (next === null) {
|
|
298
|
+
xml.remove(el);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
adjustFilterColumns(el, { from: ref, to: next, change });
|
|
302
|
+
el.setAttribute('ref', next);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function adjustBreaks(sheet, change) {
|
|
308
|
+
const breaks = xml.child(sheet.root, X, change.axis === 'row' ? 'rowBreaks' : 'colBreaks');
|
|
309
|
+
if (!breaks) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
for (const brk of xml.children(breaks, X, 'brk')) {
|
|
313
|
+
const next = formula.moveIndex(Number(brk.getAttribute('id')), change);
|
|
314
|
+
if (next === null) {
|
|
315
|
+
xml.remove(brk);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
brk.setAttribute('id', String(next));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const count = xml.children(breaks, X, 'brk').length;
|
|
322
|
+
if (!count) {
|
|
323
|
+
xml.remove(breaks);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
breaks.setAttribute('count', String(count));
|
|
327
|
+
if (breaks.hasAttribute('manualBreakCount')) {
|
|
328
|
+
breaks.setAttribute('manualBreakCount', String(count));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function adjustTables(host, sheet, change) {
|
|
332
|
+
if (change.axis !== 'row')
|
|
333
|
+
return;
|
|
334
|
+
for (const table of tables(host, sheet)) {
|
|
335
|
+
for (const el of [table.root, ...xml.children(table.root, X, 'autoFilter')]) {
|
|
336
|
+
const next = formula.adjustRange(xml.attr(el, 'ref'), change);
|
|
337
|
+
if (next) {
|
|
338
|
+
el.setAttribute('ref', next);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
host.package.touch(table.part);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
function adjustAnchors(host, sheet, change) {
|
|
345
|
+
const drawing = host.drawingOf(sheet);
|
|
346
|
+
if (!drawing) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const doc = host.package.xml(drawing);
|
|
350
|
+
const local = change.axis === 'row' ? 'row' : 'col';
|
|
351
|
+
let moved = false;
|
|
352
|
+
for (const marker of [...xml.descendants(doc, XDR, 'from'), ...xml.descendants(doc, XDR, 'to')]) {
|
|
353
|
+
const el = xml.child(marker, XDR, local);
|
|
354
|
+
if (!el) {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
const index = Number(xml.text(el));
|
|
358
|
+
const edge = (change.axis === 'row' ? refs.MAX_ROWS : refs.MAX_COLUMNS) - 1;
|
|
359
|
+
const value = formula.moveIndex(index, change) ?? (change.kind === 'insert' ? edge : change.at);
|
|
360
|
+
if (value !== index) {
|
|
361
|
+
xml.setText(el, String(value));
|
|
362
|
+
moved = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (moved) {
|
|
366
|
+
host.package.touch(drawing);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function adjustStructures(host, sheet, change) {
|
|
370
|
+
adjustList(xml.child(sheet.root, X, 'mergeCells'), 'mergeCell', change);
|
|
371
|
+
adjustList(xml.child(sheet.root, X, 'hyperlinks'), 'hyperlink', change);
|
|
372
|
+
adjustSqrefs(sheet, change);
|
|
373
|
+
adjustFilters(sheet, change);
|
|
374
|
+
adjustBreaks(sheet, change);
|
|
375
|
+
adjustTables(host, sheet, change);
|
|
376
|
+
adjustAnchors(host, sheet, change);
|
|
377
|
+
sheet.touch();
|
|
378
|
+
}
|
|
379
|
+
function adjustElsewhere(host, change) {
|
|
380
|
+
let names = false;
|
|
381
|
+
for (const dn of host.definedNames()) {
|
|
382
|
+
if (adjustText(dn, null, change)) {
|
|
383
|
+
names = true;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (names) {
|
|
387
|
+
host.package.touch(host.main);
|
|
388
|
+
}
|
|
389
|
+
for (const part of host.chartParts()) {
|
|
390
|
+
let touched = false;
|
|
391
|
+
for (const f of xml.descendants(host.package.xml(part), xml.ns.c, 'f')) {
|
|
392
|
+
if (adjustText(f, null, change)) {
|
|
393
|
+
touched = true;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (touched) {
|
|
397
|
+
host.package.touch(part);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function sheetsOf(host, target) {
|
|
402
|
+
return host
|
|
403
|
+
.entries()
|
|
404
|
+
.filter((entry) => entry.kind === 'worksheet')
|
|
405
|
+
.map((entry) => (entry.part === target.part ? target : host.sheetFor(entry)));
|
|
406
|
+
}
|
|
407
|
+
export function apply(host, target, change) {
|
|
408
|
+
for (const sheet of sheetsOf(host, target)) {
|
|
409
|
+
if (adjustFormulas(sheet, change)) {
|
|
410
|
+
sheet.touch();
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
adjustStructures(host, target, change);
|
|
414
|
+
adjustElsewhere(host, change);
|
|
415
|
+
host.state.formulas = true;
|
|
416
|
+
host.state.cellsChanged = true;
|
|
417
|
+
}
|
|
418
|
+
export function prepare(host, target) {
|
|
419
|
+
for (const sheet of sheetsOf(host, target)) {
|
|
420
|
+
if (sheet.part === target.part || needsExpansion(sheet, target.name)) {
|
|
421
|
+
expandShared(sheet);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Document, Element } from '../xml.ts';
|
|
2
|
+
import type { Package } from '../opc/package.ts';
|
|
3
|
+
import { type SharedStrings } from './strings.ts';
|
|
4
|
+
import type { Styles } from './styles.ts';
|
|
5
|
+
import type { Area, Position } from './refs.ts';
|
|
6
|
+
export type CellValue = string | number | boolean | null;
|
|
7
|
+
export interface EditState {
|
|
8
|
+
touched: Set<Sheet>;
|
|
9
|
+
formulas: boolean;
|
|
10
|
+
cellsChanged: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface SheetHost {
|
|
13
|
+
package: Package;
|
|
14
|
+
strings: SharedStrings;
|
|
15
|
+
styles: Styles;
|
|
16
|
+
state: EditState;
|
|
17
|
+
readonly date1904: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface SheetEntry {
|
|
20
|
+
el: Element;
|
|
21
|
+
index: number;
|
|
22
|
+
rId: string;
|
|
23
|
+
name: string;
|
|
24
|
+
state: string;
|
|
25
|
+
part: string;
|
|
26
|
+
kind: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CellEntry extends Position {
|
|
29
|
+
el: Element;
|
|
30
|
+
}
|
|
31
|
+
export interface RowEntry {
|
|
32
|
+
el: Element;
|
|
33
|
+
r: number;
|
|
34
|
+
}
|
|
35
|
+
export interface ReadOptions {
|
|
36
|
+
range?: string;
|
|
37
|
+
limit?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface SheetRead {
|
|
40
|
+
name: string;
|
|
41
|
+
range: string | null;
|
|
42
|
+
rows: CellValue[][];
|
|
43
|
+
formulas: Record<string, string>;
|
|
44
|
+
merged: string[];
|
|
45
|
+
truncated?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface CellRead {
|
|
48
|
+
value: CellValue;
|
|
49
|
+
formula: string | null;
|
|
50
|
+
format: string;
|
|
51
|
+
}
|
|
52
|
+
export interface SerialDate {
|
|
53
|
+
serial: number;
|
|
54
|
+
time: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface ColumnWidth {
|
|
57
|
+
col: number;
|
|
58
|
+
width: number;
|
|
59
|
+
}
|
|
60
|
+
export declare const SHEET_ORDER: string[];
|
|
61
|
+
export declare function serialToIso(serial: number, date1904: boolean): string | number;
|
|
62
|
+
export declare function isoToSerial(value: string, date1904: boolean): SerialDate;
|
|
63
|
+
export declare class Sheet {
|
|
64
|
+
host: SheetHost;
|
|
65
|
+
name: string;
|
|
66
|
+
part: string;
|
|
67
|
+
index: number;
|
|
68
|
+
private masters;
|
|
69
|
+
constructor(host: SheetHost, entry: SheetEntry);
|
|
70
|
+
get package(): Package;
|
|
71
|
+
get doc(): Document;
|
|
72
|
+
get root(): Element;
|
|
73
|
+
sheetData(): Element;
|
|
74
|
+
rows(): Element[];
|
|
75
|
+
touch(): void;
|
|
76
|
+
cells(): CellEntry[];
|
|
77
|
+
numberedRows(): RowEntry[];
|
|
78
|
+
numberedCells(row: Element, r: number): CellEntry[];
|
|
79
|
+
number(): void;
|
|
80
|
+
positionOf(c: Element): Position;
|
|
81
|
+
usedRange(): Area | null;
|
|
82
|
+
merged(): string[];
|
|
83
|
+
value(c: Element): CellValue;
|
|
84
|
+
formula(c: Element): string | null;
|
|
85
|
+
resetMasters(): void;
|
|
86
|
+
read(opts?: ReadOptions): SheetRead;
|
|
87
|
+
get(ref: unknown): CellRead;
|
|
88
|
+
findRow(r: number): Element | null;
|
|
89
|
+
ensureRow(r: number): Element;
|
|
90
|
+
findCell(pos: Position): Element | null;
|
|
91
|
+
ensureCell(pos: Position): Element;
|
|
92
|
+
write(ref: string, input: unknown): void;
|
|
93
|
+
lastRow(): number;
|
|
94
|
+
shiftRows(from: number, delta: number): void;
|
|
95
|
+
removeRows(from: number, count: number): void;
|
|
96
|
+
removeColumns(from: number, count: number): void;
|
|
97
|
+
setColumnWidth(spec: ColumnWidth): void;
|
|
98
|
+
updateDimension(): void;
|
|
99
|
+
private position;
|
|
100
|
+
private sharedMasters;
|
|
101
|
+
private fillRead;
|
|
102
|
+
private appendValue;
|
|
103
|
+
private writeContent;
|
|
104
|
+
private writeValue;
|
|
105
|
+
private shrinkColumns;
|
|
106
|
+
private guardMerged;
|
|
107
|
+
private guardWrite;
|
|
108
|
+
}
|