@midscene/recorder 0.21.4-beta-20250711063424.0 → 0.21.4-beta-20250714025212.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.
@@ -1,300 +1,1672 @@
1
+ /*! For license information please see recorder-iife.js.LICENSE.txt */
1
2
  (()=>{
2
- "use strict";
3
- const DEBUG = 'true' === localStorage.getItem('DEBUG');
4
- function debugLog(...args) {
5
- if (DEBUG) console.log('[EventRecorder]', ...args);
6
- }
7
- function generateHashId(type, elementRect) {
8
- const rectStr = elementRect ? `${elementRect.left}_${elementRect.top}_${elementRect.width}_${elementRect.height}${void 0 !== elementRect.x ? `_${elementRect.x}` : ''}${void 0 !== elementRect.y ? `_${elementRect.y}` : ''}` : 'no_rect';
9
- const combined = `${type}_${rectStr}`;
10
- let hash = 0;
11
- for(let i = 0; i < combined.length; i++){
12
- const char = combined.charCodeAt(i);
13
- hash = (hash << 5) - hash + char;
14
- hash &= hash;
15
- }
16
- return Math.abs(hash).toString(36);
17
- }
18
- const isSameInputTarget = (event1, event2)=>event1.element === event2.element;
19
- const isSameScrollTarget = (event1, event2)=>event1.element === event2.element;
20
- const getLastLabelClick = (events)=>{
21
- for(let i = events.length - 1; i >= 0; i--){
22
- const event = events[i];
23
- if ('click' === event.type && event.isLabelClick) return event;
24
- }
25
- };
26
- function getAllScrollableElements() {
27
- const elements = [];
28
- const all = document.querySelectorAll('body *');
29
- all.forEach((el)=>{
30
- const style = window.getComputedStyle(el);
31
- const overflowY = style.overflowY;
32
- const overflowX = style.overflowX;
33
- const isScrollableY = ('auto' === overflowY || 'scroll' === overflowY) && el.scrollHeight > el.clientHeight;
34
- const isScrollableX = ('auto' === overflowX || 'scroll' === overflowX) && el.scrollWidth > el.clientWidth;
35
- if (isScrollableY || isScrollableX) elements.push(el);
36
- });
37
- return elements;
38
- }
39
- class EventRecorder {
40
- isRecording = false;
41
- eventCallback;
42
- scrollThrottleTimer = null;
43
- scrollThrottleDelay = 200;
44
- lastViewportScroll = null;
45
- scrollTargets = [];
46
- sessionId;
47
- constructor(eventCallback, sessionId){
48
- this.eventCallback = eventCallback;
49
- this.sessionId = sessionId;
50
- }
51
- createNavigationEvent(url, title) {
52
- return {
53
- type: 'navigation',
54
- url,
55
- title,
56
- pageInfo: {
57
- width: window.innerWidth,
58
- height: window.innerHeight
59
- },
60
- timestamp: Date.now(),
61
- hashId: 'navigation_0'
3
+ var __webpack_modules__ = {
4
+ "../../node_modules/.pnpm/js-sha256@0.11.0/node_modules/js-sha256/src/sha256.js": function(module, __unused_webpack_exports, __webpack_require__) {
5
+ /**
6
+ * [js-sha256]{@link https://github.com/emn178/js-sha256}
7
+ *
8
+ * @version 0.11.0
9
+ * @author Chen, Yi-Cyuan [emn178@gmail.com]
10
+ * @copyright Chen, Yi-Cyuan 2014-2024
11
+ * @license MIT
12
+ */ (function() {
13
+ 'use strict';
14
+ var ERROR = 'input is invalid type';
15
+ var WINDOW = 'object' == typeof window;
16
+ var root = WINDOW ? window : {};
17
+ if (root.JS_SHA256_NO_WINDOW) WINDOW = false;
18
+ var WEB_WORKER = !WINDOW && 'object' == typeof self;
19
+ var NODE_JS = !root.JS_SHA256_NO_NODE_JS && 'object' == typeof process && process.versions && process.versions.node;
20
+ if (NODE_JS) root = __webpack_require__.g;
21
+ else if (WEB_WORKER) root = self;
22
+ var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && true && module.exports;
23
+ var AMD = 'function' == typeof define && define.amd;
24
+ var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && 'undefined' != typeof ArrayBuffer;
25
+ var HEX_CHARS = '0123456789abcdef'.split('');
26
+ var EXTRA = [
27
+ -2147483648,
28
+ 8388608,
29
+ 32768,
30
+ 128
31
+ ];
32
+ var SHIFT = [
33
+ 24,
34
+ 16,
35
+ 8,
36
+ 0
37
+ ];
38
+ var K = [
39
+ 0x428a2f98,
40
+ 0x71374491,
41
+ 0xb5c0fbcf,
42
+ 0xe9b5dba5,
43
+ 0x3956c25b,
44
+ 0x59f111f1,
45
+ 0x923f82a4,
46
+ 0xab1c5ed5,
47
+ 0xd807aa98,
48
+ 0x12835b01,
49
+ 0x243185be,
50
+ 0x550c7dc3,
51
+ 0x72be5d74,
52
+ 0x80deb1fe,
53
+ 0x9bdc06a7,
54
+ 0xc19bf174,
55
+ 0xe49b69c1,
56
+ 0xefbe4786,
57
+ 0x0fc19dc6,
58
+ 0x240ca1cc,
59
+ 0x2de92c6f,
60
+ 0x4a7484aa,
61
+ 0x5cb0a9dc,
62
+ 0x76f988da,
63
+ 0x983e5152,
64
+ 0xa831c66d,
65
+ 0xb00327c8,
66
+ 0xbf597fc7,
67
+ 0xc6e00bf3,
68
+ 0xd5a79147,
69
+ 0x06ca6351,
70
+ 0x14292967,
71
+ 0x27b70a85,
72
+ 0x2e1b2138,
73
+ 0x4d2c6dfc,
74
+ 0x53380d13,
75
+ 0x650a7354,
76
+ 0x766a0abb,
77
+ 0x81c2c92e,
78
+ 0x92722c85,
79
+ 0xa2bfe8a1,
80
+ 0xa81a664b,
81
+ 0xc24b8b70,
82
+ 0xc76c51a3,
83
+ 0xd192e819,
84
+ 0xd6990624,
85
+ 0xf40e3585,
86
+ 0x106aa070,
87
+ 0x19a4c116,
88
+ 0x1e376c08,
89
+ 0x2748774c,
90
+ 0x34b0bcb5,
91
+ 0x391c0cb3,
92
+ 0x4ed8aa4a,
93
+ 0x5b9cca4f,
94
+ 0x682e6ff3,
95
+ 0x748f82ee,
96
+ 0x78a5636f,
97
+ 0x84c87814,
98
+ 0x8cc70208,
99
+ 0x90befffa,
100
+ 0xa4506ceb,
101
+ 0xbef9a3f7,
102
+ 0xc67178f2
103
+ ];
104
+ var OUTPUT_TYPES = [
105
+ 'hex',
106
+ 'array',
107
+ 'digest',
108
+ 'arrayBuffer'
109
+ ];
110
+ var blocks = [];
111
+ if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) Array.isArray = function(obj) {
112
+ return '[object Array]' === Object.prototype.toString.call(obj);
113
+ };
114
+ if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) ArrayBuffer.isView = function(obj) {
115
+ return 'object' == typeof obj && obj.buffer && obj.buffer.constructor === ArrayBuffer;
116
+ };
117
+ var createOutputMethod = function(outputType, is224) {
118
+ return function(message) {
119
+ return new Sha256(is224, true).update(message)[outputType]();
120
+ };
121
+ };
122
+ var createMethod = function(is224) {
123
+ var method = createOutputMethod('hex', is224);
124
+ if (NODE_JS) method = nodeWrap(method, is224);
125
+ method.create = function() {
126
+ return new Sha256(is224);
127
+ };
128
+ method.update = function(message) {
129
+ return method.create().update(message);
130
+ };
131
+ for(var i = 0; i < OUTPUT_TYPES.length; ++i){
132
+ var type = OUTPUT_TYPES[i];
133
+ method[type] = createOutputMethod(type, is224);
134
+ }
135
+ return method;
136
+ };
137
+ var nodeWrap = function(method, is224) {
138
+ var crypto = __webpack_require__("?7342");
139
+ var Buffer = __webpack_require__("?d94c").Buffer;
140
+ var algorithm = is224 ? 'sha224' : 'sha256';
141
+ var bufferFrom;
142
+ bufferFrom = Buffer.from && !root.JS_SHA256_NO_BUFFER_FROM ? Buffer.from : function(message) {
143
+ return new Buffer(message);
144
+ };
145
+ var nodeMethod = function(message) {
146
+ if ('string' == typeof message) return crypto.createHash(algorithm).update(message, 'utf8').digest('hex');
147
+ if (null == message) throw new Error(ERROR);
148
+ if (message.constructor === ArrayBuffer) message = new Uint8Array(message);
149
+ if (Array.isArray(message) || ArrayBuffer.isView(message) || message.constructor === Buffer) return crypto.createHash(algorithm).update(bufferFrom(message)).digest('hex');
150
+ return method(message);
151
+ };
152
+ return nodeMethod;
153
+ };
154
+ var createHmacOutputMethod = function(outputType, is224) {
155
+ return function(key, message) {
156
+ return new HmacSha256(key, is224, true).update(message)[outputType]();
157
+ };
158
+ };
159
+ var createHmacMethod = function(is224) {
160
+ var method = createHmacOutputMethod('hex', is224);
161
+ method.create = function(key) {
162
+ return new HmacSha256(key, is224);
163
+ };
164
+ method.update = function(key, message) {
165
+ return method.create(key).update(message);
166
+ };
167
+ for(var i = 0; i < OUTPUT_TYPES.length; ++i){
168
+ var type = OUTPUT_TYPES[i];
169
+ method[type] = createHmacOutputMethod(type, is224);
170
+ }
171
+ return method;
172
+ };
173
+ function Sha256(is224, sharedMemory) {
174
+ if (sharedMemory) {
175
+ 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;
176
+ this.blocks = blocks;
177
+ } else this.blocks = [
178
+ 0,
179
+ 0,
180
+ 0,
181
+ 0,
182
+ 0,
183
+ 0,
184
+ 0,
185
+ 0,
186
+ 0,
187
+ 0,
188
+ 0,
189
+ 0,
190
+ 0,
191
+ 0,
192
+ 0,
193
+ 0,
194
+ 0
195
+ ];
196
+ if (is224) {
197
+ this.h0 = 0xc1059ed8;
198
+ this.h1 = 0x367cd507;
199
+ this.h2 = 0x3070dd17;
200
+ this.h3 = 0xf70e5939;
201
+ this.h4 = 0xffc00b31;
202
+ this.h5 = 0x68581511;
203
+ this.h6 = 0x64f98fa7;
204
+ this.h7 = 0xbefa4fa4;
205
+ } else {
206
+ this.h0 = 0x6a09e667;
207
+ this.h1 = 0xbb67ae85;
208
+ this.h2 = 0x3c6ef372;
209
+ this.h3 = 0xa54ff53a;
210
+ this.h4 = 0x510e527f;
211
+ this.h5 = 0x9b05688c;
212
+ this.h6 = 0x1f83d9ab;
213
+ this.h7 = 0x5be0cd19;
214
+ }
215
+ this.block = this.start = this.bytes = this.hBytes = 0;
216
+ this.finalized = this.hashed = false;
217
+ this.first = true;
218
+ this.is224 = is224;
219
+ }
220
+ Sha256.prototype.update = function(message) {
221
+ if (this.finalized) return;
222
+ var notString, type = typeof message;
223
+ if ('string' !== type) {
224
+ if ('object' === type) {
225
+ if (null === message) throw new Error(ERROR);
226
+ else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) message = new Uint8Array(message);
227
+ else if (!Array.isArray(message)) {
228
+ if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) throw new Error(ERROR);
229
+ }
230
+ } else throw new Error(ERROR);
231
+ notString = true;
232
+ }
233
+ var code, index = 0, i, length = message.length, blocks = this.blocks;
234
+ while(index < length){
235
+ if (this.hashed) {
236
+ this.hashed = false;
237
+ blocks[0] = this.block;
238
+ this.block = 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;
239
+ }
240
+ if (notString) for(i = this.start; index < length && i < 64; ++index)blocks[i >>> 2] |= message[index] << SHIFT[3 & i++];
241
+ else for(i = this.start; index < length && i < 64; ++index){
242
+ code = message.charCodeAt(index);
243
+ if (code < 0x80) blocks[i >>> 2] |= code << SHIFT[3 & i++];
244
+ else if (code < 0x800) {
245
+ blocks[i >>> 2] |= (0xc0 | code >>> 6) << SHIFT[3 & i++];
246
+ blocks[i >>> 2] |= (0x80 | 0x3f & code) << SHIFT[3 & i++];
247
+ } else if (code < 0xd800 || code >= 0xe000) {
248
+ blocks[i >>> 2] |= (0xe0 | code >>> 12) << SHIFT[3 & i++];
249
+ blocks[i >>> 2] |= (0x80 | code >>> 6 & 0x3f) << SHIFT[3 & i++];
250
+ blocks[i >>> 2] |= (0x80 | 0x3f & code) << SHIFT[3 & i++];
251
+ } else {
252
+ code = 0x10000 + ((0x3ff & code) << 10 | 0x3ff & message.charCodeAt(++index));
253
+ blocks[i >>> 2] |= (0xf0 | code >>> 18) << SHIFT[3 & i++];
254
+ blocks[i >>> 2] |= (0x80 | code >>> 12 & 0x3f) << SHIFT[3 & i++];
255
+ blocks[i >>> 2] |= (0x80 | code >>> 6 & 0x3f) << SHIFT[3 & i++];
256
+ blocks[i >>> 2] |= (0x80 | 0x3f & code) << SHIFT[3 & i++];
257
+ }
258
+ }
259
+ this.lastByteIndex = i;
260
+ this.bytes += i - this.start;
261
+ if (i >= 64) {
262
+ this.block = blocks[16];
263
+ this.start = i - 64;
264
+ this.hash();
265
+ this.hashed = true;
266
+ } else this.start = i;
267
+ }
268
+ if (this.bytes > 4294967295) {
269
+ this.hBytes += this.bytes / 4294967296 | 0;
270
+ this.bytes = this.bytes % 4294967296;
271
+ }
272
+ return this;
273
+ };
274
+ Sha256.prototype.finalize = function() {
275
+ if (this.finalized) return;
276
+ this.finalized = true;
277
+ var blocks = this.blocks, i = this.lastByteIndex;
278
+ blocks[16] = this.block;
279
+ blocks[i >>> 2] |= EXTRA[3 & i];
280
+ this.block = blocks[16];
281
+ if (i >= 56) {
282
+ if (!this.hashed) this.hash();
283
+ blocks[0] = this.block;
284
+ 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;
285
+ }
286
+ blocks[14] = this.hBytes << 3 | this.bytes >>> 29;
287
+ blocks[15] = this.bytes << 3;
288
+ this.hash();
289
+ };
290
+ Sha256.prototype.hash = function() {
291
+ 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, blocks = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;
292
+ for(j = 16; j < 64; ++j){
293
+ t1 = blocks[j - 15];
294
+ s0 = (t1 >>> 7 | t1 << 25) ^ (t1 >>> 18 | t1 << 14) ^ t1 >>> 3;
295
+ t1 = blocks[j - 2];
296
+ s1 = (t1 >>> 17 | t1 << 15) ^ (t1 >>> 19 | t1 << 13) ^ t1 >>> 10;
297
+ blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 | 0;
298
+ }
299
+ bc = b & c;
300
+ for(j = 0; j < 64; j += 4){
301
+ if (this.first) {
302
+ if (this.is224) {
303
+ ab = 300032;
304
+ t1 = blocks[0] - 1413257819;
305
+ h = t1 - 150054599 | 0;
306
+ d = t1 + 24177077 | 0;
307
+ } else {
308
+ ab = 704751109;
309
+ t1 = blocks[0] - 210244248;
310
+ h = t1 - 1521486534 | 0;
311
+ d = t1 + 143694565 | 0;
312
+ }
313
+ this.first = false;
314
+ } else {
315
+ s0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10);
316
+ s1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7);
317
+ ab = a & b;
318
+ maj = ab ^ a & c ^ bc;
319
+ ch = e & f ^ ~e & g;
320
+ t1 = h + s1 + ch + K[j] + blocks[j];
321
+ t2 = s0 + maj;
322
+ h = d + t1 | 0;
323
+ d = t1 + t2 | 0;
324
+ }
325
+ s0 = (d >>> 2 | d << 30) ^ (d >>> 13 | d << 19) ^ (d >>> 22 | d << 10);
326
+ s1 = (h >>> 6 | h << 26) ^ (h >>> 11 | h << 21) ^ (h >>> 25 | h << 7);
327
+ da = d & a;
328
+ maj = da ^ d & b ^ ab;
329
+ ch = h & e ^ ~h & f;
330
+ t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];
331
+ t2 = s0 + maj;
332
+ g = c + t1 | 0;
333
+ c = t1 + t2 | 0;
334
+ s0 = (c >>> 2 | c << 30) ^ (c >>> 13 | c << 19) ^ (c >>> 22 | c << 10);
335
+ s1 = (g >>> 6 | g << 26) ^ (g >>> 11 | g << 21) ^ (g >>> 25 | g << 7);
336
+ cd = c & d;
337
+ maj = cd ^ c & a ^ da;
338
+ ch = g & h ^ ~g & e;
339
+ t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];
340
+ t2 = s0 + maj;
341
+ f = b + t1 | 0;
342
+ b = t1 + t2 | 0;
343
+ s0 = (b >>> 2 | b << 30) ^ (b >>> 13 | b << 19) ^ (b >>> 22 | b << 10);
344
+ s1 = (f >>> 6 | f << 26) ^ (f >>> 11 | f << 21) ^ (f >>> 25 | f << 7);
345
+ bc = b & c;
346
+ maj = bc ^ b & d ^ cd;
347
+ ch = f & g ^ ~f & h;
348
+ t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];
349
+ t2 = s0 + maj;
350
+ e = a + t1 | 0;
351
+ a = t1 + t2 | 0;
352
+ this.chromeBugWorkAround = true;
353
+ }
354
+ this.h0 = this.h0 + a | 0;
355
+ this.h1 = this.h1 + b | 0;
356
+ this.h2 = this.h2 + c | 0;
357
+ this.h3 = this.h3 + d | 0;
358
+ this.h4 = this.h4 + e | 0;
359
+ this.h5 = this.h5 + f | 0;
360
+ this.h6 = this.h6 + g | 0;
361
+ this.h7 = this.h7 + h | 0;
362
+ };
363
+ Sha256.prototype.hex = function() {
364
+ this.finalize();
365
+ 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;
366
+ var hex = HEX_CHARS[h0 >>> 28 & 0x0F] + HEX_CHARS[h0 >>> 24 & 0x0F] + HEX_CHARS[h0 >>> 20 & 0x0F] + HEX_CHARS[h0 >>> 16 & 0x0F] + HEX_CHARS[h0 >>> 12 & 0x0F] + HEX_CHARS[h0 >>> 8 & 0x0F] + HEX_CHARS[h0 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h0] + HEX_CHARS[h1 >>> 28 & 0x0F] + HEX_CHARS[h1 >>> 24 & 0x0F] + HEX_CHARS[h1 >>> 20 & 0x0F] + HEX_CHARS[h1 >>> 16 & 0x0F] + HEX_CHARS[h1 >>> 12 & 0x0F] + HEX_CHARS[h1 >>> 8 & 0x0F] + HEX_CHARS[h1 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h1] + HEX_CHARS[h2 >>> 28 & 0x0F] + HEX_CHARS[h2 >>> 24 & 0x0F] + HEX_CHARS[h2 >>> 20 & 0x0F] + HEX_CHARS[h2 >>> 16 & 0x0F] + HEX_CHARS[h2 >>> 12 & 0x0F] + HEX_CHARS[h2 >>> 8 & 0x0F] + HEX_CHARS[h2 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h2] + HEX_CHARS[h3 >>> 28 & 0x0F] + HEX_CHARS[h3 >>> 24 & 0x0F] + HEX_CHARS[h3 >>> 20 & 0x0F] + HEX_CHARS[h3 >>> 16 & 0x0F] + HEX_CHARS[h3 >>> 12 & 0x0F] + HEX_CHARS[h3 >>> 8 & 0x0F] + HEX_CHARS[h3 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h3] + HEX_CHARS[h4 >>> 28 & 0x0F] + HEX_CHARS[h4 >>> 24 & 0x0F] + HEX_CHARS[h4 >>> 20 & 0x0F] + HEX_CHARS[h4 >>> 16 & 0x0F] + HEX_CHARS[h4 >>> 12 & 0x0F] + HEX_CHARS[h4 >>> 8 & 0x0F] + HEX_CHARS[h4 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h4] + HEX_CHARS[h5 >>> 28 & 0x0F] + HEX_CHARS[h5 >>> 24 & 0x0F] + HEX_CHARS[h5 >>> 20 & 0x0F] + HEX_CHARS[h5 >>> 16 & 0x0F] + HEX_CHARS[h5 >>> 12 & 0x0F] + HEX_CHARS[h5 >>> 8 & 0x0F] + HEX_CHARS[h5 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h5] + HEX_CHARS[h6 >>> 28 & 0x0F] + HEX_CHARS[h6 >>> 24 & 0x0F] + HEX_CHARS[h6 >>> 20 & 0x0F] + HEX_CHARS[h6 >>> 16 & 0x0F] + HEX_CHARS[h6 >>> 12 & 0x0F] + HEX_CHARS[h6 >>> 8 & 0x0F] + HEX_CHARS[h6 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h6];
367
+ if (!this.is224) hex += HEX_CHARS[h7 >>> 28 & 0x0F] + HEX_CHARS[h7 >>> 24 & 0x0F] + HEX_CHARS[h7 >>> 20 & 0x0F] + HEX_CHARS[h7 >>> 16 & 0x0F] + HEX_CHARS[h7 >>> 12 & 0x0F] + HEX_CHARS[h7 >>> 8 & 0x0F] + HEX_CHARS[h7 >>> 4 & 0x0F] + HEX_CHARS[0x0F & h7];
368
+ return hex;
369
+ };
370
+ Sha256.prototype.toString = Sha256.prototype.hex;
371
+ Sha256.prototype.digest = function() {
372
+ this.finalize();
373
+ 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;
374
+ var arr = [
375
+ h0 >>> 24 & 0xFF,
376
+ h0 >>> 16 & 0xFF,
377
+ h0 >>> 8 & 0xFF,
378
+ 0xFF & h0,
379
+ h1 >>> 24 & 0xFF,
380
+ h1 >>> 16 & 0xFF,
381
+ h1 >>> 8 & 0xFF,
382
+ 0xFF & h1,
383
+ h2 >>> 24 & 0xFF,
384
+ h2 >>> 16 & 0xFF,
385
+ h2 >>> 8 & 0xFF,
386
+ 0xFF & h2,
387
+ h3 >>> 24 & 0xFF,
388
+ h3 >>> 16 & 0xFF,
389
+ h3 >>> 8 & 0xFF,
390
+ 0xFF & h3,
391
+ h4 >>> 24 & 0xFF,
392
+ h4 >>> 16 & 0xFF,
393
+ h4 >>> 8 & 0xFF,
394
+ 0xFF & h4,
395
+ h5 >>> 24 & 0xFF,
396
+ h5 >>> 16 & 0xFF,
397
+ h5 >>> 8 & 0xFF,
398
+ 0xFF & h5,
399
+ h6 >>> 24 & 0xFF,
400
+ h6 >>> 16 & 0xFF,
401
+ h6 >>> 8 & 0xFF,
402
+ 0xFF & h6
403
+ ];
404
+ if (!this.is224) arr.push(h7 >>> 24 & 0xFF, h7 >>> 16 & 0xFF, h7 >>> 8 & 0xFF, 0xFF & h7);
405
+ return arr;
406
+ };
407
+ Sha256.prototype.array = Sha256.prototype.digest;
408
+ Sha256.prototype.arrayBuffer = function() {
409
+ this.finalize();
410
+ var buffer = new ArrayBuffer(this.is224 ? 28 : 32);
411
+ var dataView = new DataView(buffer);
412
+ dataView.setUint32(0, this.h0);
413
+ dataView.setUint32(4, this.h1);
414
+ dataView.setUint32(8, this.h2);
415
+ dataView.setUint32(12, this.h3);
416
+ dataView.setUint32(16, this.h4);
417
+ dataView.setUint32(20, this.h5);
418
+ dataView.setUint32(24, this.h6);
419
+ if (!this.is224) dataView.setUint32(28, this.h7);
420
+ return buffer;
421
+ };
422
+ function HmacSha256(key, is224, sharedMemory) {
423
+ var i, type = typeof key;
424
+ if ('string' === type) {
425
+ var bytes = [], length = key.length, index = 0, code;
426
+ for(i = 0; i < length; ++i){
427
+ code = key.charCodeAt(i);
428
+ if (code < 0x80) bytes[index++] = code;
429
+ else if (code < 0x800) {
430
+ bytes[index++] = 0xc0 | code >>> 6;
431
+ bytes[index++] = 0x80 | 0x3f & code;
432
+ } else if (code < 0xd800 || code >= 0xe000) {
433
+ bytes[index++] = 0xe0 | code >>> 12;
434
+ bytes[index++] = 0x80 | code >>> 6 & 0x3f;
435
+ bytes[index++] = 0x80 | 0x3f & code;
436
+ } else {
437
+ code = 0x10000 + ((0x3ff & code) << 10 | 0x3ff & key.charCodeAt(++i));
438
+ bytes[index++] = 0xf0 | code >>> 18;
439
+ bytes[index++] = 0x80 | code >>> 12 & 0x3f;
440
+ bytes[index++] = 0x80 | code >>> 6 & 0x3f;
441
+ bytes[index++] = 0x80 | 0x3f & code;
442
+ }
443
+ }
444
+ key = bytes;
445
+ } else if ('object' === type) {
446
+ if (null === key) throw new Error(ERROR);
447
+ else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) key = new Uint8Array(key);
448
+ else if (!Array.isArray(key)) {
449
+ if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) throw new Error(ERROR);
450
+ }
451
+ } else throw new Error(ERROR);
452
+ if (key.length > 64) key = new Sha256(is224, true).update(key).array();
453
+ var oKeyPad = [], iKeyPad = [];
454
+ for(i = 0; i < 64; ++i){
455
+ var b = key[i] || 0;
456
+ oKeyPad[i] = 0x5c ^ b;
457
+ iKeyPad[i] = 0x36 ^ b;
458
+ }
459
+ Sha256.call(this, is224, sharedMemory);
460
+ this.update(iKeyPad);
461
+ this.oKeyPad = oKeyPad;
462
+ this.inner = true;
463
+ this.sharedMemory = sharedMemory;
464
+ }
465
+ HmacSha256.prototype = new Sha256();
466
+ HmacSha256.prototype.finalize = function() {
467
+ Sha256.prototype.finalize.call(this);
468
+ if (this.inner) {
469
+ this.inner = false;
470
+ var innerHash = this.array();
471
+ Sha256.call(this, this.is224, this.sharedMemory);
472
+ this.update(this.oKeyPad);
473
+ this.update(innerHash);
474
+ Sha256.prototype.finalize.call(this);
475
+ }
476
+ };
477
+ var exports = createMethod();
478
+ exports.sha256 = exports;
479
+ exports.sha224 = createMethod(true);
480
+ exports.sha256.hmac = createHmacMethod();
481
+ exports.sha224.hmac = createHmacMethod(true);
482
+ if (COMMON_JS) module.exports = exports;
483
+ else {
484
+ root.sha256 = exports.sha256;
485
+ root.sha224 = exports.sha224;
486
+ if (AMD) define(function() {
487
+ return exports;
488
+ });
489
+ }
490
+ })();
491
+ },
492
+ "../shared/dist/lib/extractor.js": function(module, __unused_webpack_exports, __webpack_require__) {
493
+ "use strict";
494
+ var __defProp = Object.defineProperty;
495
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
496
+ var __getOwnPropNames = Object.getOwnPropertyNames;
497
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
498
+ var __export = (target, all)=>{
499
+ for(var name in all)__defProp(target, name, {
500
+ get: all[name],
501
+ enumerable: true
502
+ });
62
503
  };
63
- }
64
- start() {
65
- if (this.isRecording) return void debugLog('Recording already active, ignoring start request');
66
- this.isRecording = true;
67
- debugLog('Starting event recording');
68
- this.scrollTargets = [];
69
- if (0 === this.scrollTargets.length) {
70
- this.scrollTargets = getAllScrollableElements();
71
- this.scrollTargets.push(document.body);
72
- }
73
- debugLog('Added event listeners for', this.scrollTargets.length, 'scroll targets');
74
- setTimeout(()=>{
75
- const navigationEvent = this.createNavigationEvent(window.location.href, document.title);
76
- this.eventCallback(navigationEvent);
77
- debugLog('Added final navigation event', navigationEvent);
78
- }, 0);
79
- document.addEventListener('click', this.handleClick, true);
80
- document.addEventListener('input', this.handleInput);
81
- document.addEventListener('scroll', this.handleScroll, {
82
- passive: true
504
+ var __copyProps = (to, from, except, desc)=>{
505
+ if (from && "object" == typeof from || "function" == typeof from) {
506
+ for (let key of __getOwnPropNames(from))if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
507
+ get: ()=>from[key],
508
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
509
+ });
510
+ }
511
+ return to;
512
+ };
513
+ var __toCommonJS = (mod)=>__copyProps(__defProp({}, "__esModule", {
514
+ value: true
515
+ }), mod);
516
+ var extractor_exports = {};
517
+ __export(extractor_exports, {
518
+ descriptionOfTree: ()=>descriptionOfTree,
519
+ generateElementByPosition: ()=>generateElementByPosition,
520
+ getElementInfoByXpath: ()=>getElementInfoByXpath,
521
+ getNodeFromCacheList: ()=>getNodeFromCacheList,
522
+ getNodeInfoByXpath: ()=>getNodeInfoByXpath,
523
+ getXpathsById: ()=>getXpathsById,
524
+ isNotContainerElement: ()=>isNotContainerElement,
525
+ setNodeHashCacheListOnWindow: ()=>setNodeHashCacheListOnWindow,
526
+ traverseTree: ()=>traverseTree,
527
+ treeToList: ()=>treeToList,
528
+ trimAttributes: ()=>trimAttributes,
529
+ truncateText: ()=>truncateText,
530
+ webExtractNodeTree: ()=>extractTreeNode,
531
+ webExtractNodeTreeAsString: ()=>extractTreeNodeAsString,
532
+ webExtractTextWithPosition: ()=>extractTextWithPosition
83
533
  });
84
- this.scrollTargets.forEach((target)=>{
85
- target.addEventListener('scroll', this.handleScroll, {
86
- passive: true
534
+ module.exports = __toCommonJS(extractor_exports);
535
+ function truncateText(text, maxLength = 150) {
536
+ if (void 0 === text) return "";
537
+ if ("object" == typeof text) text = JSON.stringify(text);
538
+ if ("number" == typeof text) return text.toString();
539
+ if ("string" == typeof text && text.length > maxLength) return `${text.slice(0, maxLength)}...`;
540
+ if ("string" == typeof text) return text.trim();
541
+ return "";
542
+ }
543
+ function trimAttributes(attributes, truncateTextLength) {
544
+ const tailorAttributes = Object.keys(attributes).reduce((res, currentKey)=>{
545
+ const attributeVal = attributes[currentKey];
546
+ if ("style" === currentKey || "htmlTagName" === currentKey || "nodeType" === currentKey) return res;
547
+ res[currentKey] = truncateText(attributeVal, truncateTextLength);
548
+ return res;
549
+ }, {});
550
+ return tailorAttributes;
551
+ }
552
+ var nodeSizeThreshold = 4;
553
+ function descriptionOfTree(tree, truncateTextLength, filterNonTextContent = false, visibleOnly = true) {
554
+ const attributesString = (kv)=>Object.entries(kv).map(([key, value])=>`${key}="${truncateText(value, truncateTextLength)}"`).join(" ");
555
+ function buildContentTree(node, indent = 0, visibleOnly2 = true) {
556
+ let before = "";
557
+ let contentWithIndent = "";
558
+ let after = "";
559
+ let emptyNode = true;
560
+ const indentStr = " ".repeat(indent);
561
+ let children = "";
562
+ for(let i = 0; i < (node.children || []).length; i++){
563
+ const childContent = buildContentTree(node.children[i], indent + 1, visibleOnly2);
564
+ if (childContent) children += `
565
+ ${childContent}`;
566
+ }
567
+ if (node.node && node.node.rect.width > nodeSizeThreshold && node.node.rect.height > nodeSizeThreshold && (!filterNonTextContent || filterNonTextContent && node.node.content) && (!visibleOnly2 || visibleOnly2 && node.node.isVisible)) {
568
+ emptyNode = false;
569
+ let nodeTypeString;
570
+ nodeTypeString = node.node.attributes?.htmlTagName ? node.node.attributes.htmlTagName.replace(/[<>]/g, "") : node.node.attributes.nodeType.replace(/\sNode$/, "").toLowerCase();
571
+ const markerId = node.node.indexId;
572
+ const markerIdString = markerId ? `markerId="${markerId}"` : "";
573
+ const rectAttribute = node.node.rect ? {
574
+ left: node.node.rect.left,
575
+ top: node.node.rect.top,
576
+ width: node.node.rect.width,
577
+ height: node.node.rect.height
578
+ } : {};
579
+ before = `<${nodeTypeString} id="${node.node.id}" ${markerIdString} ${attributesString(trimAttributes(node.node.attributes || {}, truncateTextLength))} ${attributesString(rectAttribute)}>`;
580
+ const content = truncateText(node.node.content, truncateTextLength);
581
+ contentWithIndent = content ? `
582
+ ${indentStr} ${content}` : "";
583
+ after = `</${nodeTypeString}>`;
584
+ } else if (!filterNonTextContent) {
585
+ if (!children.trim().startsWith("<>")) {
586
+ before = "<>";
587
+ contentWithIndent = "";
588
+ after = "</>";
589
+ }
590
+ }
591
+ if (emptyNode && !children.trim()) return "";
592
+ const result2 = `${indentStr}${before}${contentWithIndent}${children}
593
+ ${indentStr}${after}`;
594
+ if (result2.trim()) return result2;
595
+ return "";
596
+ }
597
+ const result = buildContentTree(tree, 0, visibleOnly);
598
+ return result.replace(/^\s*\n/gm, "");
599
+ }
600
+ function treeToList(tree) {
601
+ const result = [];
602
+ function dfs(node) {
603
+ if (node.node) result.push(node.node);
604
+ for (const child of node.children)dfs(child);
605
+ }
606
+ dfs(tree);
607
+ return result;
608
+ }
609
+ function traverseTree(tree, onNode) {
610
+ function dfs(node) {
611
+ if (node.node) node.node = onNode(node.node);
612
+ for (const child of node.children)dfs(child);
613
+ }
614
+ dfs(tree);
615
+ return tree;
616
+ }
617
+ var CONTAINER_MINI_HEIGHT = 3;
618
+ var CONTAINER_MINI_WIDTH = 3;
619
+ var import_js_sha256 = __webpack_require__("../../node_modules/.pnpm/js-sha256@0.11.0/node_modules/js-sha256/src/sha256.js");
620
+ var hashMap = {};
621
+ function generateHashId(rect, content = "") {
622
+ const combined = JSON.stringify({
623
+ content,
624
+ rect
87
625
  });
88
- });
89
- }
90
- stop() {
91
- if (!this.isRecording) return void debugLog('Recording not active, ignoring stop request');
92
- this.isRecording = false;
93
- debugLog('Stopping event recording');
94
- if (this.scrollThrottleTimer) {
95
- clearTimeout(this.scrollThrottleTimer);
96
- this.scrollThrottleTimer = null;
97
- }
98
- document.removeEventListener('click', this.handleClick);
99
- document.removeEventListener('input', this.handleInput);
100
- this.scrollTargets.forEach((target)=>{
101
- target.removeEventListener('scroll', this.handleScroll);
102
- });
103
- debugLog('Removed all event listeners');
104
- }
105
- handleClick = (event)=>{
106
- if (!this.isRecording) return;
107
- const target = event.target;
108
- const { isLabelClick, labelInfo } = this.checkLabelClick(target);
109
- target.getBoundingClientRect();
110
- const elementRect = {
111
- x: Number(event.clientX.toFixed(2)),
112
- y: Number(event.clientY.toFixed(2))
113
- };
114
- const clickEvent = {
115
- type: 'click',
116
- elementRect,
117
- pageInfo: {
118
- width: window.innerWidth,
119
- height: window.innerHeight
120
- },
121
- value: '',
122
- timestamp: Date.now(),
123
- hashId: generateHashId('click', {
124
- ...elementRect
125
- }),
126
- element: target,
127
- isLabelClick,
128
- labelInfo,
129
- isTrusted: event.isTrusted,
130
- detail: event.detail
626
+ let sliceLength = 5;
627
+ let slicedHash = "";
628
+ const hashHex = import_js_sha256.sha256.create().update(combined).hex();
629
+ const toLetters = (hex)=>hex.split("").map((char)=>{
630
+ const code = Number.parseInt(char, 16);
631
+ return String.fromCharCode(97 + code % 26);
632
+ }).join("");
633
+ const hashLetters = toLetters(hashHex);
634
+ while(sliceLength < hashLetters.length - 1){
635
+ slicedHash = hashLetters.slice(0, sliceLength);
636
+ if (hashMap[slicedHash] && hashMap[slicedHash] !== combined) {
637
+ sliceLength++;
638
+ continue;
639
+ }
640
+ hashMap[slicedHash] = combined;
641
+ break;
642
+ }
643
+ return slicedHash;
644
+ }
645
+ function isFormElement(node) {
646
+ return node instanceof HTMLElement && ("input" === node.tagName.toLowerCase() || "textarea" === node.tagName.toLowerCase() || "select" === node.tagName.toLowerCase() || "option" === node.tagName.toLowerCase());
647
+ }
648
+ function isButtonElement(node) {
649
+ return node instanceof HTMLElement && "button" === node.tagName.toLowerCase();
650
+ }
651
+ function isAElement(node) {
652
+ return node instanceof HTMLElement && "a" === node.tagName.toLowerCase();
653
+ }
654
+ function isImgElement(node) {
655
+ if (!includeBaseElement(node) && node instanceof Element) {
656
+ const computedStyle = window.getComputedStyle(node);
657
+ const backgroundImage = computedStyle.getPropertyValue("background-image");
658
+ if ("none" !== backgroundImage) return true;
659
+ }
660
+ if (isIconfont(node)) return true;
661
+ return node instanceof HTMLElement && "img" === node.tagName.toLowerCase() || node instanceof SVGElement && "svg" === node.tagName.toLowerCase();
662
+ }
663
+ function isIconfont(node) {
664
+ if (node instanceof Element) {
665
+ const computedStyle = window.getComputedStyle(node);
666
+ const fontFamilyValue = computedStyle.fontFamily || "";
667
+ return fontFamilyValue.toLowerCase().indexOf("iconfont") >= 0;
668
+ }
669
+ return false;
670
+ }
671
+ function isNotContainerElement(node) {
672
+ return isTextElement(node) || isIconfont(node) || isImgElement(node) || isButtonElement(node) || isAElement(node) || isFormElement(node);
673
+ }
674
+ function isTextElement(node) {
675
+ if (node instanceof Element) {
676
+ if (node?.childNodes?.length === 1 && node?.childNodes[0] instanceof Text) return true;
677
+ }
678
+ return node.nodeName?.toLowerCase() === "#text" && !isIconfont(node);
679
+ }
680
+ function isContainerElement(node) {
681
+ if (!(node instanceof HTMLElement)) return false;
682
+ if (includeBaseElement(node)) return false;
683
+ const computedStyle = window.getComputedStyle(node);
684
+ const backgroundColor = computedStyle.getPropertyValue("background-color");
685
+ if (backgroundColor) return true;
686
+ return false;
687
+ }
688
+ function includeBaseElement(node) {
689
+ if (!(node instanceof HTMLElement)) return false;
690
+ if (node.innerText) return true;
691
+ const includeList = [
692
+ "svg",
693
+ "button",
694
+ "input",
695
+ "textarea",
696
+ "select",
697
+ "option",
698
+ "img",
699
+ "a"
700
+ ];
701
+ for (const tagName of includeList){
702
+ const element = node.querySelectorAll(tagName);
703
+ if (element.length > 0) return true;
704
+ }
705
+ return false;
706
+ }
707
+ function generateElementByPosition(position) {
708
+ const rect = {
709
+ left: Math.max(position.x - 4, 0),
710
+ top: Math.max(position.y - 4, 0),
711
+ width: 8,
712
+ height: 8
713
+ };
714
+ const id = generateHashId(rect);
715
+ const element = {
716
+ id,
717
+ attributes: {
718
+ nodeType: "POSITION Node"
719
+ },
720
+ rect,
721
+ content: "",
722
+ center: [
723
+ position.x,
724
+ position.y
725
+ ]
726
+ };
727
+ return element;
728
+ }
729
+ var MAX_VALUE_LENGTH = 300;
730
+ var debugMode = false;
731
+ function setDebugMode(mode) {
732
+ debugMode = mode;
733
+ }
734
+ function logger(..._msg) {
735
+ if (!debugMode) return;
736
+ console.log(..._msg);
737
+ }
738
+ function isElementPartiallyInViewport(rect, currentWindow, currentDocument, visibleAreaRatio = 2 / 3) {
739
+ const elementHeight = rect.height;
740
+ const elementWidth = rect.width;
741
+ const viewportRect = {
742
+ left: 0,
743
+ top: 0,
744
+ width: currentWindow.innerWidth || currentDocument.documentElement.clientWidth,
745
+ height: currentWindow.innerHeight || currentDocument.documentElement.clientHeight,
746
+ right: currentWindow.innerWidth || currentDocument.documentElement.clientWidth,
747
+ bottom: currentWindow.innerHeight || currentDocument.documentElement.clientHeight,
748
+ x: 0,
749
+ y: 0,
750
+ zoom: 1
751
+ };
752
+ const overlapRect = overlappedRect(rect, viewportRect);
753
+ if (!overlapRect) return false;
754
+ const visibleArea = overlapRect.width * overlapRect.height;
755
+ const totalArea = elementHeight * elementWidth;
756
+ return visibleArea / totalArea >= visibleAreaRatio;
757
+ }
758
+ function getPseudoElementContent(element, currentWindow) {
759
+ if (!(element instanceof currentWindow.HTMLElement)) return {
760
+ before: "",
761
+ after: ""
762
+ };
763
+ const beforeContent = currentWindow.getComputedStyle(element, "::before").getPropertyValue("content");
764
+ const afterContent = currentWindow.getComputedStyle(element, "::after").getPropertyValue("content");
765
+ return {
766
+ before: "none" === beforeContent ? "" : beforeContent.replace(/"/g, ""),
767
+ after: "none" === afterContent ? "" : afterContent.replace(/"/g, "")
768
+ };
769
+ }
770
+ function overlappedRect(rect1, rect2) {
771
+ const left = Math.max(rect1.left, rect2.left);
772
+ const top = Math.max(rect1.top, rect2.top);
773
+ const right = Math.min(rect1.right, rect2.right);
774
+ const bottom = Math.min(rect1.bottom, rect2.bottom);
775
+ if (left < right && top < bottom) return {
776
+ left,
777
+ top,
778
+ right,
779
+ bottom,
780
+ width: right - left,
781
+ height: bottom - top,
782
+ x: left,
783
+ y: top,
784
+ zoom: 1
785
+ };
786
+ return null;
787
+ }
788
+ function getRect(el, baseZoom, currentWindow) {
789
+ let originalRect;
790
+ let newZoom = 1;
791
+ if (el instanceof currentWindow.HTMLElement) {
792
+ originalRect = el.getBoundingClientRect();
793
+ if (!("currentCSSZoom" in el)) newZoom = Number.parseFloat(currentWindow.getComputedStyle(el).zoom) || 1;
794
+ } else {
795
+ const range = currentWindow.document.createRange();
796
+ range.selectNodeContents(el);
797
+ originalRect = range.getBoundingClientRect();
798
+ }
799
+ const zoom = newZoom * baseZoom;
800
+ return {
801
+ width: originalRect.width * zoom,
802
+ height: originalRect.height * zoom,
803
+ left: originalRect.left * zoom,
804
+ top: originalRect.top * zoom,
805
+ right: originalRect.right * zoom,
806
+ bottom: originalRect.bottom * zoom,
807
+ x: originalRect.x * zoom,
808
+ y: originalRect.y * zoom,
809
+ zoom
810
+ };
811
+ }
812
+ var isElementCovered = (el, rect, currentWindow)=>{
813
+ const x = rect.left + rect.width / 2;
814
+ const y = rect.top + rect.height / 2;
815
+ const topElement = currentWindow.document.elementFromPoint(x, y);
816
+ if (!topElement) return false;
817
+ if (topElement === el) return false;
818
+ if (el?.contains(topElement)) return false;
819
+ if (topElement?.contains(el)) return false;
820
+ const rectOfTopElement = getRect(topElement, 1, currentWindow);
821
+ const overlapRect = overlappedRect(rect, rectOfTopElement);
822
+ if (!overlapRect) return false;
823
+ logger(el, "Element is covered by another element", {
824
+ topElement,
825
+ el,
826
+ rect,
827
+ x,
828
+ y
829
+ });
830
+ return true;
131
831
  };
132
- this.eventCallback(clickEvent);
133
- };
134
- handleScroll = (event)=>{
135
- if (!this.isRecording) return;
136
- function isDocument(target) {
137
- return target instanceof Document;
138
- }
139
- const target = event.target;
140
- const scrollXTarget = isDocument(target) ? window.scrollX : target.scrollLeft;
141
- const scrollYTarget = isDocument(target) ? window.scrollY : target.scrollTop;
142
- const rect = isDocument(target) ? {
832
+ function elementRect(el, currentWindow, currentDocument, baseZoom = 1) {
833
+ if (!el) {
834
+ logger(el, "Element is not in the DOM hierarchy");
835
+ return false;
836
+ }
837
+ if (!(el instanceof currentWindow.HTMLElement) && el.nodeType !== Node.TEXT_NODE && "svg" !== el.nodeName.toLowerCase()) {
838
+ logger(el, "Element is not in the DOM hierarchy");
839
+ return false;
840
+ }
841
+ if (el instanceof currentWindow.HTMLElement) {
842
+ const style = currentWindow.getComputedStyle(el);
843
+ if ("none" === style.display || "hidden" === style.visibility || "0" === style.opacity && "INPUT" !== el.tagName) {
844
+ logger(el, "Element is hidden");
845
+ return false;
846
+ }
847
+ }
848
+ const rect = getRect(el, baseZoom, currentWindow);
849
+ if (0 === rect.width && 0 === rect.height) {
850
+ logger(el, "Element has no size");
851
+ return false;
852
+ }
853
+ if (1 === baseZoom && isElementCovered(el, rect, currentWindow)) return false;
854
+ const isVisible = isElementPartiallyInViewport(rect, currentWindow, currentDocument);
855
+ let parent = el;
856
+ const parentUntilNonStatic = (currentNode)=>{
857
+ let parent2 = currentNode?.parentElement;
858
+ while(parent2){
859
+ const style = currentWindow.getComputedStyle(parent2);
860
+ if ("static" !== style.position) return parent2;
861
+ parent2 = parent2.parentElement;
862
+ }
863
+ return null;
864
+ };
865
+ while(parent && parent !== currentDocument.body){
866
+ if (!(parent instanceof currentWindow.HTMLElement)) {
867
+ parent = parent.parentElement;
868
+ continue;
869
+ }
870
+ const parentStyle = currentWindow.getComputedStyle(parent);
871
+ if ("hidden" === parentStyle.overflow) {
872
+ const parentRect = getRect(parent, 1, currentWindow);
873
+ const tolerance = 10;
874
+ if (rect.right < parentRect.left - tolerance || rect.left > parentRect.right + tolerance || rect.bottom < parentRect.top - tolerance || rect.top > parentRect.bottom + tolerance) {
875
+ logger(el, "element is partially or totally hidden by an ancestor", {
876
+ rect,
877
+ parentRect
878
+ });
879
+ return false;
880
+ }
881
+ }
882
+ if ("fixed" === parentStyle.position || "sticky" === parentStyle.position) break;
883
+ parent = "absolute" === parentStyle.position ? parentUntilNonStatic(parent) : parent.parentElement;
884
+ }
885
+ return {
886
+ left: Math.round(rect.left),
887
+ top: Math.round(rect.top),
888
+ width: Math.round(rect.width),
889
+ height: Math.round(rect.height),
890
+ zoom: rect.zoom,
891
+ isVisible
892
+ };
893
+ }
894
+ function getNodeAttributes(node, currentWindow) {
895
+ if (!node || !(node instanceof currentWindow.HTMLElement) || !node.attributes) return {};
896
+ const attributesList = Array.from(node.attributes).map((attr)=>{
897
+ if ("class" === attr.name) return [
898
+ attr.name,
899
+ `.${attr.value.split(" ").join(".")}`
900
+ ];
901
+ if (!attr.value) return [];
902
+ let value = attr.value;
903
+ if (value.startsWith("data:image")) value = "image";
904
+ if (value.length > MAX_VALUE_LENGTH) value = `${value.slice(0, MAX_VALUE_LENGTH)}...`;
905
+ return [
906
+ attr.name,
907
+ value
908
+ ];
909
+ });
910
+ return Object.fromEntries(attributesList);
911
+ }
912
+ function midsceneGenerateHash(node, content, rect) {
913
+ const slicedHash = generateHashId(rect, content);
914
+ if (node) {
915
+ if (!window.midsceneNodeHashCacheList) setNodeHashCacheListOnWindow();
916
+ setNodeToCacheList(node, slicedHash);
917
+ }
918
+ return slicedHash;
919
+ }
920
+ function setNodeHashCacheListOnWindow() {
921
+ if ("undefined" != typeof window) window.midsceneNodeHashCacheList = [];
922
+ }
923
+ function setNodeToCacheList(node, id) {
924
+ if ("undefined" != typeof window) {
925
+ if (getNodeFromCacheList(id)) return;
926
+ window.midsceneNodeHashCacheList?.push({
927
+ node,
928
+ id
929
+ });
930
+ }
931
+ }
932
+ function getNodeFromCacheList(id) {
933
+ if ("undefined" != typeof window) return window.midsceneNodeHashCacheList?.find((item)=>item.id === id)?.node;
934
+ return null;
935
+ }
936
+ function getTopDocument() {
937
+ const container = document.body || document;
938
+ return container;
939
+ }
940
+ var indexId = 0;
941
+ function tagNameOfNode(node) {
942
+ let tagName = "";
943
+ if (node instanceof HTMLElement) tagName = node.tagName?.toLowerCase();
944
+ else {
945
+ const parentElement = node.parentElement;
946
+ if (parentElement && parentElement instanceof HTMLElement) tagName = parentElement.tagName?.toLowerCase();
947
+ }
948
+ return tagName ? `<${tagName}>` : "";
949
+ }
950
+ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1, basePoint = {
143
951
  left: 0,
144
- top: 0,
145
- width: window.innerWidth,
146
- height: window.innerHeight
147
- } : target.getBoundingClientRect();
148
- if (this.scrollThrottleTimer) clearTimeout(this.scrollThrottleTimer);
149
- this.scrollThrottleTimer = window.setTimeout(()=>{
150
- if (this.isRecording) {
151
- const elementRect = {
152
- left: isDocument(target) ? 0 : Number(rect.left.toFixed(2)),
153
- top: isDocument(target) ? 0 : Number(rect.top.toFixed(2)),
154
- width: isDocument(target) ? window.innerWidth : Number(rect.width.toFixed(2)),
155
- height: isDocument(target) ? window.innerHeight : Number(rect.height.toFixed(2))
952
+ top: 0
953
+ }) {
954
+ const rect = elementRect(node, currentWindow, currentDocument, baseZoom);
955
+ if (!rect) return null;
956
+ if (rect.width < CONTAINER_MINI_WIDTH || rect.height < CONTAINER_MINI_HEIGHT) return null;
957
+ if (0 !== basePoint.left || 0 !== basePoint.top) {
958
+ rect.left += basePoint.left;
959
+ rect.top += basePoint.top;
960
+ }
961
+ if (rect.height >= window.innerHeight && rect.width >= window.innerWidth) return null;
962
+ if (isFormElement(node)) {
963
+ const attributes = getNodeAttributes(node, currentWindow);
964
+ let valueContent = attributes.value || attributes.placeholder || node.textContent || "";
965
+ const nodeHashId = midsceneGenerateHash(node, valueContent, rect);
966
+ const tagName = node.tagName.toLowerCase();
967
+ if ("select" === node.tagName.toLowerCase()) {
968
+ const selectedOption = node.options[node.selectedIndex];
969
+ valueContent = selectedOption?.textContent || "";
970
+ }
971
+ if (("input" === node.tagName.toLowerCase() || "textarea" === node.tagName.toLowerCase()) && node.value) valueContent = node.value;
972
+ const elementInfo = {
973
+ id: nodeHashId,
974
+ nodeHashId,
975
+ nodeType: "FORM_ITEM Node",
976
+ indexId: indexId++,
977
+ attributes: {
978
+ ...attributes,
979
+ htmlTagName: `<${tagName}>`,
980
+ nodeType: "FORM_ITEM Node"
981
+ },
982
+ content: valueContent.trim(),
983
+ rect,
984
+ center: [
985
+ Math.round(rect.left + rect.width / 2),
986
+ Math.round(rect.top + rect.height / 2)
987
+ ],
988
+ zoom: rect.zoom,
989
+ isVisible: rect.isVisible
156
990
  };
157
- const scrollEvent = {
158
- type: 'scroll',
159
- elementRect,
160
- pageInfo: {
161
- width: window.innerWidth,
162
- height: window.innerHeight
991
+ return elementInfo;
992
+ }
993
+ if (isButtonElement(node)) {
994
+ const rect2 = mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom);
995
+ if (!rect2) return null;
996
+ const attributes = getNodeAttributes(node, currentWindow);
997
+ const pseudo = getPseudoElementContent(node, currentWindow);
998
+ const content = node.innerText || pseudo.before || pseudo.after || "";
999
+ const nodeHashId = midsceneGenerateHash(node, content, rect2);
1000
+ const elementInfo = {
1001
+ id: nodeHashId,
1002
+ indexId: indexId++,
1003
+ nodeHashId,
1004
+ nodeType: "BUTTON Node",
1005
+ attributes: {
1006
+ ...attributes,
1007
+ htmlTagName: tagNameOfNode(node),
1008
+ nodeType: "BUTTON Node"
163
1009
  },
164
- value: `${scrollXTarget.toFixed(2)},${scrollYTarget.toFixed(2)}`,
165
- timestamp: Date.now(),
166
- hashId: generateHashId('scroll', {
167
- ...elementRect
168
- }),
169
- element: target
1010
+ content,
1011
+ rect: rect2,
1012
+ center: [
1013
+ Math.round(rect2.left + rect2.width / 2),
1014
+ Math.round(rect2.top + rect2.height / 2)
1015
+ ],
1016
+ zoom: rect2.zoom,
1017
+ isVisible: rect2.isVisible
170
1018
  };
171
- this.eventCallback(scrollEvent);
1019
+ return elementInfo;
172
1020
  }
173
- this.scrollThrottleTimer = null;
174
- }, this.scrollThrottleDelay);
175
- };
176
- handleInput = (event)=>{
177
- if (!this.isRecording) return;
178
- const target = event.target;
179
- if ('checkbox' === target.type) return;
180
- const rect = target.getBoundingClientRect();
181
- const elementRect = {
182
- left: Number(rect.left.toFixed(2)),
183
- top: Number(rect.top.toFixed(2)),
184
- width: Number(rect.width.toFixed(2)),
185
- height: Number(rect.height.toFixed(2))
186
- };
187
- const inputEvent = {
188
- type: 'input',
189
- value: 'password' !== target.type ? target.value : '*****',
190
- timestamp: Date.now(),
191
- hashId: generateHashId('input', {
192
- ...elementRect
193
- }),
194
- element: target,
195
- inputType: target.type || 'text',
196
- elementRect,
197
- pageInfo: {
198
- width: window.innerWidth,
199
- height: window.innerHeight
1021
+ if (isImgElement(node)) {
1022
+ const attributes = getNodeAttributes(node, currentWindow);
1023
+ const nodeHashId = midsceneGenerateHash(node, "", rect);
1024
+ const elementInfo = {
1025
+ id: nodeHashId,
1026
+ indexId: indexId++,
1027
+ nodeHashId,
1028
+ attributes: {
1029
+ ...attributes,
1030
+ ...node.nodeName?.toLowerCase() === "svg" ? {
1031
+ svgContent: "true"
1032
+ } : {},
1033
+ nodeType: "IMG Node",
1034
+ htmlTagName: tagNameOfNode(node)
1035
+ },
1036
+ nodeType: "IMG Node",
1037
+ content: "",
1038
+ rect,
1039
+ center: [
1040
+ Math.round(rect.left + rect.width / 2),
1041
+ Math.round(rect.top + rect.height / 2)
1042
+ ],
1043
+ zoom: rect.zoom,
1044
+ isVisible: rect.isVisible
1045
+ };
1046
+ return elementInfo;
200
1047
  }
201
- };
202
- this.eventCallback(inputEvent);
203
- };
204
- checkLabelClick(target) {
205
- let isLabelClick = false;
206
- let labelInfo;
207
- if (target) if ('LABEL' === target.tagName) {
208
- isLabelClick = true;
209
- labelInfo = {
210
- htmlFor: target.htmlFor,
211
- textContent: target.textContent?.trim()
1048
+ if (isTextElement(node)) {
1049
+ const text = node.textContent?.trim().replace(/\n+/g, " ");
1050
+ if (!text) return null;
1051
+ const attributes = getNodeAttributes(node, currentWindow);
1052
+ const attributeKeys = Object.keys(attributes);
1053
+ if (!text.trim() && 0 === attributeKeys.length) return null;
1054
+ const nodeHashId = midsceneGenerateHash(node, text, rect);
1055
+ const elementInfo = {
1056
+ id: nodeHashId,
1057
+ indexId: indexId++,
1058
+ nodeHashId,
1059
+ nodeType: "TEXT Node",
1060
+ attributes: {
1061
+ ...attributes,
1062
+ nodeType: "TEXT Node",
1063
+ htmlTagName: tagNameOfNode(node)
1064
+ },
1065
+ center: [
1066
+ Math.round(rect.left + rect.width / 2),
1067
+ Math.round(rect.top + rect.height / 2)
1068
+ ],
1069
+ content: text,
1070
+ rect,
1071
+ zoom: rect.zoom,
1072
+ isVisible: rect.isVisible
1073
+ };
1074
+ return elementInfo;
1075
+ }
1076
+ if (isAElement(node)) {
1077
+ const attributes = getNodeAttributes(node, currentWindow);
1078
+ const pseudo = getPseudoElementContent(node, currentWindow);
1079
+ const content = node.innerText || pseudo.before || pseudo.after || "";
1080
+ const nodeHashId = midsceneGenerateHash(node, content, rect);
1081
+ const elementInfo = {
1082
+ id: nodeHashId,
1083
+ indexId: indexId++,
1084
+ nodeHashId,
1085
+ nodeType: "Anchor Node",
1086
+ attributes: {
1087
+ ...attributes,
1088
+ htmlTagName: tagNameOfNode(node),
1089
+ nodeType: "Anchor Node"
1090
+ },
1091
+ content,
1092
+ rect,
1093
+ center: [
1094
+ Math.round(rect.left + rect.width / 2),
1095
+ Math.round(rect.top + rect.height / 2)
1096
+ ],
1097
+ zoom: rect.zoom,
1098
+ isVisible: rect.isVisible
1099
+ };
1100
+ return elementInfo;
1101
+ }
1102
+ if (isContainerElement(node)) {
1103
+ const attributes = getNodeAttributes(node, currentWindow);
1104
+ const nodeHashId = midsceneGenerateHash(node, "", rect);
1105
+ const elementInfo = {
1106
+ id: nodeHashId,
1107
+ nodeHashId,
1108
+ indexId: indexId++,
1109
+ nodeType: "CONTAINER Node",
1110
+ attributes: {
1111
+ ...attributes,
1112
+ nodeType: "CONTAINER Node",
1113
+ htmlTagName: tagNameOfNode(node)
1114
+ },
1115
+ content: "",
1116
+ rect,
1117
+ center: [
1118
+ Math.round(rect.left + rect.width / 2),
1119
+ Math.round(rect.top + rect.height / 2)
1120
+ ],
1121
+ zoom: rect.zoom,
1122
+ isVisible: rect.isVisible
1123
+ };
1124
+ return elementInfo;
1125
+ }
1126
+ return null;
1127
+ }
1128
+ function extractTextWithPosition(initNode, debugMode2 = false) {
1129
+ const elementNode = extractTreeNode(initNode, debugMode2);
1130
+ const elementInfoArray = [];
1131
+ function dfsTopChildren(node) {
1132
+ if (node.node) elementInfoArray.push(node.node);
1133
+ for(let i = 0; i < node.children.length; i++)dfsTopChildren(node.children[i]);
1134
+ }
1135
+ dfsTopChildren({
1136
+ children: elementNode.children,
1137
+ node: elementNode.node
1138
+ });
1139
+ return elementInfoArray;
1140
+ }
1141
+ function extractTreeNodeAsString(initNode, visibleOnly = false, debugMode2 = false) {
1142
+ const elementNode = extractTreeNode(initNode, debugMode2);
1143
+ return descriptionOfTree(elementNode, void 0, false, visibleOnly);
1144
+ }
1145
+ function extractTreeNode(initNode, debugMode2 = false) {
1146
+ setDebugMode(debugMode2);
1147
+ indexId = 0;
1148
+ const topDocument = getTopDocument();
1149
+ const startNode = initNode || topDocument;
1150
+ const topChildren = [];
1151
+ function dfs(node, currentWindow, currentDocument, baseZoom = 1, basePoint = {
1152
+ left: 0,
1153
+ top: 0
1154
+ }) {
1155
+ if (!node) return null;
1156
+ if (node.nodeType && 10 === node.nodeType) return null;
1157
+ const elementInfo = collectElementInfo(node, currentWindow, currentDocument, baseZoom, basePoint);
1158
+ if (node instanceof currentWindow.HTMLIFrameElement) {
1159
+ if (node.contentWindow && node.contentWindow) return null;
1160
+ }
1161
+ const nodeInfo = {
1162
+ node: elementInfo,
1163
+ children: []
1164
+ };
1165
+ if (elementInfo?.nodeType === "BUTTON Node" || elementInfo?.nodeType === "IMG Node" || elementInfo?.nodeType === "TEXT Node" || elementInfo?.nodeType === "FORM_ITEM Node" || elementInfo?.nodeType === "CONTAINER Node") return nodeInfo;
1166
+ const rect = getRect(node, baseZoom, currentWindow);
1167
+ for(let i = 0; i < node.childNodes.length; i++){
1168
+ logger("will dfs", node.childNodes[i]);
1169
+ const childNodeInfo = dfs(node.childNodes[i], currentWindow, currentDocument, rect.zoom, basePoint);
1170
+ if (Array.isArray(childNodeInfo)) nodeInfo.children.push(...childNodeInfo);
1171
+ else if (childNodeInfo) nodeInfo.children.push(childNodeInfo);
1172
+ }
1173
+ if (null === nodeInfo.node) {
1174
+ if (0 === nodeInfo.children.length) return null;
1175
+ return nodeInfo.children;
1176
+ }
1177
+ return nodeInfo;
1178
+ }
1179
+ const rootNodeInfo = dfs(startNode, window, document, 1, {
1180
+ left: 0,
1181
+ top: 0
1182
+ });
1183
+ if (Array.isArray(rootNodeInfo)) topChildren.push(...rootNodeInfo);
1184
+ else if (rootNodeInfo) topChildren.push(rootNodeInfo);
1185
+ if (startNode === topDocument) {
1186
+ const iframes = document.querySelectorAll("iframe");
1187
+ for(let i = 0; i < iframes.length; i++){
1188
+ const iframe = iframes[i];
1189
+ if (iframe.contentDocument && iframe.contentWindow) {
1190
+ const iframeInfo = collectElementInfo(iframe, window, document, 1);
1191
+ if (iframeInfo) {
1192
+ const iframeChildren = dfs(iframe.contentDocument.body, iframe.contentWindow, iframe.contentDocument, 1, {
1193
+ left: iframeInfo.rect.left,
1194
+ top: iframeInfo.rect.top
1195
+ });
1196
+ if (Array.isArray(iframeChildren)) topChildren.push(...iframeChildren);
1197
+ else if (iframeChildren) topChildren.push(iframeChildren);
1198
+ }
1199
+ }
1200
+ }
1201
+ }
1202
+ return {
1203
+ node: null,
1204
+ children: topChildren
212
1205
  };
213
- } else {
214
- let parent = target.parentElement;
215
- while(parent){
216
- if ('LABEL' === parent.tagName) {
217
- isLabelClick = true;
218
- labelInfo = {
219
- htmlFor: parent.htmlFor,
220
- textContent: parent.textContent?.trim()
221
- };
222
- break;
1206
+ }
1207
+ function mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom = 1) {
1208
+ const selfRect = elementRect(node, currentWindow, currentDocument, baseZoom);
1209
+ if (!selfRect) return null;
1210
+ let minLeft = selfRect.left;
1211
+ let minTop = selfRect.top;
1212
+ let maxRight = selfRect.left + selfRect.width;
1213
+ let maxBottom = selfRect.top + selfRect.height;
1214
+ function traverse(child) {
1215
+ for(let i = 0; i < child.childNodes.length; i++){
1216
+ const sub = child.childNodes[i];
1217
+ if (1 === sub.nodeType) {
1218
+ const rect = elementRect(sub, currentWindow, currentDocument, baseZoom);
1219
+ if (rect) {
1220
+ minLeft = Math.min(minLeft, rect.left);
1221
+ minTop = Math.min(minTop, rect.top);
1222
+ maxRight = Math.max(maxRight, rect.left + rect.width);
1223
+ maxBottom = Math.max(maxBottom, rect.top + rect.height);
1224
+ }
1225
+ traverse(sub);
1226
+ }
223
1227
  }
224
- parent = parent.parentElement;
225
1228
  }
1229
+ traverse(node);
1230
+ return {
1231
+ ...selfRect,
1232
+ left: minLeft,
1233
+ top: minTop,
1234
+ width: maxRight - minLeft,
1235
+ height: maxBottom - minTop
1236
+ };
226
1237
  }
227
- return {
228
- isLabelClick,
229
- labelInfo
1238
+ var getElementIndex = (element)=>{
1239
+ let index = 1;
1240
+ let prev = element.previousElementSibling;
1241
+ while(prev){
1242
+ if (prev.nodeName.toLowerCase() === element.nodeName.toLowerCase()) index++;
1243
+ prev = prev.previousElementSibling;
1244
+ }
1245
+ return index;
230
1246
  };
231
- }
232
- isActive() {
233
- return this.isRecording;
234
- }
235
- optimizeEvent(event, events) {
236
- const lastEvent = events[events.length - 1];
237
- if ('click' === event.type) {
238
- const lastEvent = getLastLabelClick(events);
239
- if (lastEvent && 'click' === lastEvent.type && lastEvent.isLabelClick && lastEvent.labelInfo?.htmlFor === event.element.id) {
240
- debugLog('Skip input event triggered by label click:', event.element);
241
- return events;
1247
+ var getTextNodeIndex = (textNode)=>{
1248
+ let index = 1;
1249
+ let current = textNode.previousSibling;
1250
+ while(current){
1251
+ if (current.nodeType === Node.TEXT_NODE) index++;
1252
+ current = current.previousSibling;
242
1253
  }
1254
+ return index;
1255
+ };
1256
+ var createNormalizeSpaceCondition = (textContent)=>`[normalize-space()="${textContent}"]`;
1257
+ var addTextContentToXPath = (el, baseXPath)=>{
1258
+ const textContent = el.textContent?.trim();
1259
+ if (textContent && (isButtonElement(el) || isFormElement(el))) return `${baseXPath}${createNormalizeSpaceCondition(textContent)}`;
1260
+ return baseXPath;
1261
+ };
1262
+ var getElementXPath = (element)=>{
1263
+ if (element.nodeType === Node.TEXT_NODE) {
1264
+ const parentNode = element.parentNode;
1265
+ if (parentNode && parentNode.nodeType === Node.ELEMENT_NODE) {
1266
+ const parentXPath2 = getElementXPath(parentNode);
1267
+ const textIndex = getTextNodeIndex(element);
1268
+ const textContent = element.textContent?.trim();
1269
+ if (textContent) return `${parentXPath2}/text()[${textIndex}]${createNormalizeSpaceCondition(textContent)}`;
1270
+ return `${parentXPath2}/text()[${textIndex}]`;
1271
+ }
1272
+ return "";
1273
+ }
1274
+ if (element.nodeType !== Node.ELEMENT_NODE) return "";
1275
+ const el = element;
1276
+ if (el === document.documentElement) return "/html";
1277
+ if (el === document.body) return "/html/body";
1278
+ const index = getElementIndex(el);
1279
+ const tagName = el.nodeName.toLowerCase();
1280
+ if (!el.parentNode) {
1281
+ const baseXPath2 = `/${tagName}`;
1282
+ return addTextContentToXPath(el, baseXPath2);
1283
+ }
1284
+ const parentXPath = getElementXPath(el.parentNode);
1285
+ const baseXPath = `${parentXPath}/${tagName}[${index}]`;
1286
+ return addTextContentToXPath(el, baseXPath);
1287
+ };
1288
+ function generateXPaths(node) {
1289
+ if (!node) return [];
1290
+ const fullXPath = getElementXPath(node);
243
1291
  return [
244
- ...events,
245
- event
1292
+ fullXPath
246
1293
  ];
247
1294
  }
248
- if ('input' === event.type) {
249
- if (lastEvent && 'click' === lastEvent.type && lastEvent.isLabelClick && lastEvent.labelInfo?.htmlFor === event.targetId) {
250
- debugLog('Skipping input event - triggered by label click:', {
251
- labelHtmlFor: getLastLabelClick(events)?.labelInfo?.htmlFor,
252
- inputId: event.targetId,
253
- element: event.element
1295
+ function getXpathsById(id) {
1296
+ const node = getNodeFromCacheList(id);
1297
+ if (!node) return null;
1298
+ return generateXPaths(node);
1299
+ }
1300
+ function getNodeInfoByXpath(xpath) {
1301
+ const xpathResult = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1302
+ if (1 !== xpathResult.snapshotLength) return null;
1303
+ const node = xpathResult.snapshotItem(0);
1304
+ return node;
1305
+ }
1306
+ function getElementInfoByXpath(xpath) {
1307
+ const node = getNodeInfoByXpath(xpath);
1308
+ if (!node) return null;
1309
+ if (node instanceof HTMLElement) {
1310
+ const rect = getRect(node, 1, window);
1311
+ const isVisible = isElementPartiallyInViewport(rect, window, document, 1);
1312
+ if (!isVisible) node.scrollIntoView({
1313
+ behavior: "instant",
1314
+ block: "center"
254
1315
  });
255
- return events;
256
1316
  }
257
- if (lastEvent && 'input' === lastEvent.type && isSameInputTarget(lastEvent, event)) {
258
- const oldInputEvent = events[events.length - 1];
259
- const newEvents = [
260
- ...events
261
- ];
262
- newEvents[events.length - 1] = {
263
- value: event.element?.value,
264
- ...event
265
- };
266
- debugLog('Merging input event:', {
267
- oldValue: oldInputEvent.value,
268
- newValue: event.value,
269
- oldTimestamp: oldInputEvent.timestamp,
270
- newTimestamp: event.timestamp,
271
- target: event.targetTagName
1317
+ return collectElementInfo(node, window, document, 1, {
1318
+ left: 0,
1319
+ top: 0
1320
+ });
1321
+ }
1322
+ },
1323
+ "?d94c": function() {},
1324
+ "?7342": function() {}
1325
+ };
1326
+ var __webpack_module_cache__ = {};
1327
+ function __webpack_require__(moduleId) {
1328
+ var cachedModule = __webpack_module_cache__[moduleId];
1329
+ if (void 0 !== cachedModule) return cachedModule.exports;
1330
+ var module = __webpack_module_cache__[moduleId] = {
1331
+ exports: {}
1332
+ };
1333
+ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
1334
+ return module.exports;
1335
+ }
1336
+ (()=>{
1337
+ __webpack_require__.g = (()=>{
1338
+ if ('object' == typeof globalThis) return globalThis;
1339
+ try {
1340
+ return this || new Function('return this')();
1341
+ } catch (e) {
1342
+ if ('object' == typeof window) return window;
1343
+ }
1344
+ })();
1345
+ })();
1346
+ (()=>{
1347
+ "use strict";
1348
+ var extractor = __webpack_require__("../shared/dist/lib/extractor.js");
1349
+ const DEBUG = 'true' === localStorage.getItem('DEBUG');
1350
+ function debugLog(...args) {
1351
+ if (DEBUG) console.log('[EventRecorder]', ...args);
1352
+ }
1353
+ function generateHashId(type, elementRect) {
1354
+ const rectStr = elementRect ? `${elementRect.left}_${elementRect.top}_${elementRect.width}_${elementRect.height}${void 0 !== elementRect.x ? `_${elementRect.x}` : ''}${void 0 !== elementRect.y ? `_${elementRect.y}` : ''}` : 'no_rect';
1355
+ const combined = `${type}_${rectStr}`;
1356
+ let hash = 0;
1357
+ for(let i = 0; i < combined.length; i++){
1358
+ const char = combined.charCodeAt(i);
1359
+ hash = (hash << 5) - hash + char;
1360
+ hash &= hash;
1361
+ }
1362
+ return Math.abs(hash).toString(36);
1363
+ }
1364
+ const isSameInputTarget = (event1, event2)=>event1.element === event2.element;
1365
+ const isSameScrollTarget = (event1, event2)=>event1.element === event2.element;
1366
+ const getLastLabelClick = (events)=>{
1367
+ for(let i = events.length - 1; i >= 0; i--){
1368
+ const event = events[i];
1369
+ if ('click' === event.type && event.isLabelClick) return event;
1370
+ }
1371
+ };
1372
+ function getAllScrollableElements() {
1373
+ const elements = [];
1374
+ const all = document.querySelectorAll('body *');
1375
+ all.forEach((el)=>{
1376
+ const style = window.getComputedStyle(el);
1377
+ const overflowY = style.overflowY;
1378
+ const overflowX = style.overflowX;
1379
+ const isScrollableY = ('auto' === overflowY || 'scroll' === overflowY) && el.scrollHeight > el.clientHeight;
1380
+ const isScrollableX = ('auto' === overflowX || 'scroll' === overflowX) && el.scrollWidth > el.clientWidth;
1381
+ if (isScrollableY || isScrollableX) elements.push(el);
1382
+ });
1383
+ return elements;
1384
+ }
1385
+ class EventRecorder {
1386
+ isRecording = false;
1387
+ eventCallback;
1388
+ scrollThrottleTimer = null;
1389
+ scrollThrottleDelay = 200;
1390
+ inputThrottleTimer = null;
1391
+ inputThrottleDelay = 300;
1392
+ lastViewportScroll = null;
1393
+ scrollTargets = [];
1394
+ sessionId;
1395
+ constructor(eventCallback, sessionId){
1396
+ this.eventCallback = eventCallback;
1397
+ this.sessionId = sessionId;
1398
+ }
1399
+ createNavigationEvent(url, title) {
1400
+ return {
1401
+ type: 'navigation',
1402
+ url,
1403
+ title,
1404
+ pageInfo: {
1405
+ width: window.innerWidth,
1406
+ height: window.innerHeight
1407
+ },
1408
+ timestamp: Date.now(),
1409
+ hashId: `navigation_${Date.now()}`
1410
+ };
1411
+ }
1412
+ start() {
1413
+ if (this.isRecording) return void debugLog('Recording already active, ignoring start request');
1414
+ this.isRecording = true;
1415
+ debugLog('Starting event recording');
1416
+ this.scrollTargets = [];
1417
+ if (0 === this.scrollTargets.length) {
1418
+ this.scrollTargets = getAllScrollableElements();
1419
+ this.scrollTargets.push(document.body);
1420
+ }
1421
+ debugLog('Added event listeners for', this.scrollTargets.length, 'scroll targets');
1422
+ setTimeout(()=>{
1423
+ const navigationEvent = this.createNavigationEvent(window.location.href, document.title);
1424
+ this.eventCallback(navigationEvent);
1425
+ debugLog('Added final navigation event', navigationEvent);
1426
+ }, 0);
1427
+ document.addEventListener('click', this.handleClick, true);
1428
+ document.addEventListener('input', this.handleInput);
1429
+ document.addEventListener('scroll', this.handleScroll, {
1430
+ passive: true
1431
+ });
1432
+ this.scrollTargets.forEach((target)=>{
1433
+ target.addEventListener('scroll', this.handleScroll, {
1434
+ passive: true
272
1435
  });
273
- return newEvents;
1436
+ });
1437
+ }
1438
+ stop() {
1439
+ if (!this.isRecording) return void debugLog('Recording not active, ignoring stop request');
1440
+ this.isRecording = false;
1441
+ debugLog('Stopping event recording');
1442
+ if (this.scrollThrottleTimer) {
1443
+ clearTimeout(this.scrollThrottleTimer);
1444
+ this.scrollThrottleTimer = null;
1445
+ }
1446
+ if (this.inputThrottleTimer) {
1447
+ clearTimeout(this.inputThrottleTimer);
1448
+ this.inputThrottleTimer = null;
274
1449
  }
1450
+ document.removeEventListener('click', this.handleClick);
1451
+ document.removeEventListener('input', this.handleInput);
1452
+ this.scrollTargets.forEach((target)=>{
1453
+ target.removeEventListener('scroll', this.handleScroll);
1454
+ });
1455
+ debugLog('Removed all event listeners');
275
1456
  }
276
- if ('scroll' === event.type) {
277
- if (lastEvent && 'scroll' === lastEvent.type && isSameScrollTarget(lastEvent, event)) {
278
- const oldScrollEvent = events[events.length - 1];
279
- const newEvents = [
280
- ...events
1457
+ handleClick = (event)=>{
1458
+ if (!this.isRecording) return;
1459
+ const target = event.target;
1460
+ const { isLabelClick, labelInfo } = this.checkLabelClick(target);
1461
+ const rect = target.getBoundingClientRect();
1462
+ const elementRect = {
1463
+ x: Number(event.clientX.toFixed(2)),
1464
+ y: Number(event.clientY.toFixed(2))
1465
+ };
1466
+ console.log('isNotContainerElement', (0, extractor.isNotContainerElement)(target));
1467
+ if ((0, extractor.isNotContainerElement)(target)) {
1468
+ elementRect.left = Number(rect.left.toFixed(2));
1469
+ elementRect.top = Number(rect.top.toFixed(2));
1470
+ elementRect.width = Number(rect.width.toFixed(2));
1471
+ elementRect.height = Number(rect.height.toFixed(2));
1472
+ }
1473
+ const clickEvent = {
1474
+ type: 'click',
1475
+ elementRect,
1476
+ pageInfo: {
1477
+ width: window.innerWidth,
1478
+ height: window.innerHeight
1479
+ },
1480
+ value: '',
1481
+ timestamp: Date.now(),
1482
+ hashId: generateHashId('click', {
1483
+ ...elementRect
1484
+ }),
1485
+ element: target,
1486
+ isLabelClick,
1487
+ labelInfo,
1488
+ isTrusted: event.isTrusted,
1489
+ detail: event.detail
1490
+ };
1491
+ this.eventCallback(clickEvent);
1492
+ };
1493
+ handleScroll = (event)=>{
1494
+ if (!this.isRecording) return;
1495
+ function isDocument(target) {
1496
+ return target instanceof Document;
1497
+ }
1498
+ const target = event.target;
1499
+ const scrollXTarget = isDocument(target) ? window.scrollX : target.scrollLeft;
1500
+ const scrollYTarget = isDocument(target) ? window.scrollY : target.scrollTop;
1501
+ const rect = isDocument(target) ? {
1502
+ left: 0,
1503
+ top: 0,
1504
+ width: window.innerWidth,
1505
+ height: window.innerHeight
1506
+ } : target.getBoundingClientRect();
1507
+ if (this.scrollThrottleTimer) clearTimeout(this.scrollThrottleTimer);
1508
+ this.scrollThrottleTimer = window.setTimeout(()=>{
1509
+ if (this.isRecording) {
1510
+ const elementRect = {
1511
+ left: isDocument(target) ? 0 : Number(rect.left.toFixed(2)),
1512
+ top: isDocument(target) ? 0 : Number(rect.top.toFixed(2)),
1513
+ width: isDocument(target) ? window.innerWidth : Number(rect.width.toFixed(2)),
1514
+ height: isDocument(target) ? window.innerHeight : Number(rect.height.toFixed(2))
1515
+ };
1516
+ const scrollEvent = {
1517
+ type: 'scroll',
1518
+ elementRect,
1519
+ pageInfo: {
1520
+ width: window.innerWidth,
1521
+ height: window.innerHeight
1522
+ },
1523
+ value: `${scrollXTarget.toFixed(2)},${scrollYTarget.toFixed(2)}`,
1524
+ timestamp: Date.now(),
1525
+ hashId: generateHashId('scroll', {
1526
+ ...elementRect
1527
+ }),
1528
+ element: target
1529
+ };
1530
+ this.eventCallback(scrollEvent);
1531
+ }
1532
+ this.scrollThrottleTimer = null;
1533
+ }, this.scrollThrottleDelay);
1534
+ };
1535
+ handleInput = (event)=>{
1536
+ if (!this.isRecording) return;
1537
+ const target = event.target;
1538
+ if ('checkbox' === target.type) return;
1539
+ const rect = target.getBoundingClientRect();
1540
+ const elementRect = {
1541
+ left: Number(rect.left.toFixed(2)),
1542
+ top: Number(rect.top.toFixed(2)),
1543
+ width: Number(rect.width.toFixed(2)),
1544
+ height: Number(rect.height.toFixed(2))
1545
+ };
1546
+ if (this.inputThrottleTimer) clearTimeout(this.inputThrottleTimer);
1547
+ this.inputThrottleTimer = window.setTimeout(()=>{
1548
+ if (this.isRecording) {
1549
+ const inputEvent = {
1550
+ type: 'input',
1551
+ value: 'password' !== target.type ? target.value : '*****',
1552
+ timestamp: Date.now(),
1553
+ hashId: generateHashId('input', {
1554
+ ...elementRect
1555
+ }),
1556
+ element: target,
1557
+ inputType: target.type || 'text',
1558
+ elementRect,
1559
+ pageInfo: {
1560
+ width: window.innerWidth,
1561
+ height: window.innerHeight
1562
+ }
1563
+ };
1564
+ debugLog('Throttled input event:', {
1565
+ value: inputEvent.value,
1566
+ timestamp: inputEvent.timestamp,
1567
+ target: target.tagName,
1568
+ inputType: target.type
1569
+ });
1570
+ this.eventCallback(inputEvent);
1571
+ }
1572
+ this.inputThrottleTimer = null;
1573
+ }, this.inputThrottleDelay);
1574
+ };
1575
+ checkLabelClick(target) {
1576
+ let isLabelClick = false;
1577
+ let labelInfo;
1578
+ if (target) if ('LABEL' === target.tagName) {
1579
+ isLabelClick = true;
1580
+ labelInfo = {
1581
+ htmlFor: target.htmlFor,
1582
+ textContent: target.textContent?.trim()
1583
+ };
1584
+ } else {
1585
+ let parent = target.parentElement;
1586
+ while(parent){
1587
+ if ('LABEL' === parent.tagName) {
1588
+ isLabelClick = true;
1589
+ labelInfo = {
1590
+ htmlFor: parent.htmlFor,
1591
+ textContent: parent.textContent?.trim()
1592
+ };
1593
+ break;
1594
+ }
1595
+ parent = parent.parentElement;
1596
+ }
1597
+ }
1598
+ return {
1599
+ isLabelClick,
1600
+ labelInfo
1601
+ };
1602
+ }
1603
+ isActive() {
1604
+ return this.isRecording;
1605
+ }
1606
+ optimizeEvent(event, events) {
1607
+ const lastEvent = events[events.length - 1];
1608
+ if ('click' === event.type) {
1609
+ const lastEvent = getLastLabelClick(events);
1610
+ if (lastEvent && 'click' === lastEvent.type && lastEvent.isLabelClick && lastEvent.labelInfo?.htmlFor === event.element.id) {
1611
+ debugLog('Skip input event triggered by label click:', event.element);
1612
+ return events;
1613
+ }
1614
+ return [
1615
+ ...events,
1616
+ event
281
1617
  ];
282
- newEvents[events.length - 1] = event;
283
- debugLog('Replacing last scroll event with new scroll event:', {
284
- oldPosition: `${oldScrollEvent.elementRect?.left},${oldScrollEvent.elementRect?.top}`,
285
- newPosition: `${event.elementRect?.left},${event.elementRect?.top}`,
286
- oldTimestamp: oldScrollEvent.timestamp,
287
- newTimestamp: event.timestamp,
288
- target: event.targetTagName
289
- });
290
- return newEvents;
291
1618
  }
1619
+ if ('input' === event.type) {
1620
+ if (lastEvent && 'click' === lastEvent.type && lastEvent.isLabelClick && lastEvent.labelInfo?.htmlFor === event.targetId) {
1621
+ debugLog('Skipping input event - triggered by label click:', {
1622
+ labelHtmlFor: getLastLabelClick(events)?.labelInfo?.htmlFor,
1623
+ inputId: event.targetId,
1624
+ element: event.element
1625
+ });
1626
+ return events;
1627
+ }
1628
+ if (lastEvent && 'input' === lastEvent.type && isSameInputTarget(lastEvent, event)) {
1629
+ const oldInputEvent = events[events.length - 1];
1630
+ const newEvents = [
1631
+ ...events
1632
+ ];
1633
+ newEvents[events.length - 1] = {
1634
+ value: event.element?.value,
1635
+ ...event
1636
+ };
1637
+ debugLog('Merging input event:', {
1638
+ oldValue: oldInputEvent.value,
1639
+ newValue: event.value,
1640
+ oldTimestamp: oldInputEvent.timestamp,
1641
+ newTimestamp: event.timestamp,
1642
+ target: event.targetTagName
1643
+ });
1644
+ return newEvents;
1645
+ }
1646
+ }
1647
+ if ('scroll' === event.type) {
1648
+ if (lastEvent && 'scroll' === lastEvent.type && isSameScrollTarget(lastEvent, event)) {
1649
+ const oldScrollEvent = events[events.length - 1];
1650
+ const newEvents = [
1651
+ ...events
1652
+ ];
1653
+ newEvents[events.length - 1] = event;
1654
+ debugLog('Replacing last scroll event with new scroll event:', {
1655
+ oldPosition: `${oldScrollEvent.elementRect?.left},${oldScrollEvent.elementRect?.top}`,
1656
+ newPosition: `${event.elementRect?.left},${event.elementRect?.top}`,
1657
+ oldTimestamp: oldScrollEvent.timestamp,
1658
+ newTimestamp: event.timestamp,
1659
+ target: event.targetTagName
1660
+ });
1661
+ return newEvents;
1662
+ }
1663
+ }
1664
+ return [
1665
+ ...events,
1666
+ event
1667
+ ];
292
1668
  }
293
- return [
294
- ...events,
295
- event
296
- ];
297
1669
  }
298
- }
299
- window.EventRecorder = EventRecorder;
1670
+ window.EventRecorder = EventRecorder;
1671
+ })();
300
1672
  })();