@reportwright/pdf 0.0.0-stage → 0.1.0-beta.1

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/index.d.ts ADDED
@@ -0,0 +1,847 @@
1
+ // Types of @reportwright/pdf. Coordinates: PDF points, origin at the page's top-left corner, y growing downwards.
2
+
3
+ /**
4
+ * A gray level 0–1; '#rgb', '#rrggbb', 'rgb(255, 0, 0)', 'rgb(100% 0% 0%)' or [r, g, b] (0–1); cmyk(c, m, y, k) or
5
+ * [c, m, y, k] (0–1); a spot colour or one of its tints; an ICC colour.
6
+ */
7
+ export type Color = string | number | readonly [number, number, number] | readonly [number, number, number, number] | SpotColor | IccColor;
8
+
9
+ /** A CMYK colour, each component 0–1. */
10
+ export function cmyk(c: number, m: number, y: number, k: number): readonly [number, number, number, number];
11
+
12
+ /** A spot colour (Separation) made by pdf.spotColor: as a colour it is full tint. */
13
+ export interface SpotColor {
14
+ readonly type: 'spot';
15
+ /** the name as given (written as a PDF name with #xx escapes, so it round-trips exactly) */
16
+ readonly name: string;
17
+ /** the colour at a tint 0–1 */
18
+ tint(t: number): IccColor;
19
+ }
20
+ /** A colour in a spot or ICC colour space (an opaque handle). */
21
+ export interface IccColor { readonly type: 'color' }
22
+ /** An ICC-based colour space made by pdf.iccColorSpace. */
23
+ export interface IccColorSpace {
24
+ readonly type: 'iccColorSpace';
25
+ /** 1 (gray), 3 (RGB) or 4 (CMYK), from the profile */
26
+ readonly components: 1 | 3 | 4;
27
+ /** a colour in this space: as many components as the profile has, each 0–1 */
28
+ color(...components: number[]): IccColor;
29
+ }
30
+ /** An image made by pdf.embedImage (an opaque handle). width and height are pixels, upright (after EXIF orientation). */
31
+ export interface Image {
32
+ readonly type: 'image';
33
+ readonly width: number;
34
+ readonly height: number;
35
+ }
36
+ export interface ImageOptions {
37
+ /** top-left corner (default 0, 0) */
38
+ x?: number;
39
+ y?: number;
40
+ /** the box; only one: the other keeps the aspect ratio; neither: one point per pixel */
41
+ width?: number;
42
+ height?: number;
43
+ /** 'fill' (default: stretch), 'contain' (all of it, centred), 'cover' (fill the box, centred, cut to it) */
44
+ fit?: 'fill' | 'contain' | 'cover';
45
+ /** 0–1 */
46
+ opacity?: number;
47
+ /** tagged PDFs: the image is a Figure with this alternate text; without it, an artifact */
48
+ alt?: string;
49
+ }
50
+
51
+ /** Where the bytes go: a Node Writable, a WHATWG WritableStream, or anything with write(bytes) (a returned promise is awaited). */
52
+ export type Sink =
53
+ | NodeJS.WritableStream
54
+ | WritableStream<Uint8Array>
55
+ | { write(bytes: Uint8Array): unknown; close?(): unknown };
56
+
57
+ export interface PdfOptions {
58
+ title?: string;
59
+ author?: string;
60
+ subject?: string;
61
+ /** Info /Keywords and XMP pdf:Keywords */
62
+ keywords?: string;
63
+ /** default: now. The same input and creationDate give the same bytes. Kept to the second, in UTC. */
64
+ creationDate?: Date;
65
+ /** Flate-compress content, fonts, object streams (default true). */
66
+ compress?: boolean;
67
+ /**
68
+ * PDF/A: an output intent (sRGB, or outputIntent: your RGB or CMYK ICC output/monitor profile) and XMP
69
+ * identification. Fonts must be embedded; device colour must match the intent (CMYK needs a CMYK intent, RGB an RGB one).
70
+ * true is PDF/A-2b. part 1 (only 'b'): PDF 1.4, no transparency, layers or attachments, a classic xref.
71
+ * 'u': every character drawn must map to Unicode (a missing glyph throws). 'a': 'u' plus tagged (required).
72
+ * part 3: embedded files (pdf.attach, pdf.facturX).
73
+ */
74
+ pdfa?: boolean | { part?: 1 | 2 | 3; conformance?: 'a' | 'b' | 'u'; outputIntent?: Uint8Array | ArrayBuffer };
75
+ /** PDF/UA-1: a structure tree from page.tag(). Needs title; fonts must be embedded. */
76
+ tagged?: boolean | { lang?: string };
77
+ /**
78
+ * false: no XMP metadata stream, the Info dictionary only (about 1 KB smaller: a one-page invoice). Default true.
79
+ * Refused with pdfa or tagged: PDF/A and PDF/UA require the XMP.
80
+ */
81
+ metadata?: boolean;
82
+ /** stop the export: pending and later calls reject with signal.reason */
83
+ signal?: AbortSignal;
84
+ /** stop the export after this many milliseconds (a TimeoutError, code 'ETIMEDOUT') */
85
+ timeoutMs?: number;
86
+ /** the file identifier, 32 hex digits (default: a hash of the file's bytes) */
87
+ id?: string;
88
+ /** forms: flatten draws every field's appearance into its page and writes no AcroForm (a filled form as a plain PDF) */
89
+ form?: { flatten?: boolean };
90
+ /**
91
+ * Password protection: AES-256 (V5/R6, the default) or AES-128 (V4/R4, for old readers). RC4 is refused (broken).
92
+ * Not with PDF/A (it forbids encryption). With encryption the bytes differ on every run (random IVs and salts), and
93
+ * the file ID is random unless `id` is given.
94
+ */
95
+ encrypt?: EncryptOptions;
96
+ /** make the PDF signable with pdf.sign: every byte is hashed as it streams (true: SHA-256) */
97
+ sign?: boolean | { hash?: HashName };
98
+ }
99
+
100
+ export type HashName = 'SHA-256' | 'SHA-384' | 'SHA-512';
101
+ export interface Permissions {
102
+ print?: boolean; printHighQuality?: boolean; modify?: boolean; copy?: boolean; annotate?: boolean;
103
+ fillForms?: boolean;
104
+ /** text extraction for accessibility; forced on in a tagged (PDF/UA) PDF */
105
+ accessibility?: boolean;
106
+ assemble?: boolean;
107
+ }
108
+ export interface EncryptOptions {
109
+ /** '' (default): opens without a prompt, the permissions apply. At most 1024 characters; the PDF keeps 127 UTF-8 bytes (SASLprep) for AES-256, 32 Latin-1 characters for AES-128 */
110
+ userPassword?: string;
111
+ /** full access; omitted: a random one (nobody can lift the permissions). Not '' */
112
+ ownerPassword?: string;
113
+ algorithm?: 'aes-256' | 'aes-128';
114
+ /** every permission is granted unless set false here */
115
+ permissions?: Permissions;
116
+ /** default true; false leaves the XMP metadata readable */
117
+ encryptMetadata?: boolean;
118
+ }
119
+
120
+ /** what pdf.sign hands the signer: the digest of the signed byte ranges */
121
+ export interface SignRequest {
122
+ digest: Uint8Array;
123
+ hash: HashName;
124
+ subFilter: 'ETSI.CAdES.detached' | 'adbe.pkcs7.detached';
125
+ /** the signing time (also /M) */
126
+ date: Date;
127
+ /** RFC 3161: the signer adds its TimeStampToken as an unsigned attribute (nodeSigner and cmsSigner do) */
128
+ timestamp?: (signatureValue: Uint8Array) => Promise<Uint8Array> | Uint8Array;
129
+ signal?: AbortSignal;
130
+ }
131
+ /** gives a DER CMS SignedData (detached) for the request */
132
+ export type Signer = (r: SignRequest) => Promise<Uint8Array> | Uint8Array;
133
+ export interface SignOptions {
134
+ signer: Signer;
135
+ reason?: string; location?: string; contactInfo?: string; name?: string;
136
+ /** default: the creation date */
137
+ date?: Date;
138
+ /** a certification (DocMDP) signature: 1 no changes, 2 form filling and signing, 3 also annotations */
139
+ certify?: 1 | 2 | 3;
140
+ /** RFC 3161 TimeStampToken for the signature value (PAdES B-T). No network call is made by the library */
141
+ timestamp?: (signatureValue: Uint8Array) => Promise<Uint8Array> | Uint8Array;
142
+ /** default 'ETSI.CAdES.detached' (PAdES) */
143
+ subFilter?: 'ETSI.CAdES.detached' | 'adbe.pkcs7.detached';
144
+ /** bytes reserved for the CMS, 1024–1048576 (default 16384) */
145
+ reserve?: number;
146
+ }
147
+ /** a signer with node:crypto: RSA (PKCS#1 v1.5, or PSS with pss: true) or ECDSA P-256 / P-384; certs: the PEM chain, the signer's first */
148
+ export function nodeSigner(o: { key: unknown; certs: string | Uint8Array | (string | Uint8Array)[]; pss?: boolean }): Signer;
149
+ /** a signer around a raw signature function (an HSM, a cloud KMS): sign(signedAttributes, hash) gives the signature value */
150
+ export function cmsSigner(o: { certs: string | Uint8Array | (string | Uint8Array)[]; keyAlgorithm: 'rsa' | 'rsa-pss' | 'ecdsa'; sign(bytes: Uint8Array, hash: HashName): Promise<Uint8Array> | Uint8Array }): Signer;
151
+
152
+ export type StandardFontName =
153
+ | 'Helvetica' | 'Helvetica-Bold' | 'Helvetica-Oblique' | 'Helvetica-BoldOblique'
154
+ | 'Times-Roman' | 'Times-Bold' | 'Times-Italic' | 'Times-BoldItalic'
155
+ | 'Courier' | 'Courier-Bold' | 'Courier-Oblique' | 'Courier-BoldOblique'
156
+ | 'Symbol' | 'ZapfDingbats';
157
+
158
+ export interface Font {
159
+ /** PostScript name */
160
+ readonly key: string;
161
+ readonly standard: boolean;
162
+ /** ascender above the baseline, as a fraction of the font size */
163
+ readonly ascent: number;
164
+ /** descender (negative), as a fraction of the font size */
165
+ readonly descent: number;
166
+ /** advance width of text at size, in points (no kerning) */
167
+ widthOf(text: string, size: number): number;
168
+ /** the width text is drawn at, in points: kerned (unless kerning: false), shaped when the font has a shaper, with the spacing options */
169
+ widthOfText(text: string, size: number, o?: MeasureOptions): number;
170
+ /** the distance between baselines at size: ascent − descent + line gap (hhea); 1.2 × size for the standard fonts */
171
+ lineHeight(size: number): number;
172
+ }
173
+
174
+ export interface MeasureOptions {
175
+ /** pair kerning from GPOS or the kern table (default true; standard fonts are not kerned) */
176
+ kerning?: boolean;
177
+ /** points added after every glyph (Tc) */
178
+ characterSpacing?: number;
179
+ /** points added at every space (Tw for standard fonts; TJ adjustments for embedded ones) */
180
+ wordSpacing?: number;
181
+ /** horizontal scaling in percent (Tz, default 100) */
182
+ horizontalScaling?: number;
183
+ /** 'rtl': the run is drawn right to left (glyphs reversed, or the shaper told). No bidi algorithm: pass runs of one direction */
184
+ direction?: 'ltr' | 'rtl';
185
+ }
186
+
187
+ /** a glyph from a shaper, in font units, in visual order (HarfBuzz's glyph infos and positions) */
188
+ export interface ShapedGlyph {
189
+ /** glyph ID */
190
+ g: number;
191
+ /** cluster: the UTF-16 index in the text of the glyph's first character */
192
+ cl: number;
193
+ /** x advance */
194
+ ax: number;
195
+ /** x and y offsets */
196
+ dx?: number;
197
+ dy?: number;
198
+ }
199
+ /** shapes one run (one font, one direction); see examples/harfbuzz-shaper.mjs */
200
+ export type Shaper = (text: string, font: Font, o: { direction: 'ltr' | 'rtl'; kerning: boolean }) => ShapedGlyph[];
201
+
202
+ /** fill, stroke, fill + stroke, invisible; the same adding the glyphs to the clip (until the enclosing restore()); clip only */
203
+ export type RenderMode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 'fill' | 'stroke' | 'fillStroke' | 'invisible' | 'fillClip' | 'strokeClip' | 'fillStrokeClip' | 'clip';
204
+
205
+ export interface TextOptions extends MeasureOptions {
206
+ x?: number;
207
+ y?: number;
208
+ font: Font;
209
+ size?: number;
210
+ color?: Color;
211
+ /** characters the font lacks are drawn in the first of these that has them (at most 16) */
212
+ fallback?: Font[];
213
+ /** points the baseline is raised (Ts; negative lowers it), for super- and subscripts */
214
+ rise?: number;
215
+ renderMode?: RenderMode;
216
+ /** the outline's colour and width in the stroking modes (default: color, 1) */
217
+ strokeColor?: Color;
218
+ strokeWidth?: number;
219
+ /** radians, clockwise, about (x, y) */
220
+ rotate?: number;
221
+ }
222
+
223
+ export interface TextBoxOptions extends TextOptions {
224
+ width: number;
225
+ /** lines that do not fit are not drawn; they come back as overflow */
226
+ height?: number;
227
+ align?: 'left' | 'right' | 'center' | 'justify';
228
+ /** points between baselines (default font.lineHeight(size)) */
229
+ lineHeight?: number;
230
+ /** at most this many lines; the last ends with an ellipsis when text is left (ellipsis: false to not) */
231
+ maxLines?: number;
232
+ ellipsis?: boolean;
233
+ }
234
+
235
+ /** A subsetter that keeps glyph IDs (e.g. HarfBuzz with HB_SUBSET_FLAGS_RETAIN_GIDS). */
236
+ export type Subsetter = (font: Uint8Array, codePoints: Iterable<number>, opt: { glyphs: Iterable<number> }) => Uint8Array | Promise<Uint8Array>;
237
+
238
+ export interface TagOptions {
239
+ /** alternate description (Figure, Formula…) */
240
+ alt?: string;
241
+ /** language of this element (BCP 47) */
242
+ lang?: string;
243
+ /** a TH's scope */
244
+ scope?: 'Row' | 'Column' | 'Both';
245
+ /** /ActualText: the text this element stands for (replaces its content for extraction) */
246
+ actualText?: string;
247
+ /** /E: an abbreviation's expansion */
248
+ expansion?: string;
249
+ /** /ID (1–64 of A–Z a–z 0–9 _ . : -), unique; in the IDTree; TD/TH headers name these */
250
+ id?: string;
251
+ /** TD/TH: the ids of the TH cells that head it (/Headers) */
252
+ headers?: string[];
253
+ rowSpan?: number;
254
+ colSpan?: number;
255
+ /** L: /ListNumbering */
256
+ listNumbering?: 'None' | 'Disc' | 'Circle' | 'Square' | 'Decimal' | 'UpperRoman' | 'LowerRoman' | 'UpperAlpha' | 'LowerAlpha';
257
+ }
258
+
259
+ /** A layer (an optional content group) from pdf.layer */
260
+ export interface Layer { readonly type: 'layer'; readonly name: string }
261
+ export interface LayerOptions {
262
+ /** shown when the document opens (default true) */
263
+ visible?: boolean;
264
+ /** printed (default: visible). Differing from visible makes a print-only or screen-only layer (not in PDF/A) */
265
+ printable?: boolean;
266
+ /** the viewer does not let it be turned on or off */
267
+ locked?: boolean;
268
+ }
269
+ export interface ArtifactOptions {
270
+ type?: 'Pagination' | 'Layout' | 'Page';
271
+ /** for Pagination */
272
+ subtype?: 'Header' | 'Footer' | 'Watermark';
273
+ }
274
+ /** [x, y, width, height], top-left, inside the page (the MediaBox) */
275
+ export type Box = [number, number, number, number];
276
+ export interface PageOptions {
277
+ width?: number;
278
+ height?: number;
279
+ cropBox?: Box;
280
+ bleedBox?: Box;
281
+ /** inside the bleedBox when both are given */
282
+ trimBox?: Box;
283
+ /** inside the bleedBox when both are given */
284
+ artBox?: Box;
285
+ /** clockwise, as viewers show the page; drawing coordinates stay those of the unrotated page */
286
+ rotate?: 0 | 90 | 180 | 270;
287
+ /** the size of the default unit in 1/72 inch (PDF 1.6; not in PDF/A-1) */
288
+ userUnit?: number;
289
+ }
290
+ export type AFRelationship = 'Source' | 'Data' | 'Alternative' | 'Supplement' | 'Unspecified';
291
+ export interface AttachOptions {
292
+ /** the file name, checked (spoofing, look-alikes, device names, an allowlist of passive types) */
293
+ name: string;
294
+ /** required in PDF/A-3; must agree with the extension */
295
+ mimeType?: string;
296
+ description?: string;
297
+ /** /AFRelationship (default Unspecified in PDF/A-3) */
298
+ relationship?: AFRelationship;
299
+ created?: Date;
300
+ /** default: the document's creationDate */
301
+ modified?: Date;
302
+ /** refuse a larger file (default and at most 256 MB) */
303
+ maxBytes?: number;
304
+ allowTypes?: string[];
305
+ allowArchives?: boolean;
306
+ }
307
+ export type FacturXProfile = 'MINIMUM' | 'BASIC WL' | 'BASIC' | 'EN 16931' | 'EXTENDED' | 'XRECHNUNG';
308
+
309
+ /**
310
+ * A path, built as with the Canvas 2D API, in top-left, y-down points (angles in radians turn clockwise on the page).
311
+ * Made by page.path(); not tied to a page. At most 1,000,000 segments; every number must be finite and under 1e9.
312
+ */
313
+ export interface Path {
314
+ readonly segments: number;
315
+ moveTo(x: number, y: number): this;
316
+ /** with no current point, a moveTo */
317
+ lineTo(x: number, y: number): this;
318
+ bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): this;
319
+ /** written as the equivalent cubic */
320
+ quadraticCurveTo(cx: number, cy: number, x: number, y: number): this;
321
+ arc(x: number, y: number, r: number, start: number, end: number, counterclockwise?: boolean): this;
322
+ arcTo(x1: number, y1: number, x2: number, y2: number, r: number): this;
323
+ ellipse(x: number, y: number, rx: number, ry: number, rotation: number, start: number, end: number, counterclockwise?: boolean): this;
324
+ rect(x: number, y: number, w: number, h: number): this;
325
+ /** radii: one radius, or [all] | [tl+br, tr+bl] | [tl, tr+bl, br] | [tl, tr, br, bl]; scaled down when they do not fit */
326
+ roundedRect(x: number, y: number, w: number, h: number, radii?: number | number[]): this;
327
+ closePath(): this;
328
+ /** append SVG path data (M L H V C S Q T A Z, absolute and relative); at most 10 MB; malformed data throws a SyntaxError */
329
+ svg(d: string): this;
330
+ }
331
+
332
+ /** A gradient or tiling pattern made by a page of this document (an opaque handle: copies and forgeries are refused). */
333
+ export interface Gradient { readonly type: 'gradient' }
334
+ export interface TilingPattern { readonly type: 'tiling' }
335
+ /** A colour, or a gradient / pattern as a paint. */
336
+ export type Paint = Color | Gradient | TilingPattern;
337
+ /** [[offset 0–1, colour], …] or [{ offset, color }, …]; 1–256 stops, sorted and clamped; one colour space (gray and RGB mix) */
338
+ export type ColorStops = ([number, Color] | { offset: number; color: Color })[];
339
+
340
+ export type BlendMode =
341
+ | 'Normal' | 'Multiply' | 'Screen' | 'Overlay' | 'Darken' | 'Lighten' | 'ColorDodge' | 'ColorBurn'
342
+ | 'HardLight' | 'SoftLight' | 'Difference' | 'Exclusion' | 'Hue' | 'Saturation' | 'Color' | 'Luminosity'
343
+ | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'hard-light'
344
+ | 'soft-light' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity';
345
+
346
+ export interface DrawOptions {
347
+ /** fill paint (default black when filling); `color` sets whichever of fill / stroke the call paints */
348
+ fill?: Paint;
349
+ stroke?: Paint;
350
+ color?: Paint;
351
+ /** fill rule (default nonzero) */
352
+ rule?: 'nonzero' | 'evenodd';
353
+ /** stroke width (default 1) */
354
+ width?: number;
355
+ /** dash lengths (at most 100, not all 0) and phase */
356
+ dash?: number[];
357
+ dashPhase?: number;
358
+ cap?: 'butt' | 'round' | 'square';
359
+ join?: 'miter' | 'round' | 'bevel';
360
+ /** ≥ 1 (default 10) */
361
+ miterLimit?: number;
362
+ /** 0–1, for fill and stroke; multiplied by fillOpacity / strokeOpacity */
363
+ opacity?: number;
364
+ fillOpacity?: number;
365
+ strokeOpacity?: number;
366
+ blendMode?: BlendMode;
367
+ }
368
+
369
+ export interface Page {
370
+ /** 0-based */
371
+ readonly index: number;
372
+ /** 1-based */
373
+ readonly number: number;
374
+ readonly width: number;
375
+ readonly height: number;
376
+ /** One line of text; y is the top of the line box (baseline at y + font.ascent * size). */
377
+ text(text: string, o: TextOptions): this;
378
+ /**
379
+ * Paragraphs (split at \n) wrapped by word into width (a word longer than a line is broken), aligned, from (x, y)
380
+ * down. Returns the height used, the lines drawn and the text that did not fit (''). At most 10,000,000 characters.
381
+ */
382
+ textBox(text: string, o: TextBoxOptions): { height: number; lines: number; overflow: string };
383
+ line(x1: number, y1: number, x2: number, y2: number, o?: { color?: Color; width?: number; dash?: number[]; opacity?: number; blendMode?: string }): this;
384
+ /** fill, stroke or both; neither: filled black */
385
+ rect(x: number, y: number, w: number, h: number, o?: { fill?: Color; stroke?: Color; width?: number; dash?: number[]; opacity?: number; fillOpacity?: number; strokeOpacity?: number; blendMode?: string }): this;
386
+ /** draw an image (pdf.embedImage) in a box; the same image drawn again is not written again */
387
+ image(image: Image, o?: ImageOptions): this;
388
+ /**
389
+ * a link over a box: to a URL (http, https, mailto; allowSchemes widens, never to javascript:, vbscript:, data: or
390
+ * file:), a page with a fit (it may not exist yet), a named destination, or NextPage/PrevPage/FirstPage/LastPage.
391
+ * No other action (JavaScript, Launch, GoToR, SubmitForm…) can be written.
392
+ */
393
+ link(x: number, y: number, w: number, h: number, target: LinkTarget, o?: LinkOptions): this;
394
+ /** a sticky note (Text annotation) at (x, y), 20 × 20; replyTo another note makes it a reply (/IRT) */
395
+ note(x: number, y: number, o?: AnnotationOptions & { icon?: NoteIcon; open?: boolean; replyTo?: Annotation }): Annotation;
396
+ /** text markup over one or more rectangles (the text's boxes); QuadPoints are computed from them */
397
+ highlight(rects: Rect | Rect[], o?: AnnotationOptions): Annotation;
398
+ underline(rects: Rect | Rect[], o?: AnnotationOptions): Annotation;
399
+ strikeOut(rects: Rect | Rect[], o?: AnnotationOptions): Annotation;
400
+ squiggly(rects: Rect | Rect[], o?: AnnotationOptions): Annotation;
401
+ /** a FreeText annotation: text wrapped in a box, drawn with the package's text; contents default to the text */
402
+ freeText(text: string, o: AnnotationOptions & Rect & { font: Font; size?: number; textColor?: Color; align?: 'left' | 'center' | 'right'; border?: { width?: number; color?: Color } | false; background?: Color; padding?: number }): Annotation;
403
+ /** a shape annotation; color is the line, interior the fill (Square, Circle, Polygon; Line/PolyLine closed endings) */
404
+ markup(type: 'Square' | 'Circle', box: Rect, o?: ShapeOptions): Annotation;
405
+ markup(type: 'Line', line: { x1: number; y1: number; x2: number; y2: number }, o?: ShapeOptions & { lineEndings?: [LineEnding, LineEnding] }): Annotation;
406
+ markup(type: 'Polygon', points: Point[], o?: ShapeOptions): Annotation;
407
+ markup(type: 'PolyLine', points: Point[], o?: ShapeOptions & { lineEndings?: [LineEnding, LineEnding] }): Annotation;
408
+ markup(type: 'Ink', strokes: Point[][], o?: ShapeOptions): Annotation;
409
+ /** a rubber stamp: a standard name with its label drawn in font, or draw(ap) your own appearance (ap: a page of the box's size) */
410
+ stamp(o: AnnotationOptions & Rect & ({ name?: StampName; font: Font } | { name?: StampName; draw: (ap: Page) => void })): Annotation;
411
+ /**
412
+ * a FileAttachment annotation embedding a file (not in PDF/A-2). name is checked (core/filename.js): passive types
413
+ * only unless allowTypes lists the extension (you accept that type's risk); zip with allowArchives.
414
+ */
415
+ attachFile(bytes: Uint8Array | ArrayBuffer, o: AnnotationOptions & { x?: number; y?: number; name: string; mimeType?: string; description?: string; created?: Date; icon?: 'PushPin' | 'Paperclip' | 'Graph' | 'Tag'; allowTypes?: string[]; allowArchives?: boolean }): Annotation;
416
+ /** a new, empty path */
417
+ path(): Path;
418
+ fill(path: Path, o?: DrawOptions): this;
419
+ stroke(path: Path, o?: DrawOptions): this;
420
+ fillAndStroke(path: Path, o?: DrawOptions): this;
421
+ /** SVG path data, drawn as rect(): fill, stroke or both; neither: filled black */
422
+ svgPath(d: string, o?: DrawOptions): this;
423
+ /** intersect the clip with the path until the enclosing restore(); an empty path clips everything */
424
+ clip(path: Path, rule?: 'nonzero' | 'evenodd'): this;
425
+ /** paint a gradient over the current clip */
426
+ shade(gradient: Gradient): this;
427
+ /** save the graphics state (transform, clip, styles); at most 1000 deep (27 in PDF/A). Unrestored saves are closed at the page end with a warning */
428
+ save(): this;
429
+ /** throws without a matching save() */
430
+ restore(): this;
431
+ /** multiply the current transform (as canvas transform()) */
432
+ transform(a: number, b: number, c: number, d: number, e: number, f: number): this;
433
+ translate(x: number, y: number): this;
434
+ /** radians, clockwise on the page */
435
+ rotate(angle: number): this;
436
+ scale(sx: number, sy?: number): this;
437
+ /** radians, as CSS skew(ax, ay) */
438
+ skew(ax: number, ay?: number): this;
439
+ /** a gradient from (x0, y0) to (x1, y1), in the space current when it is painted; extend: past the ends (default true) */
440
+ linearGradient(x0: number, y0: number, x1: number, y1: number, stops: ColorStops, o?: { extend?: boolean | [boolean, boolean] }): Gradient;
441
+ radialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number, stops: ColorStops, o?: { extend?: boolean | [boolean, boolean] }): Gradient;
442
+ /** draw(cell) draws one cell (shapes, gradients, patterns; not text or links), repeated every width + spacing */
443
+ tilingPattern(o: { width: number; height: number; spacing?: number | [number, number] }, draw: (cell: Page) => void): TilingPattern;
444
+ /** tagged PDFs: what fn draws is a Figure with this alt text (required); graphics outside a tag are artifacts. Otherwise fn just runs */
445
+ figure<T>(o: { alt: string }, fn: () => T): T;
446
+ /** tagged PDFs: what fn draws (synchronously) becomes a structure element of that type; otherwise fn just runs */
447
+ tag<T>(type: string, fn: () => T, o?: TagOptions): T;
448
+ /** what fn draws is a typed artifact (/Artifact << /Type /Pagination /Subtype /Header >>); tagged PDFs, outside any tag */
449
+ artifact<T>(o: ArtifactOptions, fn: () => T): T;
450
+ /** what fn draws (synchronously) belongs to the layer; save()/restore() must balance inside fn */
451
+ layer<T>(layer: Layer, fn: () => T): T;
452
+ /** compress and write the page; nothing more can be drawn on it */
453
+ end(): Promise<void>;
454
+ }
455
+
456
+ /** how a destination fits its page; coordinates top-left. Without fit: XYZ when left, top or zoom is given, else Fit */
457
+ export interface Fit {
458
+ fit?: 'XYZ' | 'Fit' | 'FitH' | 'FitV' | 'FitR' | 'FitB' | 'FitBH' | 'FitBV';
459
+ left?: number;
460
+ top?: number;
461
+ /** FitR */
462
+ right?: number;
463
+ bottom?: number;
464
+ /** XYZ: a factor, 1 = 100% (0 or none: keep) */
465
+ zoom?: number;
466
+ }
467
+ export type LinkTarget = { url: string } | ({ page: number | Page } & Fit) | { dest: string } | { named: 'NextPage' | 'PrevPage' | 'FirstPage' | 'LastPage' };
468
+ export interface LinkOptions {
469
+ /** what screen readers say (default: the URL or "Page n") */
470
+ alt?: string;
471
+ /** URL schemes allowed besides http, https and mailto (never javascript, vbscript, data, file) */
472
+ allowSchemes?: string[];
473
+ highlight?: 'none' | 'invert' | 'outline' | 'push';
474
+ border?: { width?: number; style?: 'solid' | 'dashed' | 'beveled' | 'inset' | 'underline'; dash?: number[]; color?: Color };
475
+ quadPoints?: Rect | Rect[];
476
+ }
477
+ export interface Rect { x: number; y: number; width: number; height: number }
478
+ export type Point = [number, number] | { x: number; y: number };
479
+ /** an annotation made by a page method (an opaque handle: a note's replyTo takes one) */
480
+ export interface Annotation { readonly type: 'annotation'; readonly subtype: string }
481
+ export interface AnnotationOptions {
482
+ /** gray, RGB or CMYK (no spot or ICC colours) */
483
+ color?: Color;
484
+ /** the annotation's text; required in tagged PDFs (it is the alternate description) */
485
+ contents?: string;
486
+ /** /T */
487
+ author?: string;
488
+ modified?: Date;
489
+ /** default: print (notes and attachments: also noZoom, noRotate). PDF/A: always printed and visible */
490
+ flags?: Partial<Record<'invisible' | 'hidden' | 'print' | 'noZoom' | 'noRotate' | 'noView' | 'readOnly' | 'locked' | 'toggleNoView' | 'lockedContents', boolean>>;
491
+ }
492
+ export interface ShapeOptions extends AnnotationOptions { interior?: Color; lineWidth?: number; dash?: number[] }
493
+ export type NoteIcon = 'Comment' | 'Key' | 'Note' | 'Help' | 'NewParagraph' | 'Paragraph' | 'Insert';
494
+ export type LineEnding = 'None' | 'Square' | 'Circle' | 'Diamond' | 'OpenArrow' | 'ClosedArrow' | 'Butt' | 'ROpenArrow' | 'RClosedArrow' | 'Slash';
495
+ export type StampName = 'Approved' | 'Experimental' | 'NotApproved' | 'AsIs' | 'Expired' | 'NotForPublicRelease' | 'Confidential' | 'Final' | 'Sold' | 'Departmental' | 'ForComment' | 'TopSecret' | 'Draft' | 'ForPublicRelease';
496
+
497
+ export interface OutlineEntry extends Fit {
498
+ /** at most 4096 characters */
499
+ title: string;
500
+ /** 1-based page number or page object (or dest) */
501
+ page?: number | Page;
502
+ /** a named destination (pdf.destination) instead of page */
503
+ dest?: string;
504
+ /** nesting, 0 = top level, at most 63 */
505
+ level?: number;
506
+ /** default true; closed: its children are hidden until opened */
507
+ open?: boolean;
508
+ /** RGB or gray */
509
+ color?: Color;
510
+ bold?: boolean;
511
+ italic?: boolean;
512
+ }
513
+ export interface PageLabelRange {
514
+ /** 0-based page index where the range starts */
515
+ start: number;
516
+ /** D decimal, r/R roman, a/A letters; none: the prefix alone */
517
+ style?: 'D' | 'r' | 'R' | 'a' | 'A';
518
+ prefix?: string;
519
+ /** the first number (default 1) */
520
+ first?: number;
521
+ }
522
+ export interface ViewerOptions {
523
+ hideToolbar?: boolean; hideMenubar?: boolean; hideWindowUI?: boolean; fitWindow?: boolean; centerWindow?: boolean;
524
+ /** cannot be false in tagged PDFs */
525
+ displayDocTitle?: boolean;
526
+ direction?: 'L2R' | 'R2L';
527
+ printScaling?: 'None' | 'AppDefault';
528
+ duplex?: 'Simplex' | 'DuplexFlipShortEdge' | 'DuplexFlipLongEdge';
529
+ pickTrayByPDFSize?: boolean;
530
+ /** 1–5 */
531
+ numCopies?: number;
532
+ pageMode?: 'UseNone' | 'UseOutlines' | 'UseThumbs' | 'FullScreen' | 'UseOC' | 'UseAttachments';
533
+ pageLayout?: 'SinglePage' | 'OneColumn' | 'TwoColumnLeft' | 'TwoColumnRight' | 'TwoPageLeft' | 'TwoPageRight';
534
+ /** the open action: a page destination (the only open action written) */
535
+ openAt?: { page: number | Page } & Fit;
536
+ }
537
+
538
+ /** A form field made by pdf.form (an opaque handle: reset lists and signature locks take it). name is its full name. */
539
+ export interface Field {
540
+ readonly type: 'field';
541
+ readonly kind: 'text' | 'checkbox' | 'radio' | 'combo' | 'list' | 'button' | 'signature';
542
+ readonly name: string;
543
+ }
544
+ /** Where a widget goes: a page of this PDF and a box (top-left space). */
545
+ export interface WidgetBox { page: Page; x?: number; y?: number; width: number; height: number }
546
+ export interface FieldOptions extends WidgetBox {
547
+ /** /BS and /MK /BC (default { width: 1, color: 0 }); false: none */
548
+ border?: { width?: number; color?: Color } | false;
549
+ /** /MK /BG: a gray level, '#rrggbb', [r, g, b] or [c, m, y, k] */
550
+ background?: Color;
551
+ /** /TU: shown on hover, and the field's accessible name (required in tagged PDFs) */
552
+ tooltip?: string;
553
+ readOnly?: boolean;
554
+ required?: boolean;
555
+ }
556
+ export interface FieldTextOptions {
557
+ font: Font;
558
+ /** fonts tried, in order, for characters the font lacks (a character none has throws) */
559
+ fallback?: Font[];
560
+ /** 0 (default): auto, the largest up to 12 that fits */
561
+ size?: number;
562
+ /** a device colour (written in /DA) */
563
+ textColor?: Color;
564
+ /** /Q */
565
+ align?: 'left' | 'center' | 'right';
566
+ }
567
+ export type CheckStyle = 'check' | 'cross' | 'circle' | 'square' | 'diamond' | 'star';
568
+ export interface TextFieldOptions extends FieldOptions, FieldTextOptions {
569
+ /** at most 100,000 characters (and maxLen); line breaks only when multiline */
570
+ value?: string;
571
+ defaultValue?: string;
572
+ multiline?: boolean;
573
+ /** takes no value: readers must never store a password in the file */
574
+ password?: boolean;
575
+ /** maxLen cells of equal width (needs maxLen ≤ 1000; not multiline or password) */
576
+ comb?: boolean;
577
+ maxLen?: number;
578
+ doNotSpellCheck?: boolean;
579
+ doNotScroll?: boolean;
580
+ }
581
+ export interface CheckboxOptions extends FieldOptions {
582
+ checked?: boolean;
583
+ /** the export value (the on state's name), default 'Yes'; not 'Off' */
584
+ value?: string;
585
+ style?: CheckStyle;
586
+ /** the mark's colour */
587
+ color?: Color;
588
+ }
589
+ export interface RadioGroupOptions extends Omit<FieldOptions, keyof WidgetBox> {
590
+ /** 1–1000 buttons, each with its own export value (the same one only with radiosInUnison) */
591
+ buttons: (WidgetBox & { value: string })[];
592
+ /** the selected button's value (none: all off) */
593
+ value?: string;
594
+ /** default true: clicking the selected button does not turn it off */
595
+ noToggleToOff?: boolean;
596
+ radiosInUnison?: boolean;
597
+ /** default 'circle' */
598
+ style?: CheckStyle;
599
+ color?: Color;
600
+ }
601
+ /** an option: one string (export value and display text), or [export value, display text] */
602
+ export type ChoiceOption = string | readonly [string, string];
603
+ export interface ChoiceOptions extends FieldOptions, FieldTextOptions {
604
+ /** at most 10,000, in the order given (the Sort flag is never set); export values unique */
605
+ options: ChoiceOption[];
606
+ }
607
+ export interface ComboBoxOptions extends ChoiceOptions {
608
+ /** an export value; with editable, any text */
609
+ value?: string;
610
+ editable?: boolean;
611
+ doNotSpellCheck?: boolean;
612
+ }
613
+ export interface ListBoxOptions extends ChoiceOptions {
614
+ /** export values (several with multiSelect; /I gets their indexes) */
615
+ value?: string | string[];
616
+ multiSelect?: boolean;
617
+ }
618
+ /** A push button's action: ResetForm (all fields; or the fields named, or all but them with exclude) or a named page action. Nothing else. Not in PDF/A. */
619
+ export type ButtonAction = { reset: true } | { reset: (string | Field)[]; exclude?: boolean } | { named: 'NextPage' | 'PrevPage' | 'FirstPage' | 'LastPage' };
620
+ export interface ButtonOptions extends FieldOptions, Partial<FieldTextOptions> {
621
+ /** needs font */
622
+ label?: string;
623
+ /** an image (pdf.embedImage), fitted in the button (above the label when there is one) */
624
+ icon?: Image;
625
+ action?: ButtonAction;
626
+ /** the face when pressed (/D; not in PDF/A, whose appearances have /N only) */
627
+ pressedBackground?: Color;
628
+ }
629
+ export interface SignatureOptions extends FieldOptions {
630
+ /** /Lock: the fields signing locks */
631
+ lock?: { action?: 'All' } | { action: 'Include' | 'Exclude'; fields: (string | Field)[] };
632
+ }
633
+ /** pdf.form, or a group of it: fields named here get this group's full name before theirs ("address.city"). */
634
+ export interface FormScope {
635
+ /** a group: a parent field whose children are named "name.child". At most 32 levels. */
636
+ group(name: string): FormScope;
637
+ textField(name: string, o: TextFieldOptions): Field;
638
+ checkbox(name: string, o: CheckboxOptions): Field;
639
+ radioGroup(name: string, o: RadioGroupOptions): Field;
640
+ comboBox(name: string, o: ComboBoxOptions): Field;
641
+ listBox(name: string, o: ListBoxOptions): Field;
642
+ button(name: string, o: ButtonOptions): Field;
643
+ /** an empty signature field (a widget with a frame), for signing later */
644
+ signature(name: string, o: SignatureOptions): Field;
645
+ }
646
+
647
+ export interface Pdf {
648
+ standardFont(name: StandardFontName): Font;
649
+ /** a TrueType or OpenType/CFF font; subset by default; shaper: text goes through it (complex scripts) */
650
+ embedFont(bytes: Uint8Array | ArrayBuffer, o?: { subset?: boolean | Subsetter; shaper?: Shaper }): Promise<Font>;
651
+ /** a JPEG or PNG, written now as an image XObject. colorSpace: an ICC colour space with the image's component count */
652
+ embedImage(bytes: Uint8Array | ArrayBuffer, o?: { colorSpace?: IccColorSpace; /** the decoded size a PNG with alpha or interlacing may have; default 64 MB */ maxDecodedBytes?: number }): Promise<Image>;
653
+ /** a spot colour: its name and the device colour (gray, RGB, CMYK) shown for it at full tint. One definition per name */
654
+ spotColor(name: string, alternate: number | string | readonly number[]): SpotColor;
655
+ /** an ICC-based colour space from a gray, RGB or CMYK profile (its header is checked) */
656
+ iccColorSpace(profile: Uint8Array | ArrayBuffer): Promise<IccColorSpace>;
657
+ /** default A4 (595.28 × 841.89) */
658
+ addPage(o?: PageOptions): Page;
659
+ /** a document-level embedded file (the EmbeddedFiles name tree); PDF/A-3 only among the PDF/A levels */
660
+ attach(bytes: Uint8Array | ArrayBuffer, o: AttachOptions): Promise<void>;
661
+ /** a Factur-X / ZUGFeRD / XRechnung invoice: the CII XML as factur-x.xml (xrechnung.xml) with the fx XMP schema. PDF/A-3 */
662
+ facturX(xml: Uint8Array | ArrayBuffer, o: { profile: FacturXProfile; version?: '1.0' }): Promise<void>;
663
+ /** a layer (optional content group); draw into it with page.layer. Not in PDF/A-1 */
664
+ layer(name: string, o?: LayerOptions): Layer;
665
+ /** bookmarks; at most 100,000 entries */
666
+ outline(entry: OutlineEntry | OutlineEntry[]): void;
667
+ /** a named destination (unique, at most 1024 UTF-8 bytes, 100,000 a document) for links, outline entries */
668
+ destination(name: string, page: number | Page, fit?: Fit | Fit['fit']): void;
669
+ /** page labels (a later call replaces them) */
670
+ pageLabels(ranges: PageLabelRange[]): void;
671
+ /** viewer preferences, page mode and layout, and the open action (later calls add to and override earlier ones) */
672
+ viewer(o: ViewerOptions): void;
673
+ /**
674
+ * Interactive form fields. Names: no '.', control, format or bidi characters, at most 256 characters; full names
675
+ * unique; at most 10,000 fields. No JavaScript, additional actions or submit actions can be written.
676
+ */
677
+ readonly form: FormScope;
678
+ /**
679
+ * Sign the document (PAdES B-B, B-T with a timestamp) as it is written: needs createPdf's `sign` option. field: a
680
+ * signature field, or { name, page, x, y, width, height } to make one. The signer runs at end(); one signature a document.
681
+ */
682
+ sign(field: Field | ({ name: string } & SignatureOptions), o: SignOptions): Promise<void>;
683
+ /** end open pages, write the rest, end the sink */
684
+ end(): Promise<{ pages: number; bytes: number; warnings: string[] }>;
685
+ /** the extension API (ARCHITECTURE.md); not covered by semver in 0.x */
686
+ readonly core: unknown;
687
+ }
688
+
689
+ export function createPdf(sink: Sink, options?: PdfOptions): Pdf;
690
+ /** Build a PDF in memory. */
691
+ export function toBytes(build: (pdf: Pdf) => unknown, options?: PdfOptions): Promise<Uint8Array>;
692
+ export const STANDARD_NAMES: StandardFontName[];
693
+
694
+ // ---- reading and modifying (group H) ----
695
+
696
+ export type PdfReadErrorCode = 'E_MALFORMED' | 'E_BUDGET' | 'E_DEPTH' | 'E_CYCLE' | 'E_TIMEOUT' | 'E_ABORTED' | 'E_PASSWORD' | 'E_ENCRYPTED' | 'E_UNSUPPORTED' | 'E_ACTIVE' | 'E_SIGNED';
697
+ /** Every failure caused by the input (malformed, over budget, a loop, a wrong password, active content in an update). */
698
+ export class PdfReadError extends Error {
699
+ readonly name: 'PdfReadError';
700
+ readonly code: PdfReadErrorCode;
701
+ }
702
+ export interface ReadBudget {
703
+ /** decoded stream bytes for the whole document (default 512 MB) */
704
+ maxDecoded?: number;
705
+ /** decoded bytes of one stream (default 128 MB) */
706
+ maxStream?: number;
707
+ /** parsing steps: tokens, xref rows, tree nodes, operators (default 200,000,000) */
708
+ maxSteps?: number;
709
+ /** cross-reference entries and scanned objects held (default 5,000,000) */
710
+ maxObjects?: number;
711
+ /** pieces of text one page's extraction holds (default 1,000,000; a page also stops at 16,000,000 characters) */
712
+ maxTextItems?: number;
713
+ }
714
+ export interface LoadOptions {
715
+ /** the user or the owner password (RC4, AES-128 and AES-256 files are read; only AES is ever written) */
716
+ password?: string;
717
+ budget?: ReadBudget;
718
+ timeoutMs?: number;
719
+ signal?: AbortSignal;
720
+ }
721
+ export type Rect4 = [number, number, number, number];
722
+ export interface LoadedPage {
723
+ readonly index: number;
724
+ /** the MediaBox's size, in points */
725
+ readonly width: number;
726
+ readonly height: number;
727
+ readonly mediaBox: Rect4; readonly cropBox: Rect4; readonly bleedBox: Rect4; readonly trimBox: Rect4; readonly artBox: Rect4;
728
+ readonly rotation: 0 | 90 | 180 | 270;
729
+ readonly userUnit: number;
730
+ /** the text in content order, grouped in lines (not layout-perfect: no columns or reading order beyond the stream's) */
731
+ /** timeoutMs: 30 000 by default (Infinity: only the document's own limit); E_TIMEOUT or E_BUDGET when exceeded */
732
+ extractText(o?: { timeoutMs?: number }): string;
733
+ annotations(): { subtype: string; rect: Rect4 | null; contents: string | null; uri: string | null; page: number | null }[];
734
+ /**
735
+ * Draw on top of the page at save(), with the writer's page methods (top-left space of the MediaBox), wrapped in
736
+ * q/Q. fonts: a standard font's name or font bytes; images: PNG or JPEG bytes; made once in the new file.
737
+ */
738
+ draw(fn: (page: Page, r: { fonts: Record<string, Font>; images: Record<string, Image>; pdf: Pdf }) => void, o?: { fonts?: Record<string, StandardFontName | Uint8Array>; images?: Record<string, Uint8Array> }): this;
739
+ /** turn by a multiple of 90 degrees, clockwise */
740
+ rotate(deg: number): this;
741
+ removeAnnotations(): this;
742
+ }
743
+ export interface LoadedField {
744
+ name: string;
745
+ type: 'text' | 'checkbox' | 'radio' | 'pushbutton' | 'combo' | 'list' | 'signature' | 'unknown';
746
+ value: string | string[] | null;
747
+ readOnly: boolean; required: boolean; flags: number;
748
+ options: string[] | null; exports: string[] | null;
749
+ widgets: { ref: number; page: number | null; rect: Rect4 | null; states: string[]; state: string | null }[];
750
+ }
751
+ export interface LoadedAttachment {
752
+ /** the name as the file says it */
753
+ rawName: string;
754
+ /** the name checked like the writer's (core/filename.js), or null when refused (see refused) */
755
+ name: string | null;
756
+ refused: string | null;
757
+ mimeType: string | null; page: number | null; description: string | null; size: number | null; relationship: string | null;
758
+ /** the file's bytes, decoded under the document's budget (a PDF attachment is data: its own content is not sanitised) */
759
+ bytes(): Uint8Array;
760
+ }
761
+ export interface LoadedSignature {
762
+ field: string; subFilter: string | null; byteRange: Rect4 | null;
763
+ name: string | null; reason: string | null; location: string | null; date: Date | null;
764
+ wellFormed: boolean;
765
+ /** it covers every byte of the file but its /Contents */
766
+ coversWholeFile: boolean;
767
+ revision: number;
768
+ /** bytes appended after it (an incremental update) */
769
+ bytesAfter: number | null;
770
+ cms: Uint8Array | null;
771
+ signedBytes(): Uint8Array;
772
+ }
773
+ export interface OutlineItem { title: string; page: number | null; url: string | null; children: OutlineItem[] }
774
+ export interface SaveOptions {
775
+ /** re-compress uncompressed streams (default true) */
776
+ compress?: boolean;
777
+ /** keep JavaScript, Launch and other actions outside the allowlist, /AA, XFA, RichMedia… (default false: dropped and reported) */
778
+ keepActiveContent?: boolean;
779
+ /** AES encryption of the new file */
780
+ encrypt?: EncryptOptions | true;
781
+ /** 'keep' (default: when every document declares the same PDF/A level and output intent) or false */
782
+ pdfa?: 'keep' | false;
783
+ /** keep the structure tree (default true; only when every page comes from this document) */
784
+ keepStructure?: boolean;
785
+ creationDate?: Date;
786
+ signal?: AbortSignal;
787
+ timeoutMs?: number;
788
+ }
789
+ export interface SaveResult {
790
+ pages: number;
791
+ /** what was removed: active content, signature values */
792
+ stripped: { what: string; count: number }[];
793
+ warnings: string[];
794
+ }
795
+ export interface IncrementalOptions {
796
+ /** sign: an empty signature field's name, or { name, page, x, y, width, height } (no size: invisible) for a new one */
797
+ sign?: { field: string | { name: string; page?: number; x?: number; y?: number; width?: number; height?: number }; signer: Signer; hash?: HashName } & Omit<SignOptions, 'signer' | 'certify'>;
798
+ /** an update cannot remove bytes: a file with active content is refused (E_ACTIVE) unless this is true */
799
+ keepActiveContent?: boolean;
800
+ /** a signed document: form fills are refused (E_SIGNED) unless this is true; DocMDP and field locks still apply, and the
801
+ * filled widgets may cover at most 40% of a page in all (refilling existing widgets after signing is the "shadow
802
+ * attack" class) */
803
+ allowFillAfterSigning?: boolean;
804
+ /** a signed document without DocMDP: rotation and Info/XMP changes are refused (E_SIGNED) unless this is true */
805
+ allowChangesAfterSigning?: boolean;
806
+ }
807
+ export interface LoadedPdf {
808
+ readonly pageCount: number;
809
+ readonly version: string;
810
+ readonly encrypted: boolean;
811
+ readonly encryption: { algorithm: 'rc4' | 'aes-128' | 'aes-256'; revision: number; owner: boolean; permissions: Record<keyof Permissions, boolean> } | null;
812
+ /** the cross-reference was broken and rebuilt by scanning */
813
+ readonly recovered: boolean;
814
+ readonly warnings: string[];
815
+ readonly info: { title?: string; author?: string; subject?: string; keywords?: string; creator?: string; producer?: string; creationDate?: Date | null; modDate?: Date | null };
816
+ readonly xmp: string | null;
817
+ readonly pdfa: { part: number; conformance: 'a' | 'b' | 'u' } | null;
818
+ readonly outlines: OutlineItem[];
819
+ readonly fields: LoadedField[];
820
+ readonly attachments: LoadedAttachment[];
821
+ readonly signatures: LoadedSignature[];
822
+ page(i: number): LoadedPage;
823
+ /** every page's text, joined by form feeds */
824
+ /** timeoutMs: 30 000 by default (Infinity: only the document's own limit); E_TIMEOUT or E_BUDGET when exceeded */
825
+ extractText(o?: { timeoutMs?: number }): string;
826
+ setInfo(info: { title?: string | null; author?: string | null; subject?: string | null; keywords?: string | null; creator?: string | null }): this;
827
+ setXmp(xml: string): this;
828
+ copyPages(src: LoadedPdf, indexes?: number[], o?: { at?: number }): this;
829
+ merge(others: LoadedPdf[]): this;
830
+ removePages(indexes: number[]): this;
831
+ reorder(order: number[]): this;
832
+ movePage(from: number, to: number): this;
833
+ removeAnnotations(): this;
834
+ /** text, combo and radio: a string; check box: a boolean; list: a string or strings. font: for the new appearances (needed in PDF/A) */
835
+ fill(values: Record<string, string | boolean | string[] | null>, o?: { font?: Uint8Array }): this;
836
+ flatten(): this;
837
+ /** a new file (a full rewrite through the writer) */
838
+ save(o?: SaveOptions): Promise<SaveResult & { bytes: Uint8Array }>;
839
+ saveTo(sink: Sink, o?: SaveOptions): Promise<SaveResult & { size: number }>;
840
+ /** the original bytes and an update after them (existing signatures stay valid) */
841
+ saveIncremental(o?: IncrementalOptions): Promise<{ bytes: Uint8Array; size: number; activeContent: { what: string; count: number }[]; warnings: string[] }>;
842
+ /** an independent plan over the same source */
843
+ fork(): LoadedPdf;
844
+ }
845
+ export function loadPdf(bytes: Uint8Array | ArrayBuffer, options?: LoadOptions): Promise<LoadedPdf>;
846
+ /** every page of each document, in order, in a new file (the first one's catalog, with what the others bring) */
847
+ export function mergePdfs(docs: LoadedPdf[], options?: SaveOptions): Promise<SaveResult & { bytes: Uint8Array }>;