@zip.js/zip.js 2.8.61 → 2.10.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.
@@ -33,7 +33,7 @@
33
33
  // Every table MUST stay a PACKED_SMI array: build with array literals (not `new Array(n)`,
34
34
  // which is HOLEY) and store the signed int32 XOR result (no `>>> 0`). An unsigned or holey
35
35
  // table becomes a V8 FixedDoubleArray whose every hot-loop lookup unboxes a double (~1.6x
36
- // slower). Signedness is irrelevant to the result — the reads mask/shift it and the final
36
+ // slower). Signedness is irrelevant to the result: the reads mask/shift it and the final
37
37
  // `~crc` normalizes it. Do NOT reintroduce `>>> 0` here or switch to `new Array(256)`.
38
38
  const T = [[], [], [], [], [], [], [], []];
39
39
  for (let n = 0; n < 256; n++) {
@@ -26,23 +26,16 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global TextDecoder */
30
-
31
- const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ".split("");
32
- const VALID_CP437 = CP437.length == 256;
29
+ const CP437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\u00B6\u00A7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\u00C7\u00FC\u00E9\u00E2\u00E4\u00E0\u00E5\u00E7\u00EA\u00EB\u00E8\u00EF\u00EE\u00EC\u00C4\u00C5\u00C9\u00E6\u00C6\u00F4\u00F6\u00F2\u00FB\u00F9\u00FF\u00D6\u00DC\u00A2\u00A3\u00A5\u20A7\u0192\u00E1\u00ED\u00F3\u00FA\u00F1\u00D1\u00AA\u00BA\u00BF\u2310\u00AC\u00BD\u00BC\u00A1\u00AB\u00BB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\u00DF\u0393\u03C0\u03A3\u03C3\u00B5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\u00B1\u2265\u2264\u2320\u2321\u00F7\u2248\u00B0\u2219\u00B7\u221A\u207F\u00B2\u25A0\u00A0".split("");
33
30
 
34
31
  export {
35
32
  decodeCP437
36
33
  };
37
34
 
38
35
  function decodeCP437(stringValue) {
39
- if (VALID_CP437) {
40
- let result = "";
41
- for (let indexCharacter = 0; indexCharacter < stringValue.length; indexCharacter++) {
42
- result += CP437[stringValue[indexCharacter]];
43
- }
44
- return result;
45
- } else {
46
- return new TextDecoder().decode(stringValue);
36
+ let result = "";
37
+ for (let indexCharacter = 0; indexCharacter < stringValue.length; indexCharacter++) {
38
+ result += CP437[stringValue[indexCharacter]];
47
39
  }
40
+ return result;
48
41
  }
@@ -26,6 +26,6 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- const VERSION = "2.8.61";
29
+ const VERSION = "2.10.0";
30
30
 
31
31
  export { VERSION };
@@ -80,7 +80,14 @@ import { toExactUint8Array } from "./util/array.js";
80
80
  import { toCompatibleReadable, toCompatibleWritable } from "./util/compatible-streams.js";
81
81
 
82
82
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
83
+ const ERR_DUPLICATE_IMPORTED_ENTRY = "Duplicate entry filename in the imported zip file";
84
+ const ERR_INVALID_DUPLICATES = "Invalid duplicates option (must be \"throw\", \"keep-first\" or \"keep-last\")";
85
+ const ERR_ANCESTOR_ENTRY = "Entry is a ancestor of target entry";
83
86
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
87
+ const DUPLICATES_THROW = "throw";
88
+ const DUPLICATES_KEEP_FIRST = "keep-first";
89
+ const DUPLICATES_KEEP_LAST = "keep-last";
90
+ const DUPLICATES_VALUES = new Set([DUPLICATES_THROW, DUPLICATES_KEEP_FIRST, DUPLICATES_KEEP_LAST]);
84
91
  const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
85
92
  const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
86
93
  const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
@@ -157,12 +164,26 @@ class ZipEntry {
157
164
  }
158
165
 
159
166
  rename(name) {
160
- const parent = this.parent;
161
- if (parent && parent.getChildByName(name)) {
162
- throw new Error(ERR_ENTRY_EXISTS);
163
- } else {
164
- this.name = name;
167
+ const zipEntry = this;
168
+ let parent = zipEntry.parent;
169
+ if (parent) {
170
+ const path = splitPath(name);
171
+ if (path) {
172
+ name = path.pop();
173
+ parent = getPathParent(parent, path, zipEntry);
174
+ }
175
+ const existingChild = parent.getChildByName(name);
176
+ if (existingChild && existingChild != zipEntry) {
177
+ throw new Error(ERR_ENTRY_EXISTS);
178
+ }
179
+ if (parent != zipEntry.parent) {
180
+ detach(zipEntry);
181
+ zipEntry.parent = parent;
182
+ parent.children.push(zipEntry);
183
+ registerEntries(zipEntry.fs, zipEntry);
184
+ }
165
185
  }
186
+ zipEntry.name = name;
166
187
  }
167
188
 
168
189
  setOptions(options) {
@@ -255,47 +276,47 @@ class ZipFileEntry extends ZipEntry {
255
276
  }
256
277
 
257
278
  replaceBlob(blob) {
258
- Object.assign(this, {
279
+ replaceContent(this, {
259
280
  data: blob,
260
281
  Reader: BlobReader,
261
282
  Writer: BlobWriter,
262
- reader: null
283
+ uncompressedSize: blob.size
263
284
  });
264
285
  }
265
286
 
266
287
  replaceText(text) {
267
- Object.assign(this, {
288
+ replaceContent(this, {
268
289
  data: text,
269
290
  Reader: TextReader,
270
291
  Writer: TextWriter,
271
- reader: null
292
+ uncompressedSize: getTextSize(text)
272
293
  });
273
294
  }
274
295
 
275
296
  replaceData64URI(dataURI) {
276
- Object.assign(this, {
297
+ replaceContent(this, {
277
298
  data: dataURI,
278
299
  Reader: Data64URIReader,
279
300
  Writer: Data64URIWriter,
280
- reader: null
301
+ uncompressedSize: getData64URISize(dataURI)
281
302
  });
282
303
  }
283
304
 
284
305
  replaceUint8Array(array) {
285
- Object.assign(this, {
306
+ replaceContent(this, {
286
307
  data: array,
287
308
  Reader: Uint8ArrayReader,
288
309
  Writer: Uint8ArrayWriter,
289
- reader: null
310
+ uncompressedSize: array.length
290
311
  });
291
312
  }
292
313
 
293
314
  replaceReadable(readable) {
294
- Object.assign(this, {
315
+ replaceContent(this, {
295
316
  data: null,
296
317
  Reader: getReadableReader(readable),
297
318
  Writer: null,
298
- reader: null
319
+ uncompressedSize: UNDEFINED_VALUE
299
320
  });
300
321
  }
301
322
  }
@@ -345,17 +366,12 @@ class ZipDirectoryEntry extends ZipEntry {
345
366
  }
346
367
 
347
368
  addData64URI(name, dataURI, options = {}) {
348
- let dataEnd = dataURI.length;
349
- while (dataURI.charAt(dataEnd - 1) == "=") {
350
- dataEnd--;
351
- }
352
- const dataStart = dataURI.indexOf(",") + 1;
353
369
  return addChild(this, name, {
354
370
  data: dataURI,
355
371
  Reader: Data64URIReader,
356
372
  Writer: Data64URIWriter,
357
373
  options,
358
- uncompressedSize: Math.floor((dataEnd - dataStart) * 0.75)
374
+ uncompressedSize: getData64URISize(dataURI)
359
375
  });
360
376
  }
361
377
 
@@ -463,6 +479,7 @@ class ZipDirectoryEntry extends ZipEntry {
463
479
  await initStream(reader);
464
480
  zipReader = new ZipReader(reader, options);
465
481
  }
482
+ const duplicates = checkDuplicatesOption(options.duplicates);
466
483
  const importedEntries = [];
467
484
  const entries = await zipReader.getEntries(options);
468
485
  for (const entry of entries) {
@@ -470,19 +487,42 @@ class ZipDirectoryEntry extends ZipEntry {
470
487
  try {
471
488
  const path = entry.filename.split("/").filter(pathPart => pathPart != "" && pathPart != ".");
472
489
  const name = path.pop();
473
- path.forEach(pathPart => {
490
+ let skippedEntry = false;
491
+ for (const pathPart of path) {
474
492
  const previousParent = parent;
475
493
  parent = parent.getChildByName(pathPart);
476
494
  if (parent) {
477
495
  if (!parent.directory) {
478
- throw new Error(ERR_ENTRY_EXISTS);
496
+ if (duplicates == DUPLICATES_KEEP_FIRST) {
497
+ skippedEntry = true;
498
+ break;
499
+ } else if (duplicates == DUPLICATES_KEEP_LAST) {
500
+ this.fs.remove(parent);
501
+ parent = new ZipDirectoryEntry(this.fs, pathPart, { data: null }, previousParent);
502
+ importedEntries.push(parent);
503
+ } else {
504
+ throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
505
+ }
479
506
  }
480
507
  } else {
481
508
  parent = new ZipDirectoryEntry(this.fs, pathPart, { data: null }, previousParent);
482
509
  importedEntries.push(parent);
483
510
  }
484
- });
511
+ }
512
+ if (skippedEntry) {
513
+ continue;
514
+ }
485
515
  if (!entry.directory) {
516
+ const existingChild = parent.getChildByName(name);
517
+ if (existingChild) {
518
+ if (duplicates == DUPLICATES_KEEP_FIRST) {
519
+ continue;
520
+ } else if (duplicates == DUPLICATES_KEEP_LAST) {
521
+ this.fs.remove(existingChild);
522
+ } else {
523
+ throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
524
+ }
525
+ }
486
526
  importedEntries.push(addChild(parent, name, {
487
527
  data: entry,
488
528
  Reader: getZipBlobReader(Object.assign({}, options)),
@@ -493,11 +533,17 @@ class ZipDirectoryEntry extends ZipEntry {
493
533
  let directoryEntry = parent;
494
534
  if (name) {
495
535
  directoryEntry = parent.getChildByName(name);
496
- if (directoryEntry) {
497
- if (!directoryEntry.directory) {
498
- throw new Error(ERR_ENTRY_EXISTS);
536
+ if (directoryEntry && !directoryEntry.directory) {
537
+ if (duplicates == DUPLICATES_KEEP_FIRST) {
538
+ continue;
539
+ } else if (duplicates == DUPLICATES_KEEP_LAST) {
540
+ this.fs.remove(directoryEntry);
541
+ directoryEntry = UNDEFINED_VALUE;
542
+ } else {
543
+ throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
499
544
  }
500
- } else {
545
+ }
546
+ if (!directoryEntry) {
501
547
  directoryEntry = new ZipDirectoryEntry(this.fs, name, { data: null }, parent);
502
548
  importedEntries.push(directoryEntry);
503
549
  }
@@ -507,6 +553,7 @@ class ZipDirectoryEntry extends ZipEntry {
507
553
  }
508
554
  }
509
555
  } catch (error) {
556
+ importedEntries.reverse().forEach(importedEntry => this.fs.remove(importedEntry));
510
557
  try {
511
558
  error.cause = {
512
559
  entry
@@ -625,7 +672,7 @@ class ZipFS {
625
672
  }
626
673
  }
627
674
  } else {
628
- throw new Error("Entry is a ancestor of target entry");
675
+ throw new Error(ERR_ANCESTOR_ENTRY);
629
676
  }
630
677
  } else {
631
678
  throw new Error("Target entry is not a directory");
@@ -637,7 +684,7 @@ class ZipFS {
637
684
  const path = fullname.split("/");
638
685
  let node = this.root;
639
686
  for (let index = 0; node && index < path.length; index++) {
640
- node = node.getChildByName(path[index]);
687
+ node = node.directory ? node.getChildByName(path[index]) : UNDEFINED_VALUE;
641
688
  }
642
689
  if (!node) {
643
690
  node = this.entries.find(entry => entry && (entry == this.root || entry.isDescendantOf(this.root)) &&
@@ -699,33 +746,27 @@ class ZipFS {
699
746
  }
700
747
 
701
748
  importBlob(blob, options) {
702
- resetFS(this);
703
- return this.root.importBlob(blob, options);
749
+ return resetAndImport(this, root => root.importBlob(blob, options));
704
750
  }
705
751
 
706
752
  importData64URI(dataURI, options) {
707
- resetFS(this);
708
- return this.root.importData64URI(dataURI, options);
753
+ return resetAndImport(this, root => root.importData64URI(dataURI, options));
709
754
  }
710
755
 
711
756
  importUint8Array(array, options) {
712
- resetFS(this);
713
- return this.root.importUint8Array(array, options);
757
+ return resetAndImport(this, root => root.importUint8Array(array, options));
714
758
  }
715
759
 
716
760
  importHttpContent(url, options) {
717
- resetFS(this);
718
- return this.root.importHttpContent(url, options);
761
+ return resetAndImport(this, root => root.importHttpContent(url, options));
719
762
  }
720
763
 
721
764
  importReadable(readable, options) {
722
- resetFS(this);
723
- return this.root.importReadable(readable, options);
765
+ return resetAndImport(this, root => root.importReadable(readable, options));
724
766
  }
725
767
 
726
768
  importZip(reader, options) {
727
- resetFS(this);
728
- return this.root.importZip(reader, options);
769
+ return resetAndImport(this, root => root.importZip(reader, options));
729
770
  }
730
771
 
731
772
  exportBlob(options) {
@@ -766,7 +807,7 @@ class ZipFS {
766
807
  }
767
808
 
768
809
  const fs = { FS: ZipFS, ZipDirectoryEntry, ZipFileEntry };
769
- export { ZipFS, ZipEntry, ZipFileEntry, ZipDirectoryEntry, fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED, ERR_INVALID_PASS_THROUGH, ERR_INVALID_READER_OPTIONS, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ABORTED };
810
+ export { ZipFS, ZipEntry, ZipFileEntry, ZipDirectoryEntry, fs, ERR_ENTRY_EXISTS, ERR_DUPLICATE_IMPORTED_ENTRY, ERR_INVALID_DUPLICATES, ERR_READABLE_CONSUMED, ERR_INVALID_PASS_THROUGH, ERR_INVALID_READER_OPTIONS, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ABORTED };
770
811
 
771
812
  function getTotalSize(entries, getEntrySize) {
772
813
  let size = 0;
@@ -1046,6 +1087,25 @@ function checkReaderOptions(readerOptions) {
1046
1087
  return readerOptions;
1047
1088
  }
1048
1089
 
1090
+ function replaceContent(zipEntry, params) {
1091
+ const { uncompressedSize } = params;
1092
+ Object.assign(zipEntry, params, {
1093
+ reader: null,
1094
+ passThrough: UNDEFINED_VALUE,
1095
+ uncompressedSize: uncompressedSize === UNDEFINED_VALUE ? 0 : uncompressedSize,
1096
+ undeterminedSize: uncompressedSize === UNDEFINED_VALUE
1097
+ });
1098
+ }
1099
+
1100
+ function getData64URISize(dataURI) {
1101
+ let dataEnd = dataURI.length;
1102
+ while (dataURI.charAt(dataEnd - 1) == "=") {
1103
+ dataEnd--;
1104
+ }
1105
+ const dataStart = dataURI.indexOf(",") + 1;
1106
+ return Math.floor((dataEnd - dataStart) * 0.75);
1107
+ }
1108
+
1049
1109
  function isPassThrough(child, options) {
1050
1110
  const { readerOptions } = options;
1051
1111
  return Boolean(!child.directory && (child.passThrough || (readerOptions && readerOptions.passThrough)));
@@ -1335,6 +1395,15 @@ function resetFS(fs) {
1335
1395
  fs.root = new ZipDirectoryEntry(fs);
1336
1396
  }
1337
1397
 
1398
+ function resetAndImport(fs, importFunction) {
1399
+ const { entries, entryIdCounter, root } = fs;
1400
+ resetFS(fs);
1401
+ return importFunction(fs.root).catch(error => {
1402
+ Object.assign(fs, { entries, entryIdCounter, root });
1403
+ throw error;
1404
+ });
1405
+ }
1406
+
1338
1407
  function collectChildren(directory, recursive) {
1339
1408
  const children = [];
1340
1409
  const pendingDirectories = [directory];
@@ -1363,8 +1432,50 @@ function registerEntries(fs, entry) {
1363
1432
 
1364
1433
  function addChild(parent, name, params, directory) {
1365
1434
  if (parent.directory) {
1435
+ const path = splitPath(name);
1436
+ if (path) {
1437
+ name = path.pop();
1438
+ parent = getPathParent(parent, path);
1439
+ }
1366
1440
  return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
1367
1441
  } else {
1368
1442
  throw new Error("Parent entry is not a directory");
1369
1443
  }
1370
- }
1444
+ }
1445
+
1446
+ function checkDuplicatesOption(duplicates) {
1447
+ if (duplicates === UNDEFINED_VALUE) {
1448
+ return DUPLICATES_THROW;
1449
+ } else if (DUPLICATES_VALUES.has(duplicates)) {
1450
+ return duplicates;
1451
+ } else {
1452
+ throw new Error(ERR_INVALID_DUPLICATES);
1453
+ }
1454
+ }
1455
+
1456
+ function splitPath(name) {
1457
+ if (name.includes("/")) {
1458
+ const path = name.split("/").filter(pathPart => pathPart != "" && pathPart != ".");
1459
+ if (path.length) {
1460
+ return path;
1461
+ }
1462
+ }
1463
+ }
1464
+
1465
+ function getPathParent(parent, path, movedEntry) {
1466
+ path.forEach(pathPart => {
1467
+ const previousParent = parent;
1468
+ parent = parent.getChildByName(pathPart);
1469
+ if (parent) {
1470
+ if (!parent.directory) {
1471
+ throw new Error(ERR_ENTRY_EXISTS);
1472
+ }
1473
+ if (movedEntry && (parent == movedEntry || parent.isDescendantOf(movedEntry))) {
1474
+ throw new Error(ERR_ANCESTOR_ENTRY);
1475
+ }
1476
+ } else {
1477
+ parent = new ZipDirectoryEntry(previousParent.fs, pathPart, { data: null }, previousParent);
1478
+ }
1479
+ });
1480
+ return parent;
1481
+ }
@@ -205,6 +205,7 @@ const WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA = "unknown zip64 extensible data";
205
205
  const WARNING_WRAPPED_ENTRIES_COUNT = "wrapped entries count";
206
206
  const WARNING_APPENDED_DATA = "appended data";
207
207
  const WARNING_PREPENDED_DATA = "prepended data";
208
+ const WARNING_PREPENDED_CENTRAL_DIRECTORY = "prepended central directory";
208
209
  const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
209
210
  const WARNING_DUPLICATE_FILENAME = "duplicate filename";
210
211
  const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
@@ -298,6 +299,7 @@ class ZipReader {
298
299
  let diskNumber = getUint16(endOfDirectoryView, 6);
299
300
  let filesLength = getUint16(endOfDirectoryView, 10);
300
301
  let prependedDataLength = 0;
302
+ let prependedCentralDirectory;
301
303
  let startOffset;
302
304
  let zip64EndOfDirectory;
303
305
  let zip64EndOfDirectoryVersion2;
@@ -401,6 +403,7 @@ class ZipReader {
401
403
  directoryDataOffset = expectedDirectoryDataOffset;
402
404
  if (directoryDataOffset > originalDirectoryDataOffset) {
403
405
  prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
406
+ prependedCentralDirectory = storedPointsAtDirectory;
404
407
  }
405
408
  directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
406
409
  directoryView = getDataView(directoryArray);
@@ -628,6 +631,9 @@ class ZipReader {
628
631
  if (prependedDataLength || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
629
632
  addWarning(warnings, WARNING_PREPENDED_DATA);
630
633
  }
634
+ if (prependedCentralDirectory) {
635
+ addWarning(warnings, WARNING_PREPENDED_CENTRAL_DIRECTORY);
636
+ }
631
637
  if (extractPrependedData) {
632
638
  zipReader.prependedData = startOffset > splitZipSignatureLength ?
633
639
  await readUint8Array(reader, splitZipSignatureLength, startOffset - splitZipSignatureLength) :
@@ -756,6 +762,7 @@ export {
756
762
  WARNING_WRAPPED_ENTRIES_COUNT,
757
763
  WARNING_APPENDED_DATA,
758
764
  WARNING_PREPENDED_DATA,
765
+ WARNING_PREPENDED_CENTRAL_DIRECTORY,
759
766
  WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
760
767
  WARNING_DUPLICATE_FILENAME,
761
768
  WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
@@ -66,6 +66,7 @@ export {
66
66
  WARNING_WRAPPED_ENTRIES_COUNT,
67
67
  WARNING_APPENDED_DATA,
68
68
  WARNING_PREPENDED_DATA,
69
+ WARNING_PREPENDED_CENTRAL_DIRECTORY,
69
70
  WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
70
71
  WARNING_DUPLICATE_FILENAME,
71
72
  WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "2.8.61",
6
+ "version": "2.10.0",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",