@midscene/shared 0.24.2-beta-20250801111909.0 → 0.25.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/common.d.ts +1 -2
- package/dist/es/common.js +8 -6
- package/dist/es/constants.d.ts +2 -2
- package/dist/es/constants.js +97 -2
- package/dist/es/extractor-debug.js +1 -0
- package/dist/es/extractor.d.ts +1 -1
- package/dist/es/extractor.js +2 -0
- package/dist/es/fs.js +2 -1
- package/dist/es/img.d.ts +1 -1
- package/dist/es/img.js +302 -20
- package/dist/es/{index-65edf9c6.d.ts → index-fbb9e55d.d.ts} +2 -1
- package/dist/es/logger.js +25 -15
- package/dist/es/types.d.ts +1 -1
- package/dist/es/utils.d.ts +2 -1
- package/dist/es/utils.js +2 -0
- package/dist/lib/common.d.ts +1 -2
- package/dist/lib/common.js +9 -8
- package/dist/lib/constants.d.ts +2 -2
- package/dist/lib/constants.js +97 -2
- package/dist/lib/extractor-debug.js +1 -0
- package/dist/lib/extractor.d.ts +1 -1
- package/dist/lib/extractor.js +3 -0
- package/dist/lib/fs.js +2 -1
- package/dist/lib/img.d.ts +1 -1
- package/dist/lib/img.js +303 -21
- package/dist/lib/{index-65edf9c6.d.ts → index-fbb9e55d.d.ts} +2 -1
- package/dist/lib/logger.js +25 -15
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/utils.d.ts +2 -1
- package/dist/lib/utils.js +3 -0
- package/dist/types/common.d.ts +1 -2
- package/dist/types/constants.d.ts +2 -2
- package/dist/types/extractor.d.ts +1 -1
- package/dist/types/img.d.ts +1 -1
- package/dist/types/{index-65edf9c6.d.ts → index-fbb9e55d.d.ts} +2 -1
- package/dist/types/types.d.ts +1 -1
- package/dist/types/utils.d.ts +2 -1
- package/package.json +5 -2
- package/src/common.ts +4 -7
- package/src/constants/example-code.ts +97 -2
- package/src/extractor/index.ts +1 -0
- package/src/extractor/locator.ts +1 -1
- package/src/img/get-photon.ts +48 -0
- package/src/img/get-sharp.ts +24 -0
- package/src/img/transform.ts +88 -20
- package/src/logger.ts +25 -13
- package/src/utils.ts +2 -0
package/dist/es/common.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
declare const defaultRunDirName = "midscene_run";
|
|
2
|
-
declare const isNodeEnv: boolean;
|
|
3
2
|
declare const getMidsceneRunDir: () => string;
|
|
4
3
|
declare const getMidsceneRunBaseDir: () => string;
|
|
5
4
|
/**
|
|
@@ -11,4 +10,4 @@ declare const getMidsceneRunBaseDir: () => string;
|
|
|
11
10
|
*/
|
|
12
11
|
declare const getMidsceneRunSubDir: (subdir: "dump" | "cache" | "report" | "tmp" | "log" | "output") => string;
|
|
13
12
|
|
|
14
|
-
export { defaultRunDirName, getMidsceneRunBaseDir, getMidsceneRunDir, getMidsceneRunSubDir
|
|
13
|
+
export { defaultRunDirName, getMidsceneRunBaseDir, getMidsceneRunDir, getMidsceneRunSubDir };
|
package/dist/es/common.js
CHANGED
|
@@ -110,17 +110,20 @@ var getAIConfig = (configKey) => {
|
|
|
110
110
|
return value;
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
// src/utils.ts
|
|
114
|
+
import { sha256 } from "js-sha256";
|
|
115
|
+
var ifInNode = typeof process !== "undefined" && process.versions?.node;
|
|
116
|
+
|
|
113
117
|
// src/common.ts
|
|
114
118
|
var defaultRunDirName = "midscene_run";
|
|
115
|
-
var isNodeEnv = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
116
119
|
var getMidsceneRunDir = () => {
|
|
117
|
-
if (!
|
|
120
|
+
if (!ifInNode) {
|
|
118
121
|
return "";
|
|
119
122
|
}
|
|
120
123
|
return getAIConfig(MIDSCENE_RUN_DIR) || defaultRunDirName;
|
|
121
124
|
};
|
|
122
125
|
var getMidsceneRunBaseDir = () => {
|
|
123
|
-
if (!
|
|
126
|
+
if (!ifInNode) {
|
|
124
127
|
return "";
|
|
125
128
|
}
|
|
126
129
|
let basePath = path.resolve(process.cwd(), getMidsceneRunDir());
|
|
@@ -135,7 +138,7 @@ var getMidsceneRunBaseDir = () => {
|
|
|
135
138
|
return basePath;
|
|
136
139
|
};
|
|
137
140
|
var getMidsceneRunSubDir = (subdir) => {
|
|
138
|
-
if (!
|
|
141
|
+
if (!ifInNode) {
|
|
139
142
|
return "";
|
|
140
143
|
}
|
|
141
144
|
const basePath = getMidsceneRunBaseDir();
|
|
@@ -149,6 +152,5 @@ export {
|
|
|
149
152
|
defaultRunDirName,
|
|
150
153
|
getMidsceneRunBaseDir,
|
|
151
154
|
getMidsceneRunDir,
|
|
152
|
-
getMidsceneRunSubDir
|
|
153
|
-
isNodeEnv
|
|
155
|
+
getMidsceneRunSubDir
|
|
154
156
|
};
|
package/dist/es/constants.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
declare const PLAYWRIGHT_EXAMPLE_CODE = "\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nIMPORTANT: Follow these exact type signatures for AI functions:\n\n// Type signatures for AI functions:\naiInput(value: string, locator: string): Promise<void>\naiTap(locator: string): Promise<void> \naiAssert(assertion: string): Promise<void>\naiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions\n\n// examples:\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nimport { test as base } from '@playwright/test';\nimport type { PlayWrightAiFixtureType } from '@midscene/web/playwright';\nimport { PlaywrightAiFixture } from '@midscene/web/playwright';\n\
|
|
2
|
-
declare const YAML_EXAMPLE_CODE = "\n1. Format:\n\nweb:\n url: \"starting_url\"\n viewportWidth: 1280\n viewportHeight: 960\n\ntasks:\n - name: \"descriptive task name\"\n flow:\n - aiTap: \"element description\"\n - aiInput: 'text value'\n locate: 'input field description'\n - aiScroll:\n direction: down/up\n scrollType: untilBottom/untilTop/page\n - aiAssert: \"expected state\"\n - sleep: milliseconds\n\n2. Action Types:\n- aiTap: for clicks (natural language targeting)\n- aiInput: for text input with 'locate' field\n- aiScroll: with direction and scrollType\n- aiAssert: for validations\n- sleep: for delays (milliseconds)\n\n3. Best Practices:\n- Group related actions into logical tasks\n- Use natural language descriptions\n- Add deepThink: true for complex interactions\n- Keep task names concise but descriptive\n";
|
|
1
|
+
declare const PLAYWRIGHT_EXAMPLE_CODE = "\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nIMPORTANT: Follow these exact type signatures for AI functions:\n\n// Type signatures for AI functions:\naiInput(value: string, locator: string): Promise<void>\naiTap(locator: string): Promise<void> \naiScroll(scrollParam: {\n direction: 'up' | 'down' | 'left' | 'right',\n scrollType: 'once' | 'untilBottom' | 'untilTop' | 'untilRight' | 'untilLeft',\n distance: number - scroll distance, px is the unit\n}): Promise<void>\naiAssert(assertion: string): Promise<void>\naiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions\n\n// examples:\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nimport { test as base } from '@playwright/test';\nimport type { PlayWrightAiFixtureType } from '@midscene/web/playwright';\nimport { PlaywrightAiFixture } from '@midscene/web/playwright';\n\nconst test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({\n waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms\n}));\n\n\ntest.beforeEach(async ({ page }) => {\n await page.goto('https://www.xxx.com/');\n await page.setViewportSize({ width: 1920, height: 1080 });\n});\n\ntest('ai shop', async ({\n aiInput,\n aiAssert,\n aiQuery,\n aiKeyboardPress,\n aiHover,\n aiTap,\n agentForPage,\n page,\n}) => {\n // login\n await aiAssert('The page shows the login interface');\n await aiInput('user_name', 'in user name input');\n await aiInput('password', 'in password input');\n await aiKeyboardPress('Enter', 'Login Button');\n\n // check the login success\n await aiWaitFor('The page shows that the loading is complete');\n await aiAssert('The current page shows the product detail page');\n\n // check the product info\n const dataA = await aiQuery({\n userInfo: 'User information in the format {name: string}',\n theFirstProductInfo: 'The first product info in the format {name: string, price: number}',\n });\n expect(dataA.theFirstProductInfo.name).toBe('xxx');\n expect(dataA.theFirstProductInfo.price).toBe(100);\n\n\n // add to cart\n await aiTap('click add to cart button');\n \n await aiTap('click right top cart icon');\n await aiAssert('The cart icon shows the number 1');\n});\n";
|
|
2
|
+
declare const YAML_EXAMPLE_CODE = "\n1. Format:\n\nweb:\n url: \"starting_url\"\n viewportWidth: 1280\n viewportHeight: 960\n\ntasks:\n - name: \"descriptive task name\"\n flow:\n - aiTap: \"element description\"\n - aiInput: 'text value'\n locate: 'input field description'\n - aiScroll:\n direction: down/up\n scrollType: untilBottom/untilTop/page\n - aiAssert: \"expected state\"\n - sleep: milliseconds\n\n2. Action Types:\n- aiTap: for clicks (natural language targeting)\n- aiInput: for text input with 'locate' field\n- aiScroll: with direction and scrollType\n- aiAssert: for validations\n- sleep: for delays (milliseconds)\n\n3. Best Practices:\n- Group related actions into logical tasks\n- Use natural language descriptions\n- Add deepThink: true for complex interactions\n- Keep task names concise but descriptive\n\n\n\nYAML type\ntasks:\n - name: <name>\n continueOnError: <boolean> # Optional, whether to continue to the next task on error, defaults to false.\n flow:\n # Auto Planning (.ai)\n # ----------------\n\n # Perform an interaction. `ai` is a shorthand for `aiAction`.\n - ai: <prompt>\n cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.\n\n # This usage is the same as `ai`.\n - aiAction: <prompt>\n cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.\n\n # Instant Action (.aiTap, .aiHover, .aiInput, .aiKeyboardPress, .aiScroll)\n # ----------------\n\n # Tap an element described by a prompt.\n - aiTap: <prompt>\n deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.\n xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.\n cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.\n\n # Hover over an element described by a prompt.\n - aiHover: <prompt>\n deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.\n xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.\n cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.\n\n # Input text into an element described by a prompt.\n - aiInput: <final text content of the input>\n locate: <prompt>\n deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.\n xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.\n cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.\n\n # Press a key (e.g., Enter, Tab, Escape) on an element described by a prompt.\n - aiKeyboardPress: <key>\n locate: <prompt>\n deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.\n xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.\n cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.\n\n # Scroll globally or on an element described by a prompt.\n - aiScroll:\n direction: 'up' # or 'down' | 'left' | 'right'\n scrollType: 'once' # or 'untilTop' | 'untilBottom' | 'untilLeft' | 'untilRight'\n distance: <number> # Optional, the scroll distance in pixels.\n locate: <prompt> # Optional, the element to scroll on.\n deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.\n xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.\n cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.\n\n # Log the current screenshot with a description in the report file.\n - logScreenshot: <title> # Optional, the title of the screenshot. If not provided, the title will be 'untitled'.\n content: <content> # Optional, the description of the screenshot.\n\n # Data Extraction\n # ----------------\n\n # Perform a query that returns a JSON object.\n - aiQuery: <prompt> # Remember to describe the format of the result in the prompt.\n name: <name> # The key for the query result in the JSON output.\n\n # More APIs\n # ----------------\n\n # Wait for a condition to be met, with a timeout (in ms, optional, defaults to 30000).\n - aiWaitFor: <prompt>\n timeout: <ms>\n\n # Perform an assertion.\n - aiAssert: <prompt>\n errorMessage: <error-message> # Optional, the error message to print if the assertion fails.\n\n # Wait for a specified amount of time.\n - sleep: <ms>\n\n # Execute a piece of JavaScript code in the web page context.\n - javascript: <javascript>\n name: <name> # Optional, assign a name to the return value, which will be used as a key in the JSON output.\n\n - name: <name>\n flow:\n # ...\n";
|
|
3
3
|
|
|
4
4
|
declare const TEXT_SIZE_THRESHOLD = 9;
|
|
5
5
|
declare const TEXT_MAX_SIZE = 40;
|
package/dist/es/constants.js
CHANGED
|
@@ -8,6 +8,11 @@ IMPORTANT: Follow these exact type signatures for AI functions:
|
|
|
8
8
|
// Type signatures for AI functions:
|
|
9
9
|
aiInput(value: string, locator: string): Promise<void>
|
|
10
10
|
aiTap(locator: string): Promise<void>
|
|
11
|
+
aiScroll(scrollParam: {
|
|
12
|
+
direction: 'up' | 'down' | 'left' | 'right',
|
|
13
|
+
scrollType: 'once' | 'untilBottom' | 'untilTop' | 'untilRight' | 'untilLeft',
|
|
14
|
+
distance: number - scroll distance, px is the unit
|
|
15
|
+
}): Promise<void>
|
|
11
16
|
aiAssert(assertion: string): Promise<void>
|
|
12
17
|
aiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions
|
|
13
18
|
|
|
@@ -19,9 +24,9 @@ import { test as base } from '@playwright/test';
|
|
|
19
24
|
import type { PlayWrightAiFixtureType } from '@midscene/web/playwright';
|
|
20
25
|
import { PlaywrightAiFixture } from '@midscene/web/playwright';
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
const test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({
|
|
23
28
|
waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms
|
|
24
|
-
|
|
29
|
+
}));
|
|
25
30
|
|
|
26
31
|
|
|
27
32
|
test.beforeEach(async ({ page }) => {
|
|
@@ -97,6 +102,96 @@ tasks:
|
|
|
97
102
|
- Use natural language descriptions
|
|
98
103
|
- Add deepThink: true for complex interactions
|
|
99
104
|
- Keep task names concise but descriptive
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
YAML type
|
|
109
|
+
tasks:
|
|
110
|
+
- name: <name>
|
|
111
|
+
continueOnError: <boolean> # Optional, whether to continue to the next task on error, defaults to false.
|
|
112
|
+
flow:
|
|
113
|
+
# Auto Planning (.ai)
|
|
114
|
+
# ----------------
|
|
115
|
+
|
|
116
|
+
# Perform an interaction. \`ai\` is a shorthand for \`aiAction\`.
|
|
117
|
+
- ai: <prompt>
|
|
118
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
119
|
+
|
|
120
|
+
# This usage is the same as \`ai\`.
|
|
121
|
+
- aiAction: <prompt>
|
|
122
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
123
|
+
|
|
124
|
+
# Instant Action (.aiTap, .aiHover, .aiInput, .aiKeyboardPress, .aiScroll)
|
|
125
|
+
# ----------------
|
|
126
|
+
|
|
127
|
+
# Tap an element described by a prompt.
|
|
128
|
+
- aiTap: <prompt>
|
|
129
|
+
deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.
|
|
130
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
131
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
132
|
+
|
|
133
|
+
# Hover over an element described by a prompt.
|
|
134
|
+
- aiHover: <prompt>
|
|
135
|
+
deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.
|
|
136
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
137
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
138
|
+
|
|
139
|
+
# Input text into an element described by a prompt.
|
|
140
|
+
- aiInput: <final text content of the input>
|
|
141
|
+
locate: <prompt>
|
|
142
|
+
deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.
|
|
143
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
144
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
145
|
+
|
|
146
|
+
# Press a key (e.g., Enter, Tab, Escape) on an element described by a prompt.
|
|
147
|
+
- aiKeyboardPress: <key>
|
|
148
|
+
locate: <prompt>
|
|
149
|
+
deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.
|
|
150
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
151
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
152
|
+
|
|
153
|
+
# Scroll globally or on an element described by a prompt.
|
|
154
|
+
- aiScroll:
|
|
155
|
+
direction: 'up' # or 'down' | 'left' | 'right'
|
|
156
|
+
scrollType: 'once' # or 'untilTop' | 'untilBottom' | 'untilLeft' | 'untilRight'
|
|
157
|
+
distance: <number> # Optional, the scroll distance in pixels.
|
|
158
|
+
locate: <prompt> # Optional, the element to scroll on.
|
|
159
|
+
deepThink: <boolean> # Optional, whether to use deepThink to precisely locate the element. Defaults to False.
|
|
160
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
161
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
162
|
+
|
|
163
|
+
# Log the current screenshot with a description in the report file.
|
|
164
|
+
- logScreenshot: <title> # Optional, the title of the screenshot. If not provided, the title will be 'untitled'.
|
|
165
|
+
content: <content> # Optional, the description of the screenshot.
|
|
166
|
+
|
|
167
|
+
# Data Extraction
|
|
168
|
+
# ----------------
|
|
169
|
+
|
|
170
|
+
# Perform a query that returns a JSON object.
|
|
171
|
+
- aiQuery: <prompt> # Remember to describe the format of the result in the prompt.
|
|
172
|
+
name: <name> # The key for the query result in the JSON output.
|
|
173
|
+
|
|
174
|
+
# More APIs
|
|
175
|
+
# ----------------
|
|
176
|
+
|
|
177
|
+
# Wait for a condition to be met, with a timeout (in ms, optional, defaults to 30000).
|
|
178
|
+
- aiWaitFor: <prompt>
|
|
179
|
+
timeout: <ms>
|
|
180
|
+
|
|
181
|
+
# Perform an assertion.
|
|
182
|
+
- aiAssert: <prompt>
|
|
183
|
+
errorMessage: <error-message> # Optional, the error message to print if the assertion fails.
|
|
184
|
+
|
|
185
|
+
# Wait for a specified amount of time.
|
|
186
|
+
- sleep: <ms>
|
|
187
|
+
|
|
188
|
+
# Execute a piece of JavaScript code in the web page context.
|
|
189
|
+
- javascript: <javascript>
|
|
190
|
+
name: <name> # Optional, assign a name to the return value, which will be used as a key in the JSON output.
|
|
191
|
+
|
|
192
|
+
- name: <name>
|
|
193
|
+
flow:
|
|
194
|
+
# ...
|
|
100
195
|
`;
|
|
101
196
|
|
|
102
197
|
// src/constants/index.ts
|
package/dist/es/extractor.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import './constants.js';
|
|
2
|
-
export { E as ElementInfo, a as ElementNode, d as descriptionOfTree,
|
|
2
|
+
export { E as ElementInfo, a as ElementNode, d as descriptionOfTree, o as generateElementByPosition, m as getElementInfoByXpath, n as getElementXpath, i as getNodeFromCacheList, l as getNodeInfoByXpath, j as getXpathsById, k as getXpathsByPoint, p as isNotContainerElement, s as setNodeHashCacheListOnWindow, t as traverseTree, b as treeToList, e as trimAttributes, c as truncateText, g as webExtractNodeTree, h as webExtractNodeTreeAsString, f as webExtractTextWithPosition } from './index-fbb9e55d.js';
|
package/dist/es/extractor.js
CHANGED
|
@@ -129,6 +129,7 @@ var CONTAINER_MINI_WIDTH = 3;
|
|
|
129
129
|
|
|
130
130
|
// src/utils.ts
|
|
131
131
|
import { sha256 } from "js-sha256";
|
|
132
|
+
var ifInNode = typeof process !== "undefined" && process.versions?.node;
|
|
132
133
|
var hashMap = {};
|
|
133
134
|
function generateHashId(rect, content = "") {
|
|
134
135
|
const combined = JSON.stringify({
|
|
@@ -990,6 +991,7 @@ export {
|
|
|
990
991
|
descriptionOfTree,
|
|
991
992
|
generateElementByPosition,
|
|
992
993
|
getElementInfoByXpath,
|
|
994
|
+
getElementXpath,
|
|
993
995
|
getNodeFromCacheList,
|
|
994
996
|
getNodeInfoByXpath,
|
|
995
997
|
getXpathsById,
|
package/dist/es/fs.js
CHANGED
|
@@ -6,6 +6,7 @@ import { dirname, join } from "path";
|
|
|
6
6
|
import { sha256 } from "js-sha256";
|
|
7
7
|
var ifInBrowser = typeof window !== "undefined";
|
|
8
8
|
var ifInWorker = typeof WorkerGlobalScope !== "undefined";
|
|
9
|
+
var ifInNode = typeof process !== "undefined" && process.versions?.node;
|
|
9
10
|
|
|
10
11
|
// src/node/fs.ts
|
|
11
12
|
var pkgCacheMap = {};
|
|
@@ -46,7 +47,7 @@ function findNearestPackageJson(dir) {
|
|
|
46
47
|
return findNearestPackageJson(parentDir);
|
|
47
48
|
}
|
|
48
49
|
function getElementInfosScriptContent() {
|
|
49
|
-
const htmlElementScript = '"use strict";\nvar midscene_element_inspector = (() => {\n var __create = Object.create;\n var __defProp = Object.defineProperty;\n var __defProps = Object.defineProperties;\n var __getOwnPropDesc = Object.getOwnPropertyDescriptor;\n var __getOwnPropDescs = Object.getOwnPropertyDescriptors;\n var __getOwnPropNames = Object.getOwnPropertyNames;\n var __getOwnPropSymbols = Object.getOwnPropertySymbols;\n var __getProtoOf = Object.getPrototypeOf;\n var __hasOwnProp = Object.prototype.hasOwnProperty;\n var __propIsEnum = Object.prototype.propertyIsEnumerable;\n var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\n var __spreadValues = (a, b) => {\n for (var prop in b || (b = {}))\n if (__hasOwnProp.call(b, prop))\n __defNormalProp(a, prop, b[prop]);\n if (__getOwnPropSymbols)\n for (var prop of __getOwnPropSymbols(b)) {\n if (__propIsEnum.call(b, prop))\n __defNormalProp(a, prop, b[prop]);\n }\n return a;\n };\n var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));\n var __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n };\n var __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n };\n var __copyProps = (to, from, except, desc) => {\n if (from && typeof from === "object" || typeof from === "function") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n };\n var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. "__esModule" has not been set), then set\n // "default" to the CommonJS "module.exports" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,\n mod\n ));\n var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);\n\n // resolve-false:/empty-stub\n var require_empty_stub = __commonJS({\n "resolve-false:/empty-stub"(exports, module) {\n "use strict";\n module.exports = {};\n }\n });\n\n // ../../node_modules/.pnpm/js-sha256@0.11.0/node_modules/js-sha256/src/sha256.js\n var require_sha256 = __commonJS({\n "../../node_modules/.pnpm/js-sha256@0.11.0/node_modules/js-sha256/src/sha256.js"(exports, module) {\n "use strict";\n (function() {\n "use strict";\n var ERROR = "input is invalid type";\n var WINDOW = typeof window === "object";\n var root = WINDOW ? window : {};\n if (root.JS_SHA256_NO_WINDOW) {\n WINDOW = false;\n }\n var WEB_WORKER = !WINDOW && typeof self === "object";\n var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === "object" && process.versions && process.versions.node;\n if (NODE_JS) {\n root = global;\n } else if (WEB_WORKER) {\n root = self;\n }\n var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === "object" && module.exports;\n var AMD = typeof define === "function" && define.amd;\n var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== "undefined";\n var HEX_CHARS = "0123456789abcdef".split("");\n var EXTRA = [-2147483648, 8388608, 32768, 128];\n var SHIFT = [24, 16, 8, 0];\n var K = [\n 1116352408,\n 1899447441,\n 3049323471,\n 3921009573,\n 961987163,\n 1508970993,\n 2453635748,\n 2870763221,\n 3624381080,\n 310598401,\n 607225278,\n 1426881987,\n 1925078388,\n 2162078206,\n 2614888103,\n 3248222580,\n 3835390401,\n 4022224774,\n 264347078,\n 604807628,\n 770255983,\n 1249150122,\n 1555081692,\n 1996064986,\n 2554220882,\n 2821834349,\n 2952996808,\n 3210313671,\n 3336571891,\n 3584528711,\n 113926993,\n 338241895,\n 666307205,\n 773529912,\n 1294757372,\n 1396182291,\n 1695183700,\n 1986661051,\n 2177026350,\n 2456956037,\n 2730485921,\n 2820302411,\n 3259730800,\n 3345764771,\n 3516065817,\n 3600352804,\n 4094571909,\n 275423344,\n 430227734,\n 506948616,\n 659060556,\n 883997877,\n 958139571,\n 1322822218,\n 1537002063,\n 1747873779,\n 1955562222,\n 2024104815,\n 2227730452,\n 2361852424,\n 2428436474,\n 2756734187,\n 3204031479,\n 3329325298\n ];\n var OUTPUT_TYPES = ["hex", "array", "digest", "arrayBuffer"];\n var blocks = [];\n if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) {\n Array.isArray = function(obj) {\n return Object.prototype.toString.call(obj) === "[object Array]";\n };\n }\n if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {\n ArrayBuffer.isView = function(obj) {\n return typeof obj === "object" && obj.buffer && obj.buffer.constructor === ArrayBuffer;\n };\n }\n var createOutputMethod = function(outputType, is224) {\n return function(message) {\n return new Sha256(is224, true).update(message)[outputType]();\n };\n };\n var createMethod = function(is224) {\n var method = createOutputMethod("hex", is224);\n if (NODE_JS) {\n method = nodeWrap(method, is224);\n }\n method.create = function() {\n return new Sha256(is224);\n };\n method.update = function(message) {\n return method.create().update(message);\n };\n for (var i = 0; i < OUTPUT_TYPES.length; ++i) {\n var type = OUTPUT_TYPES[i];\n method[type] = createOutputMethod(type, is224);\n }\n return method;\n };\n var nodeWrap = function(method, is224) {\n var crypto = require_empty_stub();\n var Buffer2 = require_empty_stub().Buffer;\n var algorithm = is224 ? "sha224" : "sha256";\n var bufferFrom;\n if (Buffer2.from && !root.JS_SHA256_NO_BUFFER_FROM) {\n bufferFrom = Buffer2.from;\n } else {\n bufferFrom = function(message) {\n return new Buffer2(message);\n };\n }\n var nodeMethod = function(message) {\n if (typeof message === "string") {\n return crypto.createHash(algorithm).update(message, "utf8").digest("hex");\n } else {\n if (message === null || message === void 0) {\n throw new Error(ERROR);\n } else if (message.constructor === ArrayBuffer) {\n message = new Uint8Array(message);\n }\n }\n if (Array.isArray(message) || ArrayBuffer.isView(message) || message.constructor === Buffer2) {\n return crypto.createHash(algorithm).update(bufferFrom(message)).digest("hex");\n } else {\n return method(message);\n }\n };\n return nodeMethod;\n };\n var createHmacOutputMethod = function(outputType, is224) {\n return function(key, message) {\n return new HmacSha256(key, is224, true).update(message)[outputType]();\n };\n };\n var createHmacMethod = function(is224) {\n var method = createHmacOutputMethod("hex", is224);\n method.create = function(key) {\n return new HmacSha256(key, is224);\n };\n method.update = function(key, message) {\n return method.create(key).update(message);\n };\n for (var i = 0; i < OUTPUT_TYPES.length; ++i) {\n var type = OUTPUT_TYPES[i];\n method[type] = createHmacOutputMethod(type, is224);\n }\n return method;\n };\n function Sha256(is224, sharedMemory) {\n if (sharedMemory) {\n blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n this.blocks = blocks;\n } else {\n this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n }\n if (is224) {\n this.h0 = 3238371032;\n this.h1 = 914150663;\n this.h2 = 812702999;\n this.h3 = 4144912697;\n this.h4 = 4290775857;\n this.h5 = 1750603025;\n this.h6 = 1694076839;\n this.h7 = 3204075428;\n } else {\n this.h0 = 1779033703;\n this.h1 = 3144134277;\n this.h2 = 1013904242;\n this.h3 = 2773480762;\n this.h4 = 1359893119;\n this.h5 = 2600822924;\n this.h6 = 528734635;\n this.h7 = 1541459225;\n }\n this.block = this.start = this.bytes = this.hBytes = 0;\n this.finalized = this.hashed = false;\n this.first = true;\n this.is224 = is224;\n }\n Sha256.prototype.update = function(message) {\n if (this.finalized) {\n return;\n }\n var notString, type = typeof message;\n if (type !== "string") {\n if (type === "object") {\n if (message === null) {\n throw new Error(ERROR);\n } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {\n message = new Uint8Array(message);\n } else if (!Array.isArray(message)) {\n if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {\n throw new Error(ERROR);\n }\n }\n } else {\n throw new Error(ERROR);\n }\n notString = true;\n }\n var code, index = 0, i, length = message.length, blocks2 = this.blocks;\n while (index < length) {\n if (this.hashed) {\n this.hashed = false;\n blocks2[0] = this.block;\n this.block = blocks2[16] = blocks2[1] = blocks2[2] = blocks2[3] = blocks2[4] = blocks2[5] = blocks2[6] = blocks2[7] = blocks2[8] = blocks2[9] = blocks2[10] = blocks2[11] = blocks2[12] = blocks2[13] = blocks2[14] = blocks2[15] = 0;\n }\n if (notString) {\n for (i = this.start; index < length && i < 64; ++index) {\n blocks2[i >>> 2] |= message[index] << SHIFT[i++ & 3];\n }\n } else {\n for (i = this.start; index < length && i < 64; ++index) {\n code = message.charCodeAt(index);\n if (code < 128) {\n blocks2[i >>> 2] |= code << SHIFT[i++ & 3];\n } else if (code < 2048) {\n blocks2[i >>> 2] |= (192 | code >>> 6) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code & 63) << SHIFT[i++ & 3];\n } else if (code < 55296 || code >= 57344) {\n blocks2[i >>> 2] |= (224 | code >>> 12) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code >>> 6 & 63) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code & 63) << SHIFT[i++ & 3];\n } else {\n code = 65536 + ((code & 1023) << 10 | message.charCodeAt(++index) & 1023);\n blocks2[i >>> 2] |= (240 | code >>> 18) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code >>> 12 & 63) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code >>> 6 & 63) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code & 63) << SHIFT[i++ & 3];\n }\n }\n }\n this.lastByteIndex = i;\n this.bytes += i - this.start;\n if (i >= 64) {\n this.block = blocks2[16];\n this.start = i - 64;\n this.hash();\n this.hashed = true;\n } else {\n this.start = i;\n }\n }\n if (this.bytes > 4294967295) {\n this.hBytes += this.bytes / 4294967296 << 0;\n this.bytes = this.bytes % 4294967296;\n }\n return this;\n };\n Sha256.prototype.finalize = function() {\n if (this.finalized) {\n return;\n }\n this.finalized = true;\n var blocks2 = this.blocks, i = this.lastByteIndex;\n blocks2[16] = this.block;\n blocks2[i >>> 2] |= EXTRA[i & 3];\n this.block = blocks2[16];\n if (i >= 56) {\n if (!this.hashed) {\n this.hash();\n }\n blocks2[0] = this.block;\n blocks2[16] = blocks2[1] = blocks2[2] = blocks2[3] = blocks2[4] = blocks2[5] = blocks2[6] = blocks2[7] = blocks2[8] = blocks2[9] = blocks2[10] = blocks2[11] = blocks2[12] = blocks2[13] = blocks2[14] = blocks2[15] = 0;\n }\n blocks2[14] = this.hBytes << 3 | this.bytes >>> 29;\n blocks2[15] = this.bytes << 3;\n this.hash();\n };\n Sha256.prototype.hash = function() {\n var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4, f = this.h5, g = this.h6, h = this.h7, blocks2 = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;\n for (j = 16; j < 64; ++j) {\n t1 = blocks2[j - 15];\n s0 = (t1 >>> 7 | t1 << 25) ^ (t1 >>> 18 | t1 << 14) ^ t1 >>> 3;\n t1 = blocks2[j - 2];\n s1 = (t1 >>> 17 | t1 << 15) ^ (t1 >>> 19 | t1 << 13) ^ t1 >>> 10;\n blocks2[j] = blocks2[j - 16] + s0 + blocks2[j - 7] + s1 << 0;\n }\n bc = b & c;\n for (j = 0; j < 64; j += 4) {\n if (this.first) {\n if (this.is224) {\n ab = 300032;\n t1 = blocks2[0] - 1413257819;\n h = t1 - 150054599 << 0;\n d = t1 + 24177077 << 0;\n } else {\n ab = 704751109;\n t1 = blocks2[0] - 210244248;\n h = t1 - 1521486534 << 0;\n d = t1 + 143694565 << 0;\n }\n this.first = false;\n } else {\n s0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10);\n s1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7);\n ab = a & b;\n maj = ab ^ a & c ^ bc;\n ch = e & f ^ ~e & g;\n t1 = h + s1 + ch + K[j] + blocks2[j];\n t2 = s0 + maj;\n h = d + t1 << 0;\n d = t1 + t2 << 0;\n }\n s0 = (d >>> 2 | d << 30) ^ (d >>> 13 | d << 19) ^ (d >>> 22 | d << 10);\n s1 = (h >>> 6 | h << 26) ^ (h >>> 11 | h << 21) ^ (h >>> 25 | h << 7);\n da = d & a;\n maj = da ^ d & b ^ ab;\n ch = h & e ^ ~h & f;\n t1 = g + s1 + ch + K[j + 1] + blocks2[j + 1];\n t2 = s0 + maj;\n g = c + t1 << 0;\n c = t1 + t2 << 0;\n s0 = (c >>> 2 | c << 30) ^ (c >>> 13 | c << 19) ^ (c >>> 22 | c << 10);\n s1 = (g >>> 6 | g << 26) ^ (g >>> 11 | g << 21) ^ (g >>> 25 | g << 7);\n cd = c & d;\n maj = cd ^ c & a ^ da;\n ch = g & h ^ ~g & e;\n t1 = f + s1 + ch + K[j + 2] + blocks2[j + 2];\n t2 = s0 + maj;\n f = b + t1 << 0;\n b = t1 + t2 << 0;\n s0 = (b >>> 2 | b << 30) ^ (b >>> 13 | b << 19) ^ (b >>> 22 | b << 10);\n s1 = (f >>> 6 | f << 26) ^ (f >>> 11 | f << 21) ^ (f >>> 25 | f << 7);\n bc = b & c;\n maj = bc ^ b & d ^ cd;\n ch = f & g ^ ~f & h;\n t1 = e + s1 + ch + K[j + 3] + blocks2[j + 3];\n t2 = s0 + maj;\n e = a + t1 << 0;\n a = t1 + t2 << 0;\n this.chromeBugWorkAround = true;\n }\n this.h0 = this.h0 + a << 0;\n this.h1 = this.h1 + b << 0;\n this.h2 = this.h2 + c << 0;\n this.h3 = this.h3 + d << 0;\n this.h4 = this.h4 + e << 0;\n this.h5 = this.h5 + f << 0;\n this.h6 = this.h6 + g << 0;\n this.h7 = this.h7 + h << 0;\n };\n Sha256.prototype.hex = function() {\n this.finalize();\n var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5, h6 = this.h6, h7 = this.h7;\n var hex = HEX_CHARS[h0 >>> 28 & 15] + HEX_CHARS[h0 >>> 24 & 15] + HEX_CHARS[h0 >>> 20 & 15] + HEX_CHARS[h0 >>> 16 & 15] + HEX_CHARS[h0 >>> 12 & 15] + HEX_CHARS[h0 >>> 8 & 15] + HEX_CHARS[h0 >>> 4 & 15] + HEX_CHARS[h0 & 15] + HEX_CHARS[h1 >>> 28 & 15] + HEX_CHARS[h1 >>> 24 & 15] + HEX_CHARS[h1 >>> 20 & 15] + HEX_CHARS[h1 >>> 16 & 15] + HEX_CHARS[h1 >>> 12 & 15] + HEX_CHARS[h1 >>> 8 & 15] + HEX_CHARS[h1 >>> 4 & 15] + HEX_CHARS[h1 & 15] + HEX_CHARS[h2 >>> 28 & 15] + HEX_CHARS[h2 >>> 24 & 15] + HEX_CHARS[h2 >>> 20 & 15] + HEX_CHARS[h2 >>> 16 & 15] + HEX_CHARS[h2 >>> 12 & 15] + HEX_CHARS[h2 >>> 8 & 15] + HEX_CHARS[h2 >>> 4 & 15] + HEX_CHARS[h2 & 15] + HEX_CHARS[h3 >>> 28 & 15] + HEX_CHARS[h3 >>> 24 & 15] + HEX_CHARS[h3 >>> 20 & 15] + HEX_CHARS[h3 >>> 16 & 15] + HEX_CHARS[h3 >>> 12 & 15] + HEX_CHARS[h3 >>> 8 & 15] + HEX_CHARS[h3 >>> 4 & 15] + HEX_CHARS[h3 & 15] + HEX_CHARS[h4 >>> 28 & 15] + HEX_CHARS[h4 >>> 24 & 15] + HEX_CHARS[h4 >>> 20 & 15] + HEX_CHARS[h4 >>> 16 & 15] + HEX_CHARS[h4 >>> 12 & 15] + HEX_CHARS[h4 >>> 8 & 15] + HEX_CHARS[h4 >>> 4 & 15] + HEX_CHARS[h4 & 15] + HEX_CHARS[h5 >>> 28 & 15] + HEX_CHARS[h5 >>> 24 & 15] + HEX_CHARS[h5 >>> 20 & 15] + HEX_CHARS[h5 >>> 16 & 15] + HEX_CHARS[h5 >>> 12 & 15] + HEX_CHARS[h5 >>> 8 & 15] + HEX_CHARS[h5 >>> 4 & 15] + HEX_CHARS[h5 & 15] + HEX_CHARS[h6 >>> 28 & 15] + HEX_CHARS[h6 >>> 24 & 15] + HEX_CHARS[h6 >>> 20 & 15] + HEX_CHARS[h6 >>> 16 & 15] + HEX_CHARS[h6 >>> 12 & 15] + HEX_CHARS[h6 >>> 8 & 15] + HEX_CHARS[h6 >>> 4 & 15] + HEX_CHARS[h6 & 15];\n if (!this.is224) {\n hex += HEX_CHARS[h7 >>> 28 & 15] + HEX_CHARS[h7 >>> 24 & 15] + HEX_CHARS[h7 >>> 20 & 15] + HEX_CHARS[h7 >>> 16 & 15] + HEX_CHARS[h7 >>> 12 & 15] + HEX_CHARS[h7 >>> 8 & 15] + HEX_CHARS[h7 >>> 4 & 15] + HEX_CHARS[h7 & 15];\n }\n return hex;\n };\n Sha256.prototype.toString = Sha256.prototype.hex;\n Sha256.prototype.digest = function() {\n this.finalize();\n var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5, h6 = this.h6, h7 = this.h7;\n var arr = [\n h0 >>> 24 & 255,\n h0 >>> 16 & 255,\n h0 >>> 8 & 255,\n h0 & 255,\n h1 >>> 24 & 255,\n h1 >>> 16 & 255,\n h1 >>> 8 & 255,\n h1 & 255,\n h2 >>> 24 & 255,\n h2 >>> 16 & 255,\n h2 >>> 8 & 255,\n h2 & 255,\n h3 >>> 24 & 255,\n h3 >>> 16 & 255,\n h3 >>> 8 & 255,\n h3 & 255,\n h4 >>> 24 & 255,\n h4 >>> 16 & 255,\n h4 >>> 8 & 255,\n h4 & 255,\n h5 >>> 24 & 255,\n h5 >>> 16 & 255,\n h5 >>> 8 & 255,\n h5 & 255,\n h6 >>> 24 & 255,\n h6 >>> 16 & 255,\n h6 >>> 8 & 255,\n h6 & 255\n ];\n if (!this.is224) {\n arr.push(h7 >>> 24 & 255, h7 >>> 16 & 255, h7 >>> 8 & 255, h7 & 255);\n }\n return arr;\n };\n Sha256.prototype.array = Sha256.prototype.digest;\n Sha256.prototype.arrayBuffer = function() {\n this.finalize();\n var buffer = new ArrayBuffer(this.is224 ? 28 : 32);\n var dataView = new DataView(buffer);\n dataView.setUint32(0, this.h0);\n dataView.setUint32(4, this.h1);\n dataView.setUint32(8, this.h2);\n dataView.setUint32(12, this.h3);\n dataView.setUint32(16, this.h4);\n dataView.setUint32(20, this.h5);\n dataView.setUint32(24, this.h6);\n if (!this.is224) {\n dataView.setUint32(28, this.h7);\n }\n return buffer;\n };\n function HmacSha256(key, is224, sharedMemory) {\n var i, type = typeof key;\n if (type === "string") {\n var bytes = [], length = key.length, index = 0, code;\n for (i = 0; i < length; ++i) {\n code = key.charCodeAt(i);\n if (code < 128) {\n bytes[index++] = code;\n } else if (code < 2048) {\n bytes[index++] = 192 | code >>> 6;\n bytes[index++] = 128 | code & 63;\n } else if (code < 55296 || code >= 57344) {\n bytes[index++] = 224 | code >>> 12;\n bytes[index++] = 128 | code >>> 6 & 63;\n bytes[index++] = 128 | code & 63;\n } else {\n code = 65536 + ((code & 1023) << 10 | key.charCodeAt(++i) & 1023);\n bytes[index++] = 240 | code >>> 18;\n bytes[index++] = 128 | code >>> 12 & 63;\n bytes[index++] = 128 | code >>> 6 & 63;\n bytes[index++] = 128 | code & 63;\n }\n }\n key = bytes;\n } else {\n if (type === "object") {\n if (key === null) {\n throw new Error(ERROR);\n } else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) {\n key = new Uint8Array(key);\n } else if (!Array.isArray(key)) {\n if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) {\n throw new Error(ERROR);\n }\n }\n } else {\n throw new Error(ERROR);\n }\n }\n if (key.length > 64) {\n key = new Sha256(is224, true).update(key).array();\n }\n var oKeyPad = [], iKeyPad = [];\n for (i = 0; i < 64; ++i) {\n var b = key[i] || 0;\n oKeyPad[i] = 92 ^ b;\n iKeyPad[i] = 54 ^ b;\n }\n Sha256.call(this, is224, sharedMemory);\n this.update(iKeyPad);\n this.oKeyPad = oKeyPad;\n this.inner = true;\n this.sharedMemory = sharedMemory;\n }\n HmacSha256.prototype = new Sha256();\n HmacSha256.prototype.finalize = function() {\n Sha256.prototype.finalize.call(this);\n if (this.inner) {\n this.inner = false;\n var innerHash = this.array();\n Sha256.call(this, this.is224, this.sharedMemory);\n this.update(this.oKeyPad);\n this.update(innerHash);\n Sha256.prototype.finalize.call(this);\n }\n };\n var exports2 = createMethod();\n exports2.sha256 = exports2;\n exports2.sha224 = createMethod(true);\n exports2.sha256.hmac = createHmacMethod();\n exports2.sha224.hmac = createHmacMethod(true);\n if (COMMON_JS) {\n module.exports = exports2;\n } else {\n root.sha256 = exports2.sha256;\n root.sha224 = exports2.sha224;\n if (AMD) {\n define(function() {\n return exports2;\n });\n }\n }\n })();\n }\n });\n\n // src/extractor/index.ts\n var extractor_exports = {};\n __export(extractor_exports, {\n descriptionOfTree: () => descriptionOfTree,\n generateElementByPosition: () => generateElementByPosition,\n getElementInfoByXpath: () => getElementInfoByXpath,\n getNodeFromCacheList: () => getNodeFromCacheList,\n getNodeInfoByXpath: () => getNodeInfoByXpath,\n getXpathsById: () => getXpathsById,\n getXpathsByPoint: () => getXpathsByPoint,\n isNotContainerElement: () => isNotContainerElement,\n setNodeHashCacheListOnWindow: () => setNodeHashCacheListOnWindow,\n traverseTree: () => traverseTree,\n treeToList: () => treeToList,\n trimAttributes: () => trimAttributes,\n truncateText: () => truncateText,\n webExtractNodeTree: () => extractTreeNode,\n webExtractNodeTreeAsString: () => extractTreeNodeAsString,\n webExtractTextWithPosition: () => extractTextWithPosition\n });\n\n // src/extractor/tree.ts\n function truncateText(text, maxLength = 150) {\n if (typeof text === "undefined") {\n return "";\n }\n if (typeof text === "object") {\n text = JSON.stringify(text);\n }\n if (typeof text === "number") {\n return text.toString();\n }\n if (typeof text === "string" && text.length > maxLength) {\n return `${text.slice(0, maxLength)}...`;\n }\n if (typeof text === "string") {\n return text.trim();\n }\n return "";\n }\n function trimAttributes(attributes, truncateTextLength) {\n const tailorAttributes = Object.keys(attributes).reduce(\n (res, currentKey) => {\n const attributeVal = attributes[currentKey];\n if (currentKey === "style" || currentKey === "htmlTagName" || currentKey === "nodeType") {\n return res;\n }\n res[currentKey] = truncateText(attributeVal, truncateTextLength);\n return res;\n },\n {}\n );\n return tailorAttributes;\n }\n var nodeSizeThreshold = 4;\n function descriptionOfTree(tree, truncateTextLength, filterNonTextContent = false, visibleOnly = true) {\n const attributesString = (kv) => {\n return Object.entries(kv).map(\n ([key, value]) => `${key}="${truncateText(value, truncateTextLength)}"`\n ).join(" ");\n };\n function buildContentTree(node, indent = 0, visibleOnly2 = true) {\n var _a;\n let before = "";\n let contentWithIndent = "";\n let after = "";\n let emptyNode = true;\n const indentStr = " ".repeat(indent);\n let children = "";\n for (let i = 0; i < (node.children || []).length; i++) {\n const childContent = buildContentTree(\n node.children[i],\n indent + 1,\n visibleOnly2\n );\n if (childContent) {\n children += `\n${childContent}`;\n }\n }\n if (node.node && node.node.rect.width > nodeSizeThreshold && node.node.rect.height > nodeSizeThreshold && (!filterNonTextContent || filterNonTextContent && node.node.content) && (!visibleOnly2 || visibleOnly2 && node.node.isVisible)) {\n emptyNode = false;\n let nodeTypeString;\n if ((_a = node.node.attributes) == null ? void 0 : _a.htmlTagName) {\n nodeTypeString = node.node.attributes.htmlTagName.replace(/[<>]/g, "");\n } else {\n nodeTypeString = node.node.attributes.nodeType.replace(/\\sNode$/, "").toLowerCase();\n }\n const markerId = node.node.indexId;\n const markerIdString = markerId ? `markerId="${markerId}"` : "";\n const rectAttribute = node.node.rect ? {\n left: node.node.rect.left,\n top: node.node.rect.top,\n width: node.node.rect.width,\n height: node.node.rect.height\n } : {};\n before = `<${nodeTypeString} id="${node.node.id}" ${markerIdString} ${attributesString(trimAttributes(node.node.attributes || {}, truncateTextLength))} ${attributesString(rectAttribute)}>`;\n const content = truncateText(node.node.content, truncateTextLength);\n contentWithIndent = content ? `\n${indentStr} ${content}` : "";\n after = `</${nodeTypeString}>`;\n } else if (!filterNonTextContent) {\n if (!children.trim().startsWith("<>")) {\n before = "<>";\n contentWithIndent = "";\n after = "</>";\n }\n }\n if (emptyNode && !children.trim()) {\n return "";\n }\n const result2 = `${indentStr}${before}${contentWithIndent}${children}\n${indentStr}${after}`;\n if (result2.trim()) {\n return result2;\n }\n return "";\n }\n const result = buildContentTree(tree, 0, visibleOnly);\n return result.replace(/^\\s*\\n/gm, "");\n }\n function treeToList(tree) {\n const result = [];\n function dfs(node) {\n if (node.node) {\n result.push(node.node);\n }\n for (const child of node.children) {\n dfs(child);\n }\n }\n dfs(tree);\n return result;\n }\n function traverseTree(tree, onNode) {\n function dfs(node) {\n if (node.node) {\n node.node = onNode(node.node);\n }\n for (const child of node.children) {\n dfs(child);\n }\n }\n dfs(tree);\n return tree;\n }\n\n // src/constants/index.ts\n var CONTAINER_MINI_HEIGHT = 3;\n var CONTAINER_MINI_WIDTH = 3;\n\n // src/utils.ts\n var import_js_sha256 = __toESM(require_sha256());\n var hashMap = {};\n function generateHashId(rect, content = "") {\n const combined = JSON.stringify({\n content,\n rect\n });\n let sliceLength = 5;\n let slicedHash = "";\n const hashHex = import_js_sha256.sha256.create().update(combined).hex();\n const toLetters = (hex) => {\n return hex.split("").map((char) => {\n const code = Number.parseInt(char, 16);\n return String.fromCharCode(97 + code % 26);\n }).join("");\n };\n const hashLetters = toLetters(hashHex);\n while (sliceLength < hashLetters.length - 1) {\n slicedHash = hashLetters.slice(0, sliceLength);\n if (hashMap[slicedHash] && hashMap[slicedHash] !== combined) {\n sliceLength++;\n continue;\n }\n hashMap[slicedHash] = combined;\n break;\n }\n return slicedHash;\n }\n\n // src/extractor/dom-util.ts\n function isFormElement(node) {\n return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea" || node.tagName.toLowerCase() === "select" || node.tagName.toLowerCase() === "option");\n }\n function isButtonElement(node) {\n return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";\n }\n function isAElement(node) {\n return node instanceof HTMLElement && node.tagName.toLowerCase() === "a";\n }\n function isSvgElement(node) {\n return node instanceof SVGElement;\n }\n function isImgElement(node) {\n if (!includeBaseElement(node) && node instanceof Element) {\n const computedStyle = window.getComputedStyle(node);\n const backgroundImage = computedStyle.getPropertyValue("background-image");\n if (backgroundImage !== "none") {\n return true;\n }\n }\n if (isIconfont(node)) {\n return true;\n }\n return node instanceof HTMLElement && node.tagName.toLowerCase() === "img" || node instanceof SVGElement && node.tagName.toLowerCase() === "svg";\n }\n function isIconfont(node) {\n if (node instanceof Element) {\n const computedStyle = window.getComputedStyle(node);\n const fontFamilyValue = computedStyle.fontFamily || "";\n return fontFamilyValue.toLowerCase().indexOf("iconfont") >= 0;\n }\n return false;\n }\n function isNotContainerElement(node) {\n return isTextElement(node) || isIconfont(node) || isImgElement(node) || isButtonElement(node) || isAElement(node) || isFormElement(node);\n }\n function isTextElement(node) {\n var _a, _b, _c;\n if (node instanceof Element) {\n if (((_a = node == null ? void 0 : node.childNodes) == null ? void 0 : _a.length) === 1 && (node == null ? void 0 : node.childNodes[0]) instanceof Text) {\n return true;\n }\n }\n return ((_c = (_b = node.nodeName) == null ? void 0 : _b.toLowerCase) == null ? void 0 : _c.call(_b)) === "#text" && !isIconfont(node);\n }\n function isContainerElement(node) {\n if (!(node instanceof HTMLElement))\n return false;\n if (includeBaseElement(node)) {\n return false;\n }\n const computedStyle = window.getComputedStyle(node);\n const backgroundColor = computedStyle.getPropertyValue("background-color");\n if (backgroundColor) {\n return true;\n }\n return false;\n }\n function includeBaseElement(node) {\n if (!(node instanceof HTMLElement))\n return false;\n if (node.innerText) {\n return true;\n }\n const includeList = [\n "svg",\n "button",\n "input",\n "textarea",\n "select",\n "option",\n "img",\n "a"\n ];\n for (const tagName of includeList) {\n const element = node.querySelectorAll(tagName);\n if (element.length > 0) {\n return true;\n }\n }\n return false;\n }\n function generateElementByPosition(position) {\n const rect = {\n left: Math.max(position.x - 4, 0),\n top: Math.max(position.y - 4, 0),\n width: 8,\n height: 8\n };\n const id = generateHashId(rect);\n const element = {\n id,\n attributes: { nodeType: "POSITION Node" /* POSITION */ },\n rect,\n content: "",\n center: [position.x, position.y]\n };\n return element;\n }\n\n // src/extractor/util.ts\n var MAX_VALUE_LENGTH = 300;\n var debugMode = false;\n function setDebugMode(mode) {\n debugMode = mode;\n }\n function logger(..._msg) {\n if (!debugMode) {\n return;\n }\n console.log(..._msg);\n }\n function isElementPartiallyInViewport(rect, currentWindow, currentDocument, visibleAreaRatio = 2 / 3) {\n const elementHeight = rect.height;\n const elementWidth = rect.width;\n const viewportRect = {\n left: 0,\n top: 0,\n width: currentWindow.innerWidth || currentDocument.documentElement.clientWidth,\n height: currentWindow.innerHeight || currentDocument.documentElement.clientHeight,\n right: currentWindow.innerWidth || currentDocument.documentElement.clientWidth,\n bottom: currentWindow.innerHeight || currentDocument.documentElement.clientHeight,\n x: 0,\n y: 0,\n zoom: 1\n };\n const overlapRect = overlappedRect(rect, viewportRect);\n if (!overlapRect) {\n return false;\n }\n const visibleArea = overlapRect.width * overlapRect.height;\n const totalArea = elementHeight * elementWidth;\n return visibleArea / totalArea >= visibleAreaRatio;\n }\n function getPseudoElementContent(element, currentWindow) {\n if (!(element instanceof currentWindow.HTMLElement)) {\n return { before: "", after: "" };\n }\n const beforeContent = currentWindow.getComputedStyle(element, "::before").getPropertyValue("content");\n const afterContent = currentWindow.getComputedStyle(element, "::after").getPropertyValue("content");\n return {\n before: beforeContent === "none" ? "" : beforeContent.replace(/"/g, ""),\n after: afterContent === "none" ? "" : afterContent.replace(/"/g, "")\n };\n }\n function overlappedRect(rect1, rect2) {\n const left = Math.max(rect1.left, rect2.left);\n const top = Math.max(rect1.top, rect2.top);\n const right = Math.min(rect1.right, rect2.right);\n const bottom = Math.min(rect1.bottom, rect2.bottom);\n if (left < right && top < bottom) {\n return {\n left,\n top,\n right,\n bottom,\n width: right - left,\n height: bottom - top,\n x: left,\n y: top,\n zoom: 1\n };\n }\n return null;\n }\n function getRect(el, baseZoom, currentWindow) {\n let originalRect;\n let newZoom = 1;\n if (!(el instanceof currentWindow.HTMLElement)) {\n const range = currentWindow.document.createRange();\n range.selectNodeContents(el);\n originalRect = range.getBoundingClientRect();\n } else {\n originalRect = el.getBoundingClientRect();\n if (!("currentCSSZoom" in el)) {\n newZoom = Number.parseFloat(currentWindow.getComputedStyle(el).zoom) || 1;\n }\n }\n const zoom = newZoom * baseZoom;\n return {\n width: originalRect.width * zoom,\n height: originalRect.height * zoom,\n left: originalRect.left * zoom,\n top: originalRect.top * zoom,\n right: originalRect.right * zoom,\n bottom: originalRect.bottom * zoom,\n x: originalRect.x * zoom,\n y: originalRect.y * zoom,\n zoom\n };\n }\n var isElementCovered = (el, rect, currentWindow) => {\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n const topElement = currentWindow.document.elementFromPoint(x, y);\n if (!topElement) {\n return false;\n }\n if (topElement === el) {\n return false;\n }\n if (el == null ? void 0 : el.contains(topElement)) {\n return false;\n }\n if (topElement == null ? void 0 : topElement.contains(el)) {\n return false;\n }\n const rectOfTopElement = getRect(topElement, 1, currentWindow);\n const overlapRect = overlappedRect(rect, rectOfTopElement);\n if (!overlapRect) {\n return false;\n }\n logger(el, "Element is covered by another element", {\n topElement,\n el,\n rect,\n x,\n y\n });\n return true;\n };\n function elementRect(el, currentWindow, currentDocument, baseZoom = 1) {\n if (!el) {\n logger(el, "Element is not in the DOM hierarchy");\n return false;\n }\n if (!(el instanceof currentWindow.HTMLElement) && el.nodeType !== Node.TEXT_NODE && el.nodeName.toLowerCase() !== "svg") {\n logger(el, "Element is not in the DOM hierarchy");\n return false;\n }\n if (el instanceof currentWindow.HTMLElement) {\n const style = currentWindow.getComputedStyle(el);\n if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" && el.tagName !== "INPUT") {\n logger(el, "Element is hidden");\n return false;\n }\n }\n const rect = getRect(el, baseZoom, currentWindow);\n if (rect.width === 0 && rect.height === 0) {\n logger(el, "Element has no size");\n return false;\n }\n if (baseZoom === 1 && isElementCovered(el, rect, currentWindow)) {\n return false;\n }\n const isVisible = isElementPartiallyInViewport(\n rect,\n currentWindow,\n currentDocument\n );\n let parent = el;\n const parentUntilNonStatic = (currentNode) => {\n let parent2 = currentNode == null ? void 0 : currentNode.parentElement;\n while (parent2) {\n const style = currentWindow.getComputedStyle(parent2);\n if (style.position !== "static") {\n return parent2;\n }\n parent2 = parent2.parentElement;\n }\n return null;\n };\n while (parent && parent !== currentDocument.body) {\n if (!(parent instanceof currentWindow.HTMLElement)) {\n parent = parent.parentElement;\n continue;\n }\n const parentStyle = currentWindow.getComputedStyle(parent);\n if (parentStyle.overflow === "hidden") {\n const parentRect = getRect(parent, 1, currentWindow);\n const tolerance = 10;\n if (rect.right < parentRect.left - tolerance || rect.left > parentRect.right + tolerance || rect.bottom < parentRect.top - tolerance || rect.top > parentRect.bottom + tolerance) {\n logger(el, "element is partially or totally hidden by an ancestor", {\n rect,\n parentRect\n });\n return false;\n }\n }\n if (parentStyle.position === "fixed" || parentStyle.position === "sticky") {\n break;\n }\n if (parentStyle.position === "absolute") {\n parent = parentUntilNonStatic(parent);\n } else {\n parent = parent.parentElement;\n }\n }\n return {\n left: Math.round(rect.left),\n top: Math.round(rect.top),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n zoom: rect.zoom,\n isVisible\n };\n }\n function getNodeAttributes(node, currentWindow) {\n if (!node || !(node instanceof currentWindow.HTMLElement) || !node.attributes) {\n return {};\n }\n const attributesList = Array.from(node.attributes).map((attr) => {\n if (attr.name === "class") {\n return [attr.name, `.${attr.value.split(" ").join(".")}`];\n }\n if (!attr.value) {\n return [];\n }\n let value = attr.value;\n if (value.startsWith("data:image")) {\n value = "image";\n }\n if (value.length > MAX_VALUE_LENGTH) {\n value = `${value.slice(0, MAX_VALUE_LENGTH)}...`;\n }\n return [attr.name, value];\n });\n return Object.fromEntries(attributesList);\n }\n function midsceneGenerateHash(node, content, rect) {\n const slicedHash = generateHashId(rect, content);\n if (node) {\n if (!window.midsceneNodeHashCacheList) {\n setNodeHashCacheListOnWindow();\n }\n setNodeToCacheList(node, slicedHash);\n }\n return slicedHash;\n }\n function setNodeHashCacheListOnWindow() {\n if (typeof window !== "undefined") {\n window.midsceneNodeHashCacheList = [];\n }\n }\n function setNodeToCacheList(node, id) {\n var _a;\n if (typeof window !== "undefined") {\n if (getNodeFromCacheList(id)) {\n return;\n }\n (_a = window.midsceneNodeHashCacheList) == null ? void 0 : _a.push({ node, id });\n }\n }\n function getNodeFromCacheList(id) {\n var _a, _b;\n if (typeof window !== "undefined") {\n return (_b = (_a = window.midsceneNodeHashCacheList) == null ? void 0 : _a.find(\n (item) => item.id === id\n )) == null ? void 0 : _b.node;\n }\n return null;\n }\n function getTopDocument() {\n const container = document.body || document;\n return container;\n }\n\n // src/extractor/web-extractor.ts\n var indexId = 0;\n function tagNameOfNode(node) {\n var _a, _b;\n let tagName = "";\n if (node instanceof HTMLElement) {\n tagName = (_a = node.tagName) == null ? void 0 : _a.toLowerCase();\n } else {\n const parentElement = node.parentElement;\n if (parentElement && parentElement instanceof HTMLElement) {\n tagName = (_b = parentElement.tagName) == null ? void 0 : _b.toLowerCase();\n }\n }\n return tagName ? `<${tagName}>` : "";\n }\n function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1, basePoint = { left: 0, top: 0 }, isContainer = false) {\n var _a, _b;\n const rect = elementRect(node, currentWindow, currentDocument, baseZoom);\n if (!rect) {\n return null;\n }\n if (rect.width < CONTAINER_MINI_WIDTH || rect.height < CONTAINER_MINI_HEIGHT) {\n return null;\n }\n if (basePoint.left !== 0 || basePoint.top !== 0) {\n rect.left += basePoint.left;\n rect.top += basePoint.top;\n }\n if (rect.height >= window.innerHeight && rect.width >= window.innerWidth) {\n return null;\n }\n if (isFormElement(node)) {\n const attributes = getNodeAttributes(node, currentWindow);\n let valueContent = attributes.value || attributes.placeholder || node.textContent || "";\n const nodeHashId = midsceneGenerateHash(node, valueContent, rect);\n const tagName = node.tagName.toLowerCase();\n if (node.tagName.toLowerCase() === "select") {\n const selectedOption = node.options[node.selectedIndex];\n valueContent = (selectedOption == null ? void 0 : selectedOption.textContent) || "";\n }\n if ((node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea") && node.value) {\n valueContent = node.value;\n }\n const elementInfo = {\n id: nodeHashId,\n nodeHashId,\n nodeType: "FORM_ITEM Node" /* FORM_ITEM */,\n indexId: indexId++,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n htmlTagName: `<${tagName}>`,\n nodeType: "FORM_ITEM Node" /* FORM_ITEM */\n }),\n content: valueContent.trim(),\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isButtonElement(node)) {\n const rect2 = mergeElementAndChildrenRects(\n node,\n currentWindow,\n currentDocument,\n baseZoom\n );\n if (!rect2) {\n return null;\n }\n const attributes = getNodeAttributes(node, currentWindow);\n const pseudo = getPseudoElementContent(node, currentWindow);\n const content = node.innerText || pseudo.before || pseudo.after || "";\n const nodeHashId = midsceneGenerateHash(node, content, rect2);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n nodeType: "BUTTON Node" /* BUTTON */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n htmlTagName: tagNameOfNode(node),\n nodeType: "BUTTON Node" /* BUTTON */\n }),\n content,\n rect: rect2,\n center: [\n Math.round(rect2.left + rect2.width / 2),\n Math.round(rect2.top + rect2.height / 2)\n ],\n zoom: rect2.zoom,\n isVisible: rect2.isVisible\n };\n return elementInfo;\n }\n if (isImgElement(node)) {\n const attributes = getNodeAttributes(node, currentWindow);\n const nodeHashId = midsceneGenerateHash(node, "", rect);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n attributes: __spreadProps(__spreadValues(__spreadValues({}, attributes), ((_a = node.nodeName) == null ? void 0 : _a.toLowerCase()) === "svg" ? {\n svgContent: "true"\n } : {}), {\n nodeType: "IMG Node" /* IMG */,\n htmlTagName: tagNameOfNode(node)\n }),\n nodeType: "IMG Node" /* IMG */,\n content: "",\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isTextElement(node)) {\n const text = (_b = node.textContent) == null ? void 0 : _b.trim().replace(/\\n+/g, " ");\n if (!text) {\n return null;\n }\n const attributes = getNodeAttributes(node, currentWindow);\n const attributeKeys = Object.keys(attributes);\n if (!text.trim() && attributeKeys.length === 0) {\n return null;\n }\n const nodeHashId = midsceneGenerateHash(node, text, rect);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n nodeType: "TEXT Node" /* TEXT */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n nodeType: "TEXT Node" /* TEXT */,\n htmlTagName: tagNameOfNode(node)\n }),\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n content: text,\n rect,\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isAElement(node)) {\n const attributes = getNodeAttributes(node, currentWindow);\n const pseudo = getPseudoElementContent(node, currentWindow);\n const content = node.innerText || pseudo.before || pseudo.after || "";\n const nodeHashId = midsceneGenerateHash(node, content, rect);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n nodeType: "Anchor Node" /* A */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n htmlTagName: tagNameOfNode(node),\n nodeType: "Anchor Node" /* A */\n }),\n content,\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isContainerElement(node) || isContainer) {\n const attributes = getNodeAttributes(node, currentWindow);\n const nodeHashId = midsceneGenerateHash(node, "", rect);\n const elementInfo = {\n id: nodeHashId,\n nodeHashId,\n indexId: indexId++,\n nodeType: "CONTAINER Node" /* CONTAINER */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n nodeType: "CONTAINER Node" /* CONTAINER */,\n htmlTagName: tagNameOfNode(node)\n }),\n content: "",\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n return null;\n }\n function extractTextWithPosition(initNode, debugMode2 = false) {\n const elementNode = extractTreeNode(initNode, debugMode2);\n const elementInfoArray = [];\n function dfsTopChildren(node) {\n if (node.node) {\n elementInfoArray.push(node.node);\n }\n for (let i = 0; i < node.children.length; i++) {\n dfsTopChildren(node.children[i]);\n }\n }\n dfsTopChildren({ children: elementNode.children, node: elementNode.node });\n return elementInfoArray;\n }\n function extractTreeNodeAsString(initNode, visibleOnly = false, debugMode2 = false) {\n const elementNode = extractTreeNode(initNode, debugMode2);\n return descriptionOfTree(elementNode, void 0, false, visibleOnly);\n }\n function extractTreeNode(initNode, debugMode2 = false) {\n setDebugMode(debugMode2);\n indexId = 0;\n const topDocument = getTopDocument();\n const startNode = initNode || topDocument;\n const topChildren = [];\n function dfs(node, currentWindow, currentDocument, baseZoom = 1, basePoint = { left: 0, top: 0 }) {\n if (!node) {\n return null;\n }\n if (node.nodeType && node.nodeType === 10) {\n return null;\n }\n const elementInfo = collectElementInfo(\n node,\n currentWindow,\n currentDocument,\n baseZoom,\n basePoint\n );\n if (node instanceof currentWindow.HTMLIFrameElement) {\n if (node.contentWindow && node.contentWindow) {\n return null;\n }\n }\n const nodeInfo = {\n node: elementInfo,\n children: []\n };\n if ((elementInfo == null ? void 0 : elementInfo.nodeType) === "BUTTON Node" /* BUTTON */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "IMG Node" /* IMG */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "TEXT Node" /* TEXT */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "FORM_ITEM Node" /* FORM_ITEM */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "CONTAINER Node" /* CONTAINER */) {\n return nodeInfo;\n }\n const rect = getRect(node, baseZoom, currentWindow);\n for (let i = 0; i < node.childNodes.length; i++) {\n logger("will dfs", node.childNodes[i]);\n const childNodeInfo = dfs(\n node.childNodes[i],\n currentWindow,\n currentDocument,\n rect.zoom,\n basePoint\n );\n if (Array.isArray(childNodeInfo)) {\n nodeInfo.children.push(...childNodeInfo);\n } else if (childNodeInfo) {\n nodeInfo.children.push(childNodeInfo);\n }\n }\n if (nodeInfo.node === null) {\n if (nodeInfo.children.length === 0) {\n return null;\n }\n return nodeInfo.children;\n }\n return nodeInfo;\n }\n const rootNodeInfo = dfs(startNode, window, document, 1, {\n left: 0,\n top: 0\n });\n if (Array.isArray(rootNodeInfo)) {\n topChildren.push(...rootNodeInfo);\n } else if (rootNodeInfo) {\n topChildren.push(rootNodeInfo);\n }\n if (startNode === topDocument) {\n const iframes = document.querySelectorAll("iframe");\n for (let i = 0; i < iframes.length; i++) {\n const iframe = iframes[i];\n if (iframe.contentDocument && iframe.contentWindow) {\n const iframeInfo = collectElementInfo(iframe, window, document, 1);\n if (iframeInfo) {\n const iframeChildren = dfs(\n iframe.contentDocument.body,\n iframe.contentWindow,\n iframe.contentDocument,\n 1,\n {\n left: iframeInfo.rect.left,\n top: iframeInfo.rect.top\n }\n );\n if (Array.isArray(iframeChildren)) {\n topChildren.push(...iframeChildren);\n } else if (iframeChildren) {\n topChildren.push(iframeChildren);\n }\n }\n }\n }\n }\n return {\n node: null,\n children: topChildren\n };\n }\n function mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom = 1) {\n const selfRect = elementRect(node, currentWindow, currentDocument, baseZoom);\n if (!selfRect)\n return null;\n let minLeft = selfRect.left;\n let minTop = selfRect.top;\n let maxRight = selfRect.left + selfRect.width;\n let maxBottom = selfRect.top + selfRect.height;\n function traverse(child) {\n for (let i = 0; i < child.childNodes.length; i++) {\n const sub = child.childNodes[i];\n if (sub.nodeType === 1) {\n const rect = elementRect(sub, currentWindow, currentDocument, baseZoom);\n if (rect) {\n minLeft = Math.min(minLeft, rect.left);\n minTop = Math.min(minTop, rect.top);\n maxRight = Math.max(maxRight, rect.left + rect.width);\n maxBottom = Math.max(maxBottom, rect.top + rect.height);\n }\n traverse(sub);\n }\n }\n }\n traverse(node);\n return __spreadProps(__spreadValues({}, selfRect), {\n left: minLeft,\n top: minTop,\n width: maxRight - minLeft,\n height: maxBottom - minTop\n });\n }\n\n // src/extractor/locator.ts\n var getElementXpathIndex = (element) => {\n let index = 1;\n let prev = element.previousElementSibling;\n while (prev) {\n if (prev.nodeName.toLowerCase() === element.nodeName.toLowerCase()) {\n index++;\n }\n prev = prev.previousElementSibling;\n }\n return index;\n };\n var normalizeXpathText = (text) => {\n if (typeof text !== "string") {\n return "";\n }\n return text.replace(/\\s+/g, " ").trim();\n };\n var buildCurrentElementXpath = (element, isOrderSensitive, isLeafElement) => {\n var _a;\n const parentPath = element.parentNode ? getElementXpath(element.parentNode, isOrderSensitive) : "";\n const prefix = parentPath ? `${parentPath}/` : "/";\n const tagName = element.nodeName.toLowerCase();\n const textContent = (_a = element.textContent) == null ? void 0 : _a.trim();\n if (isOrderSensitive) {\n const index2 = getElementXpathIndex(element);\n return `${prefix}${tagName}[${index2}]`;\n }\n if (isLeafElement && textContent) {\n return `${prefix}${tagName}[normalize-space()="${normalizeXpathText(textContent)}"]`;\n }\n const index = getElementXpathIndex(element);\n return `${prefix}${tagName}[${index}]`;\n };\n var getElementXpath = (element, isOrderSensitive = false, isLeafElement = false) => {\n var _a;\n if (element.nodeType === Node.TEXT_NODE) {\n const parentNode = element.parentNode;\n if (parentNode && parentNode.nodeType === Node.ELEMENT_NODE) {\n const parentXPath = getElementXpath(parentNode, isOrderSensitive, true);\n const textContent = (_a = element.textContent) == null ? void 0 : _a.trim();\n if (textContent) {\n return `${parentXPath}/text()[normalize-space()="${normalizeXpathText(textContent)}"]`;\n }\n return `${parentXPath}/text()`;\n }\n return "";\n }\n if (element.nodeType !== Node.ELEMENT_NODE)\n return "";\n const el = element;\n if (el === document.documentElement)\n return "/html";\n if (el === document.body)\n return "/html/body";\n if (isSvgElement(el)) {\n let parent = el.parentNode;\n while (parent && parent.nodeType === Node.ELEMENT_NODE) {\n if (!isSvgElement(parent)) {\n return getElementXpath(parent, isOrderSensitive, isLeafElement);\n }\n parent = parent.parentNode;\n }\n return getElementXpath(el.parentNode, isOrderSensitive, isLeafElement);\n }\n return buildCurrentElementXpath(el, isOrderSensitive, isLeafElement);\n };\n function getXpathsById(id) {\n const node = getNodeFromCacheList(id);\n if (!node) {\n return null;\n }\n const fullXPath = getElementXpath(node, false, true);\n return [fullXPath];\n }\n function getXpathsByPoint(point, isOrderSensitive) {\n const element = document.elementFromPoint(point.left, point.top);\n if (!element) {\n return null;\n }\n const fullXPath = getElementXpath(element, isOrderSensitive, true);\n return [fullXPath];\n }\n function getNodeInfoByXpath(xpath) {\n const xpathResult = document.evaluate(\n xpath,\n document,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n if (xpathResult.snapshotLength !== 1) {\n return null;\n }\n const node = xpathResult.snapshotItem(0);\n return node;\n }\n function getElementInfoByXpath(xpath) {\n const node = getNodeInfoByXpath(xpath);\n if (!node) {\n return null;\n }\n if (node instanceof HTMLElement) {\n const rect = getRect(node, 1, window);\n const isVisible = isElementPartiallyInViewport(rect, window, document, 1);\n if (!isVisible) {\n node.scrollIntoView({ behavior: "instant", block: "center" });\n }\n }\n return collectElementInfo(\n node,\n window,\n document,\n 1,\n {\n left: 0,\n top: 0\n },\n true\n );\n }\n return __toCommonJS(extractor_exports);\n})();\n/*! Bundled license information:\n\njs-sha256/src/sha256.js:\n (**\n * [js-sha256]{@link https://github.com/emn178/js-sha256}\n *\n * @version 0.11.0\n * @author Chen, Yi-Cyuan [emn178@gmail.com]\n * @copyright Chen, Yi-Cyuan 2014-2024\n * @license MIT\n *)\n*/\n';
|
|
50
|
+
const htmlElementScript = '"use strict";\nvar midscene_element_inspector = (() => {\n var __create = Object.create;\n var __defProp = Object.defineProperty;\n var __defProps = Object.defineProperties;\n var __getOwnPropDesc = Object.getOwnPropertyDescriptor;\n var __getOwnPropDescs = Object.getOwnPropertyDescriptors;\n var __getOwnPropNames = Object.getOwnPropertyNames;\n var __getOwnPropSymbols = Object.getOwnPropertySymbols;\n var __getProtoOf = Object.getPrototypeOf;\n var __hasOwnProp = Object.prototype.hasOwnProperty;\n var __propIsEnum = Object.prototype.propertyIsEnumerable;\n var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\n var __spreadValues = (a, b) => {\n for (var prop in b || (b = {}))\n if (__hasOwnProp.call(b, prop))\n __defNormalProp(a, prop, b[prop]);\n if (__getOwnPropSymbols)\n for (var prop of __getOwnPropSymbols(b)) {\n if (__propIsEnum.call(b, prop))\n __defNormalProp(a, prop, b[prop]);\n }\n return a;\n };\n var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));\n var __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n };\n var __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n };\n var __copyProps = (to, from, except, desc) => {\n if (from && typeof from === "object" || typeof from === "function") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n };\n var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. "__esModule" has not been set), then set\n // "default" to the CommonJS "module.exports" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,\n mod\n ));\n var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);\n\n // resolve-false:/empty-stub\n var require_empty_stub = __commonJS({\n "resolve-false:/empty-stub"(exports, module) {\n "use strict";\n module.exports = {};\n }\n });\n\n // ../../node_modules/.pnpm/js-sha256@0.11.0/node_modules/js-sha256/src/sha256.js\n var require_sha256 = __commonJS({\n "../../node_modules/.pnpm/js-sha256@0.11.0/node_modules/js-sha256/src/sha256.js"(exports, module) {\n "use strict";\n (function() {\n "use strict";\n var ERROR = "input is invalid type";\n var WINDOW = typeof window === "object";\n var root = WINDOW ? window : {};\n if (root.JS_SHA256_NO_WINDOW) {\n WINDOW = false;\n }\n var WEB_WORKER = !WINDOW && typeof self === "object";\n var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === "object" && process.versions && process.versions.node;\n if (NODE_JS) {\n root = global;\n } else if (WEB_WORKER) {\n root = self;\n }\n var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === "object" && module.exports;\n var AMD = typeof define === "function" && define.amd;\n var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== "undefined";\n var HEX_CHARS = "0123456789abcdef".split("");\n var EXTRA = [-2147483648, 8388608, 32768, 128];\n var SHIFT = [24, 16, 8, 0];\n var K = [\n 1116352408,\n 1899447441,\n 3049323471,\n 3921009573,\n 961987163,\n 1508970993,\n 2453635748,\n 2870763221,\n 3624381080,\n 310598401,\n 607225278,\n 1426881987,\n 1925078388,\n 2162078206,\n 2614888103,\n 3248222580,\n 3835390401,\n 4022224774,\n 264347078,\n 604807628,\n 770255983,\n 1249150122,\n 1555081692,\n 1996064986,\n 2554220882,\n 2821834349,\n 2952996808,\n 3210313671,\n 3336571891,\n 3584528711,\n 113926993,\n 338241895,\n 666307205,\n 773529912,\n 1294757372,\n 1396182291,\n 1695183700,\n 1986661051,\n 2177026350,\n 2456956037,\n 2730485921,\n 2820302411,\n 3259730800,\n 3345764771,\n 3516065817,\n 3600352804,\n 4094571909,\n 275423344,\n 430227734,\n 506948616,\n 659060556,\n 883997877,\n 958139571,\n 1322822218,\n 1537002063,\n 1747873779,\n 1955562222,\n 2024104815,\n 2227730452,\n 2361852424,\n 2428436474,\n 2756734187,\n 3204031479,\n 3329325298\n ];\n var OUTPUT_TYPES = ["hex", "array", "digest", "arrayBuffer"];\n var blocks = [];\n if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) {\n Array.isArray = function(obj) {\n return Object.prototype.toString.call(obj) === "[object Array]";\n };\n }\n if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {\n ArrayBuffer.isView = function(obj) {\n return typeof obj === "object" && obj.buffer && obj.buffer.constructor === ArrayBuffer;\n };\n }\n var createOutputMethod = function(outputType, is224) {\n return function(message) {\n return new Sha256(is224, true).update(message)[outputType]();\n };\n };\n var createMethod = function(is224) {\n var method = createOutputMethod("hex", is224);\n if (NODE_JS) {\n method = nodeWrap(method, is224);\n }\n method.create = function() {\n return new Sha256(is224);\n };\n method.update = function(message) {\n return method.create().update(message);\n };\n for (var i = 0; i < OUTPUT_TYPES.length; ++i) {\n var type = OUTPUT_TYPES[i];\n method[type] = createOutputMethod(type, is224);\n }\n return method;\n };\n var nodeWrap = function(method, is224) {\n var crypto = require_empty_stub();\n var Buffer2 = require_empty_stub().Buffer;\n var algorithm = is224 ? "sha224" : "sha256";\n var bufferFrom;\n if (Buffer2.from && !root.JS_SHA256_NO_BUFFER_FROM) {\n bufferFrom = Buffer2.from;\n } else {\n bufferFrom = function(message) {\n return new Buffer2(message);\n };\n }\n var nodeMethod = function(message) {\n if (typeof message === "string") {\n return crypto.createHash(algorithm).update(message, "utf8").digest("hex");\n } else {\n if (message === null || message === void 0) {\n throw new Error(ERROR);\n } else if (message.constructor === ArrayBuffer) {\n message = new Uint8Array(message);\n }\n }\n if (Array.isArray(message) || ArrayBuffer.isView(message) || message.constructor === Buffer2) {\n return crypto.createHash(algorithm).update(bufferFrom(message)).digest("hex");\n } else {\n return method(message);\n }\n };\n return nodeMethod;\n };\n var createHmacOutputMethod = function(outputType, is224) {\n return function(key, message) {\n return new HmacSha256(key, is224, true).update(message)[outputType]();\n };\n };\n var createHmacMethod = function(is224) {\n var method = createHmacOutputMethod("hex", is224);\n method.create = function(key) {\n return new HmacSha256(key, is224);\n };\n method.update = function(key, message) {\n return method.create(key).update(message);\n };\n for (var i = 0; i < OUTPUT_TYPES.length; ++i) {\n var type = OUTPUT_TYPES[i];\n method[type] = createHmacOutputMethod(type, is224);\n }\n return method;\n };\n function Sha256(is224, sharedMemory) {\n if (sharedMemory) {\n blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n this.blocks = blocks;\n } else {\n this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n }\n if (is224) {\n this.h0 = 3238371032;\n this.h1 = 914150663;\n this.h2 = 812702999;\n this.h3 = 4144912697;\n this.h4 = 4290775857;\n this.h5 = 1750603025;\n this.h6 = 1694076839;\n this.h7 = 3204075428;\n } else {\n this.h0 = 1779033703;\n this.h1 = 3144134277;\n this.h2 = 1013904242;\n this.h3 = 2773480762;\n this.h4 = 1359893119;\n this.h5 = 2600822924;\n this.h6 = 528734635;\n this.h7 = 1541459225;\n }\n this.block = this.start = this.bytes = this.hBytes = 0;\n this.finalized = this.hashed = false;\n this.first = true;\n this.is224 = is224;\n }\n Sha256.prototype.update = function(message) {\n if (this.finalized) {\n return;\n }\n var notString, type = typeof message;\n if (type !== "string") {\n if (type === "object") {\n if (message === null) {\n throw new Error(ERROR);\n } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {\n message = new Uint8Array(message);\n } else if (!Array.isArray(message)) {\n if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {\n throw new Error(ERROR);\n }\n }\n } else {\n throw new Error(ERROR);\n }\n notString = true;\n }\n var code, index = 0, i, length = message.length, blocks2 = this.blocks;\n while (index < length) {\n if (this.hashed) {\n this.hashed = false;\n blocks2[0] = this.block;\n this.block = blocks2[16] = blocks2[1] = blocks2[2] = blocks2[3] = blocks2[4] = blocks2[5] = blocks2[6] = blocks2[7] = blocks2[8] = blocks2[9] = blocks2[10] = blocks2[11] = blocks2[12] = blocks2[13] = blocks2[14] = blocks2[15] = 0;\n }\n if (notString) {\n for (i = this.start; index < length && i < 64; ++index) {\n blocks2[i >>> 2] |= message[index] << SHIFT[i++ & 3];\n }\n } else {\n for (i = this.start; index < length && i < 64; ++index) {\n code = message.charCodeAt(index);\n if (code < 128) {\n blocks2[i >>> 2] |= code << SHIFT[i++ & 3];\n } else if (code < 2048) {\n blocks2[i >>> 2] |= (192 | code >>> 6) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code & 63) << SHIFT[i++ & 3];\n } else if (code < 55296 || code >= 57344) {\n blocks2[i >>> 2] |= (224 | code >>> 12) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code >>> 6 & 63) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code & 63) << SHIFT[i++ & 3];\n } else {\n code = 65536 + ((code & 1023) << 10 | message.charCodeAt(++index) & 1023);\n blocks2[i >>> 2] |= (240 | code >>> 18) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code >>> 12 & 63) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code >>> 6 & 63) << SHIFT[i++ & 3];\n blocks2[i >>> 2] |= (128 | code & 63) << SHIFT[i++ & 3];\n }\n }\n }\n this.lastByteIndex = i;\n this.bytes += i - this.start;\n if (i >= 64) {\n this.block = blocks2[16];\n this.start = i - 64;\n this.hash();\n this.hashed = true;\n } else {\n this.start = i;\n }\n }\n if (this.bytes > 4294967295) {\n this.hBytes += this.bytes / 4294967296 << 0;\n this.bytes = this.bytes % 4294967296;\n }\n return this;\n };\n Sha256.prototype.finalize = function() {\n if (this.finalized) {\n return;\n }\n this.finalized = true;\n var blocks2 = this.blocks, i = this.lastByteIndex;\n blocks2[16] = this.block;\n blocks2[i >>> 2] |= EXTRA[i & 3];\n this.block = blocks2[16];\n if (i >= 56) {\n if (!this.hashed) {\n this.hash();\n }\n blocks2[0] = this.block;\n blocks2[16] = blocks2[1] = blocks2[2] = blocks2[3] = blocks2[4] = blocks2[5] = blocks2[6] = blocks2[7] = blocks2[8] = blocks2[9] = blocks2[10] = blocks2[11] = blocks2[12] = blocks2[13] = blocks2[14] = blocks2[15] = 0;\n }\n blocks2[14] = this.hBytes << 3 | this.bytes >>> 29;\n blocks2[15] = this.bytes << 3;\n this.hash();\n };\n Sha256.prototype.hash = function() {\n var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4, f = this.h5, g = this.h6, h = this.h7, blocks2 = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;\n for (j = 16; j < 64; ++j) {\n t1 = blocks2[j - 15];\n s0 = (t1 >>> 7 | t1 << 25) ^ (t1 >>> 18 | t1 << 14) ^ t1 >>> 3;\n t1 = blocks2[j - 2];\n s1 = (t1 >>> 17 | t1 << 15) ^ (t1 >>> 19 | t1 << 13) ^ t1 >>> 10;\n blocks2[j] = blocks2[j - 16] + s0 + blocks2[j - 7] + s1 << 0;\n }\n bc = b & c;\n for (j = 0; j < 64; j += 4) {\n if (this.first) {\n if (this.is224) {\n ab = 300032;\n t1 = blocks2[0] - 1413257819;\n h = t1 - 150054599 << 0;\n d = t1 + 24177077 << 0;\n } else {\n ab = 704751109;\n t1 = blocks2[0] - 210244248;\n h = t1 - 1521486534 << 0;\n d = t1 + 143694565 << 0;\n }\n this.first = false;\n } else {\n s0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10);\n s1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7);\n ab = a & b;\n maj = ab ^ a & c ^ bc;\n ch = e & f ^ ~e & g;\n t1 = h + s1 + ch + K[j] + blocks2[j];\n t2 = s0 + maj;\n h = d + t1 << 0;\n d = t1 + t2 << 0;\n }\n s0 = (d >>> 2 | d << 30) ^ (d >>> 13 | d << 19) ^ (d >>> 22 | d << 10);\n s1 = (h >>> 6 | h << 26) ^ (h >>> 11 | h << 21) ^ (h >>> 25 | h << 7);\n da = d & a;\n maj = da ^ d & b ^ ab;\n ch = h & e ^ ~h & f;\n t1 = g + s1 + ch + K[j + 1] + blocks2[j + 1];\n t2 = s0 + maj;\n g = c + t1 << 0;\n c = t1 + t2 << 0;\n s0 = (c >>> 2 | c << 30) ^ (c >>> 13 | c << 19) ^ (c >>> 22 | c << 10);\n s1 = (g >>> 6 | g << 26) ^ (g >>> 11 | g << 21) ^ (g >>> 25 | g << 7);\n cd = c & d;\n maj = cd ^ c & a ^ da;\n ch = g & h ^ ~g & e;\n t1 = f + s1 + ch + K[j + 2] + blocks2[j + 2];\n t2 = s0 + maj;\n f = b + t1 << 0;\n b = t1 + t2 << 0;\n s0 = (b >>> 2 | b << 30) ^ (b >>> 13 | b << 19) ^ (b >>> 22 | b << 10);\n s1 = (f >>> 6 | f << 26) ^ (f >>> 11 | f << 21) ^ (f >>> 25 | f << 7);\n bc = b & c;\n maj = bc ^ b & d ^ cd;\n ch = f & g ^ ~f & h;\n t1 = e + s1 + ch + K[j + 3] + blocks2[j + 3];\n t2 = s0 + maj;\n e = a + t1 << 0;\n a = t1 + t2 << 0;\n this.chromeBugWorkAround = true;\n }\n this.h0 = this.h0 + a << 0;\n this.h1 = this.h1 + b << 0;\n this.h2 = this.h2 + c << 0;\n this.h3 = this.h3 + d << 0;\n this.h4 = this.h4 + e << 0;\n this.h5 = this.h5 + f << 0;\n this.h6 = this.h6 + g << 0;\n this.h7 = this.h7 + h << 0;\n };\n Sha256.prototype.hex = function() {\n this.finalize();\n var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5, h6 = this.h6, h7 = this.h7;\n var hex = HEX_CHARS[h0 >>> 28 & 15] + HEX_CHARS[h0 >>> 24 & 15] + HEX_CHARS[h0 >>> 20 & 15] + HEX_CHARS[h0 >>> 16 & 15] + HEX_CHARS[h0 >>> 12 & 15] + HEX_CHARS[h0 >>> 8 & 15] + HEX_CHARS[h0 >>> 4 & 15] + HEX_CHARS[h0 & 15] + HEX_CHARS[h1 >>> 28 & 15] + HEX_CHARS[h1 >>> 24 & 15] + HEX_CHARS[h1 >>> 20 & 15] + HEX_CHARS[h1 >>> 16 & 15] + HEX_CHARS[h1 >>> 12 & 15] + HEX_CHARS[h1 >>> 8 & 15] + HEX_CHARS[h1 >>> 4 & 15] + HEX_CHARS[h1 & 15] + HEX_CHARS[h2 >>> 28 & 15] + HEX_CHARS[h2 >>> 24 & 15] + HEX_CHARS[h2 >>> 20 & 15] + HEX_CHARS[h2 >>> 16 & 15] + HEX_CHARS[h2 >>> 12 & 15] + HEX_CHARS[h2 >>> 8 & 15] + HEX_CHARS[h2 >>> 4 & 15] + HEX_CHARS[h2 & 15] + HEX_CHARS[h3 >>> 28 & 15] + HEX_CHARS[h3 >>> 24 & 15] + HEX_CHARS[h3 >>> 20 & 15] + HEX_CHARS[h3 >>> 16 & 15] + HEX_CHARS[h3 >>> 12 & 15] + HEX_CHARS[h3 >>> 8 & 15] + HEX_CHARS[h3 >>> 4 & 15] + HEX_CHARS[h3 & 15] + HEX_CHARS[h4 >>> 28 & 15] + HEX_CHARS[h4 >>> 24 & 15] + HEX_CHARS[h4 >>> 20 & 15] + HEX_CHARS[h4 >>> 16 & 15] + HEX_CHARS[h4 >>> 12 & 15] + HEX_CHARS[h4 >>> 8 & 15] + HEX_CHARS[h4 >>> 4 & 15] + HEX_CHARS[h4 & 15] + HEX_CHARS[h5 >>> 28 & 15] + HEX_CHARS[h5 >>> 24 & 15] + HEX_CHARS[h5 >>> 20 & 15] + HEX_CHARS[h5 >>> 16 & 15] + HEX_CHARS[h5 >>> 12 & 15] + HEX_CHARS[h5 >>> 8 & 15] + HEX_CHARS[h5 >>> 4 & 15] + HEX_CHARS[h5 & 15] + HEX_CHARS[h6 >>> 28 & 15] + HEX_CHARS[h6 >>> 24 & 15] + HEX_CHARS[h6 >>> 20 & 15] + HEX_CHARS[h6 >>> 16 & 15] + HEX_CHARS[h6 >>> 12 & 15] + HEX_CHARS[h6 >>> 8 & 15] + HEX_CHARS[h6 >>> 4 & 15] + HEX_CHARS[h6 & 15];\n if (!this.is224) {\n hex += HEX_CHARS[h7 >>> 28 & 15] + HEX_CHARS[h7 >>> 24 & 15] + HEX_CHARS[h7 >>> 20 & 15] + HEX_CHARS[h7 >>> 16 & 15] + HEX_CHARS[h7 >>> 12 & 15] + HEX_CHARS[h7 >>> 8 & 15] + HEX_CHARS[h7 >>> 4 & 15] + HEX_CHARS[h7 & 15];\n }\n return hex;\n };\n Sha256.prototype.toString = Sha256.prototype.hex;\n Sha256.prototype.digest = function() {\n this.finalize();\n var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5, h6 = this.h6, h7 = this.h7;\n var arr = [\n h0 >>> 24 & 255,\n h0 >>> 16 & 255,\n h0 >>> 8 & 255,\n h0 & 255,\n h1 >>> 24 & 255,\n h1 >>> 16 & 255,\n h1 >>> 8 & 255,\n h1 & 255,\n h2 >>> 24 & 255,\n h2 >>> 16 & 255,\n h2 >>> 8 & 255,\n h2 & 255,\n h3 >>> 24 & 255,\n h3 >>> 16 & 255,\n h3 >>> 8 & 255,\n h3 & 255,\n h4 >>> 24 & 255,\n h4 >>> 16 & 255,\n h4 >>> 8 & 255,\n h4 & 255,\n h5 >>> 24 & 255,\n h5 >>> 16 & 255,\n h5 >>> 8 & 255,\n h5 & 255,\n h6 >>> 24 & 255,\n h6 >>> 16 & 255,\n h6 >>> 8 & 255,\n h6 & 255\n ];\n if (!this.is224) {\n arr.push(h7 >>> 24 & 255, h7 >>> 16 & 255, h7 >>> 8 & 255, h7 & 255);\n }\n return arr;\n };\n Sha256.prototype.array = Sha256.prototype.digest;\n Sha256.prototype.arrayBuffer = function() {\n this.finalize();\n var buffer = new ArrayBuffer(this.is224 ? 28 : 32);\n var dataView = new DataView(buffer);\n dataView.setUint32(0, this.h0);\n dataView.setUint32(4, this.h1);\n dataView.setUint32(8, this.h2);\n dataView.setUint32(12, this.h3);\n dataView.setUint32(16, this.h4);\n dataView.setUint32(20, this.h5);\n dataView.setUint32(24, this.h6);\n if (!this.is224) {\n dataView.setUint32(28, this.h7);\n }\n return buffer;\n };\n function HmacSha256(key, is224, sharedMemory) {\n var i, type = typeof key;\n if (type === "string") {\n var bytes = [], length = key.length, index = 0, code;\n for (i = 0; i < length; ++i) {\n code = key.charCodeAt(i);\n if (code < 128) {\n bytes[index++] = code;\n } else if (code < 2048) {\n bytes[index++] = 192 | code >>> 6;\n bytes[index++] = 128 | code & 63;\n } else if (code < 55296 || code >= 57344) {\n bytes[index++] = 224 | code >>> 12;\n bytes[index++] = 128 | code >>> 6 & 63;\n bytes[index++] = 128 | code & 63;\n } else {\n code = 65536 + ((code & 1023) << 10 | key.charCodeAt(++i) & 1023);\n bytes[index++] = 240 | code >>> 18;\n bytes[index++] = 128 | code >>> 12 & 63;\n bytes[index++] = 128 | code >>> 6 & 63;\n bytes[index++] = 128 | code & 63;\n }\n }\n key = bytes;\n } else {\n if (type === "object") {\n if (key === null) {\n throw new Error(ERROR);\n } else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) {\n key = new Uint8Array(key);\n } else if (!Array.isArray(key)) {\n if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) {\n throw new Error(ERROR);\n }\n }\n } else {\n throw new Error(ERROR);\n }\n }\n if (key.length > 64) {\n key = new Sha256(is224, true).update(key).array();\n }\n var oKeyPad = [], iKeyPad = [];\n for (i = 0; i < 64; ++i) {\n var b = key[i] || 0;\n oKeyPad[i] = 92 ^ b;\n iKeyPad[i] = 54 ^ b;\n }\n Sha256.call(this, is224, sharedMemory);\n this.update(iKeyPad);\n this.oKeyPad = oKeyPad;\n this.inner = true;\n this.sharedMemory = sharedMemory;\n }\n HmacSha256.prototype = new Sha256();\n HmacSha256.prototype.finalize = function() {\n Sha256.prototype.finalize.call(this);\n if (this.inner) {\n this.inner = false;\n var innerHash = this.array();\n Sha256.call(this, this.is224, this.sharedMemory);\n this.update(this.oKeyPad);\n this.update(innerHash);\n Sha256.prototype.finalize.call(this);\n }\n };\n var exports2 = createMethod();\n exports2.sha256 = exports2;\n exports2.sha224 = createMethod(true);\n exports2.sha256.hmac = createHmacMethod();\n exports2.sha224.hmac = createHmacMethod(true);\n if (COMMON_JS) {\n module.exports = exports2;\n } else {\n root.sha256 = exports2.sha256;\n root.sha224 = exports2.sha224;\n if (AMD) {\n define(function() {\n return exports2;\n });\n }\n }\n })();\n }\n });\n\n // src/extractor/index.ts\n var extractor_exports = {};\n __export(extractor_exports, {\n descriptionOfTree: () => descriptionOfTree,\n generateElementByPosition: () => generateElementByPosition,\n getElementInfoByXpath: () => getElementInfoByXpath,\n getElementXpath: () => getElementXpath,\n getNodeFromCacheList: () => getNodeFromCacheList,\n getNodeInfoByXpath: () => getNodeInfoByXpath,\n getXpathsById: () => getXpathsById,\n getXpathsByPoint: () => getXpathsByPoint,\n isNotContainerElement: () => isNotContainerElement,\n setNodeHashCacheListOnWindow: () => setNodeHashCacheListOnWindow,\n traverseTree: () => traverseTree,\n treeToList: () => treeToList,\n trimAttributes: () => trimAttributes,\n truncateText: () => truncateText,\n webExtractNodeTree: () => extractTreeNode,\n webExtractNodeTreeAsString: () => extractTreeNodeAsString,\n webExtractTextWithPosition: () => extractTextWithPosition\n });\n\n // src/extractor/tree.ts\n function truncateText(text, maxLength = 150) {\n if (typeof text === "undefined") {\n return "";\n }\n if (typeof text === "object") {\n text = JSON.stringify(text);\n }\n if (typeof text === "number") {\n return text.toString();\n }\n if (typeof text === "string" && text.length > maxLength) {\n return `${text.slice(0, maxLength)}...`;\n }\n if (typeof text === "string") {\n return text.trim();\n }\n return "";\n }\n function trimAttributes(attributes, truncateTextLength) {\n const tailorAttributes = Object.keys(attributes).reduce(\n (res, currentKey) => {\n const attributeVal = attributes[currentKey];\n if (currentKey === "style" || currentKey === "htmlTagName" || currentKey === "nodeType") {\n return res;\n }\n res[currentKey] = truncateText(attributeVal, truncateTextLength);\n return res;\n },\n {}\n );\n return tailorAttributes;\n }\n var nodeSizeThreshold = 4;\n function descriptionOfTree(tree, truncateTextLength, filterNonTextContent = false, visibleOnly = true) {\n const attributesString = (kv) => {\n return Object.entries(kv).map(\n ([key, value]) => `${key}="${truncateText(value, truncateTextLength)}"`\n ).join(" ");\n };\n function buildContentTree(node, indent = 0, visibleOnly2 = true) {\n var _a2;\n let before = "";\n let contentWithIndent = "";\n let after = "";\n let emptyNode = true;\n const indentStr = " ".repeat(indent);\n let children = "";\n for (let i = 0; i < (node.children || []).length; i++) {\n const childContent = buildContentTree(\n node.children[i],\n indent + 1,\n visibleOnly2\n );\n if (childContent) {\n children += `\n${childContent}`;\n }\n }\n if (node.node && node.node.rect.width > nodeSizeThreshold && node.node.rect.height > nodeSizeThreshold && (!filterNonTextContent || filterNonTextContent && node.node.content) && (!visibleOnly2 || visibleOnly2 && node.node.isVisible)) {\n emptyNode = false;\n let nodeTypeString;\n if ((_a2 = node.node.attributes) == null ? void 0 : _a2.htmlTagName) {\n nodeTypeString = node.node.attributes.htmlTagName.replace(/[<>]/g, "");\n } else {\n nodeTypeString = node.node.attributes.nodeType.replace(/\\sNode$/, "").toLowerCase();\n }\n const markerId = node.node.indexId;\n const markerIdString = markerId ? `markerId="${markerId}"` : "";\n const rectAttribute = node.node.rect ? {\n left: node.node.rect.left,\n top: node.node.rect.top,\n width: node.node.rect.width,\n height: node.node.rect.height\n } : {};\n before = `<${nodeTypeString} id="${node.node.id}" ${markerIdString} ${attributesString(trimAttributes(node.node.attributes || {}, truncateTextLength))} ${attributesString(rectAttribute)}>`;\n const content = truncateText(node.node.content, truncateTextLength);\n contentWithIndent = content ? `\n${indentStr} ${content}` : "";\n after = `</${nodeTypeString}>`;\n } else if (!filterNonTextContent) {\n if (!children.trim().startsWith("<>")) {\n before = "<>";\n contentWithIndent = "";\n after = "</>";\n }\n }\n if (emptyNode && !children.trim()) {\n return "";\n }\n const result2 = `${indentStr}${before}${contentWithIndent}${children}\n${indentStr}${after}`;\n if (result2.trim()) {\n return result2;\n }\n return "";\n }\n const result = buildContentTree(tree, 0, visibleOnly);\n return result.replace(/^\\s*\\n/gm, "");\n }\n function treeToList(tree) {\n const result = [];\n function dfs(node) {\n if (node.node) {\n result.push(node.node);\n }\n for (const child of node.children) {\n dfs(child);\n }\n }\n dfs(tree);\n return result;\n }\n function traverseTree(tree, onNode) {\n function dfs(node) {\n if (node.node) {\n node.node = onNode(node.node);\n }\n for (const child of node.children) {\n dfs(child);\n }\n }\n dfs(tree);\n return tree;\n }\n\n // src/constants/index.ts\n var CONTAINER_MINI_HEIGHT = 3;\n var CONTAINER_MINI_WIDTH = 3;\n\n // src/utils.ts\n var import_js_sha256 = __toESM(require_sha256());\n var _a;\n var ifInNode = typeof process !== "undefined" && ((_a = process.versions) == null ? void 0 : _a.node);\n var hashMap = {};\n function generateHashId(rect, content = "") {\n const combined = JSON.stringify({\n content,\n rect\n });\n let sliceLength = 5;\n let slicedHash = "";\n const hashHex = import_js_sha256.sha256.create().update(combined).hex();\n const toLetters = (hex) => {\n return hex.split("").map((char) => {\n const code = Number.parseInt(char, 16);\n return String.fromCharCode(97 + code % 26);\n }).join("");\n };\n const hashLetters = toLetters(hashHex);\n while (sliceLength < hashLetters.length - 1) {\n slicedHash = hashLetters.slice(0, sliceLength);\n if (hashMap[slicedHash] && hashMap[slicedHash] !== combined) {\n sliceLength++;\n continue;\n }\n hashMap[slicedHash] = combined;\n break;\n }\n return slicedHash;\n }\n\n // src/extractor/dom-util.ts\n function isFormElement(node) {\n return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea" || node.tagName.toLowerCase() === "select" || node.tagName.toLowerCase() === "option");\n }\n function isButtonElement(node) {\n return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";\n }\n function isAElement(node) {\n return node instanceof HTMLElement && node.tagName.toLowerCase() === "a";\n }\n function isSvgElement(node) {\n return node instanceof SVGElement;\n }\n function isImgElement(node) {\n if (!includeBaseElement(node) && node instanceof Element) {\n const computedStyle = window.getComputedStyle(node);\n const backgroundImage = computedStyle.getPropertyValue("background-image");\n if (backgroundImage !== "none") {\n return true;\n }\n }\n if (isIconfont(node)) {\n return true;\n }\n return node instanceof HTMLElement && node.tagName.toLowerCase() === "img" || node instanceof SVGElement && node.tagName.toLowerCase() === "svg";\n }\n function isIconfont(node) {\n if (node instanceof Element) {\n const computedStyle = window.getComputedStyle(node);\n const fontFamilyValue = computedStyle.fontFamily || "";\n return fontFamilyValue.toLowerCase().indexOf("iconfont") >= 0;\n }\n return false;\n }\n function isNotContainerElement(node) {\n return isTextElement(node) || isIconfont(node) || isImgElement(node) || isButtonElement(node) || isAElement(node) || isFormElement(node);\n }\n function isTextElement(node) {\n var _a2, _b, _c;\n if (node instanceof Element) {\n if (((_a2 = node == null ? void 0 : node.childNodes) == null ? void 0 : _a2.length) === 1 && (node == null ? void 0 : node.childNodes[0]) instanceof Text) {\n return true;\n }\n }\n return ((_c = (_b = node.nodeName) == null ? void 0 : _b.toLowerCase) == null ? void 0 : _c.call(_b)) === "#text" && !isIconfont(node);\n }\n function isContainerElement(node) {\n if (!(node instanceof HTMLElement))\n return false;\n if (includeBaseElement(node)) {\n return false;\n }\n const computedStyle = window.getComputedStyle(node);\n const backgroundColor = computedStyle.getPropertyValue("background-color");\n if (backgroundColor) {\n return true;\n }\n return false;\n }\n function includeBaseElement(node) {\n if (!(node instanceof HTMLElement))\n return false;\n if (node.innerText) {\n return true;\n }\n const includeList = [\n "svg",\n "button",\n "input",\n "textarea",\n "select",\n "option",\n "img",\n "a"\n ];\n for (const tagName of includeList) {\n const element = node.querySelectorAll(tagName);\n if (element.length > 0) {\n return true;\n }\n }\n return false;\n }\n function generateElementByPosition(position) {\n const rect = {\n left: Math.max(position.x - 4, 0),\n top: Math.max(position.y - 4, 0),\n width: 8,\n height: 8\n };\n const id = generateHashId(rect);\n const element = {\n id,\n attributes: { nodeType: "POSITION Node" /* POSITION */ },\n rect,\n content: "",\n center: [position.x, position.y]\n };\n return element;\n }\n\n // src/extractor/util.ts\n var MAX_VALUE_LENGTH = 300;\n var debugMode = false;\n function setDebugMode(mode) {\n debugMode = mode;\n }\n function logger(..._msg) {\n if (!debugMode) {\n return;\n }\n console.log(..._msg);\n }\n function isElementPartiallyInViewport(rect, currentWindow, currentDocument, visibleAreaRatio = 2 / 3) {\n const elementHeight = rect.height;\n const elementWidth = rect.width;\n const viewportRect = {\n left: 0,\n top: 0,\n width: currentWindow.innerWidth || currentDocument.documentElement.clientWidth,\n height: currentWindow.innerHeight || currentDocument.documentElement.clientHeight,\n right: currentWindow.innerWidth || currentDocument.documentElement.clientWidth,\n bottom: currentWindow.innerHeight || currentDocument.documentElement.clientHeight,\n x: 0,\n y: 0,\n zoom: 1\n };\n const overlapRect = overlappedRect(rect, viewportRect);\n if (!overlapRect) {\n return false;\n }\n const visibleArea = overlapRect.width * overlapRect.height;\n const totalArea = elementHeight * elementWidth;\n return visibleArea / totalArea >= visibleAreaRatio;\n }\n function getPseudoElementContent(element, currentWindow) {\n if (!(element instanceof currentWindow.HTMLElement)) {\n return { before: "", after: "" };\n }\n const beforeContent = currentWindow.getComputedStyle(element, "::before").getPropertyValue("content");\n const afterContent = currentWindow.getComputedStyle(element, "::after").getPropertyValue("content");\n return {\n before: beforeContent === "none" ? "" : beforeContent.replace(/"/g, ""),\n after: afterContent === "none" ? "" : afterContent.replace(/"/g, "")\n };\n }\n function overlappedRect(rect1, rect2) {\n const left = Math.max(rect1.left, rect2.left);\n const top = Math.max(rect1.top, rect2.top);\n const right = Math.min(rect1.right, rect2.right);\n const bottom = Math.min(rect1.bottom, rect2.bottom);\n if (left < right && top < bottom) {\n return {\n left,\n top,\n right,\n bottom,\n width: right - left,\n height: bottom - top,\n x: left,\n y: top,\n zoom: 1\n };\n }\n return null;\n }\n function getRect(el, baseZoom, currentWindow) {\n let originalRect;\n let newZoom = 1;\n if (!(el instanceof currentWindow.HTMLElement)) {\n const range = currentWindow.document.createRange();\n range.selectNodeContents(el);\n originalRect = range.getBoundingClientRect();\n } else {\n originalRect = el.getBoundingClientRect();\n if (!("currentCSSZoom" in el)) {\n newZoom = Number.parseFloat(currentWindow.getComputedStyle(el).zoom) || 1;\n }\n }\n const zoom = newZoom * baseZoom;\n return {\n width: originalRect.width * zoom,\n height: originalRect.height * zoom,\n left: originalRect.left * zoom,\n top: originalRect.top * zoom,\n right: originalRect.right * zoom,\n bottom: originalRect.bottom * zoom,\n x: originalRect.x * zoom,\n y: originalRect.y * zoom,\n zoom\n };\n }\n var isElementCovered = (el, rect, currentWindow) => {\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n const topElement = currentWindow.document.elementFromPoint(x, y);\n if (!topElement) {\n return false;\n }\n if (topElement === el) {\n return false;\n }\n if (el == null ? void 0 : el.contains(topElement)) {\n return false;\n }\n if (topElement == null ? void 0 : topElement.contains(el)) {\n return false;\n }\n const rectOfTopElement = getRect(topElement, 1, currentWindow);\n const overlapRect = overlappedRect(rect, rectOfTopElement);\n if (!overlapRect) {\n return false;\n }\n logger(el, "Element is covered by another element", {\n topElement,\n el,\n rect,\n x,\n y\n });\n return true;\n };\n function elementRect(el, currentWindow, currentDocument, baseZoom = 1) {\n if (!el) {\n logger(el, "Element is not in the DOM hierarchy");\n return false;\n }\n if (!(el instanceof currentWindow.HTMLElement) && el.nodeType !== Node.TEXT_NODE && el.nodeName.toLowerCase() !== "svg") {\n logger(el, "Element is not in the DOM hierarchy");\n return false;\n }\n if (el instanceof currentWindow.HTMLElement) {\n const style = currentWindow.getComputedStyle(el);\n if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" && el.tagName !== "INPUT") {\n logger(el, "Element is hidden");\n return false;\n }\n }\n const rect = getRect(el, baseZoom, currentWindow);\n if (rect.width === 0 && rect.height === 0) {\n logger(el, "Element has no size");\n return false;\n }\n if (baseZoom === 1 && isElementCovered(el, rect, currentWindow)) {\n return false;\n }\n const isVisible = isElementPartiallyInViewport(\n rect,\n currentWindow,\n currentDocument\n );\n let parent = el;\n const parentUntilNonStatic = (currentNode) => {\n let parent2 = currentNode == null ? void 0 : currentNode.parentElement;\n while (parent2) {\n const style = currentWindow.getComputedStyle(parent2);\n if (style.position !== "static") {\n return parent2;\n }\n parent2 = parent2.parentElement;\n }\n return null;\n };\n while (parent && parent !== currentDocument.body) {\n if (!(parent instanceof currentWindow.HTMLElement)) {\n parent = parent.parentElement;\n continue;\n }\n const parentStyle = currentWindow.getComputedStyle(parent);\n if (parentStyle.overflow === "hidden") {\n const parentRect = getRect(parent, 1, currentWindow);\n const tolerance = 10;\n if (rect.right < parentRect.left - tolerance || rect.left > parentRect.right + tolerance || rect.bottom < parentRect.top - tolerance || rect.top > parentRect.bottom + tolerance) {\n logger(el, "element is partially or totally hidden by an ancestor", {\n rect,\n parentRect\n });\n return false;\n }\n }\n if (parentStyle.position === "fixed" || parentStyle.position === "sticky") {\n break;\n }\n if (parentStyle.position === "absolute") {\n parent = parentUntilNonStatic(parent);\n } else {\n parent = parent.parentElement;\n }\n }\n return {\n left: Math.round(rect.left),\n top: Math.round(rect.top),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n zoom: rect.zoom,\n isVisible\n };\n }\n function getNodeAttributes(node, currentWindow) {\n if (!node || !(node instanceof currentWindow.HTMLElement) || !node.attributes) {\n return {};\n }\n const attributesList = Array.from(node.attributes).map((attr) => {\n if (attr.name === "class") {\n return [attr.name, `.${attr.value.split(" ").join(".")}`];\n }\n if (!attr.value) {\n return [];\n }\n let value = attr.value;\n if (value.startsWith("data:image")) {\n value = "image";\n }\n if (value.length > MAX_VALUE_LENGTH) {\n value = `${value.slice(0, MAX_VALUE_LENGTH)}...`;\n }\n return [attr.name, value];\n });\n return Object.fromEntries(attributesList);\n }\n function midsceneGenerateHash(node, content, rect) {\n const slicedHash = generateHashId(rect, content);\n if (node) {\n if (!window.midsceneNodeHashCacheList) {\n setNodeHashCacheListOnWindow();\n }\n setNodeToCacheList(node, slicedHash);\n }\n return slicedHash;\n }\n function setNodeHashCacheListOnWindow() {\n if (typeof window !== "undefined") {\n window.midsceneNodeHashCacheList = [];\n }\n }\n function setNodeToCacheList(node, id) {\n var _a2;\n if (typeof window !== "undefined") {\n if (getNodeFromCacheList(id)) {\n return;\n }\n (_a2 = window.midsceneNodeHashCacheList) == null ? void 0 : _a2.push({ node, id });\n }\n }\n function getNodeFromCacheList(id) {\n var _a2, _b;\n if (typeof window !== "undefined") {\n return (_b = (_a2 = window.midsceneNodeHashCacheList) == null ? void 0 : _a2.find(\n (item) => item.id === id\n )) == null ? void 0 : _b.node;\n }\n return null;\n }\n function getTopDocument() {\n const container = document.body || document;\n return container;\n }\n\n // src/extractor/web-extractor.ts\n var indexId = 0;\n function tagNameOfNode(node) {\n var _a2, _b;\n let tagName = "";\n if (node instanceof HTMLElement) {\n tagName = (_a2 = node.tagName) == null ? void 0 : _a2.toLowerCase();\n } else {\n const parentElement = node.parentElement;\n if (parentElement && parentElement instanceof HTMLElement) {\n tagName = (_b = parentElement.tagName) == null ? void 0 : _b.toLowerCase();\n }\n }\n return tagName ? `<${tagName}>` : "";\n }\n function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1, basePoint = { left: 0, top: 0 }, isContainer = false) {\n var _a2, _b;\n const rect = elementRect(node, currentWindow, currentDocument, baseZoom);\n if (!rect) {\n return null;\n }\n if (rect.width < CONTAINER_MINI_WIDTH || rect.height < CONTAINER_MINI_HEIGHT) {\n return null;\n }\n if (basePoint.left !== 0 || basePoint.top !== 0) {\n rect.left += basePoint.left;\n rect.top += basePoint.top;\n }\n if (rect.height >= window.innerHeight && rect.width >= window.innerWidth) {\n return null;\n }\n if (isFormElement(node)) {\n const attributes = getNodeAttributes(node, currentWindow);\n let valueContent = attributes.value || attributes.placeholder || node.textContent || "";\n const nodeHashId = midsceneGenerateHash(node, valueContent, rect);\n const tagName = node.tagName.toLowerCase();\n if (node.tagName.toLowerCase() === "select") {\n const selectedOption = node.options[node.selectedIndex];\n valueContent = (selectedOption == null ? void 0 : selectedOption.textContent) || "";\n }\n if ((node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea") && node.value) {\n valueContent = node.value;\n }\n const elementInfo = {\n id: nodeHashId,\n nodeHashId,\n nodeType: "FORM_ITEM Node" /* FORM_ITEM */,\n indexId: indexId++,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n htmlTagName: `<${tagName}>`,\n nodeType: "FORM_ITEM Node" /* FORM_ITEM */\n }),\n content: valueContent.trim(),\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isButtonElement(node)) {\n const rect2 = mergeElementAndChildrenRects(\n node,\n currentWindow,\n currentDocument,\n baseZoom\n );\n if (!rect2) {\n return null;\n }\n const attributes = getNodeAttributes(node, currentWindow);\n const pseudo = getPseudoElementContent(node, currentWindow);\n const content = node.innerText || pseudo.before || pseudo.after || "";\n const nodeHashId = midsceneGenerateHash(node, content, rect2);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n nodeType: "BUTTON Node" /* BUTTON */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n htmlTagName: tagNameOfNode(node),\n nodeType: "BUTTON Node" /* BUTTON */\n }),\n content,\n rect: rect2,\n center: [\n Math.round(rect2.left + rect2.width / 2),\n Math.round(rect2.top + rect2.height / 2)\n ],\n zoom: rect2.zoom,\n isVisible: rect2.isVisible\n };\n return elementInfo;\n }\n if (isImgElement(node)) {\n const attributes = getNodeAttributes(node, currentWindow);\n const nodeHashId = midsceneGenerateHash(node, "", rect);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n attributes: __spreadProps(__spreadValues(__spreadValues({}, attributes), ((_a2 = node.nodeName) == null ? void 0 : _a2.toLowerCase()) === "svg" ? {\n svgContent: "true"\n } : {}), {\n nodeType: "IMG Node" /* IMG */,\n htmlTagName: tagNameOfNode(node)\n }),\n nodeType: "IMG Node" /* IMG */,\n content: "",\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isTextElement(node)) {\n const text = (_b = node.textContent) == null ? void 0 : _b.trim().replace(/\\n+/g, " ");\n if (!text) {\n return null;\n }\n const attributes = getNodeAttributes(node, currentWindow);\n const attributeKeys = Object.keys(attributes);\n if (!text.trim() && attributeKeys.length === 0) {\n return null;\n }\n const nodeHashId = midsceneGenerateHash(node, text, rect);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n nodeType: "TEXT Node" /* TEXT */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n nodeType: "TEXT Node" /* TEXT */,\n htmlTagName: tagNameOfNode(node)\n }),\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n content: text,\n rect,\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isAElement(node)) {\n const attributes = getNodeAttributes(node, currentWindow);\n const pseudo = getPseudoElementContent(node, currentWindow);\n const content = node.innerText || pseudo.before || pseudo.after || "";\n const nodeHashId = midsceneGenerateHash(node, content, rect);\n const elementInfo = {\n id: nodeHashId,\n indexId: indexId++,\n nodeHashId,\n nodeType: "Anchor Node" /* A */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n htmlTagName: tagNameOfNode(node),\n nodeType: "Anchor Node" /* A */\n }),\n content,\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n if (isContainerElement(node) || isContainer) {\n const attributes = getNodeAttributes(node, currentWindow);\n const nodeHashId = midsceneGenerateHash(node, "", rect);\n const elementInfo = {\n id: nodeHashId,\n nodeHashId,\n indexId: indexId++,\n nodeType: "CONTAINER Node" /* CONTAINER */,\n attributes: __spreadProps(__spreadValues({}, attributes), {\n nodeType: "CONTAINER Node" /* CONTAINER */,\n htmlTagName: tagNameOfNode(node)\n }),\n content: "",\n rect,\n center: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2)\n ],\n zoom: rect.zoom,\n isVisible: rect.isVisible\n };\n return elementInfo;\n }\n return null;\n }\n function extractTextWithPosition(initNode, debugMode2 = false) {\n const elementNode = extractTreeNode(initNode, debugMode2);\n const elementInfoArray = [];\n function dfsTopChildren(node) {\n if (node.node) {\n elementInfoArray.push(node.node);\n }\n for (let i = 0; i < node.children.length; i++) {\n dfsTopChildren(node.children[i]);\n }\n }\n dfsTopChildren({ children: elementNode.children, node: elementNode.node });\n return elementInfoArray;\n }\n function extractTreeNodeAsString(initNode, visibleOnly = false, debugMode2 = false) {\n const elementNode = extractTreeNode(initNode, debugMode2);\n return descriptionOfTree(elementNode, void 0, false, visibleOnly);\n }\n function extractTreeNode(initNode, debugMode2 = false) {\n setDebugMode(debugMode2);\n indexId = 0;\n const topDocument = getTopDocument();\n const startNode = initNode || topDocument;\n const topChildren = [];\n function dfs(node, currentWindow, currentDocument, baseZoom = 1, basePoint = { left: 0, top: 0 }) {\n if (!node) {\n return null;\n }\n if (node.nodeType && node.nodeType === 10) {\n return null;\n }\n const elementInfo = collectElementInfo(\n node,\n currentWindow,\n currentDocument,\n baseZoom,\n basePoint\n );\n if (node instanceof currentWindow.HTMLIFrameElement) {\n if (node.contentWindow && node.contentWindow) {\n return null;\n }\n }\n const nodeInfo = {\n node: elementInfo,\n children: []\n };\n if ((elementInfo == null ? void 0 : elementInfo.nodeType) === "BUTTON Node" /* BUTTON */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "IMG Node" /* IMG */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "TEXT Node" /* TEXT */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "FORM_ITEM Node" /* FORM_ITEM */ || (elementInfo == null ? void 0 : elementInfo.nodeType) === "CONTAINER Node" /* CONTAINER */) {\n return nodeInfo;\n }\n const rect = getRect(node, baseZoom, currentWindow);\n for (let i = 0; i < node.childNodes.length; i++) {\n logger("will dfs", node.childNodes[i]);\n const childNodeInfo = dfs(\n node.childNodes[i],\n currentWindow,\n currentDocument,\n rect.zoom,\n basePoint\n );\n if (Array.isArray(childNodeInfo)) {\n nodeInfo.children.push(...childNodeInfo);\n } else if (childNodeInfo) {\n nodeInfo.children.push(childNodeInfo);\n }\n }\n if (nodeInfo.node === null) {\n if (nodeInfo.children.length === 0) {\n return null;\n }\n return nodeInfo.children;\n }\n return nodeInfo;\n }\n const rootNodeInfo = dfs(startNode, window, document, 1, {\n left: 0,\n top: 0\n });\n if (Array.isArray(rootNodeInfo)) {\n topChildren.push(...rootNodeInfo);\n } else if (rootNodeInfo) {\n topChildren.push(rootNodeInfo);\n }\n if (startNode === topDocument) {\n const iframes = document.querySelectorAll("iframe");\n for (let i = 0; i < iframes.length; i++) {\n const iframe = iframes[i];\n if (iframe.contentDocument && iframe.contentWindow) {\n const iframeInfo = collectElementInfo(iframe, window, document, 1);\n if (iframeInfo) {\n const iframeChildren = dfs(\n iframe.contentDocument.body,\n iframe.contentWindow,\n iframe.contentDocument,\n 1,\n {\n left: iframeInfo.rect.left,\n top: iframeInfo.rect.top\n }\n );\n if (Array.isArray(iframeChildren)) {\n topChildren.push(...iframeChildren);\n } else if (iframeChildren) {\n topChildren.push(iframeChildren);\n }\n }\n }\n }\n }\n return {\n node: null,\n children: topChildren\n };\n }\n function mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom = 1) {\n const selfRect = elementRect(node, currentWindow, currentDocument, baseZoom);\n if (!selfRect)\n return null;\n let minLeft = selfRect.left;\n let minTop = selfRect.top;\n let maxRight = selfRect.left + selfRect.width;\n let maxBottom = selfRect.top + selfRect.height;\n function traverse(child) {\n for (let i = 0; i < child.childNodes.length; i++) {\n const sub = child.childNodes[i];\n if (sub.nodeType === 1) {\n const rect = elementRect(sub, currentWindow, currentDocument, baseZoom);\n if (rect) {\n minLeft = Math.min(minLeft, rect.left);\n minTop = Math.min(minTop, rect.top);\n maxRight = Math.max(maxRight, rect.left + rect.width);\n maxBottom = Math.max(maxBottom, rect.top + rect.height);\n }\n traverse(sub);\n }\n }\n }\n traverse(node);\n return __spreadProps(__spreadValues({}, selfRect), {\n left: minLeft,\n top: minTop,\n width: maxRight - minLeft,\n height: maxBottom - minTop\n });\n }\n\n // src/extractor/locator.ts\n var getElementXpathIndex = (element) => {\n let index = 1;\n let prev = element.previousElementSibling;\n while (prev) {\n if (prev.nodeName.toLowerCase() === element.nodeName.toLowerCase()) {\n index++;\n }\n prev = prev.previousElementSibling;\n }\n return index;\n };\n var normalizeXpathText = (text) => {\n if (typeof text !== "string") {\n return "";\n }\n return text.replace(/\\s+/g, " ").trim();\n };\n var buildCurrentElementXpath = (element, isOrderSensitive, isLeafElement) => {\n var _a2;\n const parentPath = element.parentNode ? getElementXpath(element.parentNode, isOrderSensitive) : "";\n const prefix = parentPath ? `${parentPath}/` : "/";\n const tagName = element.nodeName.toLowerCase();\n const textContent = (_a2 = element.textContent) == null ? void 0 : _a2.trim();\n if (isOrderSensitive) {\n const index2 = getElementXpathIndex(element);\n return `${prefix}${tagName}[${index2}]`;\n }\n if (isLeafElement && textContent) {\n return `${prefix}${tagName}[normalize-space()="${normalizeXpathText(textContent)}"]`;\n }\n const index = getElementXpathIndex(element);\n return `${prefix}${tagName}[${index}]`;\n };\n var getElementXpath = (element, isOrderSensitive = false, isLeafElement = false) => {\n var _a2;\n if (element.nodeType === Node.TEXT_NODE) {\n const parentNode = element.parentNode;\n if (parentNode && parentNode.nodeType === Node.ELEMENT_NODE) {\n const parentXPath = getElementXpath(parentNode, isOrderSensitive, true);\n const textContent = (_a2 = element.textContent) == null ? void 0 : _a2.trim();\n if (textContent) {\n return `${parentXPath}/text()[normalize-space()="${normalizeXpathText(textContent)}"]`;\n }\n return `${parentXPath}/text()`;\n }\n return "";\n }\n if (element.nodeType !== Node.ELEMENT_NODE)\n return "";\n const el = element;\n if (el === document.documentElement)\n return "/html";\n if (el === document.body)\n return "/html/body";\n if (isSvgElement(el)) {\n let parent = el.parentNode;\n while (parent && parent.nodeType === Node.ELEMENT_NODE) {\n if (!isSvgElement(parent)) {\n return getElementXpath(parent, isOrderSensitive, isLeafElement);\n }\n parent = parent.parentNode;\n }\n return getElementXpath(el.parentNode, isOrderSensitive, isLeafElement);\n }\n return buildCurrentElementXpath(el, isOrderSensitive, isLeafElement);\n };\n function getXpathsById(id) {\n const node = getNodeFromCacheList(id);\n if (!node) {\n return null;\n }\n const fullXPath = getElementXpath(node, false, true);\n return [fullXPath];\n }\n function getXpathsByPoint(point, isOrderSensitive) {\n const element = document.elementFromPoint(point.left, point.top);\n if (!element) {\n return null;\n }\n const fullXPath = getElementXpath(element, isOrderSensitive, true);\n return [fullXPath];\n }\n function getNodeInfoByXpath(xpath) {\n const xpathResult = document.evaluate(\n xpath,\n document,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n if (xpathResult.snapshotLength !== 1) {\n return null;\n }\n const node = xpathResult.snapshotItem(0);\n return node;\n }\n function getElementInfoByXpath(xpath) {\n const node = getNodeInfoByXpath(xpath);\n if (!node) {\n return null;\n }\n if (node instanceof HTMLElement) {\n const rect = getRect(node, 1, window);\n const isVisible = isElementPartiallyInViewport(rect, window, document, 1);\n if (!isVisible) {\n node.scrollIntoView({ behavior: "instant", block: "center" });\n }\n }\n return collectElementInfo(\n node,\n window,\n document,\n 1,\n {\n left: 0,\n top: 0\n },\n true\n );\n }\n return __toCommonJS(extractor_exports);\n})();\n/*! Bundled license information:\n\njs-sha256/src/sha256.js:\n (**\n * [js-sha256]{@link https://github.com/emn178/js-sha256}\n *\n * @version 0.11.0\n * @author Chen, Yi-Cyuan [emn178@gmail.com]\n * @copyright Chen, Yi-Cyuan 2014-2024\n * @license MIT\n *)\n*/\n';
|
|
50
51
|
if (!htmlElementScript) {
|
|
51
52
|
throw new Error("HTML_ELEMENT_SCRIPT inject failed.");
|
|
52
53
|
}
|
package/dist/es/img.d.ts
CHANGED