@midscene/shared 0.17.2 → 0.17.3-beta-20250526031130.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/dist/es/constants.d.ts +1 -0
- package/dist/es/constants.js +1 -0
- package/dist/es/extractor-debug.js +92 -7
- package/dist/es/extractor.js +98 -35
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.js +1 -0
- package/dist/lib/extractor-debug.js +92 -7
- package/dist/lib/extractor.js +98 -35
- package/dist/script/htmlElement.js +97 -35
- package/dist/script/htmlElementDebug.js +90 -7
- package/dist/types/constants.d.ts +1 -0
- package/package.json +1 -1
- package/src/constants/index.ts +1 -0
- package/src/extractor/dom-util.ts +7 -0
- package/src/extractor/locator.ts +9 -46
- package/src/extractor/web-extractor.ts +94 -1
package/dist/es/constants.d.ts
CHANGED
package/dist/es/constants.js
CHANGED
|
@@ -7,6 +7,7 @@ var NodeType = /* @__PURE__ */ ((NodeType2) => {
|
|
|
7
7
|
NodeType2["CONTAINER"] = "CONTAINER Node";
|
|
8
8
|
NodeType2["FORM_ITEM"] = "FORM_ITEM Node";
|
|
9
9
|
NodeType2["BUTTON"] = "BUTTON Node";
|
|
10
|
+
NodeType2["A"] = "Anchor Node";
|
|
10
11
|
NodeType2["IMG"] = "IMG Node";
|
|
11
12
|
NodeType2["TEXT"] = "TEXT Node";
|
|
12
13
|
NodeType2["POSITION"] = "POSITION Node";
|
|
@@ -39,6 +39,9 @@ function isFormElement(node) {
|
|
|
39
39
|
function isButtonElement(node) {
|
|
40
40
|
return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";
|
|
41
41
|
}
|
|
42
|
+
function isAElement(node) {
|
|
43
|
+
return node instanceof HTMLElement && node.tagName.toLowerCase() === "a";
|
|
44
|
+
}
|
|
42
45
|
function isImgElement(node) {
|
|
43
46
|
if (!includeBaseElement(node) && node instanceof Element) {
|
|
44
47
|
const computedStyle = window.getComputedStyle(node);
|
|
@@ -89,7 +92,8 @@ function includeBaseElement(node) {
|
|
|
89
92
|
"textarea",
|
|
90
93
|
"select",
|
|
91
94
|
"option",
|
|
92
|
-
"img"
|
|
95
|
+
"img",
|
|
96
|
+
"a"
|
|
93
97
|
];
|
|
94
98
|
for (const tagName of includeList) {
|
|
95
99
|
const element = node.querySelectorAll(tagName);
|
|
@@ -471,10 +475,20 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
471
475
|
return elementInfo;
|
|
472
476
|
}
|
|
473
477
|
if (isButtonElement(node)) {
|
|
478
|
+
const rect2 = mergeElementAndChildrenRects(
|
|
479
|
+
node,
|
|
480
|
+
currentWindow,
|
|
481
|
+
currentDocument,
|
|
482
|
+
baseZoom,
|
|
483
|
+
visibleOnly
|
|
484
|
+
);
|
|
485
|
+
if (!rect2) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
474
488
|
const attributes = getNodeAttributes(node, currentWindow);
|
|
475
489
|
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
476
490
|
const content = node.innerText || pseudo.before || pseudo.after || "";
|
|
477
|
-
const nodeHashId = midsceneGenerateHash(node, content,
|
|
491
|
+
const nodeHashId = midsceneGenerateHash(node, content, rect2);
|
|
478
492
|
const selector = setDataForNode(node, nodeHashId, false, currentWindow);
|
|
479
493
|
const elementInfo = {
|
|
480
494
|
id: nodeHashId,
|
|
@@ -488,12 +502,12 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
488
502
|
nodeType: "BUTTON Node" /* BUTTON */
|
|
489
503
|
},
|
|
490
504
|
content,
|
|
491
|
-
rect,
|
|
505
|
+
rect: rect2,
|
|
492
506
|
center: [
|
|
493
|
-
Math.round(
|
|
494
|
-
Math.round(
|
|
507
|
+
Math.round(rect2.left + rect2.width / 2),
|
|
508
|
+
Math.round(rect2.top + rect2.height / 2)
|
|
495
509
|
],
|
|
496
|
-
zoom:
|
|
510
|
+
zoom: rect2.zoom
|
|
497
511
|
};
|
|
498
512
|
return elementInfo;
|
|
499
513
|
}
|
|
@@ -558,6 +572,33 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
558
572
|
};
|
|
559
573
|
return elementInfo;
|
|
560
574
|
}
|
|
575
|
+
if (isAElement(node)) {
|
|
576
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
577
|
+
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
578
|
+
const content = node.innerText || pseudo.before || pseudo.after || "";
|
|
579
|
+
const nodeHashId = midsceneGenerateHash(node, content, rect);
|
|
580
|
+
const selector = setDataForNode(node, nodeHashId, false, currentWindow);
|
|
581
|
+
const elementInfo = {
|
|
582
|
+
id: nodeHashId,
|
|
583
|
+
indexId: indexId++,
|
|
584
|
+
nodeHashId,
|
|
585
|
+
nodeType: "Anchor Node" /* A */,
|
|
586
|
+
locator: selector,
|
|
587
|
+
attributes: {
|
|
588
|
+
...attributes,
|
|
589
|
+
htmlTagName: tagNameOfNode(node),
|
|
590
|
+
nodeType: "Anchor Node" /* A */
|
|
591
|
+
},
|
|
592
|
+
content,
|
|
593
|
+
rect,
|
|
594
|
+
center: [
|
|
595
|
+
Math.round(rect.left + rect.width / 2),
|
|
596
|
+
Math.round(rect.top + rect.height / 2)
|
|
597
|
+
],
|
|
598
|
+
zoom: rect.zoom
|
|
599
|
+
};
|
|
600
|
+
return elementInfo;
|
|
601
|
+
}
|
|
561
602
|
if (isContainerElement(node)) {
|
|
562
603
|
const attributes = getNodeAttributes(node, currentWindow);
|
|
563
604
|
const nodeHashId = midsceneGenerateHash(node, "", rect);
|
|
@@ -628,7 +669,7 @@ function extractTreeNode(initNode, debugMode2 = false) {
|
|
|
628
669
|
node: elementInfo,
|
|
629
670
|
children: []
|
|
630
671
|
};
|
|
631
|
-
if (elementInfo?.nodeType === "BUTTON Node" /* BUTTON */ || elementInfo?.nodeType === "IMG Node" /* IMG */ || elementInfo?.nodeType === "TEXT Node" /* TEXT */ || elementInfo?.nodeType === "FORM_ITEM Node" /* FORM_ITEM */ || elementInfo?.nodeType === "CONTAINER Node" /* CONTAINER */) {
|
|
672
|
+
if (elementInfo?.nodeType === "BUTTON Node" /* BUTTON */ || elementInfo?.nodeType === "IMG Node" /* IMG */ || elementInfo?.nodeType === "TEXT Node" /* TEXT */ || elementInfo?.nodeType === "Anchor Node" /* A */ || elementInfo?.nodeType === "FORM_ITEM Node" /* FORM_ITEM */ || elementInfo?.nodeType === "CONTAINER Node" /* CONTAINER */) {
|
|
632
673
|
return nodeInfo;
|
|
633
674
|
}
|
|
634
675
|
const rect = getRect(node, baseZoom, currentWindow);
|
|
@@ -683,6 +724,50 @@ function extractTreeNode(initNode, debugMode2 = false) {
|
|
|
683
724
|
children: topChildren
|
|
684
725
|
};
|
|
685
726
|
}
|
|
727
|
+
function mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom = 1, visibleOnly = true) {
|
|
728
|
+
const selfRect = elementRect(
|
|
729
|
+
node,
|
|
730
|
+
currentWindow,
|
|
731
|
+
currentDocument,
|
|
732
|
+
baseZoom,
|
|
733
|
+
visibleOnly
|
|
734
|
+
);
|
|
735
|
+
if (!selfRect)
|
|
736
|
+
return null;
|
|
737
|
+
let minLeft = selfRect.left;
|
|
738
|
+
let minTop = selfRect.top;
|
|
739
|
+
let maxRight = selfRect.left + selfRect.width;
|
|
740
|
+
let maxBottom = selfRect.top + selfRect.height;
|
|
741
|
+
function traverse(child) {
|
|
742
|
+
for (let i = 0; i < child.childNodes.length; i++) {
|
|
743
|
+
const sub = child.childNodes[i];
|
|
744
|
+
if (sub.nodeType === 1) {
|
|
745
|
+
const rect = elementRect(
|
|
746
|
+
sub,
|
|
747
|
+
currentWindow,
|
|
748
|
+
currentDocument,
|
|
749
|
+
baseZoom,
|
|
750
|
+
visibleOnly
|
|
751
|
+
);
|
|
752
|
+
if (rect) {
|
|
753
|
+
minLeft = Math.min(minLeft, rect.left);
|
|
754
|
+
minTop = Math.min(minTop, rect.top);
|
|
755
|
+
maxRight = Math.max(maxRight, rect.left + rect.width);
|
|
756
|
+
maxBottom = Math.max(maxBottom, rect.top + rect.height);
|
|
757
|
+
}
|
|
758
|
+
traverse(sub);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
traverse(node);
|
|
763
|
+
return {
|
|
764
|
+
...selfRect,
|
|
765
|
+
left: minLeft,
|
|
766
|
+
top: minTop,
|
|
767
|
+
width: maxRight - minLeft,
|
|
768
|
+
height: maxBottom - minTop
|
|
769
|
+
};
|
|
770
|
+
}
|
|
686
771
|
|
|
687
772
|
// src/extractor/debug.ts
|
|
688
773
|
console.log(extractTextWithPosition(document.body, true));
|
package/dist/es/extractor.js
CHANGED
|
@@ -160,6 +160,9 @@ function isFormElement(node) {
|
|
|
160
160
|
function isButtonElement(node) {
|
|
161
161
|
return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";
|
|
162
162
|
}
|
|
163
|
+
function isAElement(node) {
|
|
164
|
+
return node instanceof HTMLElement && node.tagName.toLowerCase() === "a";
|
|
165
|
+
}
|
|
163
166
|
function isImgElement(node) {
|
|
164
167
|
if (!includeBaseElement(node) && node instanceof Element) {
|
|
165
168
|
const computedStyle = window.getComputedStyle(node);
|
|
@@ -210,7 +213,8 @@ function includeBaseElement(node) {
|
|
|
210
213
|
"textarea",
|
|
211
214
|
"select",
|
|
212
215
|
"option",
|
|
213
|
-
"img"
|
|
216
|
+
"img",
|
|
217
|
+
"a"
|
|
214
218
|
];
|
|
215
219
|
for (const tagName of includeList) {
|
|
216
220
|
const element = node.querySelectorAll(tagName);
|
|
@@ -599,10 +603,20 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
599
603
|
return elementInfo;
|
|
600
604
|
}
|
|
601
605
|
if (isButtonElement(node)) {
|
|
606
|
+
const rect2 = mergeElementAndChildrenRects(
|
|
607
|
+
node,
|
|
608
|
+
currentWindow,
|
|
609
|
+
currentDocument,
|
|
610
|
+
baseZoom,
|
|
611
|
+
visibleOnly
|
|
612
|
+
);
|
|
613
|
+
if (!rect2) {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
602
616
|
const attributes = getNodeAttributes(node, currentWindow);
|
|
603
617
|
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
604
618
|
const content = node.innerText || pseudo.before || pseudo.after || "";
|
|
605
|
-
const nodeHashId = midsceneGenerateHash(node, content,
|
|
619
|
+
const nodeHashId = midsceneGenerateHash(node, content, rect2);
|
|
606
620
|
const selector = setDataForNode(node, nodeHashId, false, currentWindow);
|
|
607
621
|
const elementInfo = {
|
|
608
622
|
id: nodeHashId,
|
|
@@ -616,12 +630,12 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
616
630
|
nodeType: "BUTTON Node" /* BUTTON */
|
|
617
631
|
},
|
|
618
632
|
content,
|
|
619
|
-
rect,
|
|
633
|
+
rect: rect2,
|
|
620
634
|
center: [
|
|
621
|
-
Math.round(
|
|
622
|
-
Math.round(
|
|
635
|
+
Math.round(rect2.left + rect2.width / 2),
|
|
636
|
+
Math.round(rect2.top + rect2.height / 2)
|
|
623
637
|
],
|
|
624
|
-
zoom:
|
|
638
|
+
zoom: rect2.zoom
|
|
625
639
|
};
|
|
626
640
|
return elementInfo;
|
|
627
641
|
}
|
|
@@ -686,6 +700,33 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
686
700
|
};
|
|
687
701
|
return elementInfo;
|
|
688
702
|
}
|
|
703
|
+
if (isAElement(node)) {
|
|
704
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
705
|
+
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
706
|
+
const content = node.innerText || pseudo.before || pseudo.after || "";
|
|
707
|
+
const nodeHashId = midsceneGenerateHash(node, content, rect);
|
|
708
|
+
const selector = setDataForNode(node, nodeHashId, false, currentWindow);
|
|
709
|
+
const elementInfo = {
|
|
710
|
+
id: nodeHashId,
|
|
711
|
+
indexId: indexId++,
|
|
712
|
+
nodeHashId,
|
|
713
|
+
nodeType: "Anchor Node" /* A */,
|
|
714
|
+
locator: selector,
|
|
715
|
+
attributes: {
|
|
716
|
+
...attributes,
|
|
717
|
+
htmlTagName: tagNameOfNode(node),
|
|
718
|
+
nodeType: "Anchor Node" /* A */
|
|
719
|
+
},
|
|
720
|
+
content,
|
|
721
|
+
rect,
|
|
722
|
+
center: [
|
|
723
|
+
Math.round(rect.left + rect.width / 2),
|
|
724
|
+
Math.round(rect.top + rect.height / 2)
|
|
725
|
+
],
|
|
726
|
+
zoom: rect.zoom
|
|
727
|
+
};
|
|
728
|
+
return elementInfo;
|
|
729
|
+
}
|
|
689
730
|
if (isContainerElement(node)) {
|
|
690
731
|
const attributes = getNodeAttributes(node, currentWindow);
|
|
691
732
|
const nodeHashId = midsceneGenerateHash(node, "", rect);
|
|
@@ -760,7 +801,7 @@ function extractTreeNode(initNode, debugMode2 = false) {
|
|
|
760
801
|
node: elementInfo,
|
|
761
802
|
children: []
|
|
762
803
|
};
|
|
763
|
-
if (elementInfo?.nodeType === "BUTTON Node" /* BUTTON */ || elementInfo?.nodeType === "IMG Node" /* IMG */ || elementInfo?.nodeType === "TEXT Node" /* TEXT */ || elementInfo?.nodeType === "FORM_ITEM Node" /* FORM_ITEM */ || elementInfo?.nodeType === "CONTAINER Node" /* CONTAINER */) {
|
|
804
|
+
if (elementInfo?.nodeType === "BUTTON Node" /* BUTTON */ || elementInfo?.nodeType === "IMG Node" /* IMG */ || elementInfo?.nodeType === "TEXT Node" /* TEXT */ || elementInfo?.nodeType === "Anchor Node" /* A */ || elementInfo?.nodeType === "FORM_ITEM Node" /* FORM_ITEM */ || elementInfo?.nodeType === "CONTAINER Node" /* CONTAINER */) {
|
|
764
805
|
return nodeInfo;
|
|
765
806
|
}
|
|
766
807
|
const rect = getRect(node, baseZoom, currentWindow);
|
|
@@ -815,6 +856,50 @@ function extractTreeNode(initNode, debugMode2 = false) {
|
|
|
815
856
|
children: topChildren
|
|
816
857
|
};
|
|
817
858
|
}
|
|
859
|
+
function mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom = 1, visibleOnly = true) {
|
|
860
|
+
const selfRect = elementRect(
|
|
861
|
+
node,
|
|
862
|
+
currentWindow,
|
|
863
|
+
currentDocument,
|
|
864
|
+
baseZoom,
|
|
865
|
+
visibleOnly
|
|
866
|
+
);
|
|
867
|
+
if (!selfRect)
|
|
868
|
+
return null;
|
|
869
|
+
let minLeft = selfRect.left;
|
|
870
|
+
let minTop = selfRect.top;
|
|
871
|
+
let maxRight = selfRect.left + selfRect.width;
|
|
872
|
+
let maxBottom = selfRect.top + selfRect.height;
|
|
873
|
+
function traverse(child) {
|
|
874
|
+
for (let i = 0; i < child.childNodes.length; i++) {
|
|
875
|
+
const sub = child.childNodes[i];
|
|
876
|
+
if (sub.nodeType === 1) {
|
|
877
|
+
const rect = elementRect(
|
|
878
|
+
sub,
|
|
879
|
+
currentWindow,
|
|
880
|
+
currentDocument,
|
|
881
|
+
baseZoom,
|
|
882
|
+
visibleOnly
|
|
883
|
+
);
|
|
884
|
+
if (rect) {
|
|
885
|
+
minLeft = Math.min(minLeft, rect.left);
|
|
886
|
+
minTop = Math.min(minTop, rect.top);
|
|
887
|
+
maxRight = Math.max(maxRight, rect.left + rect.width);
|
|
888
|
+
maxBottom = Math.max(maxBottom, rect.top + rect.height);
|
|
889
|
+
}
|
|
890
|
+
traverse(sub);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
traverse(node);
|
|
895
|
+
return {
|
|
896
|
+
...selfRect,
|
|
897
|
+
left: minLeft,
|
|
898
|
+
top: minTop,
|
|
899
|
+
width: maxRight - minLeft,
|
|
900
|
+
height: maxBottom - minTop
|
|
901
|
+
};
|
|
902
|
+
}
|
|
818
903
|
|
|
819
904
|
// src/extractor/locator.ts
|
|
820
905
|
var getElementIndex = (element) => {
|
|
@@ -828,16 +913,6 @@ var getElementIndex = (element) => {
|
|
|
828
913
|
}
|
|
829
914
|
return index;
|
|
830
915
|
};
|
|
831
|
-
var findFirstAncestorWithId = (element) => {
|
|
832
|
-
let current = element;
|
|
833
|
-
while (current?.parentElement) {
|
|
834
|
-
if (current.id) {
|
|
835
|
-
return current;
|
|
836
|
-
}
|
|
837
|
-
current = current.parentElement;
|
|
838
|
-
}
|
|
839
|
-
return null;
|
|
840
|
-
};
|
|
841
916
|
var getTextNodeIndex = (textNode) => {
|
|
842
917
|
let index = 1;
|
|
843
918
|
let current = textNode.previousSibling;
|
|
@@ -855,6 +930,10 @@ var getElementXPath = (element) => {
|
|
|
855
930
|
if (parentNode && parentNode.nodeType === Node.ELEMENT_NODE) {
|
|
856
931
|
const parentXPath = getElementXPath(parentNode);
|
|
857
932
|
const textIndex = getTextNodeIndex(element);
|
|
933
|
+
const textContent = element.textContent?.trim();
|
|
934
|
+
if (textContent) {
|
|
935
|
+
return `${parentXPath}/text()[${textIndex}][normalize-space()="${textContent}"]`;
|
|
936
|
+
}
|
|
858
937
|
return `${parentXPath}/text()[${textIndex}]`;
|
|
859
938
|
}
|
|
860
939
|
return "";
|
|
@@ -868,22 +947,6 @@ var getElementXPath = (element) => {
|
|
|
868
947
|
if (el === document.body) {
|
|
869
948
|
return "/html/body";
|
|
870
949
|
}
|
|
871
|
-
if (el.id) {
|
|
872
|
-
return `//*[@id="${el.id}"]`;
|
|
873
|
-
}
|
|
874
|
-
const ancestorWithId = findFirstAncestorWithId(el);
|
|
875
|
-
if (ancestorWithId) {
|
|
876
|
-
const ancestorPath = `//*[@id="${ancestorWithId.id}"]`;
|
|
877
|
-
let current = el;
|
|
878
|
-
const pathParts = [];
|
|
879
|
-
while (current && current !== ancestorWithId) {
|
|
880
|
-
const index2 = getElementIndex(current);
|
|
881
|
-
const tagName2 = current.nodeName.toLowerCase();
|
|
882
|
-
pathParts.unshift(`${tagName2}[${index2}]`);
|
|
883
|
-
current = current.parentElement;
|
|
884
|
-
}
|
|
885
|
-
return pathParts.length > 0 ? `${ancestorPath}/${pathParts.join("/")}` : ancestorPath;
|
|
886
|
-
}
|
|
887
950
|
if (!el.parentNode) {
|
|
888
951
|
return `/${el.nodeName.toLowerCase()}`;
|
|
889
952
|
}
|
|
@@ -898,8 +961,8 @@ var getElementXPath = (element) => {
|
|
|
898
961
|
function generateXPaths(node) {
|
|
899
962
|
if (!node)
|
|
900
963
|
return [];
|
|
901
|
-
const
|
|
902
|
-
return [
|
|
964
|
+
const fullXPath = getElementXPath(node);
|
|
965
|
+
return [fullXPath];
|
|
903
966
|
}
|
|
904
967
|
function getXpathsById(id) {
|
|
905
968
|
const node = getNodeFromCacheList(id);
|
package/dist/lib/constants.d.ts
CHANGED
package/dist/lib/constants.js
CHANGED
|
@@ -41,6 +41,7 @@ var NodeType = /* @__PURE__ */ ((NodeType2) => {
|
|
|
41
41
|
NodeType2["CONTAINER"] = "CONTAINER Node";
|
|
42
42
|
NodeType2["FORM_ITEM"] = "FORM_ITEM Node";
|
|
43
43
|
NodeType2["BUTTON"] = "BUTTON Node";
|
|
44
|
+
NodeType2["A"] = "Anchor Node";
|
|
44
45
|
NodeType2["IMG"] = "IMG Node";
|
|
45
46
|
NodeType2["TEXT"] = "TEXT Node";
|
|
46
47
|
NodeType2["POSITION"] = "POSITION Node";
|
|
@@ -41,6 +41,9 @@ function isFormElement(node) {
|
|
|
41
41
|
function isButtonElement(node) {
|
|
42
42
|
return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";
|
|
43
43
|
}
|
|
44
|
+
function isAElement(node) {
|
|
45
|
+
return node instanceof HTMLElement && node.tagName.toLowerCase() === "a";
|
|
46
|
+
}
|
|
44
47
|
function isImgElement(node) {
|
|
45
48
|
if (!includeBaseElement(node) && node instanceof Element) {
|
|
46
49
|
const computedStyle = window.getComputedStyle(node);
|
|
@@ -91,7 +94,8 @@ function includeBaseElement(node) {
|
|
|
91
94
|
"textarea",
|
|
92
95
|
"select",
|
|
93
96
|
"option",
|
|
94
|
-
"img"
|
|
97
|
+
"img",
|
|
98
|
+
"a"
|
|
95
99
|
];
|
|
96
100
|
for (const tagName of includeList) {
|
|
97
101
|
const element = node.querySelectorAll(tagName);
|
|
@@ -473,10 +477,20 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
473
477
|
return elementInfo;
|
|
474
478
|
}
|
|
475
479
|
if (isButtonElement(node)) {
|
|
480
|
+
const rect2 = mergeElementAndChildrenRects(
|
|
481
|
+
node,
|
|
482
|
+
currentWindow,
|
|
483
|
+
currentDocument,
|
|
484
|
+
baseZoom,
|
|
485
|
+
visibleOnly
|
|
486
|
+
);
|
|
487
|
+
if (!rect2) {
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
476
490
|
const attributes = getNodeAttributes(node, currentWindow);
|
|
477
491
|
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
478
492
|
const content = node.innerText || pseudo.before || pseudo.after || "";
|
|
479
|
-
const nodeHashId = midsceneGenerateHash(node, content,
|
|
493
|
+
const nodeHashId = midsceneGenerateHash(node, content, rect2);
|
|
480
494
|
const selector = setDataForNode(node, nodeHashId, false, currentWindow);
|
|
481
495
|
const elementInfo = {
|
|
482
496
|
id: nodeHashId,
|
|
@@ -490,12 +504,12 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
490
504
|
nodeType: "BUTTON Node" /* BUTTON */
|
|
491
505
|
},
|
|
492
506
|
content,
|
|
493
|
-
rect,
|
|
507
|
+
rect: rect2,
|
|
494
508
|
center: [
|
|
495
|
-
Math.round(
|
|
496
|
-
Math.round(
|
|
509
|
+
Math.round(rect2.left + rect2.width / 2),
|
|
510
|
+
Math.round(rect2.top + rect2.height / 2)
|
|
497
511
|
],
|
|
498
|
-
zoom:
|
|
512
|
+
zoom: rect2.zoom
|
|
499
513
|
};
|
|
500
514
|
return elementInfo;
|
|
501
515
|
}
|
|
@@ -560,6 +574,33 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
|
|
|
560
574
|
};
|
|
561
575
|
return elementInfo;
|
|
562
576
|
}
|
|
577
|
+
if (isAElement(node)) {
|
|
578
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
579
|
+
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
580
|
+
const content = node.innerText || pseudo.before || pseudo.after || "";
|
|
581
|
+
const nodeHashId = midsceneGenerateHash(node, content, rect);
|
|
582
|
+
const selector = setDataForNode(node, nodeHashId, false, currentWindow);
|
|
583
|
+
const elementInfo = {
|
|
584
|
+
id: nodeHashId,
|
|
585
|
+
indexId: indexId++,
|
|
586
|
+
nodeHashId,
|
|
587
|
+
nodeType: "Anchor Node" /* A */,
|
|
588
|
+
locator: selector,
|
|
589
|
+
attributes: {
|
|
590
|
+
...attributes,
|
|
591
|
+
htmlTagName: tagNameOfNode(node),
|
|
592
|
+
nodeType: "Anchor Node" /* A */
|
|
593
|
+
},
|
|
594
|
+
content,
|
|
595
|
+
rect,
|
|
596
|
+
center: [
|
|
597
|
+
Math.round(rect.left + rect.width / 2),
|
|
598
|
+
Math.round(rect.top + rect.height / 2)
|
|
599
|
+
],
|
|
600
|
+
zoom: rect.zoom
|
|
601
|
+
};
|
|
602
|
+
return elementInfo;
|
|
603
|
+
}
|
|
563
604
|
if (isContainerElement(node)) {
|
|
564
605
|
const attributes = getNodeAttributes(node, currentWindow);
|
|
565
606
|
const nodeHashId = midsceneGenerateHash(node, "", rect);
|
|
@@ -630,7 +671,7 @@ function extractTreeNode(initNode, debugMode2 = false) {
|
|
|
630
671
|
node: elementInfo,
|
|
631
672
|
children: []
|
|
632
673
|
};
|
|
633
|
-
if (elementInfo?.nodeType === "BUTTON Node" /* BUTTON */ || elementInfo?.nodeType === "IMG Node" /* IMG */ || elementInfo?.nodeType === "TEXT Node" /* TEXT */ || elementInfo?.nodeType === "FORM_ITEM Node" /* FORM_ITEM */ || elementInfo?.nodeType === "CONTAINER Node" /* CONTAINER */) {
|
|
674
|
+
if (elementInfo?.nodeType === "BUTTON Node" /* BUTTON */ || elementInfo?.nodeType === "IMG Node" /* IMG */ || elementInfo?.nodeType === "TEXT Node" /* TEXT */ || elementInfo?.nodeType === "Anchor Node" /* A */ || elementInfo?.nodeType === "FORM_ITEM Node" /* FORM_ITEM */ || elementInfo?.nodeType === "CONTAINER Node" /* CONTAINER */) {
|
|
634
675
|
return nodeInfo;
|
|
635
676
|
}
|
|
636
677
|
const rect = getRect(node, baseZoom, currentWindow);
|
|
@@ -685,6 +726,50 @@ function extractTreeNode(initNode, debugMode2 = false) {
|
|
|
685
726
|
children: topChildren
|
|
686
727
|
};
|
|
687
728
|
}
|
|
729
|
+
function mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom = 1, visibleOnly = true) {
|
|
730
|
+
const selfRect = elementRect(
|
|
731
|
+
node,
|
|
732
|
+
currentWindow,
|
|
733
|
+
currentDocument,
|
|
734
|
+
baseZoom,
|
|
735
|
+
visibleOnly
|
|
736
|
+
);
|
|
737
|
+
if (!selfRect)
|
|
738
|
+
return null;
|
|
739
|
+
let minLeft = selfRect.left;
|
|
740
|
+
let minTop = selfRect.top;
|
|
741
|
+
let maxRight = selfRect.left + selfRect.width;
|
|
742
|
+
let maxBottom = selfRect.top + selfRect.height;
|
|
743
|
+
function traverse(child) {
|
|
744
|
+
for (let i = 0; i < child.childNodes.length; i++) {
|
|
745
|
+
const sub = child.childNodes[i];
|
|
746
|
+
if (sub.nodeType === 1) {
|
|
747
|
+
const rect = elementRect(
|
|
748
|
+
sub,
|
|
749
|
+
currentWindow,
|
|
750
|
+
currentDocument,
|
|
751
|
+
baseZoom,
|
|
752
|
+
visibleOnly
|
|
753
|
+
);
|
|
754
|
+
if (rect) {
|
|
755
|
+
minLeft = Math.min(minLeft, rect.left);
|
|
756
|
+
minTop = Math.min(minTop, rect.top);
|
|
757
|
+
maxRight = Math.max(maxRight, rect.left + rect.width);
|
|
758
|
+
maxBottom = Math.max(maxBottom, rect.top + rect.height);
|
|
759
|
+
}
|
|
760
|
+
traverse(sub);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
traverse(node);
|
|
765
|
+
return {
|
|
766
|
+
...selfRect,
|
|
767
|
+
left: minLeft,
|
|
768
|
+
top: minTop,
|
|
769
|
+
width: maxRight - minLeft,
|
|
770
|
+
height: maxBottom - minTop
|
|
771
|
+
};
|
|
772
|
+
}
|
|
688
773
|
|
|
689
774
|
// src/extractor/debug.ts
|
|
690
775
|
console.log(extractTextWithPosition(document.body, true));
|