Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Node.js Guide

This guide covers using printwell with Node.js.

Installation

npm install printwell

Or with yarn:

yarn add printwell

Basic Usage

import { Converter } from 'printwell';

const converter = new Converter();
const result = await converter.htmlToPdf('<h1>Hello, World!</h1>');
await result.writeToFile('output.pdf');

CommonJS

const { Converter } = require('printwell');

async function main() {
    const converter = new Converter();
    const result = await converter.htmlToPdf('<h1>Hello, World!</h1>');
    await result.writeToFile('output.pdf');
}

TypeScript

Full TypeScript support with included type definitions:

import { Converter, PdfOptions, RenderOptions, PdfResult } from 'printwell';

const converter = new Converter();

const options: PdfOptions = {
    pageSize: 'A4',
    margins: { top: 20, right: 15, bottom: 20, left: 15 }
};

const result: PdfResult = await converter.htmlToPdf(html, null, options);

Converting Documents

HTML String to PDF

import { Converter } from 'printwell';

const converter = new Converter();

const html = `
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial; padding: 40px; }
        h1 { color: #333; }
    </style>
</head>
<body>
    <h1>My Document</h1>
    <p>This is a PDF generated from HTML.</p>
</body>
</html>
`;

const result = await converter.htmlToPdf(html);

// Get as Buffer
const buffer = result.data;

// Write to file
await result.writeToFile('output.pdf');

// Get page count
console.log(`Pages: ${result.pageCount}`);

URL to PDF

const result = await converter.urlToPdf('https://example.com');
await result.writeToFile('example.pdf');

Configuration Options

PDF Options

const result = await converter.htmlToPdf(html, null, {
    // Page size: 'A3', 'A4', 'A5', 'Letter', 'Legal', 'Tabloid'
    pageSize: 'A4',

    // Or custom size in mm
    pageWidthMm: 210,
    pageHeightMm: 297,

    // Orientation: 'Portrait' or 'Landscape'
    orientation: 'Portrait',

    // Margins in mm
    margins: {
        top: 20,
        right: 15,
        bottom: 20,
        left: 15
    },

    // Scale factor (0.1 to 2.0)
    scale: 1.0,

    // Print background graphics
    printBackground: true,

    // Page ranges
    pageRanges: '1-5,8,10-12',

    // Headers and footers
    headerTemplate: '<div style="font-size:10px">Header</div>',
    footerTemplate: '<div style="font-size:10px">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>',

    // Metadata
    metadata: {
        title: 'My Document',
        author: 'Author Name',
        subject: 'Document Subject',
        keywords: 'pdf, nodejs'
    }
});

Render Options

const result = await converter.htmlToPdf(html, {
    // Base URL for relative resources
    baseUrl: 'https://example.com/',

    // Viewport
    viewport: {
        width: 1920,
        height: 1080,
        deviceScaleFactor: 2.0
    },

    // Resource loading
    resources: {
        allowRemote: true,
        timeoutMs: 30000,
        blockedDomains: ['ads.example.com'],
        userAgent: 'Custom User Agent'
    },

    // Custom CSS
    userStylesheets: [
        'body { font-family: "Custom Font"; }'
    ]
});

Batch Processing

Converter Pool

For high-throughput scenarios:

import { ConverterPool } from 'printwell';

// Create pool with 4 concurrent converters
const pool = new ConverterPool(4);

// Convert multiple documents
const htmlDocs = [
    '<h1>Document 1</h1>',
    '<h1>Document 2</h1>',
    '<h1>Document 3</h1>'
];

const results = await pool.convertBatch(htmlDocs);

for (let i = 0; i < results.length; i++) {
    await results[i].writeToFile(`output_${i}.pdf`);
}

Parallel Conversion

const urls = [
    'https://example.com/page1',
    'https://example.com/page2',
    'https://example.com/page3'
];

const results = await Promise.all(
    urls.map(url => converter.urlToPdf(url))
);

PDF Post-Processing

Watermarks

import { addWatermark, addWatermarks } from 'printwell';
import { readFile, writeFile } from 'fs/promises';

const pdfData = await readFile('input.pdf');

// Text watermark
const result = addWatermark(pdfData, {
    text: 'CONFIDENTIAL',
    position: 'Center',
    rotation: 45,
    opacity: 0.3,
    fontSize: 72,
    color: { r: 128, g: 128, b: 128 }
});

await writeFile('watermarked.pdf', result);

// Multiple watermarks
const multiResult = addWatermarks(pdfData, [
    { text: 'DRAFT', position: 'Center', opacity: 0.2 },
    { text: 'Page header', position: 'TopCenter', fontSize: 12 }
]);

Bookmarks

import { addBookmarks, extractBookmarks } from 'printwell';

const pdfData = await readFile('input.pdf');

// Add bookmarks
const result = addBookmarks(pdfData, [
    { title: 'Chapter 1', page: 1 },
    { title: 'Chapter 2', page: 5, children: [
        { title: 'Section 2.1', page: 5 },
        { title: 'Section 2.2', page: 8 }
    ]},
    { title: 'Chapter 3', page: 12 }
]);

