legal-markdown-js
Version:
Node.js implementation of LegalMarkdown for processing legal documents with markdown and YAML - Complete feature parity with Ruby version
312 lines • 11.8 kB
TypeScript
/**
* PDF Generation Module for Legal Markdown Documents
*
* This module provides functionality to convert processed Legal Markdown content
* into professional PDF documents using Puppeteer for HTML-to-PDF conversion.
* It builds upon the HTML generator to create print-ready documents with
* customizable formatting, page layouts, and styling options.
*
* Features:
* - HTML-to-PDF conversion using Puppeteer
* - Multiple page formats (A4, Letter, Legal)
* - Customizable margins and page orientation
* - Header and footer template support
* - Field highlighting for document review
* - Temporary file management and cleanup
* - Error handling and logging
* - Dual PDF generation (normal and highlighted versions)
*
* @example
* ```typescript
* import { pdfGenerator } from './pdf-generator.js';
*
* const pdf = await pdfGenerator.generatePdf(markdownContent, './output.pdf', {
* format: 'A4',
* landscape: false,
* includeHighlighting: true,
* margin: { top: '2cm', bottom: '2cm' }
* });
* ```
*/
import type { MarkdownString } from '../../types/content-formats.js';
import { HtmlGeneratorOptions } from './html-generator.js';
type PuppeteerModule = typeof import('puppeteer');
declare function loadPuppeteer(): Promise<PuppeteerModule>;
export declare function isPdfAvailable(): Promise<boolean>;
/**
* Configuration options for PDF generation
*
* @interface PdfGeneratorOptions
* @extends HtmlGeneratorOptions
*/
export interface PdfGeneratorOptions extends HtmlGeneratorOptions {
/** Page format for the PDF */
format?: 'A4' | 'Letter' | 'Legal';
/** Whether to use landscape orientation */
landscape?: boolean;
/** Page margins configuration */
margin?: {
/** Top margin (e.g., '1cm', '0.5in') */
top?: string;
/** Right margin (e.g., '1cm', '0.5in') */
right?: string;
/** Bottom margin (e.g., '1cm', '0.5in') */
bottom?: string;
/** Left margin (e.g., '1cm', '0.5in') */
left?: string;
};
/** Whether to display header and footer */
displayHeaderFooter?: boolean;
/** HTML template for page headers */
headerTemplate?: string;
/** HTML template for page footers */
footerTemplate?: string;
/** Whether to print background colors and images */
printBackground?: boolean;
/** Whether to prefer CSS page size over format option */
preferCSSPageSize?: boolean;
/** Path to CSS file for automatic logo detection */
cssPath?: string;
/** Document version to display in footer (optional) */
version?: string;
}
/**
* Detects logo filename from CSS file by parsing --logo-filename custom property
*
* Searches for CSS custom property `--logo-filename` and extracts the filename value.
* Handles quoted and unquoted values, removing whitespace and quotes as needed.
*
* @param {string} cssPath - Path to the CSS file to parse
* @returns {Promise<string | null>} Logo filename or null if not found
* @example
* ```typescript
* // CSS contains: --logo-filename: logo.petalo.png;
* const filename = await detectLogoFromCSS('./styles/contract.css');
* // Returns: 'logo.petalo.png'
* ```
*/
declare function detectLogoFromCSS(cssPath: string): Promise<string | null>;
/**
* Loads and validates logo image file, converting to base64
*
* Performs comprehensive validation:
* - File existence and readability
* - File size limit (500KB max)
* - PNG format validation using magic numbers
* - Base64 encoding for embedding
*
* @param {string} logoPath - Absolute path to the logo image file
* @returns {Promise<string>} Base64 encoded image string
* @throws {Error} When file validation fails
* @example
* ```typescript
* const base64Logo = await loadAndEncodeImage('./assets/images/logo.png');
* // Returns: 'iVBORw0KGgoAAAANSUhEUgAAA...'
* ```
*/
declare function loadAndEncodeImage(logoPath: string): Promise<string>;
/**
* Downloads and validates logo image from external URL, converting to base64
*
* Performs comprehensive validation:
* - URL accessibility and download
* - File size limit (500KB max)
* - PNG format validation using magic numbers
* - Base64 encoding for embedding
*
* @param {string} logoUrl - URL to the logo image
* @returns {Promise<string>} Base64 encoded image string
* @throws {Error} When download or validation fails
* @example
* ```typescript
* const base64Logo = await downloadAndEncodeImage('https://example.com/logo.png');
* // Returns: 'iVBORw0KGgoAAAANSUhEUgAAA...'
* ```
*/
declare function downloadAndEncodeImage(logoUrl: string): Promise<string>;
/**
* PDF Generator for Legal Markdown Documents
*
* Converts processed Legal Markdown content into PDF documents using Puppeteer
* for HTML-to-PDF conversion. Provides comprehensive formatting options and
* supports both normal and highlighted document versions.
*
* @class PdfGenerator
* @example
* ```typescript
* const generator = new PdfGenerator();
* const pdf = await generator.generatePdf(content, './output.pdf', {
* format: 'A4',
* includeHighlighting: true
* });
* ```
*/
export declare class PdfGenerator {
private puppeteerOptions;
/**
* Creates a new PDF generator instance
*
*/
constructor();
/**
* Attempts to find Chrome executable on different platforms
* @private
*/
private getChromeExecutable;
/**
* Attempts to find system Chrome executable
* @private
*/
private getSystemChromeExecutable;
/**
* Attempts to find Puppeteer Chrome executable from cache
* @private
*/
private getPuppeteerChromeExecutable;
/**
* Ensures Chrome is available for Puppeteer, installing it if necessary
* @private
*/
private ensureChrome;
/**
* Gets the first available Puppeteer cache directory
* @private
*/
private getAvailablePuppeteerCache;
/**
* Checks if Puppeteer has a Chrome cache available
* @private
*/
private hasChromiumCache;
/**
* Generates a PDF document from Legal Markdown content
*
* This method orchestrates the complete PDF generation process:
* 1. Converts markdown to HTML using the HTML generator
* 2. Creates a temporary HTML file for Puppeteer
* 3. Launches a headless Chrome browser
* 4. Loads the HTML and generates PDF with specified options
* 5. Cleans up temporary files and browser resources
*
* @param {string} markdownContent - The processed Legal Markdown content
* @param {string} outputPath - Path where the PDF will be saved
* @param {PdfGeneratorOptions} [options={}] - Configuration options for PDF generation
* @returns {Promise<Buffer>} A promise that resolves to the PDF buffer
* @throws {Error} When PDF generation fails due to browser, file system, or processing errors
* @example
* ```typescript
* const pdf = await generator.generatePdf(
* markdownContent,
* './contract.pdf',
* {
* format: 'A4',
* landscape: false,
* includeHighlighting: true,
* margin: { top: '2cm', bottom: '2cm' }
* }
* );
* ```
*/
/**
* Generates a PDF document from Legal Markdown content
*
* @param {MarkdownString} markdownContent - The processed Legal Markdown content (MUST be Markdown, NOT HTML)
* @param {string} outputPath - Path where the PDF file will be saved
* @param {PdfGeneratorOptions} [options={}] - Configuration options for PDF generation
* @returns {Promise<Buffer>} A promise that resolves to the PDF buffer
* @throws {Error} When PDF generation fails
*
* @example
* ```typescript
* import { asMarkdown } from '../../types/content-formats.js';
*
* // ✅ CORRECT - Pass Markdown
* await pdfGenerator.generatePdf(
* asMarkdown('# Contract\n\nContent...'),
* './output/contract.pdf',
* { format: 'A4' }
* );
*
* // ❌ INCORRECT - Don't pass HTML
* await pdfGenerator.generatePdf(
* '<h1>Contract</h1>', // Wrong! This will produce incorrect output
* './output/contract.pdf',
* {}
* );
* ```
*/
generatePdf(markdownContent: MarkdownString, outputPath: string, options?: PdfGeneratorOptions): Promise<Buffer>;
/**
* Generate PDF from pre-generated HTML content
*
* This method accepts HTML that has already been generated by HtmlGenerator
* and converts it directly to PDF, avoiding re-processing the markdown.
* This is the preferred method for the 3-phase pipeline to avoid double conversion.
*
* @param {HtmlString} htmlContent - Pre-generated HTML content
* @param {string} outputPath - Path where the PDF file will be saved
* @param {PdfGeneratorOptions} [options={}] - Configuration options (note: CSS options are ignored since HTML is pre-generated)
* @returns {Promise<Buffer>} A promise that resolves to the PDF buffer
* @throws {Error} When PDF generation fails
*
* @example
* ```typescript
* import { htmlGenerator } from './html-generator.js';
* import { asMarkdown } from '../../types/content-formats.js';
*
* // Generate HTML once
* const html = await htmlGenerator.generateHtml(
* asMarkdown('# Contract\n\nContent...'),
* { cssPath: './styles.css', includeHighlighting: true }
* );
*
* // Use the same HTML for PDF (no re-processing)
* await pdfGenerator.generatePdfFromHtml(html, './contract.pdf', { format: 'A4' });
* ```
*/
generatePdfFromHtml(htmlContent: string, outputPath: string, options?: PdfGeneratorOptions): Promise<Buffer>;
/**
* Generate two PDF versions: one normal and one with highlighting
*
* This method creates two PDF versions of the same document:
* 1. A normal version without field highlighting
* 2. A highlighted version with field annotations
*
* This is useful for document review processes where both clean and
* annotated versions are needed for different purposes.
*
* @param {string} markdownContent - The processed Legal Markdown content
* @param {string} outputPath - Base path for PDF files (will be modified for each version)
* @param {PdfGeneratorOptions} [options={}] - Configuration options for PDF generation
* @returns {Promise<Object>} A promise that resolves to both PDF buffers
* @returns {Buffer} returns.normal - The normal PDF without highlighting
* @returns {Buffer} returns.highlighted - The highlighted PDF with field annotations
* @throws {Error} When PDF generation fails for either version
* @example
* ```typescript
* const { normal, highlighted } = await generator.generatePdfVersions(
* markdownContent,
* './contract.pdf',
* { format: 'A4' }
* );
* // Creates: contract.normal.pdf and contract.highlighted.pdf
* ```
*/
generatePdfVersions(markdownContent: MarkdownString, outputPath: string, options?: PdfGeneratorOptions): Promise<{
normal: Buffer;
highlighted: Buffer;
}>;
}
/**
* Singleton instance of PdfGenerator for convenient importing
*
* {PdfGenerator} pdfGenerator
* @example
* ```typescript
* import { pdfGenerator } from './pdf-generator.js';
* const pdf = await pdfGenerator.generatePdf(content, './output.pdf');
* ```
*/
export declare const pdfGenerator: PdfGenerator;
export { loadPuppeteer as _loadPuppeteer, loadAndEncodeImage as _loadAndEncodeImage, downloadAndEncodeImage as _downloadAndEncodeImage, detectLogoFromCSS as _detectLogoFromCSS, };
//# sourceMappingURL=pdf-generator.d.ts.map