@laminapdf/viewer 0.2.0-alpha.3 → 0.2.0-alpha.5

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 (149) hide show
  1. package/README.md +102 -8
  2. package/dist/client.d.ts +75 -2
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +192 -32
  5. package/dist/client.js.map +1 -1
  6. package/dist/find/controller.d.ts +73 -0
  7. package/dist/find/controller.d.ts.map +1 -0
  8. package/dist/find/controller.js +227 -0
  9. package/dist/find/controller.js.map +1 -0
  10. package/dist/find/fold.d.ts +23 -0
  11. package/dist/find/fold.d.ts.map +1 -0
  12. package/dist/find/fold.js +99 -0
  13. package/dist/find/fold.js.map +1 -0
  14. package/dist/find/page.d.ts +44 -0
  15. package/dist/find/page.d.ts.map +1 -0
  16. package/dist/find/page.js +173 -0
  17. package/dist/find/page.js.map +1 -0
  18. package/dist/first-draw.d.ts +10 -0
  19. package/dist/first-draw.d.ts.map +1 -0
  20. package/dist/first-draw.js +33 -0
  21. package/dist/first-draw.js.map +1 -0
  22. package/dist/history/history.d.ts +65 -0
  23. package/dist/history/history.d.ts.map +1 -0
  24. package/dist/history/history.js +135 -0
  25. package/dist/history/history.js.map +1 -0
  26. package/dist/index.d.ts +13 -2
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/layers/box.d.ts +10 -0
  31. package/dist/layers/box.d.ts.map +1 -0
  32. package/dist/layers/box.js +19 -0
  33. package/dist/layers/box.js.map +1 -0
  34. package/dist/layers/copy.d.ts +26 -0
  35. package/dist/layers/copy.d.ts.map +1 -0
  36. package/dist/layers/copy.js +150 -0
  37. package/dist/layers/copy.js.map +1 -0
  38. package/dist/layers/highlight-layer.d.ts +31 -0
  39. package/dist/layers/highlight-layer.d.ts.map +1 -0
  40. package/dist/layers/highlight-layer.js +95 -0
  41. package/dist/layers/highlight-layer.js.map +1 -0
  42. package/dist/layers/link-layer.d.ts +68 -0
  43. package/dist/layers/link-layer.d.ts.map +1 -0
  44. package/dist/layers/link-layer.js +279 -0
  45. package/dist/layers/link-layer.js.map +1 -0
  46. package/dist/layers/link-url.d.ts +19 -0
  47. package/dist/layers/link-url.d.ts.map +1 -0
  48. package/dist/layers/link-url.js +47 -0
  49. package/dist/layers/link-url.js.map +1 -0
  50. package/dist/layers/spans.d.ts +36 -0
  51. package/dist/layers/spans.d.ts.map +1 -0
  52. package/dist/layers/spans.js +103 -0
  53. package/dist/layers/spans.js.map +1 -0
  54. package/dist/layers/structure-layer.d.ts +15 -0
  55. package/dist/layers/structure-layer.d.ts.map +1 -0
  56. package/dist/layers/structure-layer.js +155 -0
  57. package/dist/layers/structure-layer.js.map +1 -0
  58. package/dist/layers/text-layer.d.ts +70 -0
  59. package/dist/layers/text-layer.d.ts.map +1 -0
  60. package/dist/layers/text-layer.js +576 -0
  61. package/dist/layers/text-layer.js.map +1 -0
  62. package/dist/layout/range.d.ts +3 -0
  63. package/dist/layout/range.d.ts.map +1 -0
  64. package/dist/layout/range.js +5 -0
  65. package/dist/layout/range.js.map +1 -0
  66. package/dist/network/watch.d.ts +30 -0
  67. package/dist/network/watch.d.ts.map +1 -0
  68. package/dist/network/watch.js +181 -0
  69. package/dist/network/watch.js.map +1 -0
  70. package/dist/protocol.d.ts +193 -6
  71. package/dist/protocol.d.ts.map +1 -1
  72. package/dist/protocol.js +16 -4
  73. package/dist/protocol.js.map +1 -1
  74. package/dist/render/tiles.d.ts +43 -3
  75. package/dist/render/tiles.d.ts.map +1 -1
  76. package/dist/render/tiles.js +62 -10
  77. package/dist/render/tiles.js.map +1 -1
  78. package/dist/source/http-range.d.ts +59 -0
  79. package/dist/source/http-range.d.ts.map +1 -0
  80. package/dist/source/http-range.js +284 -0
  81. package/dist/source/http-range.js.map +1 -0
  82. package/dist/source/opfs.d.ts +35 -0
  83. package/dist/source/opfs.d.ts.map +1 -0
  84. package/dist/source/opfs.js +178 -0
  85. package/dist/source/opfs.js.map +1 -0
  86. package/dist/thumbnails/strip.d.ts +37 -0
  87. package/dist/thumbnails/strip.d.ts.map +1 -0
  88. package/dist/thumbnails/strip.js +324 -0
  89. package/dist/thumbnails/strip.js.map +1 -0
  90. package/dist/view/budgets.d.ts +29 -0
  91. package/dist/view/budgets.d.ts.map +1 -0
  92. package/dist/view/budgets.js +63 -0
  93. package/dist/view/budgets.js.map +1 -0
  94. package/dist/view/touch.d.ts +71 -0
  95. package/dist/view/touch.d.ts.map +1 -0
  96. package/dist/view/touch.js +220 -0
  97. package/dist/view/touch.js.map +1 -0
  98. package/dist/view/user-select.d.ts +3 -0
  99. package/dist/view/user-select.d.ts.map +1 -0
  100. package/dist/view/user-select.js +10 -0
  101. package/dist/view/user-select.js.map +1 -0
  102. package/dist/view/viewer.d.ts +102 -1
  103. package/dist/view/viewer.d.ts.map +1 -1
  104. package/dist/view/viewer.js +660 -95
  105. package/dist/view/viewer.js.map +1 -1
  106. package/dist/worker/document.d.ts +53 -1
  107. package/dist/worker/document.d.ts.map +1 -1
  108. package/dist/worker/document.js +222 -24
  109. package/dist/worker/document.js.map +1 -1
  110. package/dist/worker/entry.d.ts +1 -1
  111. package/dist/worker/entry.d.ts.map +1 -1
  112. package/dist/worker/entry.js +2 -0
  113. package/dist/worker/entry.js.map +1 -1
  114. package/dist/worker/find.d.ts +7 -0
  115. package/dist/worker/find.d.ts.map +1 -0
  116. package/dist/worker/find.js +46 -0
  117. package/dist/worker/find.js.map +1 -0
  118. package/dist/worker/methods.d.ts.map +1 -1
  119. package/dist/worker/methods.js +49 -4
  120. package/dist/worker/methods.js.map +1 -1
  121. package/dist/worker/navigation.d.ts +10 -0
  122. package/dist/worker/navigation.d.ts.map +1 -0
  123. package/dist/worker/navigation.js +34 -0
  124. package/dist/worker/navigation.js.map +1 -0
  125. package/dist/worker/network.d.ts +4 -0
  126. package/dist/worker/network.d.ts.map +1 -0
  127. package/dist/worker/network.js +24 -0
  128. package/dist/worker/network.js.map +1 -0
  129. package/dist/worker/print.d.ts +14 -0
  130. package/dist/worker/print.d.ts.map +1 -0
  131. package/dist/worker/print.js +49 -0
  132. package/dist/worker/print.js.map +1 -0
  133. package/dist/worker/recent-pages.d.ts +14 -0
  134. package/dist/worker/recent-pages.d.ts.map +1 -0
  135. package/dist/worker/recent-pages.js +53 -0
  136. package/dist/worker/recent-pages.js.map +1 -0
  137. package/dist/worker/render.d.ts +5 -2
  138. package/dist/worker/render.d.ts.map +1 -1
  139. package/dist/worker/render.js +16 -6
  140. package/dist/worker/render.js.map +1 -1
  141. package/dist/worker/text.d.ts +25 -0
  142. package/dist/worker/text.d.ts.map +1 -0
  143. package/dist/worker/text.js +82 -0
  144. package/dist/worker/text.js.map +1 -0
  145. package/dist/zoom/destination.d.ts +18 -0
  146. package/dist/zoom/destination.d.ts.map +1 -0
  147. package/dist/zoom/destination.js +56 -0
  148. package/dist/zoom/destination.js.map +1 -0
  149. package/package.json +6 -5
