/** * Document - PDF document handling * * This module provides the primary API for working with PDF documents. It handles * document lifecycle, page access, metadata, security, and rendering operations. * * This implementation mirrors the Rust `fitz::document::Document` for 100% API compatibility. * * @module document * @example * ```typescript * import { Document } from 'micropdf'; * * // Open a PDF from a file * const doc = Document.open('document.pdf'); * * // Check if password is required * if (doc.needsPassword()) { * doc.authenticate('password'); * } * * // Get page count * console.log(`Pages: ${doc.pageCount}`); * * // Load and render a page * const page = doc.loadPage(0); * const pixmap = page.toPixmap(Matrix.identity()); * * // Extract text * const text = page.extractText(); * * // Clean up * page.drop(); * doc.close(); * ``` */ import { Buffer } from './buffer.js'; import { Colorspace } from './colorspace.js'; import { Rect, Quad } from './geometry.js'; import type { NativeContext, NativePage } from './native.js'; import { Pixmap } from './pixmap.js'; import { type RenderOptions, type ExtendedRenderOptions } from './render-options.js'; import { type Link, type RectLike, type MatrixLike } from './types.js'; /** * An item in the document outline (table of contents / bookmarks). * * Outline items form a tree structure representing the document's navigation hierarchy. * Each item can link to a page number, URI, or have child items. * * @class OutlineItem * @example * ```typescript * const outline = doc.getOutline(); * for (const item of outline) { * console.log(`${item.title} -> Page ${item.page}`); * for (const child of item.children) { * console.log(` ${child.title} -> Page ${child.page}`); * } * } * ``` */ export declare class OutlineItem { /** * The title/label of this outline item. * @readonly * @type {string} */ readonly title: string; /** * The destination page number (0-indexed), if this item links to a page. * Undefined if this item links to a URI instead. * @readonly * @type {number | undefined} */ readonly page: number | undefined; /** * The destination URI, if this item links to an external resource. * Undefined if this item links to a page instead. * @readonly * @type {string | undefined} */ readonly uri: string | undefined; /** * Child outline items nested under this item. * @readonly * @type {OutlineItem[]} */ readonly children: OutlineItem[]; /** * Creates a new outline item. * * @param {string} title - The title of the outline item * @param {number} [page] - The destination page number (0-indexed) * @param {string} [uri] - The destination URI */ constructor(title: string, page?: number, uri?: string); } /** * A block of text extracted from a PDF page. * * Text blocks represent cohesive units of text, typically paragraphs or sections. * They contain the bounding box, complete text, and structured line information. * * @interface TextBlock * @example * ```typescript * const blocks = page.extractTextBlocks(); * for (const block of blocks) { * console.log(`Block at [${block.bbox.x0}, ${block.bbox.y0}]:`); * console.log(block.text); * console.log(`Contains ${block.lines.length} lines`); * } * ``` */ export interface TextBlock { /** * The bounding box of the entire text block. * @readonly * @type {RectLike} */ readonly bbox: RectLike; /** * The complete text content of this block. * @readonly * @type {string} */ readonly text: string; /** * The individual lines within this block. * @readonly * @type {TextLine[]} */ readonly lines: TextLine[]; } /** * A single line of text extracted from a PDF page. * * Text lines represent a horizontal run of text, typically corresponding to * a single line in the original document layout. * * @interface TextLine * @example * ```typescript * const blocks = page.extractTextBlocks(); * for (const block of blocks) { * for (const line of block.lines) { * console.log(`Line: "${line.text}"`); * console.log(` Font sizes: ${line.spans.map(s => s.size).join(', ')}`); * } * } * ``` */ export interface TextLine { /** * The bounding box of the entire line. * @readonly * @type {RectLike} */ readonly bbox: RectLike; /** * The complete text content of this line. * @readonly * @type {string} */ readonly text: string; /** * The individual text spans within this line. * @readonly * @type {TextSpan[]} */ readonly spans: TextSpan[]; } /** * A span of text with consistent formatting properties. * * Text spans represent runs of text that share the same font, size, and color. * They are the most granular level of text extraction. * * @interface TextSpan * @example * ```typescript * const blocks = page.extractTextBlocks(); * for (const block of blocks) { * for (const line of block.lines) { * for (const span of line.spans) { * console.log(`"${span.text}" - ${span.font} @ ${span.size}pt`); * console.log(` Color: RGB(${span.color.join(', ')})`); * } * } * } * ``` */ export interface TextSpan { /** * The bounding box of this text span. * @readonly * @type {RectLike} */ readonly bbox: RectLike; /** * The text content of this span. * @readonly * @type {string} */ readonly text: string; /** * The font name used for this span. * @readonly * @type {string} */ readonly font: string; /** * The font size in points. * @readonly * @type {number} */ readonly size: number; /** * The text color as RGB values (0-255). * @readonly * @type {number[]} */ readonly color: number[]; } /** * A page in a PDF document. * * Represents a single page within a PDF document with methods for rendering, * text extraction, search, and link retrieval. Pages are loaded from a Document * using `Document.loadPage()`. * * **Important**: Pages must be explicitly freed using `drop()` when no longer needed * to prevent memory leaks. * * @class Page * @example * ```typescript * const doc = Document.open('document.pdf'); * const page = doc.loadPage(0); // Load first page * * try { * // Get page dimensions * console.log(`Size: ${page.bounds.width} x ${page.bounds.height}`); * console.log(`Rotation: ${page.rotation}°`); * * // Extract text * const text = page.extractText(); * console.log(text); * * // Search for text * const hits = page.searchText('hello'); * console.log(`Found ${hits.length} occurrences`); * * // Render to pixmap * const matrix = Matrix.scale(2, 2); // 2x zoom * const pixmap = page.toPixmap(matrix); * } finally { * page.drop(); // Always clean up! * } * * doc.close(); * ``` */ export declare class Page { /** @internal - Native context handle */ _ctx?: NativeContext | undefined; /** @internal - Native page handle */ _page?: NativePage | undefined; private readonly _pageNumber; private readonly _bounds; private readonly _mediaBox; private readonly _rotation; /** @internal */ constructor(_document: Document, pageNumber: number, bounds: Rect, mediaBox: Rect, rotation: number, ctx?: NativeContext, page?: NativePage); /** * Get the page number (0-based) */ get pageNumber(): number; /** * Get the page bounds */ get bounds(): Rect; /** * Get the media box */ get mediaBox(): Rect; /** * Get the crop box */ get cropBox(): Rect; /** * Get the page rotation (0, 90, 180, or 270) */ get rotation(): number; /** * Render the page to a pixmap using FFI * @throws Error when native bindings are not available */ toPixmap(matrix?: MatrixLike, colorspaceOrAlpha?: Colorspace | boolean, alpha?: boolean): Pixmap; /** * Render the page to PNG using FFI * @throws Error when native bindings are not available */ toPNG(dpi?: number): Uint8Array; /** * Render page with advanced options * * Provides fine-grained control over rendering quality, colorspace, * anti-aliasing, and other rendering parameters. * * @param options - Rendering options * @returns Pixmap containing the rendered page * @throws Error if native bindings are not available * @throws Error if options are invalid * * @example * ```typescript * // High-quality print rendering * const pixmap = page.renderWithOptions({ * dpi: 300, * colorspace: Colorspace.deviceRGB(), * alpha: true, * antiAlias: AntiAliasLevel.High * }); * * // Fast preview rendering * const preview = page.renderWithOptions({ * dpi: 72, * antiAlias: AntiAliasLevel.Low * }); * ``` */ renderWithOptions(options?: RenderOptions): Pixmap; /** * Render page with progress tracking * * Extended rendering with progress callbacks and timeout support. * Useful for long-running renders of complex pages. * * @param options - Extended rendering options with callbacks * @returns Promise resolving to the rendered pixmap * @throws Error if rendering fails or times out * * @example * ```typescript * const pixmap = await page.renderWithProgress({ * dpi: 600, * onProgress: (current, total) => { * console.log(`Rendering: ${Math.round(current/total * 100)}%`); * return true; // Continue rendering * }, * onError: (error) => { * console.error('Render error:', error); * }, * timeout: 30000 // 30 second timeout * }); * ``` */ renderWithProgress(options?: ExtendedRenderOptions): Promise; /** * Extract text from the page using FFI * @throws Error when native bindings are not available */ getText(): string; /** * Get text blocks from the page using FFI * @throws Error when native bindings are not available */ getTextBlocks(): TextBlock[]; /** * Get links from the page using FFI * @throws Error when native bindings are not available */ getLinks(): Link[]; /** * Search for text on the page using FFI * @throws Error when native bindings are not available */ search(needle: string): Quad[]; /** * Search for text on the page (alias for search) * * Returns results as Rects (axis-aligned bounding boxes) rather than * Quads, matching the MuPDF Python/C API convention where search * results have x0/y0/x1/y1 properties. */ searchText(needle: string): Rect[]; /** * Extract text from the page (alias for getText for MicroPDF API compatibility) */ extractText(): string; /** * Extract text blocks from the page (alias for getTextBlocks for MicroPDF API compatibility) */ extractTextBlocks(): TextBlock[]; /** * Drop/release the page resources */ drop(): void; /** * Create a minimal valid PNG file (blank white image). * * Used as a fallback when native rendering is unavailable so that * callers always receive data with a valid PNG signature. * * @internal */ static _createMinimalPNG(_w: number, _h: number): Uint8Array; } /** * A PDF or other supported document format. * * The Document class is the main entry point for working with PDF files. It provides * methods for opening documents from files or memory, accessing pages, checking security, * reading metadata, and performing document-level operations. * * **Supported formats**: PDF, XPS, CBZ, and other formats supported by MicroPDF. * * **Resource Management**: Documents must be explicitly closed using `close()` when * done to free native resources and prevent memory leaks. * * @class Document * @example * ```typescript * // Open from file * const doc = Document.open('document.pdf'); * * // Open from buffer * const buffer = fs.readFileSync('document.pdf'); * const doc2 = Document.openFromBuffer(buffer); * * // Check basic info * console.log(`Pages: ${doc.pageCount}`); * console.log(`Title: ${doc.getMetadata('Title')}`); * console.log(`Author: ${doc.getMetadata('Author')}`); * * // Handle password-protected PDFs * if (doc.needsPassword()) { * const success = doc.authenticate('password123'); * if (!success) { * throw new Error('Invalid password'); * } * } * * // Check permissions * if (!doc.hasPermission(4)) { // FZ_PERMISSION_PRINT * console.warn('Printing is not allowed'); * } * * // Work with pages * for (let i = 0; i < doc.pageCount; i++) { * const page = doc.loadPage(i); * const text = page.extractText(); * console.log(`Page ${i + 1}: ${text.substring(0, 100)}...`); * page.drop(); * } * * // Save modified document * doc.save('output.pdf'); * * // Always clean up * doc.close(); * ``` * * @example * ```typescript * // Using try-finally for proper cleanup * const doc = Document.open('document.pdf'); * try { * // Work with document * const page = doc.loadPage(0); * try { * const text = page.extractText(); * console.log(text); * } finally { * page.drop(); * } * } finally { * doc.close(); * } * ``` */ export declare class Document { private _ctx?; private _doc?; private _pages; private _pageCount; private readonly _format; private readonly _metadata; private readonly _outline; private _needsPassword; private _isAuthenticated; private constructor(); /** * Open a document from a file path * Uses native FFI bindings when available for full rendering support */ static open(path: string, password?: string): Document; /** * Open a document from a buffer * Uses native FFI bindings when available for full rendering support */ static fromBuffer(buffer: Buffer, password?: string): Document; /** * Open a document from a Uint8Array */ static fromUint8Array(data: Uint8Array, password?: string): Document; /** * Open a document from a buffer (alias for fromBuffer) * @deprecated Use fromBuffer instead */ static openFromBuffer(buffer: globalThis.Buffer, password?: string): Document; /** * Get the page count. * * The count is preserved after close() so callers can still reference * how many pages the document had. */ get pageCount(): number; /** * Get the document format (e.g., "PDF 1.4") */ get format(): string; /** * Check if the document needs a password. * * Can be called as either a method `doc.needsPassword()` or accessed * as a property `doc.needsPassword`. The implementation uses a * JavaScript getter that is also callable, matching the MuPDF API * convention where this works both ways. * * @returns true if the document requires authentication */ needsPassword(): boolean; /** * Check if the document is authenticated */ get isAuthenticated(): boolean; /** * Check if the document is a PDF */ get isPDF(): boolean; /** * Check if the document is reflowable (e.g., EPUB) */ get isReflowable(): boolean; /** * Authenticate with a password using FFI * @returns true if authentication successful * @throws Error when native bindings are not available */ authenticate(password: string): boolean; /** * Check if the document has a specific permission using FFI * @param permission The permission to check - either a number (4=print, 8=edit, 16=copy, 32=annotate) or string ("print", "edit", "copy", "annotate") * @throws Error when native bindings are not available */ hasPermission(permission: string | number): boolean; /** * Get page label for a given page number * @param pageNum Page number (0-based) * @returns Page label (e.g., "i", "ii", "1", "2", "A-1") */ getPageLabel(pageNum: number): string; /** * Get page number from a page label * @param label Page label to look up * @returns Page number (0-based) or -1 if not found */ getPageFromLabel(label: string): number; /** * Check if the document is valid (not corrupted) */ isValid(): boolean; /** * Resolve a named destination to a page location using FFI * @param name Named destination (e.g., "section1", "chapter2") * @returns Page number (0-based) or undefined if not found * @throws Error when native bindings are not available */ resolveNamedDest(name: string): number | undefined; /** * Count chapters in the document (for structured documents) */ countChapters(): number; /** * Count pages in a specific chapter * @param chapterIndex Chapter index (0-based) */ countChapterPages(chapterIndex: number): number; /** * Get page number from a chapter and page location * @param chapter Chapter index (0-based) * @param page Page within chapter (0-based) */ pageNumberFromLocation(chapter: number, page: number): number; /** * Layout the document with specific width and height (for reflowable documents) * @param width Target width * @param height Target height * @param em Font size in points */ layout(_width: number, _height: number, _em?: number): void; /** * Clone the document (create a copy) * Note: This creates a shallow copy sharing the same data */ clone(): Document; /** * Get a page by index */ getPage(index: number): Page; /** * Load a page by index (alias for getPage for MicroPDF API compatibility) */ loadPage(index: number): Page; /** * Check if the document needs a password (method form for API compatibility) */ needsPasswordCheck(): boolean; /** * Save the document to a file. * * @param path - The file path to save to * @param options - Optional save options (e.g., "incremental", "clean", "sanitize") * @throws {MicroPDFError} If native context is not available or save fails */ save(path: string, options?: string): void; /** * Write the document to a buffer. * * @returns Buffer containing the PDF data * @throws {MicroPDFError} If native context is not available or write fails */ write(): globalThis.Buffer; /** * Close the document and release resources */ close(): void; /** * Iterate over all pages */ pages(): Generator; /** * Get the document outline (table of contents) */ getOutline(): OutlineItem[]; /** * Get metadata value */ getMetadata(key: string): string; /** * Set metadata value */ setMetadata(key: string, value: string): void; /** * Get the title */ get title(): string | undefined; /** * Get the author */ get author(): string | undefined; /** * Get the subject */ get subject(): string | undefined; /** * Get the keywords */ get keywords(): string | undefined; /** * Get the creator application */ get creator(): string | undefined; /** * Get the producer application */ get producer(): string | undefined; } //# sourceMappingURL=document.d.ts.map