Refactor and enhance type safety across various modules

- Updated function parameters and return types in `page-preview.ts`, `pdf-decrypt.ts`, and `pymupdf-loader.ts` for improved type safety.
- Introduced type definitions for `CpdfInstance`, `PyMuPDFInstance`, and other related types to ensure better type checking.
- Enhanced error handling in `sanitize.ts` by creating a utility function for error messages.
- Removed unnecessary type assertions and improved type inference in `editor.ts`, `serialization.ts`, and `tools.test.ts`.
- Added type definitions for markdown-it plugins to improve compatibility and type safety.
- Enforced stricter TypeScript settings by enabling `noImplicitAny` in `tsconfig.json`.
- Cleaned up test files by refining type assertions and ensuring consistency in type usage.
This commit is contained in:
alam00000
2026-03-31 17:59:49 +05:30
parent a1fc2fc3c6
commit 9d0b68e18c
114 changed files with 2577 additions and 1868 deletions

View File

@@ -1,5 +1,7 @@
import type { PDFDocumentProxy } from 'pdfjs-dist';
export interface AlternateMergeState {
files: File[];
pdfBytes: Map<string, ArrayBuffer>;
pdfDocs: Map<string, any>;
}
files: File[];
pdfBytes: Map<string, ArrayBuffer>;
pdfDocs: Map<string, PDFDocumentProxy>;
}

View File

@@ -0,0 +1,7 @@
export interface CropBox {
x: number;
y: number;
width: number;
height: number;
scale: number | 'fit';
}

View File

