@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
@@ -2,26 +2,78 @@
2
2
  const TILE_CSS = 512;
3
3
  /** The low-resolution pass: at most this many device px wide, and at most half the sharp scale. */
4
4
  const LOW_MAX_WIDTH = 256;
5
+ /**
6
+ * The most device pixels a page's backdrop canvas holds: well below Safari's 16.7 MP per canvas,
7
+ * and small enough that the mounted pages share the pool. A page larger than this at the full
8
+ * pixel ratio keeps its backdrop at a lower one and gets a detail canvas over the part in view.
9
+ */
10
+ export const BACKDROP_MAX_PIXELS = 8 * 1024 * 1024;
11
+ /**
12
+ * Device px per CSS px of the backdrop of a page `css` CSS px in size: `dpr`, or less so that the
13
+ * whole page fits `maxPixels` ({@link BACKDROP_MAX_PIXELS} by default; less on touch devices).
14
+ */
15
+ export function backdropRatio(dpr, css, maxPixels = BACKDROP_MAX_PIXELS) {
16
+ const pixels = css.width * dpr * css.height * dpr;
17
+ return pixels <= maxPixels ? dpr : dpr * Math.sqrt(maxPixels / pixels);
18
+ }
19
+ /** The smallest rectangle covering every one of `rects`; undefined when there are none. */
20
+ export function bounds(rects) {
21
+ const [first] = rects;
22
+ if (first === undefined)
23
+ return undefined;
24
+ let [x0, y0, x1, y1] = [first.x, first.y, first.x + first.width, first.y + first.height];
25
+ for (const r of rects) {
26
+ x0 = Math.min(x0, r.x);
27
+ y0 = Math.min(y0, r.y);
28
+ x1 = Math.max(x1, r.x + r.width);
29
+ y1 = Math.max(y1, r.y + r.height);
30
+ }
31
+ return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
32
+ }
33
+ /** Whether `outer` contains all of `inner`. */
34
+ export function contains(outer, inner) {
35
+ return (inner.x >= outer.x &&
36
+ inner.y >= outer.y &&
37
+ inner.x + inner.width <= outer.x + outer.width &&
38
+ inner.y + inner.height <= outer.y + outer.height);
39
+ }
5
40
  /** The render scale (output px per pt) of the low-resolution pass for a page `widthPt` wide. */
6
41
  export function lowScale(sharpScale, widthPt) {
7
42
  return Math.min(sharpScale * 0.5, LOW_MAX_WIDTH / Math.max(1, widthPt));
8
43
  }
44
+ /**
45
+ * The sharp scale (device px per pt) of a page `css` CSS px in size at layout scale `layoutScale`:
46
+ * `layoutScale × dpr`, unless the canvas pool could only `fit` fewer pixels than `wanted`, the page
47
+ * in whole pixels at that scale (`pagePixels`); then lowered to what fits. The canvas is then
48
+ * `pagePixels` at this scale, which never exceeds `fitted` on either side.
49
+ *
50
+ * `wanted` is in whole pixels, as the pool fits them: comparing `fitted` with the fractional CSS
51
+ * size instead takes the pool's rounding (79.33 px to 79) for a cap, which lowers the scale a
52
+ * hair below the full one and sends every page asking for a detail canvas it doesn't need.
53
+ */
54
+ export function sharpScale(layoutScale, dpr, css, fitted, wanted) {
55
+ if (fitted.width >= wanted.width && fitted.height >= wanted.height)
56
+ return layoutScale * dpr;
57
+ return layoutScale * Math.min(dpr, fitted.width / css.width, fitted.height / css.height);
58
+ }
9
59
  /**
10
60
  * The tiles (device px, in the page's pixel space at the sharp scale) covering `visible`, the
11
- * part of the page in view in CSS px (x, y from the page's top-left), clamped to the page.
61
+ * part of the page in view in CSS px (x, y from the page's top-left), clamped to `page`: the
62
+ * whole page in device px, as the renderer sizes it (`pagePixels` of `@laminapdf/render`), so no
63
+ * tile reaches past it. `ratio` is device px per CSS px.
12
64
  */
