xlvane 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cli.js +331 -12
- package/dist/index.d.ts +6 -7
- package/dist/index.js +3 -3
- package/dist/{node-files-uazELnqk.js → node-files-B0iqSJIJ.js} +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +3 -3
- package/dist/{options-B7UhudO_.js → options-CwSp2pA4.js} +87 -12
- package/dist/{rows-Cwte1t8m.js → rows-DKwlr0rg.js} +222 -75
- package/dist/{stream-write-CTgWff2P.js → stream-write-BKppyMz0.js} +9 -2
- package/dist/{stream-write-Q-sef804.d.ts → stream-write-GJXORYQ2.d.ts} +37 -7
- package/docs/cli-json/inspect.schema.json +8 -0
- package/docs/errors.md +1 -1
- package/docs/exceljs-compat.md +2 -2
- package/docs/inspect-json.md +2 -0
- package/llms-full.txt +19 -9
- package/package.json +1 -1
- package/skills/xlvane/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -105,7 +105,7 @@ In Node.js, `writeWorkbookFile(workbook, 'sales.xlsx')` from `xlvane/node` write
|
|
|
105
105
|
- Values: numbers, strings, booleans, `Date`s (stored as serial numbers with a `yyyy-mm-dd` or `yyyy-mm-dd hh:mm:ss` format unless the style sets one), `{ error: '#N/A' }`, and `{ formula, result }`, also as an array formula (`{ formula, array: 'A1:A3' }`) or a shared formula (`{ formula, shared: 'B1:B9' }` on the first cell, `{ sharedFormula: 'B1' }` on the others). xlvane writes the formula text and the cached result you give; it does not calculate formulas.
|
|
106
106
|
- Styles: font (name, size, bold, italic, underline, strike, colour, superscript and subscript, family, scheme, charset, outline, shadow), fill (solid colour, pattern, or linear and path gradient), borders (top, right, bottom, left, diagonal), alignment (horizontal, vertical, wrap, shrink to fit, indent, rotation, reading order), cell protection (`locked`, `hidden`) and number format. Identical styles are stored once. `sheet.style(range, style)` merges a style into every cell of a range.
|
|
107
107
|
- Layout: column widths and hidden columns, row heights and hidden rows, outline levels of rows and columns (`row(n, { outlineLevel: 1, collapsed })`, `column('B', { outlineLevel: 1 })`), merged ranges, frozen rows and columns, autofilter, hidden and very hidden sheets. `sheet.properties({ defaultRowHeight, outlineLevelRow, outlineLevelCol, summaryBelow, summaryRight })` sets the sheet's format properties.
|
|
108
|
-
- Workbook: `workbook.views([{ x, y, width, height, firstSheet, activeTab, visibility }])` sets the workbook windows and `workbook.calculation({ fullCalcOnLoad: true })` asks applications to recalculate when the file is opened.
|
|
108
|
+
- Workbook: `workbook.views([{ x, y, width, height, firstSheet, activeTab, visibility }])` sets the workbook windows (`activeTab` and `firstSheet` are checked against the sheets when the workbook is written) and `workbook.calculation({ fullCalcOnLoad: true })` asks applications to recalculate when the file is opened. `addSheet(name, { sheetId })` sets the sheet's id in the file (1 to 65534, unique; other sheets get the lowest unused ids), and reading gives `sheet.sheetId`.
|
|
109
109
|
- Writer options: `writeWorkbook(workbook, { sharedStrings: false })` writes text inline instead of in a shared string table; `{ compressionLevel: 0 }` (0–9, default 6) stores or compresses the parts. The same options work for `writeWorkbookFile` and, with `compressionLevel`, `writeWorkbookStream`.
|
|
110
110
|
- Invalid input is rejected when it is set, with an `XlvError` saying what and where, for example `XLV_E_INVALID_SHEET_NAME` or `XLV_E_INVALID_STYLE` with the allowed values.
|
|
111
111
|
- The output is deterministic: the same workbook always gives the same bytes. The exception is a protection password (`protect({ password })`), whose verifier gets a random salt; pass a fixed salt through `hashPassword` for identical bytes. The test suite opens written files that use all of these features in LibreOffice and checks the values, styles and layout it sees.
|
|
@@ -151,7 +151,7 @@ console.log(read.hyperlinks, read.notes, read.cell('B2')?.note?.text, read.tabCo
|
|
|
151
151
|
|
|
152
152
|
- **Hyperlinks:** `link(range, { url | location, tooltip?, display? })`. A `url` (web page, `mailto:`, file) is stored as an external relationship of the sheet; a `location` (a place in the workbook) is stored without one. The cell text is set with `set`. Reading gives `sheet.hyperlinks` and `cell.hyperlink`; xlvane never opens a target, and `XLV_W_UNUSUAL_HYPERLINK` reports targets other than http(s) or mailto.
|
|
153
153
|
- **Notes (comments):** `note(cell, text | { text | runs, author?, box? })`; `box` sets the note box: `margins` in millimetres, `autoMargins`, `locked`, `lockText`, `anchor` (`'absolute'`, `'oneCell'`, `'twoCell'`); reading gives the same as `note.box`. The cell needs no value. Notes are written hidden, as spreadsheet applications show them when the pointer rests on the cell. Reading gives `sheet.notes` and `cell.note` (`text`, `author`, and `runs` for rich text). Threaded comments of current Excel versions are not read; their placeholder notes are, with `XLV_W_THREADED_COMMENTS`.
|
|
154
|
-
- **Tab colour and view:** `tabColor(color)`, and `view({ zoom, zoomScaleNormal, showGridLines, showRowColHeaders, showRuler, rightToLeft, layout, split, topLeftCell, activeCell })
|
|
154
|
+
- **Tab colour and view:** `tabColor(color)`, and `view({ zoom, zoomScaleNormal, showGridLines, showRowColHeaders, showRuler, rightToLeft, layout, split, topLeftCell, activeCell })`; a split window takes `split: { x, y, topLeftCell }` in points, where `topLeftCell` is the first cell shown in the bottom-right pane. Reading gives `sheet.tabColor`, `sheet.view`, `sheet.properties`, `workbook.views` and `workbook.calculation`.
|
|
155
155
|
- **Streaming:** `writeWorkbookStream` takes `hyperlinks` and `notes` per row (`{ values, hyperlinks: [...], notes: [...] }`, by column position) and `tabColor`/`view` per sheet. `openWorkbookStream` sets `cell.note` on the rows it returns and lists a sheet's notes with `notes(sheet)`; it does not set `cell.hyperlink`.
|
|
156
156
|
- `editCells` and `appendRows` keep existing links and notes but cannot add new ones yet.
|
|
157
157
|
|
|
@@ -293,10 +293,10 @@ const { bytes: shorter } = deleteRows(wider, { sheet: 'Orders', at: 10, count: 3
|
|
|
293
293
|
```
|
|
294
294
|
|
|
295
295
|
- Like `editCells`, they change an existing file in place and keep every other part as it was.
|
|
296
|
-
- References follow the rows as in a spreadsheet application: formulas on every sheet, merged cells, hyperlinks, notes, the autofilter, conditional formats, data validation, page breaks and defined names. A range grows when rows are inserted inside it and shrinks when some of its rows are deleted; a reference whose cells are all deleted becomes `#REF!`. The rules are in docs/facts/ref-adjust.md (observed in LibreOffice; not yet checked against Excel).
|
|
296
|
+
- References follow the rows as in a spreadsheet application: formulas on every sheet, merged cells, hyperlinks, notes, the autofilter, conditional formats (with their thresholds), data validation, page breaks and defined names. A range grows when rows are inserted inside it and shrinks when some of its rows are deleted; a reference whose cells are all deleted becomes `#REF!`. The rules are in docs/facts/ref-adjust.md (observed in LibreOffice; not yet checked against Excel).
|
|
297
297
|
- Tables move, grow and shrink with their rows; deleting a table's header row, totals row or all of its data rows is refused.
|
|
298
298
|
- Pictures move with their rows. Drawings with charts, shapes or form controls, a deletion that would cut a picture, parts xlvane cannot rewrite (charts or pivot tables that may refer to the sheet), and formulas xlvane cannot rewrite safely (for example 3-D references such as `Jan:Mar!A1` that include the sheet) are refused with `XLV_E_NOT_SUPPORTED`. Data that would be pushed past row 1048576 gives `XLV_E_LIMIT_EXCEEDED`.
|
|
299
|
-
-
|
|
299
|
+
- Conditional formats and data validations of the [MS-XLSX] extension (extended data bars, the icon sets `3Stars`, `3Triangles`, `5Boxes` and `NoIcons`, and rules written by Excel) move with the rows too, and so do thresholds that refer to cells (`{ type: 'formula', value: '$C$12' }`). Other extended content that refers to cells, such as sparklines or slicers, is refused.
|
|
300
300
|
- Sheet views (selection, frozen panes) are not changed.
|
|
301
301
|
- `adjustFormula` and `adjustRange` apply the same rules to formula text you hold yourself.
|
|
302
302
|
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { a as appendRows, c as fromCSV, d as fromJSON, f as pickSheet, h as toJSON, l as inferValue, n as insertRows, o as editCells, p as readTable, s as diff, t as deleteRows, u as toCSV } from "./rows-
|
|
4
|
-
import { i as readInput } from "./node-files-
|
|
2
|
+
import { Bt as suggest, En as XlvError, _ as isoDate, b as readWorkbook, g as inspect, ln as parseRange } from "./options-CwSp2pA4.js";
|
|
3
|
+
import { a as appendRows, c as fromCSV, d as fromJSON, f as pickSheet, h as toJSON, l as inferValue, n as insertRows, o as editCells, p as readTable, s as diff, t as deleteRows, u as toCSV } from "./rows-DKwlr0rg.js";
|
|
4
|
+
import { i as readInput } from "./node-files-B0iqSJIJ.js";
|
|
5
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
6
6
|
import { chmod, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
7
7
|
import process from "node:process";
|
|
8
|
-
import {
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
9
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
10
|
+
// src/cli/node-util.ts
|
|
11
|
+
/** The `node:util` module. */
|
|
12
|
+
const nodeUtil = createRequire(import.meta.url)("node:util");
|
|
10
13
|
// src/cli/args.ts
|
|
11
14
|
/** Options every command accepts. */
|
|
12
15
|
const GLOBAL_OPTIONS = {
|
|
@@ -64,7 +67,7 @@ function parseCommandArgs(spec, args) {
|
|
|
64
67
|
...o.short ? { short: o.short } : {},
|
|
65
68
|
...o.multiple ? { multiple: true } : {}
|
|
66
69
|
};
|
|
67
|
-
const { tokens } = parseArgs({
|
|
70
|
+
const { tokens } = nodeUtil.parseArgs({
|
|
68
71
|
args: [...args],
|
|
69
72
|
options: config,
|
|
70
73
|
strict: false,
|
|
@@ -166,6 +169,259 @@ function headerOption(args, command) {
|
|
|
166
169
|
option: "--header"
|
|
167
170
|
});
|
|
168
171
|
}
|
|
172
|
+
// src/cli/east-asian-width.ts
|
|
173
|
+
/**
|
|
174
|
+
* Code points whose East_Asian_Width is Wide (W) or Fullwidth (F), including the unassigned code
|
|
175
|
+
* points that default to W, as sorted pairs of first and last code point. Unicode 17.0.0.
|
|
176
|
+
*/
|
|
177
|
+
const EAST_ASIAN_WIDE = [
|
|
178
|
+
4352,
|
|
179
|
+
4447,
|
|
180
|
+
8986,
|
|
181
|
+
8987,
|
|
182
|
+
9001,
|
|
183
|
+
9002,
|
|
184
|
+
9193,
|
|
185
|
+
9196,
|
|
186
|
+
9200,
|
|
187
|
+
9200,
|
|
188
|
+
9203,
|
|
189
|
+
9203,
|
|
190
|
+
9725,
|
|
191
|
+
9726,
|
|
192
|
+
9748,
|
|
193
|
+
9749,
|
|
194
|
+
9776,
|
|
195
|
+
9783,
|
|
196
|
+
9800,
|
|
197
|
+
9811,
|
|
198
|
+
9855,
|
|
199
|
+
9855,
|
|
200
|
+
9866,
|
|
201
|
+
9871,
|
|
202
|
+
9875,
|
|
203
|
+
9875,
|
|
204
|
+
9889,
|
|
205
|
+
9889,
|
|
206
|
+
9898,
|
|
207
|
+
9899,
|
|
208
|
+
9917,
|
|
209
|
+
9918,
|
|
210
|
+
9924,
|
|
211
|
+
9925,
|
|
212
|
+
9934,
|
|
213
|
+
9934,
|
|
214
|
+
9940,
|
|
215
|
+
9940,
|
|
216
|
+
9962,
|
|
217
|
+
9962,
|
|
218
|
+
9970,
|
|
219
|
+
9971,
|
|
220
|
+
9973,
|
|
221
|
+
9973,
|
|
222
|
+
9978,
|
|
223
|
+
9978,
|
|
224
|
+
9981,
|
|
225
|
+
9981,
|
|
226
|
+
9989,
|
|
227
|
+
9989,
|
|
228
|
+
9994,
|
|
229
|
+
9995,
|
|
230
|
+
10024,
|
|
231
|
+
10024,
|
|
232
|
+
10060,
|
|
233
|
+
10060,
|
|
234
|
+
10062,
|
|
235
|
+
10062,
|
|
236
|
+
10067,
|
|
237
|
+
10069,
|
|
238
|
+
10071,
|
|
239
|
+
10071,
|
|
240
|
+
10133,
|
|
241
|
+
10135,
|
|
242
|
+
10160,
|
|
243
|
+
10160,
|
|
244
|
+
10175,
|
|
245
|
+
10175,
|
|
246
|
+
11035,
|
|
247
|
+
11036,
|
|
248
|
+
11088,
|
|
249
|
+
11088,
|
|
250
|
+
11093,
|
|
251
|
+
11093,
|
|
252
|
+
11904,
|
|
253
|
+
11929,
|
|
254
|
+
11931,
|
|
255
|
+
12019,
|
|
256
|
+
12032,
|
|
257
|
+
12245,
|
|
258
|
+
12272,
|
|
259
|
+
12350,
|
|
260
|
+
12353,
|
|
261
|
+
12438,
|
|
262
|
+
12441,
|
|
263
|
+
12543,
|
|
264
|
+
12549,
|
|
265
|
+
12591,
|
|
266
|
+
12593,
|
|
267
|
+
12686,
|
|
268
|
+
12688,
|
|
269
|
+
12773,
|
|
270
|
+
12783,
|
|
271
|
+
12830,
|
|
272
|
+
12832,
|
|
273
|
+
12871,
|
|
274
|
+
12880,
|
|
275
|
+
42124,
|
|
276
|
+
42128,
|
|
277
|
+
42182,
|
|
278
|
+
43360,
|
|
279
|
+
43388,
|
|
280
|
+
44032,
|
|
281
|
+
55203,
|
|
282
|
+
63744,
|
|
283
|
+
64255,
|
|
284
|
+
65040,
|
|
285
|
+
65049,
|
|
286
|
+
65072,
|
|
287
|
+
65106,
|
|
288
|
+
65108,
|
|
289
|
+
65126,
|
|
290
|
+
65128,
|
|
291
|
+
65131,
|
|
292
|
+
65281,
|
|
293
|
+
65376,
|
|
294
|
+
65504,
|
|
295
|
+
65510,
|
|
296
|
+
94176,
|
|
297
|
+
94180,
|
|
298
|
+
94192,
|
|
299
|
+
94198,
|
|
300
|
+
94208,
|
|
301
|
+
101589,
|
|
302
|
+
101631,
|
|
303
|
+
101662,
|
|
304
|
+
101760,
|
|
305
|
+
101874,
|
|
306
|
+
110576,
|
|
307
|
+
110579,
|
|
308
|
+
110581,
|
|
309
|
+
110587,
|
|
310
|
+
110589,
|
|
311
|
+
110590,
|
|
312
|
+
110592,
|
|
313
|
+
110882,
|
|
314
|
+
110898,
|
|
315
|
+
110898,
|
|
316
|
+
110928,
|
|
317
|
+
110930,
|
|
318
|
+
110933,
|
|
319
|
+
110933,
|
|
320
|
+
110948,
|
|
321
|
+
110951,
|
|
322
|
+
110960,
|
|
323
|
+
111355,
|
|
324
|
+
119552,
|
|
325
|
+
119638,
|
|
326
|
+
119648,
|
|
327
|
+
119670,
|
|
328
|
+
126980,
|
|
329
|
+
126980,
|
|
330
|
+
127183,
|
|
331
|
+
127183,
|
|
332
|
+
127374,
|
|
333
|
+
127374,
|
|
334
|
+
127377,
|
|
335
|
+
127386,
|
|
336
|
+
127488,
|
|
337
|
+
127490,
|
|
338
|
+
127504,
|
|
339
|
+
127547,
|
|
340
|
+
127552,
|
|
341
|
+
127560,
|
|
342
|
+
127568,
|
|
343
|
+
127569,
|
|
344
|
+
127584,
|
|
345
|
+
127589,
|
|
346
|
+
127744,
|
|
347
|
+
127776,
|
|
348
|
+
127789,
|
|
349
|
+
127797,
|
|
350
|
+
127799,
|
|
351
|
+
127868,
|
|
352
|
+
127870,
|
|
353
|
+
127891,
|
|
354
|
+
127904,
|
|
355
|
+
127946,
|
|
356
|
+
127951,
|
|
357
|
+
127955,
|
|
358
|
+
127968,
|
|
359
|
+
127984,
|
|
360
|
+
127988,
|
|
361
|
+
127988,
|
|
362
|
+
127992,
|
|
363
|
+
128062,
|
|
364
|
+
128064,
|
|
365
|
+
128064,
|
|
366
|
+
128066,
|
|
367
|
+
128252,
|
|
368
|
+
128255,
|
|
369
|
+
128317,
|
|
370
|
+
128331,
|
|
371
|
+
128334,
|
|
372
|
+
128336,
|
|
373
|
+
128359,
|
|
374
|
+
128378,
|
|
375
|
+
128378,
|
|
376
|
+
128405,
|
|
377
|
+
128406,
|
|
378
|
+
128420,
|
|
379
|
+
128420,
|
|
380
|
+
128507,
|
|
381
|
+
128591,
|
|
382
|
+
128640,
|
|
383
|
+
128709,
|
|
384
|
+
128716,
|
|
385
|
+
128716,
|
|
386
|
+
128720,
|
|
387
|
+
128722,
|
|
388
|
+
128725,
|
|
389
|
+
128728,
|
|
390
|
+
128732,
|
|
391
|
+
128735,
|
|
392
|
+
128747,
|
|
393
|
+
128748,
|
|
394
|
+
128756,
|
|
395
|
+
128764,
|
|
396
|
+
128992,
|
|
397
|
+
129003,
|
|
398
|
+
129008,
|
|
399
|
+
129008,
|
|
400
|
+
129292,
|
|
401
|
+
129338,
|
|
402
|
+
129340,
|
|
403
|
+
129349,
|
|
404
|
+
129351,
|
|
405
|
+
129535,
|
|
406
|
+
129648,
|
|
407
|
+
129660,
|
|
408
|
+
129664,
|
|
409
|
+
129674,
|
|
410
|
+
129678,
|
|
411
|
+
129734,
|
|
412
|
+
129736,
|
|
413
|
+
129736,
|
|
414
|
+
129741,
|
|
415
|
+
129756,
|
|
416
|
+
129759,
|
|
417
|
+
129770,
|
|
418
|
+
129775,
|
|
419
|
+
129784,
|
|
420
|
+
131072,
|
|
421
|
+
196605,
|
|
422
|
+
196608,
|
|
423
|
+
262141
|
|
424
|
+
];
|
|
169
425
|
// src/cli/output.ts
|
|
170
426
|
/**
|
|
171
427
|
* Whether to colour a stream. `util.styleText` respects NO_COLOR, NODE_DISABLE_COLORS,
|
|
@@ -208,7 +464,7 @@ var Output = class {
|
|
|
208
464
|
this.width = width;
|
|
209
465
|
}
|
|
210
466
|
style(format, text) {
|
|
211
|
-
return this.color && text !== "" ? styleText(format, text, { validateStream: false }) : text;
|
|
467
|
+
return this.color && text !== "" ? nodeUtil.styleText(format, text, { validateStream: false }) : text;
|
|
212
468
|
}
|
|
213
469
|
bold(text) {
|
|
214
470
|
return this.style("bold", text);
|
|
@@ -230,11 +486,11 @@ var Output = class {
|
|
|
230
486
|
}
|
|
231
487
|
/**
|
|
232
488
|
* An aligned table. Columns are cut with "…" to fit `width`; the widest columns shrink first.
|
|
233
|
-
*
|
|
489
|
+
* Widths are display columns ({@link displayWidth}), so CJK text and emoji stay aligned.
|
|
234
490
|
*/
|
|
235
491
|
table(headers, rows, indent = "", align = []) {
|
|
236
492
|
const count = headers.length;
|
|
237
|
-
const widths = headers.map((h, i) => Math.max(h
|
|
493
|
+
const widths = headers.map((h, i) => Math.max(displayWidth(oneLine(h)), ...rows.map((r) => displayWidth(oneLine(r[i] ?? "")))));
|
|
238
494
|
const gap = 2;
|
|
239
495
|
const available = Math.max(count * 4, this.width - indent.length - gap * (count - 1));
|
|
240
496
|
let total = widths.reduce((a, b) => a + b, 0);
|
|
@@ -248,7 +504,8 @@ var Output = class {
|
|
|
248
504
|
const line = (cells, head) => indent + cells.map((c, i) => {
|
|
249
505
|
const w = widths[i] ?? 0;
|
|
250
506
|
const text = fit(oneLine(c), w);
|
|
251
|
-
const
|
|
507
|
+
const pad = " ".repeat(Math.max(0, w - displayWidth(text)));
|
|
508
|
+
const padded = align[i] === "right" && !head ? pad + text : i === count - 1 ? text : text + pad;
|
|
252
509
|
return head ? this.bold(padded) : padded;
|
|
253
510
|
}).join(" ".repeat(gap)).trimEnd();
|
|
254
511
|
return [line(headers, true), ...rows.map((r) => line(r, false))].join("\n");
|
|
@@ -300,8 +557,70 @@ function terminalSafe(text, keepStyles) {
|
|
|
300
557
|
}
|
|
301
558
|
return start === 0 ? text : result + text.slice(start);
|
|
302
559
|
}
|
|
560
|
+
/** Cuts text to `width` display columns with "…", between grapheme clusters. */
|
|
303
561
|
function fit(text, width) {
|
|
304
|
-
|
|
562
|
+
if (displayWidth(text) <= width) return text;
|
|
563
|
+
let result = "";
|
|
564
|
+
let used = 0;
|
|
565
|
+
for (const part of graphemes(text)) {
|
|
566
|
+
const w = displayWidth(part);
|
|
567
|
+
if (used + w > width - 1) break;
|
|
568
|
+
result += part;
|
|
569
|
+
used += w;
|
|
570
|
+
}
|
|
571
|
+
return `${result}…`;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Grapheme clusters of a text (Intl.Segmenter), or its code points when the Node.js build has no
|
|
575
|
+
* Intl support, so that cutting never splits a surrogate pair or a letter from its accent.
|
|
576
|
+
*/
|
|
577
|
+
function graphemes(text) {
|
|
578
|
+
if (segmenter === void 0) return Array.from(text);
|
|
579
|
+
return Array.from(segmenter.segment(text), (s) => s.segment);
|
|
580
|
+
}
|
|
581
|
+
const segmenter = typeof Intl === "object" && typeof Intl.Segmenter === "function" ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : void 0;
|
|
582
|
+
/**
|
|
583
|
+
* The number of terminal columns a text takes, counted as Node.js counts them for its own output
|
|
584
|
+
* (src/node_i18n.cc GetColumnWidth, v22.23.4; F-UNICODE-01): East Asian Wide and Fullwidth
|
|
585
|
+
* characters (Unicode East_Asian_Width W and F) and emoji with Emoji_Presentation take two
|
|
586
|
+
* columns; control and format characters (except the soft hyphen), nonspacing and enclosing marks
|
|
587
|
+
* and emoji modifiers that are not Wide take none; every other character, including East Asian
|
|
588
|
+
* Ambiguous ones, takes one. Each code point of an emoji sequence is counted, as Node.js does by
|
|
589
|
+
* default, so a terminal that draws the sequence as one picture shows it narrower. Colour codes
|
|
590
|
+
* (`ESC [ … m`, as `Output` writes them) take no columns, as Node.js strips them first.
|
|
591
|
+
*/
|
|
592
|
+
function displayWidth(text) {
|
|
593
|
+
if (text.includes("\x1B")) text = text.replace(/\u001b\[[0-9;]*m/g, "");
|
|
594
|
+
let width = 0;
|
|
595
|
+
for (let i = 0; i < text.length; i++) {
|
|
596
|
+
const code = text.charCodeAt(i);
|
|
597
|
+
if (code >= 32 && code < 127) width++;
|
|
598
|
+
else {
|
|
599
|
+
for (const ch of text.slice(i)) width += codePointWidth(ch.codePointAt(0) ?? 0, ch);
|
|
600
|
+
break;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return width;
|
|
604
|
+
}
|
|
605
|
+
function codePointWidth(code, ch) {
|
|
606
|
+
if (isEastAsianWide(code) || EMOJI_PRESENTATION.test(ch)) return 2;
|
|
607
|
+
if (code !== 173 && ZERO_WIDTH.test(ch)) return 0;
|
|
608
|
+
return 1;
|
|
609
|
+
}
|
|
610
|
+
const EMOJI_PRESENTATION = /^\p{Emoji_Presentation}$/u;
|
|
611
|
+
const ZERO_WIDTH = /^[\p{Cc}\p{Cf}\p{Me}\p{Mn}\p{Emoji_Modifier}]$/u;
|
|
612
|
+
/** Binary search in the sorted [first, last, first, last, …] ranges of EAST_ASIAN_WIDE. */
|
|
613
|
+
function isEastAsianWide(code) {
|
|
614
|
+
if (code < 4352) return false;
|
|
615
|
+
let lo = 0;
|
|
616
|
+
let hi = EAST_ASIAN_WIDE.length / 2 - 1;
|
|
617
|
+
while (lo <= hi) {
|
|
618
|
+
const mid = lo + hi >> 1;
|
|
619
|
+
if (code < EAST_ASIAN_WIDE[mid * 2]) hi = mid - 1;
|
|
620
|
+
else if (code > EAST_ASIAN_WIDE[mid * 2 + 1]) lo = mid + 1;
|
|
621
|
+
else return true;
|
|
622
|
+
}
|
|
623
|
+
return false;
|
|
305
624
|
}
|
|
306
625
|
/** Quotes an argument for a POSIX shell when needed, so "Try:" commands can be copied. */
|
|
307
626
|
function quoteArg(arg) {
|
|
@@ -333,12 +652,12 @@ function humanSize(bytes) {
|
|
|
333
652
|
if (bytes < 1e6) return `${(bytes / 1e3).toFixed(1)} kB`;
|
|
334
653
|
return `${(bytes / 1e6).toFixed(1)} MB`;
|
|
335
654
|
}
|
|
336
|
-
/** Wraps a paragraph at `width` columns; lines after the first start with `indent`. */
|
|
655
|
+
/** Wraps a paragraph at `width` display columns; lines after the first start with `indent`. */
|
|
337
656
|
function wrap(text, width, indent = "", firstIndent = indent) {
|
|
338
657
|
const lines = [];
|
|
339
658
|
let line = "";
|
|
340
659
|
let prefix = firstIndent;
|
|
341
|
-
for (const word of text.split(/\s+/).filter((w) => w !== "")) if (line !== "" && prefix
|
|
660
|
+
for (const word of text.split(/\s+/).filter((w) => w !== "")) if (line !== "" && displayWidth(prefix) + displayWidth(line) + 1 + displayWidth(word) > width) {
|
|
342
661
|
lines.push(prefix + line);
|
|
343
662
|
prefix = indent;
|
|
344
663
|
line = word;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as InspectOptions, $n as verifyPassword, $t as DataValidationOperator, A as toJSON, An as Hyperlink, At as Workbook, B as FormulaResult, Bn as PrintErrors, Bt as CfValue, C as TableRow, Cn as ImageAnchorInput, Ct as Sheet, D as fromJSON, Dn as SheetImage, Dt as SheetState, E as WriteTableOptions, En as ImagePositionInput, Et as SheetProperties, F as CellInput, Fn as PageOrder, Ft as TableDefinitionColumn, G as SheetPropertiesOptions, Gn as SheetProtectionOptions, Gt as ConditionalFormatRule, H as NewSheet, Hn as PrintTitles, Ht as CfValueType, I as ColumnOptions, In as PageOrientation, It as TableInput, J as WriteWorkbookOptions, Jn as HashPasswordOptions, Jt as DataBarAxisPosition, K as SheetViewOptions, Kn as WorkbookProtection, Kt as ConditionalFormatRuleInput, L as CreateWorkbookOptions, Ln as PageSetup, Lt as TableStyleOptions, M as StandardSchemaV1, Mn as HeaderFooter, Mt as WorkbookView, N as AddSheetOptions, Nn as PageBreaks, Nt as TableColumnInput, O as readTable, On as WorkbookImage, Ot as SheetView, P as CalculationOptions, Pn as PageMargins, Pt as TableDefinition, Q as InspectDefinedName, Qn as legacyPasswordHash, Qt as DataValidationImeMode, R as ERROR_VALUES, Rn as PageSetupOptions, Rt as TotalsRowFunction, S as TableResult, Sn as ImageAnchor, St as RowInfo, T as ToJSONOptions, Tn as ImageOptions, Tt as SheetLayout, U as NewWorkbook, Un as SheetProtection, Ut as ConditionalFormat, V as FreezeOptions, Vn as PrintOptions, Vt as CfValueInput, W as RowOptions, Wn as SheetProtectionFlags, Wt as ConditionalFormatOperator, X as writeWorkbook, Xn as PasswordVerifier, Xt as DataValidation, Y as createWorkbook, Yn as PasswordHash, Yt as DataBarDirection, Z as InspectColumn, Zn as hashPassword, Zt as DataValidationErrorStyle, _ as JsonTable, _n as ReadingOrder, _r as DefinedNameOptions, _t as DateSystem, a as WriteWorkbookStreamOptions, an as BorderEdge, ar as XlvDetails, at as ReadOptions, b as TableColumnSpec, bn as VerticalAlignment, bt as FrozenPanes, c as OpenWorkbookStreamOptions, cn as CellStyle, cr as XlvErrorInit, ct as NoteBox, d as StreamRow, dn as FontScheme, dr as XlvWarning, dt as NoteMargins, en as DataValidationRule, er as ShaAlgorithm, et as InspectReport, f as StreamSheetInfo, fn as FontStyle, fr as XlvWarningCode, ft as Cell, g as readTableStream, gn as ProtectionStyle, gr as DefinedName, gt as Conformance, h as openWorkbookStream, hn as PatternType, hr as ReadLimits, ht as ColumnInfo, i as WriteTableStreamOptions, in as AlignmentStyle, ir as XlvDetailValue, it as inspect, j as writeTable, jn as HyperlinkTarget, jt as WorkbookFormat, k as readTableAsync, kn as imageFormat, kt as SplitPanes, l as ReadTableStreamOptions, ln as Color, lr as XlvErrorJSON, lt as NoteBoxInput, m as WorkbookStream, mn as HorizontalAlignment, mr as DEFAULT_READ_LIMITS, mt as CellValue, n as StreamRowInput, nn as IconSetType, nr as ERROR_CODES, nt as InspectTypeCounts, o as writeTableStream, on as BorderLineStyle, or as XlvError, ot as readWorkbook, p as TableStreamItem, pn as GradientFill, pr as isXlvError, pt as CellType, q as WorkbookViewOptions, qn as WorkbookProtectionOptions, qt as ConditionalFormatType, r as StreamSheetSpec, rn as TimePeriod, rr as WARNING_CODES, rt as InspectValue, s as writeWorkbookStream, sn as BorderStyle, sr as XlvErrorCode, st as Note, t as StreamDefinedName, tn as DataValidationType, tr as WorkbookProperties, tt as InspectSheet, u as STREAM_LIMIT_DEFAULTS, un as FillStyle, ur as XlvLocation, ut as NoteInput, v as ReadTableOptions, vn as UnderlineStyle, vt as Formula, w as TableValue, wn as ImageFormat, wt as SheetKind, x as TableIssue, xn as AnchorMarker, xt as RichTextRun, y as TableColumn, yn as VerticalAlignRun, yt as FormulaKind, z as ErrorValue, zn as PrintCellComments, zt as CfIcon } from "./stream-write-
|
|
1
|
+
import { $ as InspectOptions, $n as verifyPassword, $t as DataValidationOperator, A as toJSON, An as Hyperlink, At as Workbook, B as FormulaResult, Bn as PrintErrors, Bt as CfValue, C as TableRow, Cn as ImageAnchorInput, Ct as Sheet, D as fromJSON, Dn as SheetImage, Dt as SheetState, E as WriteTableOptions, En as ImagePositionInput, Et as SheetProperties, F as CellInput, Fn as PageOrder, Ft as TableDefinitionColumn, G as SheetPropertiesOptions, Gn as SheetProtectionOptions, Gt as ConditionalFormatRule, H as NewSheet, Hn as PrintTitles, Ht as CfValueType, I as ColumnOptions, In as PageOrientation, It as TableInput, J as WriteWorkbookOptions, Jn as HashPasswordOptions, Jt as DataBarAxisPosition, K as SheetViewOptions, Kn as WorkbookProtection, Kt as ConditionalFormatRuleInput, L as CreateWorkbookOptions, Ln as PageSetup, Lt as TableStyleOptions, M as StandardSchemaV1, Mn as HeaderFooter, Mt as WorkbookView, N as AddSheetOptions, Nn as PageBreaks, Nt as TableColumnInput, O as readTable, On as WorkbookImage, Ot as SheetView, P as CalculationOptions, Pn as PageMargins, Pt as TableDefinition, Q as InspectDefinedName, Qn as legacyPasswordHash, Qt as DataValidationImeMode, R as ERROR_VALUES, Rn as PageSetupOptions, Rt as TotalsRowFunction, S as TableResult, Sn as ImageAnchor, St as RowInfo, T as ToJSONOptions, Tn as ImageOptions, Tt as SheetLayout, U as NewWorkbook, Un as SheetProtection, Ut as ConditionalFormat, V as FreezeOptions, Vn as PrintOptions, Vt as CfValueInput, W as RowOptions, Wn as SheetProtectionFlags, Wt as ConditionalFormatOperator, X as writeWorkbook, Xn as PasswordVerifier, Xt as DataValidation, Y as createWorkbook, Yn as PasswordHash, Yt as DataBarDirection, Z as InspectColumn, Zn as hashPassword, Zt as DataValidationErrorStyle, _ as JsonTable, _n as ReadingOrder, _r as DefinedNameOptions, _t as DateSystem, a as WriteWorkbookStreamOptions, an as BorderEdge, ar as XlvDetails, at as ReadOptions, b as TableColumnSpec, bn as VerticalAlignment, bt as FrozenPanes, c as OpenWorkbookStreamOptions, cn as CellStyle, cr as XlvErrorInit, ct as NoteBox, d as StreamRow, dn as FontScheme, dr as XlvWarning, dt as NoteMargins, en as DataValidationRule, er as ShaAlgorithm, et as InspectReport, f as StreamSheetInfo, fn as FontStyle, fr as XlvWarningCode, ft as Cell, g as readTableStream, gn as ProtectionStyle, gr as DefinedName, gt as Conformance, h as openWorkbookStream, hn as PatternType, hr as ReadLimits, ht as ColumnInfo, i as WriteTableStreamOptions, in as AlignmentStyle, ir as XlvDetailValue, it as inspect, j as writeTable, jn as HyperlinkTarget, jt as WorkbookFormat, k as readTableAsync, kn as imageFormat, kt as SplitPanes, l as ReadTableStreamOptions, ln as Color, lr as XlvErrorJSON, lt as NoteBoxInput, m as WorkbookStream, mn as HorizontalAlignment, mr as DEFAULT_READ_LIMITS, mt as CellValue, n as StreamRowInput, nn as IconSetType, nr as ERROR_CODES, nt as InspectTypeCounts, o as writeTableStream, on as BorderLineStyle, or as XlvError, ot as readWorkbook, p as TableStreamItem, pn as GradientFill, pr as isXlvError, pt as CellType, q as WorkbookViewOptions, qn as WorkbookProtectionOptions, qt as ConditionalFormatType, r as StreamSheetSpec, rn as TimePeriod, rr as WARNING_CODES, rt as InspectValue, s as writeWorkbookStream, sn as BorderStyle, sr as XlvErrorCode, st as Note, t as StreamDefinedName, tn as DataValidationType, tr as WorkbookProperties, tt as InspectSheet, u as STREAM_LIMIT_DEFAULTS, un as FillStyle, ur as XlvLocation, ut as NoteInput, v as ReadTableOptions, vn as UnderlineStyle, vt as Formula, w as TableValue, wn as ImageFormat, wt as SheetKind, x as TableIssue, xn as AnchorMarker, xt as RichTextRun, y as TableColumn, yn as VerticalAlignRun, yt as FormulaKind, z as ErrorValue, zn as PrintCellComments, zt as CfIcon } from "./stream-write-GJXORYQ2.js";
|
|
2
2
|
/**
|
|
3
3
|
* Options for {@link toCSV}.
|
|
4
4
|
*
|
|
@@ -392,15 +392,14 @@ interface DeleteRowsOptions extends EditOptions {
|
|
|
392
392
|
* Inserts empty rows into a sheet of an existing XLSX file and returns the new file. Rows below
|
|
393
393
|
* move down, and every reference follows them as in a spreadsheet application: formulas on all
|
|
394
394
|
* sheets (ranges that the new rows fall into grow), merged cells, hyperlinks, notes, the
|
|
395
|
-
* autofilter, conditional formats
|
|
396
|
-
*
|
|
397
|
-
*
|
|
395
|
+
* autofilter, conditional formats (also those of the [MS-XLSX] extension, and thresholds that
|
|
396
|
+
* refer to cells), data validation (also of the extension), page breaks, defined names, tables
|
|
397
|
+
* (which grow when rows are inserted inside them) and pictures placed on the sheet. Every other
|
|
398
|
+
* part of the file stays exactly as it was.
|
|
398
399
|
*
|
|
399
400
|
* Refused with `XLV_E_NOT_SUPPORTED`, leaving the file unchanged: a drawing that holds charts,
|
|
400
401
|
* shapes or anything besides pictures; embedded objects, form controls, scenarios, cell watches,
|
|
401
|
-
* custom sheet views, extended content that refers to cells (
|
|
402
|
-
* including the extended data bar settings and the icon sets `3Stars`, `3Triangles`, `5Boxes`, `NoIcons`
|
|
403
|
-
* that xlvane itself writes) and
|
|
402
|
+
* custom sheet views, other extended content that refers to cells (sparklines, slicers) and
|
|
404
403
|
* other related parts xlvane does not know; charts or pivot tables anywhere in the workbook that
|
|
405
404
|
* may refer to the sheet; data tables; an array formula the change would split; and formulas it
|
|
406
405
|
* cannot rewrite safely (docs/facts/ref-adjust.md).
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as appendRows, c as fromCSV, d as fromJSON, g as writeTable, h as toJSON, i as adjustRange, m as readTableAsync, n as insertRows, o as editCells, p as readTable, r as adjustFormula, s as diff, t as deleteRows, u as toCSV } from "./rows-
|
|
3
|
-
import { a as readTableStream, i as openWorkbookStream, n as writeWorkbookStream, r as STREAM_LIMIT_DEFAULTS, t as writeTableStream } from "./stream-write-
|
|
1
|
+
import { Dn as isXlvError, En as XlvError, Gt as legacyPasswordHash, Kt as verifyPassword, Rt as DEFAULT_READ_LIMITS, Tn as WARNING_CODES, Wt as hashPassword, Zt as imageFormat, b as readWorkbook, c as NewSheet, f as createWorkbook, g as inspect, l as NewWorkbook, m as writeWorkbook, s as ERROR_VALUES, wn as ERROR_CODES, z as shiftFormula } from "./options-CwSp2pA4.js";
|
|
2
|
+
import { a as appendRows, c as fromCSV, d as fromJSON, g as writeTable, h as toJSON, i as adjustRange, m as readTableAsync, n as insertRows, o as editCells, p as readTable, r as adjustFormula, s as diff, t as deleteRows, u as toCSV } from "./rows-DKwlr0rg.js";
|
|
3
|
+
import { a as readTableStream, i as openWorkbookStream, n as writeWorkbookStream, r as STREAM_LIMIT_DEFAULTS, t as writeTableStream } from "./stream-write-BKppyMz0.js";
|
|
4
4
|
export { DEFAULT_READ_LIMITS, ERROR_CODES, ERROR_VALUES, NewSheet, NewWorkbook, STREAM_LIMIT_DEFAULTS, WARNING_CODES, XlvError, adjustFormula, adjustRange, appendRows, createWorkbook, deleteRows, diff, editCells, fromCSV, fromJSON, hashPassword, imageFormat, insertRows, inspect, isXlvError, legacyPasswordHash, openWorkbookStream, readTable, readTableAsync, readTableStream, readWorkbook, shiftFormula, toCSV, toJSON, verifyPassword, writeTable, writeTableStream, writeWorkbook, writeWorkbookStream };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { En as XlvError, zt as resolveLimits } from "./options-CwSp2pA4.js";
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
// src/util/node-files.ts
|
|
4
4
|
/** The path as shown in messages. */
|
package/dist/node.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as InspectOptions, At as Workbook, J as WriteWorkbookOptions, U as NewWorkbook, a as WriteWorkbookStreamOptions, at as ReadOptions, c as OpenWorkbookStreamOptions, et as InspectReport, m as WorkbookStream } from "./stream-write-
|
|
1
|
+
import { $ as InspectOptions, At as Workbook, J as WriteWorkbookOptions, U as NewWorkbook, a as WriteWorkbookStreamOptions, at as ReadOptions, c as OpenWorkbookStreamOptions, et as InspectReport, m as WorkbookStream } from "./stream-write-GJXORYQ2.js";
|
|
2
2
|
/**
|
|
3
3
|
* Reads an XLSX file from disk. Node.js only; in other runtimes pass the bytes to
|
|
4
4
|
* `readWorkbook` from `xlvane`. The file size is checked against `limits.maxInputBytes`
|
package/dist/node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as readInput, n as describePath, r as fileError, t as checkFile } from "./node-files-
|
|
3
|
-
import { i as openWorkbookStream, n as writeWorkbookStream, r as STREAM_LIMIT_DEFAULTS } from "./stream-write-
|
|
1
|
+
import { En as XlvError, b as readWorkbook, g as inspect, m as writeWorkbook, zt as resolveLimits } from "./options-CwSp2pA4.js";
|
|
2
|
+
import { i as readInput, n as describePath, r as fileError, t as checkFile } from "./node-files-B0iqSJIJ.js";
|
|
3
|
+
import { i as openWorkbookStream, n as writeWorkbookStream, r as STREAM_LIMIT_DEFAULTS } from "./stream-write-BKppyMz0.js";
|
|
4
4
|
import { openAsBlob } from "node:fs";
|
|
5
5
|
import { open, unlink, writeFile } from "node:fs/promises";
|
|
6
6
|
// src/node.ts
|