@embedpdf/engine-core 3.0.0-next.13 → 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-_JRjqvoI.d.ts → DocumentSecurityService-CU1M6Q7m.d.ts} +100 -112
- package/dist/{DocumentSecurityService-ClTZc0zO.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/authority-DLMNR7ff.cjs +2676 -0
- 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 +16753 -5247
- package/dist/conformance.cjs.map +1 -1
- package/dist/conformance.d.cts +928 -165
- package/dist/conformance.d.ts +928 -165
- package/dist/conformance.js +16731 -5268
- 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 +330 -103
- 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 +733 -284
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +5 -1348
- package/dist/runtime.d.ts +5 -1348
- 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 +1056 -379
- package/dist/wire.cjs.map +1 -1
- package/dist/wire.d.cts +15069 -725
- package/dist/wire.d.ts +15069 -725
- package/dist/wire.js +825 -239
- package/dist/wire.js.map +1 -1
- package/package.json +10 -1
- package/dist/AbortError-Cq2igpZ6.cjs +0 -38
- package/dist/AbortError-Cq2igpZ6.cjs.map +0 -1
- package/dist/AbortError-DHqPBnYc.js +0 -27
- package/dist/AbortError-DHqPBnYc.js.map +0 -1
- package/dist/AnnotationListSnapshot-D3mFut1e.d.cts +0 -6871
- package/dist/AnnotationListSnapshot-D3mFut1e.d.ts +0 -6871
- package/dist/Engine-Bx0NOfmd.d.cts +0 -1264
- package/dist/Engine-DxtpCYcP.d.ts +0 -1264
- package/dist/PageInsertBlankInput-CqXBmFhN.cjs +0 -449
- package/dist/PageInsertBlankInput-CqXBmFhN.cjs.map +0 -1
- package/dist/PageInsertBlankInput-cHq9-i-z.js +0 -378
- package/dist/PageInsertBlankInput-cHq9-i-z.js.map +0 -1
- package/dist/builders-Bqm8yTpi.cjs +0 -3564
- package/dist/builders-Bqm8yTpi.cjs.map +0 -1
- package/dist/builders-Dqo2X-dt.js +0 -3121
- package/dist/builders-Dqo2X-dt.js.map +0 -1
- package/dist/fold-2V29cxCV.cjs +0 -447
- package/dist/fold-2V29cxCV.cjs.map +0 -1
- package/dist/fold-CdEJTBTn.js +0 -334
- package/dist/fold-CdEJTBTn.js.map +0 -1
- package/dist/resolver-CYVNV4hn.cjs.map +0 -1
- package/dist/resolver-inAVzsWt.js.map +0 -1
- package/dist/schemas-BLARNCgx.js +0 -3113
- package/dist/schemas-BLARNCgx.js.map +0 -1
- package/dist/schemas-DIqFMmrC.cjs +0 -4468
- package/dist/schemas-DIqFMmrC.cjs.map +0 -1
package/dist/conformance.d.ts
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.js";
|
|
2
|
+
import { _ as Engine, t as LocalEngine, y as DocumentHandle } from "./LocalEngine-DPriFujS.js";
|
|
3
3
|
//#region src/conformance/runMetadataConformance.d.ts
|
|
4
4
|
interface ConformanceTestRunner {
|
|
5
5
|
describe(name: string, fn: () => void): void;
|
|
@@ -54,6 +54,10 @@ interface ConformanceOptions {
|
|
|
54
54
|
*/
|
|
55
55
|
declare function runMetadataConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
56
56
|
//#endregion
|
|
57
|
+
//#region src/conformance/runMeasurementConformance.d.ts
|
|
58
|
+
/** Shared numerical, persistence and calibration contract for local and HTTP engines. */
|
|
59
|
+
declare function runMeasurementConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
60
|
+
//#endregion
|
|
57
61
|
//#region src/conformance/runAnnotationReadConformance.d.ts
|
|
58
62
|
/**
|
|
59
63
|
* Expected per-fixture annotation knowledge. The harness asserts against
|
|
@@ -86,10 +90,10 @@ interface AnnotationReadConformanceFixture extends ConformanceFixture {
|
|
|
86
90
|
/** At least this many `'caret'` annotations on the page. Defaults to 0. */
|
|
87
91
|
minCaretCount?: number;
|
|
88
92
|
/**
|
|
89
|
-
* `true` if the fixture has at least one
|
|
90
|
-
* 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.
|
|
91
95
|
*/
|
|
92
|
-
|
|
96
|
+
expectsInlineAnnotation: boolean;
|
|
93
97
|
}
|
|
94
98
|
interface AnnotationConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
95
99
|
fixture: AnnotationReadConformanceFixture;
|
|
@@ -103,7 +107,7 @@ interface ActionsConformanceFixtures {
|
|
|
103
107
|
annotation: ConformanceFixture;
|
|
104
108
|
field: ConformanceFixture;
|
|
105
109
|
/** `action_payloads.pdf` — every executable payload shape on one page of
|
|
106
|
-
* /NM-keyed links.
|
|
110
|
+
* /NM-keyed links. Required on both flavours: payload parity is a gate. */
|
|
107
111
|
payloads: ConformanceFixture;
|
|
108
112
|
/** `open_action_dest.pdf` — a destination-form catalog `/OpenAction`. */
|
|
109
113
|
openDestination: ConformanceFixture;
|
|
@@ -131,46 +135,37 @@ declare function runActionsConformance(runner: ConformanceTestRunner, opts: Acti
|
|
|
131
135
|
interface AnnotationMutationConformanceFixture extends ConformanceFixture {
|
|
132
136
|
/** PDF object number of the page used by the mutation tests. */
|
|
133
137
|
pageObjectNumber: number;
|
|
134
|
-
/**
|
|
135
|
-
|
|
138
|
+
/** The page has at least one annotation born inline (a dictionary in `/Annots`, no object number). */
|
|
139
|
+
expectsInlineAnnotation: boolean;
|
|
136
140
|
/**
|
|
137
|
-
* QuadPoints to use for the create() smoke test
|
|
138
|
-
*
|
|
139
|
-
*
|
|
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.
|
|
140
144
|
*/
|
|
141
145
|
createQuad?: HighlightDraft['quadPoints'];
|
|
142
146
|
/**
|
|
143
|
-
*
|
|
147
|
+
* The box to use for the shape (circle/square) create tests, in page
|
|
144
148
|
* space; pick a small box that fits anywhere on the fixture page.
|
|
145
149
|
*/
|
|
146
|
-
createShapeRect?:
|
|
150
|
+
createShapeRect?: PageBox;
|
|
147
151
|
/**
|
|
148
|
-
* `/Vertices` to use for the polygon/polyline create tests
|
|
149
|
-
* space; must fit inside `createShapeRect
|
|
150
|
-
* 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.
|
|
151
154
|
*/
|
|
152
|
-
createVertices?:
|
|
155
|
+
createVertices?: PagePoint[];
|
|
153
156
|
/**
|
|
154
|
-
* `/L` endpoints to use for the line create test
|
|
155
|
-
*
|
|
157
|
+
* `/L` endpoints to use for the line create test, in page space; must fit
|
|
158
|
+
* inside `createShapeRect`. Defaults to the rect's diagonal.
|
|
156
159
|
*/
|
|
157
|
-
createLinePoints?:
|
|
160
|
+
createLinePoints?: LineDraft['linePoints'];
|
|
158
161
|
/**
|
|
159
|
-
* `/InkList` strokes to use for the ink create test
|
|
162
|
+
* `/InkList` strokes to use for the ink create test, in page space; must
|
|
160
163
|
* fit inside `createShapeRect`. Defaults to a single short stroke.
|
|
161
164
|
*/
|
|
162
|
-
createInkList?:
|
|
165
|
+
createInkList?: InkDraft['inkList'];
|
|
163
166
|
}
|
|
164
167
|
interface AnnotationMutationConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
165
168
|
fixture: AnnotationMutationConformanceFixture;
|
|
166
|
-
/**
|
|
167
|
-
* `true` for engines that expose the raw RGBA appearance rasters
|
|
168
|
-
* (`renderAppearances`). When set, the shape-create test additionally
|
|
169
|
-
* asserts that creating a shape produces a baked `/AP` the appearance
|
|
170
|
-
* reader can rasterize. The cloud engine ships encoded images instead
|
|
171
|
-
* and leaves this `false`.
|
|
172
|
-
*/
|
|
173
|
-
supportsAppearanceRasters?: boolean;
|
|
174
169
|
}
|
|
175
170
|
/**
|
|
176
171
|
* Mutation conformance suite. Mirrors the read suite: tests are written
|
|
@@ -179,22 +174,220 @@ interface AnnotationMutationConformanceOptions extends Omit<ConformanceOptions,
|
|
|
179
174
|
* @cloudpdf/server) implementations must pass identically.
|
|
180
175
|
*
|
|
181
176
|
* The locked rules being verified here:
|
|
182
|
-
* - `create` is append-only:
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* - Opportunistic /NM stamp upgrades a weak annotation's ref to
|
|
188
|
-
* `kind: 'nm'` on update; an already-durable annotation's /NM is
|
|
189
|
-
* NEVER touched.
|
|
190
|
-
* - `delete` and `move` are the only index-shifting ops. They bump
|
|
191
|
-
* the per-page revision and, on a page that had weak refs before
|
|
192
|
-
* 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.
|
|
193
182
|
* - Abort propagates as `AbortError` even before the worker
|
|
194
183
|
* responds.
|
|
195
184
|
*/
|
|
196
185
|
declare function runAnnotationMutationConformance(runner: ConformanceTestRunner, opts: AnnotationMutationConformanceOptions): void;
|
|
197
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
|
|
198
391
|
//#region src/conformance/runFormConformance.d.ts
|
|
199
392
|
/**
|
|
200
393
|
* The three fixtures the forms suite needs. Shapes (names, object numbers,
|
|
@@ -206,7 +399,7 @@ declare function runAnnotationMutationConformance(runner: ConformanceTestRunner,
|
|
|
206
399
|
* `opt_check` (/Opt "Alpha", on-state "On"), hierarchical text field
|
|
207
400
|
* `billing.name`.
|
|
208
401
|
* - `orphanWidgets` — orphan_widgets.pdf: `linked_text` in /AcroForm
|
|
209
|
-
* /Fields plus
|
|
402
|
+
* /Fields plus recovered `orphan_check` and `orphan_radio`.
|
|
210
403
|
* - `choiceFields` — listbox_form.pdf: `Listbox_MultiSelect` (options
|
|
211
404
|
* Apple..), `Listbox_SingleSelect`.
|
|
212
405
|
*/
|
|
@@ -224,6 +417,12 @@ interface FormConformanceFixtures {
|
|
|
224
417
|
* same bytes under a suffixed id the way the bytes transport does.
|
|
225
418
|
*/
|
|
226
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;
|
|
227
426
|
}
|
|
228
427
|
interface FormConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
229
428
|
fixtures: FormConformanceFixtures;
|
|
@@ -235,7 +434,7 @@ declare function runFormConformance(runner: ConformanceTestRunner, opts: FormCon
|
|
|
235
434
|
* Per-fixture knowledge for the annotation appearance conformance suite. The
|
|
236
435
|
* harness asserts thresholds (not exact wire content) so the same suite runs
|
|
237
436
|
* unchanged against the local and cloud engines and proves they emit the same
|
|
238
|
-
* set of appearances
|
|
437
|
+
* set of appearances, including those of annotations born inline in the file.
|
|
239
438
|
*/
|
|
240
439
|
interface AnnotationAppearanceConformanceFixture extends ConformanceFixture {
|
|
241
440
|
/** PDF object number of the page whose appearances are rendered. */
|
|
@@ -243,21 +442,14 @@ interface AnnotationAppearanceConformanceFixture extends ConformanceFixture {
|
|
|
243
442
|
/** At least this many `/AP` appearances are expected on that page. */
|
|
244
443
|
minAppearanceCount: number;
|
|
245
444
|
/**
|
|
246
|
-
* `true` when the page has at least one
|
|
247
|
-
*
|
|
248
|
-
*
|
|
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.
|
|
249
448
|
*/
|
|
250
|
-
|
|
449
|
+
expectsInlineAppearance: boolean;
|
|
251
450
|
}
|
|
252
451
|
interface AnnotationAppearanceConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
253
452
|
fixture: AnnotationAppearanceConformanceFixture;
|
|
254
|
-
/**
|
|
255
|
-
* `true` for engines that expose the raw RGBA rasters (`renderAppearances`).
|
|
256
|
-
* The local engine's encoder needs a browser Canvas, so under node it can
|
|
257
|
-
* only be exercised via the raw rasters; the cloud engine ships encoded
|
|
258
|
-
* images (`renderAppearanceImages`) and leaves this `false`.
|
|
259
|
-
*/
|
|
260
|
-
supportsRawRasters?: boolean;
|
|
261
453
|
}
|
|
262
454
|
declare function runAnnotationAppearanceConformance(runner: ConformanceTestRunner, opts: AnnotationAppearanceConformanceOptions): void;
|
|
263
455
|
//#endregion
|
|
@@ -269,43 +461,32 @@ declare function runAnnotationAppearanceConformance(runner: ConformanceTestRunne
|
|
|
269
461
|
* harness can exercise reorder permutations meaningfully.
|
|
270
462
|
*/
|
|
271
463
|
interface PageReorderConformanceFixture extends ConformanceFixture {
|
|
272
|
-
/** Stable, durable
|
|
464
|
+
/** Stable, durable page object numbers of (at least) three distinct pages. Order
|
|
273
465
|
* here is the *intended caller-visible* order, not the on-disk
|
|
274
466
|
* order; the suite reads `pages.list()` first and works in document
|
|
275
467
|
* order. */
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Page used for the weak-ref-survival assertion. Defaults to the
|
|
279
|
-
* first PON in `ponsForReorderTest`. The fixture page must already
|
|
280
|
-
* have at least one weak annotation (no /NM, direct object) so the
|
|
281
|
-
* harness can capture an `index`-kind ref before the page move and
|
|
282
|
-
* re-use it after.
|
|
283
|
-
*/
|
|
284
|
-
weakRefHostPon?: number;
|
|
285
|
-
/** Quad to use for the `create()` step that produces a stable ref
|
|
286
|
-
* the suite uses. */
|
|
287
|
-
createQuad?: HighlightDraft['quadPoints'];
|
|
468
|
+
pageObjectNumbersForReorderTest?: number[];
|
|
288
469
|
}
|
|
289
470
|
interface PageReorderConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
290
471
|
fixture: PageReorderConformanceFixture;
|
|
291
472
|
}
|
|
292
473
|
/**
|
|
293
474
|
* Page reorder conformance suite. Verifies the architectural invariants
|
|
294
|
-
* locked with the user, do
|
|
295
|
-
* `
|
|
475
|
+
* locked with the user, do not loosen these without re-reading
|
|
476
|
+
* `PageReorderResult` and `DocumentPagesMutator`:
|
|
296
477
|
*
|
|
297
478
|
* 1. `pages.list()` returns every page in display order, addressed
|
|
298
479
|
* by indirect `pageObjectNumber`.
|
|
299
|
-
* 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
|
|
300
482
|
* `result.layout` (the same shape `pages.list()` returns). There is
|
|
301
483
|
* no document-level revision; the wire never asks the caller for one.
|
|
302
|
-
* 3.
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
* `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`.
|
|
309
490
|
* 5. Abort propagates as `AbortError`.
|
|
310
491
|
*
|
|
311
492
|
* Both local (worker host + WASM) and cloud (HTTP + @cloudpdf/server)
|
|
@@ -316,17 +497,17 @@ declare function runPageReorderConformance(runner: ConformanceTestRunner, opts:
|
|
|
316
497
|
//#region src/conformance/runPageRotateConformance.d.ts
|
|
317
498
|
/**
|
|
318
499
|
* Page rotate conformance suite. Verifies the architectural invariants —
|
|
319
|
-
* do
|
|
500
|
+
* do not loosen these without re-reading `PageRotateResult`:
|
|
320
501
|
*
|
|
321
|
-
* 1. Rotation is
|
|
502
|
+
* 1. Rotation is absolute and idempotent: `rotate(pons, 90)` twice is
|
|
322
503
|
* `rotate(pons, 90)` once. The wire never speaks "turn by".
|
|
323
|
-
* 2. Rotation is presentation metadata over
|
|
504
|
+
* 2. Rotation is presentation metadata over normalized content: the
|
|
324
505
|
* layout's `width`/`height` stay un-rotated, order and identity are
|
|
325
|
-
* untouched, and
|
|
326
|
-
*
|
|
506
|
+
* untouched, and annotation names survive (a `baseIndex` ref captured
|
|
507
|
+
* before the rotate works after it).
|
|
327
508
|
* 3. The result returns the full new `layout`; a subsequent `list()`
|
|
328
509
|
* agrees with it.
|
|
329
|
-
* 4. Invalid inputs (bad rotation value, duplicate
|
|
510
|
+
* 4. Invalid inputs (bad rotation value, duplicate page object numbers, unknown page object numbers)
|
|
330
511
|
* reject with `InvalidArg` / `NotFound`.
|
|
331
512
|
* 5. Abort propagates as `AbortError`.
|
|
332
513
|
*
|
|
@@ -335,20 +516,248 @@ declare function runPageReorderConformance(runner: ConformanceTestRunner, opts:
|
|
|
335
516
|
*/
|
|
336
517
|
declare function runPageRotateConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
337
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
|
|
338
747
|
//#region src/conformance/runPageDeleteConformance.d.ts
|
|
339
748
|
/**
|
|
340
749
|
* Page delete conformance suite. Verifies the architectural invariants —
|
|
341
|
-
* do
|
|
750
|
+
* do not loosen these without re-reading `PageDeleteResult`:
|
|
342
751
|
*
|
|
343
752
|
* 1. `pages.delete()` removes exactly the listed pages and returns the
|
|
344
753
|
* full surviving layout; a subsequent `list()` agrees.
|
|
345
|
-
* 2. Deleted
|
|
754
|
+
* 2. Deleted page object numbers are retired: addressing a deleted page afterwards is a
|
|
346
755
|
* clean `NotFound` (an API-level error, never native-memory danger).
|
|
347
|
-
* 3.
|
|
348
|
-
*
|
|
756
|
+
* 3. Surviving pages keep identity, and their annotations keep their
|
|
757
|
+
* names — a `baseIndex` ref survives a neighbour's deletion.
|
|
349
758
|
* 4. Deleting every page is rejected (`InvalidArg`) — a document keeps at
|
|
350
759
|
* least one page.
|
|
351
|
-
* 5. Duplicate / unknown
|
|
760
|
+
* 5. Duplicate / unknown page object numbers reject with `InvalidArg` / `NotFound`;
|
|
352
761
|
* abort propagates as `AbortError`.
|
|
353
762
|
*
|
|
354
763
|
* Both local (worker host + WASM) and cloud (HTTP + @cloudpdf/server)
|
|
@@ -358,7 +767,7 @@ declare function runPageDeleteConformance(runner: ConformanceTestRunner, opts: C
|
|
|
358
767
|
//#endregion
|
|
359
768
|
//#region src/conformance/runNamedPagesConformance.d.ts
|
|
360
769
|
/**
|
|
361
|
-
* Named-pages conformance: the catalog's `/Names /Pages` registry as
|
|
770
|
+
* Named-pages conformance: the catalog's `/Names /Pages` registry as layout
|
|
362
771
|
* data. Locks the invariants both engines must share — do not loosen
|
|
363
772
|
* without re-reading `NamedPageEntry` and `PageNameResult`:
|
|
364
773
|
*
|
|
@@ -366,7 +775,7 @@ declare function runPageDeleteConformance(runner: ConformanceTestRunner, opts: C
|
|
|
366
775
|
* registration resolves to a page in `pages`, a template, or is
|
|
367
776
|
* reported dangling — never silently dropped.
|
|
368
777
|
* 2. `pages.setName()` creates or replaces by decoded key (idempotent),
|
|
369
|
-
* `replace` renames in one job, and the result
|
|
778
|
+
* `replace` renames in one job, and the result is the new layout.
|
|
370
779
|
* 3. `pages.removeName()` drops the registration and nothing else.
|
|
371
780
|
* 4. Deleting a page removes every registration pointing at it — inside
|
|
372
781
|
* the delete, with no plugin in the loop.
|
|
@@ -393,7 +802,7 @@ declare function runAnnotationFlattenConformance(runner: ConformanceTestRunner,
|
|
|
393
802
|
//#region src/conformance/runAnnotationAppearanceExportConformance.d.ts
|
|
394
803
|
/**
|
|
395
804
|
* `page(pon).annotations.exportAppearance(refs)`: the chosen annotations'
|
|
396
|
-
* appearances as
|
|
805
|
+
* appearances as one single-page PDF sized to their union /Rect. Locks:
|
|
397
806
|
* 1. bytes are a PDF; the source page is untouched (no mutation, no
|
|
398
807
|
* revision bump);
|
|
399
808
|
* 2. re-opened (local engines), the page is exactly the union size and the
|
|
@@ -408,30 +817,39 @@ declare function runAnnotationAppearanceExportConformance(runner: ConformanceTes
|
|
|
408
817
|
declare function runPageFlattenConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
409
818
|
//#endregion
|
|
410
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
|
+
}
|
|
411
829
|
/**
|
|
412
830
|
* Transport-neutral coverage for the destructive redaction-apply rail.
|
|
413
|
-
* Runs against a fixture page with
|
|
831
|
+
* Runs against a fixture page with no pre-existing annotations so the
|
|
414
832
|
* collateral counts are exact. Content-removal fidelity itself is pinned by
|
|
415
833
|
* the native embeddertests; this suite pins the transport contract: scopes,
|
|
416
|
-
* statuses, counts,
|
|
834
|
+
* statuses, counts, affected pages, events, and preflight rejection.
|
|
417
835
|
*/
|
|
418
|
-
declare function runRedactionApplyConformance(runner: ConformanceTestRunner, opts:
|
|
836
|
+
declare function runRedactionApplyConformance(runner: ConformanceTestRunner, opts: RedactionApplyConformanceOptions): void;
|
|
419
837
|
//#endregion
|
|
420
838
|
//#region src/conformance/runPageExtractConformance.d.ts
|
|
421
839
|
/**
|
|
422
|
-
* Page extract conformance suite. `pages.extract?` is
|
|
840
|
+
* Page extract conformance suite. `pages.extract?` is optional on the
|
|
423
841
|
* contract (the `downloadLayer?` pattern) — the suite runs only when the
|
|
424
842
|
* implementation provides it, so a cloud engine that has not shipped the
|
|
425
843
|
* server endpoint yet skips cleanly instead of failing.
|
|
426
844
|
*
|
|
427
845
|
* Invariants:
|
|
428
846
|
* 1. `pages.extract([pon])` returns standalone PDF bytes (magic header).
|
|
429
|
-
* 2. The
|
|
847
|
+
* 2. The source document is untouched: identical layout before/after,
|
|
430
848
|
* and page revisions do not bump (extract is a read).
|
|
431
849
|
* 3. Caller order is preserved and page geometry survives the copy
|
|
432
850
|
* (asserted by re-opening the extracted bytes — bytes-open engines
|
|
433
851
|
* only, since a cloud engine cannot re-open loose bytes).
|
|
434
|
-
* 4. Empty / duplicate
|
|
852
|
+
* 4. Empty / duplicate page object numbers reject `InvalidArg`; unknown page object numbers reject
|
|
435
853
|
* `NotFound` (or `InvalidArg`); abort propagates as `AbortError`.
|
|
436
854
|
*/
|
|
437
855
|
declare function runPageExtractConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
@@ -439,12 +857,12 @@ declare function runPageExtractConformance(runner: ConformanceTestRunner, opts:
|
|
|
439
857
|
//#region src/conformance/runAttachmentConformance.d.ts
|
|
440
858
|
/**
|
|
441
859
|
* Attachment conformance suite. Fixture requirement: a document whose
|
|
442
|
-
* `/EmbeddedFiles` name tree contains
|
|
860
|
+
* `/EmbeddedFiles` name tree contains at least one embedded file.
|
|
443
861
|
*
|
|
444
|
-
* Both attachment surfaces are
|
|
862
|
+
* Both attachment surfaces are optional on the contract (the
|
|
445
863
|
* `downloadLayer?` pattern), probed independently and skipped cleanly:
|
|
446
864
|
* - `doc.attachments?` — document-level EmbeddedFiles (list/download)
|
|
447
|
-
* - `page.annotations.
|
|
865
|
+
* - `page.annotations.downloadResource(ref, 'file')` — annotation-level file bytes
|
|
448
866
|
*
|
|
449
867
|
* Invariants:
|
|
450
868
|
* 1. `list()` reflects the name tree: positional indices, non-empty
|
|
@@ -454,83 +872,335 @@ declare function runPageExtractConformance(runner: ConformanceTestRunner, opts:
|
|
|
454
872
|
* 3. Unknown indices reject with an `EngineError`.
|
|
455
873
|
* 4. A created file-attachment annotation round-trips its file:
|
|
456
874
|
* metadata inline on the DTO (never bytes), bytes byte-identical
|
|
457
|
-
*
|
|
875
|
+
* as its `file` resource.
|
|
458
876
|
* 5. A created text (sticky-note) annotation round-trips icon + color.
|
|
459
877
|
*/
|
|
460
878
|
declare function runAttachmentConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
461
879
|
//#endregion
|
|
462
880
|
//#region src/conformance/runPageInsertConformance.d.ts
|
|
463
|
-
/**
|
|
464
|
-
* Page insert conformance. `pages.insert` is a REQUIRED member — this suite
|
|
465
|
-
* runs unconditionally on every engine, so an implementation that loses the
|
|
466
|
-
* verb fails loudly instead of being skipped past.
|
|
467
|
-
*
|
|
468
|
-
* Invariants:
|
|
469
|
-
* 1. Every page of the source bytes is COPIED in at `destIndex` (omitted →
|
|
470
|
-
* append), in source order; the result lists the fresh PONs in
|
|
471
|
-
* insertion order and they agree with the returned layout.
|
|
472
|
-
* 2. Pre-existing pages keep their identity: same PONs before and after,
|
|
473
|
-
* in the expected positions (an insert never invalidates neighbours).
|
|
474
|
-
* 3. The mutation persists through save → re-open (bytes engines only).
|
|
475
|
-
* 4. Empty bytes / malformed bytes / out-of-range destIndex reject with
|
|
476
|
-
* InvalidArg / MalformedPdf, leaving the document untouched.
|
|
477
|
-
*/
|
|
478
881
|
declare function runPageInsertConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
479
882
|
//#endregion
|
|
480
883
|
//#region src/conformance/runPageInsertBlankConformance.d.ts
|
|
481
884
|
/**
|
|
482
|
-
* Blank-page insert conformance. `pages.insertBlank` is a
|
|
885
|
+
* Blank-page insert conformance. `pages.insertBlank` is a required member —
|
|
483
886
|
* the suite runs unconditionally on every engine (no fixture bytes are
|
|
484
887
|
* needed at all, which is the point of the verb), so an implementation that
|
|
485
888
|
* loses the verb fails loudly instead of being skipped past.
|
|
486
889
|
*
|
|
487
890
|
* Invariants:
|
|
488
|
-
* 1. `count` blank pages of exactly `size` appear at `
|
|
489
|
-
* → 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
|
|
490
893
|
* order and they agree with the returned layout.
|
|
491
|
-
* 2. Pre-existing pages keep their identity: same
|
|
894
|
+
* 2. Pre-existing pages keep their identity: same page object numbers before and after,
|
|
492
895
|
* in the expected positions (an insert never invalidates neighbours).
|
|
493
896
|
* 3. The mutation persists through save → re-open (bytes engines only).
|
|
494
897
|
* 4. Non-positive size / count outside [1, PAGE_INSERT_BLANK_MAX_COUNT] /
|
|
495
|
-
* out-of-range
|
|
898
|
+
* out-of-range toIndex reject with InvalidArg, leaving the document
|
|
496
899
|
* untouched.
|
|
497
900
|
*/
|
|
498
901
|
declare function runPageInsertBlankConformance(runner: ConformanceTestRunner, opts: ConformanceOptions): void;
|
|
499
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
|
|
500
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
|
+
}
|
|
501
1171
|
/**
|
|
502
|
-
* `/PieceInfo` conformance (doc + page level)
|
|
503
|
-
*
|
|
504
|
-
* implementation provides it, so an engine that has not shipped it yet
|
|
505
|
-
* skips cleanly.
|
|
1172
|
+
* `/PieceInfo` conformance (doc + page level), on the local engine: the
|
|
1173
|
+
* only one with `/PieceInfo`.
|
|
506
1174
|
*
|
|
507
1175
|
* Invariants:
|
|
508
1176
|
* 1. The full value vocabulary round-trips at both levels: string,
|
|
509
1177
|
* number, boolean, name, string-array — read back with the same tags.
|
|
510
|
-
* 2. Writes
|
|
511
|
-
* engines only, since cloud cannot re-open loose bytes).
|
|
1178
|
+
* 2. Writes persist: download() → re-open → identical read.
|
|
512
1179
|
* 3. `null` deletes a key; sibling keys and sibling applications
|
|
513
1180
|
* survive both key deletes and whole-entry clears.
|
|
514
1181
|
* 4. An absent application reads as `null`; `applications()` enumerates
|
|
515
|
-
* what is present; every write refreshes `
|
|
1182
|
+
* what is present; every write refreshes `modifiedAt`.
|
|
516
1183
|
*/
|
|
517
|
-
declare function runPieceInfoConformance(runner: ConformanceTestRunner, opts:
|
|
1184
|
+
declare function runPieceInfoConformance(runner: ConformanceTestRunner, opts: PieceInfoConformanceOptions): void;
|
|
518
1185
|
//#endregion
|
|
519
1186
|
//#region src/conformance/runDocumentEventsConformance.d.ts
|
|
520
1187
|
/**
|
|
521
1188
|
* Document event stream conformance suite. Verifies the invariants the
|
|
522
|
-
* collaboration design rests on — do
|
|
1189
|
+
* collaboration design rests on — do not loosen these without re-reading
|
|
523
1190
|
* `DocumentEvent`:
|
|
524
1191
|
*
|
|
525
|
-
* 1.
|
|
1192
|
+
* 1. Exactly once: every confirmed mutation produces exactly one event,
|
|
526
1193
|
* in mutation order, regardless of engine (local worker or cloud HTTP).
|
|
527
|
-
* 2.
|
|
1194
|
+
* 2. Ground truth: a failed mutation publishes nothing; events fire only
|
|
528
1195
|
* after confirmation.
|
|
529
|
-
* 3.
|
|
1196
|
+
* 3. Results ride verbatim: each event embeds the result the caller
|
|
530
1197
|
* received, deep-equal field for field.
|
|
531
|
-
* 4.
|
|
532
|
-
*
|
|
533
|
-
* 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.
|
|
534
1204
|
*
|
|
535
1205
|
* Both local (worker host + WASM) and cloud (HTTP + @cloudpdf/server)
|
|
536
1206
|
* implementations must pass identically.
|
|
@@ -564,11 +1234,11 @@ declare function runPageTextConformance(runner: ConformanceTestRunner, opts: Pag
|
|
|
564
1234
|
//#endregion
|
|
565
1235
|
//#region src/conformance/runTextDivergenceConformance.d.ts
|
|
566
1236
|
/**
|
|
567
|
-
* Index-space divergence conformance: the cases where a page's
|
|
1237
|
+
* Index-space divergence conformance: the cases where a page's character
|
|
568
1238
|
* space (what geometry tiles and selection/search ranges address) and its
|
|
569
|
-
* extracted
|
|
1239
|
+
* extracted text differ — and the `charMap` contract that bridges them.
|
|
570
1240
|
*
|
|
571
|
-
* Fixtures pin
|
|
1241
|
+
* Fixtures pin exact values (text, charCount, anchors) verified against the
|
|
572
1242
|
* wasm runtime, so both engines must produce byte-identical snapshots:
|
|
573
1243
|
*
|
|
574
1244
|
* - a non-printing character occupying a character slot with no text unit
|
|
@@ -577,17 +1247,17 @@ declare function runPageTextConformance(runner: ConformanceTestRunner, opts: Pag
|
|
|
577
1247
|
* characters in lockstep with the text, identity map, real segments);
|
|
578
1248
|
* - supplementary-plane text via a ToUnicode surrogate pair
|
|
579
1249
|
* (`embedpdf_astral_tounicode.pdf` — two lockstep surrogate entries,
|
|
580
|
-
* identity map, astral content
|
|
1250
|
+
* identity map, astral content survives extraction).
|
|
581
1251
|
*
|
|
582
|
-
* The search probe closes the loop: a hit's `
|
|
583
|
-
*
|
|
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
|
|
584
1254
|
* hit's range must reproduce the matched text exactly — the law that makes
|
|
585
1255
|
* select-this-match and copy compose.
|
|
586
1256
|
*/
|
|
587
1257
|
interface TextDivergenceConformanceFixture extends ConformanceFixture {
|
|
588
1258
|
/** PDF indirect object number of the probed page. */
|
|
589
1259
|
pageObjectNumber: number;
|
|
590
|
-
/** The
|
|
1260
|
+
/** The exact extracted text (UTF-16 faithful). */
|
|
591
1261
|
exactText: string;
|
|
592
1262
|
/** The character-space size (may differ from `exactText.length`). */
|
|
593
1263
|
expectedCharCount: number;
|
|
@@ -595,15 +1265,15 @@ interface TextDivergenceConformanceFixture extends ConformanceFixture {
|
|
|
595
1265
|
expectedCharMap: ReadonlyArray<CharMapAnchor> | null;
|
|
596
1266
|
/** Char-space slice expectations (half-open). */
|
|
597
1267
|
slices?: ReadonlyArray<{
|
|
598
|
-
|
|
599
|
-
|
|
1268
|
+
start: number;
|
|
1269
|
+
count: number;
|
|
600
1270
|
text: string;
|
|
601
1271
|
}>;
|
|
602
|
-
/** Literal search probe with expected
|
|
1272
|
+
/** Literal search probe with expected character-space hit range. */
|
|
603
1273
|
search?: {
|
|
604
1274
|
query: string;
|
|
605
|
-
|
|
606
|
-
|
|
1275
|
+
start: number;
|
|
1276
|
+
count: number;
|
|
607
1277
|
matchedText: string;
|
|
608
1278
|
};
|
|
609
1279
|
}
|
|
@@ -617,7 +1287,7 @@ type TextDivergenceCase = Omit<TextDivergenceConformanceFixture, 'id' | 'bytes'
|
|
|
617
1287
|
resource: string;
|
|
618
1288
|
};
|
|
619
1289
|
/**
|
|
620
|
-
*
|
|
1290
|
+
* The pinned divergence cases — one table, consumed by both engines' suites
|
|
621
1291
|
* so expected values cannot drift. Values verified against the wasm runtime
|
|
622
1292
|
* (see each case). All fixtures are single-page; the page's indirect object
|
|
623
1293
|
* number is 3 in each.
|
|
@@ -641,7 +1311,7 @@ interface PageGeometryOrientationFixture extends ConformanceFixture {
|
|
|
641
1311
|
kind: 'empty-only';
|
|
642
1312
|
} | {
|
|
643
1313
|
kind: 'rotated';
|
|
644
|
-
/**
|
|
1314
|
+
/** Turns (degrees clockwise) rotated runs may carry. */
|
|
645
1315
|
rotations: number[];
|
|
646
1316
|
ascentFlip: boolean;
|
|
647
1317
|
/**
|
|
@@ -681,21 +1351,16 @@ interface SearchConformanceOptions extends Omit<ConformanceOptions, 'fixture'> {
|
|
|
681
1351
|
}
|
|
682
1352
|
declare function runSearchConformance(runner: ConformanceTestRunner, opts: SearchConformanceOptions): void;
|
|
683
1353
|
//#endregion
|
|
684
|
-
//#region src/conformance/
|
|
1354
|
+
//#region src/conformance/diffAnnotationList.d.ts
|
|
685
1355
|
/**
|
|
686
1356
|
* Returns a list of human-readable difference strings between two
|
|
687
|
-
*
|
|
688
|
-
* that local and cloud emit identical
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
* should be 0 for fresh reads on both sides). Page order is no longer part
|
|
693
|
-
* of `PageState`; it lives in `PageLayout.index` (see `pages.list()`).
|
|
694
|
-
* `auditHead` is likewise not compared: it is a cloud-only reconciliation
|
|
695
|
-
* 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.
|
|
696
1362
|
*/
|
|
697
|
-
declare function
|
|
698
|
-
declare function diffAnnotationListSnapshotAll(a: AnnotationListSnapshotAllPages, b: AnnotationListSnapshotAllPages): string[];
|
|
1363
|
+
declare function diffAnnotationList(a: AnnotationList, b: AnnotationList): string[];
|
|
699
1364
|
//#endregion
|
|
700
1365
|
//#region src/conformance/runSignatureConformance.d.ts
|
|
701
1366
|
interface SignatureConformanceFixtures {
|
|
@@ -744,12 +1409,12 @@ interface SignatureConformanceOptions {
|
|
|
744
1409
|
fixtures: SignatureConformanceFixtures;
|
|
745
1410
|
}
|
|
746
1411
|
/**
|
|
747
|
-
* Digital signatures, read side. The service is
|
|
1412
|
+
* Digital signatures, read side. The service is optional on the contract
|
|
748
1413
|
* (`downloadLayer?` pattern) — the suite runs only where the engine
|
|
749
1414
|
* provides it.
|
|
750
1415
|
*
|
|
751
1416
|
* Invariants:
|
|
752
|
-
* 1. Byte facts describe the
|
|
1417
|
+
* 1. Byte facts describe the loaded bytes: a revision is a byte prefix,
|
|
753
1418
|
* a whole-revision signature seals exactly one, the digest over its
|
|
754
1419
|
* `/ByteRange` is what the file's bytes hash to, and an unsaved edit
|
|
755
1420
|
* changes none of it.
|
|
@@ -764,5 +1429,103 @@ interface SignatureConformanceOptions {
|
|
|
764
1429
|
*/
|
|
765
1430
|
declare function runSignatureConformance(runner: ConformanceTestRunner, opts: SignatureConformanceOptions): void;
|
|
766
1431
|
//#endregion
|
|
767
|
-
|
|
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 };
|
|
768
1531
|
//# sourceMappingURL=conformance.d.ts.map
|