@laminapdf/viewer 0.2.0-alpha.2 → 0.2.0-alpha.4
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/README.md +107 -7
- package/dist/client.d.ts +51 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +94 -30
- package/dist/client.js.map +1 -1
- package/dist/find/controller.d.ts +73 -0
- package/dist/find/controller.d.ts.map +1 -0
- package/dist/find/controller.js +227 -0
- package/dist/find/controller.js.map +1 -0
- package/dist/find/fold.d.ts +23 -0
- package/dist/find/fold.d.ts.map +1 -0
- package/dist/find/fold.js +99 -0
- package/dist/find/fold.js.map +1 -0
- package/dist/find/page.d.ts +44 -0
- package/dist/find/page.d.ts.map +1 -0
- package/dist/find/page.js +173 -0
- package/dist/find/page.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/layers/box.d.ts +10 -0
- package/dist/layers/box.d.ts.map +1 -0
- package/dist/layers/box.js +19 -0
- package/dist/layers/box.js.map +1 -0
- package/dist/layers/highlight-layer.d.ts +31 -0
- package/dist/layers/highlight-layer.d.ts.map +1 -0
- package/dist/layers/highlight-layer.js +95 -0
- package/dist/layers/highlight-layer.js.map +1 -0
- package/dist/layers/spans.d.ts +42 -0
- package/dist/layers/spans.d.ts.map +1 -0
- package/dist/layers/spans.js +121 -0
- package/dist/layers/spans.js.map +1 -0
- package/dist/layers/structure-layer.d.ts +15 -0
- package/dist/layers/structure-layer.d.ts.map +1 -0
- package/dist/layers/structure-layer.js +152 -0
- package/dist/layers/structure-layer.js.map +1 -0
- package/dist/layers/text-layer.d.ts +53 -0
- package/dist/layers/text-layer.d.ts.map +1 -0
- package/dist/layers/text-layer.js +292 -0
- package/dist/layers/text-layer.js.map +1 -0
- package/dist/layout/range.d.ts +3 -0
- package/dist/layout/range.d.ts.map +1 -0
- package/dist/layout/range.js +5 -0
- package/dist/layout/range.js.map +1 -0
- package/dist/network/watch.d.ts +30 -0
- package/dist/network/watch.d.ts.map +1 -0
- package/dist/network/watch.js +181 -0
- package/dist/network/watch.js.map +1 -0
- package/dist/protocol.d.ts +127 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/protocol.js.map +1 -1
- package/dist/render/tiles.d.ts +43 -3
- package/dist/render/tiles.d.ts.map +1 -1
- package/dist/render/tiles.js +62 -10
- package/dist/render/tiles.js.map +1 -1
- package/dist/source/http-range.d.ts +59 -0
- package/dist/source/http-range.d.ts.map +1 -0
- package/dist/source/http-range.js +284 -0
- package/dist/source/http-range.js.map +1 -0
- package/dist/thumbnails/strip.d.ts +37 -0
- package/dist/thumbnails/strip.d.ts.map +1 -0
- package/dist/thumbnails/strip.js +313 -0
- package/dist/thumbnails/strip.js.map +1 -0
- package/dist/view/budgets.d.ts +29 -0
- package/dist/view/budgets.d.ts.map +1 -0
- package/dist/view/budgets.js +63 -0
- package/dist/view/budgets.js.map +1 -0
- package/dist/view/touch.d.ts +71 -0
- package/dist/view/touch.d.ts.map +1 -0
- package/dist/view/touch.js +220 -0
- package/dist/view/touch.js.map +1 -0
- package/dist/view/viewer.d.ts +42 -1
- package/dist/view/viewer.d.ts.map +1 -1
- package/dist/view/viewer.js +433 -69
- package/dist/view/viewer.js.map +1 -1
- package/dist/worker/document.d.ts +33 -1
- package/dist/worker/document.d.ts.map +1 -1
- package/dist/worker/document.js +181 -24
- package/dist/worker/document.js.map +1 -1
- package/dist/worker/entry.d.ts +1 -1
- package/dist/worker/entry.d.ts.map +1 -1
- package/dist/worker/entry.js +3 -1
- package/dist/worker/entry.js.map +1 -1
- package/dist/worker/find.d.ts +7 -0
- package/dist/worker/find.d.ts.map +1 -0
- package/dist/worker/find.js +59 -0
- package/dist/worker/find.js.map +1 -0
- package/dist/worker/methods.d.ts.map +1 -1
- package/dist/worker/methods.js +31 -4
- package/dist/worker/methods.js.map +1 -1
- package/dist/worker/navigation.d.ts +6 -0
- package/dist/worker/navigation.d.ts.map +1 -0
- package/dist/worker/navigation.js +16 -0
- package/dist/worker/navigation.js.map +1 -0
- package/dist/worker/network.d.ts +4 -0
- package/dist/worker/network.d.ts.map +1 -0
- package/dist/worker/network.js +24 -0
- package/dist/worker/network.js.map +1 -0
- package/dist/worker/render.d.ts +5 -2
- package/dist/worker/render.d.ts.map +1 -1
- package/dist/worker/render.js +14 -7
- package/dist/worker/render.js.map +1 -1
- package/dist/worker/text.d.ts +17 -0
- package/dist/worker/text.d.ts.map +1 -0
- package/dist/worker/text.js +75 -0
- package/dist/worker/text.js.map +1 -0
- package/dist/zoom/destination.d.ts +18 -0
- package/dist/zoom/destination.d.ts.map +1 -0
- package/dist/zoom/destination.js +56 -0
- package/dist/zoom/destination.js.map +1 -0
- package/package.json +6 -5
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
// The text layer (web-app §6 C5): on every mounted page, one transparent span per text run of
|
|
2
|
+
// Lamina PDF's extraction, laid over the rendered glyphs, so the browser's own selection, copy
|
|
3
|
+
// and screen readers work on the page's text. Spans are placed in page points inside a box that
|
|
4
|
+
// one CSS transform scales and rotates to the page's current size, so a zoom or a rotation moves
|
|
5
|
+
// no span. The viewer is the one selection root: only spans are selectable, never canvases, gaps
|
|
6
|
+
// or the app around it, so a selection runs from one page into the next; the pages it touches
|
|
7
|
+
// stay mounted while it lasts. Copy writes the extracted text, joined in reading order.
|
|
8
|
+
import { range as range_ } from "../layout/range.js";
|
|
9
|
+
import { placeBox } from "./box.js";
|
|
10
|
+
import { joinPieces, layoutSpans } from "./spans.js";
|
|
11
|
+
import { StructureLayer } from "./structure-layer.js";
|
|
12
|
+
/** Numbers each text layer, for its span ids. */
|
|
13
|
+
let nextViewer = 0;
|
|
14
|
+
/** The text layer of one viewer. */
|
|
15
|
+
export class TextLayer {
|
|
16
|
+
name = "text";
|
|
17
|
+
#host;
|
|
18
|
+
#options;
|
|
19
|
+
#pages = new Map();
|
|
20
|
+
#specs = new WeakMap();
|
|
21
|
+
#structure;
|
|
22
|
+
#cleanup = [];
|
|
23
|
+
#points = [];
|
|
24
|
+
/** Each mounted page's size in CSS px, as the last resize gave it. */
|
|
25
|
+
#sizes = new Map();
|
|
26
|
+
#pointerType = "";
|
|
27
|
+
/** Span ids' prefix, unique to this viewer, so two viewers on a page never share an id. */
|
|
28
|
+
#idPrefix = `lamina-text-${nextViewer++}-`;
|
|
29
|
+
/** Counts opens: a structure tree answered for an earlier document is dropped. */
|
|
30
|
+
#generation = 0;
|
|
31
|
+
/** Whether the last selection change was in this viewer, so a selection elsewhere is told only once. */
|
|
32
|
+
#selecting = false;
|
|
33
|
+
constructor(host, options = {}) {
|
|
34
|
+
this.#host = host;
|
|
35
|
+
this.#options = options;
|
|
36
|
+
this.#structure = new StructureLayer(host.root, options.untaggedLabel ?? "Untagged document", this.#idPrefix);
|
|
37
|
+
// Nothing in the viewer is selectable but the spans (set on each): canvases, gaps and other
|
|
38
|
+
// layers stay out of every selection.
|
|
39
|
+
selectable(host.root, "none");
|
|
40
|
+
this.#listen(document, "selectionchange", () => this.#selectionChanged());
|
|
41
|
+
this.#listen(document, "copy", (e) => this.#copy(e));
|
|
42
|
+
this.#listen(host.root, "keydown", (e) => this.#selectAll(e));
|
|
43
|
+
this.#listen(host.root, "pointerdown", (e) => {
|
|
44
|
+
this.#pointerType = e.pointerType;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/** A new document: its page sizes, and its structure tree, read once. */
|
|
48
|
+
open(document) {
|
|
49
|
+
this.#points = document.pages.map((p) => ({ width: p.width, height: p.height }));
|
|
50
|
+
this.#structure.reset();
|
|
51
|
+
const opening = ++this.#generation;
|
|
52
|
+
this.#host.client
|
|
53
|
+
.structure()
|
|
54
|
+
.then((structure) => {
|
|
55
|
+
// Another document opened while this one's tree was read: it isn't this document's.
|
|
56
|
+
if (opening !== this.#generation)
|
|
57
|
+
return;
|
|
58
|
+
this.#structure.show(structure);
|
|
59
|
+
// Pages whose text came first: link them now that their elements exist.
|
|
60
|
+
for (const page of this.#pages.keys())
|
|
61
|
+
this.#linkPage(page);
|
|
62
|
+
})
|
|
63
|
+
.catch(() => {
|
|
64
|
+
// No structure (a worker restart, a closed document): the spans still read in order.
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
onMount(page, slot) {
|
|
68
|
+
const box = document.createElement("div");
|
|
69
|
+
box.className = "lamina-text-layer";
|
|
70
|
+
// The spans lie over the canvas, so an app's ::selection fill would paint over the glyphs it
|
|
71
|
+
// selects. With the box multiplied over the canvas, the fill shows where the page is paper and
|
|
72
|
+
// the ink stays as dark as drawn: the tint sits under the text, as the find highlights do.
|
|
73
|
+
Object.assign(box.style, {
|
|
74
|
+
position: "absolute",
|
|
75
|
+
left: "0",
|
|
76
|
+
top: "0",
|
|
77
|
+
transformOrigin: "0 0",
|
|
78
|
+
mixBlendMode: "multiply",
|
|
79
|
+
});
|
|
80
|
+
slot.append(box);
|
|
81
|
+
const text = { box, abort: new AbortController(), spans: [] };
|
|
82
|
+
this.#pages.set(page, text);
|
|
83
|
+
this.#host.client
|
|
84
|
+
.pageText(page, { signal: text.abort.signal })
|
|
85
|
+
.then((data) => {
|
|
86
|
+
if (this.#pages.get(page) !== text)
|
|
87
|
+
return;
|
|
88
|
+
this.#fill(page, text, layoutSpans(data.runs, data.quads));
|
|
89
|
+
})
|
|
90
|
+
.catch(() => {
|
|
91
|
+
// Aborted (the page left), or a page whose text can't be read: it stays without text.
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
onUnmount(page) {
|
|
95
|
+
const text = this.#pages.get(page);
|
|
96
|
+
if (text === undefined)
|
|
97
|
+
return;
|
|
98
|
+
text.abort.abort();
|
|
99
|
+
text.box.remove();
|
|
100
|
+
this.#structure.unlink(page);
|
|
101
|
+
this.#pages.delete(page);
|
|
102
|
+
this.#sizes.delete(page);
|
|
103
|
+
}
|
|
104
|
+
onZoom(page, _slot, size) {
|
|
105
|
+
this.#sizes.set(page, size);
|
|
106
|
+
this.#place(page, size);
|
|
107
|
+
}
|
|
108
|
+
/** Places every page's box again: the view turned. */
|
|
109
|
+
refresh() {
|
|
110
|
+
for (const [page, size] of this.#sizes)
|
|
111
|
+
this.#place(page, size);
|
|
112
|
+
}
|
|
113
|
+
/** Scales and turns page `page`'s box to `size` at the view's rotation. */
|
|
114
|
+
#place(page, size) {
|
|
115
|
+
const text = this.#pages.get(page);
|
|
116
|
+
const points = this.#points[page];
|
|
117
|
+
if (text === undefined || points === undefined)
|
|
118
|
+
return;
|
|
119
|
+
placeBox(text.box, points, size, this.#host.rotation());
|
|
120
|
+
}
|
|
121
|
+
/** Stops listening; the viewer calls it on destroy. */
|
|
122
|
+
destroy() {
|
|
123
|
+
for (const f of this.#cleanup.splice(0))
|
|
124
|
+
f();
|
|
125
|
+
for (const page of [...this.#pages.keys()])
|
|
126
|
+
this.onUnmount(page);
|
|
127
|
+
this.#structure.reset();
|
|
128
|
+
}
|
|
129
|
+
#listen(target, type, f) {
|
|
130
|
+
target.addEventListener(type, f);
|
|
131
|
+
this.#cleanup.push(() => target.removeEventListener(type, f));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The page's spans, built once: written, then every natural width read in one pass, then each
|
|
135
|
+
* stretched to its run's width in another, so the page costs one layout, not one per span.
|
|
136
|
+
*/
|
|
137
|
+
#fill(page, text, specs) {
|
|
138
|
+
const fragment = document.createDocumentFragment();
|
|
139
|
+
text.spans = specs.map((spec, k) => {
|
|
140
|
+
const span = document.createElement("span");
|
|
141
|
+
span.id = `${this.#idPrefix}${page}-${k}`;
|
|
142
|
+
span.textContent = spec.text;
|
|
143
|
+
if (spec.rtl)
|
|
144
|
+
span.dir = "rtl";
|
|
145
|
+
Object.assign(span.style, {
|
|
146
|
+
position: "absolute",
|
|
147
|
+
left: `${spec.left}px`,
|
|
148
|
+
top: `${spec.top}px`,
|
|
149
|
+
fontSize: `${spec.height}px`,
|
|
150
|
+
lineHeight: "1",
|
|
151
|
+
fontFamily: "sans-serif",
|
|
152
|
+
whiteSpace: "pre",
|
|
153
|
+
color: "transparent",
|
|
154
|
+
cursor: "text",
|
|
155
|
+
transformOrigin: "0 0",
|
|
156
|
+
...(this.#options.outline === true ? { outline: "1px solid rgb(220 0 0 / 0.7)" } : {}),
|
|
157
|
+
});
|
|
158
|
+
selectable(span, "text");
|
|
159
|
+
this.#specs.set(span, { page, spec });
|
|
160
|
+
fragment.append(span);
|
|
161
|
+
return span;
|
|
162
|
+
});
|
|
163
|
+
text.box.append(fragment);
|
|
164
|
+
// Reads, then writes: each natural width in points, fractional, with the box briefly
|
|
165
|
+
// untransformed (its zoom and turn would scale and rotate the rects).
|
|
166
|
+
const placed = text.box.style.transform;
|
|
167
|
+
text.box.style.transform = "none";
|
|
168
|
+
// The box is its points wide: what the page around the viewer scales it by (a zoomed host)
|
|
169
|
+
// comes out of every width.
|
|
170
|
+
const outside = text.box.getBoundingClientRect().width / Math.max(1, text.box.offsetWidth);
|
|
171
|
+
const natural = text.spans.map((span) => span.getBoundingClientRect().width / (outside || 1));
|
|
172
|
+
text.box.style.transform = placed;
|
|
173
|
+
specs.forEach((spec, k) => {
|
|
174
|
+
const span = text.spans[k];
|
|
175
|
+
const fit = (natural[k] ?? 0) > 0 ? spec.width / natural[k] : 1;
|
|
176
|
+
span.style.transform = `rotate(${spec.angle}rad) scaleX(${fit})`;
|
|
177
|
+
});
|
|
178
|
+
this.#linkPage(page);
|
|
179
|
+
}
|
|
180
|
+
/** Gives the structure tree's elements the page's spans that their marked content drew. */
|
|
181
|
+
#linkPage(page) {
|
|
182
|
+
const text = this.#pages.get(page);
|
|
183
|
+
if (text === undefined)
|
|
184
|
+
return;
|
|
185
|
+
for (const span of text.spans) {
|
|
186
|
+
const mcid = this.#specs.get(span)?.spec.mcid;
|
|
187
|
+
if (mcid !== undefined)
|
|
188
|
+
this.#structure.link(page, mcid, span.id);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** The mounted pages' spans, in page and reading order. */
|
|
192
|
+
#spansInOrder() {
|
|
193
|
+
return [...this.#pages.entries()].sort(([a], [b]) => a - b).flatMap(([, text]) => text.spans);
|
|
194
|
+
}
|
|
195
|
+
/** The selection's range, when it is in this viewer's text. */
|
|
196
|
+
#range() {
|
|
197
|
+
const selection = document.getSelection();
|
|
198
|
+
if (selection === null || selection.rangeCount === 0 || selection.isCollapsed)
|
|
199
|
+
return undefined;
|
|
200
|
+
const range = selection.getRangeAt(0);
|
|
201
|
+
return this.#host.root.contains(range.commonAncestorContainer) ? range : undefined;
|
|
202
|
+
}
|
|
203
|
+
/** The selected part of each span the selection touches, in order. */
|
|
204
|
+
#pieces(range) {
|
|
205
|
+
const pieces = [];
|
|
206
|
+
for (const span of this.#spansInOrder()) {
|
|
207
|
+
const info = this.#specs.get(span);
|
|
208
|
+
if (info === undefined || !range.intersectsNode(span))
|
|
209
|
+
continue;
|
|
210
|
+
const full = span.textContent ?? "";
|
|
211
|
+
const start = span.contains(range.startContainer) ? offsetIn(span, range.startContainer, range.startOffset) : 0;
|
|
212
|
+
const end = span.contains(range.endContainer) ? offsetIn(span, range.endContainer, range.endOffset) : full.length;
|
|
213
|
+
const text = full.slice(start, end);
|
|
214
|
+
if (text !== "")
|
|
215
|
+
pieces.push({ page: info.page, text, span: info.spec });
|
|
216
|
+
}
|
|
217
|
+
return pieces;
|
|
218
|
+
}
|
|
219
|
+
#copy(event) {
|
|
220
|
+
const range = this.#range();
|
|
221
|
+
if (range === undefined || event.clipboardData === null)
|
|
222
|
+
return;
|
|
223
|
+
event.clipboardData.setData("text/plain", joinPieces(this.#pieces(range)));
|
|
224
|
+
event.preventDefault();
|
|
225
|
+
}
|
|
226
|
+
/** Ctrl/Cmd+A in the viewer selects the mounted pages' text (find reaches the rest). */
|
|
227
|
+
#selectAll(event) {
|
|
228
|
+
if (event.key.toLowerCase() !== "a" || !(event.ctrlKey || event.metaKey) || event.altKey)
|
|
229
|
+
return;
|
|
230
|
+
const spans = this.#spansInOrder();
|
|
231
|
+
const first = spans[0];
|
|
232
|
+
const last = spans.at(-1);
|
|
233
|
+
if (first === undefined || last === undefined)
|
|
234
|
+
return;
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
const range = document.createRange();
|
|
237
|
+
range.setStart(first, 0);
|
|
238
|
+
range.setEnd(last, last.childNodes.length);
|
|
239
|
+
const selection = document.getSelection();
|
|
240
|
+
selection?.removeAllRanges();
|
|
241
|
+
selection?.addRange(range);
|
|
242
|
+
}
|
|
243
|
+
#selectionChanged() {
|
|
244
|
+
const range = this.#range();
|
|
245
|
+
if (range === undefined) {
|
|
246
|
+
// A selection elsewhere on the page (an input, another viewer): told once, when it leaves.
|
|
247
|
+
if (!this.#selecting)
|
|
248
|
+
return;
|
|
249
|
+
this.#selecting = false;
|
|
250
|
+
this.#host.keepMounted([]);
|
|
251
|
+
this.#options.onSelection?.(undefined);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
this.#selecting = true;
|
|
255
|
+
// Every page from the one the selection starts on to the one it ends on, those between too:
|
|
256
|
+
// read from its two ends, not by walking every span while a drag goes on.
|
|
257
|
+
// An end in a gap between pages counts as the other end's page.
|
|
258
|
+
const start = pageOf(range.startContainer);
|
|
259
|
+
const end = pageOf(range.endContainer);
|
|
260
|
+
const [low, high] = [start ?? end, end ?? start];
|
|
261
|
+
if (low !== undefined && high !== undefined)
|
|
262
|
+
this.#host.keepMounted(range_(Math.min(low, high), Math.max(low, high)));
|
|
263
|
+
if (this.#options.onSelection === undefined)
|
|
264
|
+
return;
|
|
265
|
+
const pieces = this.#pieces(range);
|
|
266
|
+
this.#options.onSelection({
|
|
267
|
+
text: joinPieces(pieces),
|
|
268
|
+
rects: [...range.getClientRects()],
|
|
269
|
+
pages: [...new Set(pieces.map((p) => p.page))],
|
|
270
|
+
pointerType: this.#pointerType,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/** Sets `element`'s `user-select`, with WebKit's prefix (Safari before 26 reads only that). */
|
|
275
|
+
function selectable(element, value) {
|
|
276
|
+
element.style.setProperty("user-select", value);
|
|
277
|
+
element.style.setProperty("-webkit-user-select", value);
|
|
278
|
+
}
|
|
279
|
+
/** The index of the page `node` is on, from its shell. */
|
|
280
|
+
function pageOf(node) {
|
|
281
|
+
const element = node instanceof Element ? node : node.parentElement;
|
|
282
|
+
const index = element?.closest(".lamina-page")?.dataset.pageIndex;
|
|
283
|
+
return index === undefined ? undefined : Number(index);
|
|
284
|
+
}
|
|
285
|
+
/** The character offset in `span`'s text of the boundary point (`node`, `offset`). */
|
|
286
|
+
function offsetIn(span, node, offset) {
|
|
287
|
+
if (node.nodeType === Node.TEXT_NODE)
|
|
288
|
+
return offset;
|
|
289
|
+
// A boundary between the span's children: before the first or after its text.
|
|
290
|
+
return offset === 0 ? 0 : (span.textContent ?? "").length;
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=text-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-layer.js","sourceRoot":"","sources":["../../src/layers/text-layer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range.d.ts","sourceRoot":"","sources":["../../src/layout/range.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range.js","sourceRoot":"","sources":["../../src/layout/range.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,IAAY;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { NetworkRecord, NetworkSource, PolicyViolation } from "../protocol.js";
|
|
2
|
+
/** What `watchNetwork` reports to. */
|
|
3
|
+
export interface NetworkSink {
|
|
4
|
+
/** A request was made: called when it starts, failed or not, or when its timing entry arrives. */
|
|
5
|
+
request(record: NetworkRecord): void;
|
|
6
|
+
/** The scope's Content Security Policy blocked a request, so nothing was sent. */
|
|
7
|
+
violation(violation: PolicyViolation): void;
|
|
8
|
+
}
|
|
9
|
+
/** The global scope parts the watcher wraps and reads (a Window or a WorkerGlobalScope). */
|
|
10
|
+
type Scope = typeof globalThis & {
|
|
11
|
+
XMLHttpRequest?: typeof XMLHttpRequest;
|
|
12
|
+
WebSocket?: typeof WebSocket;
|
|
13
|
+
PerformanceObserver?: typeof PerformanceObserver;
|
|
14
|
+
location?: {
|
|
15
|
+
href: string;
|
|
16
|
+
};
|
|
17
|
+
navigator?: Navigator & {
|
|
18
|
+
sendBeacon?: Navigator["sendBeacon"];
|
|
19
|
+
};
|
|
20
|
+
addEventListener?: (type: string, listener: (event: Event) => void) => void;
|
|
21
|
+
removeEventListener?: (type: string, listener: (event: Event) => void) => void;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Starts reporting every request `scope` makes to `sink`, as `source`. Returns the function that
|
|
25
|
+
* stops it: the scope's own `fetch`, `XMLHttpRequest`, `WebSocket` and `sendBeacon` put back, the
|
|
26
|
+
* observers disconnected and the violation listener removed.
|
|
27
|
+
*/
|
|
28
|
+
export declare function watchNetwork(scope: Scope, sink: NetworkSink, source: NetworkSource): () => void;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/network/watch.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAQpF,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,kGAAkG;IAClG,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,kFAAkF;IAClF,SAAS,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;CAC7C;AAED,4FAA4F;AAC5F,KAAK,KAAK,GAAG,OAAO,UAAU,GAAG;IAC/B,cAAc,CAAC,EAAE,OAAO,cAAc,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,mBAAmB,CAAC,EAAE,OAAO,mBAAmB,CAAC;IACjD,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,SAAS,GAAG;QAAE,UAAU,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,CAAA;KAAE,CAAC;IACjE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;IAC5E,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;CAChF,CAAC;AAkBF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,IAAI,CAwC/F"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// Every network request a JavaScript context makes, reported as it happens: the page's and the
|
|
2
|
+
// document worker's (ADR 0011's privacy guarantees, R13's network panel). A context can request
|
|
3
|
+
// in two ways that leave different traces, so the watcher uses both:
|
|
4
|
+
//
|
|
5
|
+
// - calls the page's or the worker's code makes (`fetch`, `XMLHttpRequest`, `WebSocket`,
|
|
6
|
+
// `navigator.sendBeacon`) are wrapped, so each is reported when it starts, failed or not, and a
|
|
7
|
+
// WebSocket, which leaves no timing entry, is counted too;
|
|
8
|
+
// - everything the browser loads by itself (scripts, module imports, styles, fonts, images, the
|
|
9
|
+
// page) is read from the Resource Timing entries, whose `initiatorType` tells them apart from
|
|
10
|
+
// the wrapped calls, so nothing is counted twice.
|
|
11
|
+
//
|
|
12
|
+
// Installed before any other code of the context runs, so no code path can capture an unwrapped
|
|
13
|
+
// `fetch` first. A request the context never makes (a browser extension's) is out of its sight.
|
|
14
|
+
/** The entries a wrapped call also leaves in Resource Timing, read from the call instead. */
|
|
15
|
+
const WRAPPED_INITIATORS = new Set(["fetch", "xmlhttprequest", "beacon"]);
|
|
16
|
+
/** The `blockedURI`s of violations that block no request (CSP3 §5.3's keywords for them). */
|
|
17
|
+
const NOT_REQUESTS = new Set(["", "inline", "eval", "wasm-eval", "trusted-types-policy", "trusted-types-sink"]);
|
|
18
|
+
/** `input`'s absolute URL, against the scope's address. */
|
|
19
|
+
function urlOf(input, base) {
|
|
20
|
+
const raw = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
21
|
+
try {
|
|
22
|
+
return new URL(raw, base).href;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return raw;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** A `Content-Length` header's bytes, or 0 when there is none or it isn't a number. */
|
|
29
|
+
function lengthOf(header) {
|
|
30
|
+
const length = Number(header);
|
|
31
|
+
return Number.isFinite(length) && length > 0 ? length : 0;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Starts reporting every request `scope` makes to `sink`, as `source`. Returns the function that
|
|
35
|
+
* stops it: the scope's own `fetch`, `XMLHttpRequest`, `WebSocket` and `sendBeacon` put back, the
|
|
36
|
+
* observers disconnected and the violation listener removed.
|
|
37
|
+
*/
|
|
38
|
+
export function watchNetwork(scope, sink, source) {
|
|
39
|
+
const base = scope.location?.href;
|
|
40
|
+
const report = (record, at = Date.now()) => sink.request({ ...record, source, at });
|
|
41
|
+
const restore = [];
|
|
42
|
+
const originalFetch = scope.fetch;
|
|
43
|
+
if (typeof originalFetch === "function") {
|
|
44
|
+
scope.fetch = async (input, init) => {
|
|
45
|
+
const url = urlOf(input, base);
|
|
46
|
+
const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
|
|
47
|
+
// Stamped when the call starts: a request belongs to the file that was opening then.
|
|
48
|
+
const at = Date.now();
|
|
49
|
+
try {
|
|
50
|
+
const response = await originalFetch.call(scope, input, init);
|
|
51
|
+
const bytes = lengthOf(response.headers.get("Content-Length"));
|
|
52
|
+
report({ url, method, initiator: "fetch", bytes, failed: false }, at);
|
|
53
|
+
return response;
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
report({ url, method, initiator: "fetch", bytes: 0, failed: true }, at);
|
|
57
|
+
throw e;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
restore.push(() => {
|
|
61
|
+
scope.fetch = originalFetch;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
restore.push(...wrapXhr(scope, base, report), ...wrapWebSocket(scope, base, report));
|
|
65
|
+
restore.push(...wrapBeacon(scope, base, report), ...observeResources(scope, report));
|
|
66
|
+
const onViolation = (event) => {
|
|
67
|
+
const e = event;
|
|
68
|
+
// Inline code, eval and Trusted Types violations block no request: only a blocked URL is one.
|
|
69
|
+
if (NOT_REQUESTS.has(e.blockedURI))
|
|
70
|
+
return;
|
|
71
|
+
sink.violation({ directive: e.effectiveDirective, blockedUri: e.blockedURI, source, at: Date.now() });
|
|
72
|
+
};
|
|
73
|
+
scope.addEventListener?.("securitypolicyviolation", onViolation);
|
|
74
|
+
restore.push(() => scope.removeEventListener?.("securitypolicyviolation", onViolation));
|
|
75
|
+
return () => {
|
|
76
|
+
for (const undo of restore)
|
|
77
|
+
undo();
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** `XMLHttpRequest`: the method and URL from `open`, reported once the request ends. */
|
|
81
|
+
function wrapXhr(scope, base, report) {
|
|
82
|
+
const Xhr = scope.XMLHttpRequest;
|
|
83
|
+
if (Xhr === undefined)
|
|
84
|
+
return [];
|
|
85
|
+
const { open, send } = Xhr.prototype;
|
|
86
|
+
const seen = new WeakMap();
|
|
87
|
+
Xhr.prototype.open = function (method, url, ...rest) {
|
|
88
|
+
seen.set(this, { method: method.toUpperCase(), url: urlOf(url, base) });
|
|
89
|
+
return open.call(this, method, url, ...rest);
|
|
90
|
+
};
|
|
91
|
+
Xhr.prototype.send = function (body) {
|
|
92
|
+
const call = seen.get(this);
|
|
93
|
+
if (call !== undefined) {
|
|
94
|
+
const at = Date.now();
|
|
95
|
+
this.addEventListener("loadend", () => {
|
|
96
|
+
const bytes = lengthOf(this.getResponseHeader("Content-Length"));
|
|
97
|
+
report({ ...call, initiator: "xmlhttprequest", bytes, failed: this.status === 0 }, at);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return send.call(this, body);
|
|
101
|
+
};
|
|
102
|
+
return [
|
|
103
|
+
() => {
|
|
104
|
+
Xhr.prototype.open = open;
|
|
105
|
+
Xhr.prototype.send = send;
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
/** `WebSocket`: each connection attempt, which Resource Timing never lists. */
|
|
110
|
+
function wrapWebSocket(scope, base, report) {
|
|
111
|
+
const Socket = scope.WebSocket;
|
|
112
|
+
if (Socket === undefined)
|
|
113
|
+
return [];
|
|
114
|
+
const Wrapped = new Proxy(Socket, {
|
|
115
|
+
construct(target, args) {
|
|
116
|
+
report({ url: urlOf(args[0], base), method: "GET", initiator: "websocket", bytes: 0, failed: false });
|
|
117
|
+
return Reflect.construct(target, args);
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
scope.WebSocket = Wrapped;
|
|
121
|
+
return [
|
|
122
|
+
() => {
|
|
123
|
+
scope.WebSocket = Socket;
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
/** `navigator.sendBeacon` (the page only): each beacon, sent or refused. */
|
|
128
|
+
function wrapBeacon(scope, base, report) {
|
|
129
|
+
const nav = scope.navigator;
|
|
130
|
+
const beacon = nav?.sendBeacon;
|
|
131
|
+
if (nav === undefined || typeof beacon !== "function")
|
|
132
|
+
return [];
|
|
133
|
+
nav.sendBeacon = (url, data) => {
|
|
134
|
+
const sent = beacon.call(nav, url, data);
|
|
135
|
+
report({ url: urlOf(url, base), method: "POST", initiator: "beacon", bytes: 0, failed: !sent });
|
|
136
|
+
return sent;
|
|
137
|
+
};
|
|
138
|
+
return [
|
|
139
|
+
() => {
|
|
140
|
+
nav.sendBeacon = beacon;
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
/** What the browser loaded by itself: Resource Timing entries (and the page's own load), buffered. */
|
|
145
|
+
function observeResources(scope, report) {
|
|
146
|
+
const Observer = scope.PerformanceObserver;
|
|
147
|
+
if (Observer === undefined)
|
|
148
|
+
return [];
|
|
149
|
+
const types = new Set(Observer.supportedEntryTypes ?? []);
|
|
150
|
+
// A document navigates once, but Chromium reports its navigation entry again when the load ends.
|
|
151
|
+
let navigated = false;
|
|
152
|
+
const take = (entry) => {
|
|
153
|
+
if (entry.entryType === "navigation") {
|
|
154
|
+
if (navigated)
|
|
155
|
+
return;
|
|
156
|
+
navigated = true;
|
|
157
|
+
}
|
|
158
|
+
const timing = entry;
|
|
159
|
+
if (WRAPPED_INITIATORS.has(timing.initiatorType))
|
|
160
|
+
return;
|
|
161
|
+
if (!/^https?:/.test(timing.name))
|
|
162
|
+
return;
|
|
163
|
+
const bytes = timing.transferSize || timing.encodedBodySize || 0;
|
|
164
|
+
// When the request started, not when the observer heard of it: a buffered entry comes late.
|
|
165
|
+
const at = Math.round((scope.performance?.timeOrigin ?? Date.now()) + entry.startTime);
|
|
166
|
+
report({ url: timing.name, method: "GET", initiator: timing.initiatorType || entry.entryType, bytes, failed: false }, at);
|
|
167
|
+
};
|
|
168
|
+
const observers = [];
|
|
169
|
+
for (const type of ["navigation", "resource"]) {
|
|
170
|
+
if (!types.has(type))
|
|
171
|
+
continue;
|
|
172
|
+
const observer = new Observer((list) => {
|
|
173
|
+
for (const entry of list.getEntries())
|
|
174
|
+
take(entry);
|
|
175
|
+
});
|
|
176
|
+
observer.observe({ type, buffered: true });
|
|
177
|
+
observers.push(observer);
|
|
178
|
+
}
|
|
179
|
+
return observers.map((observer) => () => observer.disconnect());
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/network/watch.ts"],"names":[],"mappings":"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"}
|