w-zip 1.0.22 → 1.0.23

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 (48) hide show
  1. package/.github/workflows/ci-test.yml +3 -3
  2. package/README.md +7 -6
  3. package/dist/w-zip.umd.js +2 -2
  4. package/dist/w-zip.umd.js.map +1 -1
  5. package/docs/index.html +1 -1
  6. package/docs/m7z.html +30 -4
  7. package/docs/m7z.mjs.html +10 -10
  8. package/docs/mZip.html +18 -6
  9. package/docs/mZip.mjs.html +97 -132
  10. package/g-7z.mjs +3 -3
  11. package/g-zip.mjs +3 -3
  12. package/package.json +5 -7
  13. package/script.txt +0 -2
  14. package/src/m7z.mjs +9 -9
  15. package/src/mZip.mjs +96 -131
  16. package/test/7z.test.mjs +3 -3
  17. package/test/output7z/test1.7z +0 -0
  18. package/test/output7z/test2.7z +0 -0
  19. package/test/output7z/test2PW.7z +0 -0
  20. package/test/outputZip/test1.zip +0 -0
  21. package/test/outputZip/test2.zip +0 -0
  22. package/test/outputZip/test2PW.zip +0 -0
  23. package/test/zip.test.mjs +3 -3
  24. package/toolg/gDistRollup.mjs +2 -6
  25. package/testData/output7z/test1.7z +0 -0
  26. package/testData/output7z/test2.7z +0 -0
  27. package/testData/output7z/test2PW.7z +0 -0
  28. package/testData/outputZip/test1.zip +0 -0
  29. package/testData/outputZip/test2.zip +0 -0
  30. package/testData/outputZip/test2PW.zip +0 -0
  31. /package/{testData → test}/input/file1(/344/270/255/346/226/207).txt" +0 -0
  32. /package/{testData → test}/input/folder1/f1-1.xlsx +0 -0
  33. /package/{testData → test}/input/folder1/f1-2.xlsx +0 -0
  34. /package/{testData → test}/input/folder1/folder2/f2-1.xlsx +0 -0
  35. /package/{testData → test}/input/folder1/folder2/f2-2.xlsx +0 -0
  36. /package/{testData → test}/input/folder1/folder2/f2-3(/344/270/255/346/226/207).xlsx" +0 -0
  37. /package/{testData → test}/output7z/extract/test1/file1(/344/270/255/346/226/207).txt" +0 -0
  38. /package/{testData → test}/output7z/extract/test2/folder1/f1-1.xlsx +0 -0
  39. /package/{testData → test}/output7z/extract/test2/folder1/f1-2.xlsx +0 -0
  40. /package/{testData → test}/output7z/extract/test2/folder1/folder2/f2-1.xlsx +0 -0
  41. /package/{testData → test}/output7z/extract/test2/folder1/folder2/f2-2.xlsx +0 -0
  42. /package/{testData → test}/output7z/extract/test2/folder1/folder2/f2-3(/344/270/255/346/226/207).xlsx" +0 -0
  43. /package/{testData → test}/outputZip/extract/test1/file1(/344/270/255/346/226/207).txt" +0 -0
  44. /package/{testData → test}/outputZip/extract/test2/folder1/f1-1.xlsx +0 -0
  45. /package/{testData → test}/outputZip/extract/test2/folder1/f1-2.xlsx +0 -0
  46. /package/{testData → test}/outputZip/extract/test2/folder1/folder2/f2-1.xlsx +0 -0
  47. /package/{testData → test}/outputZip/extract/test2/folder1/folder2/f2-2.xlsx +0 -0
  48. /package/{testData → test}/outputZip/extract/test2/folder1/folder2/f2-3(/344/270/255/346/226/207).xlsx" +0 -0
@@ -47,18 +47,15 @@
47
47
  <article>
48
48
  <pre class="prettyprint source linenums"><code>import path from 'path'
49
49
  import fs from 'fs'
50
- import archiver from 'archiver'
51
- import archiverEnc from 'archiver-zip-encrypted'
52
- import unzipper from 'unzipper'
53
- import get from 'lodash-es/get.js'
54
- import genPm from 'wsemi/src/genPm.mjs'
55
- import pmMap from 'wsemi/src/pmMap.mjs'
50
+ import { configure, ZipWriter, ZipReader, Uint8ArrayReader, Uint8ArrayWriter } from '@zip.js/zip.js'
51
+ import get from 'lodash-es/get.js'
52
+ import fsTreeFolder from 'wsemi/src/fsTreeFolder.mjs'
56
53
  import getFileName from 'wsemi/src/getFileName.mjs'
