@embedpdf/engine-core 3.0.0-next.14 → 3.0.0-next.15
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/AnnotationList-CkijRHet.d.cts +27163 -0
- package/dist/AnnotationList-CkijRHet.d.ts +27163 -0
- package/dist/Change-CKoxfTNY.js +889 -0
- package/dist/Change-CKoxfTNY.js.map +1 -0
- package/dist/Change-CjImsrN0.cjs +1020 -0
- package/dist/Change-CjImsrN0.cjs.map +1 -0
- package/dist/DocumentRenderService-BfFdFSwI.cjs +120 -0
- package/dist/DocumentRenderService-BfFdFSwI.cjs.map +1 -0
- package/dist/DocumentRenderService-DV3J9lMz.js +85 -0
- package/dist/DocumentRenderService-DV3J9lMz.js.map +1 -0
- package/dist/{DocumentSecurityService-Ca6EK3-3.d.ts → DocumentSecurityService-CU1M6Q7m.d.ts} +100 -112
- package/dist/{DocumentSecurityService-CIx1MT0T.d.cts → DocumentSecurityService-e6vp2de8.d.cts} +100 -112
- package/dist/LocalDocumentHandle-D02FMm-Z.cjs +53 -0
- package/dist/LocalDocumentHandle-D02FMm-Z.cjs.map +1 -0
- package/dist/LocalDocumentHandle-DAPdaOt_.js +30 -0
- package/dist/LocalDocumentHandle-DAPdaOt_.js.map +1 -0
- package/dist/LocalEngine-DFoBm4B3.d.cts +1565 -0
- package/dist/LocalEngine-DPriFujS.d.ts +1565 -0
- package/dist/PageInsertBlankInput-CXHAM7l6.cjs +17 -0
- package/dist/PageInsertBlankInput-CXHAM7l6.cjs.map +1 -0
- package/dist/PageInsertBlankInput-DhVYVJ_S.js +12 -0
- package/dist/PageInsertBlankInput-DhVYVJ_S.js.map +1 -0
- package/dist/authority-B3BklsB4.js +2239 -0
- package/dist/authority-B3BklsB4.js.map +1 -0
- package/dist/{viewport-BWeNHZmb.cjs → authority-DLMNR7ff.cjs} +820 -1647
- package/dist/authority-DLMNR7ff.cjs.map +1 -0
- package/dist/builders-CNj0POeY.js +161 -0
- package/dist/builders-CNj0POeY.js.map +1 -0
- package/dist/builders-Cgdp_YCn.cjs +184 -0
- package/dist/builders-Cgdp_YCn.cjs.map +1 -0
- package/dist/calibrate-7T3fnP8-.js +2404 -0
- package/dist/calibrate-7T3fnP8-.js.map +1 -0
- package/dist/calibrate-DJBXnhLE.cjs +2919 -0
- package/dist/calibrate-DJBXnhLE.cjs.map +1 -0
- package/dist/charmap-Cprti1ta.js +239 -0
- package/dist/charmap-Cprti1ta.js.map +1 -0
- package/dist/charmap-aYlefQP9.cjs +304 -0
- package/dist/charmap-aYlefQP9.cjs.map +1 -0
- package/dist/conformance.cjs +16466 -5247
- package/dist/conformance.cjs.map +1 -1
- package/dist/conformance.d.cts +924 -165
- package/dist/conformance.d.ts +924 -165
- package/dist/conformance.js +16429 -5252
- package/dist/conformance.js.map +1 -1
- package/dist/format-Bp3QFSH1.cjs +574 -0
- package/dist/format-Bp3QFSH1.cjs.map +1 -0
- package/dist/format-Dgg428Kb.js +461 -0
- package/dist/format-Dgg428Kb.js.map +1 -0
- package/dist/index.cjs +323 -116
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -5
- package/dist/pageRefs-B3ur7Ckm.cjs +51 -0
- package/dist/pageRefs-B3ur7Ckm.cjs.map +1 -0
- package/dist/pageRefs-DkbuxSCV.js +40 -0
- package/dist/pageRefs-DkbuxSCV.js.map +1 -0
- package/dist/public.cjs +57 -0
- package/dist/public.d.cts +5 -0
- package/dist/public.d.ts +5 -0
- package/dist/public.js +9 -0
- package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs +3646 -0
- package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs.map +1 -0
- package/dist/resolveAnnotationDraft-CUpf0SMh.js +3167 -0
- package/dist/resolveAnnotationDraft-CUpf0SMh.js.map +1 -0
- package/dist/{resolver-inAVzsWt.js → resolver-CzxmD9Ck.js} +294 -144
- package/dist/resolver-CzxmD9Ck.js.map +1 -0
- package/dist/{resolver-CYVNV4hn.cjs → resolver-D2OCtE8F.cjs} +347 -143
- package/dist/resolver-D2OCtE8F.cjs.map +1 -0
- package/dist/runtime-Cl0v56mm.d.ts +2032 -0
- package/dist/runtime-p1WDzDo4.d.cts +2032 -0
- package/dist/runtime.cjs +726 -297
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +5 -1372
- package/dist/runtime.d.ts +5 -1372
- package/dist/runtime.js +396 -179
- package/dist/runtime.js.map +1 -1
- package/dist/schema-C-gU4vj7.cjs +3034 -0
- package/dist/schema-C-gU4vj7.cjs.map +1 -0
- package/dist/schema-DzlUNk38.js +2081 -0
- package/dist/schema-DzlUNk38.js.map +1 -0
- package/dist/schemas-Berf1swF.cjs +2481 -0
- package/dist/schemas-Berf1swF.cjs.map +1 -0
- package/dist/schemas-D6xOGjqg.js +1654 -0
- package/dist/schemas-D6xOGjqg.js.map +1 -0
- package/dist/subtype-CG4WpIRj.js +129 -0
- package/dist/subtype-CG4WpIRj.js.map +1 -0
- package/dist/subtype-aDt5TFmK.cjs +158 -0
- package/dist/subtype-aDt5TFmK.cjs.map +1 -0
- package/dist/validation.cjs +578 -0
- package/dist/validation.cjs.map +1 -0
- package/dist/validation.d.cts +174 -0
- package/dist/validation.d.ts +174 -0
- package/dist/validation.js +571 -0
- package/dist/validation.js.map +1 -0
- package/dist/value-BFS1R8ek.cjs +435 -0
- package/dist/value-BFS1R8ek.cjs.map +1 -0
- package/dist/value-Dhc8eYcx.js +340 -0
- package/dist/value-Dhc8eYcx.js.map +1 -0
- package/dist/viewport-BJW13EGZ.js +540 -0
- package/dist/viewport-BJW13EGZ.js.map +1 -0
- package/dist/viewport-DlL5Bxbg.cjs +671 -0
- package/dist/viewport-DlL5Bxbg.cjs.map +1 -0
- package/dist/wire.cjs +1051 -397
- package/dist/wire.cjs.map +1 -1
- package/dist/wire.d.cts +12403 -790
- package/dist/wire.d.ts +12403 -790
- package/dist/wire.js +821 -242
- package/dist/wire.js.map +1 -1
- package/package.json +10 -1
- package/dist/AbortError-DwuHPK_I.js +0 -27
- package/dist/AbortError-DwuHPK_I.js.map +0 -1
- package/dist/AbortError-P0RU0Mgg.cjs +0 -38
- package/dist/AbortError-P0RU0Mgg.cjs.map +0 -1
- package/dist/AnnotationListSnapshot-D9R5n2Kf.d.cts +0 -7101
- package/dist/AnnotationListSnapshot-D9R5n2Kf.d.ts +0 -7101
- package/dist/Engine-EWWHhEIi.d.ts +0 -1277
- package/dist/Engine-FNaAEjfb.d.cts +0 -1277
- package/dist/derive-BbsDk_Kz.cjs +0 -880
- package/dist/derive-BbsDk_Kz.cjs.map +0 -1
- package/dist/derive-DAFJolWu.js +0 -647
- package/dist/derive-DAFJolWu.js.map +0 -1
- package/dist/format-Bbphf4zR.js +0 -435
- package/dist/format-Bbphf4zR.js.map +0 -1
- package/dist/format-D_epWlob.cjs +0 -518
- package/dist/format-D_epWlob.cjs.map +0 -1
- package/dist/resolver-CYVNV4hn.cjs.map +0 -1
- package/dist/resolver-inAVzsWt.js.map +0 -1
- package/dist/schemas-CFQGvWiu.js +0 -3243
- package/dist/schemas-CFQGvWiu.js.map +0 -1
- package/dist/schemas-D0g6tKa9.cjs +0 -4694
- package/dist/schemas-D0g6tKa9.cjs.map +0 -1
- package/dist/viewport-BWeNHZmb.cjs.map +0 -1
- package/dist/viewport-CvMcadfQ.js +0 -3072
- package/dist/viewport-CvMcadfQ.js.map +0 -1
package/dist/conformance.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { E_ as Identity, Ep as CharMapAnchor, Jg as PdfRect, Nd as AnnotationResources, Ng as PageBox, Pg as PagePoint, Wm as PageTabOrder, Yg as PdfRotation, _t as LineDraft, _v as DocumentMetadata, bs as AnnotationDraft, dn as HighlightDraft, nt as InkDraft, t as AnnotationList } from "./AnnotationList-CkijRHet.cjs";
|
|
2
|
+
import { _ as Engine, t as LocalEngine, y as DocumentHandle } from "./LocalEngine-DFoBm4B3.cjs";
|
|
3
3
|
//#region src/conformance/runMetadataConformance.d.ts
|
|
4
4
|
interface ConformanceTestRunner {
|
|
5
5
|
describe(name: string, fn: () => void): void;
|
|
@@ -90,10 +90,10 @@ interface AnnotationReadConformanceFixture extends ConformanceFixture {
|
|
|
90
90
|
/** At least this many `'caret'` annotations on the page. Defaults to 0. */
|
|
91
91
|
minCaretCount?: number;
|
|
92
92
|
/**
|
|
93
|
-
* `true` if the fixture has at least one
|
|
94
|
-
* object). Drives the
|
|
93
|
+
* `true` if the fixture page has at least one annotation born inline (a
|
|
94
|
+
* dictionary in `/Annots`, no object number). Drives the `baseIndex` tests.
|
|
95
95
|
*/
|
|
96
|
-
|
|
96
|
+
expectsInlineAnnotation: boolean;
|
|
97
97
|
}
|
|
98
98
|
interface AnnotationConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
99
99
|
fixture: AnnotationReadConformanceFixture;
|
|
@@ -107,7 +107,7 @@ interface ActionsConformanceFixtures {
|
|
|
107
107
|
annotation: ConformanceFixture;
|
|
108
108
|
field: ConformanceFixture;
|
|
109
109
|
/** `action_payloads.pdf` — every executable payload shape on one page of
|
|
110
|
-
* /NM-keyed links.
|
|
110
|
+
* /NM-keyed links. Required on both flavours: payload parity is a gate. */
|
|
111
111
|
payloads: ConformanceFixture;
|
|
112
112
|
/** `open_action_dest.pdf` — a destination-form catalog `/OpenAction`. */
|
|
113
113
|
openDestination: ConformanceFixture;
|
|
@@ -135,46 +135,37 @@ declare function runActionsConformance(runner: ConformanceTestRunner, opts: Acti
|
|
|
135
135
|
interface AnnotationMutationConformanceFixture extends ConformanceFixture {
|
|
136
136
|
/** PDF object number of the page used by the mutation tests. */
|
|
137
137
|
pageObjectNumber: number;
|
|
138
|
-
/**
|
|
139
|
-
|
|
138
|
+
/** The page has at least one annotation born inline (a dictionary in `/Annots`, no object number). */
|
|
139
|
+
expectsInlineAnnotation: boolean;
|
|
140
140
|
/**
|
|
141
|
-
* QuadPoints to use for the create() smoke test
|
|
142
|
-
*
|
|
143
|
-
*
|
|
141
|
+
* QuadPoints to use for the create() smoke test, in page space; pick a
|
|
142
|
+
* small rectangle that fits anywhere on the fixture page so we don't
|
|
143
|
+
* flake on different page sizes.
|
|
144
144
|
*/
|
|
145
145
|
createQuad?: HighlightDraft['quadPoints'];
|
|
146
146
|
/**
|
|
147
|
-
*
|
|
147
|
+
* The box to use for the shape (circle/square) create tests, in page
|
|
148
148
|
* space; pick a small box that fits anywhere on the fixture page.
|
|
149
149
|
*/
|
|
150
|
-
createShapeRect?:
|
|
150
|
+
createShapeRect?: PageBox;
|
|
151
151
|
/**
|
|
152
|
-
* `/Vertices` to use for the polygon/polyline create tests
|
|
153
|
-
* space; must fit inside `createShapeRect
|
|
154
|
-
* the appearance into). Defaults to a small triangle.
|
|
152
|
+
* `/Vertices` to use for the polygon/polyline create tests, in page
|
|
153
|
+
* space; must fit inside `createShapeRect`. Defaults to a small triangle.
|
|
155
154
|
*/
|
|
156
|
-
createVertices?:
|
|
155
|
+
createVertices?: PagePoint[];
|
|
157
156
|
/**
|
|
158
|
-
* `/L` endpoints to use for the line create test
|
|
159
|
-
*
|
|
157
|
+
* `/L` endpoints to use for the line create test, in page space; must fit
|
|
158
|
+
* inside `createShapeRect`. Defaults to the rect's diagonal.
|
|
160
159
|
*/
|
|
161
|
-
createLinePoints?:
|
|
160
|
+
createLinePoints?: LineDraft['linePoints'];
|
|
162
161
|
/**
|
|
163
|
-
* `/InkList` strokes to use for the ink create test
|
|
162
|
+
* `/InkList` strokes to use for the ink create test, in page space; must
|
|
164
163
|
* fit inside `createShapeRect`. Defaults to a single short stroke.
|
|
165
164
|
*/
|
|
166
|
-
createInkList?:
|
|
165
|
+
createInkList?: InkDraft['inkList'];
|
|
167
166
|
}
|
|
168
167
|
interface AnnotationMutationConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
169
168
|
fixture: AnnotationMutationConformanceFixture;
|
|
170
|
-
/**
|
|
171
|
-
* `true` for engines that expose the raw RGBA appearance rasters
|
|
172
|
-
* (`renderAppearances`). When set, the shape-create test additionally
|
|
173
|
-
* asserts that creating a shape produces a baked `/AP` the appearance
|
|
174
|
-
* reader can rasterize. The cloud engine ships encoded images instead
|
|
175
|
-
* and leaves this `false`.
|
|
176
|
-
*/
|
|
177
|
-
supportsAppearanceRasters?: boolean;
|
|
178
169
|
}
|
|
179
170
|
/**
|
|
180
171
|
* Mutation conformance suite. Mirrors the read suite: tests are written
|
|
@@ -183,22 +174,220 @@ interface AnnotationMutationConformanceOptions extends Omit<ConformanceOptions,
|
|
|
183
174
|
* @cloudpdf/server) implementations must pass identically.
|
|
184
175
|
*
|
|
185
176
|
* The locked rules being verified here:
|
|
186
|
-
* - `create` is append-only:
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* - Opportunistic /NM stamp upgrades a weak annotation's ref to
|
|
192
|
-
* `kind: 'nm'` on update; an already-durable annotation's /NM is
|
|
193
|
-
* NEVER touched.
|
|
194
|
-
* - `delete` and `move` are the only index-shifting ops. They bump
|
|
195
|
-
* the per-page revision and, on a page that had weak refs before
|
|
196
|
-
* the mutation, surface `shouldRefetch: 'weakRefsInvalidated'`.
|
|
177
|
+
* - `create` is append-only: the new annotation paints on top of the
|
|
178
|
+
* page's others, and none of them moves.
|
|
179
|
+
* - Every annotation keeps its name through every write: an object
|
|
180
|
+
* number, or the `baseIndex` of one born inline in the file. No write
|
|
181
|
+
* stamps an /NM to name one.
|
|
197
182
|
* - Abort propagates as `AbortError` even before the worker
|
|
198
183
|
* responds.
|
|
199
184
|
*/
|
|
200
185
|
declare function runAnnotationMutationConformance(runner: ConformanceTestRunner, opts: AnnotationMutationConformanceOptions): void;
|
|
201
186
|
//#endregion
|
|
187
|
+
//#region src/conformance/runAnnotationAttributionConformance.d.ts
|
|
188
|
+
/** Who a session is and what it may do: open-time options locally, token claims on the cloud. */
|
|
189
|
+
interface AttributionSession {
|
|
190
|
+
readonly scope: ReadonlyArray<string>;
|
|
191
|
+
readonly identity: Identity;
|
|
192
|
+
}
|
|
193
|
+
interface AnnotationAttributionConformanceOptions {
|
|
194
|
+
label: string;
|
|
195
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
196
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
197
|
+
/**
|
|
198
|
+
* Open the authoring document, a document with annotations another tool
|
|
199
|
+
* wrote, as `session`. With `from`, the new session continues that open
|
|
200
|
+
* session's document and sees what it wrote (locally its downloaded bytes,
|
|
201
|
+
* on the cloud the same layer); the suite closes `from` afterwards.
|
|
202
|
+
*/
|
|
203
|
+
openAs: (engine: Engine, session: AttributionSession, from?: DocumentHandle) => Promise<DocumentHandle>;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Attribution on both engines with the same identities:
|
|
207
|
+
* `create` stamps it from the session and ignores what the data says,
|
|
208
|
+
* `update` stamps only `modifiedAt` and `modifiedBy`, and a `groupId` other than
|
|
209
|
+
* the session's own passes the set-group check or is refused. The session's
|
|
210
|
+
* whole identity reaches `doc.security.identity`; only the name and the ids
|
|
211
|
+
* reach the annotation.
|
|
212
|
+
*/
|
|
213
|
+
declare function runAnnotationAttributionConformance(runner: ConformanceTestRunner, opts: AnnotationAttributionConformanceOptions): void;
|
|
214
|
+
//#endregion
|
|
215
|
+
//#region src/conformance/runAnnotationResourceConformance.d.ts
|
|
216
|
+
/**
|
|
217
|
+
* The documents the suite opens, each a fresh copy:
|
|
218
|
+
*
|
|
219
|
+
* - `authoring`: any document; stamps are created on its first page.
|
|
220
|
+
* - `acrobat-stamps`: `stamp-opacity-acrobat.pdf`
|
|
221
|
+
* (`packages/engine/main/test/fixtures`): two stamps Acrobat saved at about
|
|
222
|
+
* 30% opacity, each appearance `/R0 gs /MWFOForm Do` with /R0 repeating the
|
|
223
|
+
* stamp's /CA.
|
|
224
|
+
* - `acrobat-rewrapped`: `stamp-rewrapped-acrobat.pdf`, stamps as EmbedPDF
|
|
225
|
+
* writes them after other tools edited them: `rewrapped-a`, turned 30
|
|
226
|
+
* degrees and set to 60% in Acrobat, under Acrobat's layer and four forms
|
|
227
|
+
* that only draw our wrapper; `rewrapped-b`, set to 100% in Acrobat, under
|
|
228
|
+
* one such form; `rewrapped-c`, our 35% layer with /CA dropped, 300 x 120.
|
|
229
|
+
* Each draws a 200 x 100 drawing, opaque where it paints.
|
|
230
|
+
* - `acrobat-roundtrip-60`, `acrobat-roundtrip-100`:
|
|
231
|
+
* `stamp-roundtrip-acrobat-{60,100}.pdf`, an "Approved" stamp made in the
|
|
232
|
+
* viewer, turned and set to 40%, then set to 60% and to 100% in Acrobat
|
|
233
|
+
* 26.2. Acrobat moves the form around our wrapper by 0.0008 pt, its box a
|
|
234
|
+
* fraction off the origin in its own arithmetic.
|
|
235
|
+
*/
|
|
236
|
+
type AnnotationResourceFixture = 'authoring' | 'acrobat-stamps' | 'acrobat-rewrapped' | 'acrobat-roundtrip-60' | 'acrobat-roundtrip-100';
|
|
237
|
+
interface AnnotationResourceConformanceOptions {
|
|
238
|
+
label: string;
|
|
239
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
240
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
241
|
+
/** Open a fresh copy of a fixture, with `doc.download` among its scopes. */
|
|
242
|
+
open: (engine: Engine, fixture: AnnotationResourceFixture) => Promise<DocumentHandle>;
|
|
243
|
+
/** Open a fresh copy of a fixture with `scope` only: the import's rights tests run with it. */
|
|
244
|
+
openScoped?: (engine: Engine, fixture: AnnotationResourceFixture, scope: readonly string[]) => Promise<DocumentHandle>;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Resources beside an annotation's data, on both engines: `downloadResource`
|
|
248
|
+
* returns what `create(data, resources)` needs to make the same annotation
|
|
249
|
+
* again. A stamp's appearance is its drawing without the fit, rotation and
|
|
250
|
+
* opacity its data describes; a stamp another tool made is drawn as shown,
|
|
251
|
+
* in its own box, without a layer that only repeats its /CA. Stamps with
|
|
252
|
+
* the same artwork place one drawing. The opacity is painted once:
|
|
253
|
+
* in a copy, after a resize, and after a change.
|
|
254
|
+
*/
|
|
255
|
+
declare function runAnnotationResourceConformance(runner: ConformanceTestRunner, opts: AnnotationResourceConformanceOptions): void;
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/conformance/runAnnotationExportConformance.d.ts
|
|
258
|
+
/**
|
|
259
|
+
* `doc.annotations.export` on both engines: the annotations as a raw read
|
|
260
|
+
* returns them, each resource once under its hash, the same bytes
|
|
261
|
+
* `downloadResource` returns, and a selection with what it points at and, by
|
|
262
|
+
* default, its threads.
|
|
263
|
+
*/
|
|
264
|
+
declare function runAnnotationExportConformance(runner: ConformanceTestRunner, opts: AnnotationResourceConformanceOptions): void;
|
|
265
|
+
//#endregion
|
|
266
|
+
//#region src/conformance/runAnnotationImportConformance.d.ts
|
|
267
|
+
/**
|
|
268
|
+
* `doc.annotations.import` on both engines, in `stamp` mode: a bundle comes
|
|
269
|
+
* back as the export had it, one fact per annotation as one transaction,
|
|
270
|
+
* what can't be carried left out and reported, pages mapped, and a refusal
|
|
271
|
+
* before anything is written. An import is a change: undone and redone with
|
|
272
|
+
* `doc.apply({ undoOf })`, answered again on a retry, and a restoring
|
|
273
|
+
* import's undo takes the import's rights.
|
|
274
|
+
*/
|
|
275
|
+
declare function runAnnotationImportConformance(runner: ConformanceTestRunner, opts: AnnotationResourceConformanceOptions): void;
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/conformance/runAnnotationTransferConformance.d.ts
|
|
278
|
+
interface AnnotationTransferConformanceOptions {
|
|
279
|
+
label: string;
|
|
280
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
281
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
282
|
+
/**
|
|
283
|
+
* The documents to round-trip. `'authoring'` is a document without
|
|
284
|
+
* annotations, which the suite fills with one annotation of every kind a
|
|
285
|
+
* create makes, two stamps sharing a drawing, a named comment with its
|
|
286
|
+
* popup and a reply, and a link.
|
|
287
|
+
*/
|
|
288
|
+
fixtures: readonly string[];
|
|
289
|
+
/** Open a fresh copy of a fixture, with every scope, `doc.annotate.import` included. */
|
|
290
|
+
open: (engine: Engine, fixture: string) => Promise<DocumentHandle>;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Check annotation transfer over every fixture on both engines. The source
|
|
294
|
+
* bundle is imported into a copy without annotations, then exported again:
|
|
295
|
+
*
|
|
296
|
+
* - The normalized exports agree after unsupported fields are dropped, and
|
|
297
|
+
* every resource has the same bytes under the same id. A copy is drawn from
|
|
298
|
+
* its data, as Acrobat's FDF and XFDF carry it: only a stamp carries its
|
|
299
|
+
* drawing. So where the data is points, the box is the frame of our
|
|
300
|
+
* drawing, which holds the points, and an icon's box is our icon at the
|
|
301
|
+
* same anchor;
|
|
302
|
+
* - Restored attribution is the source's, while stamped attribution is
|
|
303
|
+
* the session's;
|
|
304
|
+
* - Every page keeps the source bundle's annotation order;
|
|
305
|
+
* - Replies, popups, their parents and link destinations point at the copies;
|
|
306
|
+
* - A stamp draws as its source, and in our own file every kind does,
|
|
307
|
+
* an edge moved by a fraction of a pixel aside (Acrobat moves a stamp's
|
|
308
|
+
* form by a fraction of a point, which the drawing leaves out);
|
|
309
|
+
* - A second import names nothing twice and adds no drawing already present.
|
|
310
|
+
* Export golden files and forced-failure tests cover the remaining cases.
|
|
311
|
+
*/
|
|
312
|
+
declare function runAnnotationTransferConformance(runner: ConformanceTestRunner, opts: AnnotationTransferConformanceOptions): void;
|
|
313
|
+
//#endregion
|
|
314
|
+
//#region src/conformance/creatables.d.ts
|
|
315
|
+
/** A create's two arguments. */
|
|
316
|
+
interface Creatable {
|
|
317
|
+
data: AnnotationDraft;
|
|
318
|
+
resources?: AnnotationResources;
|
|
319
|
+
}
|
|
320
|
+
/** A note's or a file's icon at its usual 20 × 20, by its top-left corner. */
|
|
321
|
+
declare function iconRect(x: number, y: number): PageBox;
|
|
322
|
+
/** One create for every kind the engine can create, inside a box near the page's top-left. */
|
|
323
|
+
declare function creatables(): Creatable[];
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/conformance/runDateConformance.d.ts
|
|
326
|
+
interface DateConformanceOptions {
|
|
327
|
+
label: string;
|
|
328
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
329
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
330
|
+
/**
|
|
331
|
+
* Open a fresh copy of `dates.pdf` (`packages/engine/main/test/fixtures`):
|
|
332
|
+
* one page (object 3) whose squares carry known `/CreationDate` and `/M`
|
|
333
|
+
* values, a file attachment annotation and an embedded file whose
|
|
334
|
+
* `/Params` carry dates, and an Info dictionary with dates.
|
|
335
|
+
*/
|
|
336
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Dates on both engines: a PDF date reads as ISO 8601 with the offset it was
|
|
340
|
+
* written with, a read written back is the same moment in the same zone, a
|
|
341
|
+
* write takes the string or a `Date`, and a date that isn't one reads `null`.
|
|
342
|
+
*/
|
|
343
|
+
declare function runDateConformance(runner: ConformanceTestRunner, opts: DateConformanceOptions): void;
|
|
344
|
+
//#endregion
|
|
345
|
+
//#region src/conformance/runAnnotationDeclarationConformance.d.ts
|
|
346
|
+
interface AnnotationDeclarationFixture {
|
|
347
|
+
/** Stable id used for the local engine; cloud uses its own id. */
|
|
348
|
+
id: string;
|
|
349
|
+
/** Bytes for the local engine. */
|
|
350
|
+
bytes: () => Uint8Array | Promise<Uint8Array>;
|
|
351
|
+
/** Override the cloud-side id. Defaults to `id`. */
|
|
352
|
+
cloudId?: string;
|
|
353
|
+
}
|
|
354
|
+
interface AnnotationDeclarationConformanceOptions {
|
|
355
|
+
label: string;
|
|
356
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
357
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
358
|
+
/** Engine 'kind' for opening: 'bytes' for local, 'id' for cloud. */
|
|
359
|
+
openKind: 'bytes' | 'id';
|
|
360
|
+
/**
|
|
361
|
+
* A document without inline annotations. One annotation of every kind the
|
|
362
|
+
* engine can create is added to its first page, then read back.
|
|
363
|
+
*/
|
|
364
|
+
authoring: AnnotationDeclarationFixture;
|
|
365
|
+
/** Documents whose annotations are read as they are. */
|
|
366
|
+
documents: readonly AnnotationDeclarationFixture[];
|
|
367
|
+
/** A document with a link whose target a write can't make (a script, a viewer command). */
|
|
368
|
+
readOnlyLink: AnnotationDeclarationFixture;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Every annotation both engines read, from real documents and freshly created
|
|
372
|
+
* ones, is checked against its kind declaration.
|
|
373
|
+
*/
|
|
374
|
+
declare function runAnnotationDeclarationConformance(runner: ConformanceTestRunner, opts: AnnotationDeclarationConformanceOptions): void;
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/conformance/annotationReadDrift.d.ts
|
|
377
|
+
/**
|
|
378
|
+
* Compares annotation reads with their kind declarations. Each difference is
|
|
379
|
+
* one line, `<field>: <problem> (<kinds>)`:
|
|
380
|
+
*
|
|
381
|
+
* - `missing`: the declaration has the field, the read doesn't;
|
|
382
|
+
* - `invalid`: the read has a value the declaration doesn't accept;
|
|
383
|
+
* - `undeclared`: the read has a field the declaration doesn't know.
|
|
384
|
+
*
|
|
385
|
+
* `<kinds>` is `every kind` when the difference holds for every kind read,
|
|
386
|
+
* otherwise the affected subtypes. Lines are sorted, so two engines reading
|
|
387
|
+
* the same documents produce the same list.
|
|
388
|
+
*/
|
|
389
|
+
declare function annotationReadDriftOf(reads: readonly unknown[]): string[];
|
|
390
|
+
//#endregion
|
|
202
391
|
//#region src/conformance/runFormConformance.d.ts
|
|
203
392
|
/**
|
|
204
393
|
* The three fixtures the forms suite needs. Shapes (names, object numbers,
|
|
@@ -210,7 +399,7 @@ declare function runAnnotationMutationConformance(runner: ConformanceTestRunner,
|
|
|
210
399
|
* `opt_check` (/Opt "Alpha", on-state "On"), hierarchical text field
|
|
211
400
|
* `billing.name`.
|
|
212
401
|
* - `orphanWidgets` — orphan_widgets.pdf: `linked_text` in /AcroForm
|
|
213
|
-
* /Fields plus
|
|
402
|
+
* /Fields plus recovered `orphan_check` and `orphan_radio`.
|
|
214
403
|
* - `choiceFields` — listbox_form.pdf: `Listbox_MultiSelect` (options
|
|
215
404
|
* Apple..), `Listbox_SingleSelect`.
|
|
216
405
|
*/
|
|
@@ -228,6 +417,12 @@ interface FormConformanceFixtures {
|
|
|
228
417
|
* same bytes under a suffixed id the way the bytes transport does.
|
|
229
418
|
*/
|
|
230
419
|
importTarget?: ConformanceFixture;
|
|
420
|
+
/**
|
|
421
|
+
* Another independent copy of `toggleFields`, whose merged field/widgets
|
|
422
|
+
* the delete test removes. Required for `openKind: 'id'` (cloud): the
|
|
423
|
+
* deletes are durable server state the other tests must not see.
|
|
424
|
+
*/
|
|
425
|
+
deleteTarget?: ConformanceFixture;
|
|
231
426
|
}
|
|
232
427
|
interface FormConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
233
428
|
fixtures: FormConformanceFixtures;
|
|
@@ -239,7 +434,7 @@ declare function runFormConformance(runner: ConformanceTestRunner, opts: FormCon
|
|
|
239
434
|
* Per-fixture knowledge for the annotation appearance conformance suite. The
|
|
240
435
|
* harness asserts thresholds (not exact wire content) so the same suite runs
|
|
241
436
|
* unchanged against the local and cloud engines and proves they emit the same
|
|
242
|
-
* set of appearances
|
|
437
|
+
* set of appearances, including those of annotations born inline in the file.
|
|
243
438
|
*/
|
|
244
439
|
interface AnnotationAppearanceConformanceFixture extends ConformanceFixture {
|
|
245
440
|
/** PDF object number of the page whose appearances are rendered. */
|
|
@@ -247,21 +442,14 @@ interface AnnotationAppearanceConformanceFixture extends ConformanceFixture {
|
|
|
247
442
|
/** At least this many `/AP` appearances are expected on that page. */
|
|
248
443
|
minAppearanceCount: number;
|
|
249
444
|
/**
|
|
250
|
-
* `true` when the page has at least one
|
|
251
|
-
*
|
|
252
|
-
*
|
|
445
|
+
* `true` when the page has at least one annotation born inline in the
|
|
446
|
+
* file (named by `baseIndex`) that carries an appearance stream: it must
|
|
447
|
+
* be emitted too, under that name.
|
|
253
448
|
*/
|
|
254
|
-
|
|
449
|
+
expectsInlineAppearance: boolean;
|
|
255
450
|
}
|
|
256
451
|
interface AnnotationAppearanceConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
257
452
|
fixture: AnnotationAppearanceConformanceFixture;
|
|
258
|
-
/**
|
|
259
|
-
* `true` for engines that expose the raw RGBA rasters (`renderAppearances`).
|
|
260
|
-
* The local engine's encoder needs a browser Canvas, so under node it can
|
|
261
|
-
* only be exercised via the raw rasters; the cloud engine ships encoded
|
|
262
|
-
* images (`renderAppearanceImages`) and leaves this `false`.
|
|
263
|
-
*/
|
|
264
|
-
supportsRawRasters?: boolean;
|
|
265
453
|
}
|
|
266
454
|
declare function runAnnotationAppearanceConformance(runner: ConformanceTestRunner, opts: AnnotationAppearanceConformanceOptions): void;
|
|
267
455
|
//#endregion
|
|
@@ -273,43 +461,32 @@ declare function runAnnotationAppearanceConformance(runner: ConformanceTestRunne
|
|
|
273
461
|
* harness can exercise reorder permutations meaningfully.
|
|
274
462
|
*/
|
|
275
463
|
interface PageReorderConformanceFixture extends ConformanceFixture {
|
|
276
|
-
/** Stable, durable
|
|
464
|
+
/** Stable, durable page object numbers of (at least) three distinct pages. Order
|
|
277
465
|
* here is the *intended caller-visible* order, not the on-disk
|
|
278
466
|
* order; the suite reads `pages.list()` first and works in document
|
|
279
467
|
* order. */
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Page used for the weak-ref-survival assertion. Defaults to the
|
|
283
|
-
* first PON in `ponsForReorderTest`. The fixture page must already
|
|
284
|
-
* have at least one weak annotation (no /NM, direct object) so the
|
|
285
|
-
* harness can capture an `index`-kind ref before the page move and
|
|
286
|
-
* re-use it after.
|
|
287
|
-
*/
|
|
288
|
-
weakRefHostPon?: number;
|
|
289
|
-
/** Quad to use for the `create()` step that produces a stable ref
|
|
290
|
-
* the suite uses. */
|
|
291
|
-
createQuad?: HighlightDraft['quadPoints'];
|
|
468
|
+
pageObjectNumbersForReorderTest?: number[];
|
|
292
469
|
}
|
|
293
470
|
interface PageReorderConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
294
471
|
fixture: PageReorderConformanceFixture;
|
|
295
472
|
}
|
|
296
473
|
/**
|
|
297
474
|
* Page reorder conformance suite. Verifies the architectural invariants
|
|
298
|
-
* locked with the user, do
|
|
299
|
-
* `
|
|
475
|
+
* locked with the user, do not loosen these without re-reading
|
|
476
|
+
* `PageReorderResult` and `DocumentPagesMutator`:
|
|
300
477
|
*
|
|
301
478
|
* 1. `pages.list()` returns every page in display order, addressed
|
|
302
479
|
* by indirect `pageObjectNumber`.
|
|
303
|
-
* 2. `pages.
|
|
480
|
+
* 2. `pages.reorder()` puts the pages next to a neighbour (or at the start
|
|
481
|
+
* or end) and returns the full new order + geometry via
|
|
304
482
|
* `result.layout` (the same shape `pages.list()` returns). There is
|
|
305
483
|
* no document-level revision; the wire never asks the caller for one.
|
|
306
|
-
* 3.
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
* `destIndex`) reject with `InvalidArg`.
|
|
484
|
+
* 3. Annotation names survive a page reorder: a user shuffling pages
|
|
485
|
+
* mid-edit must not lose a pending highlight, so a `baseIndex` ref
|
|
486
|
+
* captured before the reorder works after it.
|
|
487
|
+
* 4. A page named twice, or a neighbour that is one of the moved pages,
|
|
488
|
+
* rejects with `InvalidArg`; an unknown page or neighbour with
|
|
489
|
+
* `NotFound`.
|
|
313
490
|
* 5. Abort propagates as `AbortError`.
|
|
314
491
|
*
|
|
315
492
|
* Both local (worker host + WASM) and cloud (HTTP + @cloudpdf/server)
|
|
@@ -320,17 +497,17 @@ declare function runPageReorderConformance(runner: ConformanceTestRunner, opts:
|
|
|
320
497
|
//#region src/conformance/runPageRotateConformance.d.ts
|
|
321
498
|
/**
|
|
322
499
|
* Page rotate conformance suite. Verifies the architectural invariants —
|
|
323
|
-
* do
|
|
500
|
+
* do not loosen these without re-reading `PageRotateResult`:
|
|
324
501
|
*
|
|
325
|
-
* 1. Rotation is
|
|
502
|
+
* 1. Rotation is absolute and idempotent: `rotate(pons, 90)` twice is
|
|
326
503
|
* `rotate(pons, 90)` once. The wire never speaks "turn by".
|
|
327
|
-
* 2. Rotation is presentation metadata over
|
|
504
|
+
* 2. Rotation is presentation metadata over normalized content: the
|
|
328
505
|
* layout's `width`/`height` stay un-rotated, order and identity are
|
|
329
|
-
* untouched, and
|
|
330
|
-
*
|
|
506
|
+
* untouched, and annotation names survive (a `baseIndex` ref captured
|
|
507
|
+
* before the rotate works after it).
|
|
331
508
|
* 3. The result returns the full new `layout`; a subsequent `list()`
|
|
332
509
|
* agrees with it.
|
|
333
|
-
* 4. Invalid inputs (bad rotation value, duplicate
|
|
510
|
+
* 4. Invalid inputs (bad rotation value, duplicate page object numbers, unknown page object numbers)
|
|
334
511
|
* reject with `InvalidArg` / `NotFound`.
|
|
335
512
|
* 5. Abort propagates as `AbortError`.
|
|
336
513
|
*
|
|
@@ -339,20 +516,248 @@ declare function runPageReorderConformance(runner: ConformanceTestRunner, opts:
|
|
|
339
516
|
*/
|
|
340
517
|
declare function runPageRotateConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
341
518
|
//#endregion
|
|
519
|
+
//#region src/conformance/runAnnotationRotationConformance.d.ts
|
|
520
|
+
type AnnotationRotationFixture =
|
|
521
|
+
/** A one-page document without annotations. */
|
|
522
|
+
'authoring' |
|
|
523
|
+
/** A stamp Acrobat turned 36° clockwise: `/Rotate -36`, the turn in its appearance. */
|
|
524
|
+
'acrobat-stamp-rotated' |
|
|
525
|
+
/** A text box Acrobat added on a turned page (`/Rotate 90`), and one upright. */
|
|
526
|
+
'acrobat-freetext-rotated';
|
|
527
|
+
interface AnnotationRotationConformanceOptions {
|
|
528
|
+
label: string;
|
|
529
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
530
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
531
|
+
/** Open a fresh copy of a fixture. */
|
|
532
|
+
open: (engine: Engine, fixture: AnnotationRotationFixture) => Promise<DocumentHandle>;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* An annotation's `rotation` is degrees clockwise, as every rotation in the
|
|
536
|
+
* API, on both engines. What's drawn decides it: a turn another app made
|
|
537
|
+
* (Acrobat's `/Rotate` stamps and quarter-turned text boxes) reads as ours
|
|
538
|
+
* does, with the `box` the drawing turns, and a write keeps it. A turned
|
|
539
|
+
* box's `rect` is the upright box around all it draws, which the engine
|
|
540
|
+
* works out.
|
|
541
|
+
*/
|
|
542
|
+
declare function runAnnotationRotationConformance(runner: ConformanceTestRunner, opts: AnnotationRotationConformanceOptions): void;
|
|
543
|
+
//#endregion
|
|
544
|
+
//#region src/conformance/runPageRenderConformance.d.ts
|
|
545
|
+
/**
|
|
546
|
+
* A 600 × 800 page cropped to [100 200 500 600], so its visible area does
|
|
547
|
+
* not start at 0,0, with a black square at 200..300 × 300..400 in file
|
|
548
|
+
* coordinates (the coordinates annotation rects use).
|
|
549
|
+
*/
|
|
550
|
+
declare const CROP_OFFSET_PDF: Uint8Array<ArrayBufferLike>;
|
|
551
|
+
interface PageRenderConformanceOptions {
|
|
552
|
+
label: string;
|
|
553
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
554
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
555
|
+
/** Open a fresh copy of {@link CROP_OFFSET_PDF}. */
|
|
556
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Page images on both engines: an image reports the size of its pixels and
|
|
560
|
+
* where they are on the page (its transform, the one `pageTransform` gives
|
|
561
|
+
* without rendering), a target rect is in page space like every other place
|
|
562
|
+
* (so a page whose crop box doesn't start at 0,0 renders the area asked
|
|
563
|
+
* for), `blob()` is the image's bytes, and quality goes from 0 to 1.
|
|
564
|
+
*/
|
|
565
|
+
declare function runPageRenderConformance(runner: ConformanceTestRunner, opts: PageRenderConformanceOptions): void;
|
|
566
|
+
//#endregion
|
|
567
|
+
//#region src/conformance/pageSpaceFixtures.d.ts
|
|
568
|
+
/**
|
|
569
|
+
* Small PDFs whose page boxes are odd in every way ISO 32000 allows, and in
|
|
570
|
+
* the ways broken files are odd, each with its answer written out by hand:
|
|
571
|
+
* the visible page box, the five boxes, the turn and the unit size. The
|
|
572
|
+
* answers come from the standard, never from our code, so a check against
|
|
573
|
+
* them is a check of our code:
|
|
574
|
+
* - ISO 32000-1 Table 30 and §7.7.3.4: which boxes a page inherits;
|
|
575
|
+
* - ISO 32000-1 §7.9.5: a box's corners in any order;
|
|
576
|
+
* - ISO 32000-1 §14.11.2: the defaults, and every box inside the media box.
|
|
577
|
+
* For broken files the standard has no answer; those carry our rule and say
|
|
578
|
+
* so.
|
|
579
|
+
*
|
|
580
|
+
* Each page draws black squares (`marks`) and words at known places in file
|
|
581
|
+
* coordinates, so a render shows where the page's corner really is.
|
|
582
|
+
*/
|
|
583
|
+
/** A word drawn in Helvetica, its baseline starting at `x, y` (file coordinates). */
|
|
584
|
+
interface PageSpaceWord {
|
|
585
|
+
text: string;
|
|
586
|
+
x: number;
|
|
587
|
+
y: number;
|
|
588
|
+
size: number;
|
|
589
|
+
}
|
|
590
|
+
/** A destination: a spot on a page of the same file, as the file writes it, with its answer. */
|
|
591
|
+
interface PageSpaceGoTo {
|
|
592
|
+
/** The index of the page it goes to. */
|
|
593
|
+
toPage: number;
|
|
594
|
+
/** The destination array after the page reference, as the file writes it. */
|
|
595
|
+
view: string;
|
|
596
|
+
/**
|
|
597
|
+
* The destination measured from the top-left of the target page's visible
|
|
598
|
+
* box (x from its left edge, y from its top edge); `null` keeps the current
|
|
599
|
+
* value.
|
|
600
|
+
*/
|
|
601
|
+
expected: {
|
|
602
|
+
kind: 'xyz' | 'fitH' | 'fitV' | 'fitR';
|
|
603
|
+
x?: number | null;
|
|
604
|
+
y?: number | null;
|
|
605
|
+
width?: number;
|
|
606
|
+
height?: number;
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
/** A link on a page to a spot on another page of the same file. */
|
|
610
|
+
interface PageSpaceLink extends PageSpaceGoTo {
|
|
611
|
+
/** Where the link sits, in file coordinates. */
|
|
612
|
+
rect: PdfRect;
|
|
613
|
+
}
|
|
614
|
+
interface PageSpaceBoxes {
|
|
615
|
+
media: PdfRect;
|
|
616
|
+
crop: PdfRect;
|
|
617
|
+
bleed: PdfRect;
|
|
618
|
+
trim: PdfRect;
|
|
619
|
+
art: PdfRect;
|
|
620
|
+
}
|
|
621
|
+
interface PageSpaceFixturePage {
|
|
622
|
+
/** The page dictionary's own entries: boxes, `/Rotate`, `/UserUnit`. */
|
|
623
|
+
entries: string;
|
|
624
|
+
marks: PdfRect[];
|
|
625
|
+
words: PageSpaceWord[];
|
|
626
|
+
links?: PageSpaceLink[];
|
|
627
|
+
/** The page's open action (`/AA /O`): a go-to. */
|
|
628
|
+
openAction?: PageSpaceGoTo;
|
|
629
|
+
expected: {
|
|
630
|
+
/** The visible page box: what the page shows, in file coordinates. */
|
|
631
|
+
visible: PdfRect;
|
|
632
|
+
/** The five boxes as ISO defines them: defaults applied, reduced to the media box. */
|
|
633
|
+
boxes: PageSpaceBoxes;
|
|
634
|
+
rotation: PdfRotation;
|
|
635
|
+
userUnit: number;
|
|
636
|
+
/** The order its annotations take focus in (`/Tabs`); none when the page sets none. */
|
|
637
|
+
tabOrder?: PageTabOrder;
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
interface PageSpaceFixture {
|
|
641
|
+
name: string;
|
|
642
|
+
/** The rule the fixture checks. */
|
|
643
|
+
about: string;
|
|
644
|
+
/**
|
|
645
|
+
* `iso`: the answers are the standard's. `recovery`: the file is broken and
|
|
646
|
+
* the answers are our rule, which is what Acrobat shows.
|
|
647
|
+
*/
|
|
648
|
+
source: 'iso' | 'recovery';
|
|
649
|
+
/** Entries of the page tree node, inherited by pages that don't set them. */
|
|
650
|
+
treeEntries?: string;
|
|
651
|
+
/** The catalog's `/OpenAction` as a destination: where the document opens. */
|
|
652
|
+
openDestination?: PageSpaceGoTo;
|
|
653
|
+
/** A text field on the first page whose calculate script goes on (`/Next`) to a destination. */
|
|
654
|
+
fieldAction?: PageSpaceGoTo;
|
|
655
|
+
pages: PageSpaceFixturePage[];
|
|
656
|
+
bytes: Uint8Array;
|
|
657
|
+
}
|
|
658
|
+
declare const PAGE_SPACE_FIXTURES: readonly PageSpaceFixture[];
|
|
659
|
+
//#endregion
|
|
660
|
+
//#region src/conformance/runPageSpaceConformance.d.ts
|
|
661
|
+
interface PageSpaceConformanceOptions {
|
|
662
|
+
label: string;
|
|
663
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
664
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
665
|
+
/** Open a fresh copy of `fixture`. */
|
|
666
|
+
open: (engine: Engine, fixture: PageSpaceFixture) => Promise<DocumentHandle>;
|
|
667
|
+
/** Only these fixtures (by name); all when left out. */
|
|
668
|
+
only?: readonly string[];
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Where things really are on a page, checked against what the renderer
|
|
672
|
+
* draws. An unturned render starts at the top-left of the visible page, so a
|
|
673
|
+
* position measured from there, times the scale, is a pixel. The fixtures
|
|
674
|
+
* write their answers out by hand from ISO 32000; this suite converts the
|
|
675
|
+
* engine's values with those answers, never with engine code, so it checks
|
|
676
|
+
* the engine's boxes, the renderer and every position the API returns.
|
|
677
|
+
*/
|
|
678
|
+
declare function runPageSpaceConformance(runner: ConformanceTestRunner, opts: PageSpaceConformanceOptions): void;
|
|
679
|
+
//#endregion
|
|
680
|
+
//#region src/conformance/runColorConformance.d.ts
|
|
681
|
+
/**
|
|
682
|
+
* One page with a square whose border color the file stores as gray
|
|
683
|
+
* (`/C [0.5]`) and whose fill it stores as CMYK (`/IC [0 0 0 1]`).
|
|
684
|
+
*/
|
|
685
|
+
declare const COLOR_FIXTURE_PDF: Uint8Array<ArrayBufferLike>;
|
|
686
|
+
interface ColorConformanceOptions {
|
|
687
|
+
label: string;
|
|
688
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
689
|
+
/** Open {@link COLOR_FIXTURE_PDF}, fresh for each call. */
|
|
690
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Colors are `'#rrggbb'`: lowercase when the engine gives one, either case
|
|
694
|
+
* when it takes one. A gray or CMYK color reads as its sRGB equivalent and,
|
|
695
|
+
* sent back unchanged, stays as the file stores it.
|
|
696
|
+
*/
|
|
697
|
+
declare function runColorConformance(runner: ConformanceTestRunner, opts: ColorConformanceOptions): void;
|
|
698
|
+
//#endregion
|
|
699
|
+
//#region src/conformance/runAppearanceStatesConformance.d.ts
|
|
700
|
+
/**
|
|
701
|
+
* One 200 × 200 page with a check box that is off and stores every mode:
|
|
702
|
+
* normal Yes red and Off green, down Yes blue and Off yellow, rollover Yes
|
|
703
|
+
* black. Beside it, a square whose normal appearance is one stream (cyan).
|
|
704
|
+
* Each appearance fills its box, so a picture's middle names its state.
|
|
705
|
+
*/
|
|
706
|
+
declare const APPEARANCE_STATES_FIXTURE_PDF: Uint8Array<ArrayBufferLike>;
|
|
707
|
+
interface AppearanceStatesConformanceOptions {
|
|
708
|
+
label: string;
|
|
709
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
710
|
+
/** Open {@link APPEARANCE_STATES_FIXTURE_PDF}, fresh for each call. */
|
|
711
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Appearance states and modes, and form fields in page renders, the same on
|
|
715
|
+
* every engine. A page's appearance batch holds every appearance an
|
|
716
|
+
* annotation stores: each mode it has, and every state of each mode, each
|
|
717
|
+
* image labelled with both, whatever `/AS` says. The annotation's
|
|
718
|
+
* `appearanceState` says which state it shows. Each family has its own
|
|
719
|
+
* batch: `page.annotations` the square's, `page.forms` the check box's, and
|
|
720
|
+
* neither holds the other's. A page picture draws what its two options ask
|
|
721
|
+
* for, the annotations and the form fields, each without the other.
|
|
722
|
+
*/
|
|
723
|
+
declare function runAppearanceStatesConformance(runner: ConformanceTestRunner, opts: AppearanceStatesConformanceOptions): void;
|
|
724
|
+
//#endregion
|
|
725
|
+
//#region src/conformance/runDrawingDetailsConformance.d.ts
|
|
726
|
+
/**
|
|
727
|
+
* One 300 × 300 page with what other apps write and the engine only reads:
|
|
728
|
+
* a typewriter box (`/IT /FreeTextTypeWriter`) and a square with a beveled
|
|
729
|
+
* border.
|
|
730
|
+
*/
|
|
731
|
+
declare const DRAWING_FIXTURE_PDF: Uint8Array<ArrayBufferLike>;
|
|
732
|
+
/** The fixtures the suite opens: its own, and Acrobat's text boxes (`freetext-rotated-acrobat.pdf`). */
|
|
733
|
+
type DrawingDetailsFixture = 'drawing' | 'acrobat-freetext';
|
|
734
|
+
interface DrawingDetailsConformanceOptions {
|
|
735
|
+
label: string;
|
|
736
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
737
|
+
/** A fresh copy of `fixture` for each call: the tests write to their documents. */
|
|
738
|
+
open: (engine: Engine, fixture: DrawingDetailsFixture) => Promise<DocumentHandle>;
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* How annotations draw and what a write takes: free text colors and
|
|
742
|
+
* defaults, dashes, the points a shape needs, printing, a note's `open` and
|
|
743
|
+
* its popup, and links.
|
|
744
|
+
*/
|
|
745
|
+
declare function runDrawingDetailsConformance(runner: ConformanceTestRunner, opts: DrawingDetailsConformanceOptions): void;
|
|
746
|
+
//#endregion
|
|
342
747
|
//#region src/conformance/runPageDeleteConformance.d.ts
|
|
343
748
|
/**
|
|
344
749
|
* Page delete conformance suite. Verifies the architectural invariants —
|
|
345
|
-
* do
|
|
750
|
+
* do not loosen these without re-reading `PageDeleteResult`:
|
|
346
751
|
*
|
|
347
752
|
* 1. `pages.delete()` removes exactly the listed pages and returns the
|
|
348
753
|
* full surviving layout; a subsequent `list()` agrees.
|
|
349
|
-
* 2. Deleted
|
|
754
|
+
* 2. Deleted page object numbers are retired: addressing a deleted page afterwards is a
|
|
350
755
|
* clean `NotFound` (an API-level error, never native-memory danger).
|
|
351
|
-
* 3.
|
|
352
|
-
*
|
|
756
|
+
* 3. Surviving pages keep identity, and their annotations keep their
|
|
757
|
+
* names — a `baseIndex` ref survives a neighbour's deletion.
|
|
353
758
|
* 4. Deleting every page is rejected (`InvalidArg`) — a document keeps at
|
|
354
759
|
* least one page.
|
|
355
|
-
* 5. Duplicate / unknown
|
|
760
|
+
* 5. Duplicate / unknown page object numbers reject with `InvalidArg` / `NotFound`;
|
|
356
761
|
* abort propagates as `AbortError`.
|
|
357
762
|
*
|
|
358
763
|
* Both local (worker host + WASM) and cloud (HTTP + @cloudpdf/server)
|
|
@@ -362,7 +767,7 @@ declare function runPageDeleteConformance(runner: ConformanceTestRunner, opts: C
|
|
|
362
767
|
//#endregion
|
|
363
768
|
//#region src/conformance/runNamedPagesConformance.d.ts
|
|
364
769
|
/**
|
|
365
|
-
* Named-pages conformance: the catalog's `/Names /Pages` registry as
|
|
770
|
+
* Named-pages conformance: the catalog's `/Names /Pages` registry as layout
|
|
366
771
|
* data. Locks the invariants both engines must share — do not loosen
|
|
367
772
|
* without re-reading `NamedPageEntry` and `PageNameResult`:
|
|
368
773
|
*
|
|
@@ -370,7 +775,7 @@ declare function runPageDeleteConformance(runner: ConformanceTestRunner, opts: C
|
|
|
370
775
|
* registration resolves to a page in `pages`, a template, or is
|
|
371
776
|
* reported dangling — never silently dropped.
|
|
372
777
|
* 2. `pages.setName()` creates or replaces by decoded key (idempotent),
|
|
373
|
-
* `replace` renames in one job, and the result
|
|
778
|
+
* `replace` renames in one job, and the result is the new layout.
|
|
374
779
|
* 3. `pages.removeName()` drops the registration and nothing else.
|
|
375
780
|
* 4. Deleting a page removes every registration pointing at it — inside
|
|
376
781
|
* the delete, with no plugin in the loop.
|
|
@@ -397,7 +802,7 @@ declare function runAnnotationFlattenConformance(runner: ConformanceTestRunner,
|
|
|
397
802
|
//#region src/conformance/runAnnotationAppearanceExportConformance.d.ts
|
|
398
803
|
/**
|
|
399
804
|
* `page(pon).annotations.exportAppearance(refs)`: the chosen annotations'
|
|
400
|
-
* appearances as
|
|
805
|
+
* appearances as one single-page PDF sized to their union /Rect. Locks:
|
|
401
806
|
* 1. bytes are a PDF; the source page is untouched (no mutation, no
|
|
402
807
|
* revision bump);
|
|
403
808
|
* 2. re-opened (local engines), the page is exactly the union size and the
|
|
@@ -412,30 +817,39 @@ declare function runAnnotationAppearanceExportConformance(runner: ConformanceTes
|
|
|
412
817
|
declare function runPageFlattenConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
413
818
|
//#endregion
|
|
414
819
|
//#region src/conformance/runRedactionApplyConformance.d.ts
|
|
820
|
+
/**
|
|
821
|
+
* One 300-point page with neither /Contents nor /Resources, as some
|
|
822
|
+
* generators write a blank page.
|
|
823
|
+
*/
|
|
824
|
+
declare const BARE_PAGE_FIXTURE_PDF: Uint8Array<ArrayBufferLike>;
|
|
825
|
+
interface RedactionApplyConformanceOptions extends ConformanceOptions {
|
|
826
|
+
/** Open {@link BARE_PAGE_FIXTURE_PDF}, fresh for each call, with write access. */
|
|
827
|
+
openBarePage: (engine: Engine) => Promise<DocumentHandle>;
|
|
828
|
+
}
|
|
415
829
|
/**
|
|
416
830
|
* Transport-neutral coverage for the destructive redaction-apply rail.
|
|
417
|
-
* Runs against a fixture page with
|
|
831
|
+
* Runs against a fixture page with no pre-existing annotations so the
|
|
418
832
|
* collateral counts are exact. Content-removal fidelity itself is pinned by
|
|
419
833
|
* the native embeddertests; this suite pins the transport contract: scopes,
|
|
420
|
-
* statuses, counts,
|
|
834
|
+
* statuses, counts, affected pages, events, and preflight rejection.
|
|
421
835
|
*/
|
|
422
|
-
declare function runRedactionApplyConformance(runner: ConformanceTestRunner, opts:
|
|
836
|
+
declare function runRedactionApplyConformance(runner: ConformanceTestRunner, opts: RedactionApplyConformanceOptions): void;
|
|
423
837
|
//#endregion
|
|
424
838
|
//#region src/conformance/runPageExtractConformance.d.ts
|
|
425
839
|
/**
|
|
426
|
-
* Page extract conformance suite. `pages.extract?` is
|
|
840
|
+
* Page extract conformance suite. `pages.extract?` is optional on the
|
|
427
841
|
* contract (the `downloadLayer?` pattern) — the suite runs only when the
|
|
428
842
|
* implementation provides it, so a cloud engine that has not shipped the
|
|
429
843
|
* server endpoint yet skips cleanly instead of failing.
|
|
430
844
|
*
|
|
431
845
|
* Invariants:
|
|
432
846
|
* 1. `pages.extract([pon])` returns standalone PDF bytes (magic header).
|
|
433
|
-
* 2. The
|
|
847
|
+
* 2. The source document is untouched: identical layout before/after,
|
|
434
848
|
* and page revisions do not bump (extract is a read).
|
|
435
849
|
* 3. Caller order is preserved and page geometry survives the copy
|
|
436
850
|
* (asserted by re-opening the extracted bytes — bytes-open engines
|
|
437
851
|
* only, since a cloud engine cannot re-open loose bytes).
|
|
438
|
-
* 4. Empty / duplicate
|
|
852
|
+
* 4. Empty / duplicate page object numbers reject `InvalidArg`; unknown page object numbers reject
|
|
439
853
|
* `NotFound` (or `InvalidArg`); abort propagates as `AbortError`.
|
|
440
854
|
*/
|
|
441
855
|
declare function runPageExtractConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
@@ -443,12 +857,12 @@ declare function runPageExtractConformance(runner: ConformanceTestRunner, opts:
|
|
|
443
857
|
//#region src/conformance/runAttachmentConformance.d.ts
|
|
444
858
|
/**
|
|
445
859
|
* Attachment conformance suite. Fixture requirement: a document whose
|
|
446
|
-
* `/EmbeddedFiles` name tree contains
|
|
860
|
+
* `/EmbeddedFiles` name tree contains at least one embedded file.
|
|
447
861
|
*
|
|
448
|
-
* Both attachment surfaces are
|
|
862
|
+
* Both attachment surfaces are optional on the contract (the
|
|
449
863
|
* `downloadLayer?` pattern), probed independently and skipped cleanly:
|
|
450
864
|
* - `doc.attachments?` — document-level EmbeddedFiles (list/download)
|
|
451
|
-
* - `page.annotations.
|
|
865
|
+
* - `page.annotations.downloadResource(ref, 'file')` — annotation-level file bytes
|
|
452
866
|
*
|
|
453
867
|
* Invariants:
|
|
454
868
|
* 1. `list()` reflects the name tree: positional indices, non-empty
|
|
@@ -458,83 +872,335 @@ declare function runPageExtractConformance(runner: ConformanceTestRunner, opts:
|
|
|
458
872
|
* 3. Unknown indices reject with an `EngineError`.
|
|
459
873
|
* 4. A created file-attachment annotation round-trips its file:
|
|
460
874
|
* metadata inline on the DTO (never bytes), bytes byte-identical
|
|
461
|
-
*
|
|
875
|
+
* as its `file` resource.
|
|
462
876
|
* 5. A created text (sticky-note) annotation round-trips icon + color.
|
|
463
877
|
*/
|
|
464
878
|
declare function runAttachmentConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
465
879
|
//#endregion
|
|
466
880
|
//#region src/conformance/runPageInsertConformance.d.ts
|
|
467
|
-
/**
|
|
468
|
-
* Page insert conformance. `pages.insert` is a REQUIRED member — this suite
|
|
469
|
-
* runs unconditionally on every engine, so an implementation that loses the
|
|
470
|
-
* verb fails loudly instead of being skipped past.
|
|
471
|
-
*
|
|
472
|
-
* Invariants:
|
|
473
|
-
* 1. Every page of the source bytes is COPIED in at `destIndex` (omitted →
|
|
474
|
-
* append), in source order; the result lists the fresh PONs in
|
|
475
|
-
* insertion order and they agree with the returned layout.
|
|
476
|
-
* 2. Pre-existing pages keep their identity: same PONs before and after,
|
|
477
|
-
* in the expected positions (an insert never invalidates neighbours).
|
|
478
|
-
* 3. The mutation persists through save → re-open (bytes engines only).
|
|
479
|
-
* 4. Empty bytes / malformed bytes / out-of-range destIndex reject with
|
|
480
|
-
* InvalidArg / MalformedPdf, leaving the document untouched.
|
|
481
|
-
*/
|
|
482
881
|
declare function runPageInsertConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
483
882
|
//#endregion
|
|
484
883
|
//#region src/conformance/runPageInsertBlankConformance.d.ts
|
|
485
884
|
/**
|
|
486
|
-
* Blank-page insert conformance. `pages.insertBlank` is a
|
|
885
|
+
* Blank-page insert conformance. `pages.insertBlank` is a required member —
|
|
487
886
|
* the suite runs unconditionally on every engine (no fixture bytes are
|
|
488
887
|
* needed at all, which is the point of the verb), so an implementation that
|
|
489
888
|
* loses the verb fails loudly instead of being skipped past.
|
|
490
889
|
*
|
|
491
890
|
* Invariants:
|
|
492
|
-
* 1. `count` blank pages of exactly `size` appear at `
|
|
493
|
-
* → append), rotation 0; the result lists their fresh
|
|
891
|
+
* 1. `count` blank pages of exactly `size` appear at `toIndex` (omitted
|
|
892
|
+
* → append), rotation 0; the result lists their fresh page object numbers in insertion
|
|
494
893
|
* order and they agree with the returned layout.
|
|
495
|
-
* 2. Pre-existing pages keep their identity: same
|
|
894
|
+
* 2. Pre-existing pages keep their identity: same page object numbers before and after,
|
|
496
895
|
* in the expected positions (an insert never invalidates neighbours).
|
|
497
896
|
* 3. The mutation persists through save → re-open (bytes engines only).
|
|
498
897
|
* 4. Non-positive size / count outside [1, PAGE_INSERT_BLANK_MAX_COUNT] /
|
|
499
|
-
* out-of-range
|
|
898
|
+
* out-of-range toIndex reject with InvalidArg, leaving the document
|
|
500
899
|
* untouched.
|
|
501
900
|
*/
|
|
502
901
|
declare function runPageInsertBlankConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
503
902
|
//#endregion
|
|
903
|
+
//#region src/conformance/runObjectNumberConformance.d.ts
|
|
904
|
+
/**
|
|
905
|
+
* Two pages and a form. The first page holds a merged text field and widget
|
|
906
|
+
* (object 5, `merged`), the second nothing.
|
|
907
|
+
*/
|
|
908
|
+
declare const OBJECT_NUMBER_FIXTURE_PDF: Uint8Array<ArrayBufferLike>;
|
|
909
|
+
interface ObjectNumberConformanceOptions {
|
|
910
|
+
label: string;
|
|
911
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
912
|
+
/** Open {@link OBJECT_NUMBER_FIXTURE_PDF}, fresh for each call, with write access. */
|
|
913
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Names at birth, and the order and ids of writes:
|
|
917
|
+
*
|
|
918
|
+
* - A create that names an object number from the document's pool makes its
|
|
919
|
+
* object at exactly that number, so its ref is known before the engine
|
|
920
|
+
* answers; what the engine makes for itself lands elsewhere.
|
|
921
|
+
* - A number the session doesn't hold is refused `not-held`; one a call uses
|
|
922
|
+
* twice is `taken`. A refused call changes nothing.
|
|
923
|
+
* - Writes made without waiting apply in the order they were made: a page
|
|
924
|
+
* named at birth takes an annotation at once.
|
|
925
|
+
* - Every event of a write carries its `opId` as `origin.tx`.
|
|
926
|
+
*/
|
|
927
|
+
declare function runObjectNumberConformance(runner: ConformanceTestRunner, opts: ObjectNumberConformanceOptions): void;
|
|
928
|
+
//#endregion
|
|
929
|
+
//#region src/conformance/runChangeConformance.d.ts
|
|
930
|
+
/**
|
|
931
|
+
* Two pages and a form. The first page holds, from the file: a blue square
|
|
932
|
+
* by Ann (object 5); Ann's note (6) with its popup (7) and Bea's reply to it
|
|
933
|
+
* (8); and a merged text field and widget `name` with the value `Ann` (9).
|
|
934
|
+
* The second page is empty. Both share an empty content stream (10).
|
|
935
|
+
*/
|
|
936
|
+
declare const CHANGE_FIXTURE_PDF: Uint8Array<ArrayBufferLike>;
|
|
937
|
+
interface ChangeConformanceOptions {
|
|
938
|
+
label: string;
|
|
939
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
940
|
+
/** Open {@link CHANGE_FIXTURE_PDF}, fresh for each call, with write access. */
|
|
941
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
942
|
+
/**
|
|
943
|
+
* Open the document `doc` is on as another user, with write access. A local
|
|
944
|
+
* session has one user, so without it the test of who may undo is skipped.
|
|
945
|
+
*/
|
|
946
|
+
openAsAnotherUser?: (engine: Engine, doc: DocumentHandle) => Promise<DocumentHandle>;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* `doc.apply`, one user action as one change:
|
|
950
|
+
*
|
|
951
|
+
* - The ops apply in order, all or none, as one write: one `opId`, one burst
|
|
952
|
+
* of events sharing it. Later ops name what earlier ones create, by the
|
|
953
|
+
* numbers the creates were given.
|
|
954
|
+
* - `{ undoOf }` reverses a change as the engine recorded it, op by op in
|
|
955
|
+
* reverse order, where the document still shows what the change set; what
|
|
956
|
+
* it leaves alone is reported as `skipped`. Every op type round-trips:
|
|
957
|
+
* undo gives exactly the state before, the undo's undo the state after.
|
|
958
|
+
* - A deleted annotation comes back as the same objects, with the layer's
|
|
959
|
+
* edits, its popup and its replies.
|
|
960
|
+
* - `expect` refuses a change whose assumption doesn't hold.
|
|
961
|
+
* - Every answer is kept under its `opId`, refusals included: asking again
|
|
962
|
+
* answers the same, and a different change under it is refused.
|
|
963
|
+
* - A redaction apply ends undo for the changes before it.
|
|
964
|
+
*/
|
|
965
|
+
declare function runChangeConformance(runner: ConformanceTestRunner, opts: ChangeConformanceOptions): void;
|
|
966
|
+
//#endregion
|
|
967
|
+
//#region src/conformance/pdfOf.d.ts
|
|
968
|
+
/** A PDF file of `objects`, numbered from 1, with its cross-reference table. */
|
|
969
|
+
declare function pdfOf(objects: readonly string[]): Uint8Array;
|
|
970
|
+
//#endregion
|
|
971
|
+
//#region src/conformance/runPermissionConformance.d.ts
|
|
972
|
+
/**
|
|
973
|
+
* The two read families, through three tokens: one that may do everything,
|
|
974
|
+
* one that may only fill the form, one that may only comment. Each token
|
|
975
|
+
* reads, sees and writes its own family, and is refused the other one, on
|
|
976
|
+
* every surface: the lists, the appearance images, the page pictures, the
|
|
977
|
+
* writes, and (on an engine where sessions share a document) the events of
|
|
978
|
+
* another session's writes. A widget is the form's: the annotation verbs
|
|
979
|
+
* refuse one as the wrong family (`InvalidArg`), whatever the token.
|
|
980
|
+
*
|
|
981
|
+
* It runs on {@link CHANGE_FIXTURE_PDF}: a square (5), a note (6) with its
|
|
982
|
+
* popup (7) and a reply (8), and the text field `name`, merged with its
|
|
983
|
+
* widget (9), all on the first page.
|
|
984
|
+
*/
|
|
985
|
+
declare const PERMISSION_TOKENS: {
|
|
986
|
+
readonly everything: readonly ["*"];
|
|
987
|
+
readonly fill: readonly ["doc.open", "doc.render", "doc.forms.fill"];
|
|
988
|
+
readonly comment: readonly ["doc.open", "doc.render", "doc.annotate.modify"];
|
|
989
|
+
};
|
|
990
|
+
type PermissionToken = keyof typeof PERMISSION_TOKENS;
|
|
991
|
+
interface PermissionConformanceOptions {
|
|
992
|
+
label: string;
|
|
993
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
994
|
+
/** Open a fresh copy of {@link CHANGE_FIXTURE_PDF} with `scope`. */
|
|
995
|
+
open: (engine: Engine, scope: readonly string[]) => Promise<DocumentHandle>;
|
|
996
|
+
/**
|
|
997
|
+
* Open the document `doc` is on again, on `engine`, with `scope`: another
|
|
998
|
+
* user's session. Every open is its own session, even on the same engine.
|
|
999
|
+
* A local document is its own open's alone, so without it the events test
|
|
1000
|
+
* is skipped.
|
|
1001
|
+
*/
|
|
1002
|
+
openSameDocument?: (engine: Engine, doc: DocumentHandle, scope: readonly string[]) => Promise<DocumentHandle>;
|
|
1003
|
+
}
|
|
1004
|
+
declare function runPermissionConformance(runner: ConformanceTestRunner, opts: PermissionConformanceOptions): void;
|
|
1005
|
+
//#endregion
|
|
1006
|
+
//#region src/conformance/runFormScriptConformance.d.ts
|
|
1007
|
+
/**
|
|
1008
|
+
* A field's scripts, written through `create` and `update`, and the form's
|
|
1009
|
+
* calculation order, which follows the calculate scripts and moves by
|
|
1010
|
+
* neighbour; a widget's actions, written through its placement and
|
|
1011
|
+
* `updateWidget`. Undo puts them back. A field event takes JavaScript only;
|
|
1012
|
+
* writing a script, a submit or a link takes `doc.forms.script`, while the
|
|
1013
|
+
* actions that only change the view (go to, reset, show and hide) need
|
|
1014
|
+
* `doc.forms.modify` alone.
|
|
1015
|
+
*
|
|
1016
|
+
* It runs on {@link CHANGE_FIXTURE_PDF}: the text field `name`, merged with
|
|
1017
|
+
* its widget (9) on the first page, and no calculation order.
|
|
1018
|
+
*/
|
|
1019
|
+
interface FormScriptConformanceOptions {
|
|
1020
|
+
label: string;
|
|
1021
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1022
|
+
/** Open a fresh copy of {@link CHANGE_FIXTURE_PDF} with `scope`. */
|
|
1023
|
+
open: (engine: Engine, scope: readonly string[]) => Promise<DocumentHandle>;
|
|
1024
|
+
}
|
|
1025
|
+
declare function runFormScriptConformance(runner: ConformanceTestRunner, opts: FormScriptConformanceOptions): void;
|
|
1026
|
+
//#endregion
|
|
1027
|
+
//#region src/conformance/runFormAttributionConformance.d.ts
|
|
1028
|
+
/**
|
|
1029
|
+
* Who made a field and who filled it in, on both engines with the same
|
|
1030
|
+
* identities. The engine stamps it from the session: `create` names the
|
|
1031
|
+
* creator, a write that changes a value names its filler (a script's value
|
|
1032
|
+
* counts as filled by the user whose fill ran it), a reset and an anonymous
|
|
1033
|
+
* fill name nobody, and an undo puts the previous filler back. A widget row
|
|
1034
|
+
* reports no attribution: the field holds it.
|
|
1035
|
+
*
|
|
1036
|
+
* It runs on {@link CHANGE_FIXTURE_PDF}: the text field `name`, merged with
|
|
1037
|
+
* its widget (9), holding `Ann`.
|
|
1038
|
+
*/
|
|
1039
|
+
interface FormAttributionConformanceOptions {
|
|
1040
|
+
label: string;
|
|
1041
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
1042
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1043
|
+
/**
|
|
1044
|
+
* Open a fresh copy of {@link CHANGE_FIXTURE_PDF} as `session`. With
|
|
1045
|
+
* `from`, the new session continues that open session's document and sees
|
|
1046
|
+
* what it wrote (locally its downloaded bytes, on the cloud the same
|
|
1047
|
+
* layer); the suite closes `from` afterwards.
|
|
1048
|
+
*/
|
|
1049
|
+
openAs: (engine: Engine, session: AttributionSession, from?: DocumentHandle) => Promise<DocumentHandle>;
|
|
1050
|
+
}
|
|
1051
|
+
declare function runFormAttributionConformance(runner: ConformanceTestRunner, opts: FormAttributionConformanceOptions): void;
|
|
1052
|
+
//#endregion
|
|
1053
|
+
//#region src/conformance/runFormTransferConformance.d.ts
|
|
1054
|
+
/**
|
|
1055
|
+
* `doc.forms.export`, `doc.forms.import` and `doc.forms.importValues` on
|
|
1056
|
+
* both engines. A design import copies whole fields, with their widgets,
|
|
1057
|
+
* values, scripts, actions and calculation order, so the copy exports as
|
|
1058
|
+
* its source, apart from refs, object numbers and the attribution its mode
|
|
1059
|
+
* writes. A values import fills fields of the same name and reports what it
|
|
1060
|
+
* leaves out. Both are one change each: undone and redone with
|
|
1061
|
+
* `doc.apply({ undoOf })`, answered again on a retry, refused before
|
|
1062
|
+
* anything is written.
|
|
1063
|
+
*
|
|
1064
|
+
* It runs on {@link TWO_PAGES_PDF}: two empty pages (3 and 4) and no form.
|
|
1065
|
+
*/
|
|
1066
|
+
interface FormTransferConformanceOptions {
|
|
1067
|
+
label: string;
|
|
1068
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
1069
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1070
|
+
/** Open a fresh document of `bytes` as `session`. */
|
|
1071
|
+
openAs: (engine: Engine, session: AttributionSession, bytes: Uint8Array) => Promise<DocumentHandle>;
|
|
1072
|
+
}
|
|
1073
|
+
/** Two empty 300 × 300 pages (3 and 4), and no form. */
|
|
1074
|
+
declare const TWO_PAGES_PDF: Uint8Array<ArrayBufferLike>;
|
|
1075
|
+
declare function runFormTransferConformance(runner: ConformanceTestRunner, opts: FormTransferConformanceOptions): void;
|
|
1076
|
+
//#endregion
|
|
1077
|
+
//#region src/conformance/runWidgetRotationConformance.d.ts
|
|
1078
|
+
/**
|
|
1079
|
+
* A widget turns as a box kind does: `box` is the frame its contents are
|
|
1080
|
+
* laid out in, `rotation` a quarter turn, clockwise (`/MK /R`, which the
|
|
1081
|
+
* file holds counterclockwise), and `rect` where it stands on the page, the
|
|
1082
|
+
* box turned. On both engines: Acrobat's turned fields read so, a placement
|
|
1083
|
+
* turns a new field, an update turns, moves and resizes one, undo puts it
|
|
1084
|
+
* back, and a form bundle carries the turn.
|
|
1085
|
+
*
|
|
1086
|
+
* It runs on {@link TURNED_FIELDS_PDF}.
|
|
1087
|
+
*/
|
|
1088
|
+
interface WidgetRotationConformanceOptions {
|
|
1089
|
+
label: string;
|
|
1090
|
+
/** Build a fresh engine for this suite. The suite tears it down at the end. */
|
|
1091
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1092
|
+
/** Open a fresh document of `bytes` with every scope. */
|
|
1093
|
+
open: (engine: Engine, bytes: Uint8Array) => Promise<DocumentHandle>;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Two 300 × 300 pages: the first upright (3), the second shown turned 90°
|
|
1097
|
+
* (`/Rotate 90`, page 4). Text fields with `/MK /R` as Acrobat writes it,
|
|
1098
|
+
* counterclockwise: `upright` (none), `r90` (90, the text runs up the page),
|
|
1099
|
+
* `r180`, `r270`, `odd` (45, which no viewer draws turned), `negative`
|
|
1100
|
+
* (-90, the same turn as 270), and `on-turned` on the turned page (90: an
|
|
1101
|
+
* upright field there, as Acrobat adds one).
|
|
1102
|
+
*/
|
|
1103
|
+
declare const TURNED_FIELDS_PDF: Uint8Array<ArrayBufferLike>;
|
|
1104
|
+
declare function runWidgetRotationConformance(runner: ConformanceTestRunner, opts: WidgetRotationConformanceOptions): void;
|
|
1105
|
+
//#endregion
|
|
1106
|
+
//#region src/conformance/runWidgetFindingConformance.d.ts
|
|
1107
|
+
interface WidgetFindingCase {
|
|
1108
|
+
/** What the file does. */
|
|
1109
|
+
readonly does: string;
|
|
1110
|
+
readonly pdf: Uint8Array;
|
|
1111
|
+
/** The page whose `/Annots` holds the widget, or `null` when no page shows it. */
|
|
1112
|
+
readonly page: number | null;
|
|
1113
|
+
/** The name of the field the form reads the widget into, or `null` for a widget in no field. */
|
|
1114
|
+
readonly field: string | null;
|
|
1115
|
+
}
|
|
1116
|
+
/** The cases, by name. Object 3 is the first page in each. */
|
|
1117
|
+
declare const WIDGET_FINDING_CASES: {
|
|
1118
|
+
readonly 'annots-only': {
|
|
1119
|
+
readonly does: "a merged field/widget in a page's /Annots that the field tree doesn't list";
|
|
1120
|
+
readonly pdf: Uint8Array<ArrayBufferLike>;
|
|
1121
|
+
readonly page: 3;
|
|
1122
|
+
readonly field: "orphan";
|
|
1123
|
+
};
|
|
1124
|
+
readonly inline: {
|
|
1125
|
+
readonly does: "a widget written straight into a page's /Annots, as no object of its own";
|
|
1126
|
+
readonly pdf: Uint8Array<ArrayBufferLike>;
|
|
1127
|
+
readonly page: 3;
|
|
1128
|
+
readonly field: null;
|
|
1129
|
+
};
|
|
1130
|
+
readonly 'no-acroform': {
|
|
1131
|
+
readonly does: "a field widget in a file that has no /AcroForm at all";
|
|
1132
|
+
readonly pdf: Uint8Array<ArrayBufferLike>;
|
|
1133
|
+
readonly page: 3;
|
|
1134
|
+
readonly field: "lonely";
|
|
1135
|
+
};
|
|
1136
|
+
readonly 'stale-p': {
|
|
1137
|
+
readonly does: "a widget in the second page's /Annots whose /P names the first page";
|
|
1138
|
+
readonly pdf: Uint8Array<ArrayBufferLike>;
|
|
1139
|
+
readonly page: 4;
|
|
1140
|
+
readonly field: "moved";
|
|
1141
|
+
};
|
|
1142
|
+
readonly 'deleted-page': {
|
|
1143
|
+
readonly does: "a field whose widget was on a page the document no longer has";
|
|
1144
|
+
readonly pdf: Uint8Array<ArrayBufferLike>;
|
|
1145
|
+
readonly page: null;
|
|
1146
|
+
readonly field: "gone";
|
|
1147
|
+
};
|
|
1148
|
+
readonly 'no-field-type': {
|
|
1149
|
+
readonly does: "a widget with no field type anywhere on its /Parent chain";
|
|
1150
|
+
readonly pdf: Uint8Array<ArrayBufferLike>;
|
|
1151
|
+
readonly page: 3;
|
|
1152
|
+
readonly field: null;
|
|
1153
|
+
};
|
|
1154
|
+
};
|
|
1155
|
+
type WidgetFindingCaseName = keyof typeof WIDGET_FINDING_CASES;
|
|
1156
|
+
interface WidgetFindingConformanceOptions {
|
|
1157
|
+
label: string;
|
|
1158
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1159
|
+
/** Open `pdf` with every right, as a document of its own. */
|
|
1160
|
+
open: (engine: Engine, pdf: Uint8Array, name: WidgetFindingCaseName) => Promise<DocumentHandle>;
|
|
1161
|
+
}
|
|
1162
|
+
declare function runWidgetFindingConformance(runner: ConformanceTestRunner, opts: WidgetFindingConformanceOptions): void;
|
|
1163
|
+
//#endregion
|
|
504
1164
|
//#region src/conformance/runPieceInfoConformance.d.ts
|
|
1165
|
+
interface PieceInfoConformanceOptions {
|
|
1166
|
+
label: string;
|
|
1167
|
+
/** Build a fresh local engine for this suite. The suite tears it down at the end. */
|
|
1168
|
+
makeEngine: () => Promise<LocalEngine> | LocalEngine;
|
|
1169
|
+
fixture: ConformanceFixture;
|
|
1170
|
+
}
|
|
505
1171
|
/**
|
|
506
|
-
* `/PieceInfo` conformance (doc + page level)
|
|
507
|
-
*
|
|
508
|
-
* implementation provides it, so an engine that has not shipped it yet
|
|
509
|
-
* skips cleanly.
|
|
1172
|
+
* `/PieceInfo` conformance (doc + page level), on the local engine: the
|
|
1173
|
+
* only one with `/PieceInfo`.
|
|
510
1174
|
*
|
|
511
1175
|
* Invariants:
|
|
512
1176
|
* 1. The full value vocabulary round-trips at both levels: string,
|
|
513
1177
|
* number, boolean, name, string-array — read back with the same tags.
|
|
514
|
-
* 2. Writes
|
|
515
|
-
* engines only, since cloud cannot re-open loose bytes).
|
|
1178
|
+
* 2. Writes persist: download() → re-open → identical read.
|
|
516
1179
|
* 3. `null` deletes a key; sibling keys and sibling applications
|
|
517
1180
|
* survive both key deletes and whole-entry clears.
|
|
518
1181
|
* 4. An absent application reads as `null`; `applications()` enumerates
|
|
519
|
-
* what is present; every write refreshes `
|
|
1182
|
+
* what is present; every write refreshes `modifiedAt`.
|
|
520
1183
|
*/
|
|
521
|
-
declare function runPieceInfoConformance(runner: ConformanceTestRunner, opts:
|
|
1184
|
+
declare function runPieceInfoConformance(runner: ConformanceTestRunner, opts: PieceInfoConformanceOptions): void;
|
|
522
1185
|
//#endregion
|
|
523
1186
|
//#region src/conformance/runDocumentEventsConformance.d.ts
|
|
524
1187
|
/**
|
|
525
1188
|
* Document event stream conformance suite. Verifies the invariants the
|
|
526
|
-
* collaboration design rests on — do
|
|
1189
|
+
* collaboration design rests on — do not loosen these without re-reading
|
|
527
1190
|
* `DocumentEvent`:
|
|
528
1191
|
*
|
|
529
|
-
* 1.
|
|
1192
|
+
* 1. Exactly once: every confirmed mutation produces exactly one event,
|
|
530
1193
|
* in mutation order, regardless of engine (local worker or cloud HTTP).
|
|
531
|
-
* 2.
|
|
1194
|
+
* 2. Ground truth: a failed mutation publishes nothing; events fire only
|
|
532
1195
|
* after confirmation.
|
|
533
|
-
* 3.
|
|
1196
|
+
* 3. Results ride verbatim: each event embeds the result the caller
|
|
534
1197
|
* received, deep-equal field for field.
|
|
535
|
-
* 4.
|
|
536
|
-
*
|
|
537
|
-
* 5. Unsubscribe stops delivery.
|
|
1198
|
+
* 4. Provenance: own mutations are `origin.kind: 'local'` with the
|
|
1199
|
+
* handle's one `sessionId`.
|
|
1200
|
+
* 5. Unsubscribe stops delivery; `on(type)` hears only its type.
|
|
1201
|
+
* 6. Published before settlement: the event for a session's own mutation
|
|
1202
|
+
* reaches subscribers before the mutation's promise settles, so a
|
|
1203
|
+
* caller that awaits the mutation already sees state derived from it.
|
|
538
1204
|
*
|
|
539
1205
|
* Both local (worker host + WASM) and cloud (HTTP + @cloudpdf/server)
|
|
540
1206
|
* implementations must pass identically.
|
|
@@ -568,11 +1234,11 @@ declare function runPageTextConformance(runner: ConformanceTestRunner, opts: Pag
|
|
|
568
1234
|
//#endregion
|
|
569
1235
|
//#region src/conformance/runTextDivergenceConformance.d.ts
|
|
570
1236
|
/**
|
|
571
|
-
* Index-space divergence conformance: the cases where a page's
|
|
1237
|
+
* Index-space divergence conformance: the cases where a page's character
|
|
572
1238
|
* space (what geometry tiles and selection/search ranges address) and its
|
|
573
|
-
* extracted
|
|
1239
|
+
* extracted text differ — and the `charMap` contract that bridges them.
|
|
574
1240
|
*
|
|
575
|
-
* Fixtures pin
|
|
1241
|
+
* Fixtures pin exact values (text, charCount, anchors) verified against the
|
|
576
1242
|
* wasm runtime, so both engines must produce byte-identical snapshots:
|
|
577
1243
|
*
|
|
578
1244
|
* - a non-printing character occupying a character slot with no text unit
|
|
@@ -581,17 +1247,17 @@ declare function runPageTextConformance(runner: ConformanceTestRunner, opts: Pag
|
|
|
581
1247
|
* characters in lockstep with the text, identity map, real segments);
|
|
582
1248
|
* - supplementary-plane text via a ToUnicode surrogate pair
|
|
583
1249
|
* (`embedpdf_astral_tounicode.pdf` — two lockstep surrogate entries,
|
|
584
|
-
* identity map, astral content
|
|
1250
|
+
* identity map, astral content survives extraction).
|
|
585
1251
|
*
|
|
586
|
-
* The search probe closes the loop: a hit's `
|
|
587
|
-
*
|
|
1252
|
+
* The search probe closes the loop: a hit's `start`/`count` must be
|
|
1253
|
+
* character-space (segments join geometry), and slicing the snapshot by the
|
|
588
1254
|
* hit's range must reproduce the matched text exactly — the law that makes
|
|
589
1255
|
* select-this-match and copy compose.
|
|
590
1256
|
*/
|
|
591
1257
|
interface TextDivergenceConformanceFixture extends ConformanceFixture {
|
|
592
1258
|
/** PDF indirect object number of the probed page. */
|
|
593
1259
|
pageObjectNumber: number;
|
|
594
|
-
/** The
|
|
1260
|
+
/** The exact extracted text (UTF-16 faithful). */
|
|
595
1261
|
exactText: string;
|
|
596
1262
|
/** The character-space size (may differ from `exactText.length`). */
|
|
597
1263
|
expectedCharCount: number;
|
|
@@ -599,15 +1265,15 @@ interface TextDivergenceConformanceFixture extends ConformanceFixture {
|
|
|
599
1265
|
expectedCharMap: ReadonlyArray<CharMapAnchor> | null;
|
|
600
1266
|
/** Char-space slice expectations (half-open). */
|
|
601
1267
|
slices?: ReadonlyArray<{
|
|
602
|
-
|
|
603
|
-
|
|
1268
|
+
start: number;
|
|
1269
|
+
count: number;
|
|
604
1270
|
text: string;
|
|
605
1271
|
}>;
|
|
606
|
-
/** Literal search probe with expected
|
|
1272
|
+
/** Literal search probe with expected character-space hit range. */
|
|
607
1273
|
search?: {
|
|
608
1274
|
query: string;
|
|
609
|
-
|
|
610
|
-
|
|
1275
|
+
start: number;
|
|
1276
|
+
count: number;
|
|
611
1277
|
matchedText: string;
|
|
612
1278
|
};
|
|
613
1279
|
}
|
|
@@ -621,7 +1287,7 @@ type TextDivergenceCase = Omit<TextDivergenceConformanceFixture, 'id' | 'bytes'
|
|
|
621
1287
|
resource: string;
|
|
622
1288
|
};
|
|
623
1289
|
/**
|
|
624
|
-
*
|
|
1290
|
+
* The pinned divergence cases — one table, consumed by both engines' suites
|
|
625
1291
|
* so expected values cannot drift. Values verified against the wasm runtime
|
|
626
1292
|
* (see each case). All fixtures are single-page; the page's indirect object
|
|
627
1293
|
* number is 3 in each.
|
|
@@ -645,7 +1311,7 @@ interface PageGeometryOrientationFixture extends ConformanceFixture {
|
|
|
645
1311
|
kind: 'empty-only';
|
|
646
1312
|
} | {
|
|
647
1313
|
kind: 'rotated';
|
|
648
|
-
/**
|
|
1314
|
+
/** Turns (degrees clockwise) rotated runs may carry. */
|
|
649
1315
|
rotations: number[];
|
|
650
1316
|
ascentFlip: boolean;
|
|
651
1317
|
/**
|
|
@@ -685,21 +1351,16 @@ interface SearchConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
|
685
1351
|
}
|
|
686
1352
|
declare function runSearchConformance(runner: ConformanceTestRunner, opts: SearchConformanceOptions): void;
|
|
687
1353
|
//#endregion
|
|
688
|
-
//#region src/conformance/
|
|
1354
|
+
//#region src/conformance/diffAnnotationList.d.ts
|
|
689
1355
|
/**
|
|
690
1356
|
* Returns a list of human-readable difference strings between two
|
|
691
|
-
*
|
|
692
|
-
* that local and cloud emit identical
|
|
693
|
-
*
|
|
694
|
-
*
|
|
695
|
-
*
|
|
696
|
-
* should be 0 for fresh reads on both sides). Page order is no longer part
|
|
697
|
-
* of `PageState`; it lives in `PageLayout.index` (see `pages.list()`).
|
|
698
|
-
* `auditHead` is likewise not compared: it is a cloud-only reconciliation
|
|
699
|
-
* cursor, absent on local snapshots by design.
|
|
1357
|
+
* `annotations.list()` results, page by page. Empty array means parity.
|
|
1358
|
+
* Used by `engine-node.ts` to assert that local and cloud emit identical
|
|
1359
|
+
* annotations for the same fixture: the same pages, and on each the same
|
|
1360
|
+
* annotations under the same names. `auditHead` is not compared: it is a
|
|
1361
|
+
* cloud-only reconciliation cursor, absent on local lists by design.
|
|
700
1362
|
*/
|
|
701
|
-
declare function
|
|
702
|
-
declare function diffAnnotationListSnapshotAll(a: AnnotationListSnapshotAllPages, b: AnnotationListSnapshotAllPages): string[];
|
|
1363
|
+
declare function diffAnnotationList(a: AnnotationList, b: AnnotationList): string[];
|
|
703
1364
|
//#endregion
|
|
704
1365
|
//#region src/conformance/runSignatureConformance.d.ts
|
|
705
1366
|
interface SignatureConformanceFixtures {
|
|
@@ -748,12 +1409,12 @@ interface SignatureConformanceOptions {
|
|
|
748
1409
|
fixtures: SignatureConformanceFixtures;
|
|
749
1410
|
}
|
|
750
1411
|
/**
|
|
751
|
-
* Digital signatures, read side. The service is
|
|
1412
|
+
* Digital signatures, read side. The service is optional on the contract
|
|
752
1413
|
* (`downloadLayer?` pattern) — the suite runs only where the engine
|
|
753
1414
|
* provides it.
|
|
754
1415
|
*
|
|
755
1416
|
* Invariants:
|
|
756
|
-
* 1. Byte facts describe the
|
|
1417
|
+
* 1. Byte facts describe the loaded bytes: a revision is a byte prefix,
|
|
757
1418
|
* a whole-revision signature seals exactly one, the digest over its
|
|
758
1419
|
* `/ByteRange` is what the file's bytes hash to, and an unsaved edit
|
|
759
1420
|
* changes none of it.
|
|
@@ -768,5 +1429,103 @@ interface SignatureConformanceOptions {
|
|
|
768
1429
|
*/
|
|
769
1430
|
declare function runSignatureConformance(runner: ConformanceTestRunner, opts: SignatureConformanceOptions): void;
|
|
770
1431
|
//#endregion
|
|
771
|
-
|
|
1432
|
+
//#region src/conformance/runAnnotationPredictionConformance.d.ts
|
|
1433
|
+
/** One blank US Letter page. */
|
|
1434
|
+
declare const PREDICTION_FIXTURE_PDF: Uint8Array<ArrayBufferLike>;
|
|
1435
|
+
interface AnnotationPredictionConformanceOptions {
|
|
1436
|
+
label: string;
|
|
1437
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1438
|
+
/** Open {@link PREDICTION_FIXTURE_PDF}. Called once; every case adds its own annotation. */
|
|
1439
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* What a write does, predicted: `applyAnnotationPatch(read, patch)` equals the
|
|
1443
|
+
* annotation the engine reads back after `update(ref, patch)`, and
|
|
1444
|
+
* `annotationOfDraft(draft, context)` the one it reads back after
|
|
1445
|
+
* `create(draft)`, on every field but the ones the engine works out from its
|
|
1446
|
+
* drawing or stamps on each write.
|
|
1447
|
+
* A viewer shows a pending change this way, so the prediction is what the
|
|
1448
|
+
* user sees until the engine answers.
|
|
1449
|
+
*/
|
|
1450
|
+
declare function runAnnotationPredictionConformance(runner: ConformanceTestRunner, opts: AnnotationPredictionConformanceOptions): void;
|
|
1451
|
+
//#endregion
|
|
1452
|
+
//#region src/conformance/runFormPredictionConformance.d.ts
|
|
1453
|
+
interface FormPredictionConformanceOptions {
|
|
1454
|
+
label: string;
|
|
1455
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1456
|
+
/** Open `PREDICTION_FIXTURE_PDF` (one blank page). Called once; every case adds its own field. */
|
|
1457
|
+
open: (engine: Engine) => Promise<DocumentHandle>;
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* What a form op leaves, predicted (`forms/predict.ts`): each op of every
|
|
1461
|
+
* family run against a fresh field, and the field and its widgets' rows the
|
|
1462
|
+
* engine reads back compared with the prediction, field by field. What the
|
|
1463
|
+
* engine stamps on a write (dates, who filled it in), its fonts from the
|
|
1464
|
+
* document's default appearance and the names it mints are left out.
|
|
1465
|
+
*/
|
|
1466
|
+
declare function runFormPredictionConformance(runner: ConformanceTestRunner, opts: FormPredictionConformanceOptions): void;
|
|
1467
|
+
//#endregion
|
|
1468
|
+
//#region src/conformance/runFieldGroupsConformance.d.ts
|
|
1469
|
+
/**
|
|
1470
|
+
* Field groups: who fills in and signs which fields. On a buyer and seller
|
|
1471
|
+
* contract, the same on every engine:
|
|
1472
|
+
* - each signer fills in and signs only their own group's fields;
|
|
1473
|
+
* - a field a script calculates moves with a fill of the signer's own;
|
|
1474
|
+
* - a designer puts fields in their own group, or one they may set;
|
|
1475
|
+
* - a values import leaves out the fields the token may not fill;
|
|
1476
|
+
* - signing a grouped signature field locks the rest of its group.
|
|
1477
|
+
*
|
|
1478
|
+
* It runs on {@link FIELD_GROUPS_PDF}.
|
|
1479
|
+
*/
|
|
1480
|
+
/**
|
|
1481
|
+
* One page with a buyer's and a seller's fields, each field's group in its
|
|
1482
|
+
* `/EMBD_Metadata /GroupID`: `buyer_name` and `buyer_price` (buyer),
|
|
1483
|
+
* `seller_name` (seller), `total` (no group; a calculate script, in the
|
|
1484
|
+
* calculation order), and the signature fields `buyer_sig` (buyer) and
|
|
1485
|
+
* `seller_sig` (seller).
|
|
1486
|
+
*/
|
|
1487
|
+
declare const FIELD_GROUPS_PDF: Uint8Array<ArrayBufferLike>;
|
|
1488
|
+
/** The tokens of the contract's parties. */
|
|
1489
|
+
declare const FIELD_GROUP_TOKENS: {
|
|
1490
|
+
/** The buyer: fills in and signs the buyer's fields. */
|
|
1491
|
+
readonly buyer: {
|
|
1492
|
+
readonly scope: readonly ["doc.open", "doc.render", "fields:fill:group=buyer", "fields:sign:group=buyer"];
|
|
1493
|
+
readonly identity: {
|
|
1494
|
+
readonly userId: "alice";
|
|
1495
|
+
readonly displayName: "Alice";
|
|
1496
|
+
};
|
|
1497
|
+
};
|
|
1498
|
+
/** The seller, as a share link would grant it: everything on the seller's fields. */
|
|
1499
|
+
readonly seller: {
|
|
1500
|
+
readonly scope: readonly ["doc.open", "doc.render", "fields:*:group=seller"];
|
|
1501
|
+
readonly identity: {};
|
|
1502
|
+
};
|
|
1503
|
+
/** The designer: her fields go in legal; she may put fields in the buyer's group too. */
|
|
1504
|
+
readonly designer: {
|
|
1505
|
+
readonly scope: readonly ["doc.open", "doc.render", "doc.forms.modify", "fields:set-group:group=buyer"];
|
|
1506
|
+
readonly identity: {
|
|
1507
|
+
readonly userId: "lisa";
|
|
1508
|
+
readonly groupId: "legal";
|
|
1509
|
+
};
|
|
1510
|
+
};
|
|
1511
|
+
readonly everything: {
|
|
1512
|
+
readonly scope: readonly ["*"];
|
|
1513
|
+
readonly identity: {};
|
|
1514
|
+
};
|
|
1515
|
+
};
|
|
1516
|
+
type FieldGroupToken = keyof typeof FIELD_GROUP_TOKENS;
|
|
1517
|
+
interface FieldGroupsConformanceOptions {
|
|
1518
|
+
label: string;
|
|
1519
|
+
makeEngine: () => Promise<Engine> | Engine;
|
|
1520
|
+
/** Open a fresh copy of `bytes` (default {@link FIELD_GROUPS_PDF}) with `scope`, acting for `identity`. */
|
|
1521
|
+
open: (engine: Engine, scope: readonly string[], identity: Identity, bytes?: Uint8Array) => Promise<DocumentHandle>;
|
|
1522
|
+
/**
|
|
1523
|
+
* Whether a signing completes on this engine with a placeholder CMS, so
|
|
1524
|
+
* the lock it installs can be read back. Default `true`.
|
|
1525
|
+
*/
|
|
1526
|
+
completesSignings?: boolean;
|
|
1527
|
+
}
|
|
1528
|
+
declare function runFieldGroupsConformance(runner: ConformanceTestRunner, opts: FieldGroupsConformanceOptions): void;
|
|
1529
|
+
//#endregion
|
|
1530
|
+
export { APPEARANCE_STATES_FIXTURE_PDF, type ActionsConformanceFixtures, type ActionsConformanceOptions, type AnnotationAppearanceConformanceFixture, type AnnotationAppearanceConformanceOptions, type AnnotationAttributionConformanceOptions, type AnnotationConformanceOptions, type AnnotationDeclarationConformanceOptions, type AnnotationDeclarationFixture, type AnnotationMutationConformanceFixture, type AnnotationMutationConformanceOptions, type AnnotationPredictionConformanceOptions, type AnnotationReadConformanceFixture, type AnnotationResourceConformanceOptions, type AnnotationResourceFixture, type AnnotationRotationConformanceOptions, type AnnotationRotationFixture, type AnnotationTransferConformanceOptions, type AppearanceStatesConformanceOptions, type AttributionSession, BARE_PAGE_FIXTURE_PDF, CHANGE_FIXTURE_PDF, COLOR_FIXTURE_PDF, CROP_OFFSET_PDF, type ChangeConformanceOptions, type ColorConformanceOptions, type ConformanceExpect, type ConformanceFixture, type ConformanceOptions, type ConformanceTestRunner, type Creatable, DRAWING_FIXTURE_PDF, type DateConformanceOptions, type DrawingDetailsConformanceOptions, type DrawingDetailsFixture, FIELD_GROUPS_PDF, FIELD_GROUP_TOKENS, type FieldGroupToken, type FieldGroupsConformanceOptions, type FormAttributionConformanceOptions, type FormConformanceFixtures, type FormConformanceOptions, type FormPredictionConformanceOptions, type FormScriptConformanceOptions, type FormTransferConformanceOptions, OBJECT_NUMBER_FIXTURE_PDF, type ObjectNumberConformanceOptions, PAGE_SPACE_FIXTURES, PERMISSION_TOKENS, PREDICTION_FIXTURE_PDF, type PageGeometryOrientationFixture, type PageGeometryOrientationOptions, type PageRenderConformanceOptions, type PageReorderConformanceFixture, type PageReorderConformanceOptions, type PageSpaceConformanceOptions, type PageSpaceFixture, type PageSpaceFixturePage, type PageTextConformanceFixture, type PageTextConformanceOptions, type PermissionConformanceOptions, type PermissionToken, type PieceInfoConformanceOptions, type RedactionApplyConformanceOptions, type SearchConformanceFixture, type SearchConformanceOptions, type SignatureConformanceFixtures, type SignatureConformanceOptions, TEXT_DIVERGENCE_CASES, TURNED_FIELDS_PDF, TWO_PAGES_PDF, type TextDivergenceCase, type TextDivergenceConformanceFixture, type TextDivergenceConformanceOptions, WIDGET_FINDING_CASES, type WidgetFindingCase, type WidgetFindingCaseName, type WidgetFindingConformanceOptions, type WidgetRotationConformanceOptions, annotationReadDriftOf, creatables, diffAnnotationList, iconRect, pdfOf, runActionsConformance, runAnnotationAppearanceConformance, runAnnotationAppearanceExportConformance, runAnnotationAttributionConformance, runAnnotationDeclarationConformance, runAnnotationExportConformance, runAnnotationFlattenConformance, runAnnotationImportConformance, runAnnotationMutationConformance, runAnnotationPredictionConformance, runAnnotationReadConformance, runAnnotationResourceConformance, runAnnotationRotationConformance, runAnnotationTransferConformance, runAppearanceStatesConformance, runAttachmentConformance, runChangeConformance, runColorConformance, runDateConformance, runDocumentEventsConformance, runDrawingDetailsConformance, runFieldGroupsConformance, runFormAttributionConformance, runFormConformance, runFormPredictionConformance, runFormScriptConformance, runFormTransferConformance, runMeasurementConformance, runMetadataConformance, runNamedPagesConformance, runObjectNumberConformance, runPageDeleteConformance, runPageExtractConformance, runPageFlattenConformance, runPageGeometryOrientationConformance, runPageInsertBlankConformance, runPageInsertConformance, runPageRenderConformance, runPageReorderConformance, runPageRotateConformance, runPageSpaceConformance, runPageTextConformance, runPermissionConformance, runPieceInfoConformance, runRedactionApplyConformance, runSearchConformance, runSignatureConformance, runTextDivergenceConformance, runWidgetFindingConformance, runWidgetRotationConformance };
|
|
772
1531
|
//# sourceMappingURL=conformance.d.cts.map
|