@push.rocks/smartpdf 📄✨
Transform HTML, websites, and PDFs into beautiful documents and images with just a few lines of code.
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
🚀 Why SmartPDF?
SmartPDF is your Swiss Army knife for PDF operations in Node.js. Whether you're generating invoices from HTML, snapshotting web pages, merging documents, or converting PDF pages to images — SmartPDF handles it all through a clean, async-first TypeScript API backed by headless Chromium.
✨ Features at a Glance
| Feature | Description |
|---|---|
| 📝 HTML → PDF | Render any HTML string (with full CSS) into an A4-sized PDF |
| 🌐 Website → PDF | Capture a live URL as a PDF — one page the size of its document, or the full-page scroll |
| 🔀 PDF Merging | Combine multiple PDF buffers into a single document |
| 🖼️ PDF → Images | Convert PDF pages to PNG, WebP, or progressive JPEG |
| 🧮 PDF → Pixels | Render pages to raw RGB or gray pixels at an exact DPI, one page at a time, without a browser (for raster printers) |
| 📑 Text Extraction | Pull raw text content from any PDF buffer |
| 🔍 OCR | Add a searchable text layer to scanned PDFs with the system's ocrmypdf |
| 🔌 Smart Port Management | Automatic port allocation so multiple instances never collide |
| 🎛️ DPI Control | Built-in scale constants for screen, high-quality, and print resolutions |
| 🌐 BYO Browser | Optionally pass your own Puppeteer Browser instance |
📦 Installation
pnpm add @push.rocks/smartpdf
Prerequisites: SmartPDF requires Node.js 22.13 or newer and uses headless Chromium through SmartBrowser 5's automation entry and Puppeteer 25. On most systems Chromium is handled automatically. If you run into browser-launch issues (CI, Docker, etc.), make sure the required system libraries are installed and review the Puppeteer troubleshooting guide.
Installed with it: PDF → image rendering uses PDF.js from
pdfjs-dist(Apache-2.0).pdfjs-distdeclares@napi-rs/canvas(MIT; its native binary bundles Google Skia, BSD-3-Clause) as an optional dependency, so a package manager that installs optional dependencies (the default) also fetches that binary for your platform. Rendering does not use it (PDF.js renders in the headless browser); text extraction runs PDF.js in Node.js, which loads it to defineDOMMatrixandPath2Dwhen present (see Extract Text).
Optional system tools for OCR:
ocrPdfBytes()runs OCRmyPDF (MPL-2.0), which drives Tesseract (Apache-2.0) and Ghostscript (AGPL-3.0 or commercial). They are not npm dependencies: install them with the system package manager (e.g.apt install ocrmypdf tesseract-ocr-eng ghostscript) together with the Tesseract language packs you need. SmartPDF only starts them as separate processes; nothing of them is linked into or shipped with this package. Every other feature works without them.
🎯 Quick Start
import { SmartPdf } from '@push.rocks/smartpdf';
import * as fs from 'fs';
// 1. Create and start
const smartPdf = await SmartPdf.create();
await smartPdf.start();
// 2. Generate a PDF from HTML
const pdf = await smartPdf.getA4PdfResultForHtmlString(`
<h1>Hello, PDF World! 🌍</h1>
<p>Generated with SmartPDF.</p>
`);
// 3. Write to disk
fs.writeFileSync('my-first.pdf', pdf.buffer);
// 4. Clean up
await smartPdf.stop();
Every method returns an IPdf object:
interface IPdf {
id: string | null; // Unique identifier
name: string; // Filename
buffer: Buffer; // Raw PDF bytes
metadata?: {
textExtraction?: string; // Extracted text (when available)
};
}
📚 How It Works
SmartPDF spins up a lightweight HTTP server (via @push.rocks/smartserve) bound to localhost and a headless Chromium browser. When you call a generation method:
- Your HTML is registered internally and served at
http://localhost:{port}/{id} - Puppeteer navigates to that URL, waits for the page to fully render, and captures a PDF
- A header-based security check ensures only the correct content is captured
- The server and browser are torn down when you call
stop()
This architecture means you get pixel-perfect CSS rendering, web font support, and full JavaScript execution — the same rendering engine that powers Chrome.
🏗️ Instance Management
const smartPdf = await SmartPdf.create();
await smartPdf.start();
// ... your operations ...
await smartPdf.stop();
For production use, wrap in try/finally:
const smartPdf = await SmartPdf.create();
try {
await smartPdf.start();
// ... generate PDFs ...
} finally {
await smartPdf.stop();
}
SmartPDF leaves SIGINT, SIGTERM and SIGHUP to your program: the browser it launches keeps running when the process receives one of them, so a shutdown handler can finish the PDFs in flight and then call stop(). A program without such a handler ends as Node.js does on these signals, and the browser ends with it.
🔌 Smart Port Allocation
Run multiple instances without conflicts:
// Each instance auto-selects a free port (default range: 20000–30000)
const instance1 = new SmartPdf();
const instance2 = new SmartPdf();
await instance1.start(); // e.g. port 20000
await instance2.start(); // e.g. port 20001
console.log(instance1.serverPort); // 20000
console.log(instance2.serverPort); // 20001
// Custom range
const custom = new SmartPdf({ portRangeStart: 4000, portRangeEnd: 5000 });
// Or pin a specific port
const pinned = new SmartPdf({ port: 3000 });
start() takes a port by listening on it and moves on to the next port of the range when it is in use, so instances that start at the same time, in one process or in several, each get a port of their own. If a specific port is already in use, start() throws an error immediately instead of silently failing.
🌐 Bring Your Own Browser
Pass an existing Puppeteer Browser instance — SmartPDF won't close it when you call stop().
The browser must reach http://localhost:<serverPort> of the process running SmartPDF: HTML → PDF loads your HTML from there, and PDF → image loads the render page, PDF.js and its assets from there too. A browser that runs elsewhere (another host, or a container with its own network) cannot render.
pnpm add @push.rocks/smartpdf @push.rocks/smartbrowser
import { SmartPdf } from '@push.rocks/smartpdf';
import { getEnvAwareBrowserInstance } from '@push.rocks/smartbrowser/automation';
const browser = await getEnvAwareBrowserInstance();
const smartPdf = await SmartPdf.create();
await smartPdf.start(browser); // uses your browser
await smartPdf.stop(); // server stops, browser stays open
await browser.close(); // you manage browser lifecycle
🎨 PDF Generation
📝 HTML → A4 PDF
Renders at a 794×1122 viewport (A4 at 96 DPI) with full CSS support:
const pdf = await smartPdf.getA4PdfResultForHtmlString(`
<style>
body { font-family: 'Helvetica', sans-serif; margin: 40px; }
.header {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white; padding: 30px; border-radius: 10px; text-align: center;
}
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background: #f5f5f5; }
</style>
<div class="header">
<h1>Invoice #2024-001</h1>
</div>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
<tr><td>Widget Pro</td><td>5</td><td>$49.99</td></tr>
<tr><td>Gizmo Ultra</td><td>2</td><td>$129.99</td></tr>
</table>
`);
fs.writeFileSync('invoice.pdf', pdf.buffer);
⏱️ HTML its scripts render: readySelector
By default the page is printed once its network has been idle for half a second (networkidle2). That is no sign
that the page's scripts have finished, and for a page that renders itself (a web component that lays out a document)
it is often later than needed or earlier than right. Let the page say when it is ready instead: its scripts make a
selector match, and the page is printed as soon as it has loaded and the selector matches:
const pdf = await smartPdf.getA4PdfResultForHtmlString(
`<my-invoice data="..."></my-invoice><script type="module">/* sets the attribute "rendered" when done */</script>`,
{ readySelector: 'my-invoice[rendered]' },
);
- The page's own network does not hold the print back: a request that stays open after the page is ready does not delay it.
- A page that does not match the selector within
readyTimeoutMs(default 30,000) fails the render with an error that names the selector and the errors the page threw. - Not with
network: 'blocked', which runs no JavaScript: the combination is refused.
🔒 HTML with text nobody vouches for: network: 'blocked'
By default the page loads what it references, as a browser would. When the HTML carries text a person or a program wrote (a note, a comment, an address), render it with its network blocked, so an image or a stylesheet in that text cannot make the server fetch an address:
const pdf = await smartPdf.getA4PdfResultForHtmlString(reportHtml, { network: 'blocked' });
- Every request but a
data:URI is refused before it leaves the browser: images, stylesheets, fonts, frames and prefetches, and the page is offline. Embed the images, stylesheets and fonts the PDF needs asdata:URIs; a remote reference is not loaded. - The page renders in a browser context of its own whose connections go to a proxy of the render's own that closes
them. Chrome opens a connection ahead of every frame navigation (
<iframe>,<object>,<embed>) before request interception, network emulation or a content security policy apply; through that proxy none of them reaches a host the HTML names. - The document is sandboxed (
Content-Security-Policy: sandbox) and runs no JavaScript: no<meta http-equiv="refresh">replaces it, no form is submitted, and no script opens a channel requests do not cover (a WebSocket, a WebRTC connection). Frames stay empty instead of showing the browser's error page.
🌐 Website → PDF
Two methods depending on your needs:
// Standard capture — uses the document's own dimensions
const pdf = await smartPdf.getPdfResultForWebsite('https://example.com');
// Full-page capture — scrolls to bottom, captures everything as a single page
const fullPdf = await smartPdf.getFullWebsiteAsSinglePdf('https://example.com');
getPdfResultForWebsite uses a 1980×1200 viewport and prints one page the size of the document (the larger of the
root's and the body's scroll width and height). getFullWebsiteAsSinglePdf uses a 1920px-wide viewport, grows it to the
document's scroll height and prints a single tall page.
Both print the page a website settles on. They wait for it to load (networkidle2) and then for one more second; a
navigation of its own in that time — a script's redirect once the page has loaded — is followed to the page it leads
to, up to five times. A navigation that leads to no document (no content, a download, a failed request) leaves the
page as it is. A navigation that starts later still, while the page is measured, is followed once as well. An HTTP
redirect or a navigation while the page loads lands where it leads, as before.
🔀 Merge Multiple PDFs
Combine any number of PDF buffers into one document using pdf-lib:
const invoice = await smartPdf.readFileToPdfObject('./invoice.pdf');
const terms = await smartPdf.readFileToPdfObject('./terms.pdf');
const appendix = await smartPdf.getA4PdfResultForHtmlString('<h1>Appendix</h1>...');
const merged = await smartPdf.mergePdfs([
invoice.buffer,
terms.buffer,
appendix.buffer,
]);
fs.writeFileSync('complete-package.pdf', merged);
📑 Read a PDF from Disk
const pdfObject = await smartPdf.readFileToPdfObject('./document.pdf');
console.log(pdfObject.name); // "document.pdf"
console.log(pdfObject.buffer); // <Buffer ...>
📖 Extract Text
Pull the text of every page from a PDF buffer. No browser is needed, so start() is not required:
const text = await smartPdf.extractTextFromPdfBuffer(pdf.buffer, {
maxPages: 50, // refuse longer documents before any text is read
signal: AbortSignal.timeout(30_000), // stop the work
});
console.log(text);
- Format: the text items of each page in the order PDF.js reports them (the order of the page's content stream), a line break (
\n) where PDF.js ends a line, and a blank line (\n\n, exported asPDF_TEXT_PAGE_SEPARATOR) between pages. Works best with text-based PDFs; scanned documents have no text to read. - Safety: the text is read with the bundled PDF.js 6 (
pdfjs-dist), running in Node.js. It has no eval sink reachable from document data (its Node.js build keeps one constantFunction('return this')()fallback that finds the global object, and compiles nothing from a PDF), so a malicious font cannot run code while its text is read (CVE-2024-4367); only the text layer is read, no page is rendered. - Limits:
maxPagesrefuses a document with more pages with aSmartPdfPageLimitErrorbefore any text is read; an abortedsignalrejects with the signal's reason. - Errors: if the buffer cannot be read as a PDF, the promise rejects with an
Errorwhosecauseis the PDF.js error. - Process: the first extraction loads PDF.js. In Node.js, PDF.js defines
globalThis.DOMMatrixandglobalThis.Path2Dfrom@napi-rs/canvaswhen they are missing; without that optional package it prints a warning for each and text extraction still works.
🔍 OCR Scanned PDFs
Add a searchable text layer to a scanned PDF. No browser is needed, so start() is not required, but ocrmypdf, tesseract and Ghostscript must be installed (see Installation):
const searchablePdf = await smartPdf.ocrPdfBytes(scannedPdfBytes, {
languages: ['eng', 'deu'], // tesseract language packs (default: ocrmypdf's default, eng)
rotatePages: true, // rotate pages to the detected text orientation (default: true)
signal: AbortSignal.timeout(120_000), // stop the run
});
const text = await smartPdf.extractTextFromPdfBuffer(searchablePdf);
- Process: the PDF is piped to
ocrmypdf - -and the result read from its stdout. No shell is involved and SmartPDF writes no files; ocrmypdf keeps its working files in the system temp directory (TMPDIR) and removes them. On POSIX, ocrmypdf and the tesseract and Ghostscript processes it starts run in their own, detached process group: a terminal Ctrl+C or the death of your process does not reach them. Stop a run throughsignal; after your process has died, ocrmypdf ends once it tries to write its output to the closed pipe (EPIPE). On Windows, which has no process groups, ocrmypdf runs as a plain child process. The output is ocrmypdf's default, a PDF/A-2b. - Abort: on POSIX an aborted
signalinterrupts the whole process group (SIGINT, so ocrmypdf removes its working files; SIGKILL if it has not exited after 5 seconds) and rejects with the signal's reason once the group has exited. On Windows only the ocrmypdf process is signalled: Node.js terminates it at once (Windows has no SIGINT for it, so it cannot remove its working files), and the tesseract worker processes it started may continue until their current page completes. If a signal cannot be delivered (e.g.EPERM), the call rejects with that error once ocrmypdf has exited. - Errors: an executable that is missing or not executable (
ENOENT,EACCES) rejects with aSmartPdfOcrUnavailableError. A process that cannot be created for another reason, such as exhausted file descriptors (EMFILE) or process limits (EAGAIN), rejects with aSmartPdfOcrErrorwhoseexitCodeandexitSignalarenulland whosecauseis the spawn error with itscode. A failed run rejects with aSmartPdfOcrErrorcarryingexitCode(ocrmypdf's exit codes, e.g.6for a PDF that already has text,2for input that is no PDF),exitSignalandstderrTail, the end of ocrmypdf's stderr. Language codes are validated before the run (RangeError). - Executable:
ocrmypdfPathselects anotherocrmypdfexecutable than the one found inPATH.
🖼️ PDF → Image Conversion
Convert PDF pages to raster images using Puppeteer + PDF.js. Each page becomes a separate image buffer.
Rendering and untrusted PDFs. SmartPDF bundles PDF.js 6 (
pdfjs-dist), which has no eval sink: neither the library nor its worker callsevalornew Function, the path CVE-2024-4367 used to run JavaScript from a malicious font. TheisEvalSupported: falsesetting that protected older PDF.js versions is gone from PDF.js 6 together with that path, so there is nothing to switch off. PDF.js and all of its assets (worker, WebAssembly image decoders, CMaps, standard fonts, ICC profiles) are read frompdfjs-distand served from SmartPDF's own loopback HTTP server, so nothing is fetched from the internet at render time. The render page and every PDF.js asset are served with a Content-Security-Policy withoutunsafe-eval, so the browser blocksevalandnew Functionin the page and in the PDF.js worker;wasm-unsafe-evallets PDF.js compile the WebAssembly that decodes JBIG2 and JPEG 2000 images and PostScript functions.This protects against script execution from a PDF. It does not bound the work a PDF causes: apart from
maxPagesand the 30-second limit on the in-browser render, there is no memory or CPU limit, so a hostile document can still make a render slow or memory-hungry.The image methods need a headless Chromium (via
start()). PDF.js 6 runs in that browser for them, and in Node.js for text extraction and for page rasters (rasterizePdfPages); the Node.js floor of>=22.13.0is the onepdfjs-distdeclares.
All image methods accept two guard options in addition to scale, maxWidth and maxHeight:
maxPages— refuse a document with more pages than this before any page is rendered (throwsSmartPdfPageLimitError).signal— anAbortSignalthat stops the rendering.
const pages = await smartPdf.convertPDFToPngBytes(untrustedPdf, {
maxPages: 50,
signal: controller.signal,
});
PNG — Lossless Quality
const pngPages = await smartPdf.convertPDFToPngBytes(pdf.buffer, {
scale: SmartPdf.SCALE_HIGH, // 3.0 = ~216 DPI (default)
});
pngPages.forEach((png, i) => {
fs.writeFileSync(`page-${i + 1}.png`, Buffer.from(png));
});
WebP — Modern & Efficient
25–60% smaller than PNG at similar visual quality:
const webpPages = await smartPdf.convertPDFToWebpBytes(pdf.buffer, {
scale: 2.0, // ~144 DPI
quality: 90, // 0–100 (default: 85)
});
JPEG — Progressive Loading
Generates true progressive JPEGs (multi-pass rendering) via sharp:
const jpegPages = await smartPdf.convertPDFToJpegBytes(pdf.buffer, {
scale: SmartPdf.SCALE_HIGH,
quality: 85, // 0–100 (default: 85)
maxWidth: 1920, // optional dimension constraints
maxHeight: 1080,
});
📏 DPI & Scale Reference
All image methods accept a scale parameter. PDF.js renders at 72 DPI by default, so scale is a multiplier:
| Constant | Value | DPI | Use Case |
|---|---|---|---|
SmartPdf.SCALE_SCREEN |
2.0 | ~144 | Web display, thumbnails |
SmartPdf.SCALE_HIGH |
3.0 | ~216 | General purpose (default) |
SmartPdf.SCALE_PRINT |
6.0 | ~432 | Print-quality output |
Or calculate a custom scale:
const scale = SmartPdf.getScaleForDPI(300); // → 4.167
🖼️ Dimension Constraints
All image methods support maxWidth and maxHeight to cap output size while preserving aspect ratio:
// High-res render, but capped at 800×1000 px
const constrained = await smartPdf.convertPDFToWebpBytes(pdf.buffer, {
scale: SmartPdf.SCALE_HIGH,
quality: 90,
maxWidth: 800,
maxHeight: 1000,
});
🧮 Raw Pixels at an Exact DPI
rasterizePdfPages renders each page to raw pixels at the resolution you ask for: what a printer that takes raster pages (PWG Raster, Apple URF) needs, or anything else that works on a page's pixels. A page of w × h points becomes round(w · dpi / 72) × round(h · dpi / 72) pixels as the page shows (its /Rotate applied), in RGB (three bytes a pixel) or gray (one byte, luma), row by row from the top left without padding. Transparent parts are white.
PDF.js renders the pages in Node.js on @napi-rs/canvas, the optional dependency pdfjs-dist renders with in Node.js, so no browser runs and the instance need not be started. PDF.js 6 has no eval sink reachable from document data (see the note above), glyphs are drawn as paths and fonts are never handed to the canvas; JBIG2 and JPEG 2000 images are decoded by PDF.js's WebAssembly decoders from the bundled pdfjs-dist. Rendering runs in your process: an A4 page at 300 dpi takes about 150–300 ms, during which the event loop waits, and the first call in a process also loads PDF.js (about one to two seconds). Without @napi-rs/canvas (optional dependencies skipped, or a platform it has no build for) the first page fails with PDF.js's canvas error. Pass intent: 'print' for pages that go to a printer: annotations are then drawn as they print (one marked not to be printed is left out, one marked not to be viewed but printed is drawn).
The pages come one at a time as they render, so a loop that handles each page before it asks for the next holds one page's pixels at a time (an A4 page at 300 dpi is 2480 × 3508 pixels, 26 MB in RGB). Leaving the loop early ends the rendering. maxPages refuses a longer document before any page renders, a page whose raster would be larger than 32,767 pixels a side or 268,435,456 in all (MAX_RASTER_SIDE, MAX_RASTER_AREA) is refused, and an aborted signal stops the work with its reason.
for await (const page of smartPdf.rasterizePdfPages(pdf.buffer, { dpi: 300, colorSpace: 'gray' })) {
// page.pageNumber, page.pageCount, page.width, page.height, page.dpi, page.colorSpace
// page.pixels: Uint8Array of width × height bytes (gray) or width × height × 3 (rgb)
await sendToPrinter(page);
}
📊 Format Comparison
| Format | Typical Size vs PNG | Lossy? | Transparency | Progressive | Best For |
|---|---|---|---|---|---|
| PNG | baseline | No | ✅ | — | Screenshots, diagrams, text-heavy docs |
| WebP | 40–75% | Yes | ✅ | — | Modern web apps, thumbnails |
| JPEG | 50–70% | Yes | ❌ | ✅ | Photos, complex graphics, email |
⚡ Parallel Processing
Process multiple URLs concurrently with separate instances:
const urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
];
// Spin up parallel instances
const instances = await Promise.all(
urls.map(() => SmartPdf.create())
);
await Promise.all(instances.map(i => i.start()));
// Generate in parallel
const pdfs = await Promise.all(
urls.map((url, i) => instances[i].getFullWebsiteAsSinglePdf(url))
);
// Merge all results
const merged = await instances[0].mergePdfs(pdfs.map(p => p.buffer));
fs.writeFileSync('all-pages.pdf', merged);
// Clean up
await Promise.all(instances.map(i => i.stop()));
📝 Full API Reference
SmartPdf Class
Static Properties
| Property | Type | Value | Description |
|---|---|---|---|
SCALE_SCREEN |
number |
2.0 |
~144 DPI scale factor |
SCALE_HIGH |
number |
3.0 |
~216 DPI scale factor (default) |
SCALE_PRINT |
number |
6.0 |
~432 DPI scale factor |
Static Methods
| Method | Returns | Description |
|---|---|---|
create(options?) |
Promise<SmartPdf> |
Factory method to create an instance |
getScaleForDPI(dpi) |
number |
Converts a DPI value to a scale factor (dpi / 72) |
Instance Properties
| Property | Type | Description |
|---|---|---|
serverPort |
number |
The port the internal HTTP server is listening on |
Instance Methods
| Method | Returns | Description |
|---|---|---|
start(browser?) |
Promise<void> |
Starts internal server + browser. Optionally accepts an existing Puppeteer Browser. |
stop() |
Promise<void> |
Shuts down server and browser (unless external browser was provided). |
getA4PdfResultForHtmlString(html, options?) |
Promise<IPdf> |
Renders HTML at 794×1122 viewport → A4 PDF; { network: 'blocked' } reaches nothing beyond the string; { readySelector, readyTimeoutMs? } prints once the page's scripts make the selector match |
getPdfResultForWebsite(url) |
Promise<IPdf> |
Captures website at 1980×1200 viewport → PDF |
getFullWebsiteAsSinglePdf(url) |
Promise<IPdf> |
Captures full scrollable page at 1920px wide → single-page PDF |
mergePdfs(buffers) |
Promise<Uint8Array> |
Merges an array of PDF Uint8Array buffers |
readFileToPdfObject(path) |
Promise<IPdf> |
Reads a PDF file from disk into an IPdf object |
extractTextFromPdfBuffer(buffer, opts?) |
Promise<string> |
Extracts the text of every page (options: maxPages, signal) |
ocrPdfBytes(buffer, opts?) |
Promise<Uint8Array> |
Adds a text layer to a scanned PDF with ocrmypdf (options: languages, rotatePages, signal, ocrmypdfPath) |
convertPDFToPngBytes(buffer, opts?) |
Promise<Uint8Array[]> |
Converts each PDF page to a PNG buffer |
convertPDFToWebpBytes(buffer, opts?) |
Promise<Uint8Array[]> |
Converts each PDF page to a WebP buffer |
convertPDFToJpegBytes(buffer, opts?) |
Promise<Uint8Array[]> |
Converts each PDF page to a progressive JPEG buffer |
rasterizePdfPages(buffer, opts) |
AsyncGenerator<IPdfPageRaster> |
Renders each page to raw pixels at an exact DPI, one page at a time, in Node.js without a browser (options: dpi, colorSpace 'rgb'/'gray', intent 'display'/'print', maxPages, signal) |
Image Conversion Options
{
scale?: number; // DPI multiplier (default: 3.0)
quality?: number; // 0–100, WebP/JPEG only (default: 85)
maxWidth?: number; // Max output width in pixels
maxHeight?: number; // Max output height in pixels
maxPages?: number; // Refuse longer documents before rendering (SmartPdfPageLimitError)
signal?: AbortSignal; // Stops the rendering
}
ISmartPdfOptions Interface
{
port?: number; // Use a specific port
portRangeStart?: number; // Auto-allocation range start (default: 20000)
portRangeEnd?: number; // Auto-allocation range end (default: 30000)
}
Migration from @push.rocks/smartocr
@push.rocks/smartocr is deprecated; its OCR now ships with SmartPDF.
@push.rocks/smartocr |
@push.rocks/smartpdf |
|---|---|
const ocr = await SmartOcr.createAndInit() |
const smartPdf = await SmartPdf.create() (no start() needed for OCR) |
await ocr.processPdfBuffer(pdfBuffer) → Buffer |
await smartPdf.ocrPdfBytes(pdfBytes) → Uint8Array (wrap with Buffer.from() where a Buffer is needed) |
always --rotate-pages |
rotatePages option, default true |
| — | languages, signal and ocrmypdfPath options |
ran ocrmypdf through a bash command line with temp files in the package's .nogit folder |
runs ocrmypdf without a shell over stdin/stdout |
init() (and so createAndInit()) rejected with not found: ocrmypdf when it was missing; a failed run surfaced as a file-read error |
SmartPdfOcrUnavailableError / SmartPdfOcrError with exit code and stderr tail |
License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license file.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
Company Information
Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.