@ulpi/browse 0.7.2 → 0.7.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ulpi/browse",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/ulpi-io/browse"
package/skill/SKILL.md CHANGED
@@ -261,7 +261,8 @@ browse accessibility Accessibility tree snapshot (ARIA)
261
261
  ```
262
262
  browse snapshot Full accessibility tree with @refs
263
263
  browse snapshot -i Interactive elements only — terse flat list (minimal tokens)
264
- browse snapshot -i -v Interactive elements — verbose indented tree with props
264
+ browse snapshot -i -f Interactive elements — full indented tree with props
265
+ browse snapshot -i -V Interactive elements — viewport only (skip below-fold)
265
266
  browse snapshot -c Compact (no empty structural elements)
266
267
  browse snapshot -C Cursor-interactive (detect divs with cursor:pointer/onclick/tabindex)
267
268
  browse snapshot -d <N> Limit depth to N levels
package/src/cli.ts CHANGED
@@ -612,7 +612,7 @@ Inspection: js <expr> | eval <file> | css <sel> <prop> | attrs <sel>
612
612
  cookies | storage [set <k> <v>] | perf
613
613
  value <sel> | count <sel> | clipboard [write <text>]
614
614
  Visual: screenshot [path] | pdf [path] | responsive [prefix]
615
- Snapshot: snapshot [-i] [-v] [-c] [-C] [-d N] [-s sel]
615
+ Snapshot: snapshot [-i] [-f] [-V] [-c] [-C] [-d N] [-s sel]
616
616
  Find: find role|text|label|placeholder|testid <query> [name]
617
617
  Compare: diff <url1> <url2> | screenshot-diff <baseline> [current]
618
618
  Multi-step: chain (reads JSON from stdin)
@@ -639,7 +639,8 @@ Options:
639
639
 
640
640
  Snapshot flags:
641
641
  -i Interactive elements only (terse flat list by default)
642
- -v Verbosefull indented tree with props (use with -i)
642
+ -f Full — indented tree with props and children (use with -i)
643
+ -V Viewport — only elements visible in current viewport
643
644
  -c Compact — remove empty structural elements
644
645
  -C Cursor-interactive — detect divs with cursor:pointer,
645
646
  onclick, tabindex, data-action (missed by ARIA tree)
package/src/snapshot.ts CHANGED
@@ -31,8 +31,9 @@ const INTERACTIVE_ROLES = new Set([
31
31
 
32
32
  interface SnapshotOptions {
33
33
  interactive?: boolean; // -i: only interactive elements (terse flat list by default)
34
- verbose?: boolean; // -v: full indented ARIA tree with props/children (overrides -i terse default)
34
+ full?: boolean; // -f: full indented ARIA tree with props/children (overrides -i terse default)
35
35
  compact?: boolean; // -c: remove empty structural elements
36
+ viewport?: boolean; // -V: only elements visible in current viewport
36
37
  depth?: number; // -d N: limit tree depth
37
38
  selector?: string; // -s SEL: scope to CSS selector
38
39
  cursor?: boolean; // -C: detect cursor-interactive elements (divs with cursor:pointer, onclick, tabindex)
@@ -73,9 +74,13 @@ export function parseSnapshotArgs(args: string[]): SnapshotOptions {
73
74
  case '--compact':
74
75
  opts.compact = true;
75
76
  break;
76
- case '-v':
77
- case '--verbose':
78
- opts.verbose = true;
77
+ case '-f':
78
+ case '--full':
79
+ opts.full = true;
80
+ break;
81
+ case '-V':
82
+ case '--viewport':
83
+ opts.viewport = true;
79
84
  break;
80
85
  case '-C':
81
86
  case '--cursor':
@@ -422,8 +427,8 @@ export async function handleSnapshot(
422
427
  refMap.set(ref, locator);
423
428
 
424
429
  // Format output line
425
- // -i without -v: terse flat list (no indent, no props, no children)
426
- const terse = opts.interactive && !opts.verbose;
430
+ // -i without -f: terse flat list (no indent, no props, no children)
431
+ const terse = opts.interactive && !opts.full;
427
432
  let outputLine: string;
428
433
  if (terse) {
429
434
  outputLine = `@${ref} [${node.role}]`;
@@ -441,6 +446,36 @@ export async function handleSnapshot(
441
446
  output.push(outputLine);
442
447
  }
443
448
 
449
+ // Viewport filter: remove elements below the visible viewport
450
+ if (opts.viewport) {
451
+ const vp = page.viewportSize();
452
+ if (vp) {
453
+ const toRemove = new Set<string>();
454
+ await Promise.all(
455
+ Array.from(refMap.entries()).map(async ([ref, loc]) => {
456
+ try {
457
+ const box = await loc.boundingBox({ timeout: 500 });
458
+ if (!box || box.y >= vp.height || box.y + box.height <= 0) {
459
+ toRemove.add(ref);
460
+ }
461
+ } catch {
462
+ toRemove.add(ref);
463
+ }
464
+ })
465
+ );
466
+ for (const ref of toRemove) {
467
+ refMap.delete(ref);
468
+ }
469
+ // Remove output lines for filtered refs
470
+ for (let i = output.length - 1; i >= 0; i--) {
471
+ const match = output[i].match(/@(e\d+)/);
472
+ if (match && toRemove.has(match[1])) {
473
+ output.splice(i, 1);
474
+ }
475
+ }
476
+ }
477
+ }
478
+
444
479
  // Cursor-interactive detection: supplement ARIA tree with DOM-level scan
445
480
  if (opts.cursor) {
446
481
  const result = await appendCursorElements(evalCtx, locatorRoot, opts, output, refMap, refCounter, bm);