pdfnative 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -74,8 +74,26 @@ interface RadialGradientPaint {
74
74
  readonly stops: readonly ColorStop[];
75
75
  readonly extend: GradientExtend;
76
76
  }
77
+ /**
78
+ * A sweep (conic/angular) gradient fill (COLR PaintSweepGradient).
79
+ *
80
+ * PDF has no native conic shading, so the renderer approximates it as a fan
81
+ * of flat-colour triangular wedges clipped to the glyph outline — pure path
82
+ * operators, no shading resource. Angles are in counter-clockwise degrees
83
+ * from the positive x-axis.
84
+ *
85
+ * @since 1.4.0
86
+ */
87
+ interface SweepGradientPaint {
88
+ readonly kind: 'sweep';
89
+ readonly center: readonly [number, number];
90
+ readonly startAngle: number;
91
+ readonly endAngle: number;
92
+ readonly stops: readonly ColorStop[];
93
+ readonly extend: GradientExtend;
94
+ }
77
95
  /** A paint used to fill a colour-glyph layer. */
78
- type ColorPaint = SolidPaint | LinearGradientPaint | RadialGradientPaint;
96
+ type ColorPaint = SolidPaint | LinearGradientPaint | RadialGradientPaint | SweepGradientPaint;
79
97
  /** A single colour-glyph layer: a base outline filled by a paint. */
