mostly formatting, dependency fix
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { PDFDocument, degrees } from "pdf-lib";
|
||||
import type { PdfFile, PageRef, SplitResult, Range } from "./pdfTypes";
|
||||
import { PDFDocument, degrees } from 'pdf-lib';
|
||||
import type { PdfFile, PageRef, SplitResult, Range } from './pdfTypes';
|
||||
|
||||
function createId() {
|
||||
return Math.random().toString(36).slice(2);
|
||||
@@ -12,7 +12,7 @@ function pdfBytesToArrayBuffer(bytes: Uint8Array): ArrayBuffer {
|
||||
}
|
||||
|
||||
function pdfBytesToBlob(bytes: Uint8Array): Blob {
|
||||
return new Blob([pdfBytesToArrayBuffer(bytes)], { type: "application/pdf" });
|
||||
return new Blob([pdfBytesToArrayBuffer(bytes)], { type: 'application/pdf' });
|
||||
}
|
||||
|
||||
export async function loadPdfFromFile(file: File): Promise<PdfFile> {
|
||||
@@ -31,7 +31,7 @@ export async function loadPdfFromFile(file: File): Promise<PdfFile> {
|
||||
export async function mergePdfFiles(
|
||||
basePdf: PdfFile,
|
||||
newPdf: PdfFile,
|
||||
insertAt: number,
|
||||
insertAt: number
|
||||
): Promise<PdfFile> {
|
||||
const baseDoc = basePdf.doc ?? (await PDFDocument.load(basePdf.arrayBuffer));
|
||||
const newDoc = newPdf.doc ?? (await PDFDocument.load(newPdf.arrayBuffer));
|
||||
@@ -45,11 +45,11 @@ export async function mergePdfFiles(
|
||||
|
||||
const basePages = await mergedDoc.copyPages(
|
||||
baseDoc,
|
||||
Array.from({ length: basePageCount }, (_, i) => i),
|
||||
Array.from({ length: basePageCount }, (_, i) => i)
|
||||
);
|
||||
const newPages = await mergedDoc.copyPages(
|
||||
newDoc,
|
||||
Array.from({ length: newPageCount }, (_, i) => i),
|
||||
Array.from({ length: newPageCount }, (_, i) => i)
|
||||
);
|
||||
|
||||
for (let i = 0; i < clampedInsertAt; i += 1) {
|
||||
@@ -65,8 +65,8 @@ export async function mergePdfFiles(
|
||||
const bytes = await mergedDoc.save();
|
||||
const buffer = pdfBytesToArrayBuffer(bytes);
|
||||
|
||||
const baseName = basePdf.name.replace(/\.pdf$/i, "");
|
||||
const newName = newPdf.name.replace(/\.pdf$/i, "");
|
||||
const baseName = basePdf.name.replace(/\.pdf$/i, '');
|
||||
const newName = newPdf.name.replace(/\.pdf$/i, '');
|
||||
|
||||
return {
|
||||
id: createId(),
|
||||
@@ -78,7 +78,7 @@ export async function mergePdfFiles(
|
||||
}
|
||||
|
||||
export async function splitIntoSinglePages(
|
||||
pdf: PdfFile,
|
||||
pdf: PdfFile
|
||||
): Promise<SplitResult[]> {
|
||||
const { doc, name } = pdf;
|
||||
|
||||
@@ -110,8 +110,8 @@ export async function splitIntoSinglePages(
|
||||
const bytes = await newDoc.save();
|
||||
const blob = pdfBytesToBlob(bytes);
|
||||
|
||||
const base = name.replace(/\.pdf$/i, "");
|
||||
const filename = `${base}_page_${String(i + 1).padStart(3, "0")}.pdf`;
|
||||
const base = name.replace(/\.pdf$/i, '');
|
||||
const filename = `${base}_page_${String(i + 1).padStart(3, '0')}.pdf`;
|
||||
|
||||
results.push({
|
||||
pageIndex: i,
|
||||
@@ -131,7 +131,7 @@ export async function extractRange(pdf: PdfFile, range: Range): Promise<Blob> {
|
||||
const toIndex = Math.min(pageCount - 1, range.to - 1);
|
||||
|
||||
if (fromIndex > toIndex) {
|
||||
throw new Error("Invalid range: from > to");
|
||||
throw new Error('Invalid range: from > to');
|
||||
}
|
||||
|
||||
const newDoc = await PDFDocument.create();
|
||||
@@ -161,21 +161,21 @@ export async function mergePdfs(pdfs: PdfFile[]): Promise<Blob> {
|
||||
|
||||
export async function exportPages(
|
||||
pdf: PdfFile,
|
||||
pages: PageRef[],
|
||||
pages: PageRef[]
|
||||
): Promise<Blob> {
|
||||
const { doc } = pdf;
|
||||
const pageCount = doc.getPageCount();
|
||||
|
||||
if (pages.length === 0) {
|
||||
throw new Error("Pages must contain at least one page");
|
||||
throw new Error('Pages must contain at least one page');
|
||||
}
|
||||
|
||||
if (
|
||||
pages.some(
|
||||
(page) => page.sourcePageIndex < 0 || page.sourcePageIndex >= pageCount,
|
||||
(page) => page.sourcePageIndex < 0 || page.sourcePageIndex >= pageCount
|
||||
)
|
||||
) {
|
||||
throw new Error("Pages contain invalid source page indices");
|
||||
throw new Error('Pages contain invalid source page indices');
|
||||
}
|
||||
|
||||
const newDoc = await PDFDocument.create();
|
||||
@@ -186,7 +186,7 @@ export async function exportPages(
|
||||
copiedPages.forEach((page, idx) => {
|
||||
const angle = pages[idx].rotation;
|
||||
|
||||
if (typeof angle === "number" && angle % 360 !== 0) {
|
||||
if (typeof angle === 'number' && angle % 360 !== 0) {
|
||||
page.setRotation(degrees(angle));
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ export async function exportPages(
|
||||
export async function exportReordered(
|
||||
pdf: PdfFile,
|
||||
order: number[],
|
||||
rotations?: Record<number, number>,
|
||||
rotations?: Record<number, number>
|
||||
): Promise<Blob> {
|
||||
return exportPages(
|
||||
pdf,
|
||||
@@ -208,6 +208,6 @@ export async function exportReordered(
|
||||
id: String(sourcePageIndex),
|
||||
sourcePageIndex,
|
||||
rotation: rotations?.[sourcePageIndex] ?? 0,
|
||||
})),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as pdfjsLib from "pdfjs-dist";
|
||||
import pdfjsWorker from "pdfjs-dist/build/pdf.worker?worker&url";
|
||||
import * as pdfjsLib from 'pdfjs-dist';
|
||||
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker?worker&url';
|
||||
|
||||
// pdf.js worker setup for Vite
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -42,7 +42,7 @@ interface ThumbnailGenerationOptions {
|
||||
*/
|
||||
export async function generateThumbnailsProgressive(
|
||||
arrayBuffer: ArrayBuffer,
|
||||
options: ThumbnailGenerationOptions = {},
|
||||
options: ThumbnailGenerationOptions = {}
|
||||
): Promise<string[]> {
|
||||
return generateThumbnailsInternal(arrayBuffer, {}, options);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ export async function generateThumbnailsProgressive(
|
||||
export async function generateThumbnailsWithRotationsProgressive(
|
||||
arrayBuffer: ArrayBuffer,
|
||||
rotations: RotationsMap,
|
||||
options: ThumbnailGenerationOptions = {},
|
||||
options: ThumbnailGenerationOptions = {}
|
||||
): Promise<string[]> {
|
||||
return generateThumbnailsInternal(arrayBuffer, rotations, options);
|
||||
}
|
||||
@@ -61,7 +61,7 @@ export async function generateThumbnailsWithRotationsProgressive(
|
||||
async function generateThumbnailsInternal(
|
||||
arrayBuffer: ArrayBuffer,
|
||||
rotations: RotationsMap,
|
||||
options: ThumbnailGenerationOptions = {},
|
||||
options: ThumbnailGenerationOptions = {}
|
||||
): Promise<string[]> {
|
||||
const maxHeight = options.maxHeight ?? 150;
|
||||
const maxWidth = options.maxWidth ?? 140;
|
||||
@@ -72,15 +72,15 @@ async function generateThumbnailsInternal(
|
||||
const loadingTask = pdfjsLib.getDocument({ data: dataCopy });
|
||||
const pdf = await loadingTask.promise;
|
||||
|
||||
const thumbs = Array<string>(pdf.numPages).fill("");
|
||||
const thumbs = Array<string>(pdf.numPages).fill('');
|
||||
|
||||
const pageNums = options.pageIndices
|
||||
? Array.from(
|
||||
new Set(
|
||||
options.pageIndices
|
||||
.filter((pageIndex) => pageIndex >= 0 && pageIndex < pdf.numPages)
|
||||
.map((pageIndex) => pageIndex + 1),
|
||||
),
|
||||
.map((pageIndex) => pageIndex + 1)
|
||||
)
|
||||
)
|
||||
: Array.from({ length: pdf.numPages }, (_, index) => index + 1);
|
||||
|
||||
@@ -98,7 +98,7 @@ async function generateThumbnailsInternal(
|
||||
pageIndex,
|
||||
rotations,
|
||||
maxHeight,
|
||||
maxWidth,
|
||||
maxWidth
|
||||
);
|
||||
|
||||
if (signal?.aborted) return;
|
||||
@@ -134,13 +134,13 @@ async function generateThumbnailsInternal(
|
||||
async function renderPageThumbnail(
|
||||
page: Awaited<
|
||||
ReturnType<
|
||||
Awaited<ReturnType<typeof pdfjsLib.getDocument>["promise"]>["getPage"]
|
||||
Awaited<ReturnType<typeof pdfjsLib.getDocument>['promise']>['getPage']
|
||||
>
|
||||
>,
|
||||
originalIndex: number,
|
||||
rotations: RotationsMap,
|
||||
maxHeight: number,
|
||||
maxWidth: number,
|
||||
maxWidth: number
|
||||
): Promise<string> {
|
||||
const viewport = page.getViewport({ scale: 1 });
|
||||
const scaleH = maxHeight / viewport.height;
|
||||
@@ -148,15 +148,16 @@ async function renderPageThumbnail(
|
||||
const scale = Math.min(scaleH, scaleW);
|
||||
const scaledViewport = page.getViewport({ scale });
|
||||
|
||||
const baseCanvas = document.createElement("canvas");
|
||||
const baseCtx = baseCanvas.getContext("2d");
|
||||
const baseCanvas = document.createElement('canvas');
|
||||
const baseCtx = baseCanvas.getContext('2d');
|
||||
|
||||
if (!baseCtx) return "";
|
||||
if (!baseCtx) return '';
|
||||
|
||||
baseCanvas.width = scaledViewport.width;
|
||||
baseCanvas.height = scaledViewport.height;
|
||||
|
||||
const renderTask = page.render({
|
||||
canvas: baseCanvas,
|
||||
canvasContext: baseCtx,
|
||||
viewport: scaledViewport,
|
||||
});
|
||||
@@ -167,14 +168,14 @@ async function renderPageThumbnail(
|
||||
const rotationDeg = ((rotationDegRaw % 360) + 360) % 360;
|
||||
|
||||
if (rotationDeg === 0) {
|
||||
return baseCanvas.toDataURL("image/png");
|
||||
return baseCanvas.toDataURL('image/png');
|
||||
}
|
||||
|
||||
const rotatedCanvas = document.createElement("canvas");
|
||||
const rotatedCtx = rotatedCanvas.getContext("2d");
|
||||
const rotatedCanvas = document.createElement('canvas');
|
||||
const rotatedCtx = rotatedCanvas.getContext('2d');
|
||||
|
||||
if (!rotatedCtx) {
|
||||
return baseCanvas.toDataURL("image/png");
|
||||
return baseCanvas.toDataURL('image/png');
|
||||
}
|
||||
|
||||
const rad = (rotationDeg * Math.PI) / 180;
|
||||
@@ -207,5 +208,5 @@ async function renderPageThumbnail(
|
||||
rotatedCtx.drawImage(baseCanvas, 0, 0);
|
||||
rotatedCtx.restore();
|
||||
|
||||
return rotatedCanvas.toDataURL("image/png");
|
||||
return rotatedCanvas.toDataURL('image/png');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PDFDocument } from "pdf-lib";
|
||||
import type { PDFDocument } from 'pdf-lib';
|
||||
|
||||
export interface PdfFile {
|
||||
id: string;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import type { PageRef, PdfFile } from "./pdfTypes";
|
||||
import { generateThumbnailsWithRotationsProgressive } from "./pdfThumbnailService";
|
||||
import { normalizeRotation } from "../workspace/useWorkspaceState";
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import type { PageRef, PdfFile } from './pdfTypes';
|
||||
import { generateThumbnailsWithRotationsProgressive } from './pdfThumbnailService';
|
||||
import { normalizeRotation } from '../workspace/useWorkspaceState';
|
||||
|
||||
const DEFAULT_MAX_HEIGHT = 150;
|
||||
const DEFAULT_MAX_WIDTH = 140;
|
||||
@@ -27,7 +27,7 @@ function thumbnailCacheKey(
|
||||
sourcePageIndex: number,
|
||||
rotation: number,
|
||||
maxWidth: number,
|
||||
maxHeight: number,
|
||||
maxHeight: number
|
||||
): string {
|
||||
return [
|
||||
pdfId,
|
||||
@@ -35,13 +35,13 @@ function thumbnailCacheKey(
|
||||
normalizeRotation(rotation),
|
||||
maxWidth,
|
||||
maxHeight,
|
||||
].join(":");
|
||||
].join(':');
|
||||
}
|
||||
|
||||
function pruneAndMergeThumbnails(
|
||||
previous: Record<string, string>,
|
||||
pages: PageRef[],
|
||||
updates: Record<string, string>,
|
||||
updates: Record<string, string>
|
||||
): Record<string, string> {
|
||||
const pageIds = new Set(pages.map((page) => page.id));
|
||||
const next: Record<string, string> = {};
|
||||
@@ -113,7 +113,7 @@ export function usePdfThumbnails({
|
||||
page.sourcePageIndex,
|
||||
rotation,
|
||||
maxWidth,
|
||||
maxHeight,
|
||||
maxHeight
|
||||
);
|
||||
const cached = thumbnailCacheRef.current.get(cacheKey);
|
||||
|
||||
@@ -128,7 +128,7 @@ export function usePdfThumbnails({
|
||||
}
|
||||
|
||||
setThumbnails((previous) =>
|
||||
pruneAndMergeThumbnails(previous, pages, cachedUpdates),
|
||||
pruneAndMergeThumbnails(previous, pages, cachedUpdates)
|
||||
);
|
||||
|
||||
if (renderGroups.size === 0) return;
|
||||
@@ -162,9 +162,9 @@ export function usePdfThumbnails({
|
||||
pageIndex,
|
||||
rotation,
|
||||
maxWidth,
|
||||
maxHeight,
|
||||
maxHeight
|
||||
),
|
||||
dataUrl,
|
||||
dataUrl
|
||||
);
|
||||
|
||||
const updates: Record<string, string> = {};
|
||||
@@ -184,18 +184,18 @@ export function usePdfThumbnails({
|
||||
pruneAndMergeThumbnails(
|
||||
previous,
|
||||
latestPagesRef.current,
|
||||
updates,
|
||||
),
|
||||
updates
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
void renderMissingThumbnails().catch((error) => {
|
||||
if (!controller.signal.aborted) {
|
||||
onError?.("Failed to generate thumbnails (see console).", error);
|
||||
onError?.('Failed to generate thumbnails (see console).', error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user