@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.
Files changed (134) hide show
  1. package/dist/AnnotationList-CkijRHet.d.cts +27163 -0
  2. package/dist/AnnotationList-CkijRHet.d.ts +27163 -0
  3. package/dist/Change-CKoxfTNY.js +889 -0
  4. package/dist/Change-CKoxfTNY.js.map +1 -0
  5. package/dist/Change-CjImsrN0.cjs +1020 -0
  6. package/dist/Change-CjImsrN0.cjs.map +1 -0
  7. package/dist/DocumentRenderService-BfFdFSwI.cjs +120 -0
  8. package/dist/DocumentRenderService-BfFdFSwI.cjs.map +1 -0
  9. package/dist/DocumentRenderService-DV3J9lMz.js +85 -0
  10. package/dist/DocumentRenderService-DV3J9lMz.js.map +1 -0
  11. package/dist/{DocumentSecurityService-Ca6EK3-3.d.ts → DocumentSecurityService-CU1M6Q7m.d.ts} +100 -112
  12. package/dist/{DocumentSecurityService-CIx1MT0T.d.cts → DocumentSecurityService-e6vp2de8.d.cts} +100 -112
  13. package/dist/LocalDocumentHandle-D02FMm-Z.cjs +53 -0
  14. package/dist/LocalDocumentHandle-D02FMm-Z.cjs.map +1 -0
  15. package/dist/LocalDocumentHandle-DAPdaOt_.js +30 -0
  16. package/dist/LocalDocumentHandle-DAPdaOt_.js.map +1 -0
  17. package/dist/LocalEngine-DFoBm4B3.d.cts +1565 -0
  18. package/dist/LocalEngine-DPriFujS.d.ts +1565 -0
  19. package/dist/PageInsertBlankInput-CXHAM7l6.cjs +17 -0
  20. package/dist/PageInsertBlankInput-CXHAM7l6.cjs.map +1 -0
  21. package/dist/PageInsertBlankInput-DhVYVJ_S.js +12 -0
  22. package/dist/PageInsertBlankInput-DhVYVJ_S.js.map +1 -0
  23. package/dist/authority-B3BklsB4.js +2239 -0
  24. package/dist/authority-B3BklsB4.js.map +1 -0
  25. package/dist/{viewport-BWeNHZmb.cjs → authority-DLMNR7ff.cjs} +820 -1647
  26. package/dist/authority-DLMNR7ff.cjs.map +1 -0
  27. package/dist/builders-CNj0POeY.js +161 -0
  28. package/dist/builders-CNj0POeY.js.map +1 -0
  29. package/dist/builders-Cgdp_YCn.cjs +184 -0
  30. package/dist/builders-Cgdp_YCn.cjs.map +1 -0
  31. package/dist/calibrate-7T3fnP8-.js +2404 -0
  32. package/dist/calibrate-7T3fnP8-.js.map +1 -0
  33. package/dist/calibrate-DJBXnhLE.cjs +2919 -0
  34. package/dist/calibrate-DJBXnhLE.cjs.map +1 -0
  35. package/dist/charmap-Cprti1ta.js +239 -0
  36. package/dist/charmap-Cprti1ta.js.map +1 -0
  37. package/dist/charmap-aYlefQP9.cjs +304 -0
  38. package/dist/charmap-aYlefQP9.cjs.map +1 -0
  39. package/dist/conformance.cjs +16466 -5247
  40. package/dist/conformance.cjs.map +1 -1
  41. package/dist/conformance.d.cts +924 -165
  42. package/dist/conformance.d.ts +924 -165
  43. package/dist/conformance.js +16429 -5252
  44. package/dist/conformance.js.map +1 -1
  45. package/dist/format-Bp3QFSH1.cjs +574 -0
  46. package/dist/format-Bp3QFSH1.cjs.map +1 -0
  47. package/dist/format-Dgg428Kb.js +461 -0
  48. package/dist/format-Dgg428Kb.js.map +1 -0
  49. package/dist/index.cjs +323 -116
  50. package/dist/index.d.cts +2 -2
  51. package/dist/index.d.ts +2 -2
  52. package/dist/index.js +14 -5
  53. package/dist/pageRefs-B3ur7Ckm.cjs +51 -0
  54. package/dist/pageRefs-B3ur7Ckm.cjs.map +1 -0
  55. package/dist/pageRefs-DkbuxSCV.js +40 -0
  56. package/dist/pageRefs-DkbuxSCV.js.map +1 -0
  57. package/dist/public.cjs +57 -0
  58. package/dist/public.d.cts +5 -0
  59. package/dist/public.d.ts +5 -0
  60. package/dist/public.js +9 -0
  61. package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs +3646 -0
  62. package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs.map +1 -0
  63. package/dist/resolveAnnotationDraft-CUpf0SMh.js +3167 -0
  64. package/dist/resolveAnnotationDraft-CUpf0SMh.js.map +1 -0
  65. package/dist/{resolver-inAVzsWt.js → resolver-CzxmD9Ck.js} +294 -144
  66. package/dist/resolver-CzxmD9Ck.js.map +1 -0
  67. package/dist/{resolver-CYVNV4hn.cjs → resolver-D2OCtE8F.cjs} +347 -143
  68. package/dist/resolver-D2OCtE8F.cjs.map +1 -0
  69. package/dist/runtime-Cl0v56mm.d.ts +2032 -0
  70. package/dist/runtime-p1WDzDo4.d.cts +2032 -0
  71. package/dist/runtime.cjs +726 -297
  72. package/dist/runtime.cjs.map +1 -1
  73. package/dist/runtime.d.cts +5 -1372
  74. package/dist/runtime.d.ts +5 -1372
  75. package/dist/runtime.js +396 -179
  76. package/dist/runtime.js.map +1 -1
  77. package/dist/schema-C-gU4vj7.cjs +3034 -0
  78. package/dist/schema-C-gU4vj7.cjs.map +1 -0
  79. package/dist/schema-DzlUNk38.js +2081 -0
  80. package/dist/schema-DzlUNk38.js.map +1 -0
  81. package/dist/schemas-Berf1swF.cjs +2481 -0
  82. package/dist/schemas-Berf1swF.cjs.map +1 -0
  83. package/dist/schemas-D6xOGjqg.js +1654 -0
  84. package/dist/schemas-D6xOGjqg.js.map +1 -0
  85. package/dist/subtype-CG4WpIRj.js +129 -0
  86. package/dist/subtype-CG4WpIRj.js.map +1 -0
  87. package/dist/subtype-aDt5TFmK.cjs +158 -0
  88. package/dist/subtype-aDt5TFmK.cjs.map +1 -0
  89. package/dist/validation.cjs +578 -0
  90. package/dist/validation.cjs.map +1 -0
  91. package/dist/validation.d.cts +174 -0
  92. package/dist/validation.d.ts +174 -0
  93. package/dist/validation.js +571 -0
  94. package/dist/validation.js.map +1 -0
  95. package/dist/value-BFS1R8ek.cjs +435 -0
  96. package/dist/value-BFS1R8ek.cjs.map +1 -0
  97. package/dist/value-Dhc8eYcx.js +340 -0
  98. package/dist/value-Dhc8eYcx.js.map +1 -0
  99. package/dist/viewport-BJW13EGZ.js +540 -0
  100. package/dist/viewport-BJW13EGZ.js.map +1 -0
  101. package/dist/viewport-DlL5Bxbg.cjs +671 -0
  102. package/dist/viewport-DlL5Bxbg.cjs.map +1 -0
  103. package/dist/wire.cjs +1051 -397
  104. package/dist/wire.cjs.map +1 -1
  105. package/dist/wire.d.cts +12403 -790
  106. package/dist/wire.d.ts +12403 -790
  107. package/dist/wire.js +821 -242
  108. package/dist/wire.js.map +1 -1
  109. package/package.json +10 -1
  110. package/dist/AbortError-DwuHPK_I.js +0 -27
  111. package/dist/AbortError-DwuHPK_I.js.map +0 -1
  112. package/dist/AbortError-P0RU0Mgg.cjs +0 -38
  113. package/dist/AbortError-P0RU0Mgg.cjs.map +0 -1
  114. package/dist/AnnotationListSnapshot-D9R5n2Kf.d.cts +0 -7101
  115. package/dist/AnnotationListSnapshot-D9R5n2Kf.d.ts +0 -7101
  116. package/dist/Engine-EWWHhEIi.d.ts +0 -1277
  117. package/dist/Engine-FNaAEjfb.d.cts +0 -1277
  118. package/dist/derive-BbsDk_Kz.cjs +0 -880
  119. package/dist/derive-BbsDk_Kz.cjs.map +0 -1
  120. package/dist/derive-DAFJolWu.js +0 -647
  121. package/dist/derive-DAFJolWu.js.map +0 -1
  122. package/dist/format-Bbphf4zR.js +0 -435
  123. package/dist/format-Bbphf4zR.js.map +0 -1
  124. package/dist/format-D_epWlob.cjs +0 -518
  125. package/dist/format-D_epWlob.cjs.map +0 -1
  126. package/dist/resolver-CYVNV4hn.cjs.map +0 -1
  127. package/dist/resolver-inAVzsWt.js.map +0 -1
  128. package/dist/schemas-CFQGvWiu.js +0 -3243
  129. package/dist/schemas-CFQGvWiu.js.map +0 -1
  130. package/dist/schemas-D0g6tKa9.cjs +0 -4694
  131. package/dist/schemas-D0g6tKa9.cjs.map +0 -1
  132. package/dist/viewport-BWeNHZmb.cjs.map +0 -1
  133. package/dist/viewport-CvMcadfQ.js +0 -3072
  134. 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