80
98
  interface ColorLayer {
81
99
  /** Glyph id of the base outline (in the font's `glyf` table). */
@@ -89,6 +107,17 @@ interface ColorLayer {
89
107
  * absent.
90
108
  */
91
109
  readonly transform?: readonly [number, number, number, number, number, number];
110
+ /**
111
+ * Optional PDF blend mode name (`/BM`) for this layer, flattened from a
112
+ * COLRv1 `PaintComposite` whose composite mode maps to a separable or
113
+ * non-separable PDF blend mode (e.g. `Multiply`, `Screen`, `Overlay`,
114
+ * `Darken`, `Lighten`, `Difference`, `Hue`, `Luminosity`). Absent =
115
+ * `Normal`. Porter-Duff structural modes (Clear/Src/Dest/Xor) are not
116
+ * mapped — those glyphs fall back to the monochrome font instead.
117
+ *
118
+ * @since 1.4.0
119
+ */
120
+ readonly blendMode?: string;
92
121
  }
93
122
  /** A resolved colour glyph: ordered layers painted back-to-front. */
94
123
  interface ColorGlyph {
@@ -265,6 +294,14 @@ interface ColumnDef {
265
294
  * @since 1.2.0
266
295
  */
267
296
  readonly kind?: 'amount';
297
+ /**
298
+ * Vertical alignment of this column's cell content within the row band
299
+ * (`'top'` | `'middle'` | `'bottom'`). Overrides the table-level
300
+ * `TableBlock.cellVAlign`. When omitted, the historic baseline placement is
301
+ * preserved (byte-identical to pre-1.4.0).
302
+ * @since 1.4.0
303
+ */
304
+ readonly vAlign?: 'top' | 'middle' | 'bottom';
268
305
  }
269
306
  /**
270
307
  * Options for generating a PDF in a Web Worker via `generatePDFInWorker()`.
@@ -439,6 +476,67 @@ interface PdfLayoutOptions {
439
476
  * @since 1.3.0
440
477
  */
441
478
  readonly creationDate?: Date;
479
+ /**
480
+ * How a conforming viewer should present the document when it is first
481
+ * opened: initial page layout, page mode (bookmark/thumbnail panel, full
482
+ * screen…), window fit/centering, UI-chrome visibility, and whether the
483
+ * window title shows the document title. Maps to catalog `/PageLayout`,
484
+ * `/PageMode`, and the `/ViewerPreferences` dictionary (ISO 32000-1 §12.2).
485
+ *
486
+ * Purely presentational, PDF/A-safe, and fully optional. When the document
487
+ * also has an outline, an explicit `pageMode` here overrides the outline's
488
+ * default `/UseOutlines`.
489
+ *
490
+ * Default: `undefined` (viewer default presentation).
491
+ *
492
+ * @since 1.4.0
493
+ */
494
+ readonly viewerPreferences?: ViewerPreferences;
495
+ }
496
+ /**
497
+ * Viewer presentation preferences (ISO 32000-1 §12.2, Table 150 + §7.7.2).
498
+ * Every field is optional; omitted fields leave the viewer's default behaviour
499
+ * unchanged. Purely presentational and PDF/A-safe.
500
+ *
501
+ * @since 1.4.0
502
+ */
503
+ interface ViewerPreferences {
504
+ /**
505
+ * Initial page layout (catalog `/PageLayout`):
506
+ * - `'singlePage'`: one page at a time
507
+ * - `'oneColumn'`: continuous single column
508
+ * - `'twoColumnLeft'` / `'twoColumnRight'`: continuous two columns, odd pages on the left/right
509
+ * - `'twoPageLeft'` / `'twoPageRight'`: two pages at a time, odd pages on the left/right
510
+ */
511
+ readonly pageLayout?: 'singlePage' | 'oneColumn' | 'twoColumnLeft' | 'twoColumnRight' | 'twoPageLeft' | 'twoPageRight';
512
+ /**
513
+ * Initial page mode (catalog `/PageMode`):
514
+ * - `'useNone'`: neither bookmarks nor thumbnails visible
515
+ * - `'useOutlines'`: bookmark panel open
516
+ * - `'useThumbs'`: thumbnail panel open
517
+ * - `'fullScreen'`: full-screen, no menu/panel
518
+ * - `'useOC'`: optional-content (layers) panel
519
+ * - `'useAttachments'`: attachments panel
520
+ */
521
+ readonly pageMode?: 'useNone' | 'useOutlines' | 'useThumbs' | 'fullScreen' | 'useOC' | 'useAttachments';
522
+ /** Hide the viewer's tool bars. */
523
+ readonly hideToolbar?: boolean;
524
+ /** Hide the viewer's menu bar. */
525
+ readonly hideMenubar?: boolean;
526
+ /** Hide UI elements (scrollbars, navigation controls), leaving only the page. */
527
+ readonly hideWindowUI?: boolean;
528
+ /** Resize the document window to fit the first displayed page. */
529
+ readonly fitWindow?: boolean;
530
+ /** Centre the document window on the screen. */
531
+ readonly centerWindow?: boolean;
532
+ /** Show the document title (from `/Info /Title`) in the window title bar. */
533
+ readonly displayDocTitle?: boolean;
534
+ /** Page mode to use when exiting full-screen (`/NonFullScreenPageMode`). */
535
+ readonly nonFullScreenPageMode?: 'useNone' | 'useOutlines' | 'useThumbs' | 'useOC';
536
+ /** Predominant reading order: left-to-right (default) or right-to-left. */
537
+ readonly direction?: 'l2r' | 'r2l';
538
+ /** Page-scaling default for the Print dialog (`/PrintScaling`). */
539
+ readonly printScaling?: 'none' | 'appDefault';
442
540
  }
443
541
  /**
444
542
  * Relationship of an embedded file to the PDF document (ISO 19005-3 §6.8).
@@ -892,6 +990,31 @@ declare function buildAppearanceStreamDict(w: number, h: number, streamLength: n
892
990
  */
893
991
  declare function buildRadioGroupParent(name: string, selectedValue: string, childObjNums: readonly number[], readOnly: boolean, required: boolean): string;
894
992
 
993
+ /**
994
+ * pdfnative — Page Labels (ISO 32000-1 §12.4.2)
995
+ * ==============================================
996
+ * Builds the `/PageLabels` number tree placed in the document catalog.
997
+ * Page labels control the page numbering shown in a viewer's page-number
998
+ * box and thumbnails (e.g. roman-numeral front matter `i, ii, iii`,
999
+ * decimal body `1, 2, 3`, prefixed appendices `A-1, A-2`).
1000
+ *
1001
+ * The builder is **pure** and emits an inline dictionary string — page
1002
+ * labels require no indirect objects. Output is PDF/A-safe.
1003
+ */
1004
+ /** Page-numbering style for a {@link PageLabelRange}. */
1005
+ type PageLabelStyle = 'decimal' | 'roman' | 'Roman' | 'alpha' | 'Alpha' | 'none';
1006
+ /** A contiguous run of pages sharing a numbering scheme. */
1007
+ interface PageLabelRange {
1008
+ /** 0-based index of the first page in this range. */
1009
+ readonly startPage: number;
1010
+ /** Numbering style. Omit or use `'none'` for prefix-only labels. */
1011
+ readonly style?: PageLabelStyle;
1012
+ /** Optional label prefix (e.g. `'A-'`). */
1013
+ readonly prefix?: string;
1014
+ /** First numeric value in the range (default `1`). */
1015
+ readonly start?: number;
1016
+ }
1017
+
895
1018
  /**
896
1019
  * pdfnative — Document Content Model Types
897
1020
  * ==========================================
@@ -1007,14 +1130,77 @@ interface TableBlock {
1007
1130
  * @since 1.2.0
1008
1131
  */
1009
1132
  readonly cellPadding?: number;
1133
+ /**
1134
+ * Draw borders around each header/data cell. When omitted, no cell borders
1135
+ * are drawn (byte-identical to pre-1.4.0 — the table keeps only its header
1136
+ * underline and row separators). See {@link CellBorders}.
1137
+ *
1138
+ * @since 1.4.0
1139
+ */
1140
+ readonly cellBorders?: CellBorders;
1141
+ /**
1142
+ * Vertical alignment of cell content within the row band: `'top'`,
1143
+ * `'middle'`, or `'bottom'`. A per-column {@link ColumnDef.vAlign} overrides
1144
+ * this. When omitted, the historic baseline placement is preserved exactly
1145
+ * (byte-identical to pre-1.4.0).
1146
+ *
1147
+ * @since 1.4.0
1148
+ */
1149
+ readonly cellVAlign?: 'top' | 'middle' | 'bottom';
1150
+ }
1151
+ /**
1152
+ * Per-cell border configuration for a {@link TableBlock}. All sides are off by
1153
+ * default; enable individual sides or use `all: true`. Pure vector strokes
1154
+ * (`re`/`l`/`S`), so output stays PDF/A-safe.
1155
+ *
1156
+ * @since 1.4.0
1157
+ */
1158
+ interface CellBorders {
1159
+ /** Draw the top edge of each cell. */
1160
+ readonly top?: boolean;
1161
+ /** Draw the right edge of each cell. */
1162
+ readonly right?: boolean;
1163
+ /** Draw the bottom edge of each cell. */
1164
+ readonly bottom?: boolean;
1165
+ /** Draw the left edge of each cell. */
1166
+ readonly left?: boolean;
1167
+ /** Draw all four edges (shorthand; overrides the individual side flags). */
1168
+ readonly all?: boolean;
1169
+ /** Stroke colour. Default: `'0.8 0.8 0.8'` (light grey). */
1170
+ readonly color?: PdfColor;
1171
+ /** Stroke width in points. Default: `0.5`. */
1172
+ readonly width?: number;
1173
+ /** Stroke style. Default: `'solid'`. */
1174
+ readonly style?: 'solid' | 'dashed' | 'dotted';
1010
1175
  }
1011
1176
  /** List block — bullet or numbered items. */
1012
1177
  interface ListBlock {
1013
1178
  readonly type: 'list';
1014
- readonly items: readonly string[];
1179
+ /**
1180
+ * List entries. Each entry is either a plain string (leaf item) or a
1181
+ * {@link ListItem} object that can carry its own nested sub-list, enabling
1182
+ * hierarchical (multi-level) bullet/numbered lists. Plain strings and
1183
+ * nested objects may be freely mixed. Passing only strings is byte-identical
1184
+ * to the pre-1.4.0 flat-list behaviour.
1185
+ */
1186
+ readonly items: readonly (string | ListItem)[];
1015
1187
  readonly style: 'bullet' | 'numbered';
1016
1188
  readonly fontSize?: number;
1017
1189
  }