13
- export function tilesFor(visible, pageCss, dpr) {
14
- const pageW = Math.max(1, Math.floor(pageCss.width * dpr));
15
- const pageH = Math.max(1, Math.floor(pageCss.height * dpr));
16
- const side = Math.max(1, Math.round(TILE_CSS * dpr));
17
- const x0 = Math.max(0, Math.floor((visible.x * dpr) / side) * side);
18
- const y0 = Math.max(0, Math.floor((visible.y * dpr) / side) * side);
19
- const x1 = Math.min(pageW, Math.ceil(((visible.x + visible.width) * dpr) / side) * side);
20
- const y1 = Math.min(pageH, Math.ceil(((visible.y + visible.height) * dpr) / side) * side);
65
+ export function tilesFor(visible, page, ratio) {
66
+ if (visible.width <= 0 || visible.height <= 0)
67
+ return [];
68
+ const side = Math.max(1, Math.round(TILE_CSS * ratio));
69
+ const x0 = Math.max(0, Math.floor((visible.x * ratio) / side) * side);
70
+ const y0 = Math.max(0, Math.floor((visible.y * ratio) / side) * side);
71
+ const x1 = Math.min(page.width, Math.ceil(((visible.x + visible.width) * ratio) / side) * side);
72
+ const y1 = Math.min(page.height, Math.ceil(((visible.y + visible.height) * ratio) / side) * side);
21
73
  const tiles = [];
22
74
  for (let y = y0; y < y1; y += side) {
23
75
  for (let x = x0; x < x1; x += side) {
24
- tiles.push({ x, y, width: Math.min(side, pageW - x), height: Math.min(side, pageH - y) });
76
+ tiles.push({ x, y, width: Math.min(side, page.width - x), height: Math.min(side, page.height - y) });
25
77
  }
26
78
  }
27
79
  return tiles;
@@ -1 +1 @@
1
- {"version":3,"file":"tiles.js","sourceRoot":"","sources":["../../src/render/tiles.ts"],"names":[],"mappings":"AAKA,+EAA+E;AAC/E,MAAM,QAAQ,GAAG,GAAG,CAAC;AACrB,mGAAmG;AACnG,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,gGAAgG;AAChG,MAAM,UAAU,QAAQ,CAAC,UAAkB,EAAE,OAAe;IAC1D,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,OAAoG,EACpG,OAA4D,EAC5D,GAAW;IAEX,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACpE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACpE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACzF,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1F,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"tiles.js","sourceRoot":"","sources":["../../src/render/tiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { ByteRange, RenderSource } from "@laminapdf/render";
2
+ import { type RangeSource } from "@laminapdf/sdk";
3
+ /** Options for {@link HttpRangeByteSource.open}. */
4
+ export interface HttpRangeByteSourceOptions {
5
+ /** Requests are aligned to blocks of this many bytes (default 65 536). */
6
+ readonly blockSize?: number;
7
+ /** Whole blocks fetched after each range asked for (default 1). */
8
+ readonly readahead?: number;
9
+ /** The most bytes the cache keeps; the least recently used blocks go first (default 64 MiB). */
10
+ readonly cacheBytes?: number;
11
+ /**
12
+ * The largest file downloaded whole when the server ignores `Range` (default 256 MiB); above
13
+ * it the open fails with `source-budget-exceeded`.
14
+ */
15
+ readonly maxWholeBytes?: number;
16
+ /** Skip the browser's HTTP cache (default true). */
17
+ readonly noStore?: boolean;
18
+ /** Called after each fetch with the bytes received so far and the file's size. */
19
+ readonly onProgress?: (progress: {
20
+ readonly loaded: number;
21
+ readonly total: number;
22
+ }) => void;
23
+ /** Aborts the probe. */
24
+ readonly signal?: AbortSignal;
25
+ /** The `fetch` to use (default: the global one). */
26
+ readonly fetch?: typeof fetch;
27
+ }
28
+ /** A remote file as a `RangeSource` (for Lamina PDF) and a `RenderSource` (for the render backend). */
29
+ export declare class HttpRangeByteSource implements RangeSource, RenderSource {
30
+ #private;
31
+ readonly size: number;
32
+ readonly blockSize: number;
33
+ private constructor();
34
+ /**
35
+ * Probes `url` (its last 64 KiB: the size, and the part a reader reads first) and returns the
36
+ * source. A server that ignores `Range` sends the whole file, which is kept.
37
+ *
38
+ * @throws LaminaPdfError `fetch-failed` (`data.reason` `network` covers a refused CORS check,
39
+ * which the browser doesn't tell apart from being offline), `source-changed`,
40
+ * `source-budget-exceeded`, or the signal's reason.
41
+ */
42
+ static open(url: string, options?: HttpRangeByteSourceOptions): Promise<HttpRangeByteSource>;
43
+ /** The whole file, when the server sent it whole (then every read is answered from it). */
44
+ get whole(): Uint8Array | undefined;
45
+ /** Bytes received from the network so far (the probe's included), re-fetches of evicted blocks too. */
46
+ get loaded(): number;
47
+ /** The `length` bytes at `offset` if every block is cached, else undefined (`RenderSource`). */
48
+ readSync(offset: number, length: number): Uint8Array | undefined;
49
+ /**
50
+ * Fetches the blocks `ranges` touch (and the readahead after each) that aren't cached: the
51
+ * ranges of a render backend's `data-pending`.
52
+ */
53
+ fill(ranges: readonly ByteRange[], signal?: AbortSignal): Promise<void>;
54
+ /** `RangeSource.read`: fills, then reads from the cache. */
55
+ read(offset: number, length: number, options?: {
56
+ readonly signal?: AbortSignal;
57
+ }): Promise<Uint8Array>;
58
+ }
59
+ //# sourceMappingURL=http-range.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-range.d.ts","sourceRoot":"","sources":["../../src/source/http-range.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAqD,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIrG,oDAAoD;AACpD,MAAM,WAAW,0BAA0B;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gGAAgG;IAChG,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,oDAAoD;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9F,wBAAwB;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,oDAAoD;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CAC/B;AAqED,uGAAuG;AACvG,qBAAa,mBAAoB,YAAW,WAAW,EAAE,YAAY;;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAc3B,OAAO,eAON;IAED;;;;;;;OAOG;IACH,OAAa,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+BrG;IAED,2FAA2F;IAC3F,IAAI,KAAK,IAAI,UAAU,GAAG,SAAS,CAElC;IAED,uGAAuG;IACvG,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,gGAAgG;IAChG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAuB/D;IAED;;;OAGG;IACG,IAAI,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB5E;IAeD,4DAA4D;IACtD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAO3G;CA0DF"}
@@ -0,0 +1,284 @@
1
+ // A remote PDF read in the document worker with HTTP Range requests: `@laminapdf/sdk`'s
2
+ // httpRangeSource (tail-first probe, If-Range and ETag checks, the 200 fallback) with what a
3
+ // reader needs on top:
4
+ //
5
+ // - privacy: every request omits credentials and the referrer (ADR 0011 §3), and by default skips
6
+ // the HTTP cache, so the file is not kept on disk after the tab closes;
7
+ // - a block cache that the render backend reads synchronously (`readSync`, `RenderSource`): PDFium
8
+ // asks for bytes while it draws, and a miss makes the render throw `data-pending`, after which
9
+ // the worker fills the ranges asked for and draws again;
10
+ // - readahead, a byte budget (least recently used blocks go first) and progress;
11
+ // - a cap on the whole download a server without range support makes, until large files can be
12
+ // streamed to OPFS.
13
+ import { httpRangeSource, isLaminaPdfError, LaminaPdfError } from "@laminapdf/sdk";
14
+ // Only docsUrl: the package has no side effects, so the explain pages stay out of the worker.
15
+ import { docsUrl } from "@laminapdf/sdk/explain";
16
+ const DEFAULTS = { blockSize: 65_536, readahead: 1, cacheBytes: 64 * 1024 * 1024, maxWholeBytes: 256 * 1024 * 1024 };
17
+ /**
18
+ * The fetch every request of the source goes through: no cookies or credentials, no referrer, no
19
+ * HTTP cache unless asked, CORS mode. Each answer's body is counted as it arrives (the source's
20
+ * progress), and a full answer is cut off past `maxWholeBytes`, whether it says its length or not
21
+ * (chunked, or compressed so that its length isn't the file's).
22
+ */
23
+ function privateFetch(base, noStore, maxWholeBytes, hooks) {
24
+ return async (input, init) => {
25
+ const response = await base(input, {
26
+ ...init,
27
+ credentials: "omit",
28
+ referrerPolicy: "no-referrer",
29
+ mode: "cors",
30
+ ...(noStore ? { cache: "no-store" } : {}),
31
+ });
32
+ const whole = response.status === 200;
33
+ if (whole) {
34
+ const length = Number(response.headers.get("Content-Length") ?? Number.NaN);
35
+ if (Number.isFinite(length) && length > maxWholeBytes) {
36
+ await response.body?.cancel();
37
+ throw tooLarge(length, maxWholeBytes);
38
+ }
39
+ hooks.whole();
40
+ }
41
+ if (response.body === null)
42
+ return response;
43
+ let total = 0;
44
+ const counted = response.body.pipeThrough(new TransformStream({
45
+ transform(chunk, controller) {
46
+ total += chunk.length;
47
+ if (whole && total > maxWholeBytes) {
48
+ controller.error(tooLarge(total, maxWholeBytes));
49
+ return;
50
+ }
51
+ hooks.received(chunk.length);
52
+ controller.enqueue(chunk);
53
+ },
54
+ }));
55
+ const { status, statusText, headers } = response;
56
+ return new Response(counted, { status, statusText, headers });
57
+ };
58
+ }
59
+ function tooLarge(size, budget) {
60
+ return new LaminaPdfError({
61
+ code: "source-budget-exceeded",
62
+ kind: "limit",
63
+ message: "the server doesn't send parts of the file, and the whole file is larger than the reader downloads",
64
+ data: { reason: "whole-download", size, budget },
65
+ docsUrl: docsUrl("source-budget-exceeded"),
66
+ });
67
+ }
68
+ /** httpRangeSource reports a throwing fetch as `fetch-failed`; the cap's own error is its cause. */
69
+ function unwrapCap(e) {
70
+ return isLaminaPdfError(e, "fetch-failed") && isLaminaPdfError(e.cause, "source-budget-exceeded") ? e.cause : e;
71
+ }
72
+ /** A remote file as a `RangeSource` (for Lamina PDF) and a `RenderSource` (for the render backend). */
73
+ export class HttpRangeByteSource {
74
+ size;
75
+ blockSize;
76
+ #inner;
77
+ #readahead;
78
+ #cacheBytes;
79
+ #onProgress;
80
+ /** Cached blocks by index, least recently used first (a Map keeps insertion order). */
81
+ #blocks = new Map();
82
+ #cached = 0;
83
+ /** Blocks being fetched, so two fills never fetch one block twice. */
84
+ #inFlight = new Map();
85
+ /** The whole file, when the server sent it whole. */
86
+ #whole;
87
+ #loaded = 0;
88
+ constructor(inner, options) {
89
+ this.#inner = inner;
90
+ this.size = inner.size;
91
+ this.blockSize = Math.max(1, Math.floor(options.blockSize ?? DEFAULTS.blockSize));
92
+ this.#readahead = Math.max(0, Math.floor(options.readahead ?? DEFAULTS.readahead));
93
+ this.#cacheBytes = options.cacheBytes ?? DEFAULTS.cacheBytes;
94
+ this.#onProgress = options.onProgress;
95
+ }
96
+ /**
97
+ * Probes `url` (its last 64 KiB: the size, and the part a reader reads first) and returns the
98
+ * source. A server that ignores `Range` sends the whole file, which is kept.
99
+ *
100
+ * @throws LaminaPdfError `fetch-failed` (`data.reason` `network` covers a refused CORS check,
101
+ * which the browser doesn't tell apart from being offline), `source-changed`,
102
+ * `source-budget-exceeded`, or the signal's reason.
103
+ */
104
+ static async open(url, options = {}) {
105
+ let whole = false;
106
+ let received = 0;
107
+ let source;
108
+ const fetcher = privateFetch(options.fetch ?? fetch, options.noStore ?? true, options.maxWholeBytes ?? DEFAULTS.maxWholeBytes, {
109
+ received: (bytes) => {
110
+ received += bytes;
111
+ if (source !== undefined)
112
+ source.#loaded = received;
113
+ },
114
+ whole: () => {
115
+ whole = true;
116
+ },
117
+ });
118
+ const inner = await httpRangeSource(url, {
119
+ fetch: fetcher,
120
+ blockSize: options.blockSize ?? DEFAULTS.blockSize,
121
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
122
+ }).catch((e) => {
123
+ throw unwrapCap(e);
124
+ });
125
+ source = new HttpRangeByteSource(inner, options);
126
+ source.#loaded = received;
127
+ // The probe's answer was the file: httpRangeSource holds it, and this reads it back once.
128
+ if (whole)
129
+ source.#whole = await inner.read(0, inner.size);
130
+ source.#progress();
131
+ return source;
132
+ }
133
+ /** The whole file, when the server sent it whole (then every read is answered from it). */
134
+ get whole() {
135
+ return this.#whole;
136
+ }
137
+ /** Bytes received from the network so far (the probe's included), re-fetches of evicted blocks too. */
138
+ get loaded() {
139
+ return this.#loaded;
140
+ }
141
+ /** The `length` bytes at `offset` if every block is cached, else undefined (`RenderSource`). */
142
+ readSync(offset, length) {
143
+ const end = Math.min(this.size, offset + length);
144
+ if (offset < 0 || end < offset)
145
+ return undefined;
146
+ if (this.#whole !== undefined)
147
+ return this.#whole.subarray(offset, end);
148
+ const first = Math.floor(offset / this.blockSize);
149
+ const last = Math.floor((end - 1) / this.blockSize);
150
+ if (end === offset)
151
+ return new Uint8Array();
152
+ if (first === last) {
153
+ const block = this.#touch(first);
154
+ if (block === undefined)
155
+ return undefined;
156
+ const at = first * this.blockSize;
157
+ return block.subarray(offset - at, end - at);
158
+ }
159
+ const out = new Uint8Array(end - offset);
160
+ for (let index = first; index <= last; index++) {
161
+ const block = this.#touch(index);
162
+ if (block === undefined)
163
+ return undefined;
164
+ const at = index * this.blockSize;
165
+ const from = Math.max(offset, at) - at;
166
+ const to = Math.min(end, at + block.length) - at;
167
+ out.set(block.subarray(from, to), at + from - offset);
168
+ }
169
+ return out;
170
+ }
171
+ /**
172
+ * Fetches the blocks `ranges` touch (and the readahead after each) that aren't cached: the
173
+ * ranges of a render backend's `data-pending`.
174
+ */
175
+ async fill(ranges, signal) {
176
+ if (this.#whole !== undefined)
177
+ return;
178
+ const wanted = this.#blocksFor(ranges);
179
+ const waits = [];
180
+ let run = [];
181
+ const flush = () => {
182
+ if (run.length > 0)
183
+ waits.push(this.#fetchRun(run, signal));
184
+ run = [];
185
+ };
186
+ for (const index of wanted) {
187
+ const pending = this.#inFlight.get(index);
188
+ if (pending !== undefined || this.#blocks.has(index)) {
189
+ flush();
190
+ if (pending !== undefined)
191
+ waits.push(pending);
192
+ continue;
193
+ }
194
+ if (run.length > 0 && run[run.length - 1] !== index - 1)
195
+ flush();
196
+ run.push(index);
197
+ }
198
+ flush();
199
+ await Promise.all(waits);
200
+ // Keep what this fill asked for: evicting it now would make the caller miss again.
201
+ this.#evict(new Set(wanted));
202
+ }
203
+ /** The blocks `ranges` touch, with the readahead after each, in order and once each. */
204
+ #blocksFor(ranges) {
205
+ const wanted = new Set();
206
+ const lastBlock = Math.max(0, Math.ceil(this.size / this.blockSize) - 1);
207
+ for (const [offset, length] of ranges) {
208
+ if (length <= 0)
209
+ continue;
210
+ const first = Math.floor(offset / this.blockSize);
211
+ const last = Math.min(lastBlock, Math.floor((offset + length - 1) / this.blockSize) + this.#readahead);
212
+ for (let index = first; index <= last; index++)
213
+ wanted.add(index);
214
+ }
215
+ return [...wanted].sort((a, b) => a - b);
216
+ }
217
+ /** `RangeSource.read`: fills, then reads from the cache. */
218
+ async read(offset, length, options) {
219
+ const cached = this.readSync(offset, length);
220
+ if (cached !== undefined && cached.length === length)
221
+ return cached.slice();
222
+ await this.fill([[offset, length]], options?.signal);
223
+ const bytes = this.readSync(offset, length);
224
+ if (bytes === undefined)
225
+ throw new Error("a range read missed blocks it had just fetched");
226
+ return bytes.slice();
227
+ }
228
+ /** Fetches the consecutive blocks `run` in one request. */
229
+ #fetchRun(run, signal) {
230
+ const first = run[0] ?? 0;
231
+ const last = run[run.length - 1] ?? first;
232
+ const start = first * this.blockSize;
233
+ const end = Math.min(this.size, (last + 1) * this.blockSize);
234
+ const fetching = this.#inner.read(start, end - start, signal === undefined ? {} : { signal }).then((bytes) => {
235
+ for (const index of run) {
236
+ const at = index * this.blockSize - start;
237
+ this.#store(index, bytes.slice(at, Math.min(bytes.length, at + this.blockSize)));
238
+ }
239
+ this.#progress();
240
+ }, (e) => {
241
+ throw unwrapCap(e);
242
+ });
243
+ const done = fetching.finally(() => {
244
+ for (const index of run)
245
+ if (this.#inFlight.get(index) === done)
246
+ this.#inFlight.delete(index);
247
+ });
248
+ for (const index of run)
249
+ this.#inFlight.set(index, done);
250
+ return done;
251
+ }
252
+ #store(index, block) {
253
+ const old = this.#blocks.get(index);
254
+ if (old !== undefined)
255
+ this.#cached -= old.length;
256
+ this.#blocks.delete(index);
257
+ this.#blocks.set(index, block);
258
+ this.#cached += block.length;
259
+ }
260
+ /** Block `index`, marked as used now; undefined when it isn't cached. */
261
+ #touch(index) {
262
+ const block = this.#blocks.get(index);
263
+ if (block !== undefined) {
264
+ this.#blocks.delete(index);
265
+ this.#blocks.set(index, block);
266
+ }
267
+ return block;
268
+ }
269
+ /** Drops the least recently used blocks over the budget, never one in `keep`. */
270
+ #evict(keep) {
271
+ for (const [index, block] of this.#blocks) {
272
+ if (this.#cached <= this.#cacheBytes)
273
+ return;
274
+ if (keep.has(index))
275
+ continue;
276
+ this.#blocks.delete(index);
277
+ this.#cached -= block.length;
278
+ }
279
+ }
280
+ #progress() {
281
+ this.#onProgress?.({ loaded: this.#loaded, total: this.size });
282
+ }
283
+ }
284
+ //# sourceMappingURL=http-range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-range.js","sourceRoot":"","sources":["../../src/source/http-range.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { RenderSource } from "@laminapdf/render";
2
+ import type { RangeSource } from "@laminapdf/sdk";
3
+ /** The OPFS folder of document copies, which the app's "Clear recent files and cached documents" empties too. */
4
+ export declare const CACHE_FOLDER = "documents";
5
+ /** Files above this many bytes are read from a copy: 200 MiB. */
6
+ export declare const COPY_ABOVE: number;
7
+ /** The copy's name: its size, date and a hash of its name, so the same file finds its copy again. */
8
+ export declare function copyName(file: Pick<File, "name" | "size" | "lastModified">): string;
9
+ /** How a copy is made and kept. */
10
+ export interface CopyOptions {
11
+ readonly signal: AbortSignal;
12
+ /** Told after each step of a copy being made. */
13
+ readonly onProgress?: ((loaded: number, total: number) => void) | undefined;
14
+ /** Keep the copy for next time once its document closes; false removes it then. */
15
+ readonly keep: boolean;
16
+ }
17
+ /** A copied file, read synchronously; both a RangeSource (Lamina PDF) and a RenderSource. */
18
+ export declare class OpfsByteSource implements RangeSource, RenderSource {
19
+ #private;
20
+ readonly size: number;
21
+ private constructor();
22
+ /**
23
+ * `file` read from its OPFS copy, made now if it isn't there; `undefined` where the browser has
24
+ * no OPFS or the copy can't be made (no room, locked by another tab, a write that fails), so the
25
+ * caller reads it from memory. Rejects only when `options.signal` aborts.
26
+ */
27
+ static open(file: File, options: CopyOptions): Promise<OpfsByteSource | undefined>;
28
+ readSync(offset: number, length: number): Uint8Array | undefined;
29
+ read(offset: number, length: number, options?: {
30
+ readonly signal?: AbortSignal;
31
+ }): Promise<Uint8Array>;
32
+ /** Lets the copy go: kept in the folder for next time, or removed when it isn't to be kept. */
33
+ close(): void;
34
+ }
35
+ //# sourceMappingURL=opfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opfs.d.ts","sourceRoot":"","sources":["../../src/source/opfs.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,iHAAiH;AACjH,eAAO,MAAM,YAAY,cAAc,CAAC;AAExC,iEAAiE;AACjE,eAAO,MAAM,UAAU,QAAoB,CAAC;AAuB5C,qGAAqG;AACrG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC,GAAG,MAAM,CAInF;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5E,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,6FAA6F;AAC7F,qBAAa,cAAe,YAAW,WAAW,EAAE,YAAY;;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAMtB,OAAO,eAMN;IAED;;;;OAIG;IACH,OAAa,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CA2BvF;IAED,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAM/D;IAED,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAGrG;IAED,+FAA+F;IAC/F,KAAK,IAAI,IAAI,CAGZ;CACF"}