@@ -1,8 +1,18 @@
export interface CropperState {
pdfDoc: any;
currentPageNum: number;
cropper: any;
originalPdfBytes: ArrayBuffer | null;
pageCrops: Record<number, any>;
file: File | null;
import type { PDFDocumentProxy } from 'pdfjs-dist';
import Cropper from 'cropperjs';
export interface CropPercentages {
x: number;
y: number;
width: number;
height: number;
}
export interface CropperState {
pdfDoc: PDFDocumentProxy | null;
currentPageNum: number;
cropper: Cropper | null;
originalPdfBytes: ArrayBuffer | null;
pageCrops: Record<number, CropPercentages>;
file: File | null;
}

View File

@@ -1,7 +1,10 @@
import { PDFDocument as PDFLibDocument } from 'pdf-lib';
import type { PDFDocumentProxy } from 'pdfjs-dist';
export interface DeletePagesState {
file: File | null;
pdfDoc: any;
pdfJsDoc: any;
totalPages: number;
pagesToDelete: Set<number>;
file: File | null;
pdfDoc: PDFLibDocument | null;
pdfJsDoc: PDFDocumentProxy | null;
totalPages: number;
pagesToDelete: Set<number>;
}

View File

@@ -0,0 +1,15 @@
export interface DocManagerPlugin {
onDocumentClosed: (
callback: (data: { id?: string } | string) => void
) => void;
onDocumentOpened: (
callback: (data: { id?: string; name?: string }) => void
) => void;
openDocumentBuffer: (opts: {
buffer: ArrayBuffer;
name?: string;
autoActivate?: boolean;
}) => void;
closeDocument: (id: string) => void;
saveAsCopy: (id: string) => Promise<Uint8Array>;
}

View File

@@ -56,3 +56,12 @@ export * from './pdf-to-tiff-type.ts';
export * from './pdf-to-cbz-type.ts';
export * from './password-prompt-type.ts';
export * from './config-types.ts';
export * from './utils-types.ts';
export * from './merge-worker-type.ts';
export * from './canvas-editor-type.ts';
export * from './edit-pdf-type.ts';
export * from './redact-type.ts';
export * from './shortcuts-type.ts';
export * from './ui-type.ts';
export * from './markdown-editor-type.ts';
export * from './sanitize-type.ts';

View File

@@ -0,0 +1,28 @@
export interface MarkdownItOptions {
html: boolean;
breaks: boolean;
linkify: boolean;
typographer: boolean;
highlight?: (str: string, lang: string) => string;
}
export interface MarkdownItToken {
attrSet(name: string, value: string): void;
[key: string]: unknown;
}
export interface MarkdownItRendererSelf {
renderToken(
tokens: MarkdownItToken[],
idx: number,
options: MarkdownItOptions
): string;
}
export type MarkdownItRenderRule = (
tokens: MarkdownItToken[],
idx: number,
options: MarkdownItOptions,
env: unknown,
self: MarkdownItRendererSelf
) => string;

View File

@@ -1,5 +1,7 @@
import type { PDFDocumentProxy } from 'pdfjs-dist';
export interface MergeState {
files: File[];
pdfBytes: Map<string, ArrayBuffer>;
pdfDocs: Map<string, any>;
files: File[];
pdfBytes: Map<string, ArrayBuffer>;
pdfDocs: Map<string, PDFDocumentProxy>;
}

View File

@@ -0,0 +1,32 @@
export interface MergeJob {
fileName: string;
rangeType: 'all' | 'specific' | 'single' | 'range';
rangeString?: string;
pageIndex?: number;
startPage?: number;
endPage?: number;
}
export interface MergeFile {
name: string;
data: ArrayBuffer;
}
export interface MergeMessage {
command: 'merge';
files: MergeFile[];
jobs: MergeJob[];
cpdfUrl?: string;
}
export interface MergeSuccessResponse {
status: 'success';
pdfBytes: ArrayBuffer;
}
export interface MergeErrorResponse {
status: 'error';
message: string;
}
export type MergeResponse = MergeSuccessResponse | MergeErrorResponse;

View File

@@ -0,0 +1,7 @@
export interface RedactionRect {
pageIndex: number;
canvasX: number;
canvasY: number;
canvasWidth: number;
canvasHeight: number;
}

View File

@@ -0,0 +1,8 @@
import type { PDFDict } from 'pdf-lib';
export interface PDFDocumentInternal {
getInfoDict(): PDFDict;
javaScripts?: unknown[];
embeddedFiles?: unknown[];
fonts?: unknown[];
}

View File

@@ -0,0 +1,5 @@
export interface ToolEntry {
id?: string;
href?: string;
name?: string;
}

5
src/js/types/ui-type.ts Normal file
View File

@@ -0,0 +1,5 @@
export interface FileInputOptions {
multiple?: boolean;
accept?: string;
showControls?: boolean;
}

235
src/js/types/utils-types.ts Normal file
View File

@@ -0,0 +1,235 @@
import type { PDFName, PDFObject } from 'pdf-lib';
export interface PDFDictLike {
keys(): PDFName[];
values(): PDFObject[];
entries(): [PDFName, PDFObject][];
set(key: PDFName, value: PDFObject): void;
get(key: PDFName, preservePDFNull?: boolean): PDFObject | undefined;
has(key: PDFName): boolean;
delete(key: PDFName): boolean;
lookup(key: PDFName): PDFObject | undefined;
asArray?(): PDFObject[];
}
export interface WindowWithCoherentPdf {
coherentpdf?: unknown;
}
export interface WindowWithLucide {
lucide?: {
createIcons(): void;
};
}
export interface WindowWithI18next {
i18next?: {
t(key: string): string;
};
}
export interface GlobalScopeWithGhostscript {
loadGS?: (config: { baseUrl: string }) => Promise<GhostscriptDynamicInstance>;
GhostscriptWASM?: new (url: string) => GhostscriptDynamicInstance;
}
export interface GhostscriptDynamicInstance {
convertToPDFA?(pdfBuffer: ArrayBuffer, profile: string): Promise<ArrayBuffer>;
fontToOutline?(pdfBuffer: ArrayBuffer): Promise<ArrayBuffer>;
init?(): Promise<void>;
}
export interface PyMuPDFCompressOptions {
images: {
enabled: boolean;
quality: number;
dpiTarget: number;
dpiThreshold: number;
convertToGray: boolean;
};
scrub: {
metadata: boolean;
thumbnails: boolean;
xmlMetadata?: boolean;
};
subsetFonts: boolean;
save: {
garbage: 4;
deflate: boolean;
clean: boolean;
useObjstms: boolean;
};
}
export interface PyMuPDFExtractTextOptions {
format?: string;
pages?: number[];
}
export interface PyMuPDFRasterizeOptions {
dpi?: number;
format?: string;
pages?: number[];
grayscale?: boolean;
quality?: number;
}
export interface PyMuPDFDocument {
pageCount: number;
pages: (() => PyMuPDFPage[]) & PyMuPDFPage[];
needsPass: boolean;
isEncrypted: boolean;
authenticate(password: string): boolean;
getPage(index: number): PyMuPDFPage;
save(): Uint8Array;
close(): void;
getLayerConfig?(): unknown[];
addLayer?(name: string): { number: number; xref: number };
setLayerConfig?(layers: unknown[]): void;
setLayerVisibility?(xref: number, visible: boolean): void;
deleteOCG?(xref: number): void;
addOCGWithParent?(
name: string,
parentXref: number
): { number: number; xref: number };
addOCG?(name: string): { number: number; xref: number };
applyRedactions?(): void;
searchFor?(text: string, pageNum: number): unknown[];
}
export interface PyMuPDFPage {
getText(format?: string): string;
getImages(): Array<{ data: Uint8Array; ext: string; xref: number }>;
extractTables?(): unknown[];
findTables(): Array<{
rows: (string | null)[][];
markdown: string;
rowCount: number;
colCount: number;
}>;
extractImage(xref: number): { data: Uint8Array; ext: string } | null;
toSvg?(): string;
toPixmap?(options?: { dpi?: number }): {
toBlob(format: string, quality?: number): Blob;
};
addRedactAnnot?(rect: unknown): void;
searchFor(text: string): unknown[];
addRedaction(rect: unknown, text: string, fill: unknown): void;
applyRedactions(): void;
}
export interface PyMuPDFTextToPdfOptions {
fontSize?: number;
pageSize?: string;
fontName?: string;
textColor?: string;
margins?: number;
}
export interface PyMuPDFDeskewOptions {
threshold?: number;
dpi?: number;
}
export interface PyMuPDFInstance {
load(): Promise<void>;
compressPdf(
file: Blob,
options: PyMuPDFCompressOptions
): Promise<{ blob: Blob; compressedSize: number; usedFallback?: boolean }>;
convertToPdf(
file: Blob | File,
ext: string | { filetype: string }
): Promise<Blob>;
extractText(file: Blob, options?: PyMuPDFExtractTextOptions): Promise<string>;
extractImages(file: Blob): Promise<Array<{ data: Uint8Array; ext: string }>>;
extractTables(file: Blob): Promise<unknown[]>;
toSvg(file: Blob, pageNum: number): Promise<string>;
renderPageToImage(file: Blob, pageNum: number, scale: number): Promise<Blob>;
getPageCount(file: Blob): Promise<number>;
rasterizePdf(
file: Blob | File,
options: PyMuPDFRasterizeOptions
): Promise<Blob>;
open(file: Blob | File, password?: string): Promise<PyMuPDFDocument>;
textToPdf(text: string, options?: PyMuPDFTextToPdfOptions): Promise<Blob>;
pdfToDocx(file: Blob | File): Promise<Blob>;
pdfToMarkdown(
file: Blob | File,
options?: { includeImages?: boolean }
): Promise<string>;
pdfToText(file: Blob | File): Promise<string>;
deskewPdf(
file: Blob,
options?: PyMuPDFDeskewOptions
): Promise<{
pdf: Blob;
result: {
totalPages: number;
correctedPages: number;
angles: number[];
corrected: boolean[];
};
}>;
imageToPdf(file: File, options?: { imageType?: string }): Promise<Blob>;
imagesToPdf(files: File[]): Promise<Blob>;
htmlToPdf(html: string, options: unknown): Promise<Blob>;
pdfToLlamaIndex(file: File): Promise<unknown>;
}
export type { QpdfInstance as QpdfWasmInstance } from '@neslinesli93/qpdf-wasm';
export interface QpdfInstanceExtended {
callMain: (args: string[]) => number;
FS: EmscriptenFSExtended;
}
export interface EmscriptenFSExtended {
mkdir: (path: string) => void;
mount: (
type: unknown,
opts: { blobs: { name: string; data: Blob }[] },
mountPoint: string
) => void;
unmount: (mountPoint: string) => void;
writeFile: (
path: string,
data: Uint8Array | string,
opts?: { encoding?: string }
) => void;
readFile: (path: string, opts?: { encoding?: string }) => Uint8Array;
unlink: (path: string) => void;
analyzePath: (path: string) => { exists: boolean };
}
export interface CpdfInstance {
setSlow: () => void;
fromMemory: (data: Uint8Array, userpw: string) => unknown;
isEncrypted: (pdf: unknown) => boolean;
decryptPdf: (pdf: unknown, password: string) => void;
decryptPdfOwner: (pdf: unknown, password: string) => void;
toMemory: (pdf: unknown, linearize: boolean, makeId: boolean) => Uint8Array;
deletePdf: (pdf: unknown) => void;
startGetBookmarkInfo: (pdf: unknown) => void;
numberBookmarks: () => number;
getBookmarkLevel: (index: number) => number;
getBookmarkPage: (pdf: unknown, index: number) => number;
endGetBookmarkInfo: () => void;
parsePagespec: (pdf: unknown, pagespec: string) => unknown;
removePageLabels: (pdf: unknown) => void;
all: (pdf: unknown) => unknown;
addPageLabels: (
pdf: unknown,
style: unknown,
prefix: string,
offset: number,
range: unknown,
progress: boolean
) => void;
decimalArabic: number;
lowercaseRoman: number;
uppercaseRoman: number;
lowercaseLetters: number;
uppercaseLetters: number;
noLabelPrefixOnly?: number;
}