1190
+ /**
1191
+ * A single hierarchical list entry: text plus an optional nested sub-list.
1192
+ * Used by {@link ListBlock} to build multi-level outlines (bullets within
1193
+ * bullets, numbered sub-items, …). Sub-items inherit the parent list's
1194
+ * `style`; numbered sub-lists restart their numbering at 1.
1195
+ *
1196
+ * @since 1.4.0
1197
+ */
1198
+ interface ListItem {
1199
+ /** The item's text content. */
1200
+ readonly text: string;
1201
+ /** Optional nested child entries (recursive). */
1202
+ readonly items?: readonly (string | ListItem)[];
1203
+ }
1018
1204
  /** Spacer block — vertical whitespace. */
1019
1205
  interface SpacerBlock {
1020
1206
  readonly type: 'spacer';
@@ -1131,6 +1317,38 @@ interface DocumentMetadata {
1131
1317
  readonly subject?: string;
1132
1318
  readonly keywords?: string;
1133
1319
  }
1320
+ /**
1321
+ * A document outline (bookmark) entry — ISO 32000-1 §12.3.3.
1322
+ *
1323
+ * Outline items form a navigable tree shown in a viewer's bookmarks
1324
+ * panel. Each item points at a 0-based page index and may nest children.
1325
+ * Bookmarks are purely navigational and PDF/A-safe.
1326
+ *
1327
+ * @since 1.4.0
1328
+ */
1329
+ interface OutlineItem {
1330
+ /** Bookmark label (UTF-16BE encoded automatically). */
1331
+ readonly title: string;
1332
+ /** 0-based destination page index. */
1333
+ readonly pageIndex: number;
1334
+ /** Destination Y coordinate in points (default: top of page). */
1335
+ readonly y?: number;
1336
+ /** Render the label bold (`/F` flag bit 2). */
1337
+ readonly bold?: boolean;
1338
+ /** Render the label italic (`/F` flag bit 1). */
1339
+ readonly italic?: boolean;
1340
+ /** Label colour (`/C`). Accepts hex, RGB tuple, or PDF operator string. */
1341
+ readonly color?: PdfColor;
1342
+ /**
1343
+ * Initial expansion state. `true` (default) renders the bookmark expanded
1344
+ * (positive `/Count`); `false` renders it collapsed (negative `/Count`),
1345
+ * hiding its children until the reader expands it. Only meaningful when the
1346
+ * item has `children`.
1347
+ */
1348
+ readonly open?: boolean;
1349
+ /** Nested child bookmarks. */
1350
+ readonly children?: readonly OutlineItem[];
1351
+ }
1134
1352
  /**
1135
1353
  * Parameters for the free-form document PDF builder.
1136
1354
  *
@@ -1154,6 +1372,26 @@ interface DocumentParams {
1154
1372
  readonly fontEntries?: readonly FontEntry[];
1155
1373
  readonly metadata?: DocumentMetadata;
1156
1374
  readonly layout?: Partial<PdfLayoutOptions>;
1375
+ /**
1376
+ * Document outline / bookmarks (ISO 32000-1 §12.3.3).
1377
+ *
1378
+ * - An array of {@link OutlineItem}s builds an explicit bookmark tree.
1379
+ * - The literal `'auto'` derives a flat outline from every `heading`
1380
+ * block in document order, using each heading's page and position.
1381
+ *
1382
+ * Adds `/Outlines` + `/PageMode /UseOutlines` to the catalog. PDF/A-safe.
1383
+ *
1384
+ * @since 1.4.0
1385
+ */
1386
+ readonly outline?: readonly OutlineItem[] | 'auto';
1387
+ /**
1388
+ * Page labels (ISO 32000-1 §12.4.2) — controls the page numbering shown
1389
+ * in a viewer's page box and thumbnails (e.g. roman front matter then
1390
+ * decimal body). Emitted as an inline `/PageLabels` number tree. PDF/A-safe.
1391
+ *
1392
+ * @since 1.4.0
1393
+ */
1394
+ readonly pageLabels?: readonly PageLabelRange[];
1157
1395
  }
1158
1396
 
1159
1397
  /**
@@ -1808,6 +2046,83 @@ declare function verifyCertSignature(cert: X509Certificate, issuerCert: X509Cert
1808
2046
  */
1809
2047
  declare function isSelfSigned(cert: X509Certificate): boolean;
1810
2048
 
