JavaScript
The page-validation-wasm npm package provides a JavaScript API for page, powered by WebAssembly and designed to run in the browser (see this issue for Node.js support).
Installation¶
Check compliance of a PDF¶
isPdfCompliantBytes() is the fastest way to get a simple true/false compliance result for a profile. It uses lazy validation: it stops once it finds a failing rule and returns the boolean directly:
import { isPdfCompliantBytes, ValidationProfile } from "page-validation-wasm";
const bytes = new Uint8Array(await pdfFile.arrayBuffer());
await isPdfCompliantBytes(bytes, { profile: ValidationProfile.PDF_UA_1 });
Both validation functions take the PDF bytes plus an optional { profile, limits } options object. The WebAssembly module loads and starts with the package, so no initialization call is required.
Validate a PDF with details¶
If you need details about which rules failed, use validatePdfBytes() instead:
import { ValidationProfile, validatePdfBytes } from "page-validation-wasm";
const bytes = new Uint8Array(await pdfFile.arrayBuffer());
const report = await validatePdfBytes(bytes, { profile: ValidationProfile.PDF_UA_1 });
if (report.isCompliant) {
console.log("The document passed all implemented rules.");
} else {
console.log(`${report.rules.failed} rules failed`);
console.log(`${report.checks.failed} checks failed`);
for (const failure of report.failures) {
console.log(`[${failure.ruleId}] ${failure.message}`);
}
}
Profile selection¶
If profile isn't specified, it reads the PDF/A or PDF/UA profile declared in the document's XMP metadata. Since this isn't the case for all PDFs, a document that doesn't declare it will reject with PageError:
import { validatePdfBytes } from "page-validation-wasm";
const bytes = new Uint8Array(await pdfFile.arrayBuffer());
const report = await validatePdfBytes(bytes);
The profile is a ValidationProfile:
import { ValidationProfile, validatePdfBytes } from "page-validation-wasm";
const bytes = new Uint8Array(await pdfFile.arrayBuffer());
const report = await validatePdfBytes(bytes, { profile: ValidationProfile.PDF_UA_1 });
You can find all available profiles with:
Failures¶
Each report contains a list of failures:
import { ValidationProfile, validatePdfBytes } from "page-validation-wasm";
const report = await validatePdfBytes(bytes, { profile: ValidationProfile.PDF_UA_1 });
for (const failure of report.failures) {
console.log(`Rule: ${failure.ruleId}`);
console.log(`Category: ${failure.category}`);
console.log(`Message: ${failure.message}`);
}
report.rules contains the total, passed, and failed implemented rules. report.checks.failed counts every raw finding, so several objects failing the same rule contribute one failed rule and multiple failed checks.
Failure categories describe findings from rules that ran on a parsed document:
import { validatePdfBytes } from "page-validation-wasm";
const report = await validatePdfBytes(bytes, { profile: ValidationProfile.PDF_UA_1 });
for (const failure of report.failures) {
if (failure.category === "metadata") {
console.log("metadata finding", failure.ruleId);
} else if (failure.category === "conformance") {
console.log("conformance finding", failure.ruleId);
}
}
Parser, profile, and safety-limit failures reject with PageError and do not appear in a report. PageError.kind identifies the error as input_io, parser, profile, safety_limit, or unknown; PageError.ruleId contains the associated rule identifier when available.
Safety limits¶
Safety limits protect the validator from excessively large or complex inputs. Defaults are sufficient for most cases:
import { SafetyLimits, validatePdfBytes } from "page-validation-wasm";
const limits = new SafetyLimits({
maxInputSize: 256 * 1024 * 1024, // 256 MiB
maxDecodedStreamSize: 32 * 1024 * 1024, // 32 MiB
maxTotalDecodedContentSize: 256 * 1024 * 1024, // 256 MiB
maxFormInvocations: 10_000, // Form XObject expansions per document
maxObjectCount: 1_000_000, // 1,000,000 objects
maxReferenceDepth: 256, // 256 levels
maxXrefRevisions: 1_024, // 1,024 revisions
maxTableSpan: 1_024, // rows or columns per cell
maxTableGridRows: 1_024, // rows
maxTableGridColumns: 1_024, // columns
maxTableGridCells: 1_000_000, // cells
maxUnicodeCmapMappings: 1_000_000, // mappings per ToUnicode CMap
});
const report = await validatePdfBytes(bytes, { limits });
For trusted files, pass SafetyLimits.unlimited() through the limits option:
import { SafetyLimits, validatePdfBytes } from "page-validation-wasm";
const report = await validatePdfBytes(bytes, { limits: SafetyLimits.unlimited() });
The factory returns a fresh object with Infinity in every limit field. The WebAssembly layer translates these values to native integer maxima. You can restore individual bounds by assigning finite values to its fields; partial options objects also accept positive Infinity. Validation may consume unrestricted memory and CPU; see the safety limits guide for details about each limit.
Export the report¶
Validation reports can be exported as JSON:
import { validatePdfBytes } from "page-validation-wasm";
const report = await validatePdfBytes(bytes);
const json = report.toJson();
Use report.toJSON() or JSON.stringify(report) to get the same report structure as a JavaScript object:
const reportData = report.toJSON();
console.log(reportData.is_compliant);
console.log(reportData.failures);
Each JSON failure includes category (metadata or conformance) and object_id. The object ID contains object_number and generation when the finding is attributed to an indirect object, and is null otherwise.