@ubio/webvision 2.6.6 → 3.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/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) {
@@ -280,6 +284,186 @@ function isObjectEmpty(obj) {
280
284
  return !Object.values(obj).some((value) => !!value);
281
285
  }
282
286
 
287
+ // src/page/render.ts
288
+ function renderVxNode(scope, options = {}) {
289
+ const buffer = [];
290
+ for (const { vxNode, depth } of traverseVxNode(scope)) {
291
+ if (options.skipNonInteractive && !vxNode.isInteractive) {
292
+ continue;
293
+ }
294
+ const indent = options.skipNonInteractive ? "" : " ".repeat(depth);
295
+ buffer.push(renderIndentedLine(indent, vxNode, options));
296
+ }
297
+ return buffer.join("\n");
298
+ }
299
+ function renderIndentedLine(indent, vxNode, options = {}) {
300
+ const diffPrefix = options.renderDiff ? vxNode.isNew ? "+ " : " " : "";
301
+ if (!vxNode.tagName) {
302
+ return [diffPrefix, indent, vxNode.textContent].filter(Boolean).join("");
303
+ }
304
+ const tagLine = renderTagLine(vxNode, options);
305
+ const htmlStyle = options.renderStyle === "html";
306
+ return [
307
+ diffPrefix,
308
+ indent,
309
+ tagLine,
310
+ htmlStyle ? "" : " ",
311
+ vxNode.textContent ?? ""
312
+ ].join("");
313
+ }
314
+ function renderTagLine(vxNode, options) {
315
+ const htmlStyle = options.renderStyle === "html";
316
+ const components = [];
317
+ if (options.renderTagNames && vxNode.tagName) {
318
+ components.push(vxNode.tagName);
319
+ }
320
+ if (options.renderIds && vxNode.id) {
321
+ if (htmlStyle) {
322
+ components.push(`id="${vxNode.id}"`);
323
+ } else {
324
+ components.push(`#${vxNode.id}`);
325
+ }
326
+ }
327
+ if (options.renderClassNames && vxNode.classList?.length) {
328
+ if (htmlStyle) {
329
+ components.push(`class="${vxNode.classList.join(" ")}"`);
330
+ } else {
331
+ components.push("." + vxNode.classList.join("."));
332
+ }
333
+ }
334
+ if (options.renderRefs) {
335
+ const isRenderRef = [
336
+ options.renderRefs === "all",
337
+ options.renderRefs === true && !isContainerNode(vxNode)
338
+ ].some(Boolean);
339
+ if (isRenderRef) {
340
+ components.push(`[@${vxNode.ref}]`);
341
+ }
342
+ }
343
+ const attrs = [];
344
+ if (options.renderLabelAttrs) {
345
+ for (const [attr, value] of Object.entries(vxNode.labelAttrs ?? {})) {
346
+ attrs.push(`${attr}="${truncateAttrValue(value)}"`);
347
+ }
348
+ }
349
+ if (options.renderValueAttrs) {
350
+ for (const [attr, value] of Object.entries(vxNode.valueAttrs ?? {})) {
351
+ attrs.push(`${attr}="${truncateAttrValue(value)}"`);
352
+ }
353
+ }
354
+ if (options.renderSrcAttrs) {
355
+ for (const [attr, value] of Object.entries(vxNode.srcAttrs ?? {})) {
356
+ attrs.push(`${attr}="${truncateAttrValue(value)}"`);
357
+ }
358
+ }
359
+ if (htmlStyle) {
360
+ components.push(...attrs);
361
+ } else {
362
+ components.push(...attrs.map((attr) => `[${attr}]`));
363
+ }
364
+ return htmlStyle ? `<${components.join(" ")}>` : components.join("");
365
+ }
366
+
367
+ // src/page/snapshot.ts
368
+ var VX_DOM_SYMBOL = Symbol("vx:dom");
369
+ var VX_TREE_SYMBOL = Symbol("vx:tree");
370
+ var VX_LAST_REFS_SYMBOL = Symbol("vx:lastRefs");
371
+ async function captureSnapshot(options = {}) {
372
+ const parser = new VxTreeParser(options);
373
+ const domMap = parser.getDomMap();
374
+ const vxTree = parser.getTree(options.frameId ?? "0", options.iframeRef);
375
+ globalThis[VX_DOM_SYMBOL] = domMap;
376
+ globalThis[VX_TREE_SYMBOL] = vxTree;
377
+ return vxTree;
378
+ }
379
+ function getSnapshot() {
380
+ const vxTree = globalThis[VX_TREE_SYMBOL];
381
+ if (!vxTree) {
382
+ throw new Error("[VX] Snapshot not found");
383
+ }
384
+ return vxTree;
385
+ }
386
+ function resolveDomNode(ref) {
387
+ const domMap = globalThis[VX_DOM_SYMBOL];
388
+ if (!domMap) {
389
+ return null;
390
+ }
391
+ return domMap.get(ref) ?? null;
392
+ }
393
+
394
+ // src/page/tree.ts
395
+ var VxTreeView = class {
396
+ constructor(nodes, frameId, iframeRef) {
397
+ this.nodes = nodes;
398
+ this.frameId = frameId;
399
+ this.iframeRef = iframeRef;
400
+ this.refMap = /* @__PURE__ */ new Map();
401
+ this.buildRefMap(nodes);
402
+ }
403
+ get nodeCount() {
404
+ return this.refMap.size;
405
+ }
406
+ *traverse() {
407
+ for (const vxNode of this.nodes) {
408
+ yield* traverseVxNode(vxNode, 0);
409
+ }
410
+ }
411
+ buildRefMap(nodes) {
412
+ for (const node of nodes) {
413
+ if (node.ref) {
414
+ this.refMap.set(node.ref, node);
415
+ }
416
+ this.buildRefMap(node.children ?? []);
417
+ }
418
+ }
419
+ hasRef(ref) {
420
+ return this.refMap.has(ref);
421
+ }
422
+ findNode(ref) {
423
+ return this.refMap.get(ref) ?? null;
424
+ }
425
+ render(options = {}) {
426
+ return this.nodes.map((node) => {
427
+ return renderVxNode(node, options);
428
+ }).join("\n");
429
+ }
430
+ highlight(options = {}) {
431
+ if (options.clearOverlay) {
432
+ clearOverlay();
433
+ }
434
+ const leafOnly = !options.includeAll;
435
+ const refs = this.collectRefs(leafOnly, options.filterRefs);
436
+ this.highlightRefs(refs, options);
437
+ }
438
+ highlightRefs(refs, options = {}) {
439
+ for (const ref of refs) {
440
+ const el = resolveDomNode(ref);
441
+ if (el instanceof Element) {
442
+ const vxNode = this.findNode(ref);
443
+ const isNew = vxNode?.isNew ?? false;
444
+ const color = options.useColors ? void 0 : isNew ? "#0a0" : "#060";
445
+ highlightEl(el, ref, color);
446
+ }
447
+ }
448
+ }
449
+ collectRefs(leafOnly = true, filterRefs) {
450
+ const refs = [];
451
+ for (const { vxNode } of this.traverse()) {
452
+ if (!vxNode.ref) {
453
+ continue;
454
+ }
455
+ if (leafOnly && isContainerNode(vxNode)) {
456
+ continue;
457
+ }
458
+ if (filterRefs && !filterRefs.includes(vxNode.ref)) {
459
+ continue;
460
+ }
461
+ refs.push(vxNode.ref);
462
+ }
463
+ return refs;
464
+ }
465
+ };
466
+
283
467
  // src/page/parser.ts
284
468
  var VX_NODE_SYMBOL = Symbol("vx:node");
285
469
  var VX_IGNORE_SYMBOL = Symbol("vx:ignore");
@@ -351,41 +535,36 @@ var VX_KEEP_SELECTOR = "a, button, input, textarea, select, label, iframe, optio
351
535
  var VxTreeParser = class {
352
536
  constructor(options = {}) {
353
537
  this.options = options;
538
+ this.viewport = { width: 0, height: 0 };
539
+ this.vxNodes = [];
354
540
  this.probeElements = [];
355
541
  this.domRefMap = /* @__PURE__ */ new Map();
356
- const { startRef = 0 } = options;
542
+ }
543
+ async parse() {
357
544
  this.viewport = getViewportSize();
358
- this.counter = new Counter(startRef);
359
- if (options.probeViewport) {
545
+ if (this.options.probeViewport) {
360
546
  this.probeElements = probeViewport();
361
547
  }
362
- const vxRoot = this.parseDocument();
363
- this.refRange = [startRef, this.counter.current()];
548
+ const vxRoot = await this.parseNode(document.documentElement, null);
364
549
  this.vxNodes = this.pruneRecursive(vxRoot);
365
550
  }
366
- parseDocument() {
367
- return this.parseNode(document.documentElement, null);
368
- }
369
- getTree() {
370
- return new VxTreeView(this.vxNodes, this.refRange);
551
+ getTree(frameId, iframeRef) {
552
+ return new VxTreeView(this.vxNodes, frameId, iframeRef);
371
553
  }
372
554
  getNodes() {
373
555
  return this.vxNodes;
374
556
  }
375
- getRefRange() {
376
- return this.refRange;
377
- }
378
557
  getDomMap() {
379
558
  return this.domRefMap;
380
559
  }
381
- parseNode(node, parent) {
560
+ async parseNode(node, parent) {
382
561
  if (!node || node[VX_IGNORE_SYMBOL]) {
383
562
  return null;
384
563
  }
385
564
  if (node instanceof Text) {
386
565
  const textContent = normalizeText(node.textContent ?? "");
387
566
  if (textContent) {
388
- return this.makeNode(node, {
567
+ return await this.makeNode(node, {
389
568
  textContent,
390
569
  hasVisibleArea: parent?.hasVisibleArea,
391
570
  isOutsideViewport: parent?.isOutsideViewport,
@@ -398,11 +577,11 @@ var VxTreeParser = class {
398
577
  if (this.options.opaqueOverlays) {
399
578
  makeOverlaysOpaque(node);
400
579
  }
401
- return this.parseElement(node);
580
+ return await this.parseElement(node);
402
581
  }
403
582
  return null;
404
583
  }
405
- parseElement(el) {
584
+ async parseElement(el) {
406
585
  const skip = VX_IGNORE_TAGS.includes(el.tagName.toLowerCase()) || isHidden(el);
407
586
  if (skip) {
408
587
  this.clearRecursive(el);
@@ -411,7 +590,7 @@ var VxTreeParser = class {
411
590
  const parentEl = el.matches("option, optgroup") ? el.closest("select") ?? el : el;
412
591
  const rect = parentEl.getBoundingClientRect();
413
592
  const id = el.getAttribute("id") ?? "";
414
- const vxNode = this.makeNode(el, {
593
+ const vxNode = await this.makeNode(el, {
415
594
  tagName: el.tagName.toLowerCase(),
416
595
  id: isRandomIdentifier(id) ? void 0 : id,
417
596
  classList: Array.from(el.classList).filter((cls) => !isRandomIdentifier(cls)).slice(0, 4),
@@ -424,7 +603,13 @@ var VxTreeParser = class {
424
603
  isProbeHit: this.isProbeHit(parentEl),
425
604
  isKept: el.matches(VX_KEEP_SELECTOR)
426
605
  });
427
- const children = [...el.childNodes].map((child) => this.parseNode(child, vxNode)).filter((_) => _ != null);
606
+ const children = [];
607
+ for (const child of el.childNodes) {
608
+ const childNode = await this.parseNode(child, vxNode);
609
+ if (childNode != null) {
610
+ children.push(childNode);
611
+ }
612
+ }
428
613
  if (children.length === 1 && !children[0]?.tagName) {
429
614
  vxNode.textContent = normalizeText(children[0].textContent ?? "");
430
615
  } else {
@@ -432,15 +617,17 @@ var VxTreeParser = class {
432
617
  }
433
618
  return vxNode;
434
619
  }
435
- makeNode(node, spec) {
436
- const ref = this.counter.next();
620
+ async makeNode(node, spec) {
437
621
  const isNew = !node[VX_NODE_SYMBOL];
622
+ const ref = await this.createRef(node);
438
623
  const vxNode = {
439
624
  ...spec,
440
625
  ref,
441
626
  isNew
442
627
  };
443
- this.domRefMap.set(ref, node);
628
+ if (ref) {
629
+ this.domRefMap.set(ref, node);
630
+ }
444
631
  node[VX_NODE_SYMBOL] = vxNode;
445
632
  return vxNode;
446
633
  }
@@ -578,6 +765,13 @@ var VxTreeParser = class {
578
765
  }
579
766
  }
580
767
  }
768
+ async createRef(node) {
769
+ if (node instanceof Element) {
770
+ const sig = serializeElement(node);
771
+ const hash = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(sig).buffer);
772
+ return [...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, "0")).join("").substring(0, 8);
773
+ }
774
+ }
581
775
  };
582
776
 
583
777
  // src/page/overlay.ts
@@ -621,7 +815,7 @@ function getOverlayContainer() {
621
815
  }
622
816
 
623
817
  // src/page/highlight.ts
624
- function highlightEl(el, ref = 0, color) {
818
+ function highlightEl(el, ref, color) {
625
819
  if (!(el instanceof Element)) {
626
820
  return;
627
821
  }
@@ -657,191 +851,18 @@ function highlightEl(el, ref = 0, color) {
657
851
  label.style.transform = "translateY(50%)";
658
852
  label.textContent = String(ref);
659
853
  }
660
- function getRandomColor(index) {
854
+ function getRandomColor(ref) {
855
+ const index = ref.charCodeAt(0);
661
856
  const hue = index * 120 * 0.382 % 360;
662
857
  return `hsl(${hue}, 85%, 50%)`;
663
858
  }
664
859
 
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
860
+ // src/page/page.ts
837
861
  var VxPageView = class {
838
- constructor(vxFrames) {
839
- this.vxFrames = vxFrames;
840
- this.vxFrameMap = /* @__PURE__ */ new Map();
862
+ constructor(vxTrees) {
841
863
  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));
864
+ for (const vxTree of vxTrees) {
865
+ this.vxTreeMap.set(vxTree.frameId, vxTree);
845
866
  }
846
867
  }
847
868
  get vxTrees() {
@@ -851,43 +872,28 @@ var VxPageView = class {
851
872
  return this.vxTrees.reduce((acc, vxTree) => acc + vxTree.nodeCount, 0);
852
873
  }
853
874
  findNodeByRef(ref) {
854
- const vxTree = this.findTreeByRef(ref);
855
- if (vxTree == null) {
875
+ const frame = this.findFrameByRef(ref);
876
+ if (frame == null) {
856
877
  return null;
857
878
  }
858
- return vxTree.findNode(ref);
879
+ return frame.findNode(ref);
859
880
  }
860
- findTreeByFrameId(frameId) {
881
+ findFrameById(frameId) {
861
882
  return this.vxTreeMap.get(frameId) ?? null;
862
883
  }
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
884
  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;
885
+ const frame = this.vxTrees.find((f) => f.hasRef(ref));
886
+ return frame ?? null;
881
887
  }
882
888
  getFrameByRef(ref) {
883
- const vxFrame = this.findFrameByRef(ref);
884
- if (vxFrame == null) {
889
+ const frame = this.findFrameByRef(ref);
890
+ if (frame == null) {
885
891
  throw new Error(`[VX] Frame not found for [ref=${ref}]`);
886
892
  }
887
- return vxFrame;
893
+ return frame;
888
894
  }
889
895
  findParentFrame(frameId) {
890
- const frame = this.findFrameByFrameId(frameId);
896
+ const frame = this.findFrameById(frameId);
891
897
  const iframeRef = frame?.iframeRef;
892
898
  if (iframeRef == null) {
893
899
  return null;
@@ -895,7 +901,7 @@ var VxPageView = class {
895
901
  return this.findFrameByRef(iframeRef);
896
902
  }
897
903
  isFrameShown(frameId) {
898
- const frame = this.findFrameByFrameId(frameId);
904
+ const frame = this.findFrameById(frameId);
899
905
  if (!frame) {
900
906
  return false;
901
907
  }
@@ -904,14 +910,12 @@ var VxPageView = class {
904
910
  if (parentFrame == null || iframeRef == null) {
905
911
  return true;
906
912
  }
907
- const vxTree = this.vxTreeMap.get(frameId);
908
- const existsInParent = !!vxTree?.findNode(iframeRef);
913
+ const existsInParent = !!parentFrame.findNode(iframeRef);
909
914
  return existsInParent ? this.isFrameShown(parentFrame.frameId) : false;
910
915
  }
911
916
  renderAll(options) {
912
- return this.vxFrames.map((frame) => {
913
- const vxTree = this.vxTreeMap.get(frame.frameId);
914
- const rendered = vxTree?.render(options);
917
+ return this.vxTrees.map((frame) => {
918
+ const rendered = frame?.render(options);
915
919
  return [
916
920
  `FRAME ${frame.frameId}${frame.iframeRef ? ` [@${frame.iframeRef}]` : ""}`,
917
921
  rendered
@@ -920,7 +924,6 @@ var VxPageView = class {
920
924
  }
921
925
  };
922
926
  export {
923
- Counter,
924
927
  INTERACTIVE_ROLES,
925
928
  INTERACTIVE_TAGS,
926
929
  PointSet,
@@ -943,6 +946,7 @@ export {
943
946
  containsSelector,
944
947
  escapeAttribute,
945
948
  fixZIndex,
949
+ getElementDepth,
946
950
  getNormalizedText,
947
951
  getOffsetTop,
948
952
  getOverlayContainer,
@@ -962,6 +966,7 @@ export {
962
966
  probeViewport,
963
967
  renderVxNode,
964
968
  resolveDomNode,
969
+ serializeElement,
965
970
  showPoint,
966
971
  traverseElements,
967
972
  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