feat: 集成漫画源并支持在线阅读

This commit is contained in:
lofyer
2026-08-08 19:32:47 +08:00
parent c2292da442
commit 87dcc307e6
30 changed files with 3681 additions and 58 deletions
+69
View File
@@ -0,0 +1,69 @@
const test = require('node:test');
const assert = require('node:assert');
const zip = require('../zip');
test('writeZip/readZip: 基本往返,文本与二进制内容不失真', () => {
const entries = [
{ name: 'mimetype', data: Buffer.from('application/epub+zip') },
{ name: 'a/b.txt', data: Buffer.from('hello 你好', 'utf8') },
{ name: 'c.bin', data: Buffer.from([0, 1, 2, 255, 254, 128]) }
];
const buf = zip.writeZip(entries);
const parsed = zip.readZip(buf);
assert.deepStrictEqual([...parsed.keys()], ['mimetype', 'a/b.txt', 'c.bin']);
assert.strictEqual(parsed.get('a/b.txt').toString('utf8'), 'hello 你好');
assert.deepStrictEqual([...parsed.get('c.bin')], [0, 1, 2, 255, 254, 128]);
});
test('writeZip/readZip: 大文件(跨多个 chunk)内容比特级一致', () => {
const big = Buffer.alloc(500000);
for (let i = 0; i < big.length; i++) big[i] = i % 256;
const buf = zip.writeZip([{ name: 'big.bin', data: big }]);
const parsed = zip.readZip(buf);
assert.strictEqual(Buffer.compare(parsed.get('big.bin'), big), 0);
});
test('readZip: 能解析第三方(JSZip)产出的 DEFLATE 压缩包', async () => {
const JSZip = require('../ui/vendor/jszip.min.js');
const jz = new JSZip();
jz.file('x.txt', 'DEFLATE 测试内容');
const buf = await jz.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' });
const parsed = zip.readZip(buf);
assert.strictEqual(parsed.get('x.txt').toString('utf8'), 'DEFLATE 测试内容');
});
test('writeZip: 产出的包能被第三方(JSZip)正确打开', async () => {
const JSZip = require('../ui/vendor/jszip.min.js');
const buf = zip.writeZip([
{ name: 'mimetype', data: Buffer.from('application/epub+zip') },
{ name: 'nested/dir/file.txt', data: Buffer.from('nested content') }
]);
const jz = await JSZip.loadAsync(buf);
assert.ok(jz.file('mimetype'));
const text = await jz.file('nested/dir/file.txt').async('string');
assert.strictEqual(text, 'nested content');
});
test('readZip: 空 ZIPEOCD 但无条目)不抛错,返回空 Map', () => {
const buf = zip.writeZip([]);
const parsed = zip.readZip(buf);
assert.strictEqual(parsed.size, 0);
});
test('readZip: 非 ZIP 数据抛出可读错误而不是崩溃', () => {
assert.throws(() => zip.readZip(Buffer.from('not a zip file')), /不是有效的 ZIP 文件/);
});
test('readZip: 不把未知压缩方式误当作 STORE 内容', () => {
const buf = zip.writeZip([{ name: 'x.bin', data: Buffer.from([1, 2, 3]) }]);
const central = buf.indexOf(Buffer.from([0x50, 0x4b, 0x01, 0x02]));
buf.writeUInt16LE(99, central + 10);
assert.throws(() => zip.readZip(buf), /压缩方式不受支持/);
});
test('readZip: 条目内容损坏时通过 CRC 拒绝继续读取', () => {
const buf = zip.writeZip([{ name: 'x.bin', data: Buffer.from([1, 2, 3]) }]);
const dataStart = 30 + Buffer.byteLength('x.bin');
buf[dataStart] ^= 0xff;
assert.throws(() => zip.readZip(buf), /条目校验失败/);
});