@midscene/web 0.5.1 → 0.5.2-beta-20240929094445.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.
@@ -583,17 +583,60 @@ var midscene_element_inspector = (() => {
583
583
 
584
584
  // src/extractor/dom-util.ts
585
585
  function isFormElement(node) {
586
- return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea" || node.tagName.toLowerCase() === "label" || node.tagName.toLowerCase() === "select" || node.tagName.toLowerCase() === "option");
586
+ return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea" || node.tagName.toLowerCase() === "select" || node.tagName.toLowerCase() === "option");
587
587
  }
588
588
  function isButtonElement(node) {
589
589
  return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";
590
590
  }
591
591
  function isImgElement(node) {
592
+ if (!includeBaseElement(node) && node instanceof Element) {
593
+ const computedStyle = window.getComputedStyle(node);
594
+ const backgroundImage = computedStyle.getPropertyValue("background-image");
595
+ if (backgroundImage !== "none") {
596
+ return true;
597
+ }
598
+ }
592
599
  return node instanceof HTMLElement && node.tagName.toLowerCase() === "img" || node instanceof SVGElement && node.tagName.toLowerCase() === "svg";
593
600
  }
594
601
  function isTextElement(node) {
595
602
  return node.nodeName.toLowerCase() === "#text";
596
603
  }
604
+ function isContainerElement(node) {
605
+ if (!(node instanceof HTMLElement))
606
+ return false;
607
+ if (includeBaseElement(node)) {
608
+ return false;
609
+ }
610
+ const computedStyle = window.getComputedStyle(node);
611
+ const backgroundColor = computedStyle.getPropertyValue("background-color");
612
+ if (backgroundColor) {
613
+ return true;
614
+ }
615
+ return false;
616
+ }
617
+ function includeBaseElement(node) {
618
+ if (!(node instanceof HTMLElement))
619
+ return false;
620
+ if (node.innerText) {
621
+ return true;
622
+ }
623
+ const includeList = [
624
+ "svg",
625
+ "button",
626
+ "input",
627
+ "textarea",
628
+ "select",
629
+ "option",
630
+ "img"
631
+ ];
632
+ for (const tagName of includeList) {
633
+ const element = node.querySelectorAll(tagName);
634
+ if (element.length > 0) {
635
+ return true;
636
+ }
637
+ }
638
+ return false;
639
+ }
597
640
 
598
641
  // src/extractor/util.ts
599
642
  var import_js_sha256 = __toESM(require_sha256());
@@ -621,9 +664,9 @@ var midscene_element_inspector = (() => {
621
664
  function selectorForValue(val) {
622
665
  return `[${taskIdKey}='${val}']`;
623
666
  }
624
- function setDataForNode(node, nodeHash) {
667
+ function setDataForNode(node, nodeHash, setToParentNode = false) {
625
668
  const taskId = taskIdKey;
626
- if (!(node instanceof HTMLElement)) {
669
+ if (!(node instanceof Element)) {
627
670
  return "";
628
671
  }
629
672
  if (!taskId) {
@@ -632,7 +675,13 @@ var midscene_element_inspector = (() => {
632
675
  }
633
676
  const selector = selectorForValue(nodeHash);
634
677
  if (getDebugMode()) {
635
- node.setAttribute(taskIdKey, nodeHash.toString());
678
+ if (setToParentNode) {
679
+ if (node.parentNode instanceof HTMLElement) {
680
+ node.parentNode.setAttribute(taskIdKey, nodeHash.toString());
681
+ }
682
+ } else {
683
+ node.setAttribute(taskIdKey, nodeHash.toString());
684
+ }
636
685
  }
637
686
  return selector;
638
687
  }
@@ -690,6 +739,28 @@ var midscene_element_inspector = (() => {
690
739
  zoom
691
740
  };
692
741
  }
742
+ var isElementCovered = (el, rect) => {
743
+ const x = rect.left + rect.width / 2;
744
+ const y = rect.top + rect.height / 2;
745
+ const topElement = document.elementFromPoint(x, y);
746
+ if (topElement === el) {
747
+ return false;
748
+ }
749
+ if (el == null ? void 0 : el.contains(topElement)) {
750
+ return false;
751
+ }
752
+ if (topElement == null ? void 0 : topElement.contains(el)) {
753
+ return false;
754
+ }
755
+ logger(el, "Element is covered by another element", {
756
+ topElement,
757
+ el,
758
+ rect,
759
+ x,
760
+ y
761
+ });
762
+ return true;
763
+ };
693
764
  function visibleRect(el, baseZoom = 1) {
694
765
  if (!el) {
695
766
  logger(el, "Element is not in the DOM hierarchy");
@@ -711,6 +782,9 @@ var midscene_element_inspector = (() => {
711
782
  logger(el, "Element has no size");
712
783
  return false;
713
784
  }
785
+ if (baseZoom === 1 && isElementCovered(el, rect)) {
786
+ return false;
787
+ }
714
788
  const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
715
789
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
716
790
  const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
@@ -805,12 +879,11 @@ var midscene_element_inspector = (() => {
805
879
  logger("Element is not visible", node);
806
880
  return null;
807
881
  }
808
- const debugMode2 = getDebugMode();
809
882
  if (isFormElement(node)) {
810
- const attributes2 = getNodeAttributes(node);
811
- const nodeHashId2 = midsceneGenerateHash(attributes2.placeholder, rect);
812
- const selector2 = setDataForNode(node, nodeHashId2);
813
- let valueContent = attributes2.value || attributes2.placeholder || node.textContent || "";
883
+ const attributes = getNodeAttributes(node);
884
+ const nodeHashId = midsceneGenerateHash(attributes.placeholder, rect);
885
+ const selector = setDataForNode(node, nodeHashId);
886
+ let valueContent = attributes.value || attributes.placeholder || node.textContent || "";
814
887
  const tagName = node.tagName.toLowerCase();
815
888
  if (node.tagName.toLowerCase() === "select") {
816
889
  const selectedOption = node.options[node.selectedIndex];
@@ -819,13 +892,13 @@ var midscene_element_inspector = (() => {
819
892
  if ((node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea") && node.value) {
820
893
  valueContent = node.value;
821
894
  }
822
- const elementInfo2 = {
823
- id: nodeHashId2,
895
+ const elementInfo = {
896
+ id: nodeHashId,
824
897
  nodePath,
825
- nodeHashId: nodeHashId2,
826
- locator: selector2,
898
+ nodeHashId,
899
+ locator: selector,
827
900
  nodeType: NodeType.FORM_ITEM,
828
- attributes: __spreadProps(__spreadValues({}, attributes2), {
901
+ attributes: __spreadProps(__spreadValues({}, attributes), {
829
902
  htmlTagName: `<${tagName}>`,
830
903
  nodeType: NodeType.FORM_ITEM
831
904
  }),
@@ -835,24 +908,25 @@ var midscene_element_inspector = (() => {
835
908
  Math.round(rect.left + rect.width / 2),
836
909
  Math.round(rect.top + rect.height / 2)
837
910
  ],
838
- htmlNode: debugMode2 ? node : null,
839
- zoom: rect.zoom
911
+ zoom: rect.zoom,
912
+ screenWidth: window.innerWidth,
913
+ screenHeight: window.innerHeight
840
914
  };
841
- return elementInfo2;
915
+ return elementInfo;
842
916
  }
843
917
  if (isButtonElement(node)) {
844
- const attributes2 = getNodeAttributes(node);
918
+ const attributes = getNodeAttributes(node);
845
919
  const pseudo = getPseudoElementContent(node);
846
920
  const content = node.innerText || pseudo.before || pseudo.after || "";
847
- const nodeHashId2 = midsceneGenerateHash(content, rect);
848
- const selector2 = setDataForNode(node, nodeHashId2);
849
- const elementInfo2 = {
850
- id: nodeHashId2,
921
+ const nodeHashId = midsceneGenerateHash(content, rect);
922
+ const selector = setDataForNode(node, nodeHashId);
923
+ const elementInfo = {
924
+ id: nodeHashId,
851
925
  nodePath,
852
- nodeHashId: nodeHashId2,
926
+ nodeHashId,
853
927
  nodeType: NodeType.BUTTON,
854
- locator: selector2,
855
- attributes: __spreadProps(__spreadValues({}, attributes2), {
928
+ locator: selector,
929
+ attributes: __spreadProps(__spreadValues({}, attributes), {
856
930
  nodeType: NodeType.BUTTON
857
931
  }),
858
932
  content,
@@ -861,21 +935,22 @@ var midscene_element_inspector = (() => {
861
935
  Math.round(rect.left + rect.width / 2),
862
936
  Math.round(rect.top + rect.height / 2)
863
937
  ],
864
- htmlNode: debugMode2 ? node : null,
865
- zoom: rect.zoom
938
+ zoom: rect.zoom,
939
+ screenWidth: window.innerWidth,
940
+ screenHeight: window.innerHeight
866
941
  };
867
- return elementInfo2;
942
+ return elementInfo;
868
943
  }
869
944
  if (isImgElement(node)) {
870
- const attributes2 = getNodeAttributes(node);
871
- const nodeHashId2 = midsceneGenerateHash("", rect);
872
- const selector2 = setDataForNode(node, nodeHashId2);
873
- const elementInfo2 = {
874
- id: nodeHashId2,
945
+ const attributes = getNodeAttributes(node);
946
+ const nodeHashId = midsceneGenerateHash("", rect);
947
+ const selector = setDataForNode(node, nodeHashId);
948
+ const elementInfo = {
949
+ id: nodeHashId,
875
950
  nodePath,
876
- nodeHashId: nodeHashId2,
877
- locator: selector2,
878
- attributes: __spreadProps(__spreadValues(__spreadValues({}, attributes2), node.nodeName.toLowerCase() === "svg" ? {
951
+ nodeHashId,
952
+ locator: selector,
953
+ attributes: __spreadProps(__spreadValues(__spreadValues({}, attributes), node.nodeName.toLowerCase() === "svg" ? {
879
954
  svgContent: "true"
880
955
  } : {}), {
881
956
  nodeType: NodeType.IMG
@@ -887,30 +962,31 @@ var midscene_element_inspector = (() => {
887
962
  Math.round(rect.left + rect.width / 2),
888
963
  Math.round(rect.top + rect.height / 2)
889
964
  ],
890
- htmlNode: debugMode2 ? node : null,
891
- zoom: rect.zoom
965
+ zoom: rect.zoom,
966
+ screenWidth: window.innerWidth,
967
+ screenHeight: window.innerHeight
892
968
  };
893
- return elementInfo2;
969
+ return elementInfo;
894
970
  }
895
971
  if (isTextElement(node)) {
896
972
  const text = (_a = node.textContent) == null ? void 0 : _a.trim().replace(/\n+/g, " ");
897
973
  if (!text) {
898
974
  return null;
899
975
  }
900
- const attributes2 = getNodeAttributes(node);
901
- const attributeKeys = Object.keys(attributes2);
976
+ const attributes = getNodeAttributes(node);
977
+ const attributeKeys = Object.keys(attributes);
902
978
  if (!text.trim() && attributeKeys.length === 0) {
903
979
  return null;
904
980
  }
905
- const nodeHashId2 = midsceneGenerateHash(text, rect);
906
- const selector2 = setDataForNode(node, nodeHashId2);
907
- const elementInfo2 = {
908
- id: nodeHashId2,
981
+ const nodeHashId = midsceneGenerateHash(text, rect);
982
+ const selector = setDataForNode(node, nodeHashId, true);
983
+ const elementInfo = {
984
+ id: nodeHashId,
909
985
  nodePath,
910
- nodeHashId: nodeHashId2,
986
+ nodeHashId,
911
987
  nodeType: NodeType.TEXT,
912
- locator: selector2,
913
- attributes: __spreadProps(__spreadValues({}, attributes2), {
988
+ locator: selector,
989
+ attributes: __spreadProps(__spreadValues({}, attributes), {
914
990
  nodeType: NodeType.TEXT
915
991
  }),
916
992
  center: [
@@ -920,33 +996,38 @@ var midscene_element_inspector = (() => {
920
996
  // attributes,
921
997
  content: text,
922
998
  rect,
923
- htmlNode: debugMode2 ? node : null,
924
- zoom: rect.zoom
999
+ zoom: rect.zoom,
1000
+ screenWidth: window.innerWidth,
1001
+ screenHeight: window.innerHeight
925
1002
  };
926
- return elementInfo2;
1003
+ return elementInfo;
927
1004
  }
928
- const attributes = getNodeAttributes(node);
929
- const nodeHashId = midsceneGenerateHash("", rect);
930
- const selector = setDataForNode(node, nodeHashId);
931
- const elementInfo = {
932
- id: nodeHashId,
933
- nodePath,
934
- nodeHashId,
935
- nodeType: NodeType.CONTAINER,
936
- locator: selector,
937
- attributes: __spreadProps(__spreadValues({}, attributes), {
938
- nodeType: NodeType.CONTAINER
939
- }),
940
- content: "",
941
- rect,
942
- center: [
943
- Math.round(rect.left + rect.width / 2),
944
- Math.round(rect.top + rect.height / 2)
945
- ],
946
- htmlNode: debugMode2 ? node : null,
947
- zoom: rect.zoom
948
- };
949
- return elementInfo;
1005
+ if (isContainerElement(node)) {
1006
+ const attributes = getNodeAttributes(node);
1007
+ const nodeHashId = midsceneGenerateHash("", rect);
1008
+ const selector = setDataForNode(node, nodeHashId);
1009
+ const elementInfo = {
1010
+ id: nodeHashId,
1011
+ nodePath,
1012
+ nodeHashId,
1013
+ nodeType: NodeType.CONTAINER,
1014
+ locator: selector,
1015
+ attributes: __spreadProps(__spreadValues({}, attributes), {
1016
+ nodeType: NodeType.CONTAINER
1017
+ }),
1018
+ content: "",
1019
+ rect,
1020
+ center: [
1021
+ Math.round(rect.left + rect.width / 2),
1022
+ Math.round(rect.top + rect.height / 2)
1023
+ ],
1024
+ zoom: rect.zoom,
1025
+ screenWidth: window.innerWidth,
1026
+ screenHeight: window.innerHeight
1027
+ };
1028
+ return elementInfo;
1029
+ }
1030
+ return null;
950
1031
  }
951
1032
  function extractTextWithPosition(initNode, debugMode2 = false, currentFrame = { id: 0, left: 0, top: 0 }) {
952
1033
  setDebugMode(debugMode2);
@@ -957,34 +1038,14 @@ var midscene_element_inspector = (() => {
957
1038
  return null;
958
1039
  }
959
1040
  const elementInfo = collectElementInfo(node, nodePath, baseZoom);
960
- if ((elementInfo == null ? void 0 : elementInfo.nodeType) === NodeType.BUTTON || (elementInfo == null ? void 0 : elementInfo.nodeType) === NodeType.IMG) {
1041
+ if ((elementInfo == null ? void 0 : elementInfo.nodeType) === NodeType.BUTTON || (elementInfo == null ? void 0 : elementInfo.nodeType) === NodeType.IMG || (elementInfo == null ? void 0 : elementInfo.nodeType) === NodeType.TEXT || (elementInfo == null ? void 0 : elementInfo.nodeType) === NodeType.FORM_ITEM || (elementInfo == null ? void 0 : elementInfo.nodeType) === NodeType.CONTAINER) {
1042
+ elementInfoArray.push(elementInfo);
961
1043
  return elementInfo;
962
1044
  }
963
- let hasNonContainerChildren = false;
964
- const childrenPureContainers = [];
1045
+ const rect = getRect(node, baseZoom);
965
1046
  for (let i = 0; i < node.childNodes.length; i++) {
966
1047
  logger("will dfs", node.childNodes[i]);
967
- const resultLengthBeforeDfs = elementInfoArray.length;
968
- const result = dfs(
969
- node.childNodes[i],
970
- `${nodePath}-${i}`,
971
- elementInfo == null ? void 0 : elementInfo.zoom
972
- );
973
- if (!result)
974
- continue;
975
- if ((result == null ? void 0 : result.nodeType) === NodeType.CONTAINER && elementInfoArray.length > resultLengthBeforeDfs) {
976
- hasNonContainerChildren = true;
977
- continue;
978
- }
979
- if ((result == null ? void 0 : result.nodeType) === NodeType.CONTAINER) {
980
- childrenPureContainers.push(result);
981
- } else {
982
- hasNonContainerChildren = true;
983
- elementInfoArray.push(result);
984
- }
985
- }
986
- if (hasNonContainerChildren) {
987
- elementInfoArray.push(...childrenPureContainers);
1048
+ dfs(node.childNodes[i], `${nodePath}-${i}`, rect.zoom);
988
1049
  }
989
1050
  if (!elementInfo) {
990
1051
  logger("should NOT continue for node", node);
@@ -992,10 +1053,7 @@ var midscene_element_inspector = (() => {
992
1053
  }
993
1054
  return elementInfo;
994
1055
  }
995
- const outerMostElementInfo = dfs(initNode || getDocument(), "0");
996
- if (outerMostElementInfo && !elementInfoArray.length) {
997
- elementInfoArray.push(outerMostElementInfo);
998
- }
1056
+ dfs(initNode || getDocument(), "0");
999
1057
  for (let i = 0; i < elementInfoArray.length; i++) {
1000
1058
  elementInfoArray[i].indexId = (i + 1).toString();
1001
1059
  }
@@ -1013,7 +1071,7 @@ var midscene_element_inspector = (() => {
1013
1071
 
1014
1072
  // src/extractor/debug.ts
1015
1073
  console.log(extractTextWithPosition(document.body, true));
1016
- console.log(JSON.stringify(extractTextWithPosition(document.body, false)));
1074
+ console.log(JSON.stringify(extractTextWithPosition(document.body, true)));
1017
1075
  setExtractTextWithPositionOnWindow();
1018
1076
  })();
1019
1077
  /*! Bundled license information:
@@ -1,5 +1,5 @@
1
- export { P as AppiumAgent } from './tasks-a905efe6.js';
2
- export { P as AppiumPage } from './page-2f02d5a8.js';
1
+ export { P as AppiumAgent } from './tasks-876d60ec.js';
2
+ export { P as AppiumPage } from './page-dd5d0f7b.js';
3
3
  import '@midscene/core';
4
4
  import '@midscene/shared/constants';
5
5
  import '@midscene/shared/fs';
@@ -1,5 +1,5 @@
1
1
  import { writeFileSync } from 'node:fs';
2
- import { W as WebPage, E as ElementInfo } from './page-2f02d5a8.js';
2
+ import { W as WebPage, E as ElementInfo } from './page-dd5d0f7b.js';
3
3
  import { NodeType } from '@midscene/shared/constants';
4
4
  import 'playwright';
5
5
  import 'puppeteer';
@@ -1,6 +1,6 @@
1
1
  export { PlayWrightAiFixtureType, PlaywrightAiFixture } from './playwright.js';
2
- export { P as AppiumAgent, P as PlaywrightAgent } from './tasks-a905efe6.js';
3
- export { P as AppiumPage } from './page-2f02d5a8.js';
2
+ export { P as AppiumAgent, P as PlaywrightAgent } from './tasks-876d60ec.js';
3
+ export { P as AppiumPage } from './page-dd5d0f7b.js';
4
4
  export { PuppeteerAgent } from './puppeteer.js';
5
5
  export { generateExtractData } from './debug.js';
6
6
  import '@midscene/core/.';
@@ -14,7 +14,6 @@ interface ElementInfo {
14
14
  [key: string]: string;
15
15
  };
16
16
  nodeType: NodeType;
17
- htmlNode: Node | null;
18
17
  content: string;
19
18
  rect: {
20
19
  left: number;
@@ -1,9 +1,9 @@
1
1
  import { AgentWaitForOpt } from '@midscene/core/.';
2
2
  import { TestInfo } from '@playwright/test';
3
3
  import { Page } from 'playwright';
4
- import { b as PageTaskExecutor } from './tasks-a905efe6.js';
5
- export { P as PlaywrightAgent } from './tasks-a905efe6.js';
6
- export { b as PlaywrightWebPage } from './page-2f02d5a8.js';
4
+ import { b as PageTaskExecutor } from './tasks-876d60ec.js';
5
+ export { P as PlaywrightAgent } from './tasks-876d60ec.js';
6
+ export { b as PlaywrightWebPage } from './page-dd5d0f7b.js';
7
7
  import '@midscene/core';
8
8
  import '@midscene/shared/constants';
9
9
  import '@midscene/shared/fs';
@@ -1,6 +1,6 @@
1
- import { P as PageAgent, a as PageAgentOpt } from './tasks-a905efe6.js';
1
+ import { P as PageAgent, a as PageAgentOpt } from './tasks-876d60ec.js';
2
2
  import { Page } from 'puppeteer';
3
- export { a as PuppeteerWebPage } from './page-2f02d5a8.js';
3
+ export { a as PuppeteerWebPage } from './page-dd5d0f7b.js';
4
4
  import '@midscene/core';
5
5
  import '@midscene/shared/constants';
6
6
  import '@midscene/shared/fs';
@@ -1,4 +1,4 @@
1
- import { W as WebPage } from './page-2f02d5a8.js';
1
+ import { W as WebPage } from './page-dd5d0f7b.js';
2
2
  import Insight, { BaseElement, Rect, UIContext, PlanningAction, AIElementParseResponse, GroupedActionDump, ExecutionDump, AgentWaitForOpt, InsightExtractParam, InsightAssertionResponse, PlanningActionParamWaitFor, Executor } from '@midscene/core';
3
3
  import { NodeType } from '@midscene/shared/constants';
4
4
  import { getMidscenePkgInfo } from '@midscene/shared/fs';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@midscene/web",
3
3
  "description": "Web integration for Midscene.js",
4
- "version": "0.5.1",
4
+ "version": "0.5.2-beta-20240929094445.0",
5
5
  "jsnext:source": "./src/index.ts",
6
6
  "main": "./dist/lib/index.js",
7
7
  "module": "./dist/es/index.js",
@@ -81,8 +81,8 @@
81
81
  "openai": "4.57.1",
82
82
  "inquirer": "10.1.5",
83
83
  "@xmldom/xmldom": "0.8.10",
84
- "@midscene/core": "0.5.1",
85
- "@midscene/shared": "0.5.1"
84
+ "@midscene/shared": "0.5.2-beta-20240929094445.0",
85
+ "@midscene/core": "0.5.2-beta-20240929094445.0"
86
86
  },
87
87
  "devDependencies": {
88
88
  "@modern-js/module-tools": "2.58.2",