@ubio/webvision 2.6.5 → 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,197 +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
- const whitelistRefs = options.whitelistRefs ?? [];
669
- for (const { vxNode, depth } of traverseVxNode(scope)) {
670
- if (whitelistRefs.length > 0) {
671
- if (!whitelistRefs.includes(vxNode.ref)) {
672
- continue;
673
- }
674
- }
675
- if (options.skipNonInteractive && !vxNode.isInteractive) {
676
- continue;
677
- }
678
- const indent = options.skipNonInteractive ? "" : " ".repeat(depth);
679
- buffer.push(renderIndentedLine(indent, vxNode, options));
680
- }
681
- return buffer.join("\n");
682
- }
683
- function renderIndentedLine(indent, vxNode, options = {}) {
684
- const diffPrefix = options.renderDiff ? vxNode.isNew ? "+ " : " " : "";
685
- if (!vxNode.tagName) {
686
- return [diffPrefix, indent, vxNode.textContent].filter(Boolean).join("");
687
- }
688
- const tagLine = renderTagLine(vxNode, options);
689
- const htmlStyle = options.renderStyle === "html";
690
- return [
691
- diffPrefix,
692
- indent,
693
- tagLine,
694
- htmlStyle ? "" : " ",
695
- vxNode.textContent ?? ""
696
- ].join("");
697
- }
698
- function renderTagLine(vxNode, options) {
699
- const htmlStyle = options.renderStyle === "html";
700
- const components = [];
701
- if (options.renderTagNames && vxNode.tagName) {
702
- components.push(vxNode.tagName);
703
- }
704
- if (options.renderIds && vxNode.id) {
705
- if (htmlStyle) {
706
- components.push(`id="${vxNode.id}"`);
707
- } else {
708
- components.push(`#${vxNode.id}`);
709
- }
710
- }
711
- if (options.renderClassNames && vxNode.classList?.length) {
712
- if (htmlStyle) {
713
- components.push(`class="${vxNode.classList.join(" ")}"`);
714
- } else {
715
- components.push("." + vxNode.classList.join("."));
716
- }
717
- }
718
- if (options.renderRefs) {
719
- const isRenderRef = [
720
- options.renderRefs === "all",
721
- options.renderRefs === true && !isContainerNode(vxNode)
722
- ].some(Boolean);
723
- if (isRenderRef) {
724
- components.push(`[@${vxNode.ref}]`);
725
- }
726
- }
727
- const attrs = [];
728
- if (options.renderLabelAttrs) {
729
- for (const [attr, value] of Object.entries(vxNode.labelAttrs ?? {})) {
730
- attrs.push(`${attr}="${truncateAttrValue(value)}"`);
731
- }
732
- }
733
- if (options.renderValueAttrs) {
734
- for (const [attr, value] of Object.entries(vxNode.valueAttrs ?? {})) {
735
- attrs.push(`${attr}="${truncateAttrValue(value)}"`);
736
- }
737
- }
738
- if (options.renderSrcAttrs) {
739
- for (const [attr, value] of Object.entries(vxNode.srcAttrs ?? {})) {
740
- attrs.push(`${attr}="${truncateAttrValue(value)}"`);
741
- }
742
- }
743
- if (htmlStyle) {
744
- components.push(...attrs);
745
- } else {
746
- components.push(...attrs.map((attr) => `[${attr}]`));
747
- }
748
- return htmlStyle ? `<${components.join(" ")}>` : components.join("");
749
- }
750
-
751
- // src/page/snapshot.ts
752
- var VX_DOM_SYMBOL = Symbol("vx:dom");
753
- var VX_TREE_SYMBOL = Symbol("vx:tree");
754
- var VX_LAST_REFS_SYMBOL = Symbol("vx:lastRefs");
755
- function captureSnapshot(options = {}) {
756
- const parser = new VxTreeParser(options);
757
- const domMap = parser.getDomMap();
758
- const vxTree = parser.getTree();
759
- globalThis[VX_DOM_SYMBOL] = domMap;
760
- globalThis[VX_TREE_SYMBOL] = vxTree;
761
- return vxTree;
762
- }
763
- function getSnapshot() {
764
- const vxTree = globalThis[VX_TREE_SYMBOL];
765
- if (!vxTree) {
766
- throw new Error("[VX] Snapshot not found");
767
- }
768
- return vxTree;
769
- }
770
- function resolveDomNode(ref) {
771
- const domMap = globalThis[VX_DOM_SYMBOL];
772
- if (!domMap) {
773
- return null;
774
- }
775
- return domMap.get(ref) ?? null;
776
- }
777
-
778
- // src/page/tree.ts
779
- var VxTreeView = class {
780
- constructor(nodes, refRange) {
781
- this.nodes = nodes;
782
- this.refRange = refRange;
783
- this.refMap = /* @__PURE__ */ new Map();
784
- this.buildRefMap(nodes);
785
- }
786
- get nodeCount() {
787
- return this.refMap.size;
788
- }
789
- *traverse() {
790
- for (const vxNode of this.nodes) {
791
- yield* traverseVxNode(vxNode, 0);
792
- }
793
- }
794
- buildRefMap(nodes) {
795
- for (const node of nodes) {
796
- this.refMap.set(node.ref, node);
797
- this.buildRefMap(node.children ?? []);
798
- }
799
- }
800
- findNode(ref) {
801
- return this.refMap.get(ref) ?? null;
802
- }
803
- render(options = {}) {
804
- return this.nodes.map((node) => {
805
- return renderVxNode(node, options);
806
- }).join("\n");
807
- }
808
- highlight(options = {}) {
809
- if (options.clearOverlay) {
810
- clearOverlay();
811
- }
812
- const leafOnly = !options.includeAll;
813
- const refs = this.collectRefs(leafOnly, options.filterRefs);
814
- this.highlightRefs(refs, options);
815
- }
816
- highlightRefs(refs, options = {}) {
817
- for (const ref of refs) {
818
- const el = resolveDomNode(ref);
819
- if (el instanceof Element) {
820
- const vxNode = this.findNode(ref);
821
- const isNew = vxNode?.isNew ?? false;
822
- const color = options.useColors ? void 0 : isNew ? "#0a0" : "#060";
823
- highlightEl(el, ref, color);
824
- }
825
- }
826
- }
827
- collectRefs(leafOnly = true, filterRefs) {
828
- const refs = [];
829
- for (const { vxNode } of this.traverse()) {
830
- if (leafOnly && isContainerNode(vxNode)) {
831
- continue;
832
- }
833
- if (filterRefs && !filterRefs.includes(vxNode.ref)) {
834
- continue;
835
- }
836
- refs.push(vxNode.ref);
837
- }
838
- return refs;
839
- }
840
- };
841
-
842
- // src/page/frame.ts
860
+ // src/page/page.ts
843
861
  var VxPageView = class {
844
- constructor(vxFrames) {
845
- this.vxFrames = vxFrames;
846
- this.vxFrameMap = /* @__PURE__ */ new Map();
862
+ constructor(vxTrees) {
847
863
  this.vxTreeMap = /* @__PURE__ */ new Map();
848
- for (const frame of vxFrames) {
849
- this.vxFrameMap.set(frame.frameId, frame);
850
- this.vxTreeMap.set(frame.frameId, new VxTreeView(frame.nodes, frame.refRange));
864
+ for (const vxTree of vxTrees) {
865
+ this.vxTreeMap.set(vxTree.frameId, vxTree);
851
866
  }
852
867
  }
853
868
  get vxTrees() {
@@ -857,43 +872,28 @@ var VxPageView = class {
857
872
  return this.vxTrees.reduce((acc, vxTree) => acc + vxTree.nodeCount, 0);
858
873
  }
859
874
  findNodeByRef(ref) {
860
- const vxTree = this.findTreeByRef(ref);
861
- if (vxTree == null) {
875
+ const frame = this.findFrameByRef(ref);
876
+ if (frame == null) {
862
877
  return null;
863
878
  }
864
- return vxTree.findNode(ref);
879
+ return frame.findNode(ref);
865
880
  }
866
- findTreeByFrameId(frameId) {
881
+ findFrameById(frameId) {
867
882
  return this.vxTreeMap.get(frameId) ?? null;
868
883
  }
869
- findTreeByRef(ref) {
870
- const vxFrame = this.findFrameByRef(ref);
871
- if (vxFrame == null) {
872
- return null;
873
- }
874
- return this.vxTreeMap.get(vxFrame.frameId) ?? null;
875
- }
876
- findFrameByFrameId(frameId) {
877
- return this.vxFrameMap.get(frameId) ?? null;
878
- }
879
884
  findFrameByRef(ref) {
880
- const vxFrame = this.vxFrames.find(
881
- (frame) => ref >= frame.refRange[0] && ref <= frame.refRange[1]
882
- );
883
- if (!vxFrame) {
884
- return null;
885
- }
886
- return this.vxFrameMap.get(vxFrame.frameId) ?? null;
885
+ const frame = this.vxTrees.find((f) => f.hasRef(ref));
886
+ return frame ?? null;
887
887
  }
888
888
  getFrameByRef(ref) {
889
- const vxFrame = this.findFrameByRef(ref);
890
- if (vxFrame == null) {
889
+ const frame = this.findFrameByRef(ref);
890
+ if (frame == null) {
891
891
  throw new Error(`[VX] Frame not found for [ref=${ref}]`);
892
892
  }
893
- return vxFrame;
893
+ return frame;
894
894
  }
895
895
  findParentFrame(frameId) {
896
- const frame = this.findFrameByFrameId(frameId);
896
+ const frame = this.findFrameById(frameId);
897
897
  const iframeRef = frame?.iframeRef;
898
898
  if (iframeRef == null) {
899
899
  return null;
@@ -901,7 +901,7 @@ var VxPageView = class {
901
901
  return this.findFrameByRef(iframeRef);
902
902
  }
903
903
  isFrameShown(frameId) {
904
- const frame = this.findFrameByFrameId(frameId);
904
+ const frame = this.findFrameById(frameId);
905
905
  if (!frame) {
906
906
  return false;
907
907
  }
@@ -910,14 +910,12 @@ var VxPageView = class {
910
910
  if (parentFrame == null || iframeRef == null) {
911
911
  return true;
912
912
  }
913
- const vxTree = this.vxTreeMap.get(frameId);
914
- const existsInParent = !!vxTree?.findNode(iframeRef);
913
+ const existsInParent = !!parentFrame.findNode(iframeRef);
915
914
  return existsInParent ? this.isFrameShown(parentFrame.frameId) : false;
916
915
  }
917
916
  renderAll(options) {
918
- return this.vxFrames.map((frame) => {
919
- const vxTree = this.vxTreeMap.get(frame.frameId);
920
- const rendered = vxTree?.render(options);
917
+ return this.vxTrees.map((frame) => {
918
+ const rendered = frame?.render(options);
921
919
  return [
922
920
  `FRAME ${frame.frameId}${frame.iframeRef ? ` [@${frame.iframeRef}]` : ""}`,
923
921
  rendered
@@ -926,7 +924,6 @@ var VxPageView = class {
926
924
  }
927
925
  };
928
926
  export {
929
- Counter,
930
927
  INTERACTIVE_ROLES,
931
928
  INTERACTIVE_TAGS,
932
929
  PointSet,
@@ -949,6 +946,7 @@ export {
949
946
  containsSelector,
950
947
  escapeAttribute,
951
948
  fixZIndex,
949
+ getElementDepth,
952
950
  getNormalizedText,
953
951
  getOffsetTop,
954
952
  getOverlayContainer,
@@ -968,6 +966,7 @@ export {
968
966
  probeViewport,
969
967
  renderVxNode,
970
968
  resolveDomNode,
969
+ serializeElement,
971
970
  showPoint,
972
971
  traverseElements,
973
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