@pagepocket/lib 0.7.1 → 0.8.0

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 (261) hide show
  1. package/README.md +7 -6
  2. package/dist/build-snapshot-from-bundle.d.ts +23 -0
  3. package/dist/build-snapshot-from-bundle.js +68 -0
  4. package/dist/builtin-blacklist.js +3 -6
  5. package/dist/bundle/from-network-store.d.ts +10 -0
  6. package/dist/bundle/from-network-store.js +26 -0
  7. package/dist/bundle/types.d.ts +32 -0
  8. package/dist/bundle/types.js +2 -0
  9. package/dist/capture/index.d.ts +14 -0
  10. package/dist/capture/index.js +86 -0
  11. package/dist/capture/memory-content-store.d.ts +4 -0
  12. package/dist/capture/memory-content-store.js +42 -0
  13. package/dist/capture/types.d.ts +61 -0
  14. package/dist/capture/types.js +2 -0
  15. package/dist/content-store.js +3 -8
  16. package/dist/content-type.d.ts +1 -1
  17. package/dist/content-type.js +2 -28
  18. package/dist/core/_impl/completion.d.ts +4 -0
  19. package/dist/core/_impl/completion.js +29 -0
  20. package/dist/core/_impl/content-store.d.ts +21 -0
  21. package/dist/core/_impl/content-store.js +91 -0
  22. package/dist/core/_impl/debug.d.ts +1 -0
  23. package/dist/core/_impl/debug.js +16 -0
  24. package/dist/core/_impl/inflight-tracker.d.ts +19 -0
  25. package/dist/core/_impl/inflight-tracker.js +48 -0
  26. package/dist/core/_impl/pagepocket.d.ts +27 -0
  27. package/dist/core/_impl/pagepocket.js +155 -0
  28. package/dist/core/capture/_impl/memory-content-store.d.ts +4 -0
  29. package/dist/core/capture/_impl/memory-content-store.js +42 -0
  30. package/dist/core/capture/_impl/types.d.ts +61 -0
  31. package/dist/core/capture/_impl/types.js +2 -0
  32. package/dist/core/capture/internal/memory-content-store.d.ts +4 -0
  33. package/dist/core/capture/internal/memory-content-store.js +42 -0
  34. package/dist/core/capture/internal/types.d.ts +61 -0
  35. package/dist/core/capture/internal/types.js +2 -0
  36. package/dist/core/capture/memory-content-store.d.ts +4 -0
  37. package/dist/core/capture/memory-content-store.js +38 -0
  38. package/dist/core/capture/types.d.ts +61 -0
  39. package/dist/core/capture/types.js +1 -0
  40. package/dist/core/completion.d.ts +4 -0
  41. package/dist/core/completion.js +23 -0
  42. package/dist/core/content-store.d.ts +21 -0
  43. package/dist/core/content-store.js +54 -0
  44. package/dist/core/debug.d.ts +1 -0
  45. package/dist/core/debug.js +12 -0
  46. package/dist/core/file-tree-merge.d.ts +2 -0
  47. package/dist/core/file-tree-merge.js +27 -0
  48. package/dist/core/file-tree.d.ts +36 -0
  49. package/dist/core/file-tree.js +1 -0
  50. package/dist/core/inflight-tracker.d.ts +19 -0
  51. package/dist/core/inflight-tracker.js +44 -0
  52. package/dist/core/internal/completion.d.ts +4 -0
  53. package/dist/core/internal/completion.js +29 -0
  54. package/dist/core/internal/content-store.d.ts +21 -0
  55. package/dist/core/internal/content-store.js +91 -0
  56. package/dist/core/internal/debug.d.ts +1 -0
  57. package/dist/core/internal/debug.js +16 -0
  58. package/dist/core/internal/inflight-tracker.d.ts +19 -0
  59. package/dist/core/internal/inflight-tracker.js +48 -0
  60. package/dist/core/internal/pagepocket.d.ts +27 -0
  61. package/dist/core/internal/pagepocket.js +155 -0
  62. package/dist/core/pagepocket.d.ts +38 -0
  63. package/dist/core/pagepocket.js +57 -0
  64. package/dist/core/plugin/_impl/context.d.ts +47 -0
  65. package/dist/core/plugin/_impl/context.js +142 -0
  66. package/dist/core/plugin/_impl/runner.d.ts +12 -0
  67. package/dist/core/plugin/_impl/runner.js +232 -0
  68. package/dist/core/plugin/_impl/types.d.ts +108 -0
  69. package/dist/core/plugin/_impl/types.js +2 -0
  70. package/dist/core/plugin/context.d.ts +47 -0
  71. package/dist/core/plugin/context.js +205 -0
  72. package/dist/core/plugin/internal/context.d.ts +47 -0
  73. package/dist/core/plugin/internal/context.js +142 -0
  74. package/dist/core/plugin/internal/runner.d.ts +12 -0
  75. package/dist/core/plugin/internal/runner.js +232 -0
  76. package/dist/core/plugin/internal/types.d.ts +108 -0
  77. package/dist/core/plugin/internal/types.js +2 -0
  78. package/dist/core/plugin/runner-utils.d.ts +9 -0
  79. package/dist/core/plugin/runner-utils.js +29 -0
  80. package/dist/core/plugin/runner.d.ts +12 -0
  81. package/dist/core/plugin/runner.js +118 -0
  82. package/dist/core/plugin/types.d.ts +117 -0
  83. package/dist/core/plugin/types.js +1 -0
  84. package/dist/core/runtime/types.d.ts +14 -0
  85. package/dist/core/runtime/types.js +2 -0
  86. package/dist/css-rewrite.js +1 -5
  87. package/dist/debug.d.ts +0 -1
  88. package/dist/debug.js +3 -5
  89. package/dist/files/types.d.ts +41 -0
  90. package/dist/files/types.js +2 -0
  91. package/dist/hack-html.js +20 -13
  92. package/dist/hackers/index.d.ts +1 -1
  93. package/dist/hackers/index.js +24 -27
  94. package/dist/hackers/preload-fetch.d.ts +1 -1
  95. package/dist/hackers/preload-fetch.js +1 -4
  96. package/dist/hackers/preload-xhr.d.ts +1 -1
  97. package/dist/hackers/preload-xhr.js +1 -4
  98. package/dist/hackers/replay-beacon.d.ts +1 -1
  99. package/dist/hackers/replay-beacon.js +1 -4
  100. package/dist/hackers/replay-block-text-fragment.d.ts +1 -1
  101. package/dist/hackers/replay-block-text-fragment.js +1 -4
  102. package/dist/hackers/replay-css-proxy.d.ts +1 -1
  103. package/dist/hackers/replay-css-proxy.js +9 -12
  104. package/dist/hackers/replay-dom-rewrite.d.ts +1 -1
  105. package/dist/hackers/replay-dom-rewrite.js +165 -154
  106. package/dist/hackers/replay-eventsource.d.ts +1 -1
  107. package/dist/hackers/replay-eventsource.js +1 -4
  108. package/dist/hackers/replay-fetch.d.ts +1 -1
  109. package/dist/hackers/replay-fetch.js +1 -4
  110. package/dist/hackers/replay-history-path.d.ts +1 -1
  111. package/dist/hackers/replay-history-path.js +1 -4
  112. package/dist/hackers/replay-svg-image.d.ts +1 -1
  113. package/dist/hackers/replay-svg-image.js +1 -4
  114. package/dist/hackers/replay-websocket.d.ts +1 -1
  115. package/dist/hackers/replay-websocket.js +1 -4
  116. package/dist/hackers/replay-xhr.d.ts +1 -1
  117. package/dist/hackers/replay-xhr.js +1 -4
  118. package/dist/hackers/types.js +1 -2
  119. package/dist/index.d.ts +29 -13
  120. package/dist/index.js +23 -44
  121. package/dist/kind-map.d.ts +68 -0
  122. package/dist/kind-map.js +58 -0
  123. package/dist/network-store.js +12 -1
  124. package/dist/pagepocket.d.ts +19 -4
  125. package/dist/pagepocket.js +36 -102
  126. package/dist/path-resolver.d.ts +1 -2
  127. package/dist/path-resolver.js +9 -16
  128. package/dist/plugin/builtins/build-snapshot-plugin.d.ts +5 -0
  129. package/dist/plugin/builtins/build-snapshot-plugin.js +84 -0
  130. package/dist/plugin/builtins/replace-elements-plugin.d.ts +8 -0
  131. package/dist/plugin/builtins/replace-elements-plugin.js +13 -0
  132. package/dist/plugin/builtins/to-directory-plugin.d.ts +7 -0
  133. package/dist/plugin/builtins/to-directory-plugin.js +20 -0
  134. package/dist/plugin/builtins/to-zip-plugin.d.ts +5 -0
  135. package/dist/plugin/builtins/to-zip-plugin.js +19 -0
  136. package/dist/plugin/context.d.ts +47 -0
  137. package/dist/plugin/context.js +142 -0
  138. package/dist/plugin/runner.d.ts +12 -0
  139. package/dist/plugin/runner.js +232 -0
  140. package/dist/plugin/types.d.ts +108 -0
  141. package/dist/plugin/types.js +2 -0
  142. package/dist/plugins/build-files-from-capture.d.ts +5 -0
  143. package/dist/plugins/build-files-from-capture.js +85 -0
  144. package/dist/plugins/build-warc.d.ts +5 -0
  145. package/dist/plugins/build-warc.js +225 -0
  146. package/dist/plugins/builtins/manifest.d.ts +2 -0
  147. package/dist/plugins/builtins/manifest.js +42 -0
  148. package/dist/plugins/builtins/snapshot-directory.d.ts +2 -0
  149. package/dist/plugins/builtins/snapshot-directory.js +24 -0
  150. package/dist/plugins/builtins/snapshot-zip.d.ts +2 -0
  151. package/dist/plugins/builtins/snapshot-zip.js +25 -0
  152. package/dist/plugins/capture-http-lighterceptor.d.ts +5 -0
  153. package/dist/plugins/capture-http-lighterceptor.js +85 -0
  154. package/dist/plugins/capture-http-puppeteer.d.ts +5 -0
  155. package/dist/plugins/capture-http-puppeteer.js +85 -0
  156. package/dist/plugins/host.d.ts +37 -0
  157. package/dist/plugins/host.js +105 -0
  158. package/dist/plugins/index.d.ts +6 -0
  159. package/dist/plugins/index.js +11 -0
  160. package/dist/plugins/ordering.d.ts +2 -0
  161. package/dist/plugins/ordering.js +19 -0
  162. package/dist/plugins/types.d.ts +51 -0
  163. package/dist/plugins/types.js +2 -0
  164. package/dist/preload.js +3 -7
  165. package/dist/replace-elements/actions.d.ts +5 -0
  166. package/dist/replace-elements/actions.js +86 -0
  167. package/dist/replace-elements/match.d.ts +5 -0
  168. package/dist/replace-elements/match.js +46 -0
  169. package/dist/replace-elements/normalize.d.ts +21 -0
  170. package/dist/replace-elements/normalize.js +50 -0
  171. package/dist/replace-elements.d.ts +1 -1
  172. package/dist/replace-elements.js +5 -185
  173. package/dist/replay/match-api.d.ts +10 -0
  174. package/dist/replay/match-api.js +162 -0
  175. package/dist/replay/templates/match-api-source.d.ts +1 -0
  176. package/dist/replay/templates/match-api-source.js +137 -0
  177. package/dist/replay/templates/replay-script-template.d.ts +5 -0
  178. package/dist/replay/templates/replay-script-template.js +337 -0
  179. package/dist/replay/templates/resource-proxy-script.d.ts +1 -0
  180. package/dist/replay/templates/resource-proxy-script.js +274 -0
  181. package/dist/replay-script.d.ts +3 -10
  182. package/dist/replay-script.js +11 -625
  183. package/dist/resource-filter.d.ts +1 -1
  184. package/dist/resource-filter.js +1 -5
  185. package/dist/resource-proxy/escape-percent.d.ts +1 -0
  186. package/dist/resource-proxy/escape-percent.js +12 -0
  187. package/dist/resource-proxy/multimap.d.ts +3 -0
  188. package/dist/resource-proxy/multimap.js +18 -0
  189. package/dist/resource-proxy/pathname-variants.d.ts +3 -0
  190. package/dist/resource-proxy/pathname-variants.js +54 -0
  191. package/dist/resource-proxy.d.ts +4 -2
  192. package/dist/resource-proxy.js +48 -117
  193. package/dist/resources.js +4 -42
  194. package/dist/rewrite-links/js-imports.d.ts +3 -0
  195. package/dist/rewrite-links/js-imports.js +56 -0
  196. package/dist/rewrite-links/link-rel.d.ts +2 -0
  197. package/dist/rewrite-links/link-rel.js +10 -0
  198. package/dist/rewrite-links/meta-refresh.d.ts +3 -0
  199. package/dist/rewrite-links/meta-refresh.js +22 -0
  200. package/dist/rewrite-links/skip.d.ts +1 -0
  201. package/dist/rewrite-links/skip.js +10 -0
  202. package/dist/rewrite-links/srcset.d.ts +3 -0
  203. package/dist/rewrite-links/srcset.js +63 -0
  204. package/dist/rewrite-links/url-resolve.d.ts +3 -0
  205. package/dist/rewrite-links/url-resolve.js +13 -0
  206. package/dist/rewrite-links.d.ts +3 -3
  207. package/dist/rewrite-links.js +31 -240
  208. package/dist/snapshot-builder/api.d.ts +3 -0
  209. package/dist/snapshot-builder/api.js +6 -0
  210. package/dist/snapshot-builder/build-snapshot.d.ts +3 -0
  211. package/dist/snapshot-builder/build-snapshot.js +138 -0
  212. package/dist/snapshot-builder/capture-index/index-capture.d.ts +13 -0
  213. package/dist/snapshot-builder/capture-index/index-capture.js +168 -0
  214. package/dist/snapshot-builder/capture-index/index.d.ts +2 -0
  215. package/dist/snapshot-builder/capture-index/index.js +1 -0
  216. package/dist/snapshot-builder/capture-index/types.d.ts +12 -0
  217. package/dist/snapshot-builder/capture-index/types.js +1 -0
  218. package/dist/snapshot-builder/capture-index.d.ts +12 -0
  219. package/dist/snapshot-builder/capture-index.js +173 -0
  220. package/dist/snapshot-builder/emit-document.d.ts +24 -0
  221. package/dist/snapshot-builder/emit-document.js +50 -0
  222. package/dist/snapshot-builder/grouping.d.ts +8 -0
  223. package/dist/snapshot-builder/grouping.js +87 -0
  224. package/dist/snapshot-builder/http.d.ts +6 -0
  225. package/dist/snapshot-builder/http.js +28 -0
  226. package/dist/snapshot-builder/index.d.ts +4 -0
  227. package/dist/snapshot-builder/index.js +2 -0
  228. package/dist/snapshot-builder/path-map.d.ts +3 -0
  229. package/dist/snapshot-builder/path-map.js +35 -0
  230. package/dist/snapshot-builder/resources-path.d.ts +23 -0
  231. package/dist/snapshot-builder/resources-path.js +47 -0
  232. package/dist/snapshot-builder/rewrite-resource.d.ts +18 -0
  233. package/dist/snapshot-builder/rewrite-resource.js +52 -0
  234. package/dist/snapshot-builder/types.d.ts +37 -0
  235. package/dist/snapshot-builder/types.js +2 -0
  236. package/dist/snapshot-builder.d.ts +12 -8
  237. package/dist/snapshot-builder.js +252 -27
  238. package/dist/types.d.ts +122 -78
  239. package/dist/types.js +4 -2
  240. package/dist/units/contracts-bridge.d.ts +76 -0
  241. package/dist/units/contracts-bridge.js +6 -0
  242. package/dist/units/index.d.ts +4 -0
  243. package/dist/units/index.js +2 -0
  244. package/dist/units/runner.d.ts +11 -0
  245. package/dist/units/runner.js +270 -0
  246. package/dist/units/types.d.ts +39 -0
  247. package/dist/units/types.js +1 -0
  248. package/dist/utils/streams.d.ts +2 -0
  249. package/dist/utils/streams.js +29 -0
  250. package/dist/utils.d.ts +35 -1
  251. package/dist/utils.js +107 -29
  252. package/dist/v3/contracts-bridge.d.ts +69 -0
  253. package/dist/v3/contracts-bridge.js +5 -0
  254. package/dist/v3/index.d.ts +4 -0
  255. package/dist/v3/index.js +2 -0
  256. package/dist/v3/runner.d.ts +20 -0
  257. package/dist/v3/runner.js +245 -0
  258. package/dist/v3/types.d.ts +39 -0
  259. package/dist/v3/types.js +1 -0
  260. package/dist/writers.js +3 -1
  261. package/package.json +11 -3
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayBeaconStub = void 0;
4
- exports.replayBeaconStub = {
1
+ export const replayBeaconStub = {
5
2
  id: "replay-beacon-stub",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayBlockTextFragment: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayBlockTextFragment = void 0;
4
- exports.replayBlockTextFragment = {
1
+ export const replayBlockTextFragment = {
5
2
  id: "replay-block-text-fragment",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayCssProxy: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayCssProxy = void 0;
4
- exports.replayCssProxy = {
1
+ export const replayCssProxy = {
5
2
  id: "replay-css-proxy",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -24,7 +21,7 @@ exports.replayCssProxy = {
24
21
  const text = String(cssText || "");
25
22
 
26
23
  // Rewrite url(...)
27
- const urlPattern = /url\(\s*(['"]?)([^'")]+)\\1\s*\)/g;
24
+ const urlPattern = /url\\(\\s*(['"]?)([^'")]+)\\1\\s*\\)/g;
28
25
  const updated = text.replace(urlPattern, (full, quote, rawUrl) => {
29
26
  try {
30
27
  const raw = String(rawUrl || "").trim();
@@ -32,19 +29,19 @@ exports.replayCssProxy = {
32
29
  return full;
33
30
  }
34
31
  const absolute = new URL(raw, base).toString();
35
- const localPath = findLocalPath(absolute);
36
- if (!localPath) {
32
+ const next = rewriteResourceUrl(absolute, { kind: "css-url" });
33
+ if (!next) {
37
34
  return full;
38
35
  }
39
36
  const q = quote || "";
40
- return "url(" + q + localPath + q + ")";
37
+ return "url(" + q + next + q + ")";
41
38
  } catch {
42
39
  return full;
43
40
  }
44
41
  });
45
42
 
46
43
  // Rewrite @import
47
- const importPattern = /@import\s+(?:url\()?['"]?([^'")]+)['"]?\)?/g;
44
+ const importPattern = /@import\\s+(?:url\\()?['"]?([^'")]+)['"]?\\)?/g;
48
45
  const final = updated.replace(importPattern, (full, rawUrl) => {
49
46
  try {
50
47
  const raw = String(rawUrl || "").trim();
@@ -52,11 +49,11 @@ exports.replayCssProxy = {
52
49
  return full;
53
50
  }
54
51
  const absolute = new URL(raw, base).toString();
55
- const localPath = findLocalPath(absolute);
56
- if (!localPath) {
52
+ const next = rewriteResourceUrl(absolute, { kind: "css-import", fallbackType: "text/css" });
53
+ if (!next) {
57
54
  return full;
58
55
  }
59
- return full.replace(rawUrl, localPath);
56
+ return full.replace(rawUrl, next);
60
57
  } catch {
61
58
  return full;
62
59
  }
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayDomRewriter: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayDomRewriter = void 0;
4
- exports.replayDomRewriter = {
1
+ export const replayDomRewriter = {
5
2
  id: "replay-dom-rewriter",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -35,6 +32,65 @@ exports.replayDomRewriter = {
35
32
 
36
33
  const rewritten = new WeakMap();
37
34
 
35
+ const shouldRewriteAttr = (element, attr) => {
36
+ try {
37
+ const tag = String((element && element.tagName) || "").toLowerCase();
38
+ const name = String(attr || "").toLowerCase();
39
+
40
+ if (!tag || !name) {
41
+ return false;
42
+ }
43
+
44
+ // Never rewrite navigation.
45
+ if (tag === "a" && name === "href") {
46
+ return false;
47
+ }
48
+
49
+ if (name === "src") {
50
+ return (
51
+ tag === "img" ||
52
+ tag === "source" ||
53
+ tag === "video" ||
54
+ tag === "audio" ||
55
+ tag === "script" ||
56
+ tag === "iframe" ||
57
+ tag === "object" ||
58
+ tag === "embed" ||
59
+ tag === "track"
60
+ );
61
+ }
62
+
63
+ if (name === "href") {
64
+ if (tag !== "link") {
65
+ return false;
66
+ }
67
+
68
+ const rel = String((element.getAttribute && element.getAttribute("rel")) || "").toLowerCase();
69
+ // Stylesheets + icons are resources.
70
+ if (rel.includes("stylesheet") || rel.includes("icon")) {
71
+ return true;
72
+ }
73
+
74
+ // Preload/prefetch/modulepreload are also resource loads.
75
+ // These are common in modern bundlers (Webpack/Rspack/Vite) and can
76
+ // otherwise bypass replay mapping.
77
+ if (rel.includes("preload") || rel.includes("prefetch") || rel.includes("modulepreload")) {
78
+ return true;
79
+ }
80
+
81
+ return false;
82
+ }
83
+
84
+ if (name === "srcset") {
85
+ return tag === "img" || tag === "source";
86
+ }
87
+
88
+ return false;
89
+ } catch {
90
+ return false;
91
+ }
92
+ };
93
+
38
94
  // Rewrite srcset values to local files only (avoid data: URLs in srcset).
39
95
  const rewriteSrcset = (value) => {
40
96
  if (!value) return value;
@@ -95,42 +151,40 @@ exports.replayDomRewriter = {
95
151
  return;
96
152
  }
97
153
  const tag = (element.tagName || "").toLowerCase();
98
- if (tag === "img" || tag === "source" || tag === "video" || tag === "audio" || tag === "script" || tag === "iframe" || tag === "object" || tag === "embed") {
154
+ if (tag === "img" || tag === "source" || tag === "video" || tag === "audio" || tag === "script" || tag === "iframe" || tag === "object" || tag === "embed" || tag === "track") {
99
155
  const src = currentSrc;
100
- if (src && !isLocalResource(src) && !src.startsWith("data:") && !src.startsWith("blob:")) {
101
- const localPath = findLocalPath(src);
102
- if (localPath) {
103
- element.setAttribute("src", localPath);
156
+ if (src && !src.startsWith("data:") && !src.startsWith("blob:")) {
157
+ const next = rewriteResourceUrl(src, { kind: "attr", tag, attr: "src" });
158
+ if (next && next !== src) {
159
+ element.setAttribute("src", next);
104
160
  return;
105
161
  }
106
- const record = findByUrl(src);
107
- if (record) {
108
- element.setAttribute("src", toDataUrl(record));
109
- return;
110
- }
111
-
112
- // Keep original URL when we have no snapshot match.
113
- return;
114
162
  }
115
163
  }
116
164
 
117
165
  if (tag === "link") {
118
166
  const href = currentHref;
119
167
  const rel = (element.getAttribute("rel") || "").toLowerCase();
120
- if (href && !isLocalResource(href) && !href.startsWith("data:") && !href.startsWith("blob:")) {
121
- const localPath = findLocalPath(href);
122
- if (localPath) {
123
- element.setAttribute("href", localPath);
124
- return;
125
- }
126
- const record = findByUrl(href);
127
- if (record) {
128
- element.setAttribute("href", toDataUrl(record, "text/css"));
129
- return;
130
- }
131
-
132
- return;
133
- }
168
+ if (href && !href.startsWith("data:") && !href.startsWith("blob:")) {
169
+ if (rel.includes("stylesheet") || rel.includes("icon") || rel.includes("preload") || rel.includes("prefetch") || rel.includes("modulepreload")) {
170
+ // For <link rel=preload as=style>, use a CSS fallback type.
171
+ const as = (element.getAttribute("as") || "").toLowerCase();
172
+ const fallbackType =
173
+ rel.includes("stylesheet") || (rel.includes("preload") && as === "style")
174
+ ? "text/css"
175
+ : undefined;
176
+ const next = rewriteResourceUrl(href, {
177
+ kind: "attr",
178
+ tag,
179
+ attr: "href",
180
+ fallbackType
181
+ });
182
+ if (next && next !== href) {
183
+ element.setAttribute("href", next);
184
+ return;
185
+ }
186
+ }
187
+ }
134
188
  }
135
189
 
136
190
  const srcset = currentSrcset;
@@ -160,26 +214,27 @@ exports.replayDomRewriter = {
160
214
  return originalSetAttribute.call(this, name, rewritten);
161
215
  }
162
216
 
217
+ if (!shouldRewriteAttr(this, attr)) {
218
+ return originalSetAttribute.call(this, name, value);
219
+ }
220
+
163
221
  const tag = (this.tagName || "").toLowerCase();
164
222
  const rel = (this.getAttribute && this.getAttribute("rel")) || "";
165
223
  const relLower = rel.toLowerCase();
224
+ const as = String((this.getAttribute && this.getAttribute("as")) || "").toLowerCase();
225
+ const fallbackType =
226
+ attr === "href" && (relLower.includes("stylesheet") || (relLower.includes("preload") && as === "style"))
227
+ ? "text/css"
228
+ : undefined;
166
229
 
167
- if (isLocalResource(String(value))) {
168
- return originalSetAttribute.call(this, name, value);
169
- }
170
- const localPath = findLocalPath(String(value));
171
- if (localPath) {
172
- return originalSetAttribute.call(this, name, localPath);
173
- }
174
- const record = findByUrl(String(value));
175
- if (record) {
176
- const fallbackType = attr === "href" && relLower.includes("stylesheet") ? "text/css" : undefined;
177
- const dataUrl = toDataUrl(record, fallbackType);
178
- return originalSetAttribute.call(this, name, dataUrl);
179
- }
230
+ const next = rewriteResourceUrl(String(value), {
231
+ kind: "setAttribute",
232
+ tag,
233
+ attr,
234
+ fallbackType
235
+ });
180
236
 
181
- // Keep original URL on miss.
182
- return originalSetAttribute.call(this, name, value);
237
+ return originalSetAttribute.call(this, name, next);
183
238
  }
184
239
  return originalSetAttribute.call(this, name, value);
185
240
  };
@@ -203,127 +258,81 @@ exports.replayDomRewriter = {
203
258
  const rawValue = String(value);
204
259
  if (!readyResolved) {
205
260
  onReady(() => {
206
- if (isLocalResource(rawValue)) {
207
- setter.call(this, rawValue);
208
- return;
209
- }
210
- const localPath = findLocalPath(rawValue);
211
- if (localPath) {
212
- setter.call(this, localPath);
213
- return;
214
- }
215
- const record = findByUrl(rawValue);
216
- if (record) {
217
- setter.call(this, toDataUrl(record));
218
- return;
219
- }
220
-
221
- setter.call(this, rawValue);
261
+ const next = rewriteResourceUrl(rawValue, { kind: "setter", tag: "img", attr: "src" });
262
+ setter.call(this, next);
222
263
  });
223
264
  return;
224
265
  }
225
- if (isLocalResource(rawValue)) {
226
- setter.call(this, rawValue);
227
- return;
228
- }
229
- const localPath = findLocalPath(rawValue);
230
- if (localPath) {
231
- setter.call(this, localPath);
232
- return;
233
- }
234
- const record = findByUrl(rawValue);
235
- if (record) {
236
- setter.call(this, toDataUrl(record));
237
- return;
238
- }
239
-
240
- setter.call(this, rawValue);
266
+ const next = rewriteResourceUrl(rawValue, { kind: "setter", tag: "img", attr: "src" });
267
+ setter.call(this, next);
241
268
  });
242
269
 
243
270
  patchProperty(HTMLScriptElement.prototype, "src", function(value, setter) {
244
271
  const rawValue = String(value);
245
272
  if (!readyResolved) {
246
273
  onReady(() => {
247
- if (isLocalResource(rawValue)) {
248
- setter.call(this, rawValue);
249
- return;
250
- }
251
- const localPath = findLocalPath(rawValue);
252
- if (localPath) {
253
- setter.call(this, localPath);
254
- return;
255
- }
256
- const record = findByUrl(rawValue);
257
- if (record) {
258
- setter.call(this, toDataUrl(record));
259
- return;
260
- }
261
-
262
- setter.call(this, rawValue);
274
+ const next = rewriteResourceUrl(rawValue, { kind: "setter", tag: "script", attr: "src" });
275
+ setter.call(this, next);
263
276
  });
264
277
  return;
265
278
  }
266
- if (isLocalResource(rawValue)) {
267
- setter.call(this, rawValue);
268
- return;
269
- }
270
- const localPath = findLocalPath(rawValue);
271
- if (localPath) {
272
- setter.call(this, localPath);
273
- return;
274
- }
275
- const record = findByUrl(rawValue);
276
- if (record) {
277
- setter.call(this, toDataUrl(record));
278
- return;
279
- }
280
-
281
- // Keep original URL on miss.
282
- setter.call(this, rawValue);
279
+ const next = rewriteResourceUrl(rawValue, { kind: "setter", tag: "script", attr: "src" });
280
+ setter.call(this, next);
283
281
  });
284
282
 
285
- patchProperty(HTMLLinkElement.prototype, "href", function(value, setter) {
286
- const rawValue = String(value);
287
- const rel = (this.getAttribute && this.getAttribute("rel")) || "";
288
- const relLower = rel.toLowerCase();
289
- if (!readyResolved) {
290
- onReady(() => {
291
- if (isLocalResource(rawValue)) {
292
- setter.call(this, rawValue);
293
- return;
294
- }
295
- const localPath = findLocalPath(rawValue);
296
- if (localPath) {
297
- setter.call(this, localPath);
298
- return;
299
- }
300
- const record = findByUrl(rawValue);
301
- if (record) {
302
- setter.call(this, toDataUrl(record, relLower.includes("stylesheet") ? "text/css" : undefined));
303
- return;
304
- }
305
-
306
- setter.call(this, rawValue);
307
- });
308
- return;
309
- }
310
- if (isLocalResource(rawValue)) {
311
- setter.call(this, rawValue);
312
- return;
313
- }
314
- const localPath = findLocalPath(rawValue);
315
- if (localPath) {
316
- setter.call(this, localPath);
317
- return;
318
- }
319
- const record = findByUrl(rawValue);
320
- if (record) {
321
- setter.call(this, toDataUrl(record, relLower.includes("stylesheet") ? "text/css" : undefined));
322
- return;
323
- }
324
-
325
- setter.call(this, rawValue);
326
- });
283
+ patchProperty(HTMLLinkElement.prototype, "href", function(value, setter) {
284
+ const rawValue = String(value);
285
+ const rel = (this.getAttribute && this.getAttribute("rel")) || "";
286
+ const relLower = rel.toLowerCase();
287
+ const as = String((this.getAttribute && this.getAttribute("as")) || "").toLowerCase();
288
+ if (!readyResolved) {
289
+ onReady(() => {
290
+ if (
291
+ !relLower.includes("stylesheet") &&
292
+ !relLower.includes("icon") &&
293
+ !relLower.includes("preload") &&
294
+ !relLower.includes("prefetch") &&
295
+ !relLower.includes("modulepreload")
296
+ ) {
297
+ setter.call(this, rawValue);
298
+ return;
299
+ }
300
+ const fallbackType =
301
+ relLower.includes("stylesheet") || (relLower.includes("preload") && as === "style")
302
+ ? "text/css"
303
+ : undefined;
304
+ const next = rewriteResourceUrl(rawValue, {
305
+ kind: "setter",
306
+ tag: "link",
307
+ attr: "href",
308
+ fallbackType
309
+ });
310
+ setter.call(this, next);
311
+ });
312
+ return;
313
+ }
314
+ if (
315
+ !relLower.includes("stylesheet") &&
316
+ !relLower.includes("icon") &&
317
+ !relLower.includes("preload") &&
318
+ !relLower.includes("prefetch") &&
319
+ !relLower.includes("modulepreload")
320
+ ) {
321
+ setter.call(this, rawValue);
322
+ return;
323
+ }
324
+ const fallbackType =
325
+ relLower.includes("stylesheet") || (relLower.includes("preload") && as === "style")
326
+ ? "text/css"
327
+ : undefined;
328
+ const next = rewriteResourceUrl(rawValue, {
329
+ kind: "setter",
330
+ tag: "link",
331
+ attr: "href",
332
+ fallbackType
333
+ });
334
+ setter.call(this, next);
335
+ });
327
336
 
328
337
  patchProperty(HTMLImageElement.prototype, "srcset", function(value, setter) {
329
338
  const rawValue = String(value);
@@ -358,7 +367,9 @@ exports.replayDomRewriter = {
358
367
  attributes: true,
359
368
  childList: true,
360
369
  subtree: true,
361
- attributeFilter: ["src", "href", "srcset"]
370
+ // Include rel/as so we can rewrite <link> even when href is set before
371
+ // rel/as (common in some loaders).
372
+ attributeFilter: ["src", "href", "srcset", "rel", "as"]
362
373
  });
363
374
 
364
375
  document.querySelectorAll("img,source,video,audio,script,link,iframe").forEach((el) => rewriteElement(el));
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayEventSourceStub: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayEventSourceStub = void 0;
4
- exports.replayEventSourceStub = {
1
+ export const replayEventSourceStub = {
5
2
  id: "replay-eventsource-stub",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayFetchResponder: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayFetchResponder = void 0;
4
- exports.replayFetchResponder = {
1
+ export const replayFetchResponder = {
5
2
  id: "replay-fetch-responder",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayHistoryPath: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayHistoryPath = void 0;
4
- exports.replayHistoryPath = {
1
+ export const replayHistoryPath = {
5
2
  id: "replay-history-path",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replaySvgImageRewriter: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replaySvgImageRewriter = void 0;
4
- exports.replaySvgImageRewriter = {
1
+ export const replaySvgImageRewriter = {
5
2
  id: "replay-svg-image-rewriter",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayWebSocketStub: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayWebSocketStub = void 0;
4
- exports.replayWebSocketStub = {
1
+ export const replayWebSocketStub = {
5
2
  id: "replay-websocket-stub",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1,2 @@
1
- import type { ScriptHacker } from "./types";
1
+ import type { ScriptHacker } from "./types.js";
2
2
  export declare const replayXhrResponder: ScriptHacker;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replayXhrResponder = void 0;
4
- exports.replayXhrResponder = {
1
+ export const replayXhrResponder = {
5
2
  id: "replay-xhr-responder",
6
3
  stage: "replay",
7
4
  build: () => `
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,13 +1,29 @@
1
- export { PagePocket } from "./pagepocket";
2
- export type { ApiRecord, ApiSnapshot, ApplyOptions, CaptureOptions, CompletionContext, CompletionStrategy, ContentRef, ContentStore, ContentStoreHandle, MatchQuery, NetworkEventStream, NetworkRequestEvent, NetworkRequestFailedEvent, NetworkResponseEvent, PagePocketOptions, PageSnapshot, PathResolver, ReplaceAction, ReplaceElementContext, ReplaceElementFn, ReplaceElementFnWithQuery, ReplaceElementRule, ReplaceElementsConfig, ResourceFilter, SnapshotFile, WriteFSOptions, WriteResult, ZipWriteResult, ZipResult, ZipOptions } from "./types";
3
- export { HybridContentStore } from "./content-store";
4
- export { createDefaultPathResolver, withPrefixPathResolver } from "./path-resolver";
5
- export { createDefaultResourceFilter } from "./resource-filter";
6
- export * from "./builtin-blacklist";
7
- export { networkIdle, timeout } from "./completion";
8
- export { buildReplayScript } from "./replay-script";
9
- export { buildPreloadScript } from "./preload";
10
- export { rewriteEntryHtml, rewriteJsText } from "./rewrite-links";
11
- export { rewriteCssText } from "./css-rewrite";
12
- export { writeToFS, toZip } from "./writers";
13
- export { applyReplaceElements } from "./replace-elements";
1
+ export { PagePocket } from "./core/pagepocket.js";
2
+ export * from "./units/index.js";
3
+ export type { UnitContext, UnitContributeContext, UnitPatch, UnitRuntime } from "./units/contracts-bridge.js";
4
+ export { TERMINAL_RESULT_KEY } from "./units/contracts-bridge.js";
5
+ export type { CaptureResult as PagePocketCaptureResult } from "./units/contracts-bridge.js";
6
+ export type { ApiRecord, ApiSnapshot, ApplyOptions, InterceptOptions, InterceptSession, InterceptTarget, InterceptorActions, InterceptorCapabilities, NavigateOptions, CompletionContext, CompletionStrategy, ContentRef, ContentStore, ContentStoreHandle, MatchQuery, NetworkEvent, NetworkEventHandlers, NetworkEventStream, NetworkInterceptorAdapter, NetworkRequestEvent, NetworkRequestFailedEvent, NetworkResponseEvent, PagePocketOptions, PathResolver, ReplaceAction, ReplaceElementContext, ReplaceElementFn, ReplaceElementFnWithQuery, ReplaceElementRule, ReplaceElementsConfig, ResourceFilter, ResourceType, SnapshotFile } from "./types.js";
7
+ export { TriggerActionValues } from "./types.js";
8
+ export type { TriggerAction } from "./types.js";
9
+ export { HybridContentStore } from "./core/content-store.js";
10
+ export { createDefaultPathResolver, withPrefixPathResolver } from "./path-resolver.js";
11
+ export { createDefaultResourceFilter } from "./resource-filter.js";
12
+ export { buildSnapshot } from "./snapshot-builder/index.js";
13
+ export type { BuildOptions as SnapshotBuildOptions } from "./snapshot-builder/index.js";
14
+ export * from "./builtin-blacklist.js";
15
+ export { networkIdle, timeout } from "./core/completion.js";
16
+ export { normalizeCompletion } from "./core/completion.js";
17
+ export { debugLog } from "./core/debug.js";
18
+ export { InflightTracker } from "./core/inflight-tracker.js";
19
+ export type { FileTree, FileTreeDirectory, FileTreeEntry, FileTreeFile, FileTreeSource } from "./core/file-tree.js";
20
+ export { mergeFileTrees } from "./core/file-tree-merge.js";
21
+ export type { CaptureArtifacts, CaptureCapabilities, CaptureEvent, CaptureFailedEvent, CaptureRequestEvent, CaptureResponseEvent, CaptureContext, Header } from "./core/capture/types.js";
22
+ export { createMemoryContentStore } from "./core/capture/memory-content-store.js";
23
+ export { buildReplayScript } from "./replay-script.js";
24
+ export { buildPreloadScript } from "./preload.js";
25
+ export { rewriteEntryHtml, rewriteJsText } from "./rewrite-links.js";
26
+ export { rewriteCssText } from "./css-rewrite.js";
27
+ export { applyReplaceElements } from "./replace-elements.js";
28
+ export { streamToUint8Array, streamFromUint8Array } from "./utils/streams.js";
29
+ export { mapKind, type KindBuilders, requiredEntryKindError, throwRequiredEntryKind, throwUnsupportedEntryKind, unsupportedEntryKindError } from "./kind-map.js";