2049
+ /**
2050
+ * pdfnative — Pluggable Signature Crypto Provider
2051
+ * ================================================
2052
+ * pdfnative ships its own pure-TypeScript RSA (PKCS#1 v1.5) and ECDSA (P-256)
2053
+ * implementations so that signing works in any runtime with **zero
2054
+ * dependencies**. Those pure-JS primitives are built on JavaScript `BigInt`
2055
+ * arithmetic, which V8/SpiderMonkey do **not** execute in constant time — see
2056
+ * the timing-side-channel caveat in `SECURITY.md`.
2057
+ *
2058
+ * For high-security, high-frequency server pipelines (a backend signing many
2059
+ * PDFs/s with one key under adversarial timing observation), this module lets
2060
+ * you inject a hardware-backed, **constant-time** signer — Node.js
2061
+ * `node:crypto` or a Web Crypto wrapper — without giving up the zero-dependency
2062
+ * default. The pure-JS path remains the fallback when no provider is set.
2063
+ *
2064
+ * The provider produces the raw CMS signature value over the **DER-encoded
2065
+ * signed attributes** (`tbs`, "to be signed"), matching the requested
2066
+ * algorithm:
2067
+ * - `'rsa-sha256'` → RSASSA-PKCS1-v1_5 signature over `SHA-256(tbs)`.
2068
+ * - `'ecdsa-sha256'`→ a **DER-encoded** ECDSA (P-256) signature over
2069
+ * `SHA-256(tbs)` (i.e. `SEQUENCE { r INTEGER, s INTEGER }`).
2070
+ *
2071
+ * @example Node.js `node:crypto` (constant-time, hardware-backed)
2072
+ * ```ts
2073
+ * import { setCryptoProvider } from 'pdfnative';
2074
+ * import { createSign, createPrivateKey } from 'node:crypto';
2075
+ *
2076
+ * const key = createPrivateKey(pemPrivateKey);
2077
+ * setCryptoProvider({
2078
+ * sign(tbs, algorithm) {
2079
+ * // node:crypto hashes `tbs` internally and returns a DER ECDSA sig.
2080
+ * return new Uint8Array(createSign('sha256').update(tbs).sign(key));
2081
+ * },
2082
+ * });
2083
+ * ```
2084
+ *
2085
+ * @since 1.4.0
2086
+ */
2087
+
2088
+ /**
2089
+ * A pluggable signer that replaces pdfnative's pure-JS RSA/ECDSA math with a
2090
+ * native, constant-time implementation.
2091
+ */
2092
+ interface CryptoProvider {
2093
+ /**
2094
+ * Sign the DER-encoded CMS SignedAttributes (`tbs`) and return the raw
2095
+ * signature value to embed in the CMS `SignerInfo`.
2096
+ *
2097
+ * The implementation MUST hash `tbs` with SHA-256 internally (native
2098
+ * `crypto.sign('sha256', …)` does this for you) and produce a signature
2099
+ * matching `algorithm`:
2100
+ * - `'rsa-sha256'` → RSASSA-PKCS1-v1_5 over `SHA-256(tbs)`.
2101
+ * - `'ecdsa-sha256'` → DER-encoded ECDSA-P256 over `SHA-256(tbs)`.
2102
+ */
2103
+ readonly sign: (tbs: Uint8Array, algorithm: SignatureAlgorithm) => Uint8Array;
2104
+ }
2105
+ /**
2106
+ * Install (or clear) a global signature {@link CryptoProvider}. When set, every
2107
+ * `signPdfBytes()` call that does not pass an explicit per-call provider routes
2108
+ * its signature math through `provider` instead of pdfnative's pure-JS RSA/ECDSA
2109
+ * primitives. Pass `null` to restore the zero-dependency default.
2110
+ *
2111
+ * A per-call `PdfSignOptions.provider` always takes precedence over the global
2112
+ * one set here.
2113
+ *
2114
+ * @param provider The native signer, or `null` to revert to pure-JS.
2115
+ * @since 1.4.0
2116
+ */
2117
+ declare function setCryptoProvider(provider: CryptoProvider | null): void;
2118
+ /**
2119
+ * The currently-installed global {@link CryptoProvider}, or `null` if none.
2120
+ * Primarily for internal dispatch and testing.
2121
+ *
2122
+ * @since 1.4.0
2123
+ */
2124
+ declare function getCryptoProvider(): CryptoProvider | null;
2125
+
1811
2126
  /**
1812
2127
  * pdfnative — CMS SignedData Builder (RFC 5652)
1813
2128
  * ==============================================
@@ -1832,6 +2147,14 @@ interface CmsSignOptions {
1832
2147
  readonly signingTime?: Date;
1833
2148
  /** Signature algorithm. */
1834
2149
  readonly algorithm: SignatureAlgorithm;
2150
+ /**
2151
+ * Optional native signer. When supplied (or when a global provider is set
2152
+ * via {@link setCryptoProvider}), the signature value is produced by the
2153
+ * provider instead of the pure-JS RSA/ECDSA primitives, and `rsaKey` /
2154
+ * `ecKey` are not required.
2155
+ * @since 1.4.0
2156
+ */
2157
+ readonly provider?: CryptoProvider;
1835
2158
  }
1836
2159
  /**
1837
2160
  * Build a CMS SignedData structure for a PDF detached signature.
@@ -1895,6 +2218,15 @@ interface PdfSignOptions extends SigDictMetadata {
1895
2218
  readonly ecKey?: EcPrivateKey;
1896
2219
  /** Algorithm to use. Default: 'rsa-sha256'. */
1897
2220
  readonly algorithm?: SignatureAlgorithm;
2221
+ /**
2222
+ * Optional native signature provider (e.g. `node:crypto` / Web Crypto). When
2223
+ * set — or when a global provider is installed via {@link setCryptoProvider}
2224
+ * — the constant-time native signer replaces pdfnative's pure-JS RSA/ECDSA
2225
+ * math, and `rsaKey` / `ecKey` become optional. A per-call provider takes
2226
+ * precedence over the global one.
2227
+ * @since 1.4.0
2228
+ */
2229
+ readonly provider?: CryptoProvider;
1898
2230
  }
1899
2231
  /**
1900
2232
  * Build a /Sig signature dictionary string for embedding in a PDF.
@@ -2179,6 +2511,37 @@ declare function concatChunks(chunks: readonly Uint8Array[]): Uint8Array;
2179
2511
  * @returns Total byte count
2180
2512
  */
2181
2513
  declare function streamByteLength(stream: AsyncGenerator<Uint8Array>): Promise<number>;
2514
+ /** Result of {@link streamToFile}. */
2515
+ interface StreamToFileResult {
2516
+ /** Total number of bytes written to the file. */
2517
+ readonly bytesWritten: number;
2518
+ /** The path the stream was written to. */
2519
+ readonly path: string;
2520
+ }
2521
+ /**
2522
+ * Write a streaming PDF (any of the `streamPdf`/`buildPDFStream*` generators)
2523
+ * directly to a file on disk in **constant memory**, honouring write
2524
+ * back-pressure. Node.js-only convenience wrapper.
2525
+ *
2526
+ * The dependency on `node:fs` is loaded **dynamically** so this module stays
2527
+ * tree-shakeable and bundler-safe for the browser; calling `streamToFile` in
2528
+ * a non-Node environment throws a descriptive error.
2529
+ *
2530
+ * @example
2531
+ * ```ts
2532
+ * await streamToFile(streamDocumentPdf({ blocks }), './out.pdf');
2533
+ * ```
2534
+ *
2535
+ * @param stream An async generator of PDF byte chunks.
2536
+ * @param filePath Destination path. The caller is responsible for validating
2537
+ * untrusted paths (path traversal, allowed directories).
2538
+ * @param opts Optional `AbortSignal` to cancel mid-write.
2539
+ * @returns Bytes written and the destination path.
2540
+ * @since 1.4.0
2541
+ */
2542
+ declare function streamToFile(stream: AsyncGenerator<Uint8Array>, filePath: string, opts?: {
2543
+ readonly signal?: AbortSignal;
2544
+ }): Promise<StreamToFileResult>;
2182
2545
 
2183
2546
  /**
2184
2547
  * pdfnative — SHA-384, SHA-512, HMAC-SHA256
@@ -2498,6 +2861,47 @@ declare function clearFontCache(): void;
2498
2861
  */
