@embedpdf/engine-core 3.0.0-next.14 → 3.0.0-next.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AnnotationList-CkijRHet.d.cts +27163 -0
- package/dist/AnnotationList-CkijRHet.d.ts +27163 -0
- package/dist/Change-CKoxfTNY.js +889 -0
- package/dist/Change-CKoxfTNY.js.map +1 -0
- package/dist/Change-CjImsrN0.cjs +1020 -0
- package/dist/Change-CjImsrN0.cjs.map +1 -0
- package/dist/DocumentRenderService-BfFdFSwI.cjs +120 -0
- package/dist/DocumentRenderService-BfFdFSwI.cjs.map +1 -0
- package/dist/DocumentRenderService-DV3J9lMz.js +85 -0
- package/dist/DocumentRenderService-DV3J9lMz.js.map +1 -0
- package/dist/{DocumentSecurityService-Ca6EK3-3.d.ts → DocumentSecurityService-CU1M6Q7m.d.ts} +100 -112
- package/dist/{DocumentSecurityService-CIx1MT0T.d.cts → DocumentSecurityService-e6vp2de8.d.cts} +100 -112
- package/dist/LocalDocumentHandle-D02FMm-Z.cjs +53 -0
- package/dist/LocalDocumentHandle-D02FMm-Z.cjs.map +1 -0
- package/dist/LocalDocumentHandle-DAPdaOt_.js +30 -0
- package/dist/LocalDocumentHandle-DAPdaOt_.js.map +1 -0
- package/dist/LocalEngine-DFoBm4B3.d.cts +1565 -0
- package/dist/LocalEngine-DPriFujS.d.ts +1565 -0
- package/dist/PageInsertBlankInput-CXHAM7l6.cjs +17 -0
- package/dist/PageInsertBlankInput-CXHAM7l6.cjs.map +1 -0
- package/dist/PageInsertBlankInput-DhVYVJ_S.js +12 -0
- package/dist/PageInsertBlankInput-DhVYVJ_S.js.map +1 -0
- package/dist/authority-B3BklsB4.js +2239 -0
- package/dist/authority-B3BklsB4.js.map +1 -0
- package/dist/{viewport-BWeNHZmb.cjs → authority-DLMNR7ff.cjs} +820 -1647
- package/dist/authority-DLMNR7ff.cjs.map +1 -0
- package/dist/builders-CNj0POeY.js +161 -0
- package/dist/builders-CNj0POeY.js.map +1 -0
- package/dist/builders-Cgdp_YCn.cjs +184 -0
- package/dist/builders-Cgdp_YCn.cjs.map +1 -0
- package/dist/calibrate-7T3fnP8-.js +2404 -0
- package/dist/calibrate-7T3fnP8-.js.map +1 -0
- package/dist/calibrate-DJBXnhLE.cjs +2919 -0
- package/dist/calibrate-DJBXnhLE.cjs.map +1 -0
- package/dist/charmap-Cprti1ta.js +239 -0
- package/dist/charmap-Cprti1ta.js.map +1 -0
- package/dist/charmap-aYlefQP9.cjs +304 -0
- package/dist/charmap-aYlefQP9.cjs.map +1 -0
- package/dist/conformance.cjs +16466 -5247
- package/dist/conformance.cjs.map +1 -1
- package/dist/conformance.d.cts +924 -165
- package/dist/conformance.d.ts +924 -165
- package/dist/conformance.js +16429 -5252
- package/dist/conformance.js.map +1 -1
- package/dist/format-Bp3QFSH1.cjs +574 -0
- package/dist/format-Bp3QFSH1.cjs.map +1 -0
- package/dist/format-Dgg428Kb.js +461 -0
- package/dist/format-Dgg428Kb.js.map +1 -0
- package/dist/index.cjs +323 -116
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -5
- package/dist/pageRefs-B3ur7Ckm.cjs +51 -0
- package/dist/pageRefs-B3ur7Ckm.cjs.map +1 -0
- package/dist/pageRefs-DkbuxSCV.js +40 -0
- package/dist/pageRefs-DkbuxSCV.js.map +1 -0
- package/dist/public.cjs +57 -0
- package/dist/public.d.cts +5 -0
- package/dist/public.d.ts +5 -0
- package/dist/public.js +9 -0
- package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs +3646 -0
- package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs.map +1 -0
- package/dist/resolveAnnotationDraft-CUpf0SMh.js +3167 -0
- package/dist/resolveAnnotationDraft-CUpf0SMh.js.map +1 -0
- package/dist/{resolver-inAVzsWt.js → resolver-CzxmD9Ck.js} +294 -144
- package/dist/resolver-CzxmD9Ck.js.map +1 -0
- package/dist/{resolver-CYVNV4hn.cjs → resolver-D2OCtE8F.cjs} +347 -143
- package/dist/resolver-D2OCtE8F.cjs.map +1 -0
- package/dist/runtime-Cl0v56mm.d.ts +2032 -0
- package/dist/runtime-p1WDzDo4.d.cts +2032 -0
- package/dist/runtime.cjs +726 -297
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +5 -1372
- package/dist/runtime.d.ts +5 -1372
- package/dist/runtime.js +396 -179
- package/dist/runtime.js.map +1 -1
- package/dist/schema-C-gU4vj7.cjs +3034 -0
- package/dist/schema-C-gU4vj7.cjs.map +1 -0
- package/dist/schema-DzlUNk38.js +2081 -0
- package/dist/schema-DzlUNk38.js.map +1 -0
- package/dist/schemas-Berf1swF.cjs +2481 -0
- package/dist/schemas-Berf1swF.cjs.map +1 -0
- package/dist/schemas-D6xOGjqg.js +1654 -0
- package/dist/schemas-D6xOGjqg.js.map +1 -0
- package/dist/subtype-CG4WpIRj.js +129 -0
- package/dist/subtype-CG4WpIRj.js.map +1 -0
- package/dist/subtype-aDt5TFmK.cjs +158 -0
- package/dist/subtype-aDt5TFmK.cjs.map +1 -0
- package/dist/validation.cjs +578 -0
- package/dist/validation.cjs.map +1 -0
- package/dist/validation.d.cts +174 -0
- package/dist/validation.d.ts +174 -0
- package/dist/validation.js +571 -0
- package/dist/validation.js.map +1 -0
- package/dist/value-BFS1R8ek.cjs +435 -0
- package/dist/value-BFS1R8ek.cjs.map +1 -0
- package/dist/value-Dhc8eYcx.js +340 -0
- package/dist/value-Dhc8eYcx.js.map +1 -0
- package/dist/viewport-BJW13EGZ.js +540 -0
- package/dist/viewport-BJW13EGZ.js.map +1 -0
- package/dist/viewport-DlL5Bxbg.cjs +671 -0
- package/dist/viewport-DlL5Bxbg.cjs.map +1 -0
- package/dist/wire.cjs +1051 -397
- package/dist/wire.cjs.map +1 -1
- package/dist/wire.d.cts +12403 -790
- package/dist/wire.d.ts +12403 -790
- package/dist/wire.js +821 -242
- package/dist/wire.js.map +1 -1
- package/package.json +10 -1
- package/dist/AbortError-DwuHPK_I.js +0 -27
- package/dist/AbortError-DwuHPK_I.js.map +0 -1
- package/dist/AbortError-P0RU0Mgg.cjs +0 -38
- package/dist/AbortError-P0RU0Mgg.cjs.map +0 -1
- package/dist/AnnotationListSnapshot-D9R5n2Kf.d.cts +0 -7101
- package/dist/AnnotationListSnapshot-D9R5n2Kf.d.ts +0 -7101
- package/dist/Engine-EWWHhEIi.d.ts +0 -1277
- package/dist/Engine-FNaAEjfb.d.cts +0 -1277
- package/dist/derive-BbsDk_Kz.cjs +0 -880
- package/dist/derive-BbsDk_Kz.cjs.map +0 -1
- package/dist/derive-DAFJolWu.js +0 -647
- package/dist/derive-DAFJolWu.js.map +0 -1
- package/dist/format-Bbphf4zR.js +0 -435
- package/dist/format-Bbphf4zR.js.map +0 -1
- package/dist/format-D_epWlob.cjs +0 -518
- package/dist/format-D_epWlob.cjs.map +0 -1
- package/dist/resolver-CYVNV4hn.cjs.map +0 -1
- package/dist/resolver-inAVzsWt.js.map +0 -1
- package/dist/schemas-CFQGvWiu.js +0 -3243
- package/dist/schemas-CFQGvWiu.js.map +0 -1
- package/dist/schemas-D0g6tKa9.cjs +0 -4694
- package/dist/schemas-D0g6tKa9.cjs.map +0 -1
- package/dist/viewport-BWeNHZmb.cjs.map +0 -1
- package/dist/viewport-CvMcadfQ.js +0 -3072
- package/dist/viewport-CvMcadfQ.js.map +0 -1
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
const require_resolveAnnotationDraft = require("./resolveAnnotationDraft-7Ke4nV7F.cjs");
|
|
2
|
+
const require_format = require("./format-Bp3QFSH1.cjs");
|
|
3
|
+
const require_calibrate = require("./calibrate-DJBXnhLE.cjs");
|
|
4
|
+
//#region src/promise/AbortablePromise.ts
|
|
5
|
+
let _Symbol$species;
|
|
6
|
+
_Symbol$species = Symbol.species;
|
|
7
|
+
/**
|
|
8
|
+
* Awaitable Promise subclass with abort and progress.
|
|
9
|
+
*
|
|
10
|
+
* Symbol.species returns plain Promise so chained .then/.catch/.finally
|
|
11
|
+
* return regular promises and never try to synthesize a new
|
|
12
|
+
* AbortablePromise (which would have no executor).
|
|
13
|
+
*
|
|
14
|
+
* Settlement contract:
|
|
15
|
+
* - The first settlement wins. resolve/reject handed to the executor
|
|
16
|
+
* are wrapped so that any subsequent call (whether by the executor,
|
|
17
|
+
* by abort(), or by both racing) becomes a silent no-op.
|
|
18
|
+
* - abort() rejects the public promise with AbortError immediately,
|
|
19
|
+
* even if the executor never observes the AbortSignal. The executor
|
|
20
|
+
* still receives the AbortSignal so it can stop real work
|
|
21
|
+
* cooperatively (release a queue slot, abort fetch, post a worker
|
|
22
|
+
* abort, etc.). Anything the executor does after that — including
|
|
23
|
+
* a late resolve(value), a late reject(error), or a rejected inner
|
|
24
|
+
* Promise inside AbortablePromise.run — is dropped silently.
|
|
25
|
+
* - abort() after settlement is a no-op.
|
|
26
|
+
*/
|
|
27
|
+
var AbortablePromise = class AbortablePromise extends Promise {
|
|
28
|
+
static get [_Symbol$species]() {
|
|
29
|
+
return Promise;
|
|
30
|
+
}
|
|
31
|
+
constructor(executor) {
|
|
32
|
+
const ctrl = new AbortController();
|
|
33
|
+
const progressCbs = /* @__PURE__ */ new Set();
|
|
34
|
+
const state = { settled: false };
|
|
35
|
+
let capturedReject;
|
|
36
|
+
super((resolve, reject) => {
|
|
37
|
+
capturedReject = reject;
|
|
38
|
+
const wrappedResolve = (value) => {
|
|
39
|
+
if (state.settled) return;
|
|
40
|
+
state.settled = true;
|
|
41
|
+
resolve(value);
|
|
42
|
+
};
|
|
43
|
+
const wrappedReject = (reason) => {
|
|
44
|
+
if (state.settled) return;
|
|
45
|
+
state.settled = true;
|
|
46
|
+
reject(reason);
|
|
47
|
+
};
|
|
48
|
+
const progress = (p) => {
|
|
49
|
+
if (state.settled) return;
|
|
50
|
+
for (const cb of progressCbs) try {
|
|
51
|
+
cb(p);
|
|
52
|
+
} catch {}
|
|
53
|
+
};
|
|
54
|
+
executor(wrappedResolve, wrappedReject, progress, ctrl.signal);
|
|
55
|
+
});
|
|
56
|
+
require_format._defineProperty(this, "signal", void 0);
|
|
57
|
+
require_format._defineProperty(this, "_ctrl", void 0);
|
|
58
|
+
require_format._defineProperty(this, "_progressCbs", void 0);
|
|
59
|
+
require_format._defineProperty(this, "_state", void 0);
|
|
60
|
+
require_format._defineProperty(this, "_internalReject", void 0);
|
|
61
|
+
this._ctrl = ctrl;
|
|
62
|
+
this.signal = ctrl.signal;
|
|
63
|
+
this._progressCbs = progressCbs;
|
|
64
|
+
this._state = state;
|
|
65
|
+
this._internalReject = capturedReject;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Abort the underlying operation.
|
|
69
|
+
*
|
|
70
|
+
* - If the promise has already settled, this is a no-op.
|
|
71
|
+
* - Otherwise the public promise rejects synchronously with an
|
|
72
|
+
* AbortError (wrapping the supplied reason if it is not already an
|
|
73
|
+
* AbortError) and the AbortSignal fires for any cooperative
|
|
74
|
+
* cancellation the executor wired up.
|
|
75
|
+
*/
|
|
76
|
+
abort(reason) {
|
|
77
|
+
if (this._state.settled) return;
|
|
78
|
+
if (this._ctrl.signal.aborted) return;
|
|
79
|
+
const err = reason instanceof require_calibrate.AbortError ? reason : new require_calibrate.AbortError(reason);
|
|
80
|
+
this._state.settled = true;
|
|
81
|
+
this._ctrl.abort(err);
|
|
82
|
+
this._internalReject(err);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Abort this call when `signal` aborts, at once if it already has: the
|
|
86
|
+
* bridge to code that cancels with an `AbortController` (a framework's
|
|
87
|
+
* cleanup, a `fetch`). The listener is removed when the call settles.
|
|
88
|
+
* Returns this promise, so `await call().abortWith(signal)` reads as one.
|
|
89
|
+
*/
|
|
90
|
+
abortWith(signal) {
|
|
91
|
+
if (signal.aborted) {
|
|
92
|
+
this.abort(signal.reason);
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
const onAbort = () => this.abort(signal.reason);
|
|
96
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
97
|
+
const detach = () => signal.removeEventListener("abort", onAbort);
|
|
98
|
+
Promise.prototype.then.call(this, detach, detach);
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Subscribe to progress events. Returns an unsubscribe function.
|
|
103
|
+
*
|
|
104
|
+
* @internal No engine method reports progress today; this is plumbing for
|
|
105
|
+
* one that will, typed then per method. Not part of the public contract.
|
|
106
|
+
*/
|
|
107
|
+
onProgress(cb) {
|
|
108
|
+
this._progressCbs.add(cb);
|
|
109
|
+
return () => {
|
|
110
|
+
this._progressCbs.delete(cb);
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Wrap a value in an already-resolved AbortablePromise. Mirrors Promise.resolve.
|
|
115
|
+
*/
|
|
116
|
+
static resolveValue(value) {
|
|
117
|
+
return new AbortablePromise((resolve) => resolve(value));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Wrap a thrown reason in an already-rejected AbortablePromise.
|
|
121
|
+
*/
|
|
122
|
+
static rejectReason(reason) {
|
|
123
|
+
return new AbortablePromise((_resolve, reject) => reject(reason));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Run an async function as an AbortablePromise so callers get .abort() and .signal.
|
|
127
|
+
* The async function receives the AbortSignal (and a progress emitter) so it can
|
|
128
|
+
* cooperate with the abort.
|
|
129
|
+
*
|
|
130
|
+
* If abort() fires while the inner async function is still running, the
|
|
131
|
+
* public promise rejects with AbortError immediately. The inner async
|
|
132
|
+
* function's eventual settlement (resolve or reject) is funneled through
|
|
133
|
+
* the wrapped settlers and silently dropped — including a late rejection
|
|
134
|
+
* from the underlying work, which prevents an UnhandledRejection because
|
|
135
|
+
* the .then(resolve, reject) below "handles" it via the no-op.
|
|
136
|
+
*/
|
|
137
|
+
static run(fn) {
|
|
138
|
+
return new AbortablePromise((resolve, reject, progress, signal) => {
|
|
139
|
+
fn(signal, progress).then(resolve, reject);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/identity/ObjectNumbers.ts
|
|
145
|
+
/**
|
|
146
|
+
* The highest object number a document should reach: Acrobat documents
|
|
147
|
+
* 8,388,607 objects per file, and the interoperable rule keeps every object
|
|
148
|
+
* number at or below it. A write that would pass it is refused with
|
|
149
|
+
* `LayerFull`.
|
|
150
|
+
*/
|
|
151
|
+
const OBJECT_NUMBER_CEILING = 8388607;
|
|
152
|
+
/**
|
|
153
|
+
* The last object number handed out to sessions: issuing stops here, which
|
|
154
|
+
* leaves the numbers above it to the objects the engine makes for itself
|
|
155
|
+
* (appearance streams, fonts) until the ceiling.
|
|
156
|
+
*/
|
|
157
|
+
const OBJECT_NUMBER_ISSUE_LIMIT = 8e6;
|
|
158
|
+
/**
|
|
159
|
+
* Runs of numbers as an HTTP header value, inclusive like an HTTP `Range`:
|
|
160
|
+
* `1003-1035, 2040-2042` (`EmbedPDF-Object-Numbers`).
|
|
161
|
+
*/
|
|
162
|
+
function formatObjectNumberRanges(ranges) {
|
|
163
|
+
return ranges.map(({ first, count }) => `${first}-${first + count - 1}`).join(", ");
|
|
164
|
+
}
|
|
165
|
+
/** The runs a {@link formatObjectNumberRanges} header value names; `[]` for one that names none. */
|
|
166
|
+
function parseObjectNumberRanges(value) {
|
|
167
|
+
const ranges = [];
|
|
168
|
+
for (const part of (value ?? "").split(",")) {
|
|
169
|
+
const match = /^\s*(\d+)-(\d+)\s*$/.exec(part);
|
|
170
|
+
if (!match) continue;
|
|
171
|
+
const first = Number(match[1]);
|
|
172
|
+
const last = Number(match[2]);
|
|
173
|
+
if (last >= first) ranges.push({
|
|
174
|
+
first,
|
|
175
|
+
count: last - first + 1
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return ranges;
|
|
179
|
+
}
|
|
180
|
+
/** Every number in `ranges`, in order. */
|
|
181
|
+
function objectNumbersIn(ranges) {
|
|
182
|
+
const numbers = [];
|
|
183
|
+
for (const { first, count } of ranges) for (let i = 0; i < count; i++) numbers.push(first + i);
|
|
184
|
+
return numbers;
|
|
185
|
+
}
|
|
186
|
+
/** The manifest's keys, in the order a file writes them. */
|
|
187
|
+
const FORM_BUNDLE_KEYS = [
|
|
188
|
+
"format",
|
|
189
|
+
"version",
|
|
190
|
+
"pages",
|
|
191
|
+
"fields",
|
|
192
|
+
"widgets",
|
|
193
|
+
"calculationOrder"
|
|
194
|
+
];
|
|
195
|
+
/** The resource roles a widget names: none yet. */
|
|
196
|
+
const WIDGET_RESOURCE_ROLES = [];
|
|
197
|
+
const BUNDLE_FIELDS = [...FORM_BUNDLE_KEYS, "resources"];
|
|
198
|
+
const FIELD_ROW_FIELDS = ["data"];
|
|
199
|
+
const WIDGET_ROW_FIELDS = ["data", "resources"];
|
|
200
|
+
/**
|
|
201
|
+
* Check a bundle before anything uses it, the checks cheapest first: its
|
|
202
|
+
* format, its counts and sizes against `limits` (`PayloadTooLarge`), its
|
|
203
|
+
* shape and references (`InvalidArg`), then every resource against its id.
|
|
204
|
+
*/
|
|
205
|
+
async function assertFormBundle(bundle, limits = require_calibrate.DEFAULT_BUNDLE_LIMITS) {
|
|
206
|
+
const resources = require_resolveAnnotationDraft.isRecord(bundle?.resources) ? bundle.resources : require_resolveAnnotationDraft.invalidBundle("form", "no resources");
|
|
207
|
+
const sizes = /* @__PURE__ */ new Map();
|
|
208
|
+
for (const [id, bytes] of Object.entries(resources)) {
|
|
209
|
+
if (!(bytes instanceof Uint8Array)) require_resolveAnnotationDraft.invalidBundle("form", `resource ${id} is not bytes`);
|
|
210
|
+
sizes.set(id, bytes.length);
|
|
211
|
+
}
|
|
212
|
+
assertFormBundleManifest(bundle, sizes, limits);
|
|
213
|
+
await require_resolveAnnotationDraft.assertResourceIds("form", resources);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* The checks that need no resource bytes, only their sizes by id: format
|
|
217
|
+
* and version, counts, sizes, the shape of pages, fields and widgets, and
|
|
218
|
+
* that widgets and resources name each other exactly. That a widget's field
|
|
219
|
+
* is among the bundle's is the import's to decide: one that isn't is left
|
|
220
|
+
* out.
|
|
221
|
+
*/
|
|
222
|
+
function assertFormBundleManifest(manifest, resourceSizes, limits) {
|
|
223
|
+
if (!require_resolveAnnotationDraft.isRecord(manifest)) require_resolveAnnotationDraft.invalidBundle("form", "not a form bundle");
|
|
224
|
+
require_resolveAnnotationDraft.assertKnownFields("form", "the bundle", manifest, BUNDLE_FIELDS);
|
|
225
|
+
if (manifest.format !== "embedpdf/form") require_resolveAnnotationDraft.invalidBundle("form", `unknown format ${JSON.stringify(manifest.format)}`);
|
|
226
|
+
if (manifest.version !== 1) require_resolveAnnotationDraft.invalidBundle("form", `unknown version ${JSON.stringify(manifest.version)}`);
|
|
227
|
+
const { pages, fields, widgets, calculationOrder } = manifest;
|
|
228
|
+
if (!Array.isArray(pages)) require_resolveAnnotationDraft.invalidBundle("form", "pages is not a list");
|
|
229
|
+
if (!Array.isArray(fields)) require_resolveAnnotationDraft.invalidBundle("form", "fields is not a list");
|
|
230
|
+
if (!Array.isArray(widgets)) require_resolveAnnotationDraft.invalidBundle("form", "widgets is not a list");
|
|
231
|
+
if (!Array.isArray(calculationOrder)) require_resolveAnnotationDraft.invalidBundle("form", "calculationOrder is not a list");
|
|
232
|
+
require_calibrate.assertWithinLimit("form", limits, "items", fields.length + widgets.length);
|
|
233
|
+
require_calibrate.assertWithinLimit("form", limits, "pages", pages.length);
|
|
234
|
+
require_calibrate.assertWithinLimit("form", limits, "resources", resourceSizes.size);
|
|
235
|
+
let bundleBytes = require_calibrate.manifestBytesOf({
|
|
236
|
+
pages,
|
|
237
|
+
fields,
|
|
238
|
+
widgets,
|
|
239
|
+
calculationOrder
|
|
240
|
+
});
|
|
241
|
+
require_calibrate.assertWithinLimit("form", limits, "manifestBytes", bundleBytes);
|
|
242
|
+
for (const size of resourceSizes.values()) {
|
|
243
|
+
require_calibrate.assertWithinLimit("form", limits, "resourceBytes", size);
|
|
244
|
+
bundleBytes += size;
|
|
245
|
+
}
|
|
246
|
+
require_calibrate.assertWithinLimit("form", limits, "bundleBytes", bundleBytes);
|
|
247
|
+
const pageKeys = require_resolveAnnotationDraft.assertBundlePages("form", pages);
|
|
248
|
+
fields.forEach((row, index) => {
|
|
249
|
+
if (!require_resolveAnnotationDraft.isRecord(row) || !require_resolveAnnotationDraft.isRecord(row.data) || typeof row.data.family !== "string" || typeof row.data.name !== "string" || !require_resolveAnnotationDraft.isRecord(row.data.ref)) require_resolveAnnotationDraft.invalidBundle("form", `field ${index} has no field data`);
|
|
250
|
+
require_resolveAnnotationDraft.assertKnownFields("form", `field ${index}`, row, FIELD_ROW_FIELDS);
|
|
251
|
+
});
|
|
252
|
+
const named = /* @__PURE__ */ new Set();
|
|
253
|
+
widgets.forEach((row, index) => {
|
|
254
|
+
if (!require_resolveAnnotationDraft.isRecord(row) || !require_resolveAnnotationDraft.isRecord(row.data) || row.data.subtype !== "widget") require_resolveAnnotationDraft.invalidBundle("form", `widget ${index} has no widget data`);
|
|
255
|
+
require_resolveAnnotationDraft.assertKnownFields("form", `widget ${index}`, row, WIDGET_ROW_FIELDS);
|
|
256
|
+
const ref = row.data.ref;
|
|
257
|
+
const page = require_resolveAnnotationDraft.isRecord(ref) ? ref.page : void 0;
|
|
258
|
+
if (!require_resolveAnnotationDraft.isBundlePageRef(page) || !pageKeys.has(require_format.encodePageKey(page))) require_resolveAnnotationDraft.invalidBundle("form", `widget ${index} is on a page the bundle doesn't list`);
|
|
259
|
+
require_resolveAnnotationDraft.assertRowResources("form", `widget ${index}`, row.resources, WIDGET_RESOURCE_ROLES, resourceSizes, named);
|
|
260
|
+
});
|
|
261
|
+
calculationOrder.forEach((ref, index) => {
|
|
262
|
+
if (!require_resolveAnnotationDraft.isRecord(ref)) require_resolveAnnotationDraft.invalidBundle("form", `calculation order entry ${index} is not a field ref`);
|
|
263
|
+
});
|
|
264
|
+
require_resolveAnnotationDraft.assertResourcesNamed("form", "widget", resourceSizes, named);
|
|
265
|
+
}
|
|
266
|
+
//#endregion
|
|
267
|
+
//#region src/transfer/FormTransfer.ts
|
|
268
|
+
/**
|
|
269
|
+
* A form bundle as one JSON file, each resource in base64: a bundle whole,
|
|
270
|
+
* to store or download. HTTP carries bundles as multipart instead, without
|
|
271
|
+
* the third base64 adds.
|
|
272
|
+
*/
|
|
273
|
+
const FormTransfer = require_calibrate.bundleCodec({
|
|
274
|
+
kind: "form",
|
|
275
|
+
keys: FORM_BUNDLE_KEYS,
|
|
276
|
+
assertManifest: assertFormBundleManifest
|
|
277
|
+
});
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/search/literal.ts
|
|
280
|
+
/**
|
|
281
|
+
* The fold flavor a literal query needs. Haystack and needle must be
|
|
282
|
+
* folded with the same options; corpus caches key their pre-folded text
|
|
283
|
+
* on this (the default `{}` fold is the persistable one — non-default
|
|
284
|
+
* queries fold the original page text at query time).
|
|
285
|
+
*/
|
|
286
|
+
function foldOptionsFor(query) {
|
|
287
|
+
return {
|
|
288
|
+
keepCase: !!query.matchCase,
|
|
289
|
+
keepMarks: !!query.matchDiacritics,
|
|
290
|
+
dropWhitespace: !!query.ignoreWhitespace
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
const WORD_UNIT = /[\p{L}\p{N}_]/u;
|
|
294
|
+
const MARK = /\p{M}/u;
|
|
295
|
+
/** Whether the code point ending at `index` (exclusive) is a word char. */
|
|
296
|
+
function wordBefore(text, index) {
|
|
297
|
+
if (index <= 0) return false;
|
|
298
|
+
const unit = text.charCodeAt(index - 1);
|
|
299
|
+
const start = unit >= 56320 && unit <= 57343 && index >= 2 ? index - 2 : index - 1;
|
|
300
|
+
return WORD_UNIT.test(String.fromCodePoint(text.codePointAt(start)));
|
|
301
|
+
}
|
|
302
|
+
/** Whether the code point starting at `index` is a word char. */
|
|
303
|
+
function wordAt(text, index) {
|
|
304
|
+
if (index >= text.length) return false;
|
|
305
|
+
return WORD_UNIT.test(String.fromCodePoint(text.codePointAt(index)));
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Whether the folded hit at `at` sits on word boundaries. Checked on the
|
|
309
|
+
* folded plane, except under `ignoreWhitespace`: dropping whitespace glues
|
|
310
|
+
* neighbouring words together ("i n v o i c e 42" folds to "invoice42"), so there the
|
|
311
|
+
* boundaries are read off the original text around the mapped range.
|
|
312
|
+
*/
|
|
313
|
+
function isWholeWordHit(haystack, at, needleLength, query) {
|
|
314
|
+
if (!query.ignoreWhitespace) return !wordBefore(haystack.folded, at) && !wordAt(haystack.folded, at + needleLength);
|
|
315
|
+
const { start, count } = require_calibrate.toOriginalRange(haystack, at, needleLength);
|
|
316
|
+
return !wordBefore(haystack.original, start) && !wordAt(haystack.original, start + count);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* All non-overlapping literal matches, in original code-unit space.
|
|
320
|
+
* `haystack` must have been folded with `foldOptionsFor(query)`.
|
|
321
|
+
*/
|
|
322
|
+
function matchLiteral(haystack, query) {
|
|
323
|
+
const needle = require_calibrate.foldText(query.text, foldOptionsFor(query)).folded;
|
|
324
|
+
if (needle.trim().length === 0) return [];
|
|
325
|
+
const out = [];
|
|
326
|
+
let from = 0;
|
|
327
|
+
while (from <= haystack.folded.length - needle.length) {
|
|
328
|
+
const at = haystack.folded.indexOf(needle, from);
|
|
329
|
+
if (at < 0) break;
|
|
330
|
+
if (query.wholeWord && !isWholeWordHit(haystack, at, needle.length, query)) {
|
|
331
|
+
from = at + 1;
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (query.matchDiacritics && at + needle.length < haystack.folded.length) {
|
|
335
|
+
const after = haystack.folded.codePointAt(at + needle.length);
|
|
336
|
+
if (MARK.test(String.fromCodePoint(after))) {
|
|
337
|
+
from = at + 1;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
out.push(require_calibrate.toOriginalRange(haystack, at, needle.length));
|
|
342
|
+
from = at + needle.length;
|
|
343
|
+
}
|
|
344
|
+
return out;
|
|
345
|
+
}
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/search/regex.ts
|
|
348
|
+
/**
|
|
349
|
+
* The portable search-regex dialect: JavaScript `u`-mode syntax minus the
|
|
350
|
+
* features RE2 refuses (backreferences, lookaround). The local engine
|
|
351
|
+
* executes patterns with JS `RegExp`; the server executes the same
|
|
352
|
+
* pattern with RE2, whose linear-time guarantee is the ReDoS defense.
|
|
353
|
+
* Restricting both sides to the common subset keeps one query string
|
|
354
|
+
* valid — and equally powerful — everywhere.
|
|
355
|
+
*/
|
|
356
|
+
const SEARCH_REGEX_MAX_LENGTH = 512;
|
|
357
|
+
/**
|
|
358
|
+
* Validate a pattern against the dialect. Cheap and dependency-free —
|
|
359
|
+
* viewers call it on keystroke for early feedback; engines re-validate
|
|
360
|
+
* and reject bad patterns with `InvalidArg`.
|
|
361
|
+
*/
|
|
362
|
+
function validateSearchRegex(pattern) {
|
|
363
|
+
if (pattern.length === 0) return {
|
|
364
|
+
ok: false,
|
|
365
|
+
issue: "empty",
|
|
366
|
+
message: "Pattern is empty."
|
|
367
|
+
};
|
|
368
|
+
if (pattern.length > 512) return {
|
|
369
|
+
ok: false,
|
|
370
|
+
issue: "too-long",
|
|
371
|
+
message: `Pattern exceeds 512 characters.`
|
|
372
|
+
};
|
|
373
|
+
let inClass = false;
|
|
374
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
375
|
+
const ch = pattern[i];
|
|
376
|
+
if (ch === "\\") {
|
|
377
|
+
const next = pattern[i + 1] ?? "";
|
|
378
|
+
if (!inClass && next >= "1" && next <= "9") return {
|
|
379
|
+
ok: false,
|
|
380
|
+
issue: "backreference",
|
|
381
|
+
message: `Backreference \\${next} is not supported.`
|
|
382
|
+
};
|
|
383
|
+
if (!inClass && next === "k" && pattern[i + 2] === "<") return {
|
|
384
|
+
ok: false,
|
|
385
|
+
issue: "backreference",
|
|
386
|
+
message: "Named backreferences (\\k<…>) are not supported."
|
|
387
|
+
};
|
|
388
|
+
i++;
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (inClass) {
|
|
392
|
+
if (ch === "]") inClass = false;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (ch === "[") {
|
|
396
|
+
inClass = true;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (ch === "(" && pattern[i + 1] === "?") {
|
|
400
|
+
const tag = pattern[i + 2] ?? "";
|
|
401
|
+
if (tag === "=" || tag === "!") return {
|
|
402
|
+
ok: false,
|
|
403
|
+
issue: "lookaround",
|
|
404
|
+
message: "Lookahead ((?=…), (?!…)) is not supported."
|
|
405
|
+
};
|
|
406
|
+
if (tag === "<" && (pattern[i + 3] === "=" || pattern[i + 3] === "!")) return {
|
|
407
|
+
ok: false,
|
|
408
|
+
issue: "lookaround",
|
|
409
|
+
message: "Lookbehind ((?<=…), (?<!…)) is not supported."
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
414
|
+
new RegExp(pattern, "mu");
|
|
415
|
+
} catch (error) {
|
|
416
|
+
return {
|
|
417
|
+
ok: false,
|
|
418
|
+
issue: "syntax",
|
|
419
|
+
message: error.message
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
return { ok: true };
|
|
423
|
+
}
|
|
424
|
+
function validateSearchQuery(query) {
|
|
425
|
+
if (!query.regex) return { ok: true };
|
|
426
|
+
if (query.matchDiacritics) return {
|
|
427
|
+
ok: false,
|
|
428
|
+
issue: "diacritics-with-regex",
|
|
429
|
+
message: "Diacritic-sensitive matching is not available for regex patterns (regex runs on the raw text plane)."
|
|
430
|
+
};
|
|
431
|
+
if (query.ignoreWhitespace) return {
|
|
432
|
+
ok: false,
|
|
433
|
+
issue: "ignore-whitespace-with-regex",
|
|
434
|
+
message: "Whitespace-insensitive matching is not available for regex patterns (regex runs on the raw text plane; use \\s* in the pattern)."
|
|
435
|
+
};
|
|
436
|
+
return validateSearchRegex(query.text);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* All matches of a dialect-valid pattern over the raw page text (regex
|
|
440
|
+
* does not run against folded text — case handling is the `i` flag, and
|
|
441
|
+
* diacritic folding never applies). `wholeWord` is a boundary POST-filter
|
|
442
|
+
* using the same Unicode word test as the literal path — never `\b`,
|
|
443
|
+
* whose ASCII word set would give the toggle different semantics in regex
|
|
444
|
+
* mode ("caf" whole-word matching inside "café"). Filtering after the
|
|
445
|
+
* match also survives the move to RE2 server-side. Zero-length matches
|
|
446
|
+
* are skipped: search UI cannot highlight nothing, and skipping them is
|
|
447
|
+
* also the infinite-loop guard for patterns like `a*`.
|
|
448
|
+
*/
|
|
449
|
+
function matchRegex(text, query) {
|
|
450
|
+
const valid = validateSearchQuery({
|
|
451
|
+
...query,
|
|
452
|
+
regex: true
|
|
453
|
+
});
|
|
454
|
+
if (!valid.ok) throw new Error(`Invalid search query (${valid.issue}): ${valid.message}`);
|
|
455
|
+
const re = new RegExp(query.text, query.matchCase ? "gmu" : "gimu");
|
|
456
|
+
const out = [];
|
|
457
|
+
let m;
|
|
458
|
+
while ((m = re.exec(text)) !== null) {
|
|
459
|
+
if (m[0].length === 0) {
|
|
460
|
+
const unit = text.charCodeAt(re.lastIndex);
|
|
461
|
+
re.lastIndex += unit >= 55296 && unit <= 56319 ? 2 : 1;
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
if (query.wholeWord && (wordBefore(text, m.index) || wordAt(text, m.index + m[0].length))) continue;
|
|
465
|
+
out.push({
|
|
466
|
+
start: m.index,
|
|
467
|
+
count: m[0].length
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
return out;
|
|
471
|
+
}
|
|
472
|
+
//#endregion
|
|
473
|
+
//#region src/mutation/ListPosition.ts
|
|
474
|
+
/** The neighbour a position names, or `null` for `'start'` and `'end'`. */
|
|
475
|
+
function anchorOf(position) {
|
|
476
|
+
if (position === "start" || position === "end") return null;
|
|
477
|
+
return "before" in position ? position.before : position.after;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Where `position` falls in `order`: the index the first row placed there
|
|
481
|
+
* gets. The neighbour must be in `order` (`NotFound` otherwise).
|
|
482
|
+
*/
|
|
483
|
+
function positionIndex(order, position, keyOf) {
|
|
484
|
+
if (position === "start") return 0;
|
|
485
|
+
if (position === "end") return order.length;
|
|
486
|
+
const anchor = anchorOf(position);
|
|
487
|
+
const at = order.findIndex((ref) => keyOf(ref) === keyOf(anchor));
|
|
488
|
+
if (at < 0) throw new require_format.EngineError(require_format.EngineErrorCode.NotFound, `no neighbour ${keyOf(anchor)} in the list`, { details: { field: "position" } });
|
|
489
|
+
return "before" in position ? at : at + 1;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* A list's order once `moved` go to `position`, together and in the order
|
|
493
|
+
* given: what a reorder answers, worked out as the engine does. Every moved
|
|
494
|
+
* row must be in `order`, once (`InvalidArg` otherwise), and the neighbour
|
|
495
|
+
* can't be one of them (`InvalidArg`).
|
|
496
|
+
*/
|
|
497
|
+
function reorderedList(order, moved, position, keyOf) {
|
|
498
|
+
const movedKeys = new Set(moved.map(keyOf));
|
|
499
|
+
if (movedKeys.size !== moved.length) throw new require_format.EngineError(require_format.EngineErrorCode.InvalidArg, "a row is named twice", { details: { field: "refs" } });
|
|
500
|
+
const present = new Set(order.map(keyOf));
|
|
501
|
+
const missing = moved.find((ref) => !present.has(keyOf(ref)));
|
|
502
|
+
if (missing !== void 0) throw new require_format.EngineError(require_format.EngineErrorCode.NotFound, `no row ${keyOf(missing)} in the list`, { details: { field: "refs" } });
|
|
503
|
+
const anchor = anchorOf(position);
|
|
504
|
+
if (anchor !== null && movedKeys.has(keyOf(anchor))) throw new require_format.EngineError(require_format.EngineErrorCode.InvalidArg, `the neighbour ${keyOf(anchor)} is one of the rows that move`, { details: { field: "position" } });
|
|
505
|
+
const staying = order.filter((ref) => !movedKeys.has(keyOf(ref)));
|
|
506
|
+
const at = positionIndex(staying, position, keyOf);
|
|
507
|
+
return [
|
|
508
|
+
...staying.slice(0, at),
|
|
509
|
+
...moved,
|
|
510
|
+
...staying.slice(at)
|
|
511
|
+
];
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* `list` with the items `inPart` picks put in the order `order` gives them,
|
|
515
|
+
* by key, in the slots those items have: every other item keeps its place.
|
|
516
|
+
* How a list holding several pages takes one page's new order. Items of the
|
|
517
|
+
* part `order` doesn't name follow the named ones, in their order.
|
|
518
|
+
*/
|
|
519
|
+
function reorderPart(list, inPart, order, keyOf) {
|
|
520
|
+
const part = list.filter(inPart);
|
|
521
|
+
const byKey = new Map(part.map((item) => [keyOf(item), item]));
|
|
522
|
+
const named = order.flatMap((key) => byKey.has(key) ? [byKey.get(key)] : []);
|
|
523
|
+
const placed = new Set(named);
|
|
524
|
+
const next = [...named, ...part.filter((item) => !placed.has(item))];
|
|
525
|
+
let slot = 0;
|
|
526
|
+
return list.map((item) => inPart(item) ? next[slot++] : item);
|
|
527
|
+
}
|
|
528
|
+
//#endregion
|
|
529
|
+
//#region src/measure/viewport.ts
|
|
530
|
+
/**
|
|
531
|
+
* The last viewport whose box holds `point` (the one drawn on top), or
|
|
532
|
+
* `undefined`. A foreign measure still wins; never guess a fallback.
|
|
533
|
+
*/
|
|
534
|
+
function viewportForPoint(viewports, point) {
|
|
535
|
+
return [...viewports].reverse().find(({ bbox: b }) => point.x >= b.x && point.x <= b.x + b.width && point.y >= b.y && point.y <= b.y + b.height);
|
|
536
|
+
}
|
|
537
|
+
//#endregion
|
|
538
|
+
Object.defineProperty(exports, "AbortablePromise", {
|
|
539
|
+
enumerable: true,
|
|
540
|
+
get: function() {
|
|
541
|
+
return AbortablePromise;
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
Object.defineProperty(exports, "FormTransfer", {
|
|
545
|
+
enumerable: true,
|
|
546
|
+
get: function() {
|
|
547
|
+
return FormTransfer;
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
Object.defineProperty(exports, "OBJECT_NUMBER_CEILING", {
|
|
551
|
+
enumerable: true,
|
|
552
|
+
get: function() {
|
|
553
|
+
return OBJECT_NUMBER_CEILING;
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
Object.defineProperty(exports, "OBJECT_NUMBER_ISSUE_LIMIT", {
|
|
557
|
+
enumerable: true,
|
|
558
|
+
get: function() {
|
|
559
|
+
return OBJECT_NUMBER_ISSUE_LIMIT;
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
Object.defineProperty(exports, "SEARCH_REGEX_MAX_LENGTH", {
|
|
563
|
+
enumerable: true,
|
|
564
|
+
get: function() {
|
|
565
|
+
return SEARCH_REGEX_MAX_LENGTH;
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
Object.defineProperty(exports, "anchorOf", {
|
|
569
|
+
enumerable: true,
|
|
570
|
+
get: function() {
|
|
571
|
+
return anchorOf;
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
Object.defineProperty(exports, "assertFormBundle", {
|
|
575
|
+
enumerable: true,
|
|
576
|
+
get: function() {
|
|
577
|
+
return assertFormBundle;
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
Object.defineProperty(exports, "assertFormBundleManifest", {
|
|
581
|
+
enumerable: true,
|
|
582
|
+
get: function() {
|
|
583
|
+
return assertFormBundleManifest;
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
Object.defineProperty(exports, "foldOptionsFor", {
|
|
587
|
+
enumerable: true,
|
|
588
|
+
get: function() {
|
|
589
|
+
return foldOptionsFor;
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
Object.defineProperty(exports, "formatObjectNumberRanges", {
|
|
593
|
+
enumerable: true,
|
|
594
|
+
get: function() {
|
|
595
|
+
return formatObjectNumberRanges;
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
Object.defineProperty(exports, "matchLiteral", {
|
|
599
|
+
enumerable: true,
|
|
600
|
+
get: function() {
|
|
601
|
+
return matchLiteral;
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
Object.defineProperty(exports, "matchRegex", {
|
|
605
|
+
enumerable: true,
|
|
606
|
+
get: function() {
|
|
607
|
+
return matchRegex;
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
Object.defineProperty(exports, "objectNumbersIn", {
|
|
611
|
+
enumerable: true,
|
|
612
|
+
get: function() {
|
|
613
|
+
return objectNumbersIn;
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
Object.defineProperty(exports, "parseObjectNumberRanges", {
|
|
617
|
+
enumerable: true,
|
|
618
|
+
get: function() {
|
|
619
|
+
return parseObjectNumberRanges;
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
Object.defineProperty(exports, "positionIndex", {
|
|
623
|
+
enumerable: true,
|
|
624
|
+
get: function() {
|
|
625
|
+
return positionIndex;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
Object.defineProperty(exports, "reorderPart", {
|
|
629
|
+
enumerable: true,
|
|
630
|
+
get: function() {
|
|
631
|
+
return reorderPart;
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
Object.defineProperty(exports, "reorderedList", {
|
|
635
|
+
enumerable: true,
|
|
636
|
+
get: function() {
|
|
637
|
+
return reorderedList;
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
Object.defineProperty(exports, "validateSearchQuery", {
|
|
641
|
+
enumerable: true,
|
|
642
|
+
get: function() {
|
|
643
|
+
return validateSearchQuery;
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
Object.defineProperty(exports, "validateSearchRegex", {
|
|
647
|
+
enumerable: true,
|
|
648
|
+
get: function() {
|
|
649
|
+
return validateSearchRegex;
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
Object.defineProperty(exports, "viewportForPoint", {
|
|
653
|
+
enumerable: true,
|
|
654
|
+
get: function() {
|
|
655
|
+
return viewportForPoint;
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
Object.defineProperty(exports, "wordAt", {
|
|
659
|
+
enumerable: true,
|
|
660
|
+
get: function() {
|
|
661
|
+
return wordAt;
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
Object.defineProperty(exports, "wordBefore", {
|
|
665
|
+
enumerable: true,
|
|
666
|
+
get: function() {
|
|
667
|
+
return wordBefore;
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
//# sourceMappingURL=viewport-DlL5Bxbg.cjs.map
|