@ubio/webvision 2.6.6 → 3.0.1

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/build/page.mjs CHANGED
@@ -1,17 +1,3 @@
1
- // src/page/counter.ts
2
- var Counter = class {
3
- constructor(value = 0) {
4
- this.value = value;
5
- }
6
- next() {
7
- this.value += 1;
8
- return this.value;
9
- }
10
- current() {
11
- return this.value;
12
- }
13
- };
14
-
15
1
  // src/page/dom.ts
16
2
  var ORIGINAL_STYLE_SYMBOL = Symbol("vx:originalStyle");
17
3
  var INTERACTIVE_TAGS = ["a", "button", "input", "textarea", "select", "label", "option", "optgroup"];
@@ -198,6 +184,24 @@ function fixZIndex(el) {
198
184
  }
199
185
  }
200
186
  }
187
+ function getElementDepth(el) {
188
+ let depth = 0;
189
+ while (el.parentElement) {
190
+ el = el.parentElement;
191
+ depth += 1;
192
+ }
193
+ return depth;
194
+ }
195
+ function serializeElement(el) {
196
+ const sig = [];
197
+ const depth = getElementDepth(el);
198
+ sig.push(String(depth));
199
+ sig.push(el.tagName);
200
+ for (const attr of el.attributes) {
201
+ sig.push(`${attr.name}=${attr.value}`);
202
+ }
203
+ return sig.join("|");
204
+ }
201
205
 
202
206
  // src/page/traverse.ts
