@xlsxflow/core 1.1.6 → 1.1.7
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 +10 -0
- package/README.md +12 -4
- package/dist/index.cjs +11 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +11 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.7
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Migration guides from [ExcelJS](https://github.com/xlsxflow/xlsxflow/blob/main/docs/migrating-from-exceljs.md) and [SheetJS](https://github.com/xlsxflow/xlsxflow/blob/main/docs/migrating-from-sheetjs.md), and [recipes](https://github.com/xlsxflow/xlsxflow/blob/main/examples/README.md) for streaming downloads, uploads, database exports and browser downloads. CI runs the recipes on every push.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- On a runtime without `CompressionStream` or `DecompressionStream` for `deflate-raw` (Chrome before 103, Firefox before 113, Safari before 16.4), reading and writing throw an error naming the minimum versions instead of a bare `ReferenceError` or `TypeError`.
|
|
12
|
+
|
|
3
13
|
## 1.1.6
|
|
4
14
|
|
|
5
15
|
### Changed
|
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://opensource.org/licenses/MIT)
|
|
10
10
|
[](https://github.com/xlsxflow/xlsxflow/actions/workflows/ci.yml)
|
|
11
11
|
[](https://scorecard.dev/viewer/?uri=github.com/xlsxflow/xlsxflow)
|
|
12
|
+
[](https://www.bestpractices.dev/projects/15329)
|
|
12
13
|
|
|
13
14
|
<p>
|
|
14
15
|
<a href="#features">Features</a> •
|
|
@@ -16,6 +17,7 @@
|
|
|
16
17
|
<a href="#quick-start">Quick Start</a> •
|
|
17
18
|
<a href="#styles-formulas--conditional-formats">Styles & Formulas</a> •
|
|
18
19
|
<a href="#compared-with-sheetjs-and-exceljs">Comparison</a> •
|
|
20
|
+
<a href="#recipes-and-migration-guides">Recipes</a> •
|
|
19
21
|
<a href="#benchmarks">Benchmarks</a> •
|
|
20
22
|
<a href="#free-and-pro">Free and Pro</a>
|
|
21
23
|
</p>
|
|
@@ -31,7 +33,7 @@ Rows are read and written one at a time instead of loading the whole workbook, s
|
|
|
31
33
|
|
|
32
34
|
- **No dependencies**: TypeScript on Web APIs (`ReadableStream`, `CompressionStream`, `Blob`).
|
|
33
35
|
- **Streaming**: rows are read and written one at a time, so memory stays flat as files grow (10M cells written with about 2 MB of extra heap; see [Benchmarks](#benchmarks)).
|
|
34
|
-
- **Runs anywhere with Web APIs**: tested on Node 20.12 and later, Bun, Deno, Chrome, Firefox, Safari (WebKit) and Cloudflare Workers (without `nodejs_compat`).
|
|
36
|
+
- **Runs anywhere with Web APIs**: tested on Node 20.12 and later, Bun, Deno, Chrome, Firefox, Safari (WebKit) and Cloudflare Workers (without `nodejs_compat`). Browsers need `CompressionStream` with `deflate-raw`: Chrome 103+, Firefox 113+, Safari 16.4+; older ones get an error saying so.
|
|
35
37
|
- **Read, write and edit**: stream rows out of a file, generate one on the fly, or change cells, rows, columns and sheets of an existing file while keeping everything else in it.
|
|
36
38
|
- **Styles and formulas**: fonts, fills, borders, alignment, number formats, conditional formats, validations, tables, notes, hyperlinks, autofilters, images, protection and page setup. Formulas and styles read back too.
|
|
37
39
|
- **Older and open formats**: the same reader opens Excel 97-2003 `.xls` files and OpenDocument `.ods` files, and `OdsWriter` writes `.ods`.
|
|
@@ -287,15 +289,21 @@ SheetJS reads and writes far more formats, and ExcelJS has a longer track record
|
|
|
287
289
|
October 2023). XlsxFlow focuses on `.xlsx`: streaming in flat memory, keeping everything in a file it edits,
|
|
288
290
|
and running on Web APIs alone.
|
|
289
291
|
|
|
292
|
+
## Recipes and migration guides
|
|
293
|
+
|
|
294
|
+
- [Recipes](https://github.com/xlsxflow/xlsxflow/blob/main/examples/README.md): streaming downloads from Next.js, Cloudflare Workers, Bun, Deno and Express; reading uploads; exporting a database table; an "Export to Excel" button in the browser. Each runs in CI.
|
|
295
|
+
- [Migrating from ExcelJS](https://github.com/xlsxflow/xlsxflow/blob/main/docs/migrating-from-exceljs.md) and [Migrating from SheetJS](https://github.com/xlsxflow/xlsxflow/blob/main/docs/migrating-from-sheetjs.md): each common task in both libraries, side by side, and what works differently.
|
|
296
|
+
|
|
290
297
|
## Testing
|
|
291
298
|
|
|
292
299
|
Every push and pull request runs, [in public CI](https://github.com/xlsxflow/xlsxflow/actions/workflows/ci.yml):
|
|
293
300
|
|
|
294
|
-
- the test suite (nearly 400 tests, including
|
|
295
|
-
- the README's claims, checked in Node, Bun, Deno, Chromium, Firefox, WebKit and Cloudflare Workers;
|
|
301
|
+
- the test suite (nearly 400 tests, including fuzz and property-based tests with [fast-check](https://fast-check.dev) on malformed ZIP and XML input and files saved by Excel, LibreOffice, SheetJS, ExcelJS, openpyxl and xlsx-populate) on Node 20, 22 and 24, with 96% line coverage;
|
|
302
|
+
- the README's claims, checked in Node, Bun, Deno, Chromium, Firefox, WebKit and Cloudflare Workers, and the [recipes](https://github.com/xlsxflow/xlsxflow/blob/main/examples/README.md);
|
|
303
|
+
- 10M cells written to disk and read back with Node's heap capped at 32 MB, smaller than the 34 MB file;
|
|
296
304
|
- written and edited workbooks validated against the Office Open XML schema with Microsoft's [Open XML SDK](https://github.com/dotnet/Open-XML-SDK), then opened and recalculated in LibreOffice.
|
|
297
305
|
|
|
298
|
-
[OpenSSF Scorecard](https://scorecard.dev/viewer/?uri=github.com/xlsxflow/xlsxflow) and CodeQL check the repository, and npm releases are published from CI with [provenance](https://docs.npmjs.com/generating-provenance-statements).
|
|
306
|
+
The project holds the [OpenSSF Best Practices](https://www.bestpractices.dev/projects/15329) passing badge; [OpenSSF Scorecard](https://scorecard.dev/viewer/?uri=github.com/xlsxflow/xlsxflow) and CodeQL check the repository, and npm releases are published from CI with [provenance](https://docs.npmjs.com/generating-provenance-statements).
|
|
299
307
|
|
|
300
308
|
## Benchmarks
|
|
301
309
|
|
package/dist/index.cjs
CHANGED
|
@@ -13,6 +13,15 @@ const CRC_TABLE = (() => {
|
|
|
13
13
|
function crc32(bytes) {
|
|
14
14
|
return (crc32Update(0xffffffff, bytes) ^ 0xffffffff) >>> 0;
|
|
15
15
|
}
|
|
16
|
+
// Older runtimes lack CompressionStream or its 'deflate-raw' format; say what is needed instead of a bare ReferenceError
|
|
17
|
+
function deflateRaw(kind) {
|
|
18
|
+
try {
|
|
19
|
+
return (kind === 'compress' ? new CompressionStream('deflate-raw') : new DecompressionStream('deflate-raw'));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
throw new Error(`XlsxFlow needs ${kind === 'compress' ? 'CompressionStream' : 'DecompressionStream'} with 'deflate-raw': Chrome 103+, Firefox 113+, Safari 16.4+, Node 20.12+, Deno, Bun or Cloudflare Workers`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
16
25
|
// Running CRC-32 over chunks: start at 0xffffffff, finish with (crc ^ 0xffffffff) >>> 0
|
|
17
26
|
function crc32Update(crc, bytes) {
|
|
18
27
|
for (let i = 0; i < bytes.length; i++)
|
|
@@ -58,7 +67,7 @@ class ZipStreamWriter {
|
|
|
58
67
|
// Stream data, tracking sizes and CRC32
|
|
59
68
|
let uncompressedSize = 0;
|
|
60
69
|
let crc = 0xffffffff;
|
|
61
|
-
const compressor =
|
|
70
|
+
const compressor = deflateRaw('compress');
|
|
62
71
|
const writer = compressor.writable.getWriter();
|
|
63
72
|
const reader = compressor.readable.getReader();
|
|
64
73
|
const input = inputStream.getReader();
|
|
@@ -505,7 +514,7 @@ class ZipRandomAccessParser {
|
|
|
505
514
|
}
|
|
506
515
|
const stream = await this.extractRawStream(filename);
|
|
507
516
|
const data = record.compressionMethod === 0 ? stream
|
|
508
|
-
: stream.pipeThrough(
|
|
517
|
+
: stream.pipeThrough(deflateRaw('decompress'));
|
|
509
518
|
// Node reports bad deflate data as a bare TypeError; name the entry instead
|
|
510
519
|
const inflated = data.getReader();
|
|
511
520
|
let total = 0;
|