@appsurify-testmap/rrweb-record 2.1.0-alpha.7 → 2.1.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/rrweb-record.cjs +574 -149
- package/dist/rrweb-record.cjs.map +1 -1
- package/dist/rrweb-record.js +574 -149
- package/dist/rrweb-record.js.map +1 -1
- package/dist/rrweb-record.umd.cjs +577 -151
- package/dist/rrweb-record.umd.cjs.map +3 -3
- package/dist/rrweb-record.umd.min.cjs +26 -26
- package/dist/rrweb-record.umd.min.cjs.map +3 -3
- package/package.json +4 -4
package/dist/rrweb-record.js
CHANGED
|
@@ -168,6 +168,41 @@ function patch$1(source, name, replacement) {
|
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
+
function describeNode$1(el) {
|
|
172
|
+
const tag = el.tagName.toLowerCase();
|
|
173
|
+
const id = el.id ? `#${el.id}` : "";
|
|
174
|
+
const classes = el.classList.length ? "." + Array.from(el.classList).join(".") : "";
|
|
175
|
+
return `${tag}${id}${classes}`;
|
|
176
|
+
}
|
|
177
|
+
function getElementVisibility$1(el) {
|
|
178
|
+
var _a2, _b;
|
|
179
|
+
const win = ((_a2 = el.ownerDocument) == null ? void 0 : _a2.defaultView) ?? window;
|
|
180
|
+
const rect = el.getBoundingClientRect();
|
|
181
|
+
const viewportWidth = win.innerWidth || win.document.documentElement.clientWidth || 0;
|
|
182
|
+
const viewportHeight = win.innerHeight || win.document.documentElement.clientHeight || 0;
|
|
183
|
+
const isRectVisible = rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth;
|
|
184
|
+
const style = (_b = win.getComputedStyle) == null ? void 0 : _b.call(win, el);
|
|
185
|
+
const isStyleVisible2 = !!style && style.display !== "none" && style.visibility !== "hidden" && (parseFloat(style.opacity) || 0) > 0;
|
|
186
|
+
const isVisible = isStyleVisible2 && isRectVisible;
|
|
187
|
+
let ratio = 0;
|
|
188
|
+
if (isVisible) {
|
|
189
|
+
const xOverlap = Math.max(
|
|
190
|
+
0,
|
|
191
|
+
Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0)
|
|
192
|
+
);
|
|
193
|
+
const yOverlap = Math.max(
|
|
194
|
+
0,
|
|
195
|
+
Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0)
|
|
196
|
+
);
|
|
197
|
+
const intersectionArea = xOverlap * yOverlap;
|
|
198
|
+
const elementArea = rect.width * rect.height;
|
|
199
|
+
ratio = elementArea > 0 ? intersectionArea / elementArea : 0;
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
isVisible,
|
|
203
|
+
ratio
|
|
204
|
+
};
|
|
205
|
+
}
|
|
171
206
|
const index$1 = {
|
|
172
207
|
childNodes: childNodes$1,
|
|
173
208
|
parentNode: parentNode$1,
|
|
@@ -181,7 +216,9 @@ const index$1 = {
|
|
|
181
216
|
querySelector: querySelector$1,
|
|
182
217
|
querySelectorAll: querySelectorAll$1,
|
|
183
218
|
mutationObserver: mutationObserverCtor$1,
|
|
184
|
-
patch: patch$1
|
|
219
|
+
patch: patch$1,
|
|
220
|
+
describeNode: describeNode$1,
|
|
221
|
+
getElementVisibility: getElementVisibility$1
|
|
185
222
|
};
|
|
186
223
|
function isElement(n2) {
|
|
187
224
|
return n2.nodeType === n2.ELEMENT_NODE;
|
|
@@ -555,71 +592,95 @@ function splitCssText(cssText, style, _testNoPxNorm = false) {
|
|
|
555
592
|
function markCssSplits(cssText, style) {
|
|
556
593
|
return splitCssText(cssText, style).join("/* rr_split */");
|
|
557
594
|
}
|
|
558
|
-
function
|
|
559
|
-
|
|
560
|
-
|
|
595
|
+
function isSelectorUnique(selector, target) {
|
|
596
|
+
try {
|
|
597
|
+
const matches = document.querySelectorAll(selector);
|
|
598
|
+
return matches.length === 1 && matches[0] === target;
|
|
599
|
+
} catch {
|
|
600
|
+
return false;
|
|
561
601
|
}
|
|
562
|
-
|
|
563
|
-
|
|
602
|
+
}
|
|
603
|
+
function buildSelector(node2) {
|
|
604
|
+
if (!(node2 instanceof Element)) return null;
|
|
605
|
+
if (node2.id) {
|
|
606
|
+
return `#${CSS.escape(node2.id)}`;
|
|
564
607
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
570
|
-
if (element.tagName && element.tagName.toLowerCase() === "html") {
|
|
571
|
-
return "/html";
|
|
572
|
-
}
|
|
573
|
-
if (element === document.head) {
|
|
574
|
-
return "/html/head";
|
|
575
|
-
}
|
|
576
|
-
if (element === document.body) {
|
|
577
|
-
return "/html/body";
|
|
578
|
-
}
|
|
579
|
-
const parentNode2 = element.parentNode;
|
|
580
|
-
if (!parentNode2) {
|
|
581
|
-
return "";
|
|
582
|
-
}
|
|
583
|
-
const siblings = Array.from(parentNode2.children).filter(
|
|
584
|
-
(sibling) => sibling.tagName === element.tagName
|
|
585
|
-
);
|
|
586
|
-
const index2 = siblings.length > 1 ? `[${siblings.indexOf(element) + 1}]` : "";
|
|
587
|
-
return `${getXPath(parentNode2)}/${element.tagName.toLowerCase()}${index2}`;
|
|
608
|
+
const parts = [];
|
|
609
|
+
const tag = node2.tagName.toLowerCase();
|
|
610
|
+
if (node2.classList.length) {
|
|
611
|
+
parts.push(...Array.from(node2.classList).map((cls) => `.${CSS.escape(cls)}`));
|
|
588
612
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
return "";
|
|
613
|
+
Array.from(node2.attributes).forEach((attr) => {
|
|
614
|
+
if (attr.name.startsWith("data-")) {
|
|
615
|
+
parts.push(`[${attr.name}="${CSS.escape(attr.value)}"]`);
|
|
593
616
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
617
|
+
});
|
|
618
|
+
const shortSelector = `${tag}${parts.join("")}`;
|
|
619
|
+
if (isSelectorUnique(shortSelector, node2)) {
|
|
620
|
+
return shortSelector;
|
|
621
|
+
}
|
|
622
|
+
const pathParts = [];
|
|
623
|
+
let current = node2;
|
|
624
|
+
while (current && current.nodeType === Node.ELEMENT_NODE) {
|
|
625
|
+
const parent = current.parentElement;
|
|
626
|
+
const tagName = current.tagName.toLowerCase();
|
|
627
|
+
let nth = "";
|
|
628
|
+
if (parent) {
|
|
629
|
+
const siblings = Array.from(parent.children).filter(
|
|
630
|
+
(el) => el.tagName.toLowerCase() === tagName
|
|
631
|
+
);
|
|
632
|
+
if (siblings.length > 1) {
|
|
633
|
+
nth = `:nth-of-type(${siblings.indexOf(current) + 1})`;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
pathParts.unshift(`${tagName}${nth}`);
|
|
637
|
+
current = parent;
|
|
638
|
+
}
|
|
639
|
+
return pathParts.join(" > ") || null;
|
|
640
|
+
}
|
|
641
|
+
function buildXPath(node2) {
|
|
642
|
+
switch (node2.nodeType) {
|
|
643
|
+
case Node.DOCUMENT_NODE:
|
|
644
|
+
return "/";
|
|
645
|
+
case Node.DOCUMENT_TYPE_NODE:
|
|
646
|
+
return "/html/doctype";
|
|
647
|
+
case Node.ELEMENT_NODE: {
|
|
648
|
+
const element = node2;
|
|
649
|
+
if (element.id) {
|
|
650
|
+
return `//*[@id="${CSS.escape(element.id)}"]`;
|
|
651
|
+
}
|
|
652
|
+
if (element.tagName.toLowerCase() === "html") return "/html";
|
|
653
|
+
if (element === document.head) return "/html/head";
|
|
654
|
+
if (element === document.body) return "/html/body";
|
|
655
|
+
const parent = element.parentNode;
|
|
656
|
+
if (!parent) return "";
|
|
657
|
+
const tag = element.tagName.toLowerCase();
|
|
658
|
+
const siblings = Array.from(parent.children).filter(
|
|
659
|
+
(el) => el.tagName.toLowerCase() === tag
|
|
660
|
+
);
|
|
661
|
+
const index2 = siblings.length > 1 ? `[${siblings.indexOf(element) + 1}]` : "";
|
|
662
|
+
return `${buildXPath(parent)}/${tag}${index2}`;
|
|
663
|
+
}
|
|
664
|
+
case Node.TEXT_NODE:
|
|
665
|
+
case Node.CDATA_SECTION_NODE:
|
|
666
|
+
case Node.COMMENT_NODE: {
|
|
667
|
+
const parent = node2.parentNode;
|
|
668
|
+
if (!parent) return "";
|
|
669
|
+
const typeMap = {
|
|
670
|
+
[Node.TEXT_NODE]: "text()",
|
|
671
|
+
[Node.CDATA_SECTION_NODE]: "text()",
|
|
672
|
+
// CDATA ≡ text() в XPath
|
|
673
|
+
[Node.COMMENT_NODE]: "comment()"
|
|
674
|
+
};
|
|
675
|
+
const sameTypeSiblings = Array.from(parent.childNodes).filter(
|
|
676
|
+
(sibling) => sibling.nodeType === node2.nodeType
|
|
677
|
+
);
|
|
678
|
+
const index2 = sameTypeSiblings.length > 1 ? `[${sameTypeSiblings.indexOf(node2)}]` : "";
|
|
679
|
+
return `${buildXPath(parent)}/${typeMap[node2.nodeType]}${index2}`;
|
|
604
680
|
}
|
|
605
|
-
|
|
606
|
-
(sibling) => sibling.nodeType === Node.CDATA_SECTION_NODE
|
|
607
|
-
);
|
|
608
|
-
const index2 = cdataSiblings.length > 1 ? `[${cdataSiblings.indexOf(node2) + 1}]` : "";
|
|
609
|
-
return `${getXPath(parent)}/text()${index2}`;
|
|
610
|
-
}
|
|
611
|
-
if (node2.nodeType === Node.COMMENT_NODE) {
|
|
612
|
-
const parent = node2.parentNode;
|
|
613
|
-
if (!parent) {
|
|
681
|
+
default:
|
|
614
682
|
return "";
|
|
615
|
-
}
|
|
616
|
-
const commentSiblings = Array.from(parent.childNodes).filter(
|
|
617
|
-
(sibling) => sibling.nodeType === Node.COMMENT_NODE
|
|
618
|
-
);
|
|
619
|
-
const index2 = commentSiblings.length > 1 ? `[${commentSiblings.indexOf(node2) + 1}]` : "";
|
|
620
|
-
return `${getXPath(parent)}/comment()${index2}`;
|
|
621
683
|
}
|
|
622
|
-
return "";
|
|
623
684
|
}
|
|
624
685
|
function isTextVisible(n2) {
|
|
625
686
|
var _a2;
|
|
@@ -635,20 +696,9 @@ function isTextVisible(n2) {
|
|
|
635
696
|
const textContent2 = (_a2 = n2.textContent) == null ? void 0 : _a2.trim();
|
|
636
697
|
return textContent2 !== "";
|
|
637
698
|
}
|
|
638
|
-
function isElementVisible(
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
const style = win ? win.getComputedStyle(n2) : null;
|
|
642
|
-
const isStyleVisible = style != null && style.display !== "none" && style.visibility !== "hidden" && parseFloat(style.opacity) !== 0;
|
|
643
|
-
const rect = n2.getBoundingClientRect();
|
|
644
|
-
const result2 = isStyleVisible && isRectVisible(rect);
|
|
645
|
-
return result2;
|
|
646
|
-
}
|
|
647
|
-
function isRectVisible(rect, win = window) {
|
|
648
|
-
var _a2, _b, _c, _d;
|
|
649
|
-
const height = (win == null ? void 0 : win.innerHeight) ?? ((_b = (_a2 = win == null ? void 0 : win.document) == null ? void 0 : _a2.documentElement) == null ? void 0 : _b.clientHeight) ?? 0;
|
|
650
|
-
const width = (win == null ? void 0 : win.innerWidth) ?? ((_d = (_c = win == null ? void 0 : win.document) == null ? void 0 : _c.documentElement) == null ? void 0 : _d.clientWidth) ?? 0;
|
|
651
|
-
return rect.width > 0 && rect.height > 0 && rect.top >= 0 && rect.left >= 0 && rect.bottom <= height && rect.right <= width;
|
|
699
|
+
function isElementVisible(el) {
|
|
700
|
+
const visibility = index$1.getElementVisibility(el);
|
|
701
|
+
return visibility.isVisible;
|
|
652
702
|
}
|
|
653
703
|
const interactiveEvents$1 = [
|
|
654
704
|
"change",
|
|
@@ -881,9 +931,6 @@ function transformAttribute(doc, tagName, name, value) {
|
|
|
881
931
|
function ignoreAttribute(tagName, name, _value) {
|
|
882
932
|
return (tagName === "video" || tagName === "audio") && name === "autoplay";
|
|
883
933
|
}
|
|
884
|
-
function isIncludeAttribute(name, include) {
|
|
885
|
-
return typeof include === "string" ? name.includes(include) : include.test(name);
|
|
886
|
-
}
|
|
887
934
|
function isExcludeAttribute(name, exclude) {
|
|
888
935
|
return typeof exclude === "string" ? name.includes(exclude) : exclude.test(name);
|
|
889
936
|
}
|
|
@@ -1017,7 +1064,6 @@ function serializeNode(n2, options) {
|
|
|
1017
1064
|
blockClass,
|
|
1018
1065
|
blockSelector,
|
|
1019
1066
|
excludeAttribute,
|
|
1020
|
-
includeAttribute,
|
|
1021
1067
|
needsMask,
|
|
1022
1068
|
inlineStylesheet,
|
|
1023
1069
|
maskInputOptions = {},
|
|
@@ -1031,22 +1077,19 @@ function serializeNode(n2, options) {
|
|
|
1031
1077
|
cssCaptured = false
|
|
1032
1078
|
} = options;
|
|
1033
1079
|
const rootId = getRootId(doc, mirror2);
|
|
1034
|
-
const xPath = getXPath(n2);
|
|
1035
1080
|
switch (n2.nodeType) {
|
|
1036
1081
|
case n2.DOCUMENT_NODE:
|
|
1037
1082
|
if (n2.compatMode !== "CSS1Compat") {
|
|
1038
1083
|
return {
|
|
1039
1084
|
type: NodeType$3.Document,
|
|
1040
1085
|
childNodes: [],
|
|
1041
|
-
xPath,
|
|
1042
1086
|
compatMode: n2.compatMode
|
|
1043
1087
|
// probably "BackCompat"
|
|
1044
1088
|
};
|
|
1045
1089
|
} else {
|
|
1046
1090
|
return {
|
|
1047
1091
|
type: NodeType$3.Document,
|
|
1048
|
-
childNodes: []
|
|
1049
|
-
xPath
|
|
1092
|
+
childNodes: []
|
|
1050
1093
|
};
|
|
1051
1094
|
}
|
|
1052
1095
|
case n2.DOCUMENT_TYPE_NODE:
|
|
@@ -1055,8 +1098,7 @@ function serializeNode(n2, options) {
|
|
|
1055
1098
|
name: n2.name,
|
|
1056
1099
|
publicId: n2.publicId,
|
|
1057
1100
|
systemId: n2.systemId,
|
|
1058
|
-
rootId
|
|
1059
|
-
xPath
|
|
1101
|
+
rootId
|
|
1060
1102
|
};
|
|
1061
1103
|
case n2.ELEMENT_NODE:
|
|
1062
1104
|
return serializeElementNode(n2, {
|
|
@@ -1064,7 +1106,6 @@ function serializeNode(n2, options) {
|
|
|
1064
1106
|
blockClass,
|
|
1065
1107
|
blockSelector,
|
|
1066
1108
|
excludeAttribute,
|
|
1067
|
-
includeAttribute,
|
|
1068
1109
|
inlineStylesheet,
|
|
1069
1110
|
maskInputOptions,
|
|
1070
1111
|
maskInputFn,
|
|
@@ -1073,8 +1114,7 @@ function serializeNode(n2, options) {
|
|
|
1073
1114
|
recordCanvas,
|
|
1074
1115
|
keepIframeSrcFn,
|
|
1075
1116
|
newlyAddedElement,
|
|
1076
|
-
rootId
|
|
1077
|
-
xPath
|
|
1117
|
+
rootId
|
|
1078
1118
|
});
|
|
1079
1119
|
case n2.TEXT_NODE:
|
|
1080
1120
|
return serializeTextNode(n2, {
|
|
@@ -1082,22 +1122,19 @@ function serializeNode(n2, options) {
|
|
|
1082
1122
|
needsMask,
|
|
1083
1123
|
maskTextFn,
|
|
1084
1124
|
rootId,
|
|
1085
|
-
cssCaptured
|
|
1086
|
-
xPath
|
|
1125
|
+
cssCaptured
|
|
1087
1126
|
});
|
|
1088
1127
|
case n2.CDATA_SECTION_NODE:
|
|
1089
1128
|
return {
|
|
1090
1129
|
type: NodeType$3.CDATA,
|
|
1091
1130
|
textContent: "",
|
|
1092
|
-
rootId
|
|
1093
|
-
xPath
|
|
1131
|
+
rootId
|
|
1094
1132
|
};
|
|
1095
1133
|
case n2.COMMENT_NODE:
|
|
1096
1134
|
return {
|
|
1097
1135
|
type: NodeType$3.Comment,
|
|
1098
1136
|
textContent: index$1.textContent(n2) || "",
|
|
1099
|
-
rootId
|
|
1100
|
-
xPath
|
|
1137
|
+
rootId
|
|
1101
1138
|
};
|
|
1102
1139
|
default:
|
|
1103
1140
|
return false;
|
|
@@ -1109,7 +1146,7 @@ function getRootId(doc, mirror2) {
|
|
|
1109
1146
|
return docId === 1 ? void 0 : docId;
|
|
1110
1147
|
}
|
|
1111
1148
|
function serializeTextNode(n2, options) {
|
|
1112
|
-
const { needsMask, maskTextFn, rootId, cssCaptured
|
|
1149
|
+
const { needsMask, maskTextFn, rootId, cssCaptured } = options;
|
|
1113
1150
|
const parent = index$1.parentNode(n2);
|
|
1114
1151
|
const parentTagName = parent && parent.tagName;
|
|
1115
1152
|
let textContent2 = "";
|
|
@@ -1126,15 +1163,10 @@ function serializeTextNode(n2, options) {
|
|
|
1126
1163
|
if (!isStyle && !isScript && textContent2 && needsMask) {
|
|
1127
1164
|
textContent2 = maskTextFn ? maskTextFn(textContent2, index$1.parentElement(n2)) : textContent2.replace(/[\S]/g, "*");
|
|
1128
1165
|
}
|
|
1129
|
-
const isVisible = isTextVisible(n2);
|
|
1130
|
-
const isInteractive = isElementInteractive(n2);
|
|
1131
1166
|
return {
|
|
1132
1167
|
type: NodeType$3.Text,
|
|
1133
1168
|
textContent: textContent2 || "",
|
|
1134
|
-
rootId
|
|
1135
|
-
isVisible,
|
|
1136
|
-
isInteractive,
|
|
1137
|
-
xPath
|
|
1169
|
+
rootId
|
|
1138
1170
|
};
|
|
1139
1171
|
}
|
|
1140
1172
|
function serializeElementNode(n2, options) {
|
|
@@ -1143,7 +1175,6 @@ function serializeElementNode(n2, options) {
|
|
|
1143
1175
|
blockClass,
|
|
1144
1176
|
blockSelector,
|
|
1145
1177
|
excludeAttribute,
|
|
1146
|
-
includeAttribute,
|
|
1147
1178
|
inlineStylesheet,
|
|
1148
1179
|
maskInputOptions = {},
|
|
1149
1180
|
maskInputFn,
|
|
@@ -1152,8 +1183,7 @@ function serializeElementNode(n2, options) {
|
|
|
1152
1183
|
recordCanvas,
|
|
1153
1184
|
keepIframeSrcFn,
|
|
1154
1185
|
newlyAddedElement = false,
|
|
1155
|
-
rootId
|
|
1156
|
-
xPath
|
|
1186
|
+
rootId
|
|
1157
1187
|
} = options;
|
|
1158
1188
|
const needBlock = _isBlockedElement(n2, blockClass, blockSelector);
|
|
1159
1189
|
const tagName = getValidTagName$1(n2);
|
|
@@ -1161,7 +1191,7 @@ function serializeElementNode(n2, options) {
|
|
|
1161
1191
|
const len = n2.attributes.length;
|
|
1162
1192
|
for (let i2 = 0; i2 < len; i2++) {
|
|
1163
1193
|
const attr = n2.attributes[i2];
|
|
1164
|
-
if (isExcludeAttribute(attr.name, excludeAttribute)
|
|
1194
|
+
if (isExcludeAttribute(attr.name, excludeAttribute)) {
|
|
1165
1195
|
continue;
|
|
1166
1196
|
}
|
|
1167
1197
|
if (!ignoreAttribute(tagName, attr.name, attr.value)) {
|
|
@@ -1323,8 +1353,6 @@ function serializeElementNode(n2, options) {
|
|
|
1323
1353
|
if (customElements.get(tagName)) isCustomElement = true;
|
|
1324
1354
|
} catch (e2) {
|
|
1325
1355
|
}
|
|
1326
|
-
const isVisible = isElementVisible(n2);
|
|
1327
|
-
const isInteractive = isElementInteractive(n2);
|
|
1328
1356
|
return {
|
|
1329
1357
|
type: NodeType$3.Element,
|
|
1330
1358
|
tagName,
|
|
@@ -1333,10 +1361,7 @@ function serializeElementNode(n2, options) {
|
|
|
1333
1361
|
isSVG: isSVGElement(n2) || void 0,
|
|
1334
1362
|
needBlock,
|
|
1335
1363
|
rootId,
|
|
1336
|
-
isCustom: isCustomElement
|
|
1337
|
-
isVisible,
|
|
1338
|
-
isInteractive,
|
|
1339
|
-
xPath
|
|
1364
|
+
isCustom: isCustomElement
|
|
1340
1365
|
};
|
|
1341
1366
|
}
|
|
1342
1367
|
function lowerIfExists(maybeAttr) {
|
|
@@ -1387,7 +1412,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1387
1412
|
maskTextClass,
|
|
1388
1413
|
maskTextSelector,
|
|
1389
1414
|
excludeAttribute,
|
|
1390
|
-
includeAttribute,
|
|
1391
1415
|
skipChild = false,
|
|
1392
1416
|
inlineStylesheet = true,
|
|
1393
1417
|
maskInputOptions = {},
|
|
@@ -1423,7 +1447,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1423
1447
|
blockClass,
|
|
1424
1448
|
blockSelector,
|
|
1425
1449
|
excludeAttribute,
|
|
1426
|
-
includeAttribute,
|
|
1427
1450
|
needsMask,
|
|
1428
1451
|
inlineStylesheet,
|
|
1429
1452
|
maskInputOptions,
|
|
@@ -1449,6 +1472,22 @@ function serializeNodeWithId(n2, options) {
|
|
|
1449
1472
|
id = genId();
|
|
1450
1473
|
}
|
|
1451
1474
|
const serializedNode = Object.assign(_serializedNode, { id });
|
|
1475
|
+
if (isElement(n2) || n2.nodeType === Node.TEXT_NODE) {
|
|
1476
|
+
serializedNode.xpath = buildXPath(n2);
|
|
1477
|
+
if (isElement(n2)) {
|
|
1478
|
+
const selector = buildSelector(n2);
|
|
1479
|
+
if (selector) {
|
|
1480
|
+
serializedNode.selector = selector;
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
if (n2.nodeType === Node.TEXT_NODE) {
|
|
1484
|
+
serializedNode.isVisible = isTextVisible(n2);
|
|
1485
|
+
}
|
|
1486
|
+
if (n2.nodeType === Node.ELEMENT_NODE) {
|
|
1487
|
+
serializedNode.isVisible = isElementVisible(n2);
|
|
1488
|
+
serializedNode.isInteractive = isElementInteractive(n2);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1452
1491
|
mirror2.add(n2, serializedNode);
|
|
1453
1492
|
if (id === IGNORED_NODE) {
|
|
1454
1493
|
return null;
|
|
@@ -1477,7 +1516,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1477
1516
|
maskTextClass,
|
|
1478
1517
|
maskTextSelector,
|
|
1479
1518
|
excludeAttribute,
|
|
1480
|
-
includeAttribute,
|
|
1481
1519
|
skipChild,
|
|
1482
1520
|
inlineStylesheet,
|
|
1483
1521
|
maskInputOptions,
|
|
@@ -1538,7 +1576,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1538
1576
|
maskTextClass,
|
|
1539
1577
|
maskTextSelector,
|
|
1540
1578
|
excludeAttribute,
|
|
1541
|
-
includeAttribute,
|
|
1542
1579
|
skipChild: false,
|
|
1543
1580
|
inlineStylesheet,
|
|
1544
1581
|
maskInputOptions,
|
|
@@ -1581,7 +1618,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1581
1618
|
maskTextClass,
|
|
1582
1619
|
maskTextSelector,
|
|
1583
1620
|
excludeAttribute,
|
|
1584
|
-
includeAttribute,
|
|
1585
1621
|
skipChild: false,
|
|
1586
1622
|
inlineStylesheet,
|
|
1587
1623
|
maskInputOptions,
|
|
@@ -1619,8 +1655,7 @@ function snapshot(n2, options) {
|
|
|
1619
1655
|
blockSelector = null,
|
|
1620
1656
|
maskTextClass = "rr-mask",
|
|
1621
1657
|
maskTextSelector = null,
|
|
1622
|
-
excludeAttribute =
|
|
1623
|
-
includeAttribute = /.+/i,
|
|
1658
|
+
excludeAttribute = /.^/,
|
|
1624
1659
|
inlineStylesheet = true,
|
|
1625
1660
|
inlineImages = false,
|
|
1626
1661
|
recordCanvas = false,
|
|
@@ -1681,7 +1716,6 @@ function snapshot(n2, options) {
|
|
|
1681
1716
|
maskTextClass,
|
|
1682
1717
|
maskTextSelector,
|
|
1683
1718
|
excludeAttribute,
|
|
1684
|
-
includeAttribute,
|
|
1685
1719
|
skipChild: false,
|
|
1686
1720
|
inlineStylesheet,
|
|
1687
1721
|
maskInputOptions,
|
|
@@ -9092,6 +9126,41 @@ function patch(source, name, replacement) {
|
|
|
9092
9126
|
};
|
|
9093
9127
|
}
|
|
9094
9128
|
}
|
|
9129
|
+
function describeNode(el) {
|
|
9130
|
+
const tag = el.tagName.toLowerCase();
|
|
9131
|
+
const id = el.id ? `#${el.id}` : "";
|
|
9132
|
+
const classes = el.classList.length ? "." + Array.from(el.classList).join(".") : "";
|
|
9133
|
+
return `${tag}${id}${classes}`;
|
|
9134
|
+
}
|
|
9135
|
+
function getElementVisibility(el) {
|
|
9136
|
+
var _a2, _b;
|
|
9137
|
+
const win = ((_a2 = el.ownerDocument) == null ? void 0 : _a2.defaultView) ?? window;
|
|
9138
|
+
const rect = el.getBoundingClientRect();
|
|
9139
|
+
const viewportWidth = win.innerWidth || win.document.documentElement.clientWidth || 0;
|
|
9140
|
+
const viewportHeight = win.innerHeight || win.document.documentElement.clientHeight || 0;
|
|
9141
|
+
const isRectVisible = rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth;
|
|
9142
|
+
const style = (_b = win.getComputedStyle) == null ? void 0 : _b.call(win, el);
|
|
9143
|
+
const isStyleVisible2 = !!style && style.display !== "none" && style.visibility !== "hidden" && (parseFloat(style.opacity) || 0) > 0;
|
|
9144
|
+
const isVisible = isStyleVisible2 && isRectVisible;
|
|
9145
|
+
let ratio = 0;
|
|
9146
|
+
if (isVisible) {
|
|
9147
|
+
const xOverlap = Math.max(
|
|
9148
|
+
0,
|
|
9149
|
+
Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0)
|
|
9150
|
+
);
|
|
9151
|
+
const yOverlap = Math.max(
|
|
9152
|
+
0,
|
|
9153
|
+
Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0)
|
|
9154
|
+
);
|
|
9155
|
+
const intersectionArea = xOverlap * yOverlap;
|
|
9156
|
+
const elementArea = rect.width * rect.height;
|
|
9157
|
+
ratio = elementArea > 0 ? intersectionArea / elementArea : 0;
|
|
9158
|
+
}
|
|
9159
|
+
return {
|
|
9160
|
+
isVisible,
|
|
9161
|
+
ratio
|
|
9162
|
+
};
|
|
9163
|
+
}
|
|
9095
9164
|
const index = {
|
|
9096
9165
|
childNodes,
|
|
9097
9166
|
parentNode,
|
|
@@ -9105,7 +9174,9 @@ const index = {
|
|
|
9105
9174
|
querySelector,
|
|
9106
9175
|
querySelectorAll,
|
|
9107
9176
|
mutationObserver: mutationObserverCtor,
|
|
9108
|
-
patch
|
|
9177
|
+
patch,
|
|
9178
|
+
describeNode,
|
|
9179
|
+
getElementVisibility
|
|
9109
9180
|
};
|
|
9110
9181
|
function on(type, fn, target = document) {
|
|
9111
9182
|
const options = { capture: true, passive: true };
|
|
@@ -9379,6 +9450,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
|
|
|
9379
9450
|
IncrementalSource2[IncrementalSource2["Selection"] = 14] = "Selection";
|
|
9380
9451
|
IncrementalSource2[IncrementalSource2["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
|
|
9381
9452
|
IncrementalSource2[IncrementalSource2["CustomElement"] = 16] = "CustomElement";
|
|
9453
|
+
IncrementalSource2[IncrementalSource2["VisibilityMutation"] = 17] = "VisibilityMutation";
|
|
9382
9454
|
return IncrementalSource2;
|
|
9383
9455
|
})(IncrementalSource || {});
|
|
9384
9456
|
var MouseInteractions = /* @__PURE__ */ ((MouseInteractions2) => {
|
|
@@ -9525,7 +9597,6 @@ class MutationBuffer {
|
|
|
9525
9597
|
__publicField(this, "maskTextClass");
|
|
9526
9598
|
__publicField(this, "maskTextSelector");
|
|
9527
9599
|
__publicField(this, "excludeAttribute");
|
|
9528
|
-
__publicField(this, "includeAttribute");
|
|
9529
9600
|
__publicField(this, "inlineStylesheet");
|
|
9530
9601
|
__publicField(this, "maskInputOptions");
|
|
9531
9602
|
__publicField(this, "maskTextFn");
|
|
@@ -9541,6 +9612,7 @@ class MutationBuffer {
|
|
|
9541
9612
|
__publicField(this, "stylesheetManager");
|
|
9542
9613
|
__publicField(this, "shadowDomManager");
|
|
9543
9614
|
__publicField(this, "canvasManager");
|
|
9615
|
+
__publicField(this, "visibilityManager");
|
|
9544
9616
|
__publicField(this, "processedNodeManager");
|
|
9545
9617
|
__publicField(this, "unattachedDoc");
|
|
9546
9618
|
__publicField(this, "processMutations", (mutations) => {
|
|
@@ -9590,7 +9662,6 @@ class MutationBuffer {
|
|
|
9590
9662
|
maskTextClass: this.maskTextClass,
|
|
9591
9663
|
maskTextSelector: this.maskTextSelector,
|
|
9592
9664
|
excludeAttribute: this.excludeAttribute,
|
|
9593
|
-
includeAttribute: this.includeAttribute,
|
|
9594
9665
|
skipChild: true,
|
|
9595
9666
|
newlyAddedElement: true,
|
|
9596
9667
|
inlineStylesheet: this.inlineStylesheet,
|
|
@@ -9636,7 +9707,8 @@ class MutationBuffer {
|
|
|
9636
9707
|
this.mirror.removeNodeFromMap(this.mapRemoves.shift());
|
|
9637
9708
|
}
|
|
9638
9709
|
for (const n2 of this.movedSet) {
|
|
9639
|
-
if (isParentRemoved(this.removesSubTreeCache, n2, this.mirror) &&
|
|
9710
|
+
if (isParentRemoved(this.removesSubTreeCache, n2, this.mirror) && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
9711
|
+
!this.movedSet.has(index.parentNode(n2))) {
|
|
9640
9712
|
continue;
|
|
9641
9713
|
}
|
|
9642
9714
|
pushAdd(n2);
|
|
@@ -9792,12 +9864,60 @@ class MutationBuffer {
|
|
|
9792
9864
|
const target = m.target;
|
|
9793
9865
|
let attributeName = m.attributeName;
|
|
9794
9866
|
let value = m.target.getAttribute(attributeName);
|
|
9795
|
-
const
|
|
9796
|
-
const
|
|
9867
|
+
const attrKey = attributeName;
|
|
9868
|
+
const propValue = target[attrKey];
|
|
9869
|
+
const isBooleanAttr = typeof propValue === "boolean";
|
|
9870
|
+
const inDOM = document.contains(target);
|
|
9871
|
+
const isVisible = isElementVisible(target);
|
|
9872
|
+
const isExcludeAttributeName = isExcludeAttribute(attributeName, this.excludeAttribute);
|
|
9873
|
+
const isPhantomAttributeMutation = value === null && // текущего атрибута нет
|
|
9874
|
+
!target.hasAttribute(attributeName) && // явно подтверждаем отсутствие
|
|
9875
|
+
m.oldValue !== null && // раньше он был
|
|
9876
|
+
(propValue === "" || // свойство = пустая строка
|
|
9877
|
+
propValue === null || // или null
|
|
9878
|
+
typeof propValue === "undefined");
|
|
9797
9879
|
if (isPhantomAttributeMutation) {
|
|
9880
|
+
console.debug(
|
|
9881
|
+
`[${nowTimestamp()}] [rrweb:record/mutation] ⛔ phantom attribute mutation ignored`,
|
|
9882
|
+
{
|
|
9883
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call
|
|
9884
|
+
node: index.describeNode(target),
|
|
9885
|
+
tag: target.tagName,
|
|
9886
|
+
nodeType: target.nodeType,
|
|
9887
|
+
attribute: attributeName,
|
|
9888
|
+
value,
|
|
9889
|
+
oldValue: m.oldValue,
|
|
9890
|
+
excludeAttribute: this.excludeAttribute,
|
|
9891
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
9892
|
+
propValue,
|
|
9893
|
+
isBooleanAttr,
|
|
9894
|
+
inDOM,
|
|
9895
|
+
isVisible,
|
|
9896
|
+
isExcludeAttributeName
|
|
9897
|
+
}
|
|
9898
|
+
);
|
|
9798
9899
|
return;
|
|
9799
9900
|
}
|
|
9800
9901
|
if (isExcludeAttribute(attributeName, this.excludeAttribute)) {
|
|
9902
|
+
console.debug(
|
|
9903
|
+
`[${nowTimestamp()}] [rrweb:record/mutation] ⛔ excluded attribute mutation ignored`,
|
|
9904
|
+
{
|
|
9905
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call
|
|
9906
|
+
node: index.describeNode(target),
|
|
9907
|
+
tag: target.tagName,
|
|
9908
|
+
nodeType: target.nodeType,
|
|
9909
|
+
attribute: attributeName,
|
|
9910
|
+
value,
|
|
9911
|
+
oldValue: m.oldValue,
|
|
9912
|
+
excludeAttribute: this.excludeAttribute,
|
|
9913
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
9914
|
+
propValue,
|
|
9915
|
+
isBooleanAttr,
|
|
9916
|
+
inDOM,
|
|
9917
|
+
isVisible,
|
|
9918
|
+
isExcludeAttributeName
|
|
9919
|
+
}
|
|
9920
|
+
);
|
|
9801
9921
|
return;
|
|
9802
9922
|
}
|
|
9803
9923
|
if (attributeName === "value") {
|
|
@@ -9842,9 +9962,35 @@ class MutationBuffer {
|
|
|
9842
9962
|
toLowerCase(attributeName),
|
|
9843
9963
|
value
|
|
9844
9964
|
);
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9965
|
+
const isSuspiciousClassMutation = attributeName !== "class" && (m.oldValue === null || // ранее не было класса
|
|
9966
|
+
value === "" || // класс удалён
|
|
9967
|
+
value !== m.oldValue);
|
|
9968
|
+
if (isSuspiciousClassMutation) {
|
|
9969
|
+
console.debug(
|
|
9970
|
+
`[${nowTimestamp()}] [rrweb:record/mutation] ⚠️ suspicious attribute mutation`,
|
|
9971
|
+
{
|
|
9972
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call
|
|
9973
|
+
reason: [
|
|
9974
|
+
value === m.oldValue ? "no change in value" : null,
|
|
9975
|
+
value === propValue ? "mirrored in DOM property" : null,
|
|
9976
|
+
value === item.attributes[attributeName] ? "redundant assignment" : null
|
|
9977
|
+
].filter(Boolean).join(", ") || "uncategorized",
|
|
9978
|
+
node: index.describeNode(target),
|
|
9979
|
+
tag: target.tagName,
|
|
9980
|
+
nodeType: target.nodeType,
|
|
9981
|
+
attribute: attributeName,
|
|
9982
|
+
value,
|
|
9983
|
+
oldValue: m.oldValue,
|
|
9984
|
+
transformedValue: item.attributes[attributeName],
|
|
9985
|
+
excludeAttribute: this.excludeAttribute,
|
|
9986
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
9987
|
+
propValue,
|
|
9988
|
+
isBooleanAttr,
|
|
9989
|
+
inDOM,
|
|
9990
|
+
isVisible,
|
|
9991
|
+
isExcludeAttributeName
|
|
9992
|
+
}
|
|
9993
|
+
);
|
|
9848
9994
|
}
|
|
9849
9995
|
if (attributeName === "style") {
|
|
9850
9996
|
if (!this.unattachedDoc) {
|
|
@@ -9959,7 +10105,6 @@ class MutationBuffer {
|
|
|
9959
10105
|
"maskTextClass",
|
|
9960
10106
|
"maskTextSelector",
|
|
9961
10107
|
"excludeAttribute",
|
|
9962
|
-
"includeAttribute",
|
|
9963
10108
|
"inlineStylesheet",
|
|
9964
10109
|
"maskInputOptions",
|
|
9965
10110
|
"maskTextFn",
|
|
@@ -9975,6 +10120,7 @@ class MutationBuffer {
|
|
|
9975
10120
|
"stylesheetManager",
|
|
9976
10121
|
"shadowDomManager",
|
|
9977
10122
|
"canvasManager",
|
|
10123
|
+
"visibilityManager",
|
|
9978
10124
|
"processedNodeManager"
|
|
9979
10125
|
].forEach((key) => {
|
|
9980
10126
|
this[key] = options[key];
|
|
@@ -9983,10 +10129,12 @@ class MutationBuffer {
|
|
|
9983
10129
|
freeze() {
|
|
9984
10130
|
this.frozen = true;
|
|
9985
10131
|
this.canvasManager.freeze();
|
|
10132
|
+
this.visibilityManager.freeze();
|
|
9986
10133
|
}
|
|
9987
10134
|
unfreeze() {
|
|
9988
10135
|
this.frozen = false;
|
|
9989
10136
|
this.canvasManager.unfreeze();
|
|
10137
|
+
this.visibilityManager.unfreeze();
|
|
9990
10138
|
this.emit();
|
|
9991
10139
|
}
|
|
9992
10140
|
isFrozen() {
|
|
@@ -9995,15 +10143,18 @@ class MutationBuffer {
|
|
|
9995
10143
|
lock() {
|
|
9996
10144
|
this.locked = true;
|
|
9997
10145
|
this.canvasManager.lock();
|
|
10146
|
+
this.visibilityManager.lock();
|
|
9998
10147
|
}
|
|
9999
10148
|
unlock() {
|
|
10000
10149
|
this.locked = false;
|
|
10001
10150
|
this.canvasManager.unlock();
|
|
10151
|
+
this.visibilityManager.unlock();
|
|
10002
10152
|
this.emit();
|
|
10003
10153
|
}
|
|
10004
10154
|
reset() {
|
|
10005
10155
|
this.shadowDomManager.reset();
|
|
10006
10156
|
this.canvasManager.reset();
|
|
10157
|
+
this.visibilityManager.reset();
|
|
10007
10158
|
}
|
|
10008
10159
|
}
|
|
10009
10160
|
function deepDelete(addsSet, n2) {
|
|
@@ -10937,6 +11088,7 @@ function mergeHooks(o2, hooks) {
|
|
|
10937
11088
|
styleSheetRuleCb,
|
|
10938
11089
|
styleDeclarationCb,
|
|
10939
11090
|
canvasMutationCb,
|
|
11091
|
+
visibilityMutationCb,
|
|
10940
11092
|
fontCb,
|
|
10941
11093
|
selectionCb,
|
|
10942
11094
|
customElementCb
|
|
@@ -11001,6 +11153,12 @@ function mergeHooks(o2, hooks) {
|
|
|
11001
11153
|
}
|
|
11002
11154
|
canvasMutationCb(...p);
|
|
11003
11155
|
};
|
|
11156
|
+
o2.visibilityMutationCb = (...p) => {
|
|
11157
|
+
if (hooks.visibilityMutation) {
|
|
11158
|
+
hooks.visibilityMutation(...p);
|
|
11159
|
+
}
|
|
11160
|
+
visibilityMutationCb(...p);
|
|
11161
|
+
};
|
|
11004
11162
|
o2.fontCb = (...p) => {
|
|
11005
11163
|
if (hooks.font) {
|
|
11006
11164
|
hooks.font(...p);
|
|
@@ -12114,11 +12272,249 @@ class ProcessedNodeManager {
|
|
|
12114
12272
|
destroy() {
|
|
12115
12273
|
}
|
|
12116
12274
|
}
|
|
12275
|
+
function computeVisibility(elements, previous, options) {
|
|
12276
|
+
const root2 = (options == null ? void 0 : options.root) ?? null;
|
|
12277
|
+
const threshold = (options == null ? void 0 : options.threshold) ?? 0.5;
|
|
12278
|
+
const sensitivity = (options == null ? void 0 : options.sensitivity) ?? 0.05;
|
|
12279
|
+
const rootMarginFn = parseRootMargin((options == null ? void 0 : options.rootMargin) ?? "0px");
|
|
12280
|
+
const current = /* @__PURE__ */ new Map();
|
|
12281
|
+
const rootRect = getRootRect(root2);
|
|
12282
|
+
const expandedRoot = expandRootRect(rootRect, rootMarginFn);
|
|
12283
|
+
for (const el of elements) {
|
|
12284
|
+
const elRect = el.getBoundingClientRect();
|
|
12285
|
+
let intersectionRect = emptyRect();
|
|
12286
|
+
let intersectionRatio = 0;
|
|
12287
|
+
if (elRect.width > 0 && elRect.height > 0) {
|
|
12288
|
+
intersectionRect = computeIntersectionRect(elRect, expandedRoot);
|
|
12289
|
+
intersectionRatio = computeIntersectionRatio(elRect, intersectionRect);
|
|
12290
|
+
intersectionRatio = Math.round(intersectionRatio * 100) / 100;
|
|
12291
|
+
}
|
|
12292
|
+
const isStyle = isStyleVisible(el);
|
|
12293
|
+
const old = previous.get(el) ?? null;
|
|
12294
|
+
const prevRatio = (old == null ? void 0 : old.intersectionRatio) ?? 0;
|
|
12295
|
+
const currRatio = intersectionRatio;
|
|
12296
|
+
const wasVisible = (old == null ? void 0 : old.isStyleVisible) && prevRatio > threshold;
|
|
12297
|
+
const nowVisible = isStyle && currRatio > threshold;
|
|
12298
|
+
const changed = !old || wasVisible !== nowVisible || wasVisible !== nowVisible && Math.abs(currRatio - prevRatio) > sensitivity;
|
|
12299
|
+
if (changed) {
|
|
12300
|
+
current.set(el, {
|
|
12301
|
+
target: el,
|
|
12302
|
+
isVisible: nowVisible,
|
|
12303
|
+
isStyleVisible: isStyle,
|
|
12304
|
+
intersectionRatio: currRatio,
|
|
12305
|
+
intersectionRect,
|
|
12306
|
+
oldValue: old
|
|
12307
|
+
});
|
|
12308
|
+
} else {
|
|
12309
|
+
current.set(el, old);
|
|
12310
|
+
}
|
|
12311
|
+
}
|
|
12312
|
+
return current;
|
|
12313
|
+
}
|
|
12314
|
+
function parseRootMargin(marginStr) {
|
|
12315
|
+
const parts = marginStr.trim().split(/\s+/);
|
|
12316
|
+
const getValue = (val, size) => val.endsWith("%") ? parseFloat(val) / 100 * size : parseFloat(val) || 0;
|
|
12317
|
+
return function(rootRect) {
|
|
12318
|
+
const top = getValue(parts[0] || "0px", rootRect.height);
|
|
12319
|
+
const right = getValue(parts[1] || parts[0] || "0px", rootRect.width);
|
|
12320
|
+
const bottom = getValue(parts[2] || parts[0] || "0px", rootRect.height);
|
|
12321
|
+
const left = getValue(parts[3] || parts[1] || parts[0] || "0px", rootRect.width);
|
|
12322
|
+
return { top, right, bottom, left, width: 0, height: 0 };
|
|
12323
|
+
};
|
|
12324
|
+
}
|
|
12325
|
+
function getRootRect(root2) {
|
|
12326
|
+
return root2 ? root2.getBoundingClientRect() : new DOMRect(0, 0, window.innerWidth, window.innerHeight);
|
|
12327
|
+
}
|
|
12328
|
+
function expandRootRect(rect, marginFn) {
|
|
12329
|
+
const margin = marginFn(rect);
|
|
12330
|
+
return new DOMRect(
|
|
12331
|
+
rect.left - margin.left,
|
|
12332
|
+
rect.top - margin.top,
|
|
12333
|
+
rect.width + margin.left + margin.right,
|
|
12334
|
+
rect.height + margin.top + margin.bottom
|
|
12335
|
+
);
|
|
12336
|
+
}
|
|
12337
|
+
function computeIntersectionRect(a2, b) {
|
|
12338
|
+
const top = Math.max(a2.top, b.top);
|
|
12339
|
+
const left = Math.max(a2.left, b.left);
|
|
12340
|
+
const bottom = Math.min(a2.bottom, b.bottom);
|
|
12341
|
+
const right = Math.min(a2.right, b.right);
|
|
12342
|
+
const width = Math.max(0, right - left);
|
|
12343
|
+
const height = Math.max(0, bottom - top);
|
|
12344
|
+
return { top, left, bottom, right, width, height };
|
|
12345
|
+
}
|
|
12346
|
+
function computeIntersectionRatio(elRect, intersectionRect) {
|
|
12347
|
+
const elArea = elRect.width * elRect.height;
|
|
12348
|
+
const intArea = intersectionRect.width * intersectionRect.height;
|
|
12349
|
+
return elArea > 0 ? intArea / elArea : 0;
|
|
12350
|
+
}
|
|
12351
|
+
function emptyRect() {
|
|
12352
|
+
return { top: 0, left: 0, right: 0, bottom: 0, width: 0, height: 0 };
|
|
12353
|
+
}
|
|
12354
|
+
function isStyleVisible(el) {
|
|
12355
|
+
const style = getComputedStyle(el);
|
|
12356
|
+
return style && style.display !== "none" && style.visibility !== "hidden" && parseFloat(style.opacity || "1") > 0;
|
|
12357
|
+
}
|
|
12358
|
+
class VisibilityManager {
|
|
12359
|
+
constructor(options) {
|
|
12360
|
+
__publicField(this, "frozen", false);
|
|
12361
|
+
__publicField(this, "locked", false);
|
|
12362
|
+
__publicField(this, "pending", /* @__PURE__ */ new Map());
|
|
12363
|
+
__publicField(this, "mirror");
|
|
12364
|
+
__publicField(this, "mutationCb");
|
|
12365
|
+
__publicField(this, "rafId", null);
|
|
12366
|
+
__publicField(this, "rafThrottle");
|
|
12367
|
+
__publicField(this, "lastFlushTime", 0);
|
|
12368
|
+
__publicField(this, "elements", /* @__PURE__ */ new Set());
|
|
12369
|
+
__publicField(this, "previousState", /* @__PURE__ */ new Map());
|
|
12370
|
+
__publicField(this, "root", null);
|
|
12371
|
+
__publicField(this, "threshold");
|
|
12372
|
+
__publicField(this, "sensitivity");
|
|
12373
|
+
__publicField(this, "rootMargin");
|
|
12374
|
+
__publicField(this, "hasInitialized", false);
|
|
12375
|
+
__publicField(this, "mode", "none");
|
|
12376
|
+
__publicField(this, "debounce", 50);
|
|
12377
|
+
__publicField(this, "throttle", 100);
|
|
12378
|
+
__publicField(this, "buffer", /* @__PURE__ */ new Map());
|
|
12379
|
+
__publicField(this, "debounceTimer", null);
|
|
12380
|
+
__publicField(this, "lastThrottleTime", 0);
|
|
12381
|
+
__publicField(this, "disabled", false);
|
|
12382
|
+
__publicField(this, "notifyActivity");
|
|
12383
|
+
const { doc, mirror: mirror2, sampling, mutationCb, notifyActivity } = options;
|
|
12384
|
+
this.mirror = mirror2;
|
|
12385
|
+
this.mutationCb = mutationCb;
|
|
12386
|
+
this.notifyActivity = notifyActivity;
|
|
12387
|
+
this.rootMargin = "0px";
|
|
12388
|
+
if (sampling === false) {
|
|
12389
|
+
this.disabled = true;
|
|
12390
|
+
return;
|
|
12391
|
+
}
|
|
12392
|
+
const visibilitySampling = typeof sampling === "object" && sampling !== null ? sampling : {};
|
|
12393
|
+
this.mode = (visibilitySampling == null ? void 0 : visibilitySampling.mode) ?? "none";
|
|
12394
|
+
this.debounce = Number((visibilitySampling == null ? void 0 : visibilitySampling.debounce) ?? 100);
|
|
12395
|
+
this.throttle = Number((visibilitySampling == null ? void 0 : visibilitySampling.throttle) ?? 100);
|
|
12396
|
+
this.threshold = Number((visibilitySampling == null ? void 0 : visibilitySampling.threshold) ?? 0.5);
|
|
12397
|
+
this.sensitivity = Number((visibilitySampling == null ? void 0 : visibilitySampling.sensitivity) ?? 0.05);
|
|
12398
|
+
this.rafThrottle = Number((visibilitySampling == null ? void 0 : visibilitySampling.rafThrottle) ?? 100);
|
|
12399
|
+
doc.querySelectorAll("*").forEach((el) => this.observe(el));
|
|
12400
|
+
const mo = new MutationObserver((mutations) => {
|
|
12401
|
+
mutations.forEach((m) => {
|
|
12402
|
+
m.addedNodes.forEach((n2) => {
|
|
12403
|
+
if (n2.nodeType === Node.ELEMENT_NODE) {
|
|
12404
|
+
this.observe(n2);
|
|
12405
|
+
n2.querySelectorAll("*").forEach((el) => this.observe(el));
|
|
12406
|
+
}
|
|
12407
|
+
});
|
|
12408
|
+
m.removedNodes.forEach((n2) => {
|
|
12409
|
+
if (n2.nodeType === Node.ELEMENT_NODE) {
|
|
12410
|
+
this.unobserve(n2);
|
|
12411
|
+
}
|
|
12412
|
+
});
|
|
12413
|
+
});
|
|
12414
|
+
});
|
|
12415
|
+
mo.observe(doc.body, { childList: true, subtree: true });
|
|
12416
|
+
this.startPendingFlushLoop();
|
|
12417
|
+
}
|
|
12418
|
+
startPendingFlushLoop() {
|
|
12419
|
+
if (this.disabled) return;
|
|
12420
|
+
const loop = (timestamp) => {
|
|
12421
|
+
if (timestamp - this.lastFlushTime >= this.rafThrottle) {
|
|
12422
|
+
this.lastFlushTime = timestamp;
|
|
12423
|
+
this.flushPendingVisibilityMutations();
|
|
12424
|
+
}
|
|
12425
|
+
this.rafId = requestAnimationFrame(loop);
|
|
12426
|
+
};
|
|
12427
|
+
this.rafId = requestAnimationFrame(loop);
|
|
12428
|
+
}
|
|
12429
|
+
flushPendingVisibilityMutations() {
|
|
12430
|
+
if (this.disabled) return;
|
|
12431
|
+
if (this.frozen || this.locked || this.elements.size === 0) return;
|
|
12432
|
+
const state = computeVisibility(this.elements, this.previousState, {
|
|
12433
|
+
root: this.root,
|
|
12434
|
+
threshold: this.threshold,
|
|
12435
|
+
sensitivity: this.sensitivity,
|
|
12436
|
+
rootMargin: this.rootMargin
|
|
12437
|
+
});
|
|
12438
|
+
for (const [el, entry] of state.entries()) {
|
|
12439
|
+
const old = this.previousState.get(el);
|
|
12440
|
+
const changed = !old || old.isVisible !== entry.isVisible || Math.abs(old.intersectionRatio - entry.intersectionRatio) > this.sensitivity;
|
|
12441
|
+
if (changed) {
|
|
12442
|
+
const id = this.mirror.getId(el);
|
|
12443
|
+
if (id !== -1) {
|
|
12444
|
+
this.buffer.set(el, {
|
|
12445
|
+
id,
|
|
12446
|
+
isVisible: entry.isVisible,
|
|
12447
|
+
ratio: entry.intersectionRatio
|
|
12448
|
+
});
|
|
12449
|
+
}
|
|
12450
|
+
this.previousState.set(el, entry);
|
|
12451
|
+
}
|
|
12452
|
+
}
|
|
12453
|
+
this.previousState = state;
|
|
12454
|
+
if (!this.hasInitialized) {
|
|
12455
|
+
this.hasInitialized = true;
|
|
12456
|
+
this.buffer.clear();
|
|
12457
|
+
return;
|
|
12458
|
+
}
|
|
12459
|
+
this.scheduleEmit();
|
|
12460
|
+
}
|
|
12461
|
+
scheduleEmit() {
|
|
12462
|
+
if (this.mode === "debounce") {
|
|
12463
|
+
clearTimeout(this.debounceTimer);
|
|
12464
|
+
this.debounceTimer = setTimeout(() => this.flushBuffer(), this.debounce);
|
|
12465
|
+
} else if (this.mode === "throttle") {
|
|
12466
|
+
const now = performance.now();
|
|
12467
|
+
if (now - this.lastThrottleTime >= this.throttle) {
|
|
12468
|
+
this.lastThrottleTime = now;
|
|
12469
|
+
this.flushBuffer();
|
|
12470
|
+
}
|
|
12471
|
+
} else {
|
|
12472
|
+
this.flushBuffer();
|
|
12473
|
+
}
|
|
12474
|
+
}
|
|
12475
|
+
flushBuffer() {
|
|
12476
|
+
var _a2;
|
|
12477
|
+
if (this.buffer.size === 0) return;
|
|
12478
|
+
(_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, this.buffer.size);
|
|
12479
|
+
this.mutationCb({ mutations: Array.from(this.buffer.values()) });
|
|
12480
|
+
this.buffer.clear();
|
|
12481
|
+
}
|
|
12482
|
+
observe(el) {
|
|
12483
|
+
if (this.disabled) return;
|
|
12484
|
+
this.elements.add(el);
|
|
12485
|
+
}
|
|
12486
|
+
unobserve(el) {
|
|
12487
|
+
if (this.disabled) return;
|
|
12488
|
+
this.elements.delete(el);
|
|
12489
|
+
this.previousState.delete(el);
|
|
12490
|
+
this.pending.delete(el);
|
|
12491
|
+
}
|
|
12492
|
+
freeze() {
|
|
12493
|
+
this.frozen = true;
|
|
12494
|
+
}
|
|
12495
|
+
unfreeze() {
|
|
12496
|
+
this.frozen = false;
|
|
12497
|
+
}
|
|
12498
|
+
lock() {
|
|
12499
|
+
this.locked = true;
|
|
12500
|
+
}
|
|
12501
|
+
unlock() {
|
|
12502
|
+
this.locked = false;
|
|
12503
|
+
}
|
|
12504
|
+
reset() {
|
|
12505
|
+
this.elements.clear();
|
|
12506
|
+
this.previousState.clear();
|
|
12507
|
+
this.pending.clear();
|
|
12508
|
+
if (this.rafId) cancelAnimationFrame(this.rafId);
|
|
12509
|
+
}
|
|
12510
|
+
}
|
|
12117
12511
|
let wrappedEmit;
|
|
12118
12512
|
let takeFullSnapshot$1;
|
|
12119
12513
|
let canvasManager;
|
|
12514
|
+
let visibilityManager;
|
|
12120
12515
|
let recording = false;
|
|
12121
|
-
const
|
|
12516
|
+
const customEventQueue = [];
|
|
12517
|
+
let flushCustomEventQueue;
|
|
12122
12518
|
try {
|
|
12123
12519
|
if (Array.from([1], (x2) => x2 * 2)[0] !== 2) {
|
|
12124
12520
|
const cleanFrame = document.createElement("iframe");
|
|
@@ -12135,12 +12531,12 @@ function record(options = {}) {
|
|
|
12135
12531
|
emit,
|
|
12136
12532
|
checkoutEveryNms,
|
|
12137
12533
|
checkoutEveryNth,
|
|
12534
|
+
checkoutEveryNvm,
|
|
12138
12535
|
blockClass = "rr-block",
|
|
12139
12536
|
blockSelector = null,
|
|
12140
12537
|
ignoreClass = "rr-ignore",
|
|
12141
12538
|
ignoreSelector = null,
|
|
12142
12539
|
excludeAttribute: _excludeAttribute,
|
|
12143
|
-
includeAttribute: _includeAttribute,
|
|
12144
12540
|
maskTextClass = "rr-mask",
|
|
12145
12541
|
maskTextSelector = null,
|
|
12146
12542
|
inlineStylesheet = true,
|
|
@@ -12158,7 +12554,7 @@ function record(options = {}) {
|
|
|
12158
12554
|
recordCanvas = false,
|
|
12159
12555
|
recordCrossOriginIframes = false,
|
|
12160
12556
|
recordAfter = options.recordAfter === "DOMContentLoaded" ? options.recordAfter : "load",
|
|
12161
|
-
|
|
12557
|
+
flushCustomEvent = options.flushCustomEvent !== void 0 ? options.flushCustomEvent : "after",
|
|
12162
12558
|
userTriggeredOnInput = false,
|
|
12163
12559
|
collectFonts = false,
|
|
12164
12560
|
inlineImages = false,
|
|
@@ -12190,8 +12586,7 @@ function record(options = {}) {
|
|
|
12190
12586
|
sampling.mousemove = mousemoveWait;
|
|
12191
12587
|
}
|
|
12192
12588
|
mirror.reset();
|
|
12193
|
-
const excludeAttribute = _excludeAttribute === void 0 ?
|
|
12194
|
-
const includeAttribute = _includeAttribute === void 0 ? /.+/i : _includeAttribute;
|
|
12589
|
+
const excludeAttribute = _excludeAttribute === void 0 ? /.^/ : _excludeAttribute;
|
|
12195
12590
|
const maskInputOptions = maskAllInputs === true ? {
|
|
12196
12591
|
color: true,
|
|
12197
12592
|
date: true,
|
|
@@ -12228,6 +12623,10 @@ function record(options = {}) {
|
|
|
12228
12623
|
polyfill$1();
|
|
12229
12624
|
let lastFullSnapshotEvent;
|
|
12230
12625
|
let incrementalSnapshotCount = 0;
|
|
12626
|
+
let recentVisibilityChanges = 0;
|
|
12627
|
+
const onVisibilityActivity = (count) => {
|
|
12628
|
+
recentVisibilityChanges += count;
|
|
12629
|
+
};
|
|
12231
12630
|
const eventProcessor = (e2) => {
|
|
12232
12631
|
for (const plugin3 of plugins || []) {
|
|
12233
12632
|
if (plugin3.eventProcessor) {
|
|
@@ -12268,7 +12667,11 @@ function record(options = {}) {
|
|
|
12268
12667
|
incrementalSnapshotCount++;
|
|
12269
12668
|
const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
|
|
12270
12669
|
const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
|
|
12271
|
-
|
|
12670
|
+
const exceedVisibility = checkoutEveryNvm && recentVisibilityChanges >= checkoutEveryNvm;
|
|
12671
|
+
if (exceedCount || exceedTime || exceedVisibility) {
|
|
12672
|
+
if (exceedVisibility) {
|
|
12673
|
+
recentVisibilityChanges = 0;
|
|
12674
|
+
}
|
|
12272
12675
|
takeFullSnapshot$1(true);
|
|
12273
12676
|
}
|
|
12274
12677
|
}
|
|
@@ -12296,6 +12699,17 @@ function record(options = {}) {
|
|
|
12296
12699
|
...p
|
|
12297
12700
|
}
|
|
12298
12701
|
});
|
|
12702
|
+
const wrappedVisibilityMutationEmit = (p) => {
|
|
12703
|
+
var _a2;
|
|
12704
|
+
(_a2 = hooks == null ? void 0 : hooks.visibilityMutation) == null ? void 0 : _a2.call(hooks, p);
|
|
12705
|
+
wrappedEmit({
|
|
12706
|
+
type: EventType.IncrementalSnapshot,
|
|
12707
|
+
data: {
|
|
12708
|
+
source: IncrementalSource.VisibilityMutation,
|
|
12709
|
+
...p
|
|
12710
|
+
}
|
|
12711
|
+
});
|
|
12712
|
+
};
|
|
12299
12713
|
const wrappedAdoptedStyleSheetEmit = (a2) => wrappedEmit({
|
|
12300
12714
|
type: EventType.IncrementalSnapshot,
|
|
12301
12715
|
data: {
|
|
@@ -12333,6 +12747,13 @@ function record(options = {}) {
|
|
|
12333
12747
|
sampling: sampling.canvas,
|
|
12334
12748
|
dataURLOptions
|
|
12335
12749
|
});
|
|
12750
|
+
visibilityManager = new VisibilityManager({
|
|
12751
|
+
doc: window.document,
|
|
12752
|
+
mirror,
|
|
12753
|
+
sampling: sampling.visibility,
|
|
12754
|
+
mutationCb: wrappedVisibilityMutationEmit,
|
|
12755
|
+
notifyActivity: onVisibilityActivity
|
|
12756
|
+
});
|
|
12336
12757
|
const shadowDomManager = new ShadowDomManager({
|
|
12337
12758
|
mutationCb: wrappedMutationEmit,
|
|
12338
12759
|
scrollCb: wrappedScrollEmit,
|
|
@@ -12342,7 +12763,6 @@ function record(options = {}) {
|
|
|
12342
12763
|
maskTextClass,
|
|
12343
12764
|
maskTextSelector,
|
|
12344
12765
|
excludeAttribute,
|
|
12345
|
-
includeAttribute,
|
|
12346
12766
|
inlineStylesheet,
|
|
12347
12767
|
maskInputOptions,
|
|
12348
12768
|
dataURLOptions,
|
|
@@ -12355,6 +12775,7 @@ function record(options = {}) {
|
|
|
12355
12775
|
iframeManager,
|
|
12356
12776
|
stylesheetManager,
|
|
12357
12777
|
canvasManager,
|
|
12778
|
+
visibilityManager,
|
|
12358
12779
|
keepIframeSrcFn,
|
|
12359
12780
|
processedNodeManager
|
|
12360
12781
|
},
|
|
@@ -12385,7 +12806,6 @@ function record(options = {}) {
|
|
|
12385
12806
|
maskTextClass,
|
|
12386
12807
|
maskTextSelector,
|
|
12387
12808
|
excludeAttribute,
|
|
12388
|
-
includeAttribute,
|
|
12389
12809
|
inlineStylesheet,
|
|
12390
12810
|
maskAllInputs: maskInputOptions,
|
|
12391
12811
|
maskTextFn,
|
|
@@ -12434,6 +12854,12 @@ function record(options = {}) {
|
|
|
12434
12854
|
mirror.getId(document)
|
|
12435
12855
|
);
|
|
12436
12856
|
};
|
|
12857
|
+
flushCustomEventQueue = () => {
|
|
12858
|
+
for (const e2 of customEventQueue) {
|
|
12859
|
+
wrappedEmit(e2);
|
|
12860
|
+
}
|
|
12861
|
+
customEventQueue.length = 0;
|
|
12862
|
+
};
|
|
12437
12863
|
try {
|
|
12438
12864
|
const handlers = [];
|
|
12439
12865
|
const observe = (doc) => {
|
|
@@ -12492,6 +12918,7 @@ function record(options = {}) {
|
|
|
12492
12918
|
}
|
|
12493
12919
|
}),
|
|
12494
12920
|
canvasMutationCb: wrappedCanvasMutationEmit,
|
|
12921
|
+
visibilityMutationCb: wrappedVisibilityMutationEmit,
|
|
12495
12922
|
fontCb: (p) => wrappedEmit({
|
|
12496
12923
|
type: EventType.IncrementalSnapshot,
|
|
12497
12924
|
data: {
|
|
@@ -12523,7 +12950,6 @@ function record(options = {}) {
|
|
|
12523
12950
|
maskTextClass,
|
|
12524
12951
|
maskTextSelector,
|
|
12525
12952
|
excludeAttribute,
|
|
12526
|
-
includeAttribute,
|
|
12527
12953
|
maskInputOptions,
|
|
12528
12954
|
inlineStylesheet,
|
|
12529
12955
|
sampling,
|
|
@@ -12545,6 +12971,7 @@ function record(options = {}) {
|
|
|
12545
12971
|
shadowDomManager,
|
|
12546
12972
|
processedNodeManager,
|
|
12547
12973
|
canvasManager,
|
|
12974
|
+
visibilityManager,
|
|
12548
12975
|
ignoreCSSAttributes,
|
|
12549
12976
|
plugins: ((_a2 = plugins == null ? void 0 : plugins.filter((p) => p.observer)) == null ? void 0 : _a2.map((p) => ({
|
|
12550
12977
|
observer: p.observer,
|
|
@@ -12569,14 +12996,14 @@ function record(options = {}) {
|
|
|
12569
12996
|
}
|
|
12570
12997
|
});
|
|
12571
12998
|
const init = () => {
|
|
12572
|
-
if (
|
|
12573
|
-
|
|
12999
|
+
if (flushCustomEvent === "before") {
|
|
13000
|
+
flushCustomEventQueue();
|
|
12574
13001
|
}
|
|
12575
13002
|
takeFullSnapshot$1();
|
|
12576
13003
|
handlers.push(observe(document));
|
|
12577
13004
|
recording = true;
|
|
12578
|
-
if (
|
|
12579
|
-
|
|
13005
|
+
if (flushCustomEvent === "after") {
|
|
13006
|
+
flushCustomEventQueue();
|
|
12580
13007
|
}
|
|
12581
13008
|
};
|
|
12582
13009
|
if (document.readyState === "interactive" || document.readyState === "complete") {
|
|
@@ -12606,7 +13033,7 @@ function record(options = {}) {
|
|
|
12606
13033
|
);
|
|
12607
13034
|
}
|
|
12608
13035
|
return () => {
|
|
12609
|
-
|
|
13036
|
+
flushCustomEventQueue();
|
|
12610
13037
|
handlers.forEach((h) => h());
|
|
12611
13038
|
processedNodeManager.destroy();
|
|
12612
13039
|
recording = false;
|
|
@@ -12616,12 +13043,10 @@ function record(options = {}) {
|
|
|
12616
13043
|
console.warn(error);
|
|
12617
13044
|
}
|
|
12618
13045
|
}
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12623
|
-
preRecordingCustomEvents.length = 0;
|
|
12624
|
-
}
|
|
13046
|
+
record.flushCustomEventQueue = () => {
|
|
13047
|
+
console.warn(`[rrweb] CustomEvent flushing: ${customEventQueue.length} events`);
|
|
13048
|
+
flushCustomEventQueue();
|
|
13049
|
+
};
|
|
12625
13050
|
record.addCustomEvent = (tag, payload) => {
|
|
12626
13051
|
const customEvent = {
|
|
12627
13052
|
type: EventType.Custom,
|
|
@@ -12631,8 +13056,8 @@ record.addCustomEvent = (tag, payload) => {
|
|
|
12631
13056
|
}
|
|
12632
13057
|
};
|
|
12633
13058
|
if (!recording) {
|
|
12634
|
-
console.warn(`[rrweb] CustomEvent buffered before recording start: ${tag}`);
|
|
12635
|
-
|
|
13059
|
+
console.warn(`[rrweb] CustomEvent buffered before/after recording start: ${tag}`);
|
|
13060
|
+
customEventQueue.push(customEvent);
|
|
12636
13061
|
return;
|
|
12637
13062
|
}
|
|
12638
13063
|
wrappedEmit(customEvent);
|