package/README.md CHANGED
@@ -24,25 +24,85 @@ The view keeps only the pages near the viewport in the DOM and paints each in tw
24
24
 
25
25
  - **Layout.** Every page's size comes from its displayed size in points, the zoom and the view rotation. The pages stack in one column with a gap. The offsets are prefix sums, so finding the page at a scroll position is a binary search, and a zoom change costs one pass over the pages (`PageLayout`).
26
26
  - **Virtualisation.** The viewer mounts a shell for each page in view, plus a margin of 2 pages or one viewport each side, whichever is larger. A shell that leaves the margin aborts its renders. If a result still arrives for that page, the viewer drops it and never draws it. Scroll handling reads the DOM first and writes it once per animation frame.
27
- - **Canvases.** A shell borrows its canvas from a pool of 12, which caps the canvases' total size at 64 million device pixels (`CanvasPool`). Safari fails past an undocumented total canvas area, so the pool shrinks a canvas rather than exceed the cap. Rendered bitmaps stay in a 256 MB cache, which closes the bitmaps farthest from the current page first (`BitmapCache`).
27
+ - **Canvases.** A shell borrows its canvas from a pool of 12, which caps the canvases' total size at 40 million device pixels (`CanvasPool`). Safari fails past an undocumented total canvas area, so the pool shrinks a canvas rather than exceed the cap.
28
+ - **Detail canvases.** A page's canvas holds at most 8 million pixels (`BACKDROP_MAX_PIXELS`, below Safari's limit for one canvas). A page larger than that at the full pixel ratio, or one whose canvas the pool shrank, keeps its canvas as a backdrop. A detail canvas then covers the part in view at the full ratio. The detail canvas's size follows the viewport, not the zoom, so the page in view is sharp at every zoom up to 800 %.
29
+ - **Detail pool.** Detail canvases come from a second pool of 3 canvases and 24 million pixels. Together with the page pool, that is the 64 million pixels one pool held before. A page out of view gives its detail canvas back. When none is free, a page shows its backdrop until one is.
30
+ - **Bitmaps.** Rendered bitmaps stay in a 256 MB cache, which closes the bitmaps farthest from the current page first (`BitmapCache`).
28
31
  - **Progressive rendering.** A page first paints a blurry whole-page pass, at most 256 pixels wide, at `visible` priority. Then it paints sharp tiles, 512 CSS px × the device pixel ratio on a side, over the part in view. Pages in the margin get only the blurry pass, at `prefetch` priority. A canvas is resized only when the new pixels are ready, so the page never flashes white.
