@asterdoc/render 0.0.0-stage → 0.9.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/LICENSE +25 -0
- package/README.md +264 -2
- package/dist/check-BA5xdYgi.d.ts +69 -0
- package/dist/chunk-4QVR6LUY.js +98 -0
- package/dist/chunk-ICQLU4FL.js +630 -0
- package/dist/chunk-PNYKTSIT.js +1267 -0
- package/dist/chunk-U7LF3GN4.js +34 -0
- package/dist/context-BmjDcc_j.d.ts +32 -0
- package/dist/docx.d.ts +37 -0
- package/dist/docx.js +38 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +69 -0
- package/dist/layer-bindings-CFXyN7SM.d.ts +94 -0
- package/dist/pdf.d.ts +620 -0
- package/dist/pdf.js +4638 -0
- package/dist/signatures-DPaL4gay.d.ts +20 -0
- package/dist/signatures-cS3V0yR3.d.ts +27 -0
- package/dist/text/field-formatter.d.ts +46 -0
- package/dist/text/field-formatter.js +21 -0
- package/dist/text.d.ts +44 -0
- package/dist/text.js +77 -0
- package/package.json +103 -3
package/dist/pdf.d.ts
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
import { BinaryContent, Form, Formatter, LayerFormat, AsterdocRenderer, RendererLayer, LocateHit } from '@asterdoc/types';
|
|
2
|
+
export { LocateHit } from '@asterdoc/types';
|
|
3
|
+
import { P as PdfFont } from './layer-bindings-CFXyN7SM.js';
|
|
4
|
+
export { a as PdfBindingKeyError, b as PdfBindingPart, c as PdfBindingSyntaxError, d as PdfFontError, e as PdfFontMetrics, F as PdfFontProblem, p as parseBinding, f as pdfFontMetrics } from './layer-bindings-CFXyN7SM.js';
|
|
5
|
+
|
|
6
|
+
/** Why a value could not be drawn in its PDF form field or overlay. */
|
|
7
|
+
type PdfFieldFillReason = 'overflow' | 'comb-length' | 'missing-glyph' | 'unsupported-script';
|
|
8
|
+
/** What a {@link PdfFieldFillError} reports beyond the field and the reason. */
|
|
9
|
+
interface PdfFieldFillDetail {
|
|
10
|
+
/** For `overflow`, the minimum font size in points; for `comb-length`, the number of comb boxes. */
|
|
11
|
+
limit?: number;
|
|
12
|
+
/** For `missing-glyph`, the character no available font can draw. */
|
|
13
|
+
character?: string;
|
|
14
|
+
/** For `unsupported-script`, the script that needs glyph shaping. */
|
|
15
|
+
script?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Thrown when a value cannot be drawn faithfully in a PDF form field or a text
|
|
19
|
+
* overlay, naming the field and why.
|
|
20
|
+
*/
|
|
21
|
+
declare class PdfFieldFillError extends Error {
|
|
22
|
+
/** Fully qualified name of the PDF form field, or the overlay that failed. */
|
|
23
|
+
readonly field: string;
|
|
24
|
+
readonly reason: PdfFieldFillReason;
|
|
25
|
+
readonly limit?: number;
|
|
26
|
+
readonly character?: string;
|
|
27
|
+
readonly script?: string;
|
|
28
|
+
constructor(field: string, reason: PdfFieldFillReason, detail: PdfFieldFillDetail, message: string);
|
|
29
|
+
}
|
|
30
|
+
/** Smallest size a value shrinks to before filling fails with an overflow error. */
|
|
31
|
+
declare const MIN_FONT_SIZE = 6;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Thrown by every entry point that parses or writes a PDF when the file is
|
|
35
|
+
* encrypted.
|
|
36
|
+
*
|
|
37
|
+
* An encrypted file stores its strings and streams enciphered under a key
|
|
38
|
+
* derived from the file itself. Field names read as ciphertext, values written
|
|
39
|
+
* in plaintext would not decrypt, and copied streams would be garbage, so an
|
|
40
|
+
* encrypted file is refused rather than read wrongly.
|
|
41
|
+
*/
|
|
42
|
+
declare class PdfEncryptedError extends Error {
|
|
43
|
+
readonly code: "encrypted_pdf";
|
|
44
|
+
constructor();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** What kind of control an AcroForm field is, read from its `/FT` and `/Ff`. */
|
|
48
|
+
type PdfFieldType = 'text' | 'checkbox' | 'dropdown' | 'radio' | 'button' | 'signature' | 'unknown';
|
|
49
|
+
|
|
50
|
+
interface PdfFieldInfo {
|
|
51
|
+
name: string;
|
|
52
|
+
type: PdfFieldType;
|
|
53
|
+
value?: string | boolean | string[];
|
|
54
|
+
required?: boolean;
|
|
55
|
+
page?: number;
|
|
56
|
+
rect?: [number, number, number, number];
|
|
57
|
+
maxLen?: number | null;
|
|
58
|
+
}
|
|
59
|
+
interface InspectOptions {
|
|
60
|
+
includeButton?: boolean;
|
|
61
|
+
includeSignature?: boolean;
|
|
62
|
+
}
|
|
63
|
+
interface PdfPageInfo {
|
|
64
|
+
/** One-based page number. */
|
|
65
|
+
page: number;
|
|
66
|
+
/** Page width in PDF points. */
|
|
67
|
+
width: number;
|
|
68
|
+
/** Page height in PDF points. */
|
|
69
|
+
height: number;
|
|
70
|
+
}
|
|
71
|
+
interface PdfInfo {
|
|
72
|
+
pageCount: number;
|
|
73
|
+
pages: PdfPageInfo[];
|
|
74
|
+
}
|
|
75
|
+
/** Inspect page count and dimensions without loading a full PDF toolkit. */
|
|
76
|
+
declare function inspectPdf(template: BinaryContent): Promise<PdfInfo>;
|
|
77
|
+
/** List the AcroForm fields a PDF declares, walked as fill walks them. */
|
|
78
|
+
declare function inspectAcroFormFields(template: BinaryContent, options?: InspectOptions): Promise<PdfFieldInfo[]>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Burn AcroForm widget appearances into their pages and remove the interactive
|
|
82
|
+
* form controls. A widget a viewer does not show (Hidden or NoView) is removed
|
|
83
|
+
* without being drawn. PDFs without an AcroForm are returned unchanged.
|
|
84
|
+
*/
|
|
85
|
+
declare function flattenPdf(template: BinaryContent): Promise<Uint8Array>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* One PDF from several, page for page.
|
|
89
|
+
*
|
|
90
|
+
* A packet is a sequence of documents a reader sees as one file, and one file
|
|
91
|
+
* is what a hash and a signature map describe. Merging is how the sequence
|
|
92
|
+
* becomes that file.
|
|
93
|
+
*
|
|
94
|
+
* The merge writes a fresh document rather than appending an incremental
|
|
95
|
+
* update, because two sources number their objects from one and an incremental
|
|
96
|
+
* update has no way to hold both. Every object a kept page can reach is copied
|
|
97
|
+
* with a new number, every reference inside it is rewritten to that number, and
|
|
98
|
+
* a new catalog and page tree are written over the result. Stream bytes are
|
|
99
|
+
* copied exactly as they were stored, filters and all, so nothing is
|
|
100
|
+
* re-encoded and nothing is re-rendered.
|
|
101
|
+
*
|
|
102
|
+
* **What a merge drops.** Everything the old catalog held rather than the page:
|
|
103
|
+
*
|
|
104
|
+
* - the interactive form (`AcroForm`), so flatten a filled form before merging
|
|
105
|
+
* it and its values arrive as page content;
|
|
106
|
+
* - the structure tree (`StructTreeRoot`) and the role map, which is the
|
|
107
|
+
* document's accessibility tagging. A copied page keeps its `StructParents`
|
|
108
|
+
* key, which then points at a tree that is no longer there. A reader ignores
|
|
109
|
+
* a dangling `StructParents`; a screen reader gets untagged pages;
|
|
110
|
+
* - the name tree (`Names`) and `Dests`, so a named destination no longer
|
|
111
|
+
* resolves and a link that used one goes nowhere;
|
|
112
|
+
* - optional content (`OCProperties`), so a page drawn with layers loses the
|
|
113
|
+
* configuration that decides which are visible, and every layer paints;
|
|
114
|
+
* - `Lang`, `ViewerPreferences`, `Outlines`, `PageLabels`, `Metadata` and
|
|
115
|
+
* `PageMode`.
|
|
116
|
+
*
|
|
117
|
+
* A packet is assembled from documents that are already final, and none of
|
|
118
|
+
* those survive a print either, which is what makes the trade acceptable here.
|
|
119
|
+
* A caller who needs any of them should say so rather than merge.
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
/** Thrown when a source cannot be merged, naming which one and why. */
|
|
123
|
+
declare class PdfMergeError extends Error {
|
|
124
|
+
/** Zero-based position of the offending source in the input. */
|
|
125
|
+
readonly source: number;
|
|
126
|
+
constructor(source: number, detail: string);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Concatenate PDFs into one document, keeping every page in the order given.
|
|
130
|
+
*
|
|
131
|
+
* A single source is returned unchanged, so merging a one-part packet costs
|
|
132
|
+
* nothing and produces the bytes the part already had.
|
|
133
|
+
*
|
|
134
|
+
* @throws {PdfEncryptedError} when a source is encrypted.
|
|
135
|
+
* @throws {PdfMergeError} naming the source, when it has no catalog, no pages,
|
|
136
|
+
* or cannot be read at all.
|
|
137
|
+
*/
|
|
138
|
+
declare function mergePdfs(sources: readonly BinaryContent[]): Promise<Uint8Array>;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* A PDF holding some of another's pages.
|
|
142
|
+
*
|
|
143
|
+
* Selection writes a fresh document, not an incremental update: an update
|
|
144
|
+
* keeps the original bytes, so every dropped page, its content and its fields
|
|
145
|
+
* would still be in the file. The new document holds the catalog, a new page
|
|
146
|
+
* tree over the kept pages, and every object those reach. Dropped pages, the
|
|
147
|
+
* widgets that sit only on them, and form fields left with no widget are not
|
|
148
|
+
* carried; a reference to one from what is kept is dropped from a list and
|
|
149
|
+
* becomes `null` anywhere else.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
/** Return a PDF containing the requested one-based pages in source order. */
|
|
153
|
+
declare function selectPdfPages(template: BinaryContent, requestedPages: readonly number[]): Promise<Uint8Array>;
|
|
154
|
+
|
|
155
|
+
interface PdfOverlayBase {
|
|
156
|
+
/** One-based page number. */
|
|
157
|
+
page: number;
|
|
158
|
+
/** Horizontal position in PDF points from the bottom-left corner. */
|
|
159
|
+
x: number;
|
|
160
|
+
/** Vertical position in PDF points from the bottom-left corner. */
|
|
161
|
+
y: number;
|
|
162
|
+
}
|
|
163
|
+
type PdfTextOverlay = PdfOverlayBase & {
|
|
164
|
+
fontSize?: number;
|
|
165
|
+
/**
|
|
166
|
+
* Fit text inside this width, shrinking no smaller than 6 points. Text that
|
|
167
|
+
* still does not fit fails with an overflow error.
|
|
168
|
+
*/
|
|
169
|
+
width?: number;
|
|
170
|
+
/** Vertically center text inside this height. */
|
|
171
|
+
height?: number;
|
|
172
|
+
/** RGB components in the range 0–1. */
|
|
173
|
+
color?: [number, number, number];
|
|
174
|
+
/**
|
|
175
|
+
* A font for this overlay alone, tried before the render's other fonts, so
|
|
176
|
+
* one render can draw text in more than one font (a bold heading, say).
|
|
177
|
+
*/
|
|
178
|
+
font?: PdfFont;
|
|
179
|
+
} & ({
|
|
180
|
+
text: string | number | boolean;
|
|
181
|
+
field?: never;
|
|
182
|
+
} | {
|
|
183
|
+
field: string;
|
|
184
|
+
text?: never;
|
|
185
|
+
});
|
|
186
|
+
type PdfImageOverlay = PdfOverlayBase & {
|
|
187
|
+
image: Uint8Array;
|
|
188
|
+
mediaType: 'image/png' | 'image/jpeg';
|
|
189
|
+
width: number;
|
|
190
|
+
height: number;
|
|
191
|
+
fit?: 'contain' | 'fill';
|
|
192
|
+
};
|
|
193
|
+
type PdfOverlay = PdfTextOverlay | PdfImageOverlay;
|
|
194
|
+
|
|
195
|
+
interface RenderPdfOptions {
|
|
196
|
+
template: BinaryContent;
|
|
197
|
+
form?: Form;
|
|
198
|
+
data: Record<string, unknown>;
|
|
199
|
+
bindings?: Record<string, string>;
|
|
200
|
+
formatter?: Formatter;
|
|
201
|
+
overlays?: PdfOverlay[];
|
|
202
|
+
/**
|
|
203
|
+
* A font supplied at render time. It is tried first for every text value,
|
|
204
|
+
* ahead of the layer's declared font.
|
|
205
|
+
*/
|
|
206
|
+
font?: PdfFont;
|
|
207
|
+
/** The font the artifact's PDF layer declares, tried after `font`. */
|
|
208
|
+
layerFont?: PdfFont;
|
|
209
|
+
/**
|
|
210
|
+
* The presentation the artifact's PDF layer declares, applied over
|
|
211
|
+
* `formatter`. `{ money: { currencyDisplay: 'none' } }` prints amounts
|
|
212
|
+
* without a symbol beside a template's pre-printed one.
|
|
213
|
+
*/
|
|
214
|
+
format?: LayerFormat;
|
|
215
|
+
}
|
|
216
|
+
declare function renderPdf({ template, form, data, bindings, formatter, overlays, font, layerFont, format, }: RenderPdfOptions): Promise<BinaryContent>;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* PDF signature fields: the file structure a digital signature lives in.
|
|
220
|
+
*
|
|
221
|
+
* A signature is an incremental update (ISO 32000-1, 12.8). The update adds a
|
|
222
|
+
* signature dictionary, a signature field whose widget sits on the first page
|
|
223
|
+
* and whose `/V` is that dictionary, and an AcroForm entry with `/SigFlags 3`.
|
|
224
|
+
* The dictionary's `/ByteRange` covers the whole file except the `/Contents`
|
|
225
|
+
* hex string, which holds the signature container.
|
|
226
|
+
*
|
|
227
|
+
* This module writes and reads that structure only. Producing and checking the
|
|
228
|
+
* container (CMS, keys, certificates) is the caller's work: prepare the field,
|
|
229
|
+
* sign the bytes its byte range covers, then embed the container.
|
|
230
|
+
*/
|
|
231
|
+
/** What a new signature dictionary says about the signature. */
|
|
232
|
+
interface PdfSignatureOptions {
|
|
233
|
+
/** Bytes reserved for the signature container. The embedded container may be shorter, never longer. */
|
|
234
|
+
contentsSize: number;
|
|
235
|
+
/** The signing time, written as `/M`. */
|
|
236
|
+
signingTime: Date;
|
|
237
|
+
/** The signer's name, in any script (`/Name`). */
|
|
238
|
+
name?: string;
|
|
239
|
+
/** Why the document was signed (`/Reason`). */
|
|
240
|
+
reason?: string;
|
|
241
|
+
/** Where it was signed (`/Location`). */
|
|
242
|
+
location?: string;
|
|
243
|
+
/** How to reach the signer (`/ContactInfo`). */
|
|
244
|
+
contactInfo?: string;
|
|
245
|
+
}
|
|
246
|
+
/** A PDF with a signature field whose container is still empty. */
|
|
247
|
+
interface PreparedPdfSignature {
|
|
248
|
+
/** The PDF, with `/ByteRange` written and `/Contents` zero-filled. */
|
|
249
|
+
bytes: Uint8Array;
|
|
250
|
+
/** `[0, gapStart, gapEnd, length - gapEnd]`: the two ranges the signature covers. */
|
|
251
|
+
byteRange: [number, number, number, number];
|
|
252
|
+
}
|
|
253
|
+
/** The newest signature in a PDF, read from its signature dictionary. */
|
|
254
|
+
interface PdfSignatureRecord {
|
|
255
|
+
/** The signature container, including any zero padding after it. */
|
|
256
|
+
contents: Uint8Array;
|
|
257
|
+
/** The ranges the signature covers, as the dictionary states them. */
|
|
258
|
+
byteRange: [number, number, number, number];
|
|
259
|
+
/** The bytes `byteRange` covers, concatenated. */
|
|
260
|
+
signedBytes: Uint8Array;
|
|
261
|
+
/**
|
|
262
|
+
* True when the byte range starts at the first byte, ends at the last byte,
|
|
263
|
+
* and leaves out exactly this dictionary's `/Contents` hex string. False when
|
|
264
|
+
* any other byte is unsigned, such as an update appended after signing.
|
|
265
|
+
*/
|
|
266
|
+
coversWholeFile: boolean;
|
|
267
|
+
name?: string;
|
|
268
|
+
reason?: string;
|
|
269
|
+
location?: string;
|
|
270
|
+
contactInfo?: string;
|
|
271
|
+
signingTime?: Date;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* `pdf` with a new, empty signature field added as an incremental update.
|
|
275
|
+
*
|
|
276
|
+
* The field is invisible (a zero-size widget on the first page). Its byte range
|
|
277
|
+
* is final; sign `signedBytes(prepared)` and pass the container to
|
|
278
|
+
* `embedPdfSignature`.
|
|
279
|
+
*/
|
|
280
|
+
declare function preparePdfSignature(pdf: Uint8Array, options: PdfSignatureOptions): Promise<PreparedPdfSignature>;
|
|
281
|
+
/** The bytes a prepared signature covers: what the signature container signs. */
|
|
282
|
+
declare function signedBytes(prepared: PreparedPdfSignature): Uint8Array;
|
|
283
|
+
/** The prepared PDF with `container` written into its `/Contents`. */
|
|
284
|
+
declare function embedPdfSignature(prepared: PreparedPdfSignature, container: Uint8Array): Uint8Array;
|
|
285
|
+
/**
|
|
286
|
+
* The newest signature in `pdf`: the signature dictionary whose byte range
|
|
287
|
+
* reaches furthest into the file. Every value comes from that dictionary, so
|
|
288
|
+
* other objects (an annotation's `/Contents`, a field's `/Name`) never stand in
|
|
289
|
+
* for it. Returns `undefined` when the file holds no signature.
|
|
290
|
+
*/
|
|
291
|
+
declare function readPdfSignature(pdf: Uint8Array): Promise<PdfSignatureRecord | undefined>;
|
|
292
|
+
|
|
293
|
+
interface PdfRendererOptions {
|
|
294
|
+
formatter?: Formatter;
|
|
295
|
+
/**
|
|
296
|
+
* A font supplied at render time, such as a licensed corporate font. It is
|
|
297
|
+
* tried before the font the layer declares.
|
|
298
|
+
*/
|
|
299
|
+
font?: PdfFont;
|
|
300
|
+
}
|
|
301
|
+
type PdfLayer = RendererLayer & {
|
|
302
|
+
type: 'pdf';
|
|
303
|
+
content: Uint8Array;
|
|
304
|
+
};
|
|
305
|
+
declare function pdfRenderer(options?: PdfRendererOptions): AsterdocRenderer<PdfLayer, Uint8Array>;
|
|
306
|
+
|
|
307
|
+
declare const FieldType: {
|
|
308
|
+
readonly SIGNATURE: 0;
|
|
309
|
+
readonly INITIALS: 1;
|
|
310
|
+
};
|
|
311
|
+
type FieldTypeValue = (typeof FieldType)[keyof typeof FieldType];
|
|
312
|
+
declare function encode(signerIndex: number, fieldType: number): string;
|
|
313
|
+
interface DecodedEncoding {
|
|
314
|
+
signerIndex: number;
|
|
315
|
+
fieldType: number;
|
|
316
|
+
}
|
|
317
|
+
interface DecodedEncodingWithPosition extends DecodedEncoding {
|
|
318
|
+
/** Character position in the scanned text where the encoding starts. */
|
|
319
|
+
position: number;
|
|
320
|
+
}
|
|
321
|
+
declare function decodeAll(text: string): DecodedEncodingWithPosition[];
|
|
322
|
+
declare function stripEncoding(text: string): string;
|
|
323
|
+
declare function containsEncoding(text: string): boolean;
|
|
324
|
+
|
|
325
|
+
/** One text-showing run, in content-stream order. */
|
|
326
|
+
interface TextRun {
|
|
327
|
+
/** Decoded Unicode text of the run. */
|
|
328
|
+
text: string;
|
|
329
|
+
/** Device-space x of the run start, in points. */
|
|
330
|
+
x: number;
|
|
331
|
+
/** Device-space y of the run start (bottom-origin), in points. */
|
|
332
|
+
y: number;
|
|
333
|
+
/** Advance width of the run in device space, in points. */
|
|
334
|
+
width: number;
|
|
335
|
+
/** Effective font height in device space, in points. */
|
|
336
|
+
height: number;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** A signature or initials field located in the PDF. */
|
|
340
|
+
interface ExtractedField {
|
|
341
|
+
signerIndex: number;
|
|
342
|
+
fieldType: 'signature' | 'initials';
|
|
343
|
+
/** 1-based page number. */
|
|
344
|
+
page: number;
|
|
345
|
+
/** Points from the left page edge. */
|
|
346
|
+
x: number;
|
|
347
|
+
/** Points from the top page edge. */
|
|
348
|
+
y: number;
|
|
349
|
+
width: number;
|
|
350
|
+
height: number;
|
|
351
|
+
/** Raw bottom-origin y from the PDF. */
|
|
352
|
+
rawY: number;
|
|
353
|
+
pageHeight: number;
|
|
354
|
+
}
|
|
355
|
+
/** A decoded marker whose field type code has no meaning to this reader. */
|
|
356
|
+
interface UnknownMarker {
|
|
357
|
+
/** 1-based page number. */
|
|
358
|
+
page: number;
|
|
359
|
+
signerIndex: number;
|
|
360
|
+
/** The raw field type code (0-15). */
|
|
361
|
+
fieldType: number;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Thrown when a PDF carries markers whose field type is not signature or
|
|
365
|
+
* initials. Such a marker comes from a newer encoder or a damaged text layer;
|
|
366
|
+
* reading it as either known type could put a signer's mark in the wrong box.
|
|
367
|
+
*/
|
|
368
|
+
declare class UnknownMarkerError extends Error {
|
|
369
|
+
readonly markers: UnknownMarker[];
|
|
370
|
+
constructor(markers: UnknownMarker[]);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Extract signature/initials fields from a PDF produced by a converter.
|
|
374
|
+
*
|
|
375
|
+
* @throws {UnknownMarkerError} naming every marker whose field type is not
|
|
376
|
+
* signature or initials.
|
|
377
|
+
*/
|
|
378
|
+
declare function extractFieldsFromPdf(pdf: Uint8Array): Promise<ExtractedField[]>;
|
|
379
|
+
/** Positioned, merged text runs for one page, with its geometry. */
|
|
380
|
+
interface PageTextRuns {
|
|
381
|
+
/** [x0, y0, x1, y1] MediaBox in points. */
|
|
382
|
+
mediaBox: [number, number, number, number];
|
|
383
|
+
runs: TextRun[];
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Merged text runs for every page, in document order. Low-level building
|
|
387
|
+
* block for verification and layout tooling; coordinates are raw PDF user
|
|
388
|
+
* space (bottom-origin y).
|
|
389
|
+
*/
|
|
390
|
+
declare function pageTextRuns(pdf: Uint8Array): Promise<PageTextRuns[]>;
|
|
391
|
+
/** True when any page's text layer contains encoding characters. */
|
|
392
|
+
declare function pdfContainsEncoding(pdf: Uint8Array): Promise<boolean>;
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* A placement query against a converter-produced PDF.
|
|
396
|
+
*
|
|
397
|
+
* - `marker`: find the invisible encoding for a signer index + field type
|
|
398
|
+
* that the render stage injected into the document.
|
|
399
|
+
* - `anchor`: find literal document text. Without `occurrence` the text must
|
|
400
|
+
* appear exactly once; ambiguity is an error, not a guess.
|
|
401
|
+
*/
|
|
402
|
+
type LocateQuery = {
|
|
403
|
+
id: string;
|
|
404
|
+
} & ({
|
|
405
|
+
kind: 'marker';
|
|
406
|
+
signerIndex: number;
|
|
407
|
+
fieldType: FieldTypeValue;
|
|
408
|
+
} | {
|
|
409
|
+
kind: 'anchor';
|
|
410
|
+
text: string;
|
|
411
|
+
occurrence?: number;
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Factory returning a locator object for core's `seal({ locate })` option.
|
|
416
|
+
* Kept as a factory so future variants (imported-PDF tier, hosted tier) share
|
|
417
|
+
* the calling convention.
|
|
418
|
+
*/
|
|
419
|
+
declare function locator(): {
|
|
420
|
+
locate: typeof locate;
|
|
421
|
+
};
|
|
422
|
+
/** Thrown when any query cannot be resolved deterministically. */
|
|
423
|
+
declare class LocateError extends Error {
|
|
424
|
+
readonly failures: {
|
|
425
|
+
id: string;
|
|
426
|
+
reason: 'missing' | 'ambiguous';
|
|
427
|
+
matches?: number;
|
|
428
|
+
}[];
|
|
429
|
+
constructor(message: string, failures: {
|
|
430
|
+
id: string;
|
|
431
|
+
reason: 'missing' | 'ambiguous';
|
|
432
|
+
matches?: number;
|
|
433
|
+
}[]);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Resolve placement queries against a PDF. All queries succeed or the call
|
|
437
|
+
* throws a `LocateError` naming every failed id — partial results are never
|
|
438
|
+
* returned, so a seal pipeline cannot proceed on a silently incomplete map.
|
|
439
|
+
*/
|
|
440
|
+
declare function locate(pdf: Uint8Array, queries: LocateQuery[]): Promise<LocateHit[]>;
|
|
441
|
+
|
|
442
|
+
/** Why a PDF could not be read as the artifact's filled form. */
|
|
443
|
+
type PdfExtractionErrorCode = 'malformed_pdf' | 'no_form_fields' | 'not_matching' | 'no_pdf_layer' | 'layer_required' | 'layer_not_found' | 'not_pdf_layer' | 'unknown_bindings_source';
|
|
444
|
+
/** Extraction refused the input. `code` says which failure case applies. */
|
|
445
|
+
declare class PdfExtractionError extends Error {
|
|
446
|
+
readonly code: PdfExtractionErrorCode;
|
|
447
|
+
constructor(code: PdfExtractionErrorCode, message: string);
|
|
448
|
+
}
|
|
449
|
+
/** What happened to one artifact path the layer's bindings target. */
|
|
450
|
+
type PdfExtractionStatus = 'recovered' | 'empty' | 'not_recoverable' | 'unparseable';
|
|
451
|
+
/** One PDF field that carries a binding target, with the raw value read from it. */
|
|
452
|
+
interface PdfExtractionSource {
|
|
453
|
+
/** Fully qualified AcroForm field name. */
|
|
454
|
+
field: string;
|
|
455
|
+
/** Raw PDF value: the text, the selected option, or a button state name. Absent when the field has none. */
|
|
456
|
+
value?: string;
|
|
457
|
+
}
|
|
458
|
+
/** One entry per artifact path the layer's bindings target. */
|
|
459
|
+
interface PdfExtractionEntry {
|
|
460
|
+
/** The binding target, as written in the layer's bindings. */
|
|
461
|
+
path: string;
|
|
462
|
+
status: PdfExtractionStatus;
|
|
463
|
+
/** Every PDF field that carries this path. */
|
|
464
|
+
sources: PdfExtractionSource[];
|
|
465
|
+
/** Why the value is not recoverable or could not be parsed. */
|
|
466
|
+
reason?: string;
|
|
467
|
+
}
|
|
468
|
+
/** A PDF field that holds a value no binding covers. */
|
|
469
|
+
interface PdfUnboundField {
|
|
470
|
+
field: string;
|
|
471
|
+
type: 'text' | 'checkbox' | 'radio' | 'dropdown';
|
|
472
|
+
value: string;
|
|
473
|
+
}
|
|
474
|
+
interface PdfExtractionReport {
|
|
475
|
+
entries: PdfExtractionEntry[];
|
|
476
|
+
unbound: PdfUnboundField[];
|
|
477
|
+
}
|
|
478
|
+
/** Partial artifact data in the fill payload shape. It holds only values recovered exactly. */
|
|
479
|
+
interface PdfExtractedData {
|
|
480
|
+
fields: Record<string, unknown>;
|
|
481
|
+
parties?: Record<string, unknown>;
|
|
482
|
+
annexes?: Record<string, unknown>;
|
|
483
|
+
}
|
|
484
|
+
interface PdfExtraction {
|
|
485
|
+
data: PdfExtractedData;
|
|
486
|
+
report: PdfExtractionReport;
|
|
487
|
+
}
|
|
488
|
+
interface ExtractPdfDataOptions {
|
|
489
|
+
/** The filled PDF. It is read, never modified. */
|
|
490
|
+
pdf: BinaryContent;
|
|
491
|
+
/** The artifact whose layer produced the PDF. */
|
|
492
|
+
form: Form;
|
|
493
|
+
/** The PDF layer's bindings: AcroForm field name to artifact path. */
|
|
494
|
+
bindings: Record<string, string>;
|
|
495
|
+
/** The formatter the PDF was filled with. Defaults to the default formatter. */
|
|
496
|
+
formatter?: Formatter;
|
|
497
|
+
/**
|
|
498
|
+
* The presentation the PDF layer declares, applied over `formatter` as it
|
|
499
|
+
* was when filling. With `money.currencyDisplay: 'none'`, an amount is read
|
|
500
|
+
* in the currency its field declares.
|
|
501
|
+
*/
|
|
502
|
+
format?: LayerFormat;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Read a filled PDF back into artifact data through the layer's bindings.
|
|
506
|
+
*
|
|
507
|
+
* Only exact reversals are returned: direct fields, split fields, checkbox and
|
|
508
|
+
* radio maps. A joined binding's raw text is reported as not recoverable, and
|
|
509
|
+
* text that does not parse into the field's type is reported with its raw
|
|
510
|
+
* value. Nothing is validated here; pass the data to the normal fill path.
|
|
511
|
+
*
|
|
512
|
+
* @throws {PdfEncryptedError} when the PDF is encrypted.
|
|
513
|
+
* @throws {PdfExtractionError} when the PDF or the layer choice cannot be read.
|
|
514
|
+
*/
|
|
515
|
+
declare function extractPdfData({ pdf, form, bindings, formatter: filledWith, format }: ExtractPdfDataOptions): Promise<PdfExtraction>;
|
|
516
|
+
/** A PDF layer as the artifact declares it. */
|
|
517
|
+
interface PdfLayerSpec {
|
|
518
|
+
mimeType?: string;
|
|
519
|
+
bindings?: Record<string, string>;
|
|
520
|
+
bindingsFrom?: string;
|
|
521
|
+
format?: LayerFormat;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Choose the PDF layer to read against: the named one, or the only PDF layer.
|
|
525
|
+
* Returns its key, resolved bindings, and declared format.
|
|
526
|
+
*/
|
|
527
|
+
declare function selectPdfExtractionLayer(layers: Record<string, PdfLayerSpec> | undefined, requested?: string): {
|
|
528
|
+
key: string;
|
|
529
|
+
bindings: Record<string, string>;
|
|
530
|
+
format?: LayerFormat;
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Authoring check that the values an artifact can bind to a PDF form's text
|
|
535
|
+
* fields fit their boxes.
|
|
536
|
+
*
|
|
537
|
+
* Filling fails when a value cannot fit its box at {@link MIN_FONT_SIZE}, or
|
|
538
|
+
* has more characters than a comb field has boxes. This check finds those
|
|
539
|
+
* failures before any data exists: for each binding to an AcroForm text field
|
|
540
|
+
* it builds values the bound artifact field accepts and lays them out with the
|
|
541
|
+
* same code filling uses.
|
|
542
|
+
*
|
|
543
|
+
* A text, email, uuid, or uri field is checked at its length bound: `maxLength`
|
|
544
|
+
* characters, or the length its `pattern` bounds (a uuid without a pattern
|
|
545
|
+
* takes its 36-character canonical form). Two values of that length are laid out:
|
|
546
|
+
* - a typical value: each open position holds the next character of
|
|
547
|
+
* {@link TYPICAL_TEXT}; a position the pattern constrains holds the allowed
|
|
548
|
+
* character nearest the allowed characters' mean width. When it cannot fit,
|
|
549
|
+
* ordinary answers fail to fill: an error.
|
|
550
|
+
* - the widest value: each position holds the widest character it may hold
|
|
551
|
+
* (the widest Latin letter or digit when open, `W` in Helvetica). When only
|
|
552
|
+
* this value cannot fit, unusual answers fail to fill: a warning.
|
|
553
|
+
*
|
|
554
|
+
* A split binding (`path:2`) takes the matching hyphen-separated part of the
|
|
555
|
+
* pattern, or the whole value's bound when the pattern does not fix the parts.
|
|
556
|
+
* Enum and multiselect fields write known option values, so they are checked
|
|
557
|
+
* exactly: the widest option value, or the widest `max` values (all of them
|
|
558
|
+
* without `max`) joined with ", ". A comma-joined binding joins each path's
|
|
559
|
+
* value with ", ". More characters than a comb field has boxes is an error.
|
|
560
|
+
*
|
|
561
|
+
* The font is the one filling would choose: the layer's declared font, then
|
|
562
|
+
* the form's own font for the field, then Helvetica. A font supplied only at
|
|
563
|
+
* render time is not known here.
|
|
564
|
+
*/
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* The text a typical value is made of: an English pangram with its word spaces,
|
|
568
|
+
* repeated. It holds every lowercase letter, one capital, and spaces at about
|
|
569
|
+
* the rate English prose has them, so its mean advance (456 units in Helvetica)
|
|
570
|
+
* sits just above that of letter-frequency-weighted English text (441).
|
|
571
|
+
*/
|
|
572
|
+
declare const TYPICAL_TEXT = "The quick brown fox jumps over the lazy dog ";
|
|
573
|
+
/** Why a binding may not fit its PDF text field. */
|
|
574
|
+
type PdfBindingFitReason = 'overflow' | 'comb-length' | 'unbounded';
|
|
575
|
+
/** One binding whose values may not fit the PDF text field it fills. */
|
|
576
|
+
interface PdfBindingFitIssue {
|
|
577
|
+
/** Fully qualified name of the PDF form field. */
|
|
578
|
+
field: string;
|
|
579
|
+
/** The binding as the layer declares it. */
|
|
580
|
+
binding: string;
|
|
581
|
+
/** The artifact paths the binding reads, such as `fields.amountSource`. */
|
|
582
|
+
paths: string[];
|
|
583
|
+
/**
|
|
584
|
+
* `error` when a typical value, an option value, or a value's length cannot
|
|
585
|
+
* be filled; `warning` when only the widest value overflows, or nothing
|
|
586
|
+
* bounds the value.
|
|
587
|
+
*/
|
|
588
|
+
severity: 'error' | 'warning';
|
|
589
|
+
reason: PdfBindingFitReason;
|
|
590
|
+
/** Which value failed: a typical one, or the widest. Absent for `unbounded`. */
|
|
591
|
+
value?: 'typical' | 'widest';
|
|
592
|
+
/** For `overflow`, the minimum font size in points; for `comb-length`, the number of comb boxes. */
|
|
593
|
+
limit?: number;
|
|
594
|
+
/** Characters in the widest value checked. */
|
|
595
|
+
length?: number;
|
|
596
|
+
message: string;
|
|
597
|
+
}
|
|
598
|
+
/** Options for {@link checkPdfBindingFit}. */
|
|
599
|
+
interface CheckPdfBindingFitOptions {
|
|
600
|
+
/** The PDF layer's bytes. */
|
|
601
|
+
template: Uint8Array;
|
|
602
|
+
form: Form;
|
|
603
|
+
/** The layer's bindings; without them, fields fill the PDF fields of the same name. */
|
|
604
|
+
bindings?: Record<string, string>;
|
|
605
|
+
/** The font the layer declares. */
|
|
606
|
+
layerFont?: PdfFont;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Check that every value the artifact accepts for a binding to a PDF text
|
|
610
|
+
* field can be filled: that it fits the box at the minimum font size, and
|
|
611
|
+
* that it has no more characters than a comb field has boxes. A text field
|
|
612
|
+
* with nothing bounding its length is a warning. A PDF without an AcroForm
|
|
613
|
+
* has nothing to check.
|
|
614
|
+
*
|
|
615
|
+
* @throws {PdfFontError} when the layer's font cannot be read.
|
|
616
|
+
* @throws {PdfBindingSyntaxError} when a binding cannot be parsed.
|
|
617
|
+
*/
|
|
618
|
+
declare function checkPdfBindingFit({ template, form, bindings, layerFont }: CheckPdfBindingFitOptions): Promise<PdfBindingFitIssue[]>;
|
|
619
|
+
|
|
620
|
+
export { type CheckPdfBindingFitOptions, type DecodedEncoding, type DecodedEncodingWithPosition, type ExtractPdfDataOptions, type ExtractedField, FieldType, type FieldTypeValue, type InspectOptions, LocateError, type LocateQuery, MIN_FONT_SIZE, type PageTextRuns, type PdfBindingFitIssue, type PdfBindingFitReason, PdfEncryptedError, type PdfExtractedData, type PdfExtraction, type PdfExtractionEntry, PdfExtractionError, type PdfExtractionErrorCode, type PdfExtractionReport, type PdfExtractionSource, type PdfExtractionStatus, type PdfFieldFillDetail, PdfFieldFillError, type PdfFieldFillReason, type PdfFieldInfo, type PdfFieldType, PdfFont, type PdfImageOverlay, type PdfInfo, PdfMergeError, type PdfOverlay, type PdfPageInfo, type PdfRendererOptions, type PdfSignatureOptions, type PdfSignatureRecord, type PdfTextOverlay, type PdfUnboundField, type PreparedPdfSignature, type RenderPdfOptions, TYPICAL_TEXT, type TextRun, type UnknownMarker, UnknownMarkerError, checkPdfBindingFit, containsEncoding, decodeAll, embedPdfSignature, encode, extractFieldsFromPdf, extractPdfData, flattenPdf, inspectAcroFormFields, inspectPdf, locate, locator, mergePdfs, pageTextRuns, pdfContainsEncoding, pdfRenderer, preparePdfSignature, readPdfSignature, renderPdf, selectPdfExtractionLayer, selectPdfPages, signedBytes, stripEncoding };
|