@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.
- package/README.md +7 -6
- package/dist/build-snapshot-from-bundle.d.ts +23 -0
- package/dist/build-snapshot-from-bundle.js +68 -0
- package/dist/builtin-blacklist.js +3 -6
- package/dist/bundle/from-network-store.d.ts +10 -0
- package/dist/bundle/from-network-store.js +26 -0
- package/dist/bundle/types.d.ts +32 -0
- package/dist/bundle/types.js +2 -0
- package/dist/capture/index.d.ts +14 -0
- package/dist/capture/index.js +86 -0
- package/dist/capture/memory-content-store.d.ts +4 -0
- package/dist/capture/memory-content-store.js +42 -0
- package/dist/capture/types.d.ts +61 -0
- package/dist/capture/types.js +2 -0
- package/dist/content-store.js +3 -8
- package/dist/content-type.d.ts +1 -1
- package/dist/content-type.js +2 -28
- package/dist/core/_impl/completion.d.ts +4 -0
- package/dist/core/_impl/completion.js +29 -0
- package/dist/core/_impl/content-store.d.ts +21 -0
- package/dist/core/_impl/content-store.js +91 -0
- package/dist/core/_impl/debug.d.ts +1 -0
- package/dist/core/_impl/debug.js +16 -0
- package/dist/core/_impl/inflight-tracker.d.ts +19 -0
- package/dist/core/_impl/inflight-tracker.js +48 -0
- package/dist/core/_impl/pagepocket.d.ts +27 -0
- package/dist/core/_impl/pagepocket.js +155 -0
- package/dist/core/capture/_impl/memory-content-store.d.ts +4 -0
- package/dist/core/capture/_impl/memory-content-store.js +42 -0
- package/dist/core/capture/_impl/types.d.ts +61 -0
- package/dist/core/capture/_impl/types.js +2 -0
- package/dist/core/capture/internal/memory-content-store.d.ts +4 -0
- package/dist/core/capture/internal/memory-content-store.js +42 -0
- package/dist/core/capture/internal/types.d.ts +61 -0
- package/dist/core/capture/internal/types.js +2 -0
- package/dist/core/capture/memory-content-store.d.ts +4 -0
- package/dist/core/capture/memory-content-store.js +38 -0
- package/dist/core/capture/types.d.ts +61 -0
- package/dist/core/capture/types.js +1 -0
- package/dist/core/completion.d.ts +4 -0
- package/dist/core/completion.js +23 -0
- package/dist/core/content-store.d.ts +21 -0
- package/dist/core/content-store.js +54 -0
- package/dist/core/debug.d.ts +1 -0
- package/dist/core/debug.js +12 -0
- package/dist/core/file-tree-merge.d.ts +2 -0
- package/dist/core/file-tree-merge.js +27 -0
- package/dist/core/file-tree.d.ts +36 -0
- package/dist/core/file-tree.js +1 -0
- package/dist/core/inflight-tracker.d.ts +19 -0
- package/dist/core/inflight-tracker.js +44 -0
- package/dist/core/internal/completion.d.ts +4 -0
- package/dist/core/internal/completion.js +29 -0
- package/dist/core/internal/content-store.d.ts +21 -0
- package/dist/core/internal/content-store.js +91 -0
- package/dist/core/internal/debug.d.ts +1 -0
- package/dist/core/internal/debug.js +16 -0
- package/dist/core/internal/inflight-tracker.d.ts +19 -0
- package/dist/core/internal/inflight-tracker.js +48 -0
- package/dist/core/internal/pagepocket.d.ts +27 -0
- package/dist/core/internal/pagepocket.js +155 -0
- package/dist/core/pagepocket.d.ts +38 -0
- package/dist/core/pagepocket.js +57 -0
- package/dist/core/plugin/_impl/context.d.ts +47 -0
- package/dist/core/plugin/_impl/context.js +142 -0
- package/dist/core/plugin/_impl/runner.d.ts +12 -0
- package/dist/core/plugin/_impl/runner.js +232 -0
- package/dist/core/plugin/_impl/types.d.ts +108 -0
- package/dist/core/plugin/_impl/types.js +2 -0
- package/dist/core/plugin/context.d.ts +47 -0
- package/dist/core/plugin/context.js +205 -0
- package/dist/core/plugin/internal/context.d.ts +47 -0
- package/dist/core/plugin/internal/context.js +142 -0
- package/dist/core/plugin/internal/runner.d.ts +12 -0
- package/dist/core/plugin/internal/runner.js +232 -0
- package/dist/core/plugin/internal/types.d.ts +108 -0
- package/dist/core/plugin/internal/types.js +2 -0
- package/dist/core/plugin/runner-utils.d.ts +9 -0
- package/dist/core/plugin/runner-utils.js +29 -0
- package/dist/core/plugin/runner.d.ts +12 -0
- package/dist/core/plugin/runner.js +118 -0
- package/dist/core/plugin/types.d.ts +117 -0
- package/dist/core/plugin/types.js +1 -0
- package/dist/core/runtime/types.d.ts +14 -0
- package/dist/core/runtime/types.js +2 -0
- package/dist/css-rewrite.js +1 -5
- package/dist/debug.d.ts +0 -1
- package/dist/debug.js +3 -5
- package/dist/files/types.d.ts +41 -0
- package/dist/files/types.js +2 -0
- package/dist/hack-html.js +20 -13
- package/dist/hackers/index.d.ts +1 -1
- package/dist/hackers/index.js +24 -27
- package/dist/hackers/preload-fetch.d.ts +1 -1
- package/dist/hackers/preload-fetch.js +1 -4
- package/dist/hackers/preload-xhr.d.ts +1 -1
- package/dist/hackers/preload-xhr.js +1 -4
- package/dist/hackers/replay-beacon.d.ts +1 -1
- package/dist/hackers/replay-beacon.js +1 -4
- package/dist/hackers/replay-block-text-fragment.d.ts +1 -1
- package/dist/hackers/replay-block-text-fragment.js +1 -4
- package/dist/hackers/replay-css-proxy.d.ts +1 -1
- package/dist/hackers/replay-css-proxy.js +9 -12
- package/dist/hackers/replay-dom-rewrite.d.ts +1 -1
- package/dist/hackers/replay-dom-rewrite.js +165 -154
- package/dist/hackers/replay-eventsource.d.ts +1 -1
- package/dist/hackers/replay-eventsource.js +1 -4
- package/dist/hackers/replay-fetch.d.ts +1 -1
- package/dist/hackers/replay-fetch.js +1 -4
- package/dist/hackers/replay-history-path.d.ts +1 -1
- package/dist/hackers/replay-history-path.js +1 -4
- package/dist/hackers/replay-svg-image.d.ts +1 -1
- package/dist/hackers/replay-svg-image.js +1 -4
- package/dist/hackers/replay-websocket.d.ts +1 -1
- package/dist/hackers/replay-websocket.js +1 -4
- package/dist/hackers/replay-xhr.d.ts +1 -1
- package/dist/hackers/replay-xhr.js +1 -4
- package/dist/hackers/types.js +1 -2
- package/dist/index.d.ts +29 -13
- package/dist/index.js +23 -44
- package/dist/kind-map.d.ts +68 -0
- package/dist/kind-map.js +58 -0
- package/dist/network-store.js +12 -1
- package/dist/pagepocket.d.ts +19 -4
- package/dist/pagepocket.js +36 -102
- package/dist/path-resolver.d.ts +1 -2
- package/dist/path-resolver.js +9 -16
- package/dist/plugin/builtins/build-snapshot-plugin.d.ts +5 -0
- package/dist/plugin/builtins/build-snapshot-plugin.js +84 -0
- package/dist/plugin/builtins/replace-elements-plugin.d.ts +8 -0
- package/dist/plugin/builtins/replace-elements-plugin.js +13 -0
- package/dist/plugin/builtins/to-directory-plugin.d.ts +7 -0
- package/dist/plugin/builtins/to-directory-plugin.js +20 -0
- package/dist/plugin/builtins/to-zip-plugin.d.ts +5 -0
- package/dist/plugin/builtins/to-zip-plugin.js +19 -0
- package/dist/plugin/context.d.ts +47 -0
- package/dist/plugin/context.js +142 -0
- package/dist/plugin/runner.d.ts +12 -0
- package/dist/plugin/runner.js +232 -0
- package/dist/plugin/types.d.ts +108 -0
- package/dist/plugin/types.js +2 -0
- package/dist/plugins/build-files-from-capture.d.ts +5 -0
- package/dist/plugins/build-files-from-capture.js +85 -0
- package/dist/plugins/build-warc.d.ts +5 -0
- package/dist/plugins/build-warc.js +225 -0
- package/dist/plugins/builtins/manifest.d.ts +2 -0
- package/dist/plugins/builtins/manifest.js +42 -0
- package/dist/plugins/builtins/snapshot-directory.d.ts +2 -0
- package/dist/plugins/builtins/snapshot-directory.js +24 -0
- package/dist/plugins/builtins/snapshot-zip.d.ts +2 -0
- package/dist/plugins/builtins/snapshot-zip.js +25 -0
- package/dist/plugins/capture-http-lighterceptor.d.ts +5 -0
- package/dist/plugins/capture-http-lighterceptor.js +85 -0
- package/dist/plugins/capture-http-puppeteer.d.ts +5 -0
- package/dist/plugins/capture-http-puppeteer.js +85 -0
- package/dist/plugins/host.d.ts +37 -0
- package/dist/plugins/host.js +105 -0
- package/dist/plugins/index.d.ts +6 -0
- package/dist/plugins/index.js +11 -0
- package/dist/plugins/ordering.d.ts +2 -0
- package/dist/plugins/ordering.js +19 -0
- package/dist/plugins/types.d.ts +51 -0
- package/dist/plugins/types.js +2 -0
- package/dist/preload.js +3 -7
- package/dist/replace-elements/actions.d.ts +5 -0
- package/dist/replace-elements/actions.js +86 -0
- package/dist/replace-elements/match.d.ts +5 -0
- package/dist/replace-elements/match.js +46 -0
- package/dist/replace-elements/normalize.d.ts +21 -0
- package/dist/replace-elements/normalize.js +50 -0
- package/dist/replace-elements.d.ts +1 -1
- package/dist/replace-elements.js +5 -185
- package/dist/replay/match-api.d.ts +10 -0
- package/dist/replay/match-api.js +162 -0
- package/dist/replay/templates/match-api-source.d.ts +1 -0
- package/dist/replay/templates/match-api-source.js +137 -0
- package/dist/replay/templates/replay-script-template.d.ts +5 -0
- package/dist/replay/templates/replay-script-template.js +337 -0
- package/dist/replay/templates/resource-proxy-script.d.ts +1 -0
- package/dist/replay/templates/resource-proxy-script.js +274 -0
- package/dist/replay-script.d.ts +3 -10
- package/dist/replay-script.js +11 -625
- package/dist/resource-filter.d.ts +1 -1
- package/dist/resource-filter.js +1 -5
- package/dist/resource-proxy/escape-percent.d.ts +1 -0
- package/dist/resource-proxy/escape-percent.js +12 -0
- package/dist/resource-proxy/multimap.d.ts +3 -0
- package/dist/resource-proxy/multimap.js +18 -0
- package/dist/resource-proxy/pathname-variants.d.ts +3 -0
- package/dist/resource-proxy/pathname-variants.js +54 -0
- package/dist/resource-proxy.d.ts +4 -2
- package/dist/resource-proxy.js +48 -117
- package/dist/resources.js +4 -42
- package/dist/rewrite-links/js-imports.d.ts +3 -0
- package/dist/rewrite-links/js-imports.js +56 -0
- package/dist/rewrite-links/link-rel.d.ts +2 -0
- package/dist/rewrite-links/link-rel.js +10 -0
- package/dist/rewrite-links/meta-refresh.d.ts +3 -0
- package/dist/rewrite-links/meta-refresh.js +22 -0
- package/dist/rewrite-links/skip.d.ts +1 -0
- package/dist/rewrite-links/skip.js +10 -0
- package/dist/rewrite-links/srcset.d.ts +3 -0
- package/dist/rewrite-links/srcset.js +63 -0
- package/dist/rewrite-links/url-resolve.d.ts +3 -0
- package/dist/rewrite-links/url-resolve.js +13 -0
- package/dist/rewrite-links.d.ts +3 -3
- package/dist/rewrite-links.js +31 -240
- package/dist/snapshot-builder/api.d.ts +3 -0
- package/dist/snapshot-builder/api.js +6 -0
- package/dist/snapshot-builder/build-snapshot.d.ts +3 -0
- package/dist/snapshot-builder/build-snapshot.js +138 -0
- package/dist/snapshot-builder/capture-index/index-capture.d.ts +13 -0
- package/dist/snapshot-builder/capture-index/index-capture.js +168 -0
- package/dist/snapshot-builder/capture-index/index.d.ts +2 -0
- package/dist/snapshot-builder/capture-index/index.js +1 -0
- package/dist/snapshot-builder/capture-index/types.d.ts +12 -0
- package/dist/snapshot-builder/capture-index/types.js +1 -0
- package/dist/snapshot-builder/capture-index.d.ts +12 -0
- package/dist/snapshot-builder/capture-index.js +173 -0
- package/dist/snapshot-builder/emit-document.d.ts +24 -0
- package/dist/snapshot-builder/emit-document.js +50 -0
- package/dist/snapshot-builder/grouping.d.ts +8 -0
- package/dist/snapshot-builder/grouping.js +87 -0
- package/dist/snapshot-builder/http.d.ts +6 -0
- package/dist/snapshot-builder/http.js +28 -0
- package/dist/snapshot-builder/index.d.ts +4 -0
- package/dist/snapshot-builder/index.js +2 -0
- package/dist/snapshot-builder/path-map.d.ts +3 -0
- package/dist/snapshot-builder/path-map.js +35 -0
- package/dist/snapshot-builder/resources-path.d.ts +23 -0
- package/dist/snapshot-builder/resources-path.js +47 -0
- package/dist/snapshot-builder/rewrite-resource.d.ts +18 -0
- package/dist/snapshot-builder/rewrite-resource.js +52 -0
- package/dist/snapshot-builder/types.d.ts +37 -0
- package/dist/snapshot-builder/types.js +2 -0
- package/dist/snapshot-builder.d.ts +12 -8
- package/dist/snapshot-builder.js +252 -27
- package/dist/types.d.ts +122 -78
- package/dist/types.js +4 -2
- package/dist/units/contracts-bridge.d.ts +76 -0
- package/dist/units/contracts-bridge.js +6 -0
- package/dist/units/index.d.ts +4 -0
- package/dist/units/index.js +2 -0
- package/dist/units/runner.d.ts +11 -0
- package/dist/units/runner.js +270 -0
- package/dist/units/types.d.ts +39 -0
- package/dist/units/types.js +1 -0
- package/dist/utils/streams.d.ts +2 -0
- package/dist/utils/streams.js +29 -0
- package/dist/utils.d.ts +35 -1
- package/dist/utils.js +107 -29
- package/dist/v3/contracts-bridge.d.ts +69 -0
- package/dist/v3/contracts-bridge.js +5 -0
- package/dist/v3/index.d.ts +4 -0
- package/dist/v3/index.js +2 -0
- package/dist/v3/runner.d.ts +20 -0
- package/dist/v3/runner.js +245 -0
- package/dist/v3/types.d.ts +39 -0
- package/dist/v3/types.js +1 -0
- package/dist/writers.js +3 -1
- package/package.json +11 -3
package/dist/replay-script.js
CHANGED
|
@@ -1,632 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const hackers_1 = require("./hackers");
|
|
6
|
-
function matchAPI(options) {
|
|
7
|
-
const { records, byKey, baseUrl, method, url, body } = options;
|
|
8
|
-
const normalizeBody = (value) => {
|
|
9
|
-
if (value === undefined || value === null)
|
|
10
|
-
return "";
|
|
11
|
-
if (typeof value === "string")
|
|
12
|
-
return value;
|
|
13
|
-
try {
|
|
14
|
-
return String(value);
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return "";
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
const normalizeUrl = (input) => {
|
|
21
|
-
try {
|
|
22
|
-
return new URL(input, baseUrl).toString();
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return input;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
const stripHash = (value) => {
|
|
29
|
-
const index = value.indexOf("#");
|
|
30
|
-
return index === -1 ? value : value.slice(0, index);
|
|
31
|
-
};
|
|
32
|
-
const stripTrailingSlash = (value) => {
|
|
33
|
-
if (value.length > 1 && value.endsWith("/")) {
|
|
34
|
-
return value.slice(0, -1);
|
|
35
|
-
}
|
|
36
|
-
return value;
|
|
37
|
-
};
|
|
38
|
-
const safeUrl = (input) => {
|
|
39
|
-
try {
|
|
40
|
-
return new URL(input, baseUrl);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
const toPathSearch = (input) => {
|
|
47
|
-
const parsed = safeUrl(input);
|
|
48
|
-
if (!parsed)
|
|
49
|
-
return input;
|
|
50
|
-
return parsed.pathname + parsed.search;
|
|
51
|
-
};
|
|
52
|
-
const toPathname = (input) => {
|
|
53
|
-
const parsed = safeUrl(input);
|
|
54
|
-
return parsed ? parsed.pathname : input;
|
|
55
|
-
};
|
|
56
|
-
const buildUrlVariants = (input) => {
|
|
57
|
-
const variants = new Set();
|
|
58
|
-
const push = (value) => {
|
|
59
|
-
if (!value)
|
|
60
|
-
return;
|
|
61
|
-
variants.add(value);
|
|
62
|
-
};
|
|
63
|
-
const raw = String(input ?? "");
|
|
64
|
-
push(raw);
|
|
65
|
-
push(stripHash(raw));
|
|
66
|
-
push(stripTrailingSlash(raw));
|
|
67
|
-
push(stripTrailingSlash(stripHash(raw)));
|
|
68
|
-
const absolute = normalizeUrl(raw);
|
|
69
|
-
push(absolute);
|
|
70
|
-
const absoluteNoHash = stripHash(absolute);
|
|
71
|
-
push(absoluteNoHash);
|
|
72
|
-
push(stripTrailingSlash(absoluteNoHash));
|
|
73
|
-
const pathSearch = toPathSearch(raw);
|
|
74
|
-
push(pathSearch);
|
|
75
|
-
push(stripTrailingSlash(pathSearch));
|
|
76
|
-
const pathname = toPathname(raw);
|
|
77
|
-
push(pathname);
|
|
78
|
-
push(stripTrailingSlash(pathname));
|
|
79
|
-
return Array.from(variants);
|
|
80
|
-
};
|
|
81
|
-
const makeKey = (keyMethod, keyUrl, keyBody) => keyMethod.toUpperCase() + " " + normalizeUrl(keyUrl) + " " + normalizeBody(keyBody);
|
|
82
|
-
const urlVariants = buildUrlVariants(url);
|
|
83
|
-
const bodyValue = normalizeBody(body);
|
|
84
|
-
const methodValue = (method || "GET").toUpperCase();
|
|
85
|
-
const tryLookup = (keyMethod, keyBody) => {
|
|
86
|
-
if (!byKey)
|
|
87
|
-
return undefined;
|
|
88
|
-
for (const urlVariant of urlVariants) {
|
|
89
|
-
const record = byKey.get(makeKey(keyMethod, urlVariant, keyBody));
|
|
90
|
-
if (record)
|
|
91
|
-
return record;
|
|
92
|
-
}
|
|
93
|
-
return undefined;
|
|
94
|
-
};
|
|
95
|
-
const matchOrder = [
|
|
96
|
-
[methodValue, bodyValue],
|
|
97
|
-
[methodValue, ""],
|
|
98
|
-
["GET", ""],
|
|
99
|
-
["GET", bodyValue]
|
|
100
|
-
];
|
|
101
|
-
for (const [keyMethod, keyBody] of matchOrder) {
|
|
102
|
-
const record = tryLookup(keyMethod, keyBody);
|
|
103
|
-
if (record)
|
|
104
|
-
return record;
|
|
105
|
-
}
|
|
106
|
-
const urlMatches = (inputUrl, recordUrl) => {
|
|
107
|
-
const inputAbs = stripHash(normalizeUrl(inputUrl));
|
|
108
|
-
const recordAbs = stripHash(normalizeUrl(recordUrl));
|
|
109
|
-
if (inputAbs === recordAbs)
|
|
110
|
-
return true;
|
|
111
|
-
const inputPathSearch = stripTrailingSlash(toPathSearch(inputUrl));
|
|
112
|
-
const recordPathSearch = stripTrailingSlash(toPathSearch(recordUrl));
|
|
113
|
-
if (inputPathSearch === recordPathSearch)
|
|
114
|
-
return true;
|
|
115
|
-
const inputPath = stripTrailingSlash(toPathname(inputUrl));
|
|
116
|
-
const recordPath = stripTrailingSlash(toPathname(recordUrl));
|
|
117
|
-
if (inputPath === recordPath)
|
|
118
|
-
return true;
|
|
119
|
-
return false;
|
|
120
|
-
};
|
|
121
|
-
const scanRecords = (keyMethod, keyBody) => {
|
|
122
|
-
for (const record of records || []) {
|
|
123
|
-
if (!record || !record.url || !record.method)
|
|
124
|
-
continue;
|
|
125
|
-
if (record.method.toUpperCase() !== keyMethod)
|
|
126
|
-
continue;
|
|
127
|
-
if (!urlMatches(url, record.url))
|
|
128
|
-
continue;
|
|
129
|
-
const recordBody = record.requestBody || record.requestBodyBase64 || "";
|
|
130
|
-
if (keyBody && recordBody !== keyBody)
|
|
131
|
-
continue;
|
|
132
|
-
return record;
|
|
133
|
-
}
|
|
134
|
-
return undefined;
|
|
135
|
-
};
|
|
136
|
-
for (const [keyMethod, keyBody] of matchOrder) {
|
|
137
|
-
const record = scanRecords(keyMethod, keyBody);
|
|
138
|
-
if (record)
|
|
139
|
-
return record;
|
|
140
|
-
}
|
|
141
|
-
return undefined;
|
|
142
|
-
}
|
|
143
|
-
const buildReplayScript = (apiPath, baseUrl) => {
|
|
1
|
+
import { replayHackers } from "./hackers/index.js";
|
|
2
|
+
import { matchAPI } from "./replay/match-api.js";
|
|
3
|
+
import { buildReplayInjectedScript } from "./replay/templates/replay-script-template.js";
|
|
4
|
+
export const buildReplayScript = (apiPath, baseUrl) => {
|
|
144
5
|
const basePayload = JSON.stringify(baseUrl);
|
|
145
6
|
const apiPayload = JSON.stringify(apiPath);
|
|
146
7
|
const context = { stage: "replay" };
|
|
147
|
-
const hackerScripts =
|
|
8
|
+
const hackerScripts = replayHackers
|
|
148
9
|
.map((hacker) => ` // hacker:${hacker.id}\n${hacker.build(context)}`)
|
|
149
10
|
.join("\n");
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const index = input.indexOf("#");
|
|
155
|
-
return index === -1 ? input : input.slice(0, index);
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const stripTrailingSlash = (value) => {
|
|
159
|
-
const input = String(value || "");
|
|
160
|
-
if (!input || input === "/") return input;
|
|
161
|
-
return input.endsWith("/") ? input.slice(0, -1) : input;
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const looksAlreadyEscapedForStaticServers = (value) => {
|
|
165
|
-
return /%25[0-9a-fA-F]{2}/.test(String(value || ""));
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
const escapePercentForStaticServersOnce = (value) => {
|
|
169
|
-
const input = String(value || "");
|
|
170
|
-
if (!input) return input;
|
|
171
|
-
if (looksAlreadyEscapedForStaticServers(input)) return input;
|
|
172
|
-
return input.split("%").join("%25");
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const isLikelyHostname = (value) => {
|
|
176
|
-
const input = String(value || "");
|
|
177
|
-
if (!input) return false;
|
|
178
|
-
if (input === "localhost") return true;
|
|
179
|
-
return input.includes(".");
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const encodeEmbeddedUrlTailIfPresent = (pathname) => {
|
|
183
|
-
const raw = String(pathname || "");
|
|
184
|
-
if (!raw.includes("/http")) return null;
|
|
185
|
-
const parts = raw.split("/");
|
|
186
|
-
for (let i = 0; i < parts.length; i += 1) {
|
|
187
|
-
const scheme = parts[i];
|
|
188
|
-
if (scheme !== "http:" && scheme !== "https:") continue;
|
|
189
|
-
const hasDoubleSlash = parts[i + 1] === "";
|
|
190
|
-
const host = parts[i + 2] || "";
|
|
191
|
-
if (!hasDoubleSlash || !isLikelyHostname(host)) continue;
|
|
192
|
-
const embedded = scheme + "//" + parts.slice(i + 2).join("/");
|
|
193
|
-
const encoded = encodeURIComponent(embedded);
|
|
194
|
-
const nextParts = parts.slice(0, i).concat(encoded);
|
|
195
|
-
const rebuilt = nextParts.join("/") || "/";
|
|
196
|
-
return rebuilt.startsWith("/") ? rebuilt : "/" + rebuilt;
|
|
197
|
-
}
|
|
198
|
-
return null;
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
const makePathnameVariants = (pathname) => {
|
|
202
|
-
const variants = new Set();
|
|
203
|
-
const push = (value) => {
|
|
204
|
-
if (!value) return;
|
|
205
|
-
variants.add(value);
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const raw = String(pathname || "");
|
|
209
|
-
push(raw);
|
|
210
|
-
push(stripTrailingSlash(raw));
|
|
211
|
-
|
|
212
|
-
const encodedTail = encodeEmbeddedUrlTailIfPresent(raw);
|
|
213
|
-
if (encodedTail && encodedTail !== raw) {
|
|
214
|
-
push(encodedTail);
|
|
215
|
-
push(stripTrailingSlash(encodedTail));
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return Array.from(variants);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
const toUrlOrNull = (value, base) => {
|
|
222
|
-
try {
|
|
223
|
-
return new URL(String(value || ""), String(base || ""));
|
|
224
|
-
} catch {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const getBasename = (pathname) => {
|
|
230
|
-
const clean = String(pathname || "").split("?")[0] || "";
|
|
231
|
-
const parts = clean.split("/").filter(Boolean);
|
|
232
|
-
return parts[parts.length - 1] || "";
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
const makeSuffixes = (pathname) => {
|
|
236
|
-
const parts = String(pathname || "").split("/").filter(Boolean);
|
|
237
|
-
const out = [];
|
|
238
|
-
for (let i = 0; i < parts.length; i += 1) {
|
|
239
|
-
out.push({ key: "/" + parts.slice(i).join("/"), depth: parts.length - i });
|
|
240
|
-
}
|
|
241
|
-
return out;
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
const toArray = (value) => {
|
|
245
|
-
if (!value) return [];
|
|
246
|
-
return Array.isArray(value) ? value : [value];
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
const addMulti = (map, key, value) => {
|
|
250
|
-
const existing = map.get(key);
|
|
251
|
-
if (!existing) {
|
|
252
|
-
map.set(key, value);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
if (Array.isArray(existing)) {
|
|
256
|
-
existing.push(value);
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
map.set(key, [existing, value]);
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
const uniqByPath = (items) => {
|
|
263
|
-
const seen = new Set();
|
|
264
|
-
const out = [];
|
|
265
|
-
for (const item of items || []) {
|
|
266
|
-
const p = item && item.path;
|
|
267
|
-
if (!p || seen.has(p)) continue;
|
|
268
|
-
seen.add(p);
|
|
269
|
-
out.push(item);
|
|
270
|
-
}
|
|
271
|
-
return out;
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const chooseUnique = (items, baseUrl, depth) => {
|
|
275
|
-
const unique = uniqByPath(items);
|
|
276
|
-
if (unique.length === 0) return null;
|
|
277
|
-
if (unique.length === 1) return unique[0];
|
|
278
|
-
|
|
279
|
-
try {
|
|
280
|
-
const base = new URL(String(baseUrl || ""));
|
|
281
|
-
const sameOrigin = unique.filter((i) => i && i.origin === base.origin);
|
|
282
|
-
if (sameOrigin.length === 1) {
|
|
283
|
-
return sameOrigin[0];
|
|
284
|
-
}
|
|
285
|
-
if (sameOrigin.length > 1) {
|
|
286
|
-
items = sameOrigin;
|
|
287
|
-
}
|
|
288
|
-
} catch {}
|
|
289
|
-
|
|
290
|
-
if (depth < 2) {
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return null;
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
const buildIndex = (snapshot) => {
|
|
298
|
-
const byExactUrl = new Map();
|
|
299
|
-
const byPathnameWithSearch = new Map();
|
|
300
|
-
const byPathname = new Map();
|
|
301
|
-
const byBasename = new Map();
|
|
302
|
-
|
|
303
|
-
for (const item of (snapshot && snapshot.items) || []) {
|
|
304
|
-
if (!item || !item.url || !item.path) continue;
|
|
305
|
-
let parsed = null;
|
|
306
|
-
try {
|
|
307
|
-
parsed = new URL(item.url);
|
|
308
|
-
} catch {
|
|
309
|
-
parsed = null;
|
|
310
|
-
}
|
|
311
|
-
if (!parsed) continue;
|
|
312
|
-
|
|
313
|
-
const pathname = parsed.pathname || "/";
|
|
314
|
-
const pathnameWithSearch = pathname + (parsed.search || "");
|
|
315
|
-
const basename = getBasename(pathname);
|
|
316
|
-
|
|
317
|
-
const indexed = {
|
|
318
|
-
url: parsed.toString(),
|
|
319
|
-
origin: parsed.origin,
|
|
320
|
-
pathname,
|
|
321
|
-
pathnameWithSearch,
|
|
322
|
-
basename,
|
|
323
|
-
path: item.path,
|
|
324
|
-
resourceType: item.resourceType,
|
|
325
|
-
mimeType: item.mimeType,
|
|
326
|
-
size: item.size
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
if (!byExactUrl.has(indexed.url)) {
|
|
330
|
-
byExactUrl.set(indexed.url, indexed);
|
|
331
|
-
}
|
|
332
|
-
addMulti(byPathnameWithSearch, pathnameWithSearch, indexed);
|
|
333
|
-
addMulti(byPathname, pathname, indexed);
|
|
334
|
-
if (basename) {
|
|
335
|
-
addMulti(byBasename, basename, indexed);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return { byExactUrl, byPathnameWithSearch, byPathname, byBasename };
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
const resolveToLocalPath = (requestUrl, baseUrl, index) => {
|
|
343
|
-
if (!requestUrl) return null;
|
|
344
|
-
const abs = toUrlOrNull(String(requestUrl), baseUrl);
|
|
345
|
-
if (!abs) return null;
|
|
346
|
-
|
|
347
|
-
const absString = abs.toString();
|
|
348
|
-
const exact = index && index.byExactUrl && index.byExactUrl.get(absString);
|
|
349
|
-
if (exact) return escapePercentForStaticServersOnce(exact.path);
|
|
350
|
-
|
|
351
|
-
const withoutHash = stripHash(absString);
|
|
352
|
-
if (withoutHash !== absString) {
|
|
353
|
-
const found = index.byExactUrl.get(withoutHash);
|
|
354
|
-
if (found) return escapePercentForStaticServersOnce(found.path);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const pathname = abs.pathname || "/";
|
|
358
|
-
const pathnameVariants = makePathnameVariants(pathname);
|
|
359
|
-
const search = abs.search || "";
|
|
360
|
-
const pathnameWithSearchVariants = pathnameVariants.map((p) => String(p) + search);
|
|
361
|
-
|
|
362
|
-
for (const key of pathnameWithSearchVariants) {
|
|
363
|
-
const items = toArray(index.byPathnameWithSearch.get(key));
|
|
364
|
-
const chosen = chooseUnique(items, baseUrl, 99);
|
|
365
|
-
if (chosen) return escapePercentForStaticServersOnce(chosen.path);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
for (const key of pathnameVariants) {
|
|
369
|
-
const items = toArray(index.byPathname.get(key));
|
|
370
|
-
const chosen = chooseUnique(items, baseUrl, 99);
|
|
371
|
-
if (chosen) return escapePercentForStaticServersOnce(chosen.path);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
for (const variant of pathnameVariants) {
|
|
375
|
-
for (const suffix of makeSuffixes(variant)) {
|
|
376
|
-
const items = toArray(index.byPathname.get(suffix.key));
|
|
377
|
-
const chosen = chooseUnique(items, baseUrl, suffix.depth);
|
|
378
|
-
if (chosen) return escapePercentForStaticServersOnce(chosen.path);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
const basename = getBasename(pathname);
|
|
383
|
-
if (basename) {
|
|
384
|
-
const items = toArray(index.byBasename.get(basename));
|
|
385
|
-
const chosen = chooseUnique(items, baseUrl, 1);
|
|
386
|
-
if (chosen) return escapePercentForStaticServersOnce(chosen.path);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
return null;
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
return { buildIndex, resolveToLocalPath };
|
|
393
|
-
})();
|
|
394
|
-
`;
|
|
395
|
-
return `
|
|
396
|
-
<script>
|
|
397
|
-
(function(){
|
|
398
|
-
const baseUrl = ${basePayload};
|
|
399
|
-
const apiUrl = ${apiPayload};
|
|
400
|
-
const resourcesPathUrl = "/resources_path.json";
|
|
401
|
-
const __pagepocketOriginalFetch = window.fetch ? window.fetch.bind(window) : null;
|
|
402
|
-
|
|
403
|
-
${resourceProxyScript}
|
|
404
|
-
|
|
405
|
-
const loadResourcesPath = async () => {
|
|
406
|
-
try {
|
|
407
|
-
if (!__pagepocketOriginalFetch) {
|
|
408
|
-
throw new Error("Fetch is unavailable");
|
|
409
|
-
}
|
|
410
|
-
const response = await __pagepocketOriginalFetch(resourcesPathUrl);
|
|
411
|
-
if (!response.ok) {
|
|
412
|
-
throw new Error("Failed to load resources_path.json");
|
|
413
|
-
}
|
|
414
|
-
const json = await response.json();
|
|
415
|
-
if (!json || json.version !== "1.0" || !Array.isArray(json.items)) {
|
|
416
|
-
throw new Error("Invalid resources_path.json");
|
|
417
|
-
}
|
|
418
|
-
return json;
|
|
419
|
-
} catch {
|
|
420
|
-
return { version: "1.0", createdAt: 0, items: [] };
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
const loadApiSnapshot = async () => {
|
|
425
|
-
try {
|
|
426
|
-
if (!__pagepocketOriginalFetch) {
|
|
427
|
-
throw new Error("Fetch is unavailable");
|
|
428
|
-
}
|
|
429
|
-
const response = await __pagepocketOriginalFetch(apiUrl);
|
|
430
|
-
if (!response.ok) {
|
|
431
|
-
throw new Error("Failed to load api.json");
|
|
432
|
-
}
|
|
433
|
-
return await response.json();
|
|
434
|
-
} catch {
|
|
435
|
-
return { version: "1.0", url: baseUrl, createdAt: 0, records: [] };
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
|
|
439
|
-
const originalResponseJson = Response && Response.prototype && Response.prototype.json;
|
|
440
|
-
if (originalResponseJson) {
|
|
441
|
-
Response.prototype.json = function(...args) {
|
|
442
|
-
try {
|
|
443
|
-
return originalResponseJson.apply(this, args).catch(() => null);
|
|
444
|
-
} catch {
|
|
445
|
-
return Promise.resolve(null);
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
const ensureReplayPatches = () => {
|
|
451
|
-
try {
|
|
452
|
-
if (!window.fetch.__pagepocketOriginal && typeof __pagepocketOriginalFetch === "function") {
|
|
453
|
-
window.fetch.__pagepocketOriginal = __pagepocketOriginalFetch;
|
|
454
|
-
}
|
|
455
|
-
} catch {}
|
|
456
|
-
try {
|
|
457
|
-
if (!XMLHttpRequest.prototype.send.__pagepocketOriginal) {
|
|
458
|
-
XMLHttpRequest.prototype.send.__pagepocketOriginal = XMLHttpRequest.prototype.send;
|
|
459
|
-
}
|
|
460
|
-
} catch {}
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
let records = [];
|
|
464
|
-
const byKey = new Map();
|
|
465
|
-
|
|
466
|
-
let resourceIndex = null;
|
|
467
|
-
|
|
468
|
-
const normalizeUrl = (input) => {
|
|
469
|
-
try { return new URL(input, baseUrl).toString(); } catch { return input; }
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
const normalizeBody = (body) => {
|
|
473
|
-
if (body === undefined || body === null) return "";
|
|
474
|
-
if (typeof body === "string") return body;
|
|
475
|
-
try { return String(body); } catch { return ""; }
|
|
476
|
-
};
|
|
477
|
-
|
|
478
|
-
const makeKey = (method, url, body) => method.toUpperCase() + " " + normalizeUrl(url) + " " + normalizeBody(body);
|
|
479
|
-
const makeVariantKeys = (method, url, body) => [makeKey(method, url, body)];
|
|
480
|
-
|
|
481
|
-
const matchAPI = ${matchAPI.toString()};
|
|
482
|
-
|
|
483
|
-
const primeLookups = (snapshot) => {
|
|
484
|
-
records = snapshot.records || [];
|
|
485
|
-
byKey.clear();
|
|
486
|
-
for (const record of records) {
|
|
487
|
-
if (!record || !record.url || !record.method) continue;
|
|
488
|
-
const keys = makeVariantKeys(record.method, record.url, record.requestBody || record.requestBodyBase64 || "");
|
|
489
|
-
for (const key of keys) {
|
|
490
|
-
if (!byKey.has(key)) {
|
|
491
|
-
byKey.set(key, record);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
|
|
497
|
-
const ready = (async () => {
|
|
498
|
-
const [apiSnapshot, resourcesPath] = await Promise.all([loadApiSnapshot(), loadResourcesPath()]);
|
|
499
|
-
resourceIndex = __pagepocketResourceProxy.buildIndex(resourcesPath || {});
|
|
500
|
-
|
|
501
|
-
const snapshot = apiSnapshot || {};
|
|
502
|
-
primeLookups(snapshot);
|
|
503
|
-
return snapshot;
|
|
504
|
-
})();
|
|
505
|
-
|
|
506
|
-
const isLocalResource = (value) => {
|
|
507
|
-
if (!value) return false;
|
|
508
|
-
if (value.startsWith("data:") || value.startsWith("blob:")) return true;
|
|
509
|
-
if (value.startsWith("/")) return true;
|
|
510
|
-
return false;
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
const findRecord = (method, url, body) => {
|
|
514
|
-
return matchAPI({ records, byKey, baseUrl, method, url, body });
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
const urlLookupCache = new Map();
|
|
518
|
-
const findByUrl = (url) => {
|
|
519
|
-
if (isLocalResource(url)) return null;
|
|
520
|
-
if (urlLookupCache.has(url)) {
|
|
521
|
-
return urlLookupCache.get(url);
|
|
522
|
-
}
|
|
523
|
-
const record = matchAPI({ records, byKey, baseUrl, method: "GET", url, body: "" });
|
|
524
|
-
urlLookupCache.set(url, record || null);
|
|
525
|
-
return record;
|
|
526
|
-
};
|
|
527
|
-
|
|
528
|
-
const findLocalPath = (url) => {
|
|
529
|
-
try {
|
|
530
|
-
if (!url || isLocalResource(String(url))) {
|
|
531
|
-
return null;
|
|
532
|
-
}
|
|
533
|
-
if (!resourceIndex) {
|
|
534
|
-
return null;
|
|
535
|
-
}
|
|
536
|
-
return __pagepocketResourceProxy.resolveToLocalPath(String(url), baseUrl, resourceIndex);
|
|
537
|
-
} catch {
|
|
538
|
-
return null;
|
|
539
|
-
}
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
const defineProp = (obj, key, value) => {
|
|
543
|
-
try {
|
|
544
|
-
Object.defineProperty(obj, key, { value, configurable: true });
|
|
545
|
-
} catch {}
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
const decodeBase64 = (input) => {
|
|
549
|
-
try {
|
|
550
|
-
const binary = atob(input || "");
|
|
551
|
-
const bytes = new Uint8Array(binary.length);
|
|
552
|
-
Array.from(binary).forEach((char, index) => {
|
|
553
|
-
bytes[index] = char.charCodeAt(0);
|
|
554
|
-
});
|
|
555
|
-
return bytes;
|
|
556
|
-
} catch {
|
|
557
|
-
return new Uint8Array();
|
|
558
|
-
}
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
const bytesToBase64 = (bytes) => {
|
|
562
|
-
const binary = Array.from(bytes, (value) => String.fromCharCode(value)).join("");
|
|
563
|
-
return btoa(binary);
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
const textToBase64 = (text) => {
|
|
567
|
-
try {
|
|
568
|
-
const bytes = new TextEncoder().encode(text || "");
|
|
569
|
-
return bytesToBase64(bytes);
|
|
570
|
-
} catch {
|
|
571
|
-
return btoa(text || "");
|
|
572
|
-
}
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
const getContentType = (record) => {
|
|
576
|
-
const headers = record.responseHeaders || {};
|
|
577
|
-
for (const key in headers) {
|
|
578
|
-
if (key.toLowerCase() === "content-type") {
|
|
579
|
-
return headers[key] || "application/octet-stream";
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
return "application/octet-stream";
|
|
583
|
-
};
|
|
584
|
-
|
|
585
|
-
const dataUrlCache = new Map();
|
|
586
|
-
const toDataUrl = (record, fallbackType) => {
|
|
587
|
-
if (!record) return "";
|
|
588
|
-
const contentType = getContentType(record) || fallbackType || "application/octet-stream";
|
|
589
|
-
const cacheKey = (record.url || "") + "|" + contentType + "|" + (record.responseEncoding || "") + "|" +
|
|
590
|
-
(record.responseBodyBase64 ? "b64:" + record.responseBodyBase64.length : "txt:" + (record.responseBody ? record.responseBody.length : 0));
|
|
591
|
-
if (dataUrlCache.has(cacheKey)) {
|
|
592
|
-
return dataUrlCache.get(cacheKey);
|
|
593
|
-
}
|
|
594
|
-
if (record.responseEncoding === "base64" && record.responseBodyBase64) {
|
|
595
|
-
const dataUrl = "data:" + contentType + ";base64," + record.responseBodyBase64;
|
|
596
|
-
dataUrlCache.set(cacheKey, dataUrl);
|
|
597
|
-
return dataUrl;
|
|
598
|
-
}
|
|
599
|
-
if (record.responseBody) {
|
|
600
|
-
const dataUrl = "data:" + contentType + ";base64," + textToBase64(record.responseBody);
|
|
601
|
-
dataUrlCache.set(cacheKey, dataUrl);
|
|
602
|
-
return dataUrl;
|
|
603
|
-
}
|
|
604
|
-
const dataUrl = "data:" + (fallbackType || "application/octet-stream") + ",";
|
|
605
|
-
dataUrlCache.set(cacheKey, dataUrl);
|
|
606
|
-
return dataUrl;
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
const responseFromRecord = (record) => {
|
|
610
|
-
const headers = new Headers(record.responseHeaders || {});
|
|
611
|
-
if (record.responseEncoding === "base64" && record.responseBodyBase64) {
|
|
612
|
-
const bytes = decodeBase64(record.responseBodyBase64);
|
|
613
|
-
return new Response(bytes, {
|
|
614
|
-
status: record.status || 200,
|
|
615
|
-
statusText: record.statusText || "OK",
|
|
616
|
-
headers
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
const bodyText = record.responseBody || "";
|
|
620
|
-
return new Response(bodyText, {
|
|
621
|
-
status: record.status || 200,
|
|
622
|
-
statusText: record.statusText || "OK",
|
|
623
|
-
headers
|
|
11
|
+
return buildReplayInjectedScript({
|
|
12
|
+
basePayload,
|
|
13
|
+
apiPayload,
|
|
14
|
+
hackerScripts
|
|
624
15
|
});
|
|
625
|
-
};
|
|
626
|
-
|
|
627
|
-
${hackerScripts}
|
|
628
|
-
})();
|
|
629
|
-
</script>
|
|
630
|
-
`;
|
|
631
16
|
};
|
|
632
|
-
|
|
17
|
+
// Exported for unit tests; runtime replay uses injected matchAPISource.
|
|
18
|
+
export { matchAPI };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { ResourceFilter } from "./types";
|
|
1
|
+
import type { ResourceFilter } from "./types.js";
|
|
2
2
|
export declare const createDefaultResourceFilter: () => ResourceFilter;
|
package/dist/resource-filter.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createDefaultResourceFilter = void 0;
|
|
4
1
|
const DEFAULT_ALLOWED = new Set(["document", "stylesheet", "script", "image", "font", "media"]);
|
|
5
2
|
const isSkippableUrl = (url) => url.startsWith("data:") ||
|
|
6
3
|
url.startsWith("blob:") ||
|
|
7
4
|
url.startsWith("mailto:") ||
|
|
8
5
|
url.startsWith("tel:") ||
|
|
9
6
|
url.startsWith("javascript:");
|
|
10
|
-
const createDefaultResourceFilter = () => ({
|
|
7
|
+
export const createDefaultResourceFilter = () => ({
|
|
11
8
|
shouldSave(req, res) {
|
|
12
9
|
if (isSkippableUrl(req.url)) {
|
|
13
10
|
return false;
|
|
@@ -24,4 +21,3 @@ const createDefaultResourceFilter = () => ({
|
|
|
24
21
|
return true;
|
|
25
22
|
}
|
|
26
23
|
});
|
|
27
|
-
exports.createDefaultResourceFilter = createDefaultResourceFilter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const escapePercentForStaticServersOnce: (value: string) => string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const looksAlreadyEscapedForStaticServers = (value) => {
|
|
2
|
+
return /%25[0-9a-fA-F]{2}/.test(value);
|
|
3
|
+
};
|
|
4
|
+
export const escapePercentForStaticServersOnce = (value) => {
|
|
5
|
+
if (!value) {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
if (looksAlreadyEscapedForStaticServers(value)) {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
return value.split("%").join("%25");
|
|
12
|
+
};
|