57
54
  import checkTarget from './checkTarget.mjs'
58
55
 
59
56
 
60
- //registerFormat
61
- archiver.registerFormat('zip-encrypted', archiverEnc)
57
+ //configure
58
+ configure({ useWebWorkers: false }) //關閉web worker改用主執行緒壓縮, 確保nodejs下無殘留worker導致process無法結束
62
59
 
63
60
 
64
61
  /**
@@ -69,13 +66,13 @@ archiver.registerFormat('zip-encrypted', archiverEnc)
69
66
  * @example
70
67
  * import wz from 'w-zip'
71
68
  *
72
- * let fpUnzip = './testData/outputZip'
69
+ * let fpUnzip = './test/outputZip'
73
70
  * let fpUnzipExtract = fpUnzip + '/extract'
74
71
  *
75
- * let fpSrc1 = './testData/input/file1(中文).txt'
72
+ * let fpSrc1 = './test/input/file1(中文).txt'
76
73
  * let fpZip1 = fpUnzip + '/test1.zip'
77
74
  *
78
- * let fpSrc2 = './testData/input/folder1'
75
+ * let fpSrc2 = './test/input/folder1'
79
76
  * let fpZip2 = fpUnzip + '/test2.zip'
80
77
  * let fpZip2PW = fpUnzip + '/test2PW.zip'
81
78
  * let pw = 'abc'
@@ -147,7 +144,7 @@ function mZip() {
147
144
  * @param {String} fpSrc 輸入壓縮來源檔案位置字串
148
145
  * @param {String} fpTar 輸入壓縮目標檔案位置字串
149
146
  * @param {Object} [opt={}] 輸入設定物件,預設{}
150
- * @param {Integer} [opt.level] 輸入壓縮程度整數,範圍為0至9,0為不壓縮而9為最高壓縮,預設9
147
+ * @param {Integer} [opt.level=9] 輸入壓縮程度整數,範圍為0至9,0為不壓縮而9為最高壓縮,預設9
151
148
  * @param {String} [opt.pw] 輸入壓縮密碼字串,預設''
152
149
  * @returns {Promise} 回傳Promise,resolve為成功資訊,reject為失敗資訊
153
150
  */
