imperium-crawl 1.5.2 → 2.0.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 +370 -257
- package/dist/constants.d.ts +2 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/network/interceptor.d.ts +19 -0
- package/dist/network/interceptor.d.ts.map +1 -0
- package/dist/network/interceptor.js +82 -0
- package/dist/network/interceptor.js.map +1 -0
- package/dist/network/types.d.ts +27 -0
- package/dist/network/types.d.ts.map +1 -0
- package/dist/network/types.js +2 -0
- package/dist/network/types.js.map +1 -0
- package/dist/security/action-policy.d.ts +26 -0
- package/dist/security/action-policy.d.ts.map +1 -0
- package/dist/security/action-policy.js +136 -0
- package/dist/security/action-policy.js.map +1 -0
- package/dist/security/auth-vault.d.ts +49 -0
- package/dist/security/auth-vault.d.ts.map +1 -0
- package/dist/security/auth-vault.js +133 -0
- package/dist/security/auth-vault.js.map +1 -0
- package/dist/security/domain-filter.d.ts +19 -0
- package/dist/security/domain-filter.d.ts.map +1 -0
- package/dist/security/domain-filter.js +114 -0
- package/dist/security/domain-filter.js.map +1 -0
- package/dist/security/types.d.ts +19 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/security/types.js +2 -0
- package/dist/security/types.js.map +1 -0
- package/dist/sessions/encryption.d.ts +37 -0
- package/dist/sessions/encryption.d.ts.map +1 -0
- package/dist/sessions/encryption.js +108 -0
- package/dist/sessions/encryption.js.map +1 -0
- package/dist/sessions/index.d.ts +1 -0
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +1 -0
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/manager.d.ts +3 -0
- package/dist/sessions/manager.d.ts.map +1 -1
- package/dist/sessions/manager.js +28 -2
- package/dist/sessions/manager.js.map +1 -1
- package/dist/snapshot/annotator.d.ts +21 -0
- package/dist/snapshot/annotator.d.ts.map +1 -0
- package/dist/snapshot/annotator.js +152 -0
- package/dist/snapshot/annotator.js.map +1 -0
- package/dist/snapshot/boundary.d.ts +7 -0
- package/dist/snapshot/boundary.d.ts.map +1 -0
- package/dist/snapshot/boundary.js +12 -0
- package/dist/snapshot/boundary.js.map +1 -0
- package/dist/snapshot/differ.d.ts +40 -0
- package/dist/snapshot/differ.d.ts.map +1 -0
- package/dist/snapshot/differ.js +194 -0
- package/dist/snapshot/differ.js.map +1 -0
- package/dist/snapshot/extractor.d.ts +27 -0
- package/dist/snapshot/extractor.d.ts.map +1 -0
- package/dist/snapshot/extractor.js +265 -0
- package/dist/snapshot/extractor.js.map +1 -0
- package/dist/snapshot/index.d.ts +8 -0
- package/dist/snapshot/index.d.ts.map +1 -0
- package/dist/snapshot/index.js +6 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/snapshot/store.d.ts +28 -0
- package/dist/snapshot/store.d.ts.map +1 -0
- package/dist/snapshot/store.js +65 -0
- package/dist/snapshot/store.js.map +1 -0
- package/dist/snapshot/types.d.ts +42 -0
- package/dist/snapshot/types.d.ts.map +1 -0
- package/dist/snapshot/types.js +2 -0
- package/dist/snapshot/types.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/interact.d.ts +194 -5
- package/dist/tools/interact.d.ts.map +1 -1
- package/dist/tools/interact.js +355 -20
- package/dist/tools/interact.js.map +1 -1
- package/dist/tools/snapshot.d.ts +53 -0
- package/dist/tools/snapshot.d.ts.map +1 -0
- package/dist/tools/snapshot.js +160 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dual diff system — text (Myers) + image (pixel comparison).
|
|
3
|
+
*
|
|
4
|
+
* Text diff: Line-level Myers algorithm on snapshot strings.
|
|
5
|
+
* Image diff: Canvas-based pixel comparison in an isolated browser page.
|
|
6
|
+
*/
|
|
7
|
+
type BrowserContext = import("rebrowser-playwright").BrowserContext;
|
|
8
|
+
export interface TextDiffResult {
|
|
9
|
+
diff: string;
|
|
10
|
+
additions: number;
|
|
11
|
+
removals: number;
|
|
12
|
+
unchanged: number;
|
|
13
|
+
changed: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Myers diff algorithm (line-level).
|
|
17
|
+
* Returns unified diff format with +/- prefixes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function diffSnapshots(before: string, after: string): TextDiffResult;
|
|
20
|
+
export interface ImageDiffResult {
|
|
21
|
+
mismatchPercentage: number;
|
|
22
|
+
match: boolean;
|
|
23
|
+
diffImage: Buffer;
|
|
24
|
+
totalPixels: number;
|
|
25
|
+
changedPixels: number;
|
|
26
|
+
}
|
|
27
|
+
export interface ImageDiffOptions {
|
|
28
|
+
/** Color distance threshold (0-255). Default: 30 */
|
|
29
|
+
threshold?: number;
|
|
30
|
+
/** Match if mismatch is below this % (default: 1.0) */
|
|
31
|
+
matchThreshold?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Pixel-level comparison of two screenshots.
|
|
35
|
+
* Opens an isolated page, loads images via intercepted routes,
|
|
36
|
+
* computes per-pixel color distance, generates diff PNG.
|
|
37
|
+
*/
|
|
38
|
+
export declare function diffScreenshots(context: BrowserContext, baseline: Buffer, current: Buffer, options?: ImageDiffOptions): Promise<ImageDiffResult>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=differ.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"differ.d.ts","sourceRoot":"","sources":["../../src/snapshot/differ.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,KAAK,cAAc,GAAG,OAAO,sBAAsB,EAAE,cAAc,CAAC;AAIpE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAOD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAwF3E;AAID,MAAM,WAAW,eAAe;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAkH1B"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dual diff system — text (Myers) + image (pixel comparison).
|
|
3
|
+
*
|
|
4
|
+
* Text diff: Line-level Myers algorithm on snapshot strings.
|
|
5
|
+
* Image diff: Canvas-based pixel comparison in an isolated browser page.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Myers diff algorithm (line-level).
|
|
9
|
+
* Returns unified diff format with +/- prefixes.
|
|
10
|
+
*/
|
|
11
|
+
export function diffSnapshots(before, after) {
|
|
12
|
+
const beforeLines = before.split("\n");
|
|
13
|
+
const afterLines = after.split("\n");
|
|
14
|
+
const n = beforeLines.length;
|
|
15
|
+
const m = afterLines.length;
|
|
16
|
+
const max = n + m;
|
|
17
|
+
// Shortcut: identical
|
|
18
|
+
if (before === after) {
|
|
19
|
+
return {
|
|
20
|
+
diff: beforeLines.map((l) => ` ${l}`).join("\n"),
|
|
21
|
+
additions: 0,
|
|
22
|
+
removals: 0,
|
|
23
|
+
unchanged: n,
|
|
24
|
+
changed: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Myers shortest edit script
|
|
28
|
+
const v = { 1: { x: 0, history: [] } };
|
|
29
|
+
for (let d = 0; d <= max; d++) {
|
|
30
|
+
for (let k = -d; k <= d; k += 2) {
|
|
31
|
+
let path;
|
|
32
|
+
// Choose path: go down (insert) or go right (delete)
|
|
33
|
+
if (k === -d || (k !== d && v[k - 1].x < v[k + 1].x)) {
|
|
34
|
+
// Move down: insert from after
|
|
35
|
+
const prev = v[k + 1];
|
|
36
|
+
path = {
|
|
37
|
+
x: prev.x,
|
|
38
|
+
history: [...prev.history, { type: "add", line: afterLines[prev.x - k - 1] ?? "" }],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// Move right: delete from before
|
|
43
|
+
const prev = v[k - 1];
|
|
44
|
+
path = {
|
|
45
|
+
x: prev.x + 1,
|
|
46
|
+
history: [...prev.history, { type: "remove", line: beforeLines[prev.x] ?? "" }],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Follow diagonal (equal lines)
|
|
50
|
+
while (path.x < n && path.x - k < m && beforeLines[path.x] === afterLines[path.x - k]) {
|
|
51
|
+
path.history = [...path.history, { type: "equal", line: beforeLines[path.x] }];
|
|
52
|
+
path.x++;
|
|
53
|
+
}
|
|
54
|
+
// Check if we reached the end
|
|
55
|
+
if (path.x >= n && path.x - k >= m) {
|
|
56
|
+
let additions = 0;
|
|
57
|
+
let removals = 0;
|
|
58
|
+
let unchanged = 0;
|
|
59
|
+
const lines = [];
|
|
60
|
+
for (const entry of path.history) {
|
|
61
|
+
switch (entry.type) {
|
|
62
|
+
case "equal":
|
|
63
|
+
lines.push(` ${entry.line}`);
|
|
64
|
+
unchanged++;
|
|
65
|
+
break;
|
|
66
|
+
case "add":
|
|
67
|
+
lines.push(`+ ${entry.line}`);
|
|
68
|
+
additions++;
|
|
69
|
+
break;
|
|
70
|
+
case "remove":
|
|
71
|
+
lines.push(`- ${entry.line}`);
|
|
72
|
+
removals++;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
diff: lines.join("\n"),
|
|
78
|
+
additions,
|
|
79
|
+
removals,
|
|
80
|
+
unchanged,
|
|
81
|
+
changed: additions > 0 || removals > 0,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
v[k] = path;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Should never reach here for valid inputs
|
|
88
|
+
return { diff: "", additions: 0, removals: 0, unchanged: 0, changed: false };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Pixel-level comparison of two screenshots.
|
|
92
|
+
* Opens an isolated page, loads images via intercepted routes,
|
|
93
|
+
* computes per-pixel color distance, generates diff PNG.
|
|
94
|
+
*/
|
|
95
|
+
export async function diffScreenshots(context, baseline, current, options = {}) {
|
|
96
|
+
const { threshold = 30, matchThreshold = 1.0 } = options;
|
|
97
|
+
const page = await context.newPage();
|
|
98
|
+
try {
|
|
99
|
+
// Intercept image routes to serve our buffers
|
|
100
|
+
await page.route("**/baseline.png", (route) => {
|
|
101
|
+
route.fulfill({
|
|
102
|
+
status: 200,
|
|
103
|
+
contentType: "image/png",
|
|
104
|
+
body: baseline,
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
await page.route("**/current.png", (route) => {
|
|
108
|
+
route.fulfill({
|
|
109
|
+
status: 200,
|
|
110
|
+
contentType: "image/png",
|
|
111
|
+
body: current,
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
// Canvas-based pixel diff in browser context
|
|
115
|
+
const result = await page.evaluate(async (thresh) => {
|
|
116
|
+
// Load images
|
|
117
|
+
const loadImage = (src) => new Promise((resolve, reject) => {
|
|
118
|
+
const img = new Image();
|
|
119
|
+
img.onload = () => resolve(img);
|
|
120
|
+
img.onerror = reject;
|
|
121
|
+
img.src = src;
|
|
122
|
+
});
|
|
123
|
+
const [img1, img2] = await Promise.all([
|
|
124
|
+
loadImage("/baseline.png"),
|
|
125
|
+
loadImage("/current.png"),
|
|
126
|
+
]);
|
|
127
|
+
const width = Math.max(img1.width, img2.width);
|
|
128
|
+
const height = Math.max(img1.height, img2.height);
|
|
129
|
+
// Draw images to canvases
|
|
130
|
+
const canvas1 = document.createElement("canvas");
|
|
131
|
+
canvas1.width = width;
|
|
132
|
+
canvas1.height = height;
|
|
133
|
+
canvas1.getContext("2d").drawImage(img1, 0, 0);
|
|
134
|
+
const canvas2 = document.createElement("canvas");
|
|
135
|
+
canvas2.width = width;
|
|
136
|
+
canvas2.height = height;
|
|
137
|
+
canvas2.getContext("2d").drawImage(img2, 0, 0);
|
|
138
|
+
// Diff canvas
|
|
139
|
+
const diffCanvas = document.createElement("canvas");
|
|
140
|
+
diffCanvas.width = width;
|
|
141
|
+
diffCanvas.height = height;
|
|
142
|
+
const diffCtx = diffCanvas.getContext("2d");
|
|
143
|
+
const data1 = canvas1.getContext("2d").getImageData(0, 0, width, height).data;
|
|
144
|
+
const data2 = canvas2.getContext("2d").getImageData(0, 0, width, height).data;
|
|
145
|
+
const diffData = diffCtx.createImageData(width, height);
|
|
146
|
+
let changed = 0;
|
|
147
|
+
const totalPixels = width * height;
|
|
148
|
+
for (let i = 0; i < data1.length; i += 4) {
|
|
149
|
+
const dr = Math.abs(data1[i] - data2[i]);
|
|
150
|
+
const dg = Math.abs(data1[i + 1] - data2[i + 1]);
|
|
151
|
+
const db = Math.abs(data1[i + 2] - data2[i + 2]);
|
|
152
|
+
const dist = Math.sqrt(dr * dr + dg * dg + db * db);
|
|
153
|
+
if (dist > thresh) {
|
|
154
|
+
// Highlight difference in red
|
|
155
|
+
diffData.data[i] = 255;
|
|
156
|
+
diffData.data[i + 1] = 0;
|
|
157
|
+
diffData.data[i + 2] = 0;
|
|
158
|
+
diffData.data[i + 3] = 200;
|
|
159
|
+
changed++;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// Darken unchanged pixels
|
|
163
|
+
diffData.data[i] = Math.floor(data2[i] * 0.3);
|
|
164
|
+
diffData.data[i + 1] = Math.floor(data2[i + 1] * 0.3);
|
|
165
|
+
diffData.data[i + 2] = Math.floor(data2[i + 2] * 0.3);
|
|
166
|
+
diffData.data[i + 3] = 255;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
diffCtx.putImageData(diffData, 0, 0);
|
|
170
|
+
// Export as data URL
|
|
171
|
+
const dataUrl = diffCanvas.toDataURL("image/png");
|
|
172
|
+
return {
|
|
173
|
+
totalPixels,
|
|
174
|
+
changedPixels: changed,
|
|
175
|
+
mismatchPercentage: (changed / totalPixels) * 100,
|
|
176
|
+
dataUrl,
|
|
177
|
+
};
|
|
178
|
+
}, threshold);
|
|
179
|
+
// Convert data URL to buffer
|
|
180
|
+
const base64Data = result.dataUrl.split(",")[1];
|
|
181
|
+
const diffImage = Buffer.from(base64Data, "base64");
|
|
182
|
+
return {
|
|
183
|
+
mismatchPercentage: result.mismatchPercentage,
|
|
184
|
+
match: result.mismatchPercentage <= matchThreshold,
|
|
185
|
+
diffImage,
|
|
186
|
+
totalPixels: result.totalPixels,
|
|
187
|
+
changedPixels: result.changedPixels,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
await page.close();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=differ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"differ.js","sourceRoot":"","sources":["../../src/snapshot/differ.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot Extractor — Core engine for ARIA-based page snapshots.
|
|
3
|
+
*
|
|
4
|
+
* Uses Playwright's locator.ariaSnapshot() for the ARIA tree,
|
|
5
|
+
* then post-processes to add [ref=eN] tags for interactive elements.
|
|
6
|
+
* Optionally detects cursor-interactive elements without ARIA roles.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by agent-browser's approach but with:
|
|
9
|
+
* - Per-snapshot ref counter (thread-safe, no global state)
|
|
10
|
+
* - Hybrid cursor detection
|
|
11
|
+
* - Semantic locators (getByRole) for robust element targeting
|
|
12
|
+
*/
|
|
13
|
+
import type { EnhancedSnapshot, SnapshotOptions } from "./types.js";
|
|
14
|
+
type Page = import("rebrowser-playwright").Page;
|
|
15
|
+
/**
|
|
16
|
+
* Generate an enhanced ARIA snapshot with ref annotations.
|
|
17
|
+
*
|
|
18
|
+
* Flow:
|
|
19
|
+
* 1. Get ARIA tree from Playwright's ariaSnapshot()
|
|
20
|
+
* 2. Parse each line, identify roles
|
|
21
|
+
* 3. Two-pass ref assignment (count first for dedup, then assign)
|
|
22
|
+
* 4. Optionally detect cursor-interactive elements
|
|
23
|
+
* 5. Build RefMap and annotated tree string
|
|
24
|
+
*/
|
|
25
|
+
export declare function getEnhancedSnapshot(page: Page, options?: SnapshotOptions): Promise<EnhancedSnapshot>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/snapshot/extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAU,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5E,KAAK,IAAI,GAAG,OAAO,sBAAsB,EAAE,IAAI,CAAC;AAkLhD;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAyH3B"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot Extractor — Core engine for ARIA-based page snapshots.
|
|
3
|
+
*
|
|
4
|
+
* Uses Playwright's locator.ariaSnapshot() for the ARIA tree,
|
|
5
|
+
* then post-processes to add [ref=eN] tags for interactive elements.
|
|
6
|
+
* Optionally detects cursor-interactive elements without ARIA roles.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by agent-browser's approach but with:
|
|
9
|
+
* - Per-snapshot ref counter (thread-safe, no global state)
|
|
10
|
+
* - Hybrid cursor detection
|
|
11
|
+
* - Semantic locators (getByRole) for robust element targeting
|
|
12
|
+
*/
|
|
13
|
+
// ── Role classification ──
|
|
14
|
+
const INTERACTIVE_ROLES = new Set([
|
|
15
|
+
"button", "link", "textbox", "checkbox", "radio",
|
|
16
|
+
"combobox", "listbox", "menuitem", "option", "searchbox",
|
|
17
|
+
"slider", "spinbutton", "switch", "tab", "treeitem",
|
|
18
|
+
]);
|
|
19
|
+
const CONTENT_ROLES = new Set([
|
|
20
|
+
"heading", "cell", "article", "region", "navigation",
|
|
21
|
+
"img", "figure", "blockquote", "code",
|
|
22
|
+
]);
|
|
23
|
+
const STRUCTURAL_ROLES = new Set([
|
|
24
|
+
"generic", "group", "list", "table", "row", "rowgroup",
|
|
25
|
+
"columnheader", "rowheader", "presentation", "none",
|
|
26
|
+
"separator", "toolbar", "banner", "contentinfo", "main",
|
|
27
|
+
"complementary", "form",
|
|
28
|
+
]);
|
|
29
|
+
/**
|
|
30
|
+
* Parse a single line from Playwright's ariaSnapshot output.
|
|
31
|
+
* Format: " - role \"name\" [attributes]" or " - role \"name\":"
|
|
32
|
+
* Also handles: " - text: content here"
|
|
33
|
+
*/
|
|
34
|
+
function parseLine(line) {
|
|
35
|
+
// Count leading spaces for indentation
|
|
36
|
+
const stripped = line.replace(/^\s*/, "");
|
|
37
|
+
const indent = line.length - stripped.length;
|
|
38
|
+
// Must start with "- "
|
|
39
|
+
if (!stripped.startsWith("- "))
|
|
40
|
+
return null;
|
|
41
|
+
const content = stripped.slice(2);
|
|
42
|
+
// Match: role "name" or role "name": or just role:
|
|
43
|
+
const roleNameMatch = content.match(/^(\w+)\s+"([^"]*)"(.*)$/);
|
|
44
|
+
if (roleNameMatch) {
|
|
45
|
+
return {
|
|
46
|
+
indent,
|
|
47
|
+
role: roleNameMatch[1],
|
|
48
|
+
name: roleNameMatch[2],
|
|
49
|
+
rawLine: line,
|
|
50
|
+
attributes: roleNameMatch[3].trim(),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Match: role (no name) — e.g. "- list:" or "- generic"
|
|
54
|
+
const roleOnlyMatch = content.match(/^(\w+):?\s*$/);
|
|
55
|
+
if (roleOnlyMatch) {
|
|
56
|
+
return {
|
|
57
|
+
indent,
|
|
58
|
+
role: roleOnlyMatch[1],
|
|
59
|
+
name: "",
|
|
60
|
+
rawLine: line,
|
|
61
|
+
attributes: "",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Text node: "- text: some content"
|
|
65
|
+
if (content.startsWith("text:")) {
|
|
66
|
+
return {
|
|
67
|
+
indent,
|
|
68
|
+
role: "text",
|
|
69
|
+
name: content.slice(5).trim(),
|
|
70
|
+
rawLine: line,
|
|
71
|
+
attributes: "",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// Plain text line (e.g. "- Some text content")
|
|
75
|
+
return {
|
|
76
|
+
indent,
|
|
77
|
+
role: "text",
|
|
78
|
+
name: content.replace(/:$/, "").trim(),
|
|
79
|
+
rawLine: line,
|
|
80
|
+
attributes: "",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ── Role+Name dedup tracker ──
|
|
84
|
+
class RoleNameTracker {
|
|
85
|
+
counts = new Map();
|
|
86
|
+
assigned = new Map();
|
|
87
|
+
/** First pass: count occurrences */
|
|
88
|
+
count(role, name) {
|
|
89
|
+
const key = `${role}:::${name}`;
|
|
90
|
+
this.counts.set(key, (this.counts.get(key) ?? 0) + 1);
|
|
91
|
+
}
|
|
92
|
+
/** Second pass: get nth index (only if duplicates exist) */
|
|
93
|
+
getNth(role, name) {
|
|
94
|
+
const key = `${role}:::${name}`;
|
|
95
|
+
const total = this.counts.get(key) ?? 1;
|
|
96
|
+
if (total <= 1)
|
|
97
|
+
return undefined;
|
|
98
|
+
const idx = this.assigned.get(key) ?? 0;
|
|
99
|
+
this.assigned.set(key, idx + 1);
|
|
100
|
+
return idx;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// ── Selector builder ──
|
|
104
|
+
function buildSelector(role, name, nth) {
|
|
105
|
+
const nameOpt = name ? `, { name: '${name.replace(/'/g, "\\'")}', exact: true }` : "";
|
|
106
|
+
const base = `getByRole('${role}'${nameOpt})`;
|
|
107
|
+
return nth !== undefined ? `${base}.nth(${nth})` : base;
|
|
108
|
+
}
|
|
109
|
+
async function findCursorInteractiveElements(page, scopeSelector) {
|
|
110
|
+
return page.evaluate((scope) => {
|
|
111
|
+
const root = scope
|
|
112
|
+
? document.querySelector(scope) ?? document.body
|
|
113
|
+
: document.body;
|
|
114
|
+
const results = [];
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
|
117
|
+
let node = walker.nextNode();
|
|
118
|
+
while (node) {
|
|
119
|
+
if (!seen.has(node)) {
|
|
120
|
+
const style = getComputedStyle(node);
|
|
121
|
+
const hasClick = node.hasAttribute("onclick") ||
|
|
122
|
+
node.hasAttribute("tabindex") ||
|
|
123
|
+
style.cursor === "pointer";
|
|
124
|
+
const role = node.getAttribute("role");
|
|
125
|
+
const tag = node.tagName.toLowerCase();
|
|
126
|
+
// Only capture elements that LOOK interactive but have no ARIA role
|
|
127
|
+
if (hasClick && !role && !["a", "button", "input", "select", "textarea"].includes(tag)) {
|
|
128
|
+
results.push({
|
|
129
|
+
role: "generic",
|
|
130
|
+
name: node.getAttribute("aria-label") ||
|
|
131
|
+
(node.textContent ?? "").trim().slice(0, 80) || "",
|
|
132
|
+
tagName: tag,
|
|
133
|
+
ariaLabel: node.getAttribute("aria-label") ?? "",
|
|
134
|
+
});
|
|
135
|
+
seen.add(node);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
node = walker.nextNode();
|
|
139
|
+
}
|
|
140
|
+
return results;
|
|
141
|
+
}, scopeSelector);
|
|
142
|
+
}
|
|
143
|
+
// ── Main export ──
|
|
144
|
+
/**
|
|
145
|
+
* Generate an enhanced ARIA snapshot with ref annotations.
|
|
146
|
+
*
|
|
147
|
+
* Flow:
|
|
148
|
+
* 1. Get ARIA tree from Playwright's ariaSnapshot()
|
|
149
|
+
* 2. Parse each line, identify roles
|
|
150
|
+
* 3. Two-pass ref assignment (count first for dedup, then assign)
|
|
151
|
+
* 4. Optionally detect cursor-interactive elements
|
|
152
|
+
* 5. Build RefMap and annotated tree string
|
|
153
|
+
*/
|
|
154
|
+
export async function getEnhancedSnapshot(page, options = {}) {
|
|
155
|
+
const { interactive = true, cursor = false, compact = true, selector, } = options;
|
|
156
|
+
// Get the ARIA tree from Playwright
|
|
157
|
+
const locator = selector
|
|
158
|
+
? page.locator(selector)
|
|
159
|
+
: page.locator("body");
|
|
160
|
+
// ariaSnapshot() exists in playwright-core 1.49+ but types may not be in rebrowser-playwright
|
|
161
|
+
const ariaTree = await locator.ariaSnapshot();
|
|
162
|
+
const lines = ariaTree.split("\n");
|
|
163
|
+
const parsed = lines.map(parseLine);
|
|
164
|
+
// ── First pass: count role+name for dedup ──
|
|
165
|
+
const tracker = new RoleNameTracker();
|
|
166
|
+
for (const p of parsed) {
|
|
167
|
+
if (!p)
|
|
168
|
+
continue;
|
|
169
|
+
if (p.role === "text")
|
|
170
|
+
continue;
|
|
171
|
+
if (INTERACTIVE_ROLES.has(p.role) || CONTENT_ROLES.has(p.role)) {
|
|
172
|
+
tracker.count(p.role, p.name);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ── Second pass: assign refs ──
|
|
176
|
+
let refCounter = 0;
|
|
177
|
+
const refs = {};
|
|
178
|
+
const annotatedLines = [];
|
|
179
|
+
let totalElements = 0;
|
|
180
|
+
let interactiveCount = 0;
|
|
181
|
+
let contentCount = 0;
|
|
182
|
+
for (let i = 0; i < lines.length; i++) {
|
|
183
|
+
const p = parsed[i];
|
|
184
|
+
if (!p) {
|
|
185
|
+
// Keep raw lines that didn't parse (empty lines, etc.)
|
|
186
|
+
if (lines[i].trim())
|
|
187
|
+
annotatedLines.push(lines[i]);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
totalElements++;
|
|
191
|
+
const isInteractive = INTERACTIVE_ROLES.has(p.role);
|
|
192
|
+
const isContent = CONTENT_ROLES.has(p.role);
|
|
193
|
+
const isStructural = STRUCTURAL_ROLES.has(p.role);
|
|
194
|
+
const isText = p.role === "text";
|
|
195
|
+
// Decide whether to assign a ref
|
|
196
|
+
let ref;
|
|
197
|
+
if (isInteractive) {
|
|
198
|
+
interactiveCount++;
|
|
199
|
+
ref = `e${++refCounter}`;
|
|
200
|
+
const nth = tracker.getNth(p.role, p.name);
|
|
201
|
+
refs[ref] = {
|
|
202
|
+
selector: buildSelector(p.role, p.name, nth),
|
|
203
|
+
role: p.role,
|
|
204
|
+
name: p.name,
|
|
205
|
+
...(nth !== undefined && { nth }),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
else if (isContent && !interactive) {
|
|
209
|
+
contentCount++;
|
|
210
|
+
ref = `e${++refCounter}`;
|
|
211
|
+
const nth = tracker.getNth(p.role, p.name);
|
|
212
|
+
refs[ref] = {
|
|
213
|
+
selector: buildSelector(p.role, p.name, nth),
|
|
214
|
+
role: p.role,
|
|
215
|
+
name: p.name,
|
|
216
|
+
...(nth !== undefined && { nth }),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// Build annotated line
|
|
220
|
+
if (compact && isStructural && !ref) {
|
|
221
|
+
// In compact mode, skip structural elements without refs
|
|
222
|
+
// BUT keep them if they have children (indicated by trailing ":")
|
|
223
|
+
if (!p.rawLine.trimEnd().endsWith(":"))
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (ref) {
|
|
227
|
+
// Insert [ref=eN] after the role
|
|
228
|
+
const indent = " ".repeat(p.indent);
|
|
229
|
+
const nameStr = p.name ? ` "${p.name}"` : "";
|
|
230
|
+
const attrStr = p.attributes ? ` ${p.attributes}` : "";
|
|
231
|
+
annotatedLines.push(`${indent}- ${p.role}${nameStr} [ref=${ref}]${attrStr}`);
|
|
232
|
+
}
|
|
233
|
+
else if (isText || !compact || !isStructural) {
|
|
234
|
+
annotatedLines.push(p.rawLine);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// ── Cursor-interactive elements (optional) ──
|
|
238
|
+
if (cursor) {
|
|
239
|
+
const cursorElements = await findCursorInteractiveElements(page, selector);
|
|
240
|
+
for (const el of cursorElements) {
|
|
241
|
+
const ref = `e${++refCounter}`;
|
|
242
|
+
interactiveCount++;
|
|
243
|
+
// For cursor elements, build a CSS-based selector as fallback
|
|
244
|
+
const nameStr = el.ariaLabel || el.name;
|
|
245
|
+
refs[ref] = {
|
|
246
|
+
selector: nameStr
|
|
247
|
+
? `getByRole('${el.role}', { name: '${nameStr.replace(/'/g, "\\'")}', exact: true })`
|
|
248
|
+
: `locator('${el.tagName}')`,
|
|
249
|
+
role: el.role || "generic",
|
|
250
|
+
name: nameStr,
|
|
251
|
+
};
|
|
252
|
+
annotatedLines.push(`- ${el.role || "generic"} "${nameStr}" [ref=${ref}] (cursor-interactive)`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
tree: annotatedLines.join("\n"),
|
|
257
|
+
refs,
|
|
258
|
+
stats: {
|
|
259
|
+
totalElements,
|
|
260
|
+
interactiveElements: interactiveCount,
|
|
261
|
+
contentElements: contentCount,
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/snapshot/extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type { RefMap, RefEntry, EnhancedSnapshot, SnapshotOptions } from "./types.js";
|
|
2
|
+
export { getEnhancedSnapshot } from "./extractor.js";
|
|
3
|
+
export { getSnapshotStore, resetSnapshotStore } from "./store.js";
|
|
4
|
+
export { annotateScreenshot } from "./annotator.js";
|
|
5
|
+
export { generateBoundary, wrapContent } from "./boundary.js";
|
|
6
|
+
export { diffSnapshots, diffScreenshots } from "./differ.js";
|
|
7
|
+
export type { TextDiffResult, ImageDiffResult, ImageDiffOptions } from "./differ.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/snapshot/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { getEnhancedSnapshot } from "./extractor.js";
|
|
2
|
+
export { getSnapshotStore, resetSnapshotStore } from "./store.js";
|
|
3
|
+
export { annotateScreenshot } from "./annotator.js";
|
|
4
|
+
export { generateBoundary, wrapContent } from "./boundary.js";
|
|
5
|
+
export { diffSnapshots, diffScreenshots } from "./differ.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/snapshot/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SnapshotStore — In-memory ref storage with LRU eviction.
|
|
3
|
+
*
|
|
4
|
+
* Stores RefMaps keyed by session_id (or auto-generated snapshot IDs).
|
|
5
|
+
* Refs are ephemeral — they exist only in memory and are invalidated
|
|
6
|
+
* when a new snapshot is taken for the same session.
|
|
7
|
+
*/
|
|
8
|
+
import type { RefMap, RefEntry } from "./types.js";
|
|
9
|
+
declare class SnapshotStore {
|
|
10
|
+
private store;
|
|
11
|
+
/** Save a snapshot's refs, evicting oldest if at capacity */
|
|
12
|
+
save(id: string, refs: RefMap, url: string): void;
|
|
13
|
+
/** Resolve a ref string (e.g. "e5" or "@e5") to its locator info */
|
|
14
|
+
resolveRef(id: string, refString: string): RefEntry | null;
|
|
15
|
+
/** Get all refs for a snapshot */
|
|
16
|
+
getRefs(id: string): RefMap | null;
|
|
17
|
+
/** Invalidate a specific snapshot */
|
|
18
|
+
invalidate(id: string): void;
|
|
19
|
+
/** Clear all stored snapshots */
|
|
20
|
+
clear(): void;
|
|
21
|
+
/** Number of stored snapshots */
|
|
22
|
+
get size(): number;
|
|
23
|
+
}
|
|
24
|
+
export declare function getSnapshotStore(): SnapshotStore;
|
|
25
|
+
/** Reset singleton (for testing) */
|
|
26
|
+
export declare function resetSnapshotStore(): void;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/snapshot/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AASnD,cAAM,aAAa;IACjB,OAAO,CAAC,KAAK,CAAqC;IAElD,6DAA6D;IAC7D,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAiBjD,oEAAoE;IACpE,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAS1D,kCAAkC;IAClC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIlC,qCAAqC;IACrC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI5B,iCAAiC;IACjC,KAAK,IAAI,IAAI;IAIb,iCAAiC;IACjC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAMD,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD;AAED,oCAAoC;AACpC,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|