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