feat(archive): add MIME types and compound-extension aliases for archive formats
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,12 @@ const OUTPUT_MIME_TYPES = {
|
|||||||
snb: 'application/octet-stream',
|
snb: 'application/octet-stream',
|
||||||
tcr: 'application/octet-stream',
|
tcr: 'application/octet-stream',
|
||||||
azw3: 'application/vnd.amazon.ebook',
|
azw3: 'application/vnd.amazon.ebook',
|
||||||
|
zip: 'application/zip',
|
||||||
|
tar: 'application/x-tar',
|
||||||
|
'tar.gz': 'application/gzip',
|
||||||
|
'tar.bz2': 'application/x-bzip2',
|
||||||
|
'7z': 'application/x-7z-compressed',
|
||||||
|
'tar.7z': 'application/x-7z-compressed',
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function detectInputMime(filePath) {
|
export async function detectInputMime(filePath) {
|
||||||
@@ -67,6 +73,9 @@ function normalizeFormat(format) {
|
|||||||
if (format === 'heif') return 'heic';
|
if (format === 'heif') return 'heic';
|
||||||
if (format === 'azw3') return 'mobi';
|
if (format === 'azw3') return 'mobi';
|
||||||
if (format === 'fb2') return 'xml';
|
if (format === 'fb2') return 'xml';
|
||||||
|
if (format === 'tar.gz') return 'gz';
|
||||||
|
if (format === 'tar.bz2') return 'bz2';
|
||||||
|
if (format === 'tar.7z') return '7z';
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -242,3 +242,38 @@ describe('resolveInputFormat — dfont', () => {
|
|||||||
await fs.unlink(fixturePath);
|
await fs.unlink(fixturePath);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('outputMimeType — archives', () => {
|
||||||
|
it('returns the correct MIME type for each archive target format', () => {
|
||||||
|
expect(outputMimeType('zip')).toBe('application/zip');
|
||||||
|
expect(outputMimeType('tar')).toBe('application/x-tar');
|
||||||
|
expect(outputMimeType('tar.gz')).toBe('application/gzip');
|
||||||
|
expect(outputMimeType('tar.bz2')).toBe('application/x-bzip2');
|
||||||
|
expect(outputMimeType('7z')).toBe('application/x-7z-compressed');
|
||||||
|
expect(outputMimeType('tar.7z')).toBe('application/x-7z-compressed');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('resolveInputFormat — compound archive extensions', () => {
|
||||||
|
it('accepts a real gzip file declared as tar.gz (file-type sniffs the outer gzip layer only)', async () => {
|
||||||
|
const zlib = await import('node:zlib');
|
||||||
|
const fixturePath = path.join(import.meta.dirname, 'fixtures', 'sample.tar.gz');
|
||||||
|
await fs.writeFile(fixturePath, zlib.gzipSync(Buffer.from('irrelevant payload for this check')));
|
||||||
|
|
||||||
|
const result = await resolveInputFormat(fixturePath, 'tar.gz');
|
||||||
|
expect(result.valid).toBe(true);
|
||||||
|
|
||||||
|
await fs.unlink(fixturePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts a real 7z file declared as tar.7z (file-type sniffs the outer 7z layer only)', async () => {
|
||||||
|
const fixturePath = path.join(import.meta.dirname, 'fixtures', 'sample.tar.7z');
|
||||||
|
// Minimal valid 7z signature header (6-byte magic + 2-byte version), enough for file-type to sniff `ext: '7z'`.
|
||||||
|
await fs.writeFile(fixturePath, Buffer.from([0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c, 0x00, 0x04]));
|
||||||
|
|
||||||
|
const result = await resolveInputFormat(fixturePath, 'tar.7z');
|
||||||
|
expect(result.valid).toBe(true);
|
||||||
|
|
||||||
|
await fs.unlink(fixturePath);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user