@@ -172,54 +169,32 @@ function mZip() {
172
169
 
173
170
  try {
174
171
 
175
- //pm
176
- let pm = genPm()
177
-
178
172
  //check
179
173
  if (!fs.existsSync(path.dirname(fpTar))) {
180
174
  fs.mkdirSync(path.dirname(fpTar), { recursive: true })
181
175
  }
182
176
 
183
- //archiver
184
- let output = fs.createWriteStream(fpTar)
185
- let archive
186
- if (pw === '') {
187
- archive = archiver('zip', {
188
- zlib: { level },
189
- })
190
- }
191
- else {
192
- archive = archiver('zip-encrypted', {
193
- zlib: { level },
194
- encryptionMethod: 'zip20', //只能用zip20, 因unzipper目前不支援aes256
195
- password: pw,
196
- })
177
+ //zipOpt
178
+ let zipOpt = { level }
179
+ if (pw !== '') {
180
+ zipOpt.password = pw
181
+ zipOpt.zipCrypto = true //使用ZipCrypto(即zip20)加密維持與舊版相同相容性, 若需更強加密可改為encryptionStrength: 3(AES-256)
197
182
  }
198
183
 
199
- output.on('close', function() {
200
- //console.log(archive.pointer() + ' total bytes')
201
-
202
- //resolve
203
- pm.resolve('done: ' + fpTar)
184
+ //zipWriter
185
+ let zipWriter = new ZipWriter(new Uint8ArrayWriter(), zipOpt)
204
186
 
205
- })
206
- archive.on('warning', function(warn) {
207
- //console.log('warning', warn)
208
- })
209
- archive.on('error', function(err) {
210
- Promise.reject(err)
211
- })
187
+ //add
188
+ let b = fs.readFileSync(fpSrc)
189
+ await zipWriter.add(path.basename(fpSrc), new Uint8ArrayReader(b))
212
190
 
213
- //pipe
214
- archive.pipe(output)
191
+ //close
192
+ let u8 = await zipWriter.close()
215
193
 
216
- //file
217
- archive.file(fpSrc, { name: path.basename(fpSrc) })
194
+ //writeFileSync
195
+ fs.writeFileSync(fpTar, u8)
218
196
 
219
- //finalize
220
- archive.finalize()
221
-
222
- return pm
197
+ return Promise.resolve('done: ' + fpTar)
223
198
  }
224
199
  catch (err) {
225
200
  return Promise.reject(err)
@@ -257,54 +232,57 @@ function mZip() {
257
232
 
258
233
  try {
259
234
 
260
- //pm
261
- let pm = genPm()
262
-
263
235
  //check
264
236
  if (!fs.existsSync(path.dirname(fpTar))) {
265
237
  fs.mkdirSync(path.dirname(fpTar), { recursive: true })
266
238
  }
267
239
 
268
- //archiver
269
- let output = fs.createWriteStream(fpTar)
270
- let archive
271
- if (pw === '') {
272
- archive = archiver('zip', {
273
- zlib: { level },
274
- })
275
- }
276
- else {
277
- archive = archiver('zip-encrypted', {
278
- zlib: { level },
279
- encryptionMethod: 'zip20', //只能用zip20, 因unzipper目前不支援aes256
280
- password: pw,
281
- })
240
+ //zipOpt
241
+ let zipOpt = { level }
242
+ if (pw !== '') {
243
+ zipOpt.password = pw
244
+ zipOpt.zipCrypto = true //使用ZipCrypto(即zip20)加密維持與舊版相同相容性, 若需更強加密可改為encryptionStrength: 3(AES-256)
282
245
  }
283
246
 
284
- output.on('close', function() {
285
- //console.log(archive.pointer() + ' total bytes')
247
+ //zipWriter
248
+ let zipWriter = new ZipWriter(new Uint8ArrayWriter(), zipOpt)
286
249
 
287
- //resolve
288
- pm.resolve('done: ' + fpTar)
250
+ //bn, 以來源資料夾名稱為zip內根目錄(同archiver.directory(fpSrc, basename)行為)
251
+ let bn = path.basename(fpSrc)
289
252
 
290
- })
291
- archive.on('warning', function(warn) {
292
- //console.log('warning', warn)
293
- })
294
- archive.on('error', function(err) {
295
- Promise.reject(err)
296
- })
253
+ //items, 遞迴列舉資料夾下全部檔案與子資料夾
254
+ let items = fsTreeFolder(fpSrc, null)
297
255
 
298
- //pipe
299
- archive.pipe(output)
256
+ //add
257
+ for (let item of items) {
300
258
 
301
- //directory
302
- archive.directory(fpSrc, path.basename(fpSrc))
259
+ //name, zip內相對路徑統一用'/'
260
+ let rel = path.relative(fpSrc, item.path)
261
+ let name = path.join(bn, rel).replaceAll('\\', '/')
262
+
263
+ if (item.isFolder) {
264
+
265
+ //directory, 保留空資料夾結構
266
+ await zipWriter.add(name, undefined, { directory: true })
267
+
268
+ }
269
+ else {
303
270
 
304
- //finalize
305
- archive.finalize()
271
+ //file
272
+ let b = fs.readFileSync(item.path)
273
+ await zipWriter.add(name, new Uint8ArrayReader(b))
306
274
 
307
- return pm
275
+ }
276
+
277
+ }
278
+
279
+ //close
280
+ let u8 = await zipWriter.close()
281
+
282
+ //writeFileSync
283
+ fs.writeFileSync(fpTar, u8)
284
+
285
+ return Promise.resolve('done: ' + fpTar)
308
286
  }
309
287
  catch (err) {
310
288
  return Promise.reject(err)
@@ -340,67 +318,54 @@ function mZip() {
340
318
  //default
341
319
  let pw = get(opt, 'pw', '')
342
320
 
343
- //extract
344
- async function extract(fpSrc, fpTar, password) {
345
-
346
- //mkdir
347
- async function mkdir(fd) {
348
- try {
349
-
350
- //check
351
- if (!fs.existsSync(fd)) {
352
- fs.mkdirSync(fd, { recursive: true })
353
- }
321
+ try {
354
322
 
355
- }
356
- catch (err) {
357
- return Promise.reject(err)
358
- }
359
- return 'done'
323
+ //readerOpt
324
+ let readerOpt = {}
325
+ if (pw !== '') {
326
+ readerOpt.password = pw
360
327
  }
361
328
 
362
- //extractFile
363
- async function extractFile(file, fn, password = '') {
364
- try {
329
+ //zipReader
330
+ let b = fs.readFileSync(fpSrc)
331
+ let zipReader = new ZipReader(new Uint8ArrayReader(b), readerOpt)
365
332
 
366
- //check
367
- if (!fs.existsSync(path.dirname(fn))) {
368
- fs.mkdirSync(path.dirname(fn), { recursive: true })
369
- }
333
+ //entries
334
+ let entries = await zipReader.getEntries()
370
335
 
371
- //buffer
372
- let b = await file.buffer(password)
336
+ //extract
337
+ for (let entry of entries) {
373
338
 
374
- //writeFileSync
375
- fs.writeFileSync(fn, b)
339
+ //p, 解壓目標位置
340
+ let p = path.join(fpTar, entry.filename)
376
341
 
377
- }
378
- catch (err) {
379
- return Promise.reject(err)
380
- }
381
- return 'done'
382
- }
342
+ if (entry.directory) {
383
343
 
384
- //directory
385
- let directory = await unzipper.Open.file(fpSrc)
344
+ //mkdir
345
+ if (!fs.existsSync(p)) {
346
+ fs.mkdirSync(p, { recursive: true })
347
+ }
386
348
 
387
- //pmMap
388
- return pmMap(directory.files, async (file) => {
389
- let p = path.join(fpTar, file.path)
390
- if (file.type === 'File') {
391
- return extractFile(file, p, password)
392
349
  }
393
350
  else {
394
- return mkdir(p)
395
- }
396
- })
397
351
 
398
- }
352
+ //mkdir, 先建立上層資料夾
353
+ if (!fs.existsSync(path.dirname(p))) {
354
+ fs.mkdirSync(path.dirname(p), { recursive: true })
355
+ }
399
356
 
400
- try {
357
+ //getData
358
+ let u8 = await entry.getData(new Uint8ArrayWriter())
401
359
 
402
- //extract
403
- await extract(fpSrc, fpTar, pw)
360
+ //writeFileSync
361
+ fs.writeFileSync(p, u8)
362
+
363
+ }
364
+
365
+ }
366
+
367
+ //close
368
+ await zipReader.close()
404
369
 
405
370
  return Promise.resolve('done: ' + getFileName(fpTar))
406
371
  }
@@ -433,7 +398,7 @@ export default mZip()
433
398
  <br class="clear">
434
399
 
435
400
  <footer>
436
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Tue Oct 07 2025 10:35:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
401
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat May 30 2026 20:38:46 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
437
402
  </footer>
438
403
 
439
404
  <script>prettyPrint();</script>
package/g-7z.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  import wz from './src/WZip.mjs'
2
2
  import w from 'wsemi'
3
3
 
4
- let fpUnzip = './testData/output7z'
4
+ let fpUnzip = './test/output7z'
5
5
  let fpUnzipExtract = fpUnzip + '/extract'
6
6
 
7
- let fpSrc1 = './testData/input/file1(中文).txt'
7
+ let fpSrc1 = './test/input/file1(中文).txt'
8
8
  let fpZip1 = fpUnzip + '/test1.7z'
9
9
 
10
- let fpSrc2 = './testData/input/folder1'
10
+ let fpSrc2 = './test/input/folder1'
11
11
  let fpZip2 = fpUnzip + '/test2.7z'
12
12
  let fpZip2PW = fpUnzip + '/test2PW.7z'
13
13
  let pw = 'abc'
package/g-zip.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  import wz from './src/WZip.mjs'
2
2
  import w from 'wsemi'
3
3
 
4
- let fpUnzip = './testData/outputZip'
4
+ let fpUnzip = './test/outputZip'
5
5
  let fpUnzipExtract = fpUnzip + '/extract'
6
6
 
7
- let fpSrc1 = './testData/input/file1(中文).txt'
7
+ let fpSrc1 = './test/input/file1(中文).txt'
8
8
  let fpZip1 = fpUnzip + '/test1.zip'
9
9
 
10
- let fpSrc2 = './testData/input/folder1'
10
+ let fpSrc2 = './test/input/folder1'
11
11
  let fpZip2 = fpUnzip + '/test2.zip'
12
12
  let fpZip2PW = fpUnzip + '/test2PW.zip'
13
13
  let pw = 'abc'
package/package.json CHANGED
@@ -1,16 +1,14 @@
1
1
  {
2
2
  "name": "w-zip",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "main": "dist/w-zip.umd.js",
5
5
  "dependencies": {
6
- "archiver": "^7.0.1",
7
- "archiver-zip-encrypted": "^2.0.0",
8
- "unzipper": "^0.12.3",
9
- "lodash-es": "^4.17.21",
10
- "wsemi": "^1.8.22"
6
+ "@zip.js/zip.js": "^2.8.26",
7
+ "lodash-es": "^4.18.1",
8
+ "wsemi": "^1.8.54"
11
9
  },
12
10
  "devDependencies": {
13
- "w-package-tools": "^1.1.2"
11
+ "w-package-tools": "^1.1.7"
14
12
  },
15
13
  "scripts": {
16
14
  "test": "mocha --parallel --timeout 60000",
package/script.txt CHANGED
@@ -14,6 +14,4 @@ npm run deploy
14
14
 
15
15
  #npm test
16
16
 
17
- #node g-zip.mjs
18
-
19
17
  #npm publish
package/src/m7z.mjs CHANGED
@@ -13,13 +13,13 @@ import checkTarget from './checkTarget.mjs'
13
13
  * @example
14
14
  * import wz from 'w-zip'
15
15
  *
16
- * let fpUnzip = './testData/output7z'
16
+ * let fpUnzip = './test/output7z'
17
17
  * let fpUnzipExtract = fpUnzip + '/extract'
18
18
  *
19
- * let fpSrc1 = './testData/input/file1(中文).txt'
19
+ * let fpSrc1 = './test/input/file1(中文).txt'
20
20
  * let fpZip1 = fpUnzip + '/test1.7z'
21
21
  *
22
- * let fpSrc2 = './testData/input/folder1'
22
+ * let fpSrc2 = './test/input/folder1'
23
23
  * let fpZip2 = fpUnzip + '/test2.7z'
24
24
  * let fpZip2PW = fpUnzip + '/test2PW.7z'
25
25
  * let pw = 'abc'
@@ -119,7 +119,7 @@ function m7z() {
119
119
  }
120
120
 
121
121
 
122
- async function zip(fpSrc, fpTar, level = 9, pw = '') {
122
+ async function zip(fpSrc, fpTar, level = 1, pw = '') { //7z的-mx1為最快速壓縮(mx0為不壓縮)
123
123
  let arg = [
124
124
  'a',
125
125
  fpTar,
@@ -141,8 +141,8 @@ function m7z() {
141
141
  * @param {String} fpSrc 輸入壓縮來源檔案位置字串
142
142
  * @param {String} fpTar 輸入壓縮目標檔案位置字串
143
143
  * @param {Object} [opt={}] 輸入設定物件,預設{}
144
- * @param {Integer} [opt.level] 輸入壓縮程度整數,範圍為0至9,0為不壓縮而9為最高壓縮,預設9
145
- * @param {String} [opt.pw] 輸入壓縮密碼字串,預設''
144
+ * @param {Integer} [opt.level=1] 輸入壓縮程度整數,範圍為0至9,0為不壓縮而9為最高壓縮,預設1為最快速壓縮
145
+ * @param {String} [opt.pw=''] 輸入壓縮密碼字串,預設''
146
146
  * @returns {Promise} 回傳Promise,resolve為成功資訊,reject為失敗資訊
147
147
  */
148
148
  async function zipFile(fpSrc, fpTar, opt = {}) {
@@ -161,7 +161,7 @@ function m7z() {
161
161
  }
162
162
 
163
163
  //default
164
- let level = get(opt, 'level', 9)
164
+ let level = get(opt, 'level', 1)
165
165
  let pw = get(opt, 'pw', '')
166
166
 
167
167
  //r
@@ -190,7 +190,7 @@ function m7z() {
190
190
  * @param {String} fpSrc 輸入壓縮來源資料夾位置字串
191
191
  * @param {String} fpTar 輸入壓縮目標資料夾位置字串
192
192
  * @param {Object} [opt={}] 輸入設定物件,預設{}
193
- * @param {Integer} [opt.level] 輸入壓縮程度整數,範圍為0至9,0為不壓縮而9為最高壓縮,預設9
193
+ * @param {Integer} [opt.level=1] 輸入壓縮程度整數,範圍為0至9,0為不壓縮而9為最高壓縮,預設1為最快速壓縮
194
194
  * @param {String} [opt.pw] 輸入壓縮密碼字串,預設''
195
195
  * @returns {Promise} 回傳Promise,resolve為成功資訊,reject為失敗資訊
196
196
  */
@@ -210,7 +210,7 @@ function m7z() {
210
210
  }
211
211
 
212
212
  //default
213
- let level = get(opt, 'level', 9)
213
+ let level = get(opt, 'level', 1)
214
214
  let pw = get(opt, 'pw', '')
215
215
 
216
216
  //r