// Extract existing bookmarks
const bookmarks = extractBookmarks(pdfData);
console.log(bookmarks);

Annotations

import { addAnnotations, listAnnotations, removeAnnotations } from 'printwell';

// Add highlight annotation
const result = addAnnotations(pdfData, [
    {
        type: 'Highlight',
        page: 1,
        rect: { x: 100, y: 700, width: 200, height: 20 },
        color: { r: 255, g: 255, b: 0 },
        opacity: 0.5
    },
    {
        type: 'Text',  // Sticky note
        page: 1,
        rect: { x: 50, y: 600, width: 24, height: 24 },
        contents: 'Review this section',
        author: 'Reviewer'
    }
]);

// List annotations
const annotations = listAnnotations(pdfData);

// Remove all highlight annotations
const cleaned = removeAnnotations(pdfData, {
    types: ['Highlight']
});

Encryption

import { encryptPdf, decryptPdf } from 'printwell';

// Encrypt PDF
const encrypted = encryptPdf(pdfData, {
    ownerPassword: 'admin123',
    userPassword: 'user123',
    permissions: {
        print: true,
        copy: false,
        modify: false,
        annotate: true
    },
    algorithm: 'Aes256'
});

await writeFile('encrypted.pdf', encrypted);

// Decrypt PDF
const decrypted = decryptPdf(encrypted, 'admin123');

Digital Signatures

import { signPdf, signPdfVisible, verifySignatures } from 'printwell';

const pdfData = await readFile('document.pdf');
const certData = await readFile('certificate.p12');

// Invisible signature
const signed = signPdf(pdfData, certData, 'certificate_password', {
    reason: 'Approved',
    location: 'New York',
    signatureLevel: 'PadesB'
});

// Visible signature
const signedVisible = signPdfVisible(pdfData, certData, 'password', {
    reason: 'Approved'
}, {
    page: 1,
    x: 400,
    y: 50,
    width: 200,
    height: 75,
    showName: true,
    showDate: true
});

// Verify signatures
const verifications = verifySignatures(signedData);
for (const v of verifications) {
    console.log(`Signer: ${v.signerName}, Valid: ${v.isValid}`);
}

Form Fields

import { addFormFields, validateFormFields } from 'printwell';

// Add form fields
const result = addFormFields(pdfData, [
    {
        fieldType: 'text',
        name: 'full_name',
        page: 1,
        rect: { x: 100, y: 700, width: 200, height: 20 },
        required: true
    },
    {
        fieldType: 'checkbox',
        name: 'agree_terms',
        page: 1,
        rect: { x: 100, y: 650, width: 15, height: 15 },
        checked: false
    },
    {
        fieldType: 'dropdown',
        name: 'country',
        page: 1,
        rect: { x: 100, y: 600, width: 150, height: 20 },
        options: ['USA', 'Canada', 'UK', 'Other']
    }
]);

// Validate form fields
const validation = validateFormFields(formElements, [
    { fieldName: 'full_name', required: true, minLength: 2 },
    { fieldName: 'email', required: true, pattern: '^[^@]+@[^@]+$' }
]);

console.log(`Valid: ${validation.allValid}`);

PDF/A Compliance

import { validatePdfa, addPdfaMetadata } from 'printwell';

// Validate PDF/A compliance
const result = validatePdfa(pdfData, 'PdfA2b');
console.log(`Compliant: ${result.isCompliant}`);
for (const issue of result.issues) {
    console.log(`${issue.severity}: ${issue.message}`);
}

// Add PDF/A metadata
const pdfaDoc = addPdfaMetadata(pdfData, 'PdfA2b', {
    title: 'Archived Document',
    author: 'Author Name'
});

PDF/UA Accessibility

import { validatePdfua, addPdfuaMetadata } from 'printwell';

// Validate accessibility
const result = validatePdfua(pdfData, 'PdfUA1');
console.log(`Accessible: ${result.isCompliant}`);

// Add accessibility metadata
const accessibleDoc = addPdfuaMetadata(pdfData, 'PdfUA1', {
    language: 'en',
    title: 'Accessible Document',
    generateOutline: true
});

Error Handling

import { Converter } from 'printwell';

try {
    const converter = new Converter();
    const result = await converter.htmlToPdf(html);
    await result.writeToFile('output.pdf');
} catch (error) {
    if (error.code === 'CONVERSION_ERROR') {
        console.error('Failed to convert HTML:', error.message);
    } else if (error.code === 'RESOURCE_ERROR') {
        console.error('Failed to load resource:', error.message);
    } else {
        throw error;
    }
}

Express.js Integration

import express from 'express';
import { Converter } from 'printwell';

const app = express();
const converter = new Converter();

app.get('/generate-pdf', async (req, res) => {
    try {
        const html = `<h1>Generated at ${new Date().toISOString()}</h1>`;
        const result = await converter.htmlToPdf(html);

        res.setHeader('Content-Type', 'application/pdf');
        res.setHeader('Content-Disposition', 'attachment; filename="document.pdf"');
        res.send(result.data);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.listen(3000);