Releases: ABCrimson/modern-pdf-lib
v0.27.0 — Spot Colors, Streaming Parser, Builder Pattern, PDF/X, Plugins
What's New in v0.27.0
The biggest release yet — 29 roadmap items across patch, minor, and major tiers. 82 files changed, 19,668 insertions.
Major Features
- Spot Colors & DeviceN — Separation and DeviceN color spaces for professional print production (
spotColor(),deviceNColor(), CMYK↔RGB conversion) - Streaming PDF Parser — Process multi-GB PDFs without loading into memory via
StreamingPdfParser(Web Streams API) - PdfDocumentBuilder — Fluent builder pattern with method chaining:
.create().setTitle().addPage().save() - PDF/X Compliance — ISO 15930 validation and enforcement (
validatePdfX,enforcePdfX, output intents) - Plugin System — Lifecycle hooks (
onBeforeAddPage,onAfterSave, etc.) withPdfPluginManager+ 3 built-in plugins (timestamp, metadata, accessibility) - Advanced Text Layout — Knuth-Plass line breaking, rich text spans, multi-column layout engine
- Unified Async API —
embedPng()is now async (matchingembedJpeg()) for consistent API - PDF/UA Accessibility — Full validator with enforcement for accessible document creation
Minor Features
- Header/Footer Engine — Template variables (
{page},{pages},{date},{title}), Roman/alpha numbering - Batch Processing —
processBatch(),batchMerge(),batchFlatten()with error strategies (fail-fast/continue/collect) - SVG Gradient Interpolation — Linear RGB interpolation with sRGB gamma correction
- Enhanced Redaction — Overlay alignment options for redaction annotations
- Page Labels & Bookmarks — Full API for document navigation
- Inline WASM Preloading —
preloadInlineWasm()for eager initialization
Patch Fixes
- ES2025+ modernization audit — zero anti-patterns across entire codebase
- TypeScript strict mode compliance (
exactOptionalPropertyTypes) - Operator builder helpers with modern camelCase aliases
Stats
- 5,904 tests passing across 236 test suites
- 82 files changed, +19,668 / -675 lines
- 1 runtime dependency (fflate)
Full Changelog: https://github.com/ABCrimson/modern-pdf-lib/blob/master/CHANGELOG.md
v0.26.0
Added
-
PDF form flattening (
src/form/formFlatten.ts):flattenForm()— burn all form fields into page content, remove AcroFormflattenField()/flattenFields()— flatten specific fields by nameFlattenOptionswithpreserveReadOnlysupport
-
Bookmarks / Outlines API (
src/core/outlines.ts):addBookmark()— add nested bookmarks with bold/italic/color/positiongetBookmarks()— return the full bookmark treeremoveBookmark()/removeAllBookmarks()— bookmark management
-
Page labels (
src/core/pageLabels.ts):setPageLabels()— set label ranges (decimal, roman, alpha, custom prefix)getPageLabels()/removePageLabels()— label management- Catalog integration with
/PageLabelsnumber tree
-
AES-256 encryption (PDF 2.0, V=5 R=6):
- Full writer integration —
doc.encrypt({ algorithm: 'aes-256' })now works end-to-end - Algorithm 2.B key derivation (ISO 32000-2), SASLprep password normalization
%PDF-2.0header for AES-256 encrypted documents- Trailer
/Encryptand/IDdictionary generation
- Full writer integration —
-
SVG-to-PDF vector conversion (enhanced):
- Text rendering with standard font resolution (Helvetica/Times/Courier families)
- Fill-rule support (nonzero/evenodd →
f/f*/B/B*) - Stroke properties: linecap, linejoin, miterlimit, dasharray, dashoffset
- 60 new SVG conversion tests
-
Redaction application (
src/annotation/applyRedactions.ts):applyRedactions()— apply all redaction annotations (fill area, overlay text, remove annotation)applyRedaction()— apply a single redaction by page/annotation index
-
Batch processing (
src/batch/batchProcessor.ts):processBatch()— process multiple PDFs with bounded concurrencybatchMerge()/batchFlatten()— parallel merge and flatten operations- Progress callbacks, error isolation, runtime-aware concurrency
-
PDF linearization (fast web view) — complete rewrite:
linearizePdf()— full page classification, hint tables, xref streamsdelinearizePdf()— convert linearized PDF back to normalgetLinearizationInfo()— extract linearization parameters- Page offset and shared object hint tables per PDF spec §F
-
PDF/UA accessibility validation (
src/accessibility/pdfUaValidator.ts):validatePdfUa()— 12 checks: structure tree, language, title, headings, alt text, tables, lists, reading order, fonts, contrast, bookmarks, tab orderenforcePdfUa()— auto-fix language, title, structure tree, tab order- Page tab order API (
setTabOrder())
-
WASM-by-default infrastructure:
getInlineWasmBytes()— decode base64-embedded WASM at runtimescripts/generate-inline-wasm.ts— build-time code generation for inline WASMgenerate:wasm-inlinenpm script
-
586 new tests across 20+ test files:
- Form flattening (26), outlines (24), page labels (31), AES-256 (55)
- SVG conversion (60 new), redaction (17), batch processing (18)
- Linearization (44), PDF/UA validation (51), inline WASM (17)
- PDF/A enforcement (24), sRGB ICC profile (20), transparency flattener (18)
- JPEG2000 tiles (25), JPEG2000 bit depth (41)
- Object pool (26), PDF value helpers (24), validation (60)
Changed
- WASM loader — now resolves
dist/wasm/layout first (npm consumers), falls back to devsrc/wasm/layout - tsdown config — removed duplicate IIFE config (esbuild script handles it)
- Coverage threshold — branch coverage raised from 80% to 85%
- Modernization audit — 32 changes across 14 source files:
- 22×
isNaN()→Number.isNaN(),isFinite()→Number.isFinite() .indexOf() >= 0→.includes()in generated Acrobat JS- Removed 4
as unknowncasts via proper typing .split('')→[...str]spread for string iteration
- 22×
- PdfWriter — now async with full AES-256 encryption integration
- API audit — comprehensive audit doc at
docs/plans/api-audit-results.md - Test count: 5,135 tests passing across 227 test suites
Fixed
- IIFE test failures from tsdown config removal
fieldVisibilitytest updated for.includes()modernization
Full Changelog: v0.25.0...v0.26.0
v0.25.0 — Test Coverage, Complete Exports, CI/Build Pipeline
Added
-
267 new tests — comprehensive coverage for previously untested security-critical and core modules:
signatureVerifier.test.ts(23 tests) — digital signature verification with tamper detection, multi-sig, hash algorithmssha256.test.ts(28 tests) — NIST FIPS 180-4 test vectors for SHA-256/384/512textShaper.test.ts(32 tests) — Unicode text shaping, RTL, glyph mapping, WASM fallbackjpegEmbed.test.ts(42 tests) — SOF parsing, color space detection, Adobe APP14, error handlingcffEmbed.test.ts(36 tests) — OpenType table directory parsing, tag matching, all standard tagsfreeTextAnnotation.test.ts(16 tests) — creation, parsing, alignment, font sizeinkAnnotation.test.ts(12 tests) — ink list management, multi-path, clear workflowredactAnnotation.test.ts(13 tests) — overlay text, interior color, quad pointsstampAnnotation.test.ts(13 tests) — all 14 standard stamp names, custom stampsdetect.test.ts(16 tests) — runtime detection for Node/Deno/Bun, caching, adapter creationadapter.test.ts(18 tests) — runtime adapter interface, override, stream creationcli.test.ts(18 tests) — help text, argument parsing, validation, optimize command
-
Complete sub-entry point exports:
modern-pdf-lib/create— added ~30 missing exports: gradients, patterns, page manipulation, PDF embedding, QR code options, transparency, document metadatamodern-pdf-lib/parse— addedOperandtype,AnalyzeImagesOptions,PdfParseError,formatHexContextmodern-pdf-lib/forms— added 7 appearance generators + 9 option types for complete form appearance API
Fixed
- CI/CD branch mismatch —
.github/workflows/ci.ymltriggered onmainbut repo usesmaster; CI was never running on pushes or PRs - Missing sidebar entries —
Image FormatsandMulti-Party Signingguides were invisible in VitePress navigation - CI WASM build missing crates —
build-wasm-ci.shwas missingjbig2andjpegmodules (only had 4/6) - WASM binaries excluded from npm package — added
dist/wasm/**topackage.jsonfiles field - No WASM copy step in build pipeline — added
copy:wasmscript to copy built WASM fromsrc/wasm/*/pkg/todist/wasm/ - IIFE bundle not in build pipeline — added
build:iifetobuild:allscript chain
Changed
- Code deduplication — inlined
.toHex()at 8 call sites, removed 3 identical wrapper functions fromocsp.ts,crl.ts,chainValidator.ts - Test count: 4,549 tests passing across 211 test suites (up from 4,282 across 199)
Full Changelog: v0.24.10...v0.25.0
v0.24.10
Added
-
Incremental save with signature preservation (
src/signature/incrementalSave.ts):saveIncrementalWithSignaturePreservation()— preserves all existing signature byte rangesappendIncrementalUpdate()— pure append-only incremental updatesparseExistingTrailer()— parse trailer info from existing PDFfindExistingSignatures()/validateByteRangeIntegrity()— signature detection and validation
-
Multi-signature chain validation (
src/signature/multiSignatureValidator.ts):validateSignatureChain()— validates ordered chain of signatures and byte range coverage
-
MDP certification policy (
src/signature/mdpPolicy.ts):MdpPermissionenum (NoChanges, FormFillAndSign, FormFillSignAnnotate)setCertificationLevel()/getCertificationLevel()— DocMDP transform methods
-
Modification detection (
src/signature/modificationDetector.ts):detectModifications()— checks if modifications exceed MDP-permitted level
-
Signature field locking (
src/signature/fieldLock.ts):addFieldLock()/getFieldLocks()— lock specific fields after signing
-
Document diff (
src/signature/documentDiff.ts):diffSignedContent()— compares signed version vs current content
-
Counter-signatures (
src/signature/counterSignature.ts):addCounterSignature()/getCounterSignatures()— sign existing signatures
-
LTV embedding (
src/signature/ltvEmbed.ts):embedLtvData()— embeds CRL + OCSP + certs in Document Security Store (DSS)hasLtvData()/buildDssDictionary()— LTV data detection and building
-
Incremental save optimization (
src/signature/incrementalOptimizer.ts):optimizeIncrementalSave()— FNV-1a object hashing, only append changed objectsfindChangedObjects()/computeObjectHash()— object-level diff detection
-
WebP image embedding (
src/assets/image/webpDecode.ts):decodeWebP()— pure TypeScript VP8 (lossy) and VP8L (lossless) decoder- Alpha channel support via ALPH chunk parsing
- DCT coefficient decoding, YUV420→RGB, macroblock processing
- LZ77, Huffman coding, spatial prediction (13 modes) for lossless
-
TIFF image embedding (
src/assets/image/tiffDecode.ts):decodeTiff()/decodeTiffPage()/decodeTiffAll()— full TIFF decoder- Uncompressed, PackBits, LZW, Deflate, JPEG-in-TIFF compression support
- Multi-page TIFF (IFD chain following)
getTiffPageCount()/parseTiffIfd()— TIFF introspection
-
TIFF CMYK support (
src/assets/image/tiffCmyk.ts):embedTiffCmyk()— native DeviceCMYK embedding (no RGB conversion)convertTiffCmykToRgb()— CMYK→RGB conversion when needed
-
Image format auto-detection (
src/assets/image/formatDetect.ts):detectImageFormat()— detects PNG/JPEG/WebP/TIFF from magic bytes- Updated
embedImage()to support all 4 formats automatically
-
WebP optimization (
src/assets/image/webpOptimize.ts):webpToJpeg()/webpToPng()— format conversionrecompressWebP()— decode → JPEG/PNG re-encode pipeline
-
TIFF direct embedding (
src/assets/image/tiffDirectEmbed.ts):embedTiffDirect()— direct strip/tile mapping (skip decode/re-encode)canDirectEmbed()— format compatibility check
-
Documentation:
- Multi-signature workflow guide (
docs/guide/multi-sign.md) - Image format support guide (
docs/guide/image-formats.md)
- Multi-signature workflow guide (
Stats
- 4,282 tests passing across 199 suites (+285 new tests)
- Zero TypeScript errors (strict mode + exactOptionalPropertyTypes)
- 15 new source files, 15 new test files, 2 new guides
Full Changelog: v0.22.9...v0.24.10
v0.22.9
Added
-
CRL/OCSP revocation checking (
src/signature/):- OCSP request building, response parsing, and certificate status checking
- CRL parsing, download, and revocation checking with distribution points
- Certificate chain building and validation with Web Crypto signature verification
- TTL-based OCSP/CRL response caching with automatic expiry
- OCSP stapling — embed/extract OCSP responses in PKCS#7 signatures
- Delta CRL parsing and merging with base CRLs (RFC 5280)
- Enhanced verification with structured results (chain, revocation, timestamps)
- Offline revocation data extraction and verification without network
- Custom trust store class for enterprise PKI certificate management
- Key usage, extended key usage, and certificate policy validation
- New guide:
docs/guide/verification.md
-
JPEG2000 (JPXDecode) decoder (
src/parser/):- Full JP2/J2K decoder with MQ arithmetic coder and discrete wavelet transform
- JPXDecode filter integration in the stream decoder pipeline
- JP2 container vs J2K codestream detection and parsing
- Alpha channel detection, separation, and premultiplication
- JP2-to-JPEG transcoding for downstream JPEG workflows
- 16-bit to 8-bit bit depth normalization
- Tiled and region-of-interest decoding for large images
- WASM bridge with automatic JS fallback
- New guide:
docs/guide/jpeg2000.md
-
Form field JavaScript evaluation (
src/form/):- Arithmetic expression evaluator and AFSimple_Calculate parser
- Field calculation order with dependency graphs and topological sort
- AFNumber_Format/Keystroke and AFDate_FormatEx/KeystrokeEx builtins
- Field validation: email, phone, range, regex, and length constraints
- AFPercent_Format, AFSpecial_Format (ZIP, SSN, phone number)
- Field visibility toggle with condition-based show/hide
- getField() cross-field references with field proxy objects
- Document-level scripts: open, close, print, and save actions
- Sandboxed script execution with reserved word filtering and strict mode
- New guide:
docs/guide/form-scripts.md
Changed
- Test count: 3,260 → 3,997 across 184 test suites (was 158).
Full Changelog: v0.19.9...v0.22.9
v0.19.9
Added
-
Table layout engine (
src/layout/): Full-featured table rendering with PDF operators.renderTable()— single-page table rendering to content-stream operatorsrenderMultiPageTable()— automatic page breaks with header row repetition- Column width modes: fixed, percentage, flex (weighted), auto-fit (content-based)
- Cell padding (per-cell or table-wide, four-sided or uniform)
- Horizontal alignment (left, center, right) and vertical alignment (top, middle, bottom)
- Colspan and rowspan with 2D occupation grid tracking
- Alternating row colors, header background/text color
- Nested tables as cell content (recursive rendering)
- Rich cell content with
TextRun[](per-run font, color, size) - Text overflow modes: wrap, truncate, ellipsis, shrink-to-fit
- Styling presets:
minimalPreset(),stripedPreset(),borderedPreset(),professionalPreset() applyPreset()andapplyTablePreset()for named preset selectionPdfPage.drawTable()convenience method- Overflow utilities:
estimateTextWidth(),wrapText(),truncateText(),ellipsisText(),shrinkFontSize() - 200 tests across 11 test files
-
QR code & barcode engine (
src/barcode/): 9 barcode formats with full encoding.- QR code (ISO 18004): versions 1–40, all EC levels (L/M/Q/H), 8 mask patterns, GF(256) Reed-Solomon
- Code 128 (A/B/C auto-switching, mod-103 check digit)
- EAN-13 / EAN-8 with L/G/R patterns and parity tables
- UPC-A (delegates to EAN-13 with leading zero)
- Code 39 with optional mod-43 check digit
- ITF (Interleaved 2 of 5) with bearer bars
- PDF417 (text/byte compaction, RS over GF(929), clusters 0/3/6)
- Data Matrix ECC200 (RS over GF(256), Utah placement algorithm)
renderStyledBarcode()for styled rendering with text, borders, colorsreadBarcode()/readCode128()/readEan13()for round-trip verificationPdfPage.drawQrCode()convenience method- 204 tests across 10 test files
-
Browser utilities (
src/browser/):saveAsDownload(),saveAsBlob(),saveAsDataUrl(),openInNewTab()- Service Worker helpers:
handlePdfRequest(),createPdfResponse(),isCacheAvailable() PdfWorkerclass for Web Worker PDF generation- CSP compatibility:
disableWasmoption,isWasmDisabled(), runtime detection - WASM streaming:
loadWasmModuleStreaming(),instantiateWasmModuleStreaming()
-
PDF/A full enforcement (
src/compliance/):enforcePdfAFull()— complete pipeline chaining all PDF/A fixes- sRGB ICC profile generation (~3KB ICC v2 profile)
- OutputIntent builder with OutputIntentOptions
- ToUnicode CMap generation (WinAnsi, Symbol, ZapfDingbats)
- Transparency detection and flattening
- XMP metadata validation and generation for PDF/A conformance
- PDF/A profile definitions (1a/1b, 2a/2b/2u, 3a/3b/3u)
- Associated files for PDF/A-3 (/AF key)
- Prohibited feature stripping (JavaScript, Launch, Sound, Movie, RichMedia)
- veraPDF CLI wrapper for CI validation
-
Documentation: New guides for tables, barcodes, PDF/A, CSP, and browser integration.
Changed
- Test count: 2,323 → 3,260 across 158 test suites (was 110).
Full Changelog: v0.15.1...v0.19.9
v0.15.1
Fixed
- CLI build: Added
src/cli/index.tsas a tsdown entry point sodist/cli/index.mjsis produced during build. Previously,npx modern-pdf optimizewould fail because the CLI file was never emitted. - CJS compatibility: Replaced top-level
awaitin CLI entry with anasync main()wrapper to avoidTop-level await is not supported with CJS outputbuild errors.
Full Changelog: v0.15.0...v0.15.1
v0.15.0 — JPEG WASM & Image Optimization
Added
- JPEG WASM module: New Rust WASM crate (
src/wasm/jpeg/) usingjpeg-encoder0.7 +jpeg-decoder0.3 for high-performance JPEG encoding and decoding. TypeScript bridge (initJpegWasm(),encodeJpegWasm(),decodeJpegWasm()) with graceful JS fallback when WASM is unavailable. - JPEG quality auto-detection:
estimateJpegQuality(jpegBytes)analyzes DQT (quantization table) markers to reverse-engineer the original JPEG quality level (1–100). Pure TypeScript — no WASM required. - Progressive JPEG support:
progressiveoption for JPEG encoding produces progressive scan-order JPEGs (better for web delivery). - Chroma subsampling control:
chromaSubsamplingoption ('4:4:4'|'4:2:2'|'4:2:0') for JPEG encoding. Default'4:2:0'matches industry standard for smallest files. - CMYK JPEG handling: Automatic CMYK→RGB conversion before JPEG encoding using the standard formula
R = 255 × (1 − C/255) × (1 − K/255). - Batch image optimization API:
optimizeAllImages(doc, options)walks all image XObjects in a parsed PDF, recompresses them as JPEG, and replaces stream data in-place. Returns detailedOptimizationReportwith per-image breakdown. Options:quality,maxDpi,progressive,chromaSubsampling,skipSmallImages,minSavingsPercent,autoGrayscale. - Image extraction API:
extractImages(doc)collects metadata for all image XObjects across all pages.decodeImageStream(imageInfo)decodes stream data for further processing. - Image deduplication:
deduplicateImages(doc)detects identical images by FNV-1a hashing and replaces duplicate references with a single canonical copy. ReturnsDeduplicationReportwith bytes-saved statistics. - Grayscale auto-detection:
isGrayscaleImage()detects RGB images where all pixels are effectively grayscale (R ≈ G ≈ B within tolerance).convertToGrayscale()converts using ITU-R BT.601 luma formula, saving ~66% for RGB→grayscale. - DPI-aware downscaling:
computeImageDpi()andcomputeTargetDimensions()calculate effective DPI from pixel dimensions and display size in points. Used by batch optimizer for automatic DPI-based downscaling. - CLI tool:
npx modern-pdf optimize input.pdf output.pdf [options]— command-line interface for image optimization with--quality,--progressive,--grayscale,--dedup,--chroma,--verboseoptions. - Image optimization VitePress guide (
docs/guide/image-optimization.md): Comprehensive guide covering the full image optimization API, CLI usage, and options reference.
Changed
- WASM modules: 5 → 6 (added
jpegfor JPEG encode/decode). - Test count: 2,243 → 2,323 across 110 test suites (was 103).
- package.json: Added
"bin": { "modern-pdf": "./dist/cli/index.mjs" }for CLI support.
Full Changelog: v0.14.1...v0.15.0
v0.14.1
Added
- Unified
embedImage()method: Auto-detects PNG (magic bytes89 50 4E 47) vs JPEG (FF D8 FF) from the raw file data — no need to callembedPng()orembedJpeg()separately. AcceptsUint8ArrayorArrayBuffer, throws descriptive errors for unsupported formats. - Image optimization API exports:
downscaleImage(),recompressImage(), andoptimizeImage()are now exported from the main entry point along with their option types (DownscaleOptions,RecompressOptions,ImageOptimizeOptions,RawImageData,OptimizeResult). - SASLprep password normalization (RFC 4013): V=5/R=6 (AES-256) password preparation now follows the full SASLprep profile — B.1 "mapped to nothing" characters are stripped, non-ASCII spaces are normalized to U+0020, NFKC normalization is applied, and prohibited characters (control chars, private use, surrogates, tagging) are rejected. This ensures correct password handling for internationalized passwords per ISO 32000-2.
- Visible signature appearances:
signPdf()now accepts anappearanceoption withrect,text,fontSize,backgroundColor,borderColor, andborderWidth. When provided, the signature renders as a visible box on the page with auto-generated text (signer name from certificate CN, reason, location, date) or custom text lines. Uses a PDF Form XObject appearance stream with Helvetica. - Popup annotation type (
PdfPopupAnnotation): Floating window annotation that displays parent annotation text. SupportsisOpen()/setOpen()andsetParent()/getParent()for linking to parent annotations. Reference: PDF 1.7 §12.5.6.14. - Caret annotation type (
PdfCaretAnnotation): Marks text insertion points in review workflows. SupportsgetSymbol()/setSymbol()('None'|'P'for paragraph) andgetCaretRect()/setCaretRect()for inner rectangle (RD) insets. Reference: PDF 1.7 §12.5.6.11. - File attachment annotation type (
PdfFileAttachmentAnnotation): Embeds a file as a clickable icon on a page. SupportsgetIcon()/setIcon()('GraphPushPin'|'PaperclipTag'|'Paperclip'|'Tag'),getFileName(), andbuildFileSpec(registry)for building the embedded file stream, EF dictionary, and file specification. Reference: PDF 1.7 §12.5.6.15. - Digital signatures guide (
docs/guide/signatures.md): Comprehensive guide covering invisible and visible signing, verification, low-level ByteRange API, external signers, RFC 3161 timestamping, and key preparation with OpenSSL. - Accessibility & tagged PDF guide (
docs/guide/accessibility.md): Guide covering document language, title metadata, font embedding for Unicode, color contrast, multilingual content, PDF/UA compliance checklist, and XMP metadata. - Annotations guide (
docs/guide/annotations.md): Complete reference for all 18 annotation types with code examples — Text, Link, FreeText, Highlight, Underline, Squiggly, StrikeOut, Line, Square, Circle, Polygon, PolyLine, Stamp, Ink, Redact, Popup, Caret, FileAttachment. Includes annotation flags, appearance generation, and parsing from existing PDFs.
Performance
- Per-object encryption key caching:
deriveObjectKey()inPdfEncryptionHandlernow caches computed keys in aMap<number, Uint8Array>keyed on(objNum << 16) | genNum. For V=1-4 encrypted PDFs, this eliminates redundant MD5 computations when decrypting multiple strings/streams in the same object. - File-level encryption key caching:
computeFileEncryptionKey()now maintains an LRU cache (max 32 entries) keyed on password + encryption dictionary parameters. Re-opening the same PDF with the same password skips the expensive key derivation (especially Algorithm 2.B for R=6 which runs 64+ rounds of AES+SHA).
Changed
- Annotation count: 15 → 18 annotation types (added Popup, Caret, FileAttachment).
- Test count: 2,199 → 2,243 across 103 test suites (was 100).
Full Changelog: v0.14.0...v0.14.1
v0.14.0 — Performance Audit & Bug Fixes
Performance
Comprehensive internal performance audit across the entire codebase. All changes are internal hot-path optimizations — zero API surface changes.
Lexer & Content Stream Parser:
- String concatenation in
readLiteralString(),readHexString(),readName()replaced withparts[]+.join('')pattern bytesToAscii()/decodeAscii()replaced with batchString.fromCharCode.apply()- Hex string parsing rewritten to single-pass direct byte decoding with
hexVallookup table (eliminates intermediate string +parseInt)
LZW Decompression:
- Complete rewrite with pooled flat buffer (
Uint8Array+Int32Arrayindex pairs) replacing per-entryUint8Array[]allocations - Identity entries (0-255) initialized once and persist across table resets
- Pre-allocated output buffer with manual growth instead of
number[]+.push()
XRef Recovery & Parsing:
rebuildXrefFromScan()rewritten to scan rawUint8Arraybytes directly forobjpattern instead ofTextDecoder.decode()+ regex on the entire file- Standard xref entries parsed directly from bytes (fixed 20-byte format) without TextDecoder
- Keyword checks (
xref,trailer) replaced with direct byte comparison
PDF Object Serialization:
escapeLiteralString(): 5 chained.replace()calls replaced with single-pass character loopPdfName.serialize(): String concatenation replaced with array + joinformatNumber(): Regex trailing-zero trim replaced with manual digit loop
Cryptographic Key Derivation:
- Pre-allocated
modKeybuffer outside 19x RC4 iteration loops in owner/user password verification - Direct K1 buffer construction in Algorithm 2.B (eliminates intermediate concatenation)
Other:
- ASCII85 decoder: Fixed-size group buffer + pre-allocated output
- SVG color parser: Module-level result cache (
Map<string, ParsedColor>) - XMP
escapeXml(): Single-pass character loop replacing chained.replace() - Inline image EI scanning:
data.indexOf(0x45)jump instead of byte-by-byte scan - Object stream header: Array + join replacing string concatenation
Fixed
- CCITT Group 3/4 2D decode bug:
read2DMode()returnedHORIZONTALfor bit pattern011instead ofVERTICAL_PLUS_1— correct logic existed but was unreachable due to premature return. This could cause incorrect rendering of CCITT Group 4 and Group 3 2D compressed images (scanned documents). customNamefont option ignored for empty strings:||operator treated empty string as falsy, falling through topostScriptName. Changed to??(nullish coalescing).embedPages()unnecessarily async: Method was declaredasyncbut contained only synchronous code, wrapping return in an unnecessaryPromise. Now returnsEmbeddedPdfPage[]directly.- Duplicate hash computation in document merge:
hashBytes()was called twice on the same stream data during cross-document page copy. Now computed once and reused.
Removed
- Dead
PdfArrimport alias inpdfWriter.ts - Unused
objectBufvariable allocation in object stream serialization - Unused
objectContainsPageRef()function in linearization module
Full Changelog: v0.13.0...v0.14.0