29
- - **Zoom.** The modes are fit width, fit page, actual size (96 CSS px per inch) and 10–800 %. Zoom comes from ctrl/cmd+wheel, trackpad pinch (ctrl+wheel, or Safari's gesture events), touch pinch and the `+`, `-` and `0` keys. The document point under the cursor stays where it is: always vertically, and horizontally while the pages are wider than the viewport. Narrower pages are centred, so no horizontal scroll can keep it there. During a gesture the canvases stretch, and the sharp re-render waits until the gesture pauses for 150 ms.
32
+ - **Zoom.** The modes are fit width, fit page, actual size (96 CSS px per inch) and 10–800 %. Zoom comes from ctrl/cmd+wheel, trackpad pinch (ctrl+wheel, or Safari's gesture events), touch (below) and the `+`, `-` and `0` keys. The document point under the cursor stays where it is: always vertically, and horizontally while the pages are wider than the viewport. Narrower pages are centred, so no horizontal scroll can keep it there. During a gesture the canvases stretch, and the sharp re-render waits until the gesture pauses for 150 ms.
33
+ - **Touch.** The viewer handles touch itself, and its root has `touch-action: none`, so the browser's page zoom never fights it. The browser still zooms the rest of the page, so accessibility zoom keeps working. A pen pans like a finger until a mode draws with it; the mouse stays the browser's.
34
+ - **Gestures.** One finger pans once it moves 10 px, and a flick carries the page on as it slows. Two fingers pinch: the document point that started under them stays under them, even when they also move together. At fit width a double tap zooms in; at any other zoom it returns to fit width. A finger held still for half a second is left to the browser, so a long press still selects text.
35
+ - **Canvas size on touch devices.** A phone or tablet can't hold the desktop's canvases: iOS Safari reloads a tab whose canvases pass 224–384 MB in all. With a coarse pointer, every canvas holds at most 5 million pixels; on a tablet whose window covers more than 5 million device pixels, the page in view shows its backdrop rather than a detail canvas.
36
+ - **Memory on touch devices.** The two pools and the bitmap cache together stay under 184 MB by default. On a device that reports 2 GB of memory or less (`navigator.deviceMemory`, in Chromium) the limit is 116 MB, and on one that reports 4 GB or more, 304 MB. `createViewer`'s options override each budget, and `device` gives the hints the budgets are chosen from instead of detecting them.
30
37
  - **Tall documents.** A document taller than 16 million CSS px at the chosen zoom gets its zoom capped, because browsers stop scrolling near that height.
38
+ - **Page appearance.** `setAppearance("sepia" | "dark" | "original")`, or High contrast with two colours (`{ kind: "high-contrast", ink, paper }`), draws the pages in other colours. Images and annotations keep theirs ([`@laminapdf/render`](../render/README.md) says how). The pages in view paint again, a quick pass then sharp tiles, and the scroll position stays where it was. Other mounted pages give their canvas back and paint once they come into view. Until a page's pixels arrive, its shell shows `--lamina-page-paper` (white by default), so set it to the appearance's paper. The thumbnails follow, and `getState().appearance` says which appearance is shown.
31
39
 
32
40
  **API.**
33
41
 
34
42
  | Member | What it does |
35
43
  | --- | --- |
36
- | `createViewer({ client, margin?, gap?, pool?, cacheBytes?, settleMs?, zoom? })` | Makes a viewer over a `ViewerClient`. |
44
+ | `createViewer({ client, margin?, gap?, pool?, detailPool?, cacheBytes?, backdropMaxPixels?, canvasMaxPixels?, device?, settleMs?, zoom?, text?, links?, history? })` | Makes a viewer over a `ViewerClient`. `text` is on by default; `false` leaves the text layer out, and an object sets its `outline`, `untaggedLabel` and `onSelection`. `links` is on by default too; an object sets its `href`, `onExternal` and `words` (below). `history.max` caps the entries kept (default 100). |
37
45
  | `mount(container)`, `open(document)`, `destroy()` | Puts it on the page, shows a document, takes it down. |
38
46
  | `goToPage(index, { anchor })`, `setZoom(zoom, { anchor })`, `rotate(delta)` | Navigation. `zoom` is a mode or a percentage. |
47
+ | `goToDestination(target)` | Goes to an outline item's or a named destination's target (below). |
48
+ | `jumpToPage(index)`, `jumpToDestination(target)` | Like `goToPage` and `goToDestination`, but recorded as history jumps, so Back returns to where the view was. |
49
+ | `history` | Back and forward through the jumps (below). |
39
50
  | `getState()`, `subscribe(listener)` | The view state (`currentPage`, `pageCount`, `zoom`, `percent`, `rotation`, `scrollTop`, `visibleRange`), for `useSyncExternalStore`. |
40
51
  | `on("pagechange" \| "zoomchange" \| "renderstats", …)`, `stats()` | Events and counters. `renderstats` counts renders, for measuring performance. |
41
52
  | `addLayer({ name, onMount, onUnmount, onZoom })` | Mounts a layer into each page. |
53
+ | `keepMounted(pages)` | Keeps these pages mounted wherever the view scrolls, replacing the previous set; `[]` releases them. The text layer pins the pages a selection touches. |
42
54
  | `pointAt(x, y)`, `positionOf(point)` | Converts between viewport positions and document points. |
43
55
  | `MIN_ZOOM`, `MAX_ZOOM` | The bounds of a percentage zoom, 10 and 800, for a zoom control's range. |
44
56
 
45
- **Layers.** Each page shell stacks a canvas and three slots above it: `div.lamina-layer-text`, `div.lamina-layer-annot` and `div.lamina-layer-highlight`. The coming text layer, find highlights and links will mount there through `addLayer`. A layer with another name gets its own slot on top.
57
+ **Layers.** Each page shell stacks a canvas and three slots above it: `div.lamina-layer-text`, `div.lamina-layer-annot` and `div.lamina-layer-highlight`. The text layer fills the first, links the second and find highlights the third, through `addLayer`. A layer with another name gets its own slot on top. Every slot above the text lets the pointer through (`pointer-events: none`), so text stays selectable under it; an element a layer wants clicked, such as a link's anchor, sets `pointer-events: auto` on itself.
58
+
59
+ **Text.** The text layer makes every page's text selectable, copyable and readable by screen readers, whichever backend draws the page.
60
+ - **Spans.** Each text run of Lamina PDF's extraction gets one transparent span, placed from its glyphs' quads, never from the renderer's. A rotated or vertical run gets a rotated span, and a span reads right to left when its first letter does. The spans sit in a box sized in points, which one CSS transform scales and turns to the page, so a zoom or a rotation moves no span.
61
+ - **Selection.** Only the spans are selectable. A drag runs from one page into the next and never takes in a canvas or a gap. A drag that leaves the viewer also highlights your app's text; set `user-select: none` on text you want to keep out. Copy, the pinned pages and `onSelection` keep to the part inside the viewer either way. Keep `user-select: none` off every ancestor of the viewer: Firefox then stops selecting. The pages a selection touches stay mounted while it lasts. Ctrl/⌘+A in the viewer selects the text of the mounted pages only.
62
+ - **Copy** writes the selected text as plain text and as HTML, in one of two modes:
63
+ - **By paragraph** (the default) follows the reading order Lamina PDF's extraction finds, so a selection across two columns copies the left column, then the right. A paragraph's lines join into one line, hyphenated words at a line's end join again, ligatures become their letters, and a blank line separates paragraphs.
64
+ - **Exact** keeps the layout's lines: a space at a gap, and a new line at each new baseline and between pages. A table's lines keep their breaks in both modes.
65
+ - **`copySelection(mode)`** copies in either mode from a command or a button. Call it from a click or key handler: browsers refuse clipboard writes outside one, and it then resolves `false`.
66
+ - **Column selection:** an Alt/Option-drag selects the text inside a rectangle, such as one column of a page. Setting `columnSelect` makes a plain drag do the same.
67
+ - **Selection events:** `onSelection` and the viewer's `selectionchange` event give the app the selected text, its client rectangles, its pages and the pointer that made it. `settled` is false during a drag and true once the pointer is up, when a toolbar may show; `column` marks a column selection.
68
+ - **Structure.** For a tagged document, a hidden tree of ARIA elements follows the structure tree. Headings carry their levels, and figures their alternate text; paragraphs, lists and tables keep their roles. Each element owns its text spans through `aria-owns`, matched by page and marked-content ID (the number a tagged PDF gives each piece of a page's content), so a screen reader reads the document in structure order. For a document without a structure tree, a screen reader hears "Untagged document" once (`untaggedLabel`).
69
+
70
+ The document Web Worker reads each page's text at `background` priority, after the tiles in view, and caches the text of the last 24 pages. Text needs the extract module, which the document Web Worker loads once the render backend is ready, so the first page never waits for it. Selection colours are the app's: style `.lamina-text-layer span::selection`, since the viewer adds no style sheet.
71
+
72
+ **Find.** `viewer.find` searches the whole document and highlights what it finds.
73
+ - **How it searches.** `find(query, { matchCase, wholeWords, matchDiacritics })` starts from the current page, reaches the last page and wraps to the first. The document Web Worker searches four pages per call, at `background` priority, so the pages in view render first and scrolling never waits. It keeps each page's searchable text in a cache of its own, up to 32 MB, so the next query, such as one you typed more letters into, searches the pages it has already read without reading their text again.
74
+ - **What it compares.** Find normalises text the way pdf.js does, so the counts match: ligatures unfolded, soft hyphens dropped, a word split by a hyphen at a line's end joined, white space collapsed. Case and diacritics are ignored unless asked, and diacritics are every combining mark: Latin accents, Hebrew points, Arabic harakat, Indic vowel signs. Whole words means no letter or digit runs on at either end.
75
+ - **Results.** Matches stream in by page: `getState()` gives `total`, `current`, `searched`, `pagesWithoutText` and `done` as matches arrive. The first match on or after the current page shows as soon as it's found. `next()` and `previous()` move in document order and wrap, scrolling a match to the viewport's centre when it's out of view.
76
+ - **The list of results.** `results()` lists every match found so far in document order, each with its `ordinal`, its `page` and a `snippet` of `{ before, match, after }`. The snippet keeps up to about 40 characters of the page's text on each side, cut at a word, with the match as the page spells it. `goTo(ordinal)` makes one current and scrolls it into view, and `next()` and `previous()` go on from there. The list is the same array until find's state next changes, so a React component can read it on each render.
77
+ - **Cancelling.** A new query, or `close()`, stops the search under way; its late results never show.
78
+ - **Highlights.** Every match on a mounted page gets a box with the class `lamina-find-match` in the `highlight` slot; the current match also has `lamina-find-current`. Colour them with `--lamina-find-match` and `--lamina-find-current`; the current one also has an outline, `--lamina-find-current-outline`, so it never differs by colour alone. The boxes take no pointer events, so they never get in a selection's way.
79
+
80
+ **Destinations.** `ViewerClient.outline()` reads the document's outline in the document Web Worker, and `namedDestination(name)` finds one named destination. Each item's target is a page and a view in page space: points from the displayed page's top-left, y down, whichever coordinates the file used. `goToDestination(target)` follows the target's view (ISO 32000-2 §12.3.2.2). It applies the target's zoom, if it has one, and then puts the target's point at the viewport's top-left:
81
+ - **A point** (`at`, from `/XYZ`) at its zoom, or at the current zoom when the file gives none.
82
+ - **Fit the page** (`fit`, from `/Fit` and `/FitB`).
83
+ - **Fit the width** from a top (`fit-width`, from `/FitH` and `/FitBH`), or the height from a left (`fit-height`, from `/FitV` and `/FitBV`).
84
+ - **Fit a rectangle** (`fit-rect`, from `/FitR`).
85
+
86
+ A left the file leaves out keeps the current horizontal scroll, and a top it leaves out goes to the page's top. A view rotated by `rotate()` turns the point with the page, and a fit always fits the viewport's own width or height, as in pdf.js.
87
+
88
+ **Links.** The link layer puts an anchor over each link on a mounted page, from Lamina PDF's reading of the page's link annotations (`ViewerClient.pageLinks(index)`), never the renderer's. Each link does one of three things, and none runs a script or program the file names:
89
+ - **Inside the document.** A link to a destination, or one of the named actions Next page, Previous page, First page and Last page, goes there as a history jump. Make `links.href(page)` return the app's address for that page. It becomes the anchor's `href`, so a middle click or "Open in new tab" opens the same document there.
90
+ - **To the web.** Only `http:`, `https:` and `mailto:` addresses may open, and only after the app confirms. A click, a middle click or Enter calls `links.onExternal(link)`, with the address normalised (an international host in punycode) and split around its host for showing it. The anchor has no `href`, so no browser menu can open it unasked; its title shows the address. `externalLink(uri)` gives the app the same rules.
91
+ - **Everything else does nothing.** A link to another file, an action such as Launch or JavaScript, a refused address (`javascript:`, `file:`, `data:`) or a destination missing from the file gets no `href`, and its title says why.
92
+
93
+ Anchors follow page order, so Tab reaches a page's links in order. Each is named by its `/Contents` or by what it does ("Link to page 3"); `links.words` gives those names in another language. Only the anchors take pointer events, so text beside a link still selects. Style them as `a.lamina-link`; the viewer adds no style sheet.
94
+
95
+ **History.** `viewer.history` records jumps: links, `jumpToPage`, `jumpToDestination`, find's moves and thumbnail clicks. Scrolling alone records nothing. Each jump saves the view it leaves, both scroll position and zoom, so Back returns there, not only to that page.
96
+ - `back()`, `forward()` and `goTo(id)` move the view; `getState()` and `subscribe()` say where Back and Forward go (`back`, `forward`, `current`, each an entry with a page point and a zoom).
97
+ - A jump that lands where the view already is adds nothing, and a new jump drops what Forward held.
98
+ - `onEntry(listener)` hears of each entry added, so an app can keep its own history in step: the web reader writes each jump into the browser's history through the address fragment, and `goTo(id)` answers the browser's Back.
99
+
100
+ **Thumbnails.** `new ThumbnailStrip(client, viewer, { width?, margin?, cacheBytes?, label?, name? })` makes a list of the pages as small pictures, for a sidebar. `mount(container)` puts it on the page, and `open(document)` shows the document the viewer opened. Size its `element` with CSS; it scrolls inside.
101
+ - **Like the viewer, it mounts only what is near its view.** It keeps the thumbnails in view and 4 either side. Each borrows a canvas from the strip's own pool, and a thumbnail scrolled away aborts its render.
102
+ - **Renders wait for the main view.** Thumbnails render at `background` priority, so the pages in view always come first. Bitmaps stay in a cache of their own, 32 MB by default.
103
+ - **It follows the viewer.** The current page is marked `aria-selected` and scrolled into the strip; a rotation turns every thumbnail.
104
+ - **Keyboard and pointer.** A click, or Enter or Space, goes to that page. The arrow keys, Home and End move the focus, and only one thumbnail is in the Tab order.
105
+ - **Names.** Each thumbnail is named by its page label and number ("Page iv (4 of 120)") and captioned with its label. For another language, pass `label` to replace both and `name` to replace the list's own name.
46
106
 
47
107
  **Tuning.** The margin, pool size, pixel cap, cache budget and settle delay are measured by the perf harness ([Performance](#performance)); the first full run kept them.
48
108
 
@@ -55,7 +115,11 @@ The client starts the Web Worker and talks to it; you call `ViewerClient`'s meth
55
115
  | Event | Source | Data | Meaning |
56
116
  | --- | --- | --- | --- |
57
117
  | `warning` | Web Worker | a reader warning | for example, a repaired xref |
118
+ | `progress` | Web Worker | `{ loaded, total }` | bytes of a remote document read so far, and its size |
58
119
  | `render-start` | Web Worker | `{ page, scale }` | a render began, for measuring performance |
120
+ | `render-fetching` | Web Worker | `{ key }` | a remote document's render stopped to fetch bytes; `render-start` follows |
121
+ | `network` | Web Worker | `{ worker, index, record }` | the Web Worker made a network request (`NetworkRecord`: URL, method, what made it, bytes, failed) |
122
+ | `csp-violation` | Web Worker | `{ worker, index, violation }` | the Web Worker's Content Security Policy blocked a request |
59
123
  | `render-slow` | page | `{ id, page }` | the soft timeout passed, counted from `render-start`: waiting in the queue isn't slow |
60
124
  | `render-stuck` | page | `{ id, page, needsPassword }` | an encrypted document's render passed the hard cap |
61
125
  | `crashed` | page | `{ reason }` | the Web Worker crashed |
@@ -63,6 +127,8 @@ The client starts the Web Worker and talks to it; you call `ViewerClient`'s meth
63
127
  | `password-required` | page | — | the new Web Worker can't reopen without the password |
64
128
  | `restart-failed` | page | `{ reason, error }` | a restart failed (for example, the backend wouldn't load again) |
65
129
 
130
+ **Network requests:** the Web Worker counts every request it makes from the moment it starts, with `watchNetwork`, which this package also exports for the page. The function wraps `fetch`, `XMLHttpRequest`, `WebSocket` and `sendBeacon`, and reads everything else from Resource Timing, so a reader can show what left the device.
131
+
66
132
  ### How it behaves
67
133
 
68
134
  - **Priorities and coalescing:** the Web Worker runs one call at a time, the highest priority first, FIFO within one.
@@ -72,6 +138,8 @@ The client starts the Web Worker and talks to it; you call `ViewerClient`'s meth
72
138
  - A queued render is dropped.
73
139
  - A running one finishes, because synchronous WebAssembly can't be interrupted. Its late answer's bitmap is closed unpainted (`onDiscard`).
74
140
  - (`@laminapdf/sdk/worker` itself rejects with a `cancelled` LaminaPdfError; the viewer maps it to `AbortError`.)
141
+ - An open is the exception. A cancel can reach the page after the Web Worker already opened the new file and closed the old one. So after a cancelled open, `open()` asks the Web Worker which document it holds (`currentDocument`). If this open made it, the cancel came too late: `open()` resolves with that document after all, and the page and the Web Worker agree. Otherwise it rejects with `AbortError`, and the old document stays open.
142
+ - Either way, an aborted `open()` settles only once the Web Worker has finished the open it was running. `stop()` ends a stuck one at once.
75
143
  - **Timeouts:** the page keeps the timers, because a Web Worker inside a render can't post anything.
76
144
  - Defaults are `soft` 10 s (`render-slow`) and `hard` 120 s.
77
145
  - At the hard cap the client calls `stop("hard-timeout")`. For a document that needed a password, it emits `render-stuck` instead and waits for the user's `stop()`.
@@ -85,10 +153,16 @@ The client starts the Web Worker and talks to it; you call `ViewerClient`'s meth
85
153
  - **Sources:**
86
154
  - A `Blob`/`File` is sent by reference, and the Web Worker reads it in 4 MiB `slice()`s.
87
155
  - Bytes are copied, and kept on the page for a reopen.
156
+ - `{ url }` is a remote file the Web Worker fetches itself, so its bytes never reach the page:
157
+ - It reads the file with HTTP Range requests through `@laminapdf/sdk`'s `httpRangeSource`, in 64 KiB blocks with one block read ahead, and keeps up to 64 MiB of them.
158
+ - Lamina PDF opens the file range by range, and a render that needs bytes not yet read fetches them and draws again, so page 1 of a large file needs only a small part of it.
159
+ - While a render fetches, it emits `render-fetching` and its timeouts pause until it draws again (`render-start`): a slow network is never a stuck render. The Web Worker still runs one call at a time, so other calls wait for that fetch.
160
+ - Requests send no cookies or referrer and skip the HTTP cache.
161
+ - A server that ignores `Range` sends the whole file, which the Web Worker accepts up to 256 MiB (`source-budget-exceeded` above that).
88
162
 
89
163
  ## For contributors
90
164
 
91
- The viewer is the web client of [ADR 0009](../../docs/decisions/0009-web-client-architecture.md); it was built in [C3a](../../docs/todos/done/C3a-viewer-worker-rpc.md) (the document worker and its typed RPC) and [C3b](../../docs/todos/done/C3b-viewer-virtualiser-and-zoom.md) (the viewer). [C3c](../../docs/todos/done/C3c-viewer-perf-harness.md) measures the tuning values with `renderstats`. The layers are for [C5a](../../docs/todos/ready/C5a-text-layer-and-selection.md) (text), [C5b](../../docs/todos/ready/C5b-find-in-document.md) (find) and [C6b](../../docs/todos/ready/C6b-links-and-history.md) (links); C4c will read documents by range through `@laminapdf/sdk`'s `RangeSource`. Cancellation follows ADR 0009 §3.5, and warnings are [ADR 0003](../../docs/decisions/0003-reader-tolerance-and-limits.md)'s.
165
+ The viewer is the web client of [ADR 0009](../../docs/decisions/0009-web-client-architecture.md); it was built in [C3a](../../docs/todos/done/C3a-viewer-worker-rpc.md) (the document worker and its typed RPC) and [C3b](../../docs/todos/done/C3b-viewer-virtualiser-and-zoom.md) (the viewer). [C3c](../../docs/todos/done/C3c-viewer-perf-harness.md) measures the tuning values with `renderstats`. The layers are for [C5a](../../docs/todos/done/C5a-text-layer-and-selection.md) (text), [C5b](../../docs/todos/done/C5b-find-in-document.md) (find) and [C6b](../../docs/todos/done/C6b-links-and-history.md) (links); C4c will read documents by range through `@laminapdf/sdk`'s `RangeSource`. Cancellation follows ADR 0009 §3.5, and warnings are [ADR 0003](../../docs/decisions/0003-reader-tolerance-and-limits.md)'s.
92
166
 
93
167
  ### Architecture
94
168
 
@@ -113,11 +187,20 @@ There is one protocol, not two: the viewer's worker is `@laminapdf/sdk/worker`'s
113
187
  | Method | Params | Result | Priority |
114
188
  | --- | --- | --- | --- |
115
189
  | `initBackend` | `{ backend: "pdfium" \| "hayro", wasm? }` | `{ name, version }` | document. Sent by `create()`, before a file is chosen, so the WebAssembly downloads in parallel with file selection. |
116
- | `openDocument` | `source` (`Blob`, `ArrayBuffer`, `Uint8Array`), `{ password?, limits?, renderLimits? }` | `{ pageCount, pages, needsPassword, backend }` | document |
190
+ | `openDocument` | `source` (`Blob`, `ArrayBuffer`, `Uint8Array`), `{ password?, limits?, renderLimits? }`, `ticket?` (the client's number for this open) | `{ pageCount, pages, needsPassword, backend }` | document |
191
+ | `currentDocument` | — | `{ document, ticket }` of the open document, or `undefined`: `open()` asks after a cancelled open | document |
117
192
  | `closeDocument` | — | — | document |
118
193
  | `pageInfo` | `index` | `PageInfo` (displayed size in points, rotation, ID, label) | document |
194
+ | `find` | `query`, `FindOptions`, `pages` | `FindPageResult[]`: each page's matches as quads, and whether it has no text | `background` |
119
195
  | `render` | ADR 0004 `RenderRequest` | `{ bitmap: ImageBitmap, width, height }` (transferred) | `visible` > `prefetch` > `background` |
120
196
  | `memory` | — | `WorkerMemory`: the bytes of the backend's and Lamina PDF's WebAssembly memories | document. `client.memory()`; the perf harness samples it. |
197
+ | `pageText` | `index` | `PageTextData`: the page's runs and glyph quads | `background` |
198
+ | `structure` | — | `StructureData`: whether the document is tagged, and its structure tree | document |
199
+ | `outline` | — | `OutlineNode[]`: the outline, each item's target in page space | document |
200
+ | `namedDestination` | `name` | `Target \| undefined` | document |
201
+ | `pageLinks` | `index` | `PageLink[]`: the page's links in page space, by `kind`; the last 24 pages' are cached | document |
202
+ | `reflow` | — | `Reflow`: the document for reader mode, its blocks in the structure tree's order with figures, formulas and tables as crops, or why not | document. `client.reflow()`; the extract module only |
203
+ | `networkLog` | — | `WorkerNetworkLog`: every request and blocked request since the Web Worker started | document. `client.networkLog()`: what the `network` and `csp-violation` events reported, those sent before anyone listened included; `index` merges the two. |
121
204
 
122
205
  `client.call(method, params, { priority, signal })` is typed by the `Methods` map: an unknown method or wrong params fails `tsc` (`test/types.test.ts`).
123
206
 
@@ -140,7 +223,15 @@ The browser suites run in Chromium, Firefox and WebKit over the built package: r
140
223
  - slow, stuck and stopped renders;
141
224
  - crashes, including an encrypted file;
142
225
  - the password count.
226
+ - `test/find-parity.test.ts` (Node) checks find's counts against pdf.js's find controller on every case of `fixtures/text/search.json`.
143
227
  - Unit tests sit next to their modules (`src/**/*.test.ts`) and run in Node. They cover the layout's cost, counted in steps, and the fit modes for portrait, landscape and rotated pages. They also cover zoom anchoring, tiles, cache eviction and the pool's caps. `test/dependencies.test.ts` checks that `src/` imports no UI framework, and `test/types.test.ts` checks the RPC types.
228
+ - `test/browser/navigation.browser.test.ts` covers the thumbnails strip over a 1,000-page document:
229
+ - while the whole strip scrolls, no more than the thumbnails in view and 4 either side mounted;
230
+ - a visible render, queued behind thumbnails, running first;
231
+ - a click and the keyboard going to a page;
232
+ - page labels in the names;
233
+ - the outline and a named destination of the links-and-outlines reference PDF landing on their pages.
234
+ - Unit tests sit next to their modules (`src/**/*.test.ts`) and run in Node. They cover the layout's cost, counted in steps, and the fit modes for portrait, landscape and rotated pages. They also cover zoom anchoring, tiles, cache eviction and the pool's caps, and where each kind of destination puts the view at each rotation. `test/dependencies.test.ts` checks that `src/` imports no UI framework, and `test/types.test.ts` checks the RPC types.
144
235
  - Two demo pages are manual checks: run `pnpm --filter @laminapdf/viewer exec vite examples`. `examples/viewer-demo.html` is the viewer, with zoom buttons; `examples/rpc-demo.html` draws page 1 through the RPC alone. The perf harness has its own page, `perf/page/` ([Performance](#performance)).
145
236
 
146
237
  ### Performance
@@ -160,7 +251,8 @@ It writes `target/viewer-perf/<browser>.json` and `summary.md`, and never fails
160
251
  | Scenario | Measures | Target |
161
252
  | --- | --- | --- |
162
253
  | Open the 10-page file, warm (after a reload) | time to the first page's first paint | ≤ 700 ms |
163
- | The same, cold, on Chrome DevTools' Fast 4G (Chromium only) | time from navigation to the first page | ≤ 3 s |
254
+ | The same, cold, on Chrome DevTools' Fast 4G (Chromium only), the file on the device | time from navigation to the first page | ≤ 3 s |
255
+ | The same, cold, the file from a link (Range requests, as a `#url=` link reads it) | time from navigation to the first page | ≤ 3 s (reported) |
164
256
  | Scroll the 1,000-page file end to end, twice, with wheel steps every 20 ms; stop at a quarter, a half and three quarters | the longest main-thread task, time to sharp after each stop, peak memory, memory after each pass, cancelled renders that painted | no task > 50 ms; sharp ≤ 300 ms; ≤ 600 MB; second pass ≤ first + 5 %; 0 |
165
257
  | Fling across the 300 image pages, then stop | time to sharp | ≤ 300 ms |
166
258
  | Three ctrl+wheel bursts in and out on the 10-page file | the longest frame, time to sharp after each burst | reported |
@@ -171,7 +263,9 @@ It writes `target/viewer-perf/<browser>.json` and `summary.md`, and never fails
171
263
 
172
264
  **The reference machine.** The official numbers are the nightly lane's, from the Mac that hosts the self-hosted runners, with nothing else running on it. Each report ends with the machine it ran on (CPU, cores, memory, OS). Numbers from other machines, CI containers included, are relative: compare them with each other, not with the targets.
173
265
 
174
- **First measurements and tuning.** The first full run (Chromium 153 on a 4-core Linux container, 2026-11-05) came in under every scrolling and memory target, a first reading until the reference machine's numbers arrive. It had no long task while scrolling, pages were sharp 0–17 ms after a scroll stopped and 33 ms after a fling, memory peaked at 302 MB, the second pass ended 0.5 % above the first, and no cancelled render painted. So the defaults above stay: a margin of 2 pages or one viewport, a pool of 12 canvases and 64 million pixels, a 256 MB bitmap cache, 512 CSS px tiles and a 150 ms settle. It missed one target and found one slow spot, both for [C7c](../../docs/todos/ready/C7c-performance-gates-and-launch.md):
266
+ **First measurements and tuning.** The first full run (Chromium 153 on a 4-core Linux container, 2026-11-05) came in under every scrolling and memory target, a first reading until the reference machine's numbers arrive. It had no long task while scrolling, pages were sharp 0–17 ms after a scroll stopped and 33 ms after a fling, memory peaked at 302 MB, the second pass ended 0.5 % above the first, and no cancelled render painted. So the defaults above stay: a margin of 2 pages or one viewport, a pool of 12 canvases and 64 million pixels, a 256 MB bitmap cache, 512 CSS px tiles and a 150 ms settle. It missed one target and found one slow spot, both for [C7c](../../docs/todos/done/C7c-performance-gates-and-launch.md):
175
267
 
176
268
  - **The cold first page took 4.2 s on Fast 4G (target 3 s).** The download alone takes about 3.7 s at Fast 4G's 1 MB/s: PDFium's WebAssembly (2.2 MB gzipped), Lamina PDF's base module (0.4 MB) and the 1 MB file.
269
+
270
+ **Cold first page (C7d, 2026-11-10).** By then the cold page took 5.2 s, and a trace of the worker's requests showed why. Lamina PDF's base module and PDFium downloaded one after the other; the link layer's first call needed the extract module (710 KB), and the worker answers one call at a time, so the first page's render waited for that download; and the harness fetched the whole 1 MB file over the throttled network, which a file chosen on the device never costs. Now `ViewerClient.create` compiles PDFium on the page while the worker loads its base module, the text, structure, reading-order and link calls wait for the open document's first drawn page (2 s at most), and the extract module loads after it. A file on the device paints its first page in 3.3 s, a linked 1 MB file in 4.75 s (opening reads most of this file, whose page objects are spread through it). The release gate holds the device case to the target plus its margin; the linked case is reported.
177
271
  - **Zooming in took about 1.2 s to sharp, with a 317 ms frame.** Zooming out took about 300 ms. The plan sets no zoom target.
package/dist/client.d.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  import type { RenderRequest } from "@laminapdf/render";
2
2
  import { type WorkerInitOptions, type WorkerWasmSource } from "@laminapdf/sdk/worker";
3
- import { type BackendInit, type MethodName, type OpenedDocument, type Params, type Priority, type RenderedBitmap, type Result, type SourceInit, type ViewerOpenOptions } from "./protocol.js";
3
+ import type { FindOptions } from "./find/fold.js";
4
+ import { type BackendInit, type LoadProgress, type MethodName, type NetworkRecord, type OpenedDocument, type Params, type PolicyViolation, type PrintOptions, type Priority, type RenderedBitmap, type Result, type SourceInit, type ViewerOpenOptions, type WorkerNetworkLog } from "./protocol.js";
4
5
  /** `ViewerClient.create`'s options: the backend, Lamina PDF's WebAssembly, the timeouts, the worker and a signal to stop starting. */
5
6
  export interface ViewerOptions {
6
7
  /** The render engine; PDFium needs its `.wasm` URL from your bundler (`pdfium.wasm?url`). */
7
8
  readonly backend: BackendInit;
8
- /** Where the worker loads Lamina PDF's own WebAssembly from (`@laminapdf/sdk/worker`'s `init`). */
9
+ /**
10
+ * Where the worker loads Lamina PDF's own WebAssembly from (`@laminapdf/sdk/worker`'s `init`).
11
+ * The worker loads the extract module itself, for the text layer, once the backend is ready.
12
+ */
9
13
  readonly lamina?: WorkerWasmSource | WorkerInitOptions;
10
14
  /** Render timeouts in ms (`soft` emits `render-slow`; `hard` restarts or emits `render-stuck`). */
11
15
  readonly timeouts?: {
@@ -26,12 +30,30 @@ export interface ViewerEvents {
26
30
  readonly code: string;
27
31
  readonly message: string;
28
32
  };
33
+ /** How much of a remote document the worker has fetched (bytes; the size). */
34
+ progress: LoadProgress;
29
35
  /** The worker started drawing a render (so a performance test can see what the worker is busy with). */
30
36
  "render-start": {
31
37
  readonly page: number;
32
38
  readonly scale: number;
33
39
  readonly key: string;
34
40
  };
41
+ /** A remote document's render stopped drawing to fetch bytes it needs; `render-start` follows when it draws again. */
42
+ "render-fetching": {
43
+ readonly key: string;
44
+ };
45
+ /** The document worker made a network request (`worker` names the worker, so a restart's records stay apart). */
46
+ network: {
47
+ readonly worker: string;
48
+ readonly index: number;
49
+ readonly record: NetworkRecord;
50
+ };
51
+ /** The worker's Content Security Policy blocked a request it tried. */
52
+ "csp-violation": {
53
+ readonly worker: string;
54
+ readonly index: number;
55
+ readonly violation: PolicyViolation;
56
+ };
35
57
  /** A render passed the soft timeout: offer Stop. */
36
58
  "render-slow": {
37
59
  readonly id: number;
@@ -93,10 +115,61 @@ export declare class ViewerClient {
93
115
  get document(): OpenedDocument | undefined;
94
116
  /** Closes the document in the worker (the worker stays, ready for another `open`). */
95
117
  close(): Promise<void>;
118
+ /**
119
+ * Every request the document worker has made, and had blocked, since it started: what its
120
+ * `network` and `csp-violation` events reported, including those sent before anyone listened.
121
+ */
122
+ networkLog(options?: ViewerCallOptions): Promise<WorkerNetworkLog>;
96
123
  /** The worker's WebAssembly memory in bytes (see `WorkerMemory`), for measuring. */
97
124
  memory(options?: ViewerCallOptions): Promise<import("./protocol.js").WorkerMemory>;
98
125
  /** Page `index`'s size, rotation, ID and label. */
99
126
  pageInfo(index: number, options?: ViewerCallOptions): Promise<import("@laminapdf/wasm/text").PageInfoJs>;
127
+ /**
128
+ * Page `index`'s text runs and glyph quads, read by Lamina PDF (needs the extract or text
129
+ * module, loaded by default). At `background` priority unless `options` says otherwise.
130
+ */
131
+ pageText(index: number, options?: ViewerCallOptions): Promise<import("./protocol.js").PageTextData>;
132
+ /**
133
+ * Page `index`'s text blocks in reading order (Lamina PDF's extraction), for copy as paragraph.
134
+ * At `background` priority unless `options` says otherwise.
135
+ */
136
+ readingOrder(index: number, options?: ViewerCallOptions): Promise<import("./protocol.js").ReadingBlock[]>;
137
+ /**
138
+ * The matches of `query` on each of `pages`, at `background` priority unless `options` says
139
+ * otherwise, so renders run first. The find controller calls it a few pages at a time.
140
+ */
141
+ find(query: string, find: FindOptions, pages: readonly number[], options?: ViewerCallOptions): Promise<import("./protocol.js").FindPageResult[]>;
142
+ /** Whether the open document says it is tagged, and its structure tree when it has one. */
143
+ structure(options?: ViewerCallOptions): Promise<import("./protocol.js").StructureData>;
144
+ /**
145
+ * The open document for reader mode: its blocks in the structure tree's order, figures,
146
+ * formulas and tables as crops with their alternate text, or why its tree can't be trusted.
147
+ */
148
+ reflow(options?: ViewerCallOptions): Promise<import("@laminapdf/sdk").Reflow>;
149
+ /**
150
+ * The open document's outline (bookmarks): top-level items, each with its children and where
151
+ * it goes as a page and a page-space view; empty without one. Read when first asked for.
152
+ */
153
+ outline(options?: ViewerCallOptions): Promise<import("@laminapdf/wasm/text").OutlineNodeJs[]>;
154
+ /** Where the named destination `name` goes, or `undefined` when the document has no such name. */
155
+ namedDestination(name: string, options?: ViewerCallOptions): Promise<import("@laminapdf/wasm/text").TargetJs | undefined>;
156
+ /**
157
+ * What a properties view shows about the open document (`@laminapdf/sdk`'s `properties()`,
158
+ * read in the worker). It reads every object once: ask when the view opens.
159
+ */
160
+ properties(options?: ViewerCallOptions): Promise<import("@laminapdf/wasm/text").PropertiesJs>;
161
+ /**
162
+ * Page `index` drawn for printing at `print.dpi` with annotations as their print flags say, as
163
+ * a PNG, at `background` priority unless `options` says otherwise, so the pages in view draw first.
164
+ */
165
+ printPage(index: number, print: PrintOptions, options?: ViewerCallOptions): Promise<import("./protocol.js").PrintedPage>;
166
+ /**
167
+ * Every byte of the open remote file as it was opened, fetched where the block cache lacks
168
+ * them. A local file's bytes are the page's own: it never asks.
169
+ */
170
+ fileBytes(options?: ViewerCallOptions): Promise<Uint8Array<ArrayBufferLike>>;
171
+ /** Page `index`'s links, in annotation order, each with what following it does (the link layer asks as pages mount). */
172
+ pageLinks(index: number, options?: ViewerCallOptions): Promise<readonly import("@laminapdf/wasm/text").PageLinkJs[]>;
100
173
  /**
101
174
  * Renders `request` as an ImageBitmap (close it when done). Identical requests in flight are
102
175
  * drawn once. An aborted render rejects with `AbortError` and never paints.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}