UNPKG

pdf-node

Version:

A modern, feature-rich PDF generation library for Node.js with TypeScript support. Convert HTML to PDF with Handlebars templates, buffers, and streams.

152 lines 5.37 kB
import * as pdf from 'html-pdf'; import Handlebars from 'handlebars'; import * as ejs from 'ejs'; import handleError from 'cli-error-handler'; const templateCache = {}; export { Handlebars, ejs }; /** * Generates a PDF from an HTML template and data * @param options PDF generation options * @returns Promise that resolves with the generated PDF (as buffer or file info) * @throws {Error} If required options are missing or PDF generation fails */ export function generatePDF(options) { return new Promise((resolve, reject) => { void (async () => { if (!options || !options.html || !options.data) { reject(new Error('Some, or all, options are missing.')); return; } if (options.type !== undefined && options.type !== 'pdf') { reject(new Error('Only PDF file type is supported')); return; } const pdfOptions = options.pdfOptions || {}; const useCache = options.cacheTemplate !== false; // Default to true const engine = options.engine || 'handlebars'; // Get compiled template let html; try { html = await compileTemplate(options.html, options.data, engine, useCache); } catch (error) { handleError('Error generating PDF', error); reject(error); return; } // Check if buffer output is requested if (options.buffer === true) { // Output will be PDF buffer (useful for APIs/web services) pdf.create(html, pdfOptions).toBuffer(function (err, buffer) { if (err) { handleError('error in creating buffer', err); reject(err); return; } // PDF buffer generated successfully resolve({ buffer: buffer, size: buffer.length, type: 'application/pdf' }); }); } else { // Output will be PDF file (default behavior) if (!options.path) { reject(new Error('Path is required when buffer option is not set to true.')); return; } const filepath = options.path; pdf.create(html, pdfOptions).toFile(filepath, function (err, res) { if (err) { handleError('error in creating file', err); reject(err); return; } // File generated successfully resolve(res); }); } })(); }); } /** * Adds a page break to the PDF * @returns HTML string with a page break */ export function addNewPage() { return '<div style="page-break-after: always;"></div>'; } /** * Compiles a template with the specified engine * @param template The template string * @param data Data to inject into the template * @param engine Template engine to use ('handlebars', 'ejs', or 'html') * @param useCache Whether to cache the compiled template * @returns Compiled HTML string */ async function compileTemplate(template, data, engine = 'handlebars', useCache = true) { const cacheKey = useCache ? `${engine}:${template}` : null; // Return cached template if available if (cacheKey && templateCache[cacheKey]) { const cached = templateCache[cacheKey]; if (typeof cached === 'function') { return cached(data); } return cached; } // Compile and cache the template let compiled; switch (engine) { case 'ejs': { try { const ejs = await import('ejs'); const templateFn = ejs.compile(template, { async: true }); compiled = async (data) => await templateFn(data); } catch (error) { throw new Error(`Failed to compile EJS template: ${error}`); } break; } case 'html': { // Simple variable replacement for HTML mode compiled = template.replace(/\{\{([^}]+)\}\}/g, (_, key) => { return data[key.trim()] || ''; }); break; } case 'handlebars': default: { const handlebarsTemplate = Handlebars.compile(template); compiled = (templateData) => Promise.resolve(handlebarsTemplate(templateData)); break; } } // Cache the compiled template if needed if (useCache && cacheKey) { templateCache[cacheKey] = compiled; } return typeof compiled === 'function' ? compiled(data) : compiled; } /** * Clears the template cache */ export function clearTemplateCache() { Object.keys(templateCache).forEach(key => { delete templateCache[key]; }); } const pdfNode = { generatePDF, addNewPage, clearTemplateCache, // Export template engines for advanced usage engines: { handlebars: Handlebars, ejs } }; export default pdfNode; //# sourceMappingURL=index.js.map