fix(cover): respect PDF crop box during extraction

Render the visible page region so wraparound covers do not appear in generated thumbnails.

Fixes #1242
This commit is contained in:
neon
2026-09-02 00:18:51 +00:00
parent e3779c1d7e
commit 3f06d4eee9
2 changed files with 3 additions and 3 deletions
@@ -25,11 +25,11 @@ describe('extractPdfCover', () => {
mockMkdtemp.mockResolvedValue('/tmp/pdf-cover-abc'); mockMkdtemp.mockResolvedValue('/tmp/pdf-cover-abc');
}); });
it('extracts first-page jpeg bytes and always cleans up temp directory', async () => { it('extracts the first-page crop box as jpeg bytes and always cleans up the temp directory', async () => {
const coverBytes = Buffer.from('cover-bytes'); const coverBytes = Buffer.from('cover-bytes');
mockExecFile.mockImplementation((file, args, callback) => { mockExecFile.mockImplementation((file, args, callback) => {
expect(file).toBe('pdftoppm'); expect(file).toBe('pdftoppm');
expect(args).toEqual(['-jpeg', '-singlefile', '-r', '150', '-f', '1', '-l', '1', '/books/test.pdf', '/tmp/pdf-cover-abc/cover']); expect(args).toEqual(['-jpeg', '-singlefile', '-cropbox', '-r', '150', '-f', '1', '-l', '1', '/books/test.pdf', '/tmp/pdf-cover-abc/cover']);
callback?.(null, '', ''); callback?.(null, '', '');
return {} as never; return {} as never;
}); });
+1 -1
View File
@@ -11,7 +11,7 @@ export async function extractPdfCover(absolutePath: string): Promise<Buffer | nu
const outPrefix = join(tmpDir, 'cover'); const outPrefix = join(tmpDir, 'cover');
try { try {
await execFileAsync('pdftoppm', ['-jpeg', '-singlefile', '-r', '150', '-f', '1', '-l', '1', absolutePath, outPrefix]); await execFileAsync('pdftoppm', ['-jpeg', '-singlefile', '-cropbox', '-r', '150', '-f', '1', '-l', '1', absolutePath, outPrefix]);
return await readFile(`${outPrefix}.jpg`); return await readFile(`${outPrefix}.jpg`);
} finally { } finally {
await rm(tmpDir, { recursive: true, force: true }); await rm(tmpDir, { recursive: true, force: true });