2499
2862
  declare function resetFontRegistry(): void;
2500
2863
 
2864
+ /**
2865
+ * pdfnative — Font Data Validator
2866
+ * ================================
2867
+ * `validateFontData()` performs a read-only structural sanity check on a
2868
+ * {@link FontData} module before it is used for rendering. The bundled font
2869
+ * modules under `pdfnative/fonts/*` are already trusted; this validator exists
2870
+ * for consumers who **build their own** font data (via `tools/build-font-data.cjs`
2871
+ * or by hand) from an untrusted or unfamiliar TTF/OTF.
2872
+ *
2873
+ * It catches the common failure modes — a corrupt/empty base64 payload, a
2874
+ * non-SFNT binary, an empty `cmap`, glyph ids that point outside the metrics,
2875
+ * a malformed `pdfWidthArray`, or non-finite metrics — and reports them as
2876
+ * descriptive errors instead of letting a cryptic `.notdef`/`NaN` failure
2877
+ * surface deep inside the encoding/subsetting pipeline.
2878
+ *
2879
+ * The check is **opt-in and standalone**: it is NOT invoked automatically by
2880
+ * `registerFont()` (that would add cost to every load and risks false-rejecting
2881
+ * edge-valid fonts). Call it yourself when ingesting third-party font data.
2882
+ *
2883
+ * @since 1.4.0
2884
+ */
2885
+ /** Result of {@link validateFontData}. */
2886
+ interface FontValidationResult {
2887
+ /** True when no blocking errors were found. */
2888
+ readonly valid: boolean;
2889
+ /** Blocking structural problems that would break rendering. */
2890
+ readonly errors: readonly string[];
2891
+ /** Non-blocking concerns (suspicious but not necessarily fatal). */
2892
+ readonly warnings: readonly string[];
2893
+ }
2894
+ /**
2895
+ * Structurally validate a {@link FontData} module. Returns `{ valid, errors,
2896
+ * warnings }`; `valid` is `false` when any blocking problem is found. Does not
2897
+ * throw on malformed input — it reports.
2898
+ *
2899
+ * @param data The font data to validate (typically the default export of a
2900
+ * generated `*-data.js` module).
2901
+ * @since 1.4.0
2902
+ */
2903
+ declare function validateFontData(data: unknown): FontValidationResult;
2904
+
2501
2905
  /**
2502
2906
  * pdfnative — Thai Mini-Shaper
2503
2907
  * =============================
@@ -3183,13 +3587,15 @@ declare function extractGlyphContours(font: GlyfFont, gid: number, depth?: numbe
3183
3587
  * Supported:
3184
3588
  * - COLR v0 — layered solid fills.
3185
3589
  * - COLR v1 — PaintColrLayers, PaintGlyph, PaintColrGlyph, PaintSolid,
3186
- * PaintLinearGradient, PaintRadialGradient, PaintTransform,
3187
- * PaintTranslate, PaintScale (+ around-center).
3590
+ * PaintLinearGradient, PaintRadialGradient, PaintSweepGradient,
3591
+ * PaintTransform, PaintTranslate, PaintScale (+ around-center),
3592
+ * PaintComposite (blend-mode-mappable composite modes).
3188
3593
  *
3189
- * Unsupported paints (sweep gradients, compositing, variable paints) cause
3190
- * the affected glyph to be skipped so the caller can fall back to the
3191
- * monochrome emoji font. This keeps output correct (never garbled) while
3192
- * covering the overwhelming majority of Noto Color Emoji glyphs.
3594
+ * Unsupported paints (variable paints, Porter-Duff structural composite
3595
+ * modes Clear/Src/Dest/Xor/…) cause the affected glyph to be skipped so the
3596
+ * caller can fall back to the monochrome emoji font. This keeps output
3597
+ * correct (never garbled) while covering the overwhelming majority of
3598
+ * Noto Color Emoji glyphs.
3193
3599
  *
3194
3600
  * Zero external dependency.
3195
3601
  *
@@ -3222,6 +3628,10 @@ declare function parseColrCpal(bytes: Uint8Array): Record<number, ColorGlyph> |
3222
3628
  * - Linear gradients → `/Shading` Type 2 (axial) painted via `sh`,
3223
3629
  * clipped to the glyph outline.
3224
3630
  * - Radial gradients → `/Shading` Type 3, likewise.
3631
+ * - Sweep (conic) gradients → a fan of flat-colour triangular wedges
3632
+ * clipped to the outline (PDF has no native conic shading). (v1.4.0)
3633
+ * - Per-layer blend modes (`/BM`, from COLRv1 `PaintComposite`) via an
3634
+ * ExtGState applied around the layer's fill. (v1.4.0)
3225
3635
  *
3226
3636
  * The Form XObject's user space is font units; the caller scales it onto the
3227
3637
  * page with a `cm` and draws it with `Do`.
@@ -3565,6 +3975,99 @@ interface PdfModifier {
3565
3975
  */
3566
3976
  declare function createModifier(reader: PdfReader): PdfModifier;
3567
3977
 
