@sightmap/playwright 0.9.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fullstory, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # @sightmap/playwright
2
+
3
+ Sightmap-aware wrapper around `@playwright/cli`. Adds sightmap-aware
4
+ commands (`snapshot`, `match`, `act`, `network`) that consume your
5
+ `.sightmap/` corpus and enrich the agent-facing output with component
6
+ names, view memory, and request annotations. Other commands pass through
7
+ to `@playwright/cli` unchanged.
8
+
9
+ This is the **no-MCP** path: a coding agent invokes `sightmap-playwright`
10
+ the same way it would invoke `playwright`, with no MCP protocol overhead.
11
+
12
+ ## Install
13
+
14
+ ```sh
15
+ pnpm add -D @sightmap/playwright @playwright/cli
16
+ ```
17
+
18
+ `@playwright/cli` is a peer dependency. `sightmap-playwright` shells out
19
+ to it for the browser primitives.
20
+
21
+ ## Usage
22
+
23
+ ```sh
24
+ sightmap-playwright [global flags] <command> [args...]
25
+ ```
26
+
27
+ Global flags:
28
+
29
+ ```
30
+ -s, --session NAME Named playwright-cli session (default: "default")
31
+ --sightmap-dir DIR Path to .sightmap/ directory (default: ".sightmap")
32
+ --json Emit JSON instead of human-readable text
33
+ ```
34
+
35
+ ## Sightmap-specific commands
36
+
37
+ ### `snapshot` — enriched a11y snapshot
38
+
39
+ Captures an ARIA snapshot from the current page and annotates it with
40
+ the matched sightmap view, view memory, and the sightmap components
41
+ present on the page (with live `matchCount`).
42
+
43
+ ```text
44
+ $ sightmap-playwright snapshot
45
+ View: SearchResults (/search)
46
+ memory:
47
+ - paginated; load-more button at bottom
48
+ Components:
49
+ - SearchBar (global) — 1 match
50
+ - ResultCard (view-scoped) — 12 matches
51
+ memory: clicking opens detail in a new tab
52
+
53
+ --- ARIA snapshot ---
54
+ - main:
55
+ - heading "Results for 'sightmap'" [level=1]
56
+ ...
57
+ ```
58
+
59
+ Pass `--json` to get the structured `EnrichedSnapshot` plus raw ARIA text.
60
+
61
+ ### `match URL` — show the matching sightmap view
62
+
63
+ Pure-query: resolves a URL (or pathname) against the loaded sightmap and
64
+ prints the matched view, applicable components, and known requests.
65
+
66
+ ```text
67
+ $ sightmap-playwright match /list/abc123
68
+ View: ListDetailScreen (/list/*)
69
+ memory: id is opaque; do not parse
70
+ Components:
71
+ - BottomTabBar (global)
72
+ - ListCard (view-scoped)
73
+ Requests:
74
+ - GET /api/list/:id → fetchList
75
+ ```
76
+
77
+ No browser is launched; this is the same matcher used by `@sightmap/sightmap`
78
+ exposed through the playwright-cli wrapper for convenience.
79
+
80
+ ### `act NAME` — resolve a component name to a selector
81
+
82
+ Resolves a sightmap component name to its primary selector (plus any
83
+ fallbacks). Prints the selector to stdout so it can be piped into another
84
+ playwright-cli command.
85
+
86
+ ```text
87
+ $ sightmap-playwright act SubmitButton
88
+ [data-testid="submit"]
89
+ # fallbacks: button[type="submit"]
90
+ ```
91
+
92
+ Exits non-zero if the component name is unknown. Pass `--json` for the
93
+ full resolution result.
94
+
95
+ ### `network` — annotated network requests
96
+
97
+ Pulls recent network requests from the current session and tags any
98
+ that match a `requests:` entry in the sightmap, attaching request memory.
99
+
100
+ ```text
101
+ $ sightmap-playwright network
102
+ [GET] https://example.test/api/list/abc → 200 [fetchList]
103
+ memory: returns 404 for archived lists; treat as "not found"
104
+ [POST] https://example.test/api/track → 204
105
+ ```
106
+
107
+ ## Passthrough
108
+
109
+ Anything that isn't a sightmap-specific command is forwarded to
110
+ `@playwright/cli` verbatim, preserving the session flag:
111
+
112
+ ```sh
113
+ sightmap-playwright open https://example.test
114
+ sightmap-playwright close
115
+ ```
116
+
117
+ This means you can use `sightmap-playwright` as a drop-in for
118
+ `playwright` and only opt into the sightmap-aware behavior on the four
119
+ commands above.
120
+
121
+ ## Sessions
122
+
123
+ `@playwright/cli` uses **named sessions** to keep a browser context alive
124
+ across invocations. `sightmap-playwright` honors the same flag:
125
+
126
+ ```sh
127
+ sightmap-playwright -s checkout open https://shop.test
128
+ sightmap-playwright -s checkout snapshot
129
+ sightmap-playwright -s checkout network
130
+ sightmap-playwright -s checkout close
131
+ ```
132
+
133
+ If you don't pass `-s`/`--session`, the session is `"default"`. Run
134
+ parallel flows by giving them distinct session names.
135
+
136
+ ## `.sightmap/` resolution
137
+
138
+ Sightmap files are loaded **per invocation** from `--sightmap-dir`
139
+ (default `.sightmap`), resolved against the current working directory.
140
+ Override it if you're invoking from outside the project root:
141
+
142
+ ```sh
143
+ sightmap-playwright --sightmap-dir /path/to/repo/.sightmap snapshot
144
+ ```
145
+
146
+ There is no daemon and no cache — each command re-reads the corpus, so
147
+ edits to `.sightmap/` are picked up immediately.
148
+
149
+ ## See also
150
+
151
+ - [`@sightmap/sightmap`](../sightmap) — the underlying matcher, lint, and
152
+ validate library. Same semantics, no browser.
153
+ - [`@sightmap/mcp`](../mcp) — the MCP-server alternative if your host
154
+ agent speaks MCP.
155
+ - [sightmap.org](https://sightmap.org) — spec and full docs.
156
+
157
+ ## License
158
+
159
+ MIT.
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,437 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/act.ts
4
+ import {
5
+ loadDirectory,
6
+ resolveSightmapAct
7
+ } from "@sightmap/sightmap";
8
+ async function runActCommand(opts) {
9
+ const sightmap = await loadDirectory(opts.sightmapDir);
10
+ const r = resolveSightmapAct(sightmap, { componentName: opts.componentName });
11
+ if (r.kind === "error") {
12
+ process.stderr.write(r.message + "\n");
13
+ process.exit(1);
14
+ return;
15
+ }
16
+ if (opts.json) {
17
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
18
+ return;
19
+ }
20
+ process.stdout.write(`${r.selector}
21
+ `);
22
+ if (r.allSelectors.length > 1) {
23
+ process.stdout.write(`# fallbacks: ${r.allSelectors.slice(1).join(", ")}
24
+ `);
25
+ }
26
+ }
27
+
28
+ // src/commands/match.ts
29
+ import { loadDirectory as loadDirectory2, match } from "@sightmap/sightmap";
30
+ async function runMatchCommand(opts) {
31
+ const sightmap = await loadDirectory2(opts.sightmapDir);
32
+ const result = match(sightmap, { url: opts.url });
33
+ if (opts.json) {
34
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
35
+ return;
36
+ }
37
+ const lines = [];
38
+ if (result.view) {
39
+ lines.push(`View: ${result.view.name} (${result.view.route})`);
40
+ for (const m of result.view.memory ?? []) lines.push(` memory: ${m}`);
41
+ } else {
42
+ lines.push(`View: (no match)`);
43
+ }
44
+ if (result.components.length > 0) {
45
+ lines.push(`Components:`);
46
+ for (const c of result.components) {
47
+ lines.push(` - ${c.name} (${c.scope})`);
48
+ }
49
+ }
50
+ if (result.requests.length > 0) {
51
+ lines.push(`Requests:`);
52
+ for (const r of result.requests) {
53
+ lines.push(` - ${r.method ?? "ANY"} ${r.route} \u2192 ${r.name}`);
54
+ }
55
+ }
56
+ process.stdout.write(lines.join("\n") + "\n");
57
+ }
58
+
59
+ // src/commands/network.ts
60
+ import {
61
+ loadDirectory as loadDirectory3,
62
+ annotateNetworkRequests
63
+ } from "@sightmap/sightmap";
64
+
65
+ // src/exec.ts
66
+ import { spawn } from "child_process";
67
+ async function execPlaywrightCli(args, options = {}) {
68
+ const binary = options.binary ?? "playwright-cli";
69
+ const timeoutMs = options.timeoutMs ?? 6e4;
70
+ return await new Promise((resolve, reject) => {
71
+ const child = spawn(binary, args, {
72
+ cwd: options.cwd ?? process.cwd(),
73
+ env: options.env ?? process.env,
74
+ stdio: ["ignore", "pipe", "pipe"]
75
+ });
76
+ const stdoutChunks = [];
77
+ const stderrChunks = [];
78
+ child.stdout.on("data", (c) => stdoutChunks.push(c));
79
+ child.stderr.on("data", (c) => stderrChunks.push(c));
80
+ const killTimer = setTimeout(() => {
81
+ child.kill("SIGTERM");
82
+ }, timeoutMs);
83
+ child.on("error", (err) => {
84
+ clearTimeout(killTimer);
85
+ reject(err);
86
+ });
87
+ child.on("close", (code) => {
88
+ clearTimeout(killTimer);
89
+ resolve({
90
+ exitCode: code ?? -1,
91
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
92
+ stderr: Buffer.concat(stderrChunks).toString("utf8")
93
+ });
94
+ });
95
+ });
96
+ }
97
+ async function streamPlaywrightCli(args, options = {}) {
98
+ const binary = options.binary ?? "playwright-cli";
99
+ return await new Promise((resolve, reject) => {
100
+ const child = spawn(binary, args, {
101
+ cwd: options.cwd ?? process.cwd(),
102
+ env: options.env ?? process.env,
103
+ stdio: "inherit"
104
+ });
105
+ child.on("error", reject);
106
+ child.on("close", (code) => {
107
+ resolve({ exitCode: code ?? -1 });
108
+ });
109
+ });
110
+ }
111
+
112
+ // src/parse-network.ts
113
+ function parsePlaywrightCliNetwork(text) {
114
+ const requests = [];
115
+ if (!/^###\s+Result/m.test(text)) return [];
116
+ const lines = text.split(/\r?\n/);
117
+ const re = /^\s*\d+\.\s*\[([A-Z]+)\]\s+(\S+)\s+=>\s+\[(\d+)\]\s*(.*?)\s*$/;
118
+ for (const line of lines) {
119
+ const m = re.exec(line);
120
+ if (m === null) continue;
121
+ requests.push({
122
+ method: m[1] ?? "",
123
+ url: m[2] ?? "",
124
+ status: Number.parseInt(m[3] ?? "0", 10),
125
+ statusText: m[4] ?? ""
126
+ });
127
+ }
128
+ return requests;
129
+ }
130
+
131
+ // src/commands/network.ts
132
+ async function runNetworkCommand(opts) {
133
+ const sightmap = await loadDirectory3(opts.sightmapDir);
134
+ const result = await execPlaywrightCli([
135
+ "-s",
136
+ opts.sessionName,
137
+ "network",
138
+ "requests"
139
+ ]);
140
+ if (result.exitCode !== 0) {
141
+ process.stderr.write(result.stderr);
142
+ process.exit(result.exitCode);
143
+ }
144
+ const parsed = parsePlaywrightCliNetwork(result.stdout);
145
+ const annotated = annotateNetworkRequests(sightmap, parsed);
146
+ if (opts.json) {
147
+ process.stdout.write(JSON.stringify(annotated, null, 2) + "\n");
148
+ return;
149
+ }
150
+ for (const r of annotated) {
151
+ const tag = r.sightmapName ? ` [${r.sightmapName}]` : "";
152
+ process.stdout.write(`[${r.method}] ${r.url} \u2192 ${r.status}${tag}
153
+ `);
154
+ if (r.sightmapMemory) {
155
+ for (const m of r.sightmapMemory) process.stdout.write(` memory: ${m}
156
+ `);
157
+ }
158
+ }
159
+ }
160
+
161
+ // src/commands/passthrough.ts
162
+ async function runPassthroughCommand(opts) {
163
+ const { exitCode } = await streamPlaywrightCli([
164
+ "-s",
165
+ opts.sessionName,
166
+ ...opts.rest
167
+ ]);
168
+ if (exitCode !== 0) process.exit(exitCode);
169
+ }
170
+
171
+ // src/commands/snapshot.ts
172
+ import {
173
+ enrichSnapshot,
174
+ loadDirectory as loadDirectory4,
175
+ match as sightmapMatch
176
+ } from "@sightmap/sightmap";
177
+
178
+ // src/parse-snapshot.ts
179
+ function parsePlaywrightCliSnapshot(text) {
180
+ const lines = text.split(/\r?\n/);
181
+ let url = "";
182
+ let title;
183
+ const nodes = [];
184
+ let inSnapshotSection = false;
185
+ let snapshotBaseIndent = null;
186
+ const pageUrlRe = /^- Page URL:\s*(\S+)/;
187
+ const pageTitleRe = /^- Page Title:\s*(.+?)\s*$/;
188
+ const nodeRe = /^(\s*)-\s+([a-zA-Z][\w-]*)\s*(?:"([^"]*)")?\s*((?:\[[^\]]+\]\s*)*)\s*:?/;
189
+ const refAttrRe = /\[ref=(e\d+)\]/;
190
+ for (const line of lines) {
191
+ if (/^###\s+Snapshot/.test(line)) {
192
+ inSnapshotSection = true;
193
+ continue;
194
+ }
195
+ if (/^###\s+Events/.test(line)) {
196
+ inSnapshotSection = false;
197
+ continue;
198
+ }
199
+ if (/^###\s+/.test(line)) {
200
+ inSnapshotSection = false;
201
+ continue;
202
+ }
203
+ if (/^```/.test(line)) continue;
204
+ if (!inSnapshotSection) {
205
+ const u = pageUrlRe.exec(line);
206
+ if (u) {
207
+ url = u[1] ?? "";
208
+ continue;
209
+ }
210
+ const t = pageTitleRe.exec(line);
211
+ if (t) {
212
+ title = t[1];
213
+ continue;
214
+ }
215
+ continue;
216
+ }
217
+ const m = nodeRe.exec(line);
218
+ if (m === null) continue;
219
+ const indent = m[1] ?? "";
220
+ const role = m[2];
221
+ const name = m[3];
222
+ const attrs = m[4] ?? "";
223
+ const refMatch = refAttrRe.exec(attrs);
224
+ const ref = refMatch?.[1];
225
+ if (snapshotBaseIndent === null) snapshotBaseIndent = indent.length;
226
+ const depth = Math.max(
227
+ 0,
228
+ Math.floor((indent.length - snapshotBaseIndent) / 2)
229
+ );
230
+ nodes.push({
231
+ depth,
232
+ ...ref !== void 0 ? { ref } : {},
233
+ ...role !== void 0 ? { role } : {},
234
+ ...name !== void 0 ? { name } : {}
235
+ });
236
+ }
237
+ return {
238
+ url,
239
+ ...title !== void 0 ? { title } : {},
240
+ ariaText: text,
241
+ nodes
242
+ };
243
+ }
244
+
245
+ // src/in-page-runner.ts
246
+ import {
247
+ buildInPageEvalFunction
248
+ } from "@sightmap/sightmap";
249
+ async function runInPageMatcher(components, sessionName, options = {}) {
250
+ if (components.length === 0) return [];
251
+ const js = buildInPageEvalFunction(components);
252
+ const result = await execPlaywrightCli(
253
+ ["-s", sessionName, "eval", js],
254
+ options
255
+ );
256
+ if (result.exitCode !== 0) {
257
+ throw new Error(`playwright-cli eval failed: ${result.stderr}`);
258
+ }
259
+ return parseInPageEvalStdout(result.stdout);
260
+ }
261
+ function parseInPageEvalStdout(stdout) {
262
+ const text = stdout.trim();
263
+ if (text.length === 0) return [];
264
+ const afterResult = text.split(/^###\s*Result/im)[1] ?? text;
265
+ const start = afterResult.indexOf("{");
266
+ if (start < 0) return [];
267
+ for (let end = afterResult.length; end > start; end--) {
268
+ try {
269
+ const parsed = JSON.parse(afterResult.slice(start, end));
270
+ if (Array.isArray(parsed.matches)) return parsed.matches;
271
+ } catch {
272
+ }
273
+ }
274
+ return [];
275
+ }
276
+
277
+ // src/commands/snapshot.ts
278
+ async function runSnapshotCommand(opts) {
279
+ const sightmap = await loadDirectory4(opts.sightmapDir);
280
+ const snapResult = await execPlaywrightCli([
281
+ "-s",
282
+ opts.sessionName,
283
+ "snapshot"
284
+ ]);
285
+ if (snapResult.exitCode !== 0) {
286
+ process.stderr.write(snapResult.stderr);
287
+ process.exit(snapResult.exitCode);
288
+ }
289
+ const parsed = parsePlaywrightCliSnapshot(snapResult.stdout);
290
+ const matchResult = sightmapMatch(sightmap, { url: parsed.url });
291
+ const allComponents = matchResult.components.map((c) => ({
292
+ name: c.name,
293
+ selector: c.selector
294
+ }));
295
+ const inPage = await runInPageMatcher(allComponents, opts.sessionName);
296
+ const enriched = enrichSnapshot({
297
+ sightmap,
298
+ currentUrl: parsed.url,
299
+ inPageMatches: inPage
300
+ });
301
+ if (opts.json) {
302
+ process.stdout.write(
303
+ JSON.stringify({ ...enriched, ariaSnapshot: parsed.ariaText }, null, 2) + "\n"
304
+ );
305
+ } else {
306
+ process.stdout.write(formatHuman(enriched, parsed.ariaText));
307
+ }
308
+ }
309
+ function formatHuman(enriched, ariaText) {
310
+ const lines = [];
311
+ if (enriched.view) {
312
+ lines.push(`View: ${enriched.view.name} (${enriched.view.route})`);
313
+ if (enriched.view.memory.length > 0) {
314
+ lines.push(` memory:`);
315
+ for (const m of enriched.view.memory) lines.push(` - ${m}`);
316
+ }
317
+ } else {
318
+ lines.push(`View: (no match)`);
319
+ }
320
+ if (enriched.components.length > 0) {
321
+ lines.push(`Components:`);
322
+ for (const c of enriched.components) {
323
+ lines.push(
324
+ ` - ${c.name} (${c.scope}) \u2014 ${c.matchCount} match${c.matchCount === 1 ? "" : "es"}`
325
+ );
326
+ for (const m of c.memory) lines.push(` memory: ${m}`);
327
+ }
328
+ }
329
+ lines.push("");
330
+ lines.push("--- ARIA snapshot ---");
331
+ lines.push(ariaText);
332
+ return lines.join("\n");
333
+ }
334
+
335
+ // src/cli.ts
336
+ function requireValue(flag, next) {
337
+ if (next === void 0 || next.startsWith("-")) {
338
+ console.error(
339
+ `${flag}: expected a value, got "${next ?? "(end of args)"}"`
340
+ );
341
+ process.exit(2);
342
+ }
343
+ return next;
344
+ }
345
+ function parseArgs(argv) {
346
+ let session = "default";
347
+ let sightmapDir = ".sightmap";
348
+ let json = false;
349
+ const positional = [];
350
+ for (let i = 0; i < argv.length; i++) {
351
+ const a = argv[i];
352
+ if (a === "-s" || a === "--session") {
353
+ session = requireValue(a, argv[++i]);
354
+ } else if (a === "--sightmap-dir") {
355
+ sightmapDir = requireValue(a, argv[++i]);
356
+ } else if (a === "--json") {
357
+ json = true;
358
+ } else {
359
+ positional.push(a);
360
+ }
361
+ }
362
+ return {
363
+ command: positional[0] ?? "",
364
+ session,
365
+ sightmapDir,
366
+ json,
367
+ rest: positional.slice(1)
368
+ };
369
+ }
370
+ function printHelp() {
371
+ console.log(
372
+ `sightmap-playwright \u2014 sightmap-aware wrapper around @playwright/cli
373
+
374
+ Usage:
375
+ sightmap-playwright [global flags] <command> [args...]
376
+
377
+ Global flags:
378
+ -s, --session NAME Named playwright-cli session (default: "default")
379
+ --sightmap-dir DIR Path to .sightmap/ directory (default: ".sightmap")
380
+ --json Emit JSON instead of human-readable text
381
+
382
+ Sightmap-specific commands:
383
+ snapshot Enriched a11y snapshot with sightmap component names
384
+ match URL Show the matching sightmap view for URL
385
+ act NAME Resolve a sightmap component name to a selector
386
+ network Network requests annotated with sightmap memory
387
+
388
+ All other commands are forwarded to @playwright/cli verbatim.
389
+ `
390
+ );
391
+ }
392
+ async function main() {
393
+ const argv = process.argv.slice(2);
394
+ if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
395
+ printHelp();
396
+ return;
397
+ }
398
+ const { command, session, sightmapDir, json, rest } = parseArgs(argv);
399
+ switch (command) {
400
+ case "snapshot":
401
+ await runSnapshotCommand({ sessionName: session, sightmapDir, json });
402
+ return;
403
+ case "match": {
404
+ const url = rest[0];
405
+ if (url === void 0) {
406
+ console.error("sightmap-playwright match: URL required");
407
+ process.exit(2);
408
+ }
409
+ await runMatchCommand({ url, sightmapDir, json });
410
+ return;
411
+ }
412
+ case "act": {
413
+ const name = rest[0];
414
+ if (name === void 0) {
415
+ console.error("sightmap-playwright act: component name required");
416
+ process.exit(2);
417
+ }
418
+ await runActCommand({ componentName: name, sightmapDir, json });
419
+ return;
420
+ }
421
+ case "network":
422
+ await runNetworkCommand({ sessionName: session, sightmapDir, json });
423
+ return;
424
+ default: {
425
+ const passArgs = json ? ["--json", command, ...rest] : [command, ...rest];
426
+ await runPassthroughCommand({
427
+ sessionName: session,
428
+ rest: passArgs.filter((s) => s.length > 0)
429
+ });
430
+ return;
431
+ }
432
+ }
433
+ }
434
+ main().catch((err) => {
435
+ console.error(err instanceof Error ? err.message : String(err));
436
+ process.exit(1);
437
+ });
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@sightmap/playwright",
3
+ "version": "0.9.0",
4
+ "description": "Sightmap-aware wrapper around @playwright/cli. Adds sightmap_* commands and enriches snapshot output with component names from .sightmap/.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/sightmap/sightmap-js.git",
9
+ "directory": "packages/playwright"
10
+ },
11
+ "homepage": "https://sightmap.org",
12
+ "keywords": [
13
+ "sightmap",
14
+ "playwright",
15
+ "cli",
16
+ "agent",
17
+ "browser"
18
+ ],
19
+ "type": "module",
20
+ "bin": {
21
+ "sightmap-playwright": "./dist/cli.js"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "devDependencies": {
32
+ "@playwright/cli": "^0.1.13",
33
+ "@types/node": "^20.19.39",
34
+ "tsup": "^8.5.1",
35
+ "typescript": "~5.7.3",
36
+ "vitest": "^3.0.0"
37
+ },
38
+ "dependencies": {
39
+ "@sightmap/sightmap": "^0.9.0"
40
+ },
41
+ "peerDependencies": {
42
+ "@playwright/cli": "^0.1.0"
43
+ },
44
+ "peerDependenciesMeta": {
45
+ "@playwright/cli": {
46
+ "optional": false
47
+ }
48
+ },
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "test": "vitest run",
52
+ "test:watch": "vitest",
53
+ "typecheck": "tsc --noEmit"
54
+ }
55
+ }