203
207
  function* traverseVxNode(vxNode, depth = 0) {
@@ -279,6 +283,191 @@ function isContainerNode(vxNode) {
279
283
  function isObjectEmpty(obj) {
280
284
  return !Object.values(obj).some((value) => !!value);
281
285
  }
286
+ function normalizeRef(ref) {
287
+ return ref.toLowerCase().trim().replace(/^[@#]/, "");
288
+ }
289
+
290
+ // src/page/render.ts
291
+ function renderVxNode(scope, options = {}) {
292
+ const buffer = [];
293
+ for (const { vxNode, depth } of traverseVxNode(scope)) {
294
+ if (options.skipNonInteractive && !vxNode.isInteractive) {
295
+ continue;
296
+ }
297
+ const indent = options.skipNonInteractive ? "" : " ".repeat(depth);
298
+ buffer.push(renderIndentedLine(indent, vxNode, options));
299
+ }
300
+ return buffer.join("\n");
301
+ }
302
+ function renderIndentedLine(indent, vxNode, options = {}) {
303
+ const diffPrefix = options.renderDiff ? vxNode.isNew ? "+ " : " " : "";
304
+ if (!vxNode.tagName) {
305
+ return [diffPrefix, indent, vxNode.textContent].filter(Boolean).join("");
306
+ }
307
+ const tagLine = renderTagLine(vxNode, options);
308
+ const htmlStyle = options.renderStyle === "html";
309
+ return [
310
+ diffPrefix,
311
+ indent,
312
+ tagLine,
313
+ htmlStyle ? "" : " ",
314
+ vxNode.textContent ?? ""
315
+ ].join("");
316
+ }
317
+ function renderTagLine(vxNode, options) {
318
+ const htmlStyle = options.renderStyle === "html";
319
+ const components = [];
320
+ if (options.renderTagNames && vxNode.tagName) {
321
+ components.push(vxNode.tagName);
322
+ }
323
+ if (options.renderIds && vxNode.id) {
324
+ if (htmlStyle) {
325
+ components.push(`id="${vxNode.id}"`);
326
+ } else {
327
+ components.push(`#${vxNode.id}`);
328
+ }
329
+ }
330
+ if (options.renderClassNames && vxNode.classList?.length) {
331
+ if (htmlStyle) {
332
+ components.push(`class="${vxNode.classList.join(" ")}"`);
333
+ } else {
334
+ components.push("." + vxNode.classList.join("."));
335
+ }
336
+ }
337
+ if (options.renderRefs) {
338
+ const isRenderRef = [
339
+ options.renderRefs === "all",
340
+ options.renderRefs === true && !isContainerNode(vxNode)
341
+ ].some(Boolean);
342
+ if (isRenderRef) {
343
+ components.push(`[@${vxNode.ref}]`);
344
+ }
345
+ }
346
+ const attrs = [];
347
+ if (options.renderLabelAttrs) {
348
+ for (const [attr, value] of Object.entries(vxNode.labelAttrs ?? {})) {
349
+ attrs.push(`${attr}="${truncateAttrValue(value)}"`);
350
+ }
351
+ }
352
+ if (options.renderValueAttrs) {
353
+ for (const [attr, value] of Object.entries(vxNode.valueAttrs ?? {})) {
354
+ attrs.push(`${attr}="${truncateAttrValue(value)}"`);
355
+ }
356
+ }
357
+ if (options.renderSrcAttrs) {
358
+ for (const [attr, value] of Object.entries(vxNode.srcAttrs ?? {})) {
359
+ attrs.push(`${attr}="${truncateAttrValue(value)}"`);
360
+ }
361
+ }
362
+ if (htmlStyle) {
363
+ components.push(...attrs);
364
+ } else {
365
+ components.push(...attrs.map((attr) => `[${attr}]`));
366
+ }
367
+ return htmlStyle ? `<${components.join(" ")}>` : components.join("");
368
+ }
369
+
370
+ // src/page/snapshot.ts
371
+ var VX_DOM_SYMBOL = Symbol("vx:dom");
372
+ var VX_TREE_SYMBOL = Symbol("vx:tree");
373
+ var VX_LAST_REFS_SYMBOL = Symbol("vx:lastRefs");
374
+ async function captureSnapshot(options = {}) {
375
+ const parser = new VxTreeParser(options);
376
+ const domMap = parser.getDomMap();
377
+ const vxTree = parser.getTree(options.frameId ?? "0", options.iframeRef);
378
+ globalThis[VX_DOM_SYMBOL] = domMap;
379
+ globalThis[VX_TREE_SYMBOL] = vxTree;
380
+ return vxTree;
381
+ }
382
+ function getSnapshot() {
383
+ const vxTree = globalThis[VX_TREE_SYMBOL];
384
+ if (!vxTree) {
385
+ throw new Error("[VX] Snapshot not found");
386
+ }
387
+ return vxTree;
388
+ }
389
+ function resolveDomNode(ref) {
390
+ const domMap = globalThis[VX_DOM_SYMBOL];
391
+ if (!domMap) {
392
+ return null;
393
+ }
394
+ return domMap.get(ref) ?? null;
395
+ }
396
+
397
+ // src/page/tree.ts
398
+ var VxTreeView = class {
399
+ constructor(nodes, frameId, iframeRef) {
400
+ this.nodes = nodes;
401
+ this.frameId = frameId;
402
+ this.iframeRef = iframeRef;
403
+ this.refMap = /* @__PURE__ */ new Map();
404
+ this.buildRefMap(nodes);
405
+ }
406
+ get nodeCount() {
407
+ return this.refMap.size;
408
+ }
409
+ *traverse() {
410
+ for (const vxNode of this.nodes) {
411
+ yield* traverseVxNode(vxNode, 0);
412
+ }
413
+ }
414
+ buildRefMap(nodes) {
415
+ for (const node of nodes) {
416
+ if (node.ref) {
417
+ this.refMap.set(node.ref, node);
418
+ }
419
+ this.buildRefMap(node.children ?? []);
420
+ }
421
+ }
422
+ hasRef(ref) {
423
+ const nref = normalizeRef(ref);
424
+ return this.refMap.has(nref);
425
+ }
426
+ findNode(ref) {
427
+ const nref = normalizeRef(ref);
428
+ return this.refMap.get(nref) ?? null;
429
+ }
430
+ render(options = {}) {
431
+ return this.nodes.map((node) => {
432
+ return renderVxNode(node, options);
433
+ }).join("\n");
434
+ }
435
+ highlight(options = {}) {
436
+ if (options.clearOverlay) {
437
+ clearOverlay();
438
+ }
439
+ const leafOnly = !options.includeAll;
440
+ const refs = this.collectRefs(leafOnly, options.filterRefs);
441
+ this.highlightRefs(refs, options);
442
+ }
443
+ highlightRefs(refs, options = {}) {
444
+ for (const ref of refs) {
445
+ const el = resolveDomNode(ref);
446
+ if (el instanceof Element) {
447
+ const vxNode = this.findNode(ref);
448
+ const isNew = vxNode?.isNew ?? false;
449
+ const color = options.useColors ? void 0 : isNew ? "#0a0" : "#060";
450
+ highlightEl(el, ref, color);
451
+ }
452
+ }
453
+ }
454
+ collectRefs(leafOnly = true, filterRefs) {
455
+ const refs = [];
456
+ for (const { vxNode } of this.traverse()) {
457
+ if (!vxNode.ref) {
458
+ continue;
459
+ }
460
+ if (leafOnly && isContainerNode(vxNode)) {
461
+ continue;
462
+ }
463
+ if (filterRefs && !filterRefs.includes(vxNode.ref)) {
464
+ continue;
465
+ }
466
+ refs.push(vxNode.ref);
467
+ }
468
+ return refs;
469
+ }
470
+ };
282
471
 
283
472
  // src/page/parser.ts
284
473
  var VX_NODE_SYMBOL = Symbol("vx:node");
@@ -351,41 +540,36 @@ var VX_KEEP_SELECTOR = "a, button, input, textarea, select, label, iframe, optio
351
540
  var VxTreeParser = class {
352
541
  constructor(options = {}) {
353
542
  this.options = options;
543
+ this.viewport = { width: 0, height: 0 };
544
+ this.vxNodes = [];
354
545
  this.probeElements = [];
355
546
  this.domRefMap = /* @__PURE__ */ new Map();
356
- const { startRef = 0 } = options;
547
+ }
548
+ async parse() {
357
549
  this.viewport = getViewportSize();
358
- this.counter = new Counter(startRef);
359
- if (options.probeViewport) {
550
+ if (this.options.probeViewport) {
360
551
  this.probeElements = probeViewport();
361
552
  }
362
- const vxRoot = this.parseDocument();
363
- this.refRange = [startRef, this.counter.current()];
553
+ const vxRoot = await this.parseNode(document.documentElement, null);
364
554
  this.vxNodes = this.pruneRecursive(vxRoot);
365
555
  }
366
- parseDocument() {
367
- return this.parseNode(document.documentElement, null);
368
- }
369
- getTree() {
370
- return new VxTreeView(this.vxNodes, this.refRange);
556
+ getTree(frameId, iframeRef) {
557
+ return new VxTreeView(this.vxNodes, frameId, iframeRef);
371
558
  }
372
559
  getNodes() {
373
560
  return this.vxNodes;
374
561
  }
375
- getRefRange() {
376
- return this.refRange;
377
- }
378
562
  getDomMap() {
379
563
  return this.domRefMap;
380
564
  }
381
- parseNode(node, parent) {
565
+ async parseNode(node, parent) {
382
566
  if (!node || node[VX_IGNORE_SYMBOL]) {
383
567
  return null;
384
568
  }
385
569
  if (node instanceof Text) {
386
570
  const textContent = normalizeText(node.textContent ?? "");
387
571
  if (textContent) {
388
- return this.makeNode(node, {
572
+ return await this.makeNode(node, {
389
573
  textContent,
390
574
  hasVisibleArea: parent?.hasVisibleArea,
391
575
  isOutsideViewport: parent?.isOutsideViewport,
@@ -398,11 +582,11 @@ var VxTreeParser = class {
398
582
  if (this.options.opaqueOverlays) {
399
583
  makeOverlaysOpaque(node);
400
584
  }
401
- return this.parseElement(node);
585
+ return await this.parseElement(node);
402
586
  }
403
587
  return null;
404
588
  }
405
- parseElement(el) {
589
+ async parseElement(el) {
406
590
  const skip = VX_IGNORE_TAGS.includes(el.tagName.toLowerCase()) || isHidden(el);
407
591
  if (skip) {
408
592
  this.clearRecursive(el);
@@ -411,7 +595,7 @@ var VxTreeParser = class {
411
595
  const parentEl = el.matches("option, optgroup") ? el.closest("select") ?? el : el;
412
596
  const rect = parentEl.getBoundingClientRect();
413
597
  const id = el.getAttribute("id") ?? "";
414
- const vxNode = this.makeNode(el, {
598
+ const vxNode = await this.makeNode(el, {
415
599
  tagName: el.tagName.toLowerCase(),
416
600
  id: isRandomIdentifier(id) ? void 0 : id,
417
601
  classList: Array.from(el.classList).filter((cls) => !isRandomIdentifier(cls)).slice(0, 4),
@@ -424,7 +608,13 @@ var VxTreeParser = class {
424
608
  isProbeHit: this.isProbeHit(parentEl),
425
609
  isKept: el.matches(VX_KEEP_SELECTOR)
426
610
  });
427
- const children = [...el.childNodes].map((child) => this.parseNode(child, vxNode)).filter((_) => _ != null);
611
+ const children = [];
612
+ for (const child of el.childNodes) {
613
+ const childNode = await this.parseNode(child, vxNode);
614
+ if (childNode != null) {
615
+ children.push(childNode);
616
+ }
617
+ }
428
618
  if (children.length === 1 && !children[0]?.tagName) {
429
619
  vxNode.textContent = normalizeText(children[0].textContent ?? "");
430
620
  } else {
@@ -432,15 +622,17 @@ var VxTreeParser = class {
432
622
  }
433
623
  return vxNode;
434
624
  }
435
- makeNode(node, spec) {
436
- const ref = this.counter.next();
625
+ async makeNode(node, spec) {
437
626
  const isNew = !node[VX_NODE_SYMBOL];
627
+ const ref = await this.createRef(node);
438
628
  const vxNode = {
439
629
  ...spec,
440
630
  ref,
441
631
  isNew
442
632
  };
443
- this.domRefMap.set(ref, node);
633
+ if (ref) {
634
+ this.domRefMap.set(ref, node);
635
+ }
444
636
  node[VX_NODE_SYMBOL] = vxNode;
445
637
  return vxNode;
446
638
  }
@@ -578,6 +770,13 @@ var VxTreeParser = class {
578
770
  }
579
771
  }
580
772
  }
773
+ async createRef(node) {
774
+ if (node instanceof Element) {
775
+ const sig = serializeElement(node);
776
+ const hash = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(sig).buffer);
777
+ return [...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, "0")).join("").substring(0, 8);
778
+ }
779
+ }
581
780
  };
582
781
 
583
782
  // src/page/overlay.ts
@@ -621,7 +820,7 @@ function getOverlayContainer() {
621
820
  }
622
821
 
623
822
  // src/page/highlight.ts
624
- function highlightEl(el, ref = 0, color) {
823
+ function highlightEl(el, ref, color) {
625
824
  if (!(el instanceof Element)) {
626
825
  return;
627
826
  }
@@ -657,191 +856,18 @@ function highlightEl(el, ref = 0, color) {
657
856
  label.style.transform = "translateY(50%)";
658
857
  label.textContent = String(ref);
659
858
  }
660
- function getRandomColor(index) {
859
+ function getRandomColor(ref) {
860
+ const index = ref.charCodeAt(0);
661
861
  const hue = index * 120 * 0.382 % 360;
662
862
  return `hsl(${hue}, 85%, 50%)`;
663
863
  }
664
864
 
665
- // src/page/render.ts
666
- function renderVxNode(scope, options = {}) {
667
- const buffer = [];
668
- for (const { vxNode, depth } of traverseVxNode(scope)) {
669
- if (options.skipNonInteractive && !vxNode.isInteractive) {
670
- continue;
671
- }
672
- const indent = options.skipNonInteractive ? "" : " ".repeat(depth);
673
- buffer.push(renderIndentedLine(indent, vxNode, options));
674
- }
675
- return buffer.join("\n");
676
- }
677
- function renderIndentedLine(indent, vxNode, options = {}) {
678
- const diffPrefix = options.renderDiff ? vxNode.isNew ? "+ " : " " : "";
679
- if (!vxNode.tagName) {
680
- return [diffPrefix, indent, vxNode.textContent].filter(Boolean).join("");
681
- }
682
- const tagLine = renderTagLine(vxNode, options);
683
- const htmlStyle = options.renderStyle === "html";
684
- return [
685
- diffPrefix,
686
- indent,
687
- tagLine,
688
- htmlStyle ? "" : " ",
689
- vxNode.textContent ?? ""
690
- ].join("");
691
- }
692
- function renderTagLine(vxNode, options) {
693
- const htmlStyle = options.renderStyle === "html";
694
- const components = [];
695
- if (options.renderTagNames && vxNode.tagName) {
696
- components.push(vxNode.tagName);
697
- }
698
- if (options.renderIds && vxNode.id) {
699
- if (htmlStyle) {
700
- components.push(`id="${vxNode.id}"`);
701
- } else {
702
- components.push(`#${vxNode.id}`);
703
- }
704
- }
705
- if (options.renderClassNames && vxNode.classList?.length) {
706
- if (htmlStyle) {
707
- components.push(`class="${vxNode.classList.join(" ")}"`);
708
- } else {
709
- components.push("." + vxNode.classList.join("."));
710
- }
711
- }
712
- if (options.renderRefs) {
713
- const isRenderRef = [
714
- options.renderRefs === "all",
715
- options.renderRefs === true && !isContainerNode(vxNode)
716
- ].some(Boolean);
717
- if (isRenderRef) {
718
- components.push(`[@${vxNode.ref}]`);
719
- }
720
- }
721
- const attrs = [];
722
- if (options.renderLabelAttrs) {
723
- for (const [attr, value] of Object.entries(vxNode.labelAttrs ?? {})) {
724
- attrs.push(`${attr}="${truncateAttrValue(value)}"`);
725
- }
726
- }
727
- if (options.renderValueAttrs) {
728
- for (const [attr, value] of Object.entries(vxNode.valueAttrs ?? {})) {
729
- attrs.push(`${attr}="${truncateAttrValue(value)}"`);
730
- }
731
- }
732
- if (options.renderSrcAttrs) {
733
- for (const [attr, value] of Object.entries(vxNode.srcAttrs ?? {})) {
734
- attrs.push(`${attr}="${truncateAttrValue(value)}"`);
735
- }
736
- }
737
- if (htmlStyle) {
738
- components.push(...attrs);
739
- } else {
740
- components.push(...attrs.map((attr) => `[${attr}]`));
741
- }
742
- return htmlStyle ? `<${components.join(" ")}>` : components.join("");
743
- }
744
-
745
- // src/page/snapshot.ts
746
- var VX_DOM_SYMBOL = Symbol("vx:dom");
747
- var VX_TREE_SYMBOL = Symbol("vx:tree");
748
- var VX_LAST_REFS_SYMBOL = Symbol("vx:lastRefs");
749
- function captureSnapshot(options = {}) {
750
- const parser = new VxTreeParser(options);
751
- const domMap = parser.getDomMap();
752
- const vxTree = parser.getTree();
753
- globalThis[VX_DOM_SYMBOL] = domMap;
754
- globalThis[VX_TREE_SYMBOL] = vxTree;
755
- return vxTree;
756
- }
757
- function getSnapshot() {
758
- const vxTree = globalThis[VX_TREE_SYMBOL];
759
- if (!vxTree) {
760
- throw new Error("[VX] Snapshot not found");
761
- }
762
- return vxTree;
763
- }
764
- function resolveDomNode(ref) {
765
- const domMap = globalThis[VX_DOM_SYMBOL];
766
- if (!domMap) {
767
- return null;
768
- }
769
- return domMap.get(ref) ?? null;
770
- }
771
-
772
- // src/page/tree.ts
773
- var VxTreeView = class {
774
- constructor(nodes, refRange) {
775
- this.nodes = nodes;
776
- this.refRange = refRange;
777
- this.refMap = /* @__PURE__ */ new Map();
778
- this.buildRefMap(nodes);
779
- }
780
- get nodeCount() {
781
- return this.refMap.size;
782
- }
783
- *traverse() {
784
- for (const vxNode of this.nodes) {
785
- yield* traverseVxNode(vxNode, 0);
786
- }
787
- }
788
- buildRefMap(nodes) {
789
- for (const node of nodes) {
790
- this.refMap.set(node.ref, node);
791
- this.buildRefMap(node.children ?? []);
792
- }
793
- }
794
- findNode(ref) {
795
- return this.refMap.get(ref) ?? null;
796
- }
797
- render(options = {}) {
798
- return this.nodes.map((node) => {
799
- return renderVxNode(node, options);
800
- }).join("\n");
801
- }
802
- highlight(options = {}) {
803
- if (options.clearOverlay) {
804
- clearOverlay();
805
- }
806
- const leafOnly = !options.includeAll;
807
- const refs = this.collectRefs(leafOnly, options.filterRefs);
808
- this.highlightRefs(refs, options);
809
- }
810
- highlightRefs(refs, options = {}) {
811
- for (const ref of refs) {
812
- const el = resolveDomNode(ref);
813
- if (el instanceof Element) {
814
- const vxNode = this.findNode(ref);
815
- const isNew = vxNode?.isNew ?? false;
816
- const color = options.useColors ? void 0 : isNew ? "#0a0" : "#060";
817
- highlightEl(el, ref, color);
818
- }
819
- }
820
- }
821
- collectRefs(leafOnly = true, filterRefs) {
822
- const refs = [];
823
- for (const { vxNode } of this.traverse()) {
824
- if (leafOnly && isContainerNode(vxNode)) {
825
- continue;
826
- }
827
- if (filterRefs && !filterRefs.includes(vxNode.ref)) {
828
- continue;
829
- }
830
- refs.push(vxNode.ref);
831
- }
832
- return refs;
833
- }
834
- };
835
-
836
- // src/page/frame.ts
865
+ // src/page/page.ts
837
866
  var VxPageView = class {
838
- constructor(vxFrames) {
839
- this.vxFrames = vxFrames;
840
- this.vxFrameMap = /* @__PURE__ */ new Map();
867
+ constructor(vxTrees) {
841
868
  this.vxTreeMap = /* @__PURE__ */ new Map();
842
- for (const frame of vxFrames) {
843
- this.vxFrameMap.set(frame.frameId, frame);
844
- this.vxTreeMap.set(frame.frameId, new VxTreeView(frame.nodes, frame.refRange));
869
+ for (const vxTree of vxTrees) {
870
+ this.vxTreeMap.set(vxTree.frameId, vxTree);
845
871
  }
846
872
  }
847
873
  get vxTrees() {
@@ -851,43 +877,28 @@ var VxPageView = class {
851
877
  return this.vxTrees.reduce((acc, vxTree) => acc + vxTree.nodeCount, 0);
852
878
  }
853
879
  findNodeByRef(ref) {
854
- const vxTree = this.findTreeByRef(ref);
855
- if (vxTree == null) {
880
+ const frame = this.findFrameByRef(ref);
881
+ if (frame == null) {
856
882
  return null;
857
883
  }
858
- return vxTree.findNode(ref);
884
+ return frame.findNode(ref);
859
885
  }
860
- findTreeByFrameId(frameId) {
886
+ findFrameById(frameId) {
861
887
  return this.vxTreeMap.get(frameId) ?? null;
862
888
  }
863
- findTreeByRef(ref) {
864
- const vxFrame = this.findFrameByRef(ref);
865
- if (vxFrame == null) {
866
- return null;
867
- }
868
- return this.vxTreeMap.get(vxFrame.frameId) ?? null;
869
- }
870
- findFrameByFrameId(frameId) {
871
- return this.vxFrameMap.get(frameId) ?? null;
872
- }
873
889
  findFrameByRef(ref) {
874
- const vxFrame = this.vxFrames.find(
875
- (frame) => ref >= frame.refRange[0] && ref <= frame.refRange[1]
876
- );
877
- if (!vxFrame) {
878
- return null;
879
- }
880
- return this.vxFrameMap.get(vxFrame.frameId) ?? null;
890
+ const frame = this.vxTrees.find((f) => f.hasRef(ref));
891
+ return frame ?? null;
881
892
  }
882
893
  getFrameByRef(ref) {
883
- const vxFrame = this.findFrameByRef(ref);
884
- if (vxFrame == null) {
894
+ const frame = this.findFrameByRef(ref);
895
+ if (frame == null) {
885
896
  throw new Error(`[VX] Frame not found for [ref=${ref}]`);
886
897
  }
887
- return vxFrame;
898
+ return frame;
888
899
  }
889
900
  findParentFrame(frameId) {
890
- const frame = this.findFrameByFrameId(frameId);
901
+ const frame = this.findFrameById(frameId);
891
902
  const iframeRef = frame?.iframeRef;
892
903
  if (iframeRef == null) {
893
904
  return null;
@@ -895,7 +906,7 @@ var VxPageView = class {
895
906
  return this.findFrameByRef(iframeRef);
896
907
  }
897
908
  isFrameShown(frameId) {
898
- const frame = this.findFrameByFrameId(frameId);
909
+ const frame = this.findFrameById(frameId);
899
910
  if (!frame) {
900
911
  return false;
901
912
  }
@@ -904,14 +915,12 @@ var VxPageView = class {
904
915
  if (parentFrame == null || iframeRef == null) {
905
916
  return true;
906
917
  }
907
- const vxTree = this.vxTreeMap.get(frameId);
908
- const existsInParent = !!vxTree?.findNode(iframeRef);
918
+ const existsInParent = !!parentFrame.findNode(iframeRef);
909
919
  return existsInParent ? this.isFrameShown(parentFrame.frameId) : false;
910
920
  }
911
921
  renderAll(options) {
912
- return this.vxFrames.map((frame) => {
913
- const vxTree = this.vxTreeMap.get(frame.frameId);
914
- const rendered = vxTree?.render(options);
922
+ return this.vxTrees.map((frame) => {
923
+ const rendered = frame?.render(options);
915
924
  return [
916
925
  `FRAME ${frame.frameId}${frame.iframeRef ? ` [@${frame.iframeRef}]` : ""}`,
917
926
  rendered
@@ -920,7 +929,6 @@ var VxPageView = class {
920
929
  }
921
930
  };
922
931
  export {
923
- Counter,
924
932
  INTERACTIVE_ROLES,
925
933
  INTERACTIVE_TAGS,
926
934
  PointSet,
@@ -943,6 +951,7 @@ export {
943
951
  containsSelector,
944
952
  escapeAttribute,
945
953
  fixZIndex,
954
+ getElementDepth,
946
955
  getNormalizedText,
947
956
  getOffsetTop,
948
957
  getOverlayContainer,
@@ -958,10 +967,12 @@ export {
958
967
  isRandomIdentifier,
959
968
  isRectInViewport,
960
969
  makeOverlaysOpaque,
970
+ normalizeRef,
961
971
  normalizeText,
962
972
  probeViewport,
963
973
  renderVxNode,
964
974
  resolveDomNode,
975
+ serializeElement,
965
976
  showPoint,
966
977
  traverseElements,
967
978
  traverseVxNode,
package/out/page/dom.d.ts CHANGED
@@ -19,3 +19,5 @@ export declare function isRectInViewport(rect: DOMRect, viewport: Viewport): boo
19
19
  export declare function makeOverlaysOpaque(el: HTMLElement): void;
20
20
  export declare function isRandomIdentifier(str: string): boolean;
21
21
  export declare function fixZIndex(el: HTMLElement): void;
22
+ export declare function getElementDepth(el: Element): number;
23
+ export declare function serializeElement(el: Element): string;
package/out/page/dom.js CHANGED
@@ -177,4 +177,22 @@ export function fixZIndex(el) {
177
177
  }
178
178
  }
179
179
  }
180
+ export function getElementDepth(el) {
181
+ let depth = 0;
182
+ while (el.parentElement) {
183
+ el = el.parentElement;
184
+ depth += 1;
185
+ }
186
+ return depth;
187
+ }
188
+ export function serializeElement(el) {
189
+ const sig = [];
190
+ const depth = getElementDepth(el);
191
+ sig.push(String(depth));
192
+ sig.push(el.tagName);
193
+ for (const attr of el.attributes) {
194
+ sig.push(`${attr.name}=${attr.value}`);
195
+ }
196
+ return sig.join('|');
197
+ }
180
198
  //# sourceMappingURL=dom.js.map