3978
+ /**
3979
+ * pdfnative — Page-Tree Manipulation API (ISO 32000-1 §7.7.3)
3980
+ * ============================================================
3981
+ * Safe, **faithful** page-level document assembly: merge, split, and
3982
+ * extract pages across PDF documents.
3983
+ *
3984
+ * Unlike the incremental modifier (`createModifier`), these operations
3985
+ * **rebuild** a brand-new document from scratch: every kept page and its
3986
+ * transitive object graph (`/Contents`, `/Resources`, fonts, XObjects,
3987
+ * ExtGState, …) is deep-copied into a fresh, contiguous object-number
3988
+ * space, then wired into a new flat `/Pages` tree, `/Catalog`, xref, and
3989
+ * trailer. This avoids production-unsafe in-place surgery (relocating
3990
+ * `/Kids`, rewriting `/Parent` chains, merging resource pools).
3991
+ *
3992
+ * Safety guarantees (documented behaviour):
3993
+ * - **Encrypted sources are rejected** (no Standard Security Handler
3994
+ * writer yet) — throws.
3995
+ * - **Signatures are always removed** — any page-tree edit invalidates a
3996
+ * document signature's `/ByteRange`, so signature/Widget annotations and
3997
+ * the `/AcroForm` are dropped. The `dropSignatures` flag is accepted for
3998
+ * API clarity but the behaviour is unconditional.
3999
+ * - **Annotations** default to URI-`/Link`-only (self-contained). Cross-page
4000
+ * GoTo links and form widgets are dropped to guarantee no dangling
4001
+ * references. `dropAnnotations: true` removes all annotations.
4002
+ * - Output is **not** claimed to be PDF/A — merged OutputIntents / XMP
4003
+ * cannot be reconciled safely.
4004
+ *
4005
+ * @since 1.4.0
4006
+ */
4007
+ /** A contiguous, inclusive page range (0-based). */
4008
+ interface PageRange {
4009
+ /** First page index (0-based, inclusive). */
4010
+ readonly start: number;
4011
+ /** Last page index (0-based, inclusive). Defaults to `start`. */
4012
+ readonly end?: number;
4013
+ }
4014
+ /**
4015
+ * Options for the page-tree manipulation API ({@link mergePdfs},
4016
+ * {@link splitPdf}, {@link extractPages}).
4017
+ */
4018
+ interface MergeOptions {
4019
+ /**
4020
+ * Drop signature fields/widgets. Accepted for clarity; merging always
4021
+ * removes signatures because the operation invalidates `/ByteRange`.
4022
+ */
4023
+ readonly dropSignatures?: boolean;
4024
+ /** Drop **all** annotations (default keeps self-contained URI links). */
4025
+ readonly dropAnnotations?: boolean;
4026
+ /**
4027
+ * Maximum size, in bytes, of the assembled output document. The operation
4028
+ * throws as soon as the copied object graph would exceed this limit — even
4029
+ * mid-copy, before a multi-gigabyte stream is materialised — so a malicious
4030
+ * or accidentally huge source cannot exhaust process memory.
4031
+ *
4032
+ * Defaults to `268435456` (256 MiB). Pass `Infinity` to disable the guard
4033
+ * (not recommended for untrusted input).
4034
+ *
4035
+ * @defaultValue 268435456 (256 MiB)
4036
+ */
4037
+ readonly maxOutputSize?: number;
4038
+ }
4039
+ /**
4040
+ * Concatenate multiple PDF documents into one, preserving page order.
4041
+ *
4042
+ * @param sources 1–50 PDF byte arrays.
4043
+ * @param opts See {@link MergeOptions}.
4044
+ * @returns A new, self-contained PDF.
4045
+ * @throws If `sources` is empty/too large, or any source is encrypted.
4046
+ */
4047
+ declare function mergePdfs(sources: readonly Uint8Array[], opts?: MergeOptions): Uint8Array;
4048
+ /**
4049
+ * Extract a subset of pages from a single document into a new PDF.
4050
+ * Indices may repeat and need not be ordered — output follows the given order.
4051
+ *
4052
+ * @param src Source PDF bytes.
4053
+ * @param pageIndices 0-based page indices to keep.
4054
+ * @param opts See {@link MergeOptions} (e.g. `maxOutputSize`,
4055
+ * `dropAnnotations`).
4056
+ * @throws If `src` is encrypted, indices is empty, or an index is out of range.
4057
+ */
4058
+ declare function extractPages(src: Uint8Array, pageIndices: readonly number[], opts?: MergeOptions): Uint8Array;
4059
+ /**
4060
+ * Split a document into multiple PDFs, one per page range.
4061
+ *
4062
+ * @param src Source PDF bytes.
4063
+ * @param ranges Inclusive 0-based page ranges.
4064
+ * @param opts See {@link MergeOptions} (e.g. `maxOutputSize`,
4065
+ * `dropAnnotations`); applied to every emitted document.
4066
+ * @returns One PDF per range, in order.
4067
+ * @throws If `src` is encrypted, ranges is empty, or a range is invalid.
4068
+ */
4069
+ declare function splitPdf(src: Uint8Array, ranges: readonly PageRange[], opts?: MergeOptions): Uint8Array[];
4070
+
3568
4071
  /**
3569
4072
  * pdfnative — PDF/UA structural validator (ISO 14289-1)
3570
4073
  * ======================================================
@@ -3750,4 +4253,4 @@ declare function createPDF(pdfParams: PdfParams, options?: {
3750
4253
  layoutOptions?: Partial<PdfLayoutOptions>;
3751
4254
  }): Promise<Uint8Array>;
3752
4255
 
3753
- export { type AddSignaturePlaceholderOptions, type Annotation, type Asn1Node, BAL_H, type BarcodeBlock, type BarcodeFormat, type BidiRun, type CmsSignOptions, type ColorGlyph, type ColorGlyphForm, type ColorLayer, type ColorPaint, type ColorStop, type ColumnDef, type Contour, type CpalColor, DEFAULT_COLORS, DEFAULT_COLUMNS, DEFAULT_CW, DEFAULT_FONT_SIZES, DEFAULT_MARGINS, DEFAULT_MAX_BLOCKS, DEFAULT_MAX_INFLATE_OUTPUT, type DocumentBlock, type DocumentMetadata, type DocumentParams, type EcPrivateKey, type EcPublicKey, type EmbeddedFilesResult, type EncodingContext, type EncryptionOptions, FT_H, type FontData, type FontEntry, type FontLoader, type FontMetrics, type FontRun, type FormField, type FormFieldBlock, type FormFieldType, type FormWidgetResult, type GlyfFont, type GradientExtend, HEADER_H, type HeadingBlock, INFO_LN, type ImageBlock, type InternalLink, KNOWN_DECODE_FILTERS, type LinearGradientPaint, type LinkAnnotation, type LinkBlock, type ListBlock, MAX_PARSE_DEPTH, MAX_XREF_CHAIN, type OutlinePoint, type OutlineProvider, PAGE_SIZES, PDF_A_CONFORMANCE_TARGETS, PG_H, PG_W, type PageBreakBlock, type PageTemplate, type ParagraphBlock, type PdfArray as ParsedArray, type PdfDict as ParsedDict, type ParsedImage, type PdfAConfig, type PdfAConformanceTarget, type PdfAttachment, type PdfAttachmentRelationship, type PdfColor, type PdfColors, type PdfIndirectObject, type PdfInfoItem, type PdfLayoutOptions, type PdfModifier, type PdfName, type PdfParams, type PdfReader, type PdfRef, type PdfRgbString, type PdfRgbTuple, type PdfRow, type PdfSignOptions, type PdfStream, type PdfToken, type PdfTokenizer, type PdfUAValidationResult, type PdfValue, type QRErrorLevel, ROW_H, type RadialGradientPaint, type RadioGroupContext, type RsaPrivateKey, type RsaPublicKey, type ShapedGlyph, type SigDictMetadata, type SignatureAlgorithm, type SolidPaint, type SpacerBlock, type StreamOptions, type SvgBlock, type SvgRenderOptions, type SvgSegment, TH_H, TITLE_LN, type TableBlock, type TextRun, type TocBlock, type TokenType, type UseCategory, type UseClassifiedCp, type UseCluster, WORKER_THRESHOLD, WORKER_TIMEOUT_MS, type WatermarkImage, type WatermarkOptions, type WatermarkState, type WatermarkText, type WorkerGenerationOptions, type WorkerInputMessage, type WorkerOutputMessage, type X509Certificate, type X509Name, type XrefEntry, type XrefTable, addSignaturePlaceholder, applyDecodeFilter, buildAcroFormDict, buildAppearanceStreamDict, buildCmsSignedData, buildDocumentPDF, buildDocumentPDFBytes, buildDocumentPDFStream, buildDocumentPDFStreamPageByPage, buildDocumentPDFStreamTrue, buildEmbeddedFiles, buildFormWidget, buildImageOperators, buildImageXObject, buildInternalLinkAnnotation, buildLinkAnnotation, buildPDF, buildPDFBytes, buildPDFStream, buildPDFStreamPageByPage, buildPDFStreamTrue, buildRadioGroupParent, buildSMaskXObject, buildSigDict, buildWatermarkState, chunkBinaryString, classifyClusters, classifyUseCategory, clearFontCache, computeColumnPositions, concatChunks, containsArabic, containsBengali, containsDevanagari, containsEthiopic, containsHebrew, containsKhmer, containsMyanmar, containsRTL, containsSinhala, containsTamil, containsTelugu, containsThai, containsTibetan, contoursToPath, createEncodingContext, createModifier, createPDF, createTokenizer, decodeASCII85, decodeASCIIHex, decodeEcPublicKey, decodeLZW, decodeRunLength, defaultFieldHeight, derBitString, derDecode, derInteger, derOctetString, derOid, derSequence, detectCharLang, detectFallbackLangs, detectImageFormat, dictGet, dictGetArray, dictGetDict, dictGetName, dictGetNum, dictGetRef, downloadBlob, ean13CheckDigit, ecPublicKeyFromPrivate, ecdsaSign, ecdsaVerify, encodeCode128, encodeEcPublicKey, encodePDF417, encodePdfTextString, estimateCmsSize, estimateContentsSize, extractGlyphContours, findStartxref, generateDataMatrix, generatePDFInWorker, generatePDFMainThread, generateQR, getMaxInflateOutputSize, getRegisteredLangs, getTrailerRef, getTrailerValue, hasFontLoader, helveticaBoldWidth, helveticaWidth, hmacSha256, inflateSync, initCrypto, initNodeCompression, initNodeDecompression as initNodeDecompression_parser, isArmenianCodepoint, isArray, isBengaliCodepoint, isCyrillicCodepoint, isDevanagariCodepoint, isDict, isEthiopicCodepoint, isGeorgianCodepoint, isKhmerCodepoint, isLinkAnnotation, isMyanmarCodepoint, isName, isRef, isSelfSigned, isSinhalaCodepoint, isStream, isTamilCodepoint, isTeluguCodepoint, isTibetanCodepoint, isValidPdfRgb, loadFontData, nameValue, needsUnicodeFont, normalizeBidiEmbeddings, normalizeColors, openPdf, parseCertificate, parseColor, parseColrCpal, parseCpal, parseGlyfFont, parseImage, parseIndirectObject, parseJPEG, parsePNG, parseRsaPrivateKey, parseRsaPublicKey, parseSvgPath, parseValue, parseXrefTable, pdfString, registerFont, registerFonts, renderBarcode, renderCode128, renderColorGlyph, renderDataMatrix, renderEAN13, renderPDF417, renderQR, renderSvg, resetFontRegistry, resolveBidiRuns, resolveLayout, resolvePdfAConfig, resolveTemplate, rsaSign, rsaSignHash, rsaVerify, rsaVerifyHash, setDeflateImpl, setInflateImpl, setMaxInflateOutputSize, sha384, sha512, shapeArabicText, shapeBengaliText, shapeDevanagariText, shapeKhmerText, shapeMyanmarText, shapeSinhalaText, shapeTamilText, shapeTeluguText, shapeThaiText, shapeTibetanText, signPdfBytes, slugify, splitTextByFont, streamByteLength, stripBidiControls, toBytes, toWinAnsi, truncate, truncateToWidth, validateAttachments, validateDocumentStreamable, validatePdfUA, validateTableStreamable, validateURL, validateWatermark, verifyCertSignature, wrapText };
4256
+ export { type AddSignaturePlaceholderOptions, type Annotation, type Asn1Node, BAL_H, type BarcodeBlock, type BarcodeFormat, type BidiRun, type CellBorders, type CmsSignOptions, type ColorGlyph, type ColorGlyphForm, type ColorLayer, type ColorPaint, type ColorStop, type ColumnDef, type Contour, type CpalColor, type CryptoProvider, DEFAULT_COLORS, DEFAULT_COLUMNS, DEFAULT_CW, DEFAULT_FONT_SIZES, DEFAULT_MARGINS, DEFAULT_MAX_BLOCKS, DEFAULT_MAX_INFLATE_OUTPUT, type DocumentBlock, type DocumentMetadata, type DocumentParams, type EcPrivateKey, type EcPublicKey, type EmbeddedFilesResult, type EncodingContext, type EncryptionOptions, FT_H, type FontData, type FontEntry, type FontLoader, type FontMetrics, type FontRun, type FontValidationResult, type FormField, type FormFieldBlock, type FormFieldType, type FormWidgetResult, type GlyfFont, type GradientExtend, HEADER_H, type HeadingBlock, INFO_LN, type ImageBlock, type InternalLink, KNOWN_DECODE_FILTERS, type LinearGradientPaint, type LinkAnnotation, type LinkBlock, type ListBlock, type ListItem, MAX_PARSE_DEPTH, MAX_XREF_CHAIN, type MergeOptions, type OutlineItem, type OutlinePoint, type OutlineProvider, PAGE_SIZES, PDF_A_CONFORMANCE_TARGETS, PG_H, PG_W, type PageBreakBlock, type PageLabelRange, type PageLabelStyle, type PageRange, type PageTemplate, type ParagraphBlock, type PdfArray as ParsedArray, type PdfDict as ParsedDict, type ParsedImage, type PdfAConfig, type PdfAConformanceTarget, type PdfAttachment, type PdfAttachmentRelationship, type PdfColor, type PdfColors, type PdfIndirectObject, type PdfInfoItem, type PdfLayoutOptions, type PdfModifier, type PdfName, type PdfParams, type PdfReader, type PdfRef, type PdfRgbString, type PdfRgbTuple, type PdfRow, type PdfSignOptions, type PdfStream, type PdfToken, type PdfTokenizer, type PdfUAValidationResult, type PdfValue, type QRErrorLevel, ROW_H, type RadialGradientPaint, type RadioGroupContext, type RsaPrivateKey, type RsaPublicKey, type ShapedGlyph, type SigDictMetadata, type SignatureAlgorithm, type SolidPaint, type SpacerBlock, type StreamOptions, type StreamToFileResult, type SvgBlock, type SvgRenderOptions, type SvgSegment, TH_H, TITLE_LN, type TableBlock, type TextRun, type TocBlock, type TokenType, type UseCategory, type UseClassifiedCp, type UseCluster, type ViewerPreferences, WORKER_THRESHOLD, WORKER_TIMEOUT_MS, type WatermarkImage, type WatermarkOptions, type WatermarkState, type WatermarkText, type WorkerGenerationOptions, type WorkerInputMessage, type WorkerOutputMessage, type X509Certificate, type X509Name, type XrefEntry, type XrefTable, addSignaturePlaceholder, applyDecodeFilter, buildAcroFormDict, buildAppearanceStreamDict, buildCmsSignedData, buildDocumentPDF, buildDocumentPDFBytes, buildDocumentPDFStream, buildDocumentPDFStreamPageByPage, buildDocumentPDFStreamTrue, buildEmbeddedFiles, buildFormWidget, buildImageOperators, buildImageXObject, buildInternalLinkAnnotation, buildLinkAnnotation, buildPDF, buildPDFBytes, buildPDFStream, buildPDFStreamPageByPage, buildPDFStreamTrue, buildRadioGroupParent, buildSMaskXObject, buildSigDict, buildWatermarkState, chunkBinaryString, classifyClusters, classifyUseCategory, clearFontCache, computeColumnPositions, concatChunks, containsArabic, containsBengali, containsDevanagari, containsEthiopic, containsHebrew, containsKhmer, containsMyanmar, containsRTL, containsSinhala, containsTamil, containsTelugu, containsThai, containsTibetan, contoursToPath, createEncodingContext, createModifier, createPDF, createTokenizer, decodeASCII85, decodeASCIIHex, decodeEcPublicKey, decodeLZW, decodeRunLength, defaultFieldHeight, derBitString, derDecode, derInteger, derOctetString, derOid, derSequence, detectCharLang, detectFallbackLangs, detectImageFormat, dictGet, dictGetArray, dictGetDict, dictGetName, dictGetNum, dictGetRef, downloadBlob, ean13CheckDigit, ecPublicKeyFromPrivate, ecdsaSign, ecdsaVerify, encodeCode128, encodeEcPublicKey, encodePDF417, encodePdfTextString, estimateCmsSize, estimateContentsSize, extractGlyphContours, extractPages, findStartxref, generateDataMatrix, generatePDFInWorker, generatePDFMainThread, generateQR, getCryptoProvider, getMaxInflateOutputSize, getRegisteredLangs, getTrailerRef, getTrailerValue, hasFontLoader, helveticaBoldWidth, helveticaWidth, hmacSha256, inflateSync, initCrypto, initNodeCompression, initNodeDecompression as initNodeDecompression_parser, isArmenianCodepoint, isArray, isBengaliCodepoint, isCyrillicCodepoint, isDevanagariCodepoint, isDict, isEthiopicCodepoint, isGeorgianCodepoint, isKhmerCodepoint, isLinkAnnotation, isMyanmarCodepoint, isName, isRef, isSelfSigned, isSinhalaCodepoint, isStream, isTamilCodepoint, isTeluguCodepoint, isTibetanCodepoint, isValidPdfRgb, loadFontData, mergePdfs, nameValue, needsUnicodeFont, normalizeBidiEmbeddings, normalizeColors, openPdf, parseCertificate, parseColor, parseColrCpal, parseCpal, parseGlyfFont, parseImage, parseIndirectObject, parseJPEG, parsePNG, parseRsaPrivateKey, parseRsaPublicKey, parseSvgPath, parseValue, parseXrefTable, pdfString, registerFont, registerFonts, renderBarcode, renderCode128, renderColorGlyph, renderDataMatrix, renderEAN13, renderPDF417, renderQR, renderSvg, resetFontRegistry, resolveBidiRuns, resolveLayout, resolvePdfAConfig, resolveTemplate, rsaSign, rsaSignHash, rsaVerify, rsaVerifyHash, setCryptoProvider, setDeflateImpl, setInflateImpl, setMaxInflateOutputSize, sha384, sha512, shapeArabicText, shapeBengaliText, shapeDevanagariText, shapeKhmerText, shapeMyanmarText, shapeSinhalaText, shapeTamilText, shapeTeluguText, shapeThaiText, shapeTibetanText, signPdfBytes, slugify, splitPdf, splitTextByFont, streamByteLength, streamToFile, stripBidiControls, toBytes, toWinAnsi, truncate, truncateToWidth, validateAttachments, validateDocumentStreamable, validateFontData, validatePdfUA, validateTableStreamable, validateURL, validateWatermark, verifyCertSignature, wrapText };