@wenathlan/extension 1.1.39 → 1.1.40
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 +5 -4
- package/dist/capture.d.ts +161 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +360 -4
- package/dist/index.js.map +3 -3
- package/dist/memory.d.ts +17 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/policy.d.ts +19 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +18 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/types.d.ts +89 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +841 -50
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +1 -1
- package/extension/dist/pagebridge.js +53 -2
- package/extension/dist/pagebridge.js.map +2 -2
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +9 -1
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +138 -1
- package/extension/dist/sidepanel.js.map +2 -2
- package/extension/dist/style.css +2 -0
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,201 @@
|
|
|
1
|
+
// capture.ts
|
|
2
|
+
var captureformats = ["png", "jpeg", "webp"];
|
|
3
|
+
var capturetargets = ["memory", "download", "clipboard"];
|
|
4
|
+
var capturekinds = ["shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"];
|
|
5
|
+
function captureoptionsof(value) {
|
|
6
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
7
|
+
const options = value;
|
|
8
|
+
const normalized = {};
|
|
9
|
+
if (options.format === "png" || options.format === "jpeg" || options.format === "webp") normalized.format = options.format;
|
|
10
|
+
if (typeof options.quality === "number" && Number.isFinite(options.quality)) normalized.quality = options.quality;
|
|
11
|
+
if (typeof options.pixelratio === "number" && Number.isFinite(options.pixelratio)) normalized.pixelratio = options.pixelratio;
|
|
12
|
+
if (typeof options.annotate === "boolean") normalized.annotate = options.annotate;
|
|
13
|
+
if (options.exporttarget === "memory" || options.exporttarget === "download" || options.exporttarget === "clipboard") normalized.exporttarget = options.exporttarget;
|
|
14
|
+
return normalized;
|
|
15
|
+
}
|
|
16
|
+
function capturevisible(input) {
|
|
17
|
+
const ratio = input.options.pixelratio ?? 1;
|
|
18
|
+
return {
|
|
19
|
+
id: input.id,
|
|
20
|
+
runid: input.runid,
|
|
21
|
+
stepid: input.stepid,
|
|
22
|
+
kind: "shotview",
|
|
23
|
+
format: input.options.format ?? "png",
|
|
24
|
+
width: Math.round(input.viewport.width * ratio),
|
|
25
|
+
height: Math.round(input.viewport.height * ratio),
|
|
26
|
+
capturedat: input.at,
|
|
27
|
+
bytes: input.dataurl,
|
|
28
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
29
|
+
...input.options.annotate === true ? { annotated: true } : {},
|
|
30
|
+
...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {},
|
|
31
|
+
...input.target !== void 0 ? { target: input.target } : {}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function capturestitched(input) {
|
|
35
|
+
const ratio = input.options.pixelratio ?? 1;
|
|
36
|
+
return {
|
|
37
|
+
id: input.id,
|
|
38
|
+
runid: input.runid,
|
|
39
|
+
stepid: input.stepid,
|
|
40
|
+
kind: "shotfullpage",
|
|
41
|
+
format: input.options.format ?? "png",
|
|
42
|
+
width: Math.round(input.plan.scrollwidth * ratio),
|
|
43
|
+
height: Math.round(input.plan.scrollheight * ratio),
|
|
44
|
+
capturedat: input.at,
|
|
45
|
+
bytes: input.dataurl,
|
|
46
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
47
|
+
...input.options.annotate === true ? { annotated: true } : {},
|
|
48
|
+
...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function captureelement(input) {
|
|
52
|
+
const ratio = input.options.pixelratio ?? 1;
|
|
53
|
+
const scaled = scaledrect(input.rect, ratio);
|
|
54
|
+
return {
|
|
55
|
+
id: input.id,
|
|
56
|
+
runid: input.runid,
|
|
57
|
+
stepid: input.stepid,
|
|
58
|
+
kind: "shotelement",
|
|
59
|
+
format: input.options.format ?? "png",
|
|
60
|
+
width: scaled.width,
|
|
61
|
+
height: scaled.height,
|
|
62
|
+
capturedat: input.at,
|
|
63
|
+
bytes: input.dataurl,
|
|
64
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
65
|
+
...input.options.annotate === true ? { annotated: true } : {},
|
|
66
|
+
...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {},
|
|
67
|
+
...input.target !== void 0 ? { target: input.target } : {}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function captureregion(input) {
|
|
71
|
+
const ratio = input.options.pixelratio ?? 1;
|
|
72
|
+
const scaled = scaledrect(input.rect, ratio);
|
|
73
|
+
return {
|
|
74
|
+
id: input.id,
|
|
75
|
+
runid: input.runid,
|
|
76
|
+
stepid: input.stepid,
|
|
77
|
+
kind: "shotregion",
|
|
78
|
+
format: input.options.format ?? "png",
|
|
79
|
+
width: scaled.width,
|
|
80
|
+
height: scaled.height,
|
|
81
|
+
capturedat: input.at,
|
|
82
|
+
bytes: input.dataurl,
|
|
83
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
84
|
+
...input.options.annotate === true ? { annotated: true } : {},
|
|
85
|
+
...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {},
|
|
86
|
+
...input.target !== void 0 ? { target: input.target } : {}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function pairstates(before, after, action, at, id) {
|
|
90
|
+
if (!before) return { skipped: "before", reason: "The before shot was not captured, so no state pair exists." };
|
|
91
|
+
if (!after) return { skipped: "after", reason: `The action of kind ${action.kind} failed before the after shot, so the state pair is skipped.` };
|
|
92
|
+
return {
|
|
93
|
+
pair: {
|
|
94
|
+
id,
|
|
95
|
+
beforeid: before.id,
|
|
96
|
+
afterid: after.id,
|
|
97
|
+
actionkind: action.kind,
|
|
98
|
+
...action.target !== void 0 ? { target: action.target } : {},
|
|
99
|
+
...action.domsnapshotid !== void 0 ? { domsnapshotid: action.domsnapshotid } : {},
|
|
100
|
+
at
|
|
101
|
+
},
|
|
102
|
+
reason: `Paired the before shot ${before.id} with the after shot ${after.id} around the ${action.kind} action.`
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function capturestates(input) {
|
|
106
|
+
if (input.policy !== "beforeafter") return { reason: `The ${input.policy} capture policy takes no state pair around the ${input.actionkind} action.` };
|
|
107
|
+
return pairstates(input.before, input.after, { kind: input.actionkind, ...input.target !== void 0 ? { target: input.target } : {}, ...input.domsnapshotid !== void 0 ? { domsnapshotid: input.domsnapshotid } : {} }, input.at, input.id);
|
|
108
|
+
}
|
|
109
|
+
function buildstitchplan(input) {
|
|
110
|
+
const overlap = Math.max(0, Math.round(input.overlap ?? 0));
|
|
111
|
+
const stepy = Math.max(1, input.viewportheight - overlap);
|
|
112
|
+
const columns = Math.max(1, Math.ceil(input.scrollwidth / input.viewportwidth));
|
|
113
|
+
const rows = input.scrollheight <= input.viewportheight ? 1 : Math.max(1, Math.ceil((input.scrollheight - overlap) / stepy));
|
|
114
|
+
const tiles = [];
|
|
115
|
+
for (let column = 0; column < columns; column += 1) {
|
|
116
|
+
for (let row = 0; row < rows; row += 1) {
|
|
117
|
+
const x = Math.min(column * input.viewportwidth, Math.max(0, input.scrollwidth - input.viewportwidth));
|
|
118
|
+
const y = rows === 1 ? 0 : Math.min(row * stepy, Math.max(0, input.scrollheight - input.viewportheight));
|
|
119
|
+
tiles.push({ x: Math.round(x), y: Math.round(y) });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { columns, rows, tiles, overlap, scrollwidth: Math.round(input.scrollwidth), scrollheight: Math.round(input.scrollheight), viewportwidth: Math.round(input.viewportwidth), viewportheight: Math.round(input.viewportheight) };
|
|
123
|
+
}
|
|
124
|
+
function seamweights(overlap) {
|
|
125
|
+
if (overlap <= 0) return [];
|
|
126
|
+
const weights = [];
|
|
127
|
+
for (let index = 0; index < overlap; index += 1) weights.push((index + 1) / (overlap + 1));
|
|
128
|
+
return weights;
|
|
129
|
+
}
|
|
130
|
+
function blendrows(upper, lower) {
|
|
131
|
+
const weights = seamweights(upper.length);
|
|
132
|
+
return upper.map((value, index) => {
|
|
133
|
+
const weight = weights[index] ?? 1;
|
|
134
|
+
return value * (1 - weight) + (lower[index] ?? value) * weight;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function fixedheadermatch(band, firstband) {
|
|
138
|
+
if (band.length === 0 || band.length !== firstband.length) return false;
|
|
139
|
+
return band.every((value, index) => value === firstband[index]);
|
|
140
|
+
}
|
|
141
|
+
function scaledrect(rect, pixelratio) {
|
|
142
|
+
const ratio = pixelratio >= 1 ? pixelratio : 1;
|
|
143
|
+
return { x: Math.round(rect.x * ratio), y: Math.round(rect.y * ratio), width: Math.round(rect.width * ratio), height: Math.round(rect.height * ratio) };
|
|
144
|
+
}
|
|
145
|
+
function croprect(rect, viewport) {
|
|
146
|
+
const x = Math.max(0, rect.x);
|
|
147
|
+
const y = Math.max(0, rect.y);
|
|
148
|
+
return { x: Math.round(x), y: Math.round(y), width: Math.round(Math.max(0, Math.min(rect.width, viewport.width - x))), height: Math.round(Math.max(0, Math.min(rect.height, viewport.height - y))) };
|
|
149
|
+
}
|
|
150
|
+
function crossesviewport(rect, viewport) {
|
|
151
|
+
return rect.x < 0 || rect.y < 0 || rect.x + rect.width > viewport.width || rect.y + rect.height > viewport.height;
|
|
152
|
+
}
|
|
153
|
+
function regionsteps(containerheight, viewportstep) {
|
|
154
|
+
if (containerheight <= 0 || viewportstep <= 0) return [0];
|
|
155
|
+
const steps = [];
|
|
156
|
+
for (let top = 0; top < containerheight; top += viewportstep) {
|
|
157
|
+
const clamped = Math.min(top, Math.max(0, containerheight - viewportstep));
|
|
158
|
+
if (!steps.includes(clamped)) steps.push(clamped);
|
|
159
|
+
}
|
|
160
|
+
return steps;
|
|
161
|
+
}
|
|
162
|
+
function buildsheet(cells, layout) {
|
|
163
|
+
const columns = Math.max(1, Math.round(layout.columns));
|
|
164
|
+
const rows = Math.max(1, Math.ceil(cells.length / columns));
|
|
165
|
+
const placed = cells.map((cell, index) => {
|
|
166
|
+
const column = index % columns;
|
|
167
|
+
const row = Math.floor(index / columns);
|
|
168
|
+
const label = cell.label ?? "";
|
|
169
|
+
const caption = layout.label === "none" ? "" : layout.label === "index" ? `${index + 1}` : layout.label === "selector" ? cell.selector : label ? `${index + 1} \xB7 ${cell.selector} \xB7 ${label}` : `${index + 1} \xB7 ${cell.selector}`;
|
|
170
|
+
return { index, column, row, selector: cell.selector, label, caption };
|
|
171
|
+
});
|
|
172
|
+
return { columns, rows, cells: placed };
|
|
173
|
+
}
|
|
174
|
+
function capturepart(value) {
|
|
175
|
+
return value.replace(/[^a-z0-9-]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "capture";
|
|
176
|
+
}
|
|
177
|
+
function buildname(rule, parts, extension) {
|
|
178
|
+
const segments = [];
|
|
179
|
+
if (rule.run) segments.push(capturepart(parts.run));
|
|
180
|
+
if (rule.step) segments.push(capturepart(parts.step));
|
|
181
|
+
if (rule.sequence) segments.push(String(Math.max(0, Math.round(parts.sequence))));
|
|
182
|
+
if (rule.kind) segments.push(capturepart(parts.kind));
|
|
183
|
+
const safeextension = extension.replace(/^\.+/, "").toLowerCase() || "png";
|
|
184
|
+
return `${(segments.length > 0 ? segments : ["capture"]).join("-")}.${safeextension}`;
|
|
185
|
+
}
|
|
186
|
+
function annotationplanof(input) {
|
|
187
|
+
const inset = Math.min(24, Math.max(8, Math.round(Math.min(input.width, input.height) / 12)));
|
|
188
|
+
const plan = {
|
|
189
|
+
marker: { x: inset, y: inset, number: Math.max(1, Math.round(input.step)) },
|
|
190
|
+
footer: `${new Date(input.at).toISOString()} \xB7 ${input.url}`
|
|
191
|
+
};
|
|
192
|
+
if (input.rect !== void 0) {
|
|
193
|
+
const expansion = 2;
|
|
194
|
+
plan.outline = { x: Math.round(input.rect.x - expansion), y: Math.round(input.rect.y - expansion), width: Math.round(input.rect.width + expansion * 2), height: Math.round(input.rect.height + expansion * 2) };
|
|
195
|
+
}
|
|
196
|
+
return plan;
|
|
197
|
+
}
|
|
198
|
+
|
|
1
199
|
// memory.ts
|
|
2
200
|
var sessionmemory = class {
|
|
3
201
|
constructor(adapter) {
|
|
@@ -731,7 +929,46 @@ var sessionmemory = class {
|
|
|
731
929
|
async getmimefilters() {
|
|
732
930
|
return await this.adapter.get("mimefilters") ?? [];
|
|
733
931
|
}
|
|
932
|
+
/** Stores one capture record with its bytes and step linkage, replacing the previous record of that id; the user configured capture retention window expires the oldest bytes while the metadata always survives for the audit trail. */
|
|
933
|
+
async addcapture(record2) {
|
|
934
|
+
const records = await this.getcaptures();
|
|
935
|
+
const retention = (await this.getsettings())?.captureretention;
|
|
936
|
+
const combined = [record2, ...records.filter((item) => item.id !== record2.id)];
|
|
937
|
+
const stored = retention === void 0 ? combined : combined.map((item, index) => index < retention ? item : expirecapturebytes(item));
|
|
938
|
+
await this.adapter.set("captures", stored);
|
|
939
|
+
}
|
|
940
|
+
/** Returns every stored capture record with its metadata, newest first. */
|
|
941
|
+
async getcaptures() {
|
|
942
|
+
return await this.adapter.get("captures") ?? [];
|
|
943
|
+
}
|
|
944
|
+
/** Returns one capture record with its bytes by its id. */
|
|
945
|
+
async getcapture(id) {
|
|
946
|
+
return (await this.getcaptures()).find((item) => item.id === id);
|
|
947
|
+
}
|
|
948
|
+
/** Returns the capture records filtered by run, step and kind. */
|
|
949
|
+
async listcaptures(filter) {
|
|
950
|
+
const records = await this.getcaptures();
|
|
951
|
+
return records.filter((item) => (filter.runid === void 0 || item.runid === filter.runid) && (filter.stepid === void 0 || item.stepid === filter.stepid) && (filter.kind === void 0 || item.kind === filter.kind));
|
|
952
|
+
}
|
|
953
|
+
/** Records one before and after shotpair of the run with its action context. */
|
|
954
|
+
async addpair(pair) {
|
|
955
|
+
const records = await this.getpairs();
|
|
956
|
+
await this.adapter.set("capturepairs", [pair, ...records.filter((item) => item.id !== pair.id)]);
|
|
957
|
+
}
|
|
958
|
+
/** Returns the shotpairs of one run resolved through their before records, newest first; an absent run returns every pair. */
|
|
959
|
+
async getpairs(runid) {
|
|
960
|
+
const records = await this.adapter.get("capturepairs") ?? [];
|
|
961
|
+
if (runid === void 0) return records;
|
|
962
|
+
const runs = /* @__PURE__ */ new Map();
|
|
963
|
+
for (const capture of await this.getcaptures()) runs.set(capture.id, capture.runid);
|
|
964
|
+
return records.filter((item) => runs.get(item.beforeid) === runid);
|
|
965
|
+
}
|
|
734
966
|
};
|
|
967
|
+
function expirecapturebytes(record2) {
|
|
968
|
+
const { bytes, ...metadata } = record2;
|
|
969
|
+
void bytes;
|
|
970
|
+
return { ...metadata, bytesexpired: true };
|
|
971
|
+
}
|
|
735
972
|
function randomid() {
|
|
736
973
|
return crypto.randomUUID();
|
|
737
974
|
}
|
|
@@ -739,16 +976,17 @@ function randomid() {
|
|
|
739
976
|
// policy.ts
|
|
740
977
|
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts"]);
|
|
741
978
|
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction"]);
|
|
742
|
-
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures"]);
|
|
979
|
+
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"]);
|
|
743
980
|
var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
|
|
744
981
|
var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
|
|
745
|
-
var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor", "shiftclick", "typetime", "appendtext", "setvalue", "typeedit", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "expanddetails", "verifyvisible", "verifyenabled", "pierceshadow", "deriveselector", "fingerprintsection", "submitform", "retryform", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "scrapetable", "paginateextract"]);
|
|
982
|
+
var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor", "shiftclick", "typetime", "appendtext", "setvalue", "typeedit", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "expanddetails", "verifyvisible", "verifyenabled", "pierceshadow", "deriveselector", "fingerprintsection", "submitform", "retryform", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "scrapetable", "paginateextract", "shotelement"]);
|
|
746
983
|
var valueactions = /* @__PURE__ */ new Set(["presskey", "drag", "drop", "upload", "readattribute", "removeattribute", "waittext", "evaluate", "zoomset", "tabactivate", "tabclose", "tabreload", "windowclose", "windowresize", "tabcreate", "windowcreate", "downloadfile", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "chooseradio", "setslider", "setdate", "setcolor", "followlink", "setfragment", "handleauth", "navintent", "openclipboard", "checksafe", "reopentab", "spanav", "duplicatetab", "pintab", "mutetab", "movetab", "movetabwindow", "searchtabs", "badgetab", "attachmeta", "focuswindow", "maximizewindow", "minimizewindow", "restorewindow", "incognitowindow", "asksubmit", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "pausedownload", "resumedownload", "verifydownload", "writeclipboard", "quarantinedownload", "scanvirus"]);
|
|
747
984
|
var tabscommandactions = /* @__PURE__ */ new Set(["querytabs", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "watchtab", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "savelayout", "restorelayout", "findclones", "searchtabs", "badgetab", "attachmeta", "listaudio", "reopenrun", "snapshotsession"]);
|
|
748
985
|
var formactions = /* @__PURE__ */ new Set(["fillform", "filllabel", "fillplaceholder", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "submitform", "readerrors", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "handoffcaptcha", "fillcard", "fillcode", "consentpassword", "skiphoneypot", "detectlogin", "detecttemplate"]);
|
|
749
986
|
var datasetactions = /* @__PURE__ */ new Set(["scrapetable", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "importcsv", "looprows", "transformvalues", "deduperows", "paginateextract", "mergepages", "stamplerows", "previewgrid", "streamdisk", "resumeextract", "logprovenance"]);
|
|
750
987
|
var exportactions = /* @__PURE__ */ new Set(["exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk"]);
|
|
751
988
|
var filesactions = /* @__PURE__ */ new Set(["batchdownload", "pausedownload", "resumedownload", "verifydownload", "interceptmime", "exportnetlog", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "namecaptures", "cleanupartifacts"]);
|
|
989
|
+
var captureactions = /* @__PURE__ */ new Set(["shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"]);
|
|
752
990
|
var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
|
|
753
991
|
var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
|
|
754
992
|
var groupcolors = ["grey", "blue", "red", "yellow", "green", "pink", "purple", "cyan", "orange"];
|
|
@@ -805,6 +1043,83 @@ function isexportkind(kind) {
|
|
|
805
1043
|
function isfileskind(kind) {
|
|
806
1044
|
return filesactions.has(kind);
|
|
807
1045
|
}
|
|
1046
|
+
function iscapturekind(kind) {
|
|
1047
|
+
return captureactions.has(kind);
|
|
1048
|
+
}
|
|
1049
|
+
function capturegate(session, tabid, origin, now) {
|
|
1050
|
+
if (!session || session.stoppedat) return { allowed: false, reason: "No active browser session exists for the capture." };
|
|
1051
|
+
if (session.expiresat <= now) return { allowed: false, reason: "The browser session has expired and cannot capture." };
|
|
1052
|
+
if (session.pausedat) return { allowed: false, reason: "The browser session is paused and cannot capture." };
|
|
1053
|
+
if (session.tabid !== tabid) return { allowed: false, reason: `The capture needs the active tab grant of session tab ${session.tabid} and refuses tab ${tabid}.` };
|
|
1054
|
+
if (!origingranted(session, origin)) return { allowed: false, reason: `The capture of ${origin} needs the session origin grants first.` };
|
|
1055
|
+
return { allowed: true };
|
|
1056
|
+
}
|
|
1057
|
+
function validatecaptureoptions(value) {
|
|
1058
|
+
if (value === void 0) return { allowed: true };
|
|
1059
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "The reviewed capture options must be an object in options.capture." };
|
|
1060
|
+
const options = value;
|
|
1061
|
+
if (options.format !== void 0 && options.format !== "png" && options.format !== "jpeg" && options.format !== "webp") return { allowed: false, reason: "The reviewed capture format must be png, jpeg or webp." };
|
|
1062
|
+
if (options.quality !== void 0 && (typeof options.quality !== "number" || !Number.isFinite(options.quality) || options.quality < 0 || options.quality > 100)) return { allowed: false, reason: "The reviewed capture quality must stay between zero and one hundred; any value in that range is the user choice with no code cap." };
|
|
1063
|
+
if (options.pixelratio !== void 0 && (typeof options.pixelratio !== "number" || !Number.isFinite(options.pixelratio) || options.pixelratio < 1)) return { allowed: false, reason: "The reviewed pixel ratio starts at one and climbs to any user configured ceiling with no code ceiling." };
|
|
1064
|
+
if (options.annotate !== void 0 && typeof options.annotate !== "boolean") return { allowed: false, reason: "The reviewed capture annotation flag must be a boolean." };
|
|
1065
|
+
if (options.exporttarget !== void 0 && options.exporttarget !== "memory" && options.exporttarget !== "download" && options.exporttarget !== "clipboard") return { allowed: false, reason: "The reviewed capture export target must be memory, download or clipboard." };
|
|
1066
|
+
return { allowed: true };
|
|
1067
|
+
}
|
|
1068
|
+
function validateregionrect(value) {
|
|
1069
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "A reviewed regionrect with x, y, width and height in css pixels is required in options." };
|
|
1070
|
+
const rect = value;
|
|
1071
|
+
for (const field of ["x", "y", "width", "height"]) {
|
|
1072
|
+
if (typeof rect[field] !== "number" || !Number.isFinite(rect[field])) return { allowed: false, reason: `The reviewed regionrect needs a numeric ${field} in css pixels.` };
|
|
1073
|
+
}
|
|
1074
|
+
if (rect.x < 0 || rect.y < 0) return { allowed: false, reason: "The reviewed regionrect refuses negative coordinates." };
|
|
1075
|
+
if (rect.width <= 0 || rect.height <= 0) return { allowed: false, reason: "The reviewed regionrect needs positive width and height values." };
|
|
1076
|
+
return { allowed: true };
|
|
1077
|
+
}
|
|
1078
|
+
function validatecapturenaming(value) {
|
|
1079
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "A reviewed capturenaming rule with run, step, sequence and kind flags is required." };
|
|
1080
|
+
const rule = value;
|
|
1081
|
+
const segments = ["run", "step", "sequence", "kind"];
|
|
1082
|
+
for (const key of Object.keys(rule)) {
|
|
1083
|
+
if (!segments.includes(key)) return { allowed: false, reason: `The reviewed capturenaming rule refuses the unknown ${key} segment; only run, step, sequence and kind participate.` };
|
|
1084
|
+
}
|
|
1085
|
+
for (const segment of segments) {
|
|
1086
|
+
if (rule[segment] !== void 0 && typeof rule[segment] !== "boolean") return { allowed: false, reason: `The reviewed capturenaming ${segment} flag must be a boolean.` };
|
|
1087
|
+
}
|
|
1088
|
+
if (!segments.some((segment) => rule[segment] === true)) return { allowed: false, reason: "The reviewed capturenaming rule needs at least one enabled segment of run, step, sequence and kind." };
|
|
1089
|
+
return { allowed: true };
|
|
1090
|
+
}
|
|
1091
|
+
function validatecapturegrammar(step, options) {
|
|
1092
|
+
const kind = step.kind;
|
|
1093
|
+
const optioncheck = validatecaptureoptions(options.capture);
|
|
1094
|
+
if (!optioncheck.allowed) return optioncheck;
|
|
1095
|
+
if (options.settle !== void 0 && (typeof options.settle !== "number" || !Number.isFinite(options.settle) || options.settle < 0)) return { allowed: false, reason: "The reviewed capture settle window must be zero or a positive number of milliseconds." };
|
|
1096
|
+
if (options.overlap !== void 0 && (typeof options.overlap !== "number" || !Number.isInteger(options.overlap) || options.overlap < 0)) return { allowed: false, reason: "The reviewed stitch overlap must be zero or a positive number of rows." };
|
|
1097
|
+
if (options.wait !== void 0 && (typeof options.wait !== "number" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: "The reviewed capture wait window must be zero or a positive number of milliseconds." };
|
|
1098
|
+
if (options.naming !== void 0) {
|
|
1099
|
+
const namingcheck = validatecapturenaming(options.naming);
|
|
1100
|
+
if (!namingcheck.allowed) return namingcheck;
|
|
1101
|
+
}
|
|
1102
|
+
if (kind === "shotregion") {
|
|
1103
|
+
const rectcheck = validateregionrect(options.regionrect);
|
|
1104
|
+
if (!rectcheck.allowed) return rectcheck;
|
|
1105
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Every reviewed regionrect needs the explicit reviewed flag before shotregion runs." };
|
|
1106
|
+
if (options.container !== void 0 && !isnonempty(options.container)) return { allowed: false, reason: "The reviewed scrollable container selector must be a non-empty string." };
|
|
1107
|
+
if (options.steps !== void 0 && (typeof options.steps !== "number" || !Number.isInteger(options.steps) || options.steps < 1)) return { allowed: false, reason: "The reviewed container scroll steps must be a positive integer with no code ceiling." };
|
|
1108
|
+
}
|
|
1109
|
+
if (kind === "contactsheet") {
|
|
1110
|
+
const elements = options.elements;
|
|
1111
|
+
if (!Array.isArray(elements) || elements.length === 0 || !elements.every((item) => isnonempty(item))) return { allowed: false, reason: "A reviewed non-empty list of element selectors is required in options for the contact sheet; the cell count stays the user choice." };
|
|
1112
|
+
const layout = options.sheet;
|
|
1113
|
+
if (layout !== void 0) {
|
|
1114
|
+
if (!layout || typeof layout !== "object" || Array.isArray(layout)) return { allowed: false, reason: "The reviewed sheetlayout must be an object with cellsize, columns and label." };
|
|
1115
|
+
const sheet = layout;
|
|
1116
|
+
if (typeof sheet.cellsize !== "number" || !Number.isFinite(sheet.cellsize) || sheet.cellsize <= 0) return { allowed: false, reason: "The reviewed contact sheet cell size must be a positive number of pixels." };
|
|
1117
|
+
if (typeof sheet.columns !== "number" || !Number.isInteger(sheet.columns) || sheet.columns < 1) return { allowed: false, reason: "The reviewed contact sheet column count must be a positive integer with no code ceiling." };
|
|
1118
|
+
if (sheet.label !== void 0 && sheet.label !== "none" && sheet.label !== "index" && sheet.label !== "selector" && sheet.label !== "both") return { allowed: false, reason: "The reviewed contact sheet label style must be none, index, selector or both." };
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
return { allowed: true };
|
|
1122
|
+
}
|
|
808
1123
|
function exportgranted(session, origin) {
|
|
809
1124
|
if (!origingranted(session, origin)) return { allowed: false, reason: `The export of extracted data from ${origin} needs the session origin grants before it leaves local memory.` };
|
|
810
1125
|
return { allowed: true };
|
|
@@ -1590,6 +1905,10 @@ function validatestep(step, origin) {
|
|
|
1590
1905
|
const filescheck = validatefilesgrammar(step, options);
|
|
1591
1906
|
if (!filescheck.allowed) return filescheck;
|
|
1592
1907
|
}
|
|
1908
|
+
if (iscapturekind(step.kind)) {
|
|
1909
|
+
const capturecheck = validatecapturegrammar(step, options);
|
|
1910
|
+
if (!capturecheck.allowed) return capturecheck;
|
|
1911
|
+
}
|
|
1593
1912
|
if (step.kind === "tabcreate") {
|
|
1594
1913
|
if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
|
|
1595
1914
|
if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed target window id must be a non-negative integer." };
|
|
@@ -1649,6 +1968,18 @@ function canexecute(input) {
|
|
|
1649
1968
|
if (!clipgate.allowed) return clipgate;
|
|
1650
1969
|
}
|
|
1651
1970
|
if (input.step.kind === "interceptmime" && !origingranted(input.session, input.origin)) return { allowed: false, reason: "The download interception is outside the session origin grants." };
|
|
1971
|
+
if (iscapturekind(input.step.kind)) {
|
|
1972
|
+
const capturegatecheck = capturegate(input.session, input.tabid, input.origin, now);
|
|
1973
|
+
if (!capturegatecheck.allowed) return capturegatecheck;
|
|
1974
|
+
let captureoptions = {};
|
|
1975
|
+
try {
|
|
1976
|
+
captureoptions = parseoptions(input.step);
|
|
1977
|
+
} catch {
|
|
1978
|
+
captureoptions = {};
|
|
1979
|
+
}
|
|
1980
|
+
const target = captureoptions.capture?.exporttarget;
|
|
1981
|
+
if (target !== void 0 && target !== "memory" && target !== "download" && target !== "clipboard") return { allowed: false, reason: "The capture export target must be memory, download or clipboard." };
|
|
1982
|
+
}
|
|
1652
1983
|
if (input.step.kind === "openlink" || input.step.kind === "openprivate" || input.step.kind === "batchopen" || input.step.kind === "prefetch" || input.step.kind === "deeplink" || input.step.kind === "reopentab") {
|
|
1653
1984
|
let options = {};
|
|
1654
1985
|
try {
|
|
@@ -1670,7 +2001,7 @@ function canexecute(input) {
|
|
|
1670
2001
|
}
|
|
1671
2002
|
|
|
1672
2003
|
// version.ts
|
|
1673
|
-
var packageversion = "1.1.
|
|
2004
|
+
var packageversion = "1.1.40";
|
|
1674
2005
|
|
|
1675
2006
|
// types.ts
|
|
1676
2007
|
var protocolversion = packageversion;
|
|
@@ -1734,7 +2065,7 @@ function requestbody(input) {
|
|
|
1734
2065
|
return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
|
|
1735
2066
|
}
|
|
1736
2067
|
function outcomeresponse(input) {
|
|
1737
|
-
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {} });
|
|
2068
|
+
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {} });
|
|
1738
2069
|
}
|
|
1739
2070
|
function mapresponse(input) {
|
|
1740
2071
|
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
|
|
@@ -1811,8 +2142,28 @@ function netlogreport(input) {
|
|
|
1811
2142
|
function quarantinereport(input) {
|
|
1812
2143
|
return { version: protocolversion, entries: input.entries };
|
|
1813
2144
|
}
|
|
2145
|
+
function capturereport(input) {
|
|
2146
|
+
return { version: protocolversion, records: input.records, pairs: input.pairs };
|
|
2147
|
+
}
|
|
1814
2148
|
export {
|
|
2149
|
+
annotationplanof,
|
|
2150
|
+
blendrows,
|
|
2151
|
+
buildname,
|
|
2152
|
+
buildsheet,
|
|
2153
|
+
buildstitchplan,
|
|
1815
2154
|
canexecute,
|
|
2155
|
+
captureelement,
|
|
2156
|
+
captureformats,
|
|
2157
|
+
capturekinds,
|
|
2158
|
+
captureoptionsof,
|
|
2159
|
+
captureregion,
|
|
2160
|
+
capturereport,
|
|
2161
|
+
capturestates,
|
|
2162
|
+
capturestitched,
|
|
2163
|
+
capturetargets,
|
|
2164
|
+
capturevisible,
|
|
2165
|
+
croprect,
|
|
2166
|
+
crossesviewport,
|
|
1816
2167
|
datasetresponse,
|
|
1817
2168
|
actionrisk as deriveactionrisk,
|
|
1818
2169
|
diffresponse,
|
|
@@ -1820,6 +2171,7 @@ export {
|
|
|
1820
2171
|
errorreportresponse,
|
|
1821
2172
|
eventresponse,
|
|
1822
2173
|
extractionreport,
|
|
2174
|
+
fixedheadermatch,
|
|
1823
2175
|
formreportresponse,
|
|
1824
2176
|
generatedvalueallowed,
|
|
1825
2177
|
heldkeysreport,
|
|
@@ -1834,6 +2186,7 @@ export {
|
|
|
1834
2186
|
observationmodeof,
|
|
1835
2187
|
observationresponse,
|
|
1836
2188
|
outcomeresponse,
|
|
2189
|
+
pairstates,
|
|
1837
2190
|
parseproposal,
|
|
1838
2191
|
passwordconsentgranted,
|
|
1839
2192
|
profilegrantgranted,
|
|
@@ -1841,9 +2194,12 @@ export {
|
|
|
1841
2194
|
provenancereport,
|
|
1842
2195
|
quarantinereport,
|
|
1843
2196
|
randomid,
|
|
2197
|
+
regionsteps,
|
|
1844
2198
|
requestbody,
|
|
1845
2199
|
resolutionverdict,
|
|
1846
2200
|
safetyresponse,
|
|
2201
|
+
scaledrect,
|
|
2202
|
+
seamweights,
|
|
1847
2203
|
selectorresponse,
|
|
1848
2204
|
sessionmemory,
|
|
1849
2205
|
signalsreport,
|