@appsurify-testmap/rrweb 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/assets/image-bitmap-data-url-worker-IJpC7g_b.js.map +1 -1
- package/dist/rrweb.cjs +576 -151
- package/dist/rrweb.cjs.map +1 -1
- package/dist/rrweb.d.cts +4 -3
- package/dist/rrweb.d.ts +4 -3
- package/dist/rrweb.js +576 -151
- package/dist/rrweb.js.map +1 -1
- package/dist/rrweb.umd.cjs +576 -150
- package/dist/rrweb.umd.cjs.map +4 -4
- package/dist/rrweb.umd.min.cjs +26 -26
- package/dist/rrweb.umd.min.cjs.map +4 -4
- package/package.json +5 -5
package/dist/rrweb.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;
|
|
@@ -567,71 +604,95 @@ function splitCssText(cssText, style, _testNoPxNorm = false) {
|
|
|
567
604
|
function markCssSplits(cssText, style) {
|
|
568
605
|
return splitCssText(cssText, style).join("/* rr_split */");
|
|
569
606
|
}
|
|
570
|
-
function
|
|
571
|
-
|
|
572
|
-
|
|
607
|
+
function isSelectorUnique(selector, target) {
|
|
608
|
+
try {
|
|
609
|
+
const matches = document.querySelectorAll(selector);
|
|
610
|
+
return matches.length === 1 && matches[0] === target;
|
|
611
|
+
} catch {
|
|
612
|
+
return false;
|
|
573
613
|
}
|
|
574
|
-
|
|
575
|
-
|
|
614
|
+
}
|
|
615
|
+
function buildSelector(node2) {
|
|
616
|
+
if (!(node2 instanceof Element)) return null;
|
|
617
|
+
if (node2.id) {
|
|
618
|
+
return `#${CSS.escape(node2.id)}`;
|
|
576
619
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
}
|
|
582
|
-
if (element.tagName && element.tagName.toLowerCase() === "html") {
|
|
583
|
-
return "/html";
|
|
584
|
-
}
|
|
585
|
-
if (element === document.head) {
|
|
586
|
-
return "/html/head";
|
|
587
|
-
}
|
|
588
|
-
if (element === document.body) {
|
|
589
|
-
return "/html/body";
|
|
590
|
-
}
|
|
591
|
-
const parentNode2 = element.parentNode;
|
|
592
|
-
if (!parentNode2) {
|
|
593
|
-
return "";
|
|
594
|
-
}
|
|
595
|
-
const siblings = Array.from(parentNode2.children).filter(
|
|
596
|
-
(sibling) => sibling.tagName === element.tagName
|
|
597
|
-
);
|
|
598
|
-
const index2 = siblings.length > 1 ? `[${siblings.indexOf(element) + 1}]` : "";
|
|
599
|
-
return `${getXPath(parentNode2)}/${element.tagName.toLowerCase()}${index2}`;
|
|
620
|
+
const parts = [];
|
|
621
|
+
const tag = node2.tagName.toLowerCase();
|
|
622
|
+
if (node2.classList.length) {
|
|
623
|
+
parts.push(...Array.from(node2.classList).map((cls) => `.${CSS.escape(cls)}`));
|
|
600
624
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
return "";
|
|
625
|
+
Array.from(node2.attributes).forEach((attr) => {
|
|
626
|
+
if (attr.name.startsWith("data-")) {
|
|
627
|
+
parts.push(`[${attr.name}="${CSS.escape(attr.value)}"]`);
|
|
605
628
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
629
|
+
});
|
|
630
|
+
const shortSelector = `${tag}${parts.join("")}`;
|
|
631
|
+
if (isSelectorUnique(shortSelector, node2)) {
|
|
632
|
+
return shortSelector;
|
|
633
|
+
}
|
|
634
|
+
const pathParts = [];
|
|
635
|
+
let current = node2;
|
|
636
|
+
while (current && current.nodeType === Node.ELEMENT_NODE) {
|
|
637
|
+
const parent = current.parentElement;
|
|
638
|
+
const tagName = current.tagName.toLowerCase();
|
|
639
|
+
let nth = "";
|
|
640
|
+
if (parent) {
|
|
641
|
+
const siblings = Array.from(parent.children).filter(
|
|
642
|
+
(el) => el.tagName.toLowerCase() === tagName
|
|
643
|
+
);
|
|
644
|
+
if (siblings.length > 1) {
|
|
645
|
+
nth = `:nth-of-type(${siblings.indexOf(current) + 1})`;
|
|
646
|
+
}
|
|
616
647
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
);
|
|
620
|
-
const index2 = cdataSiblings.length > 1 ? `[${cdataSiblings.indexOf(node2) + 1}]` : "";
|
|
621
|
-
return `${getXPath(parent)}/text()${index2}`;
|
|
648
|
+
pathParts.unshift(`${tagName}${nth}`);
|
|
649
|
+
current = parent;
|
|
622
650
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
651
|
+
return pathParts.join(" > ") || null;
|
|
652
|
+
}
|
|
653
|
+
function buildXPath(node2) {
|
|
654
|
+
switch (node2.nodeType) {
|
|
655
|
+
case Node.DOCUMENT_NODE:
|
|
656
|
+
return "/";
|
|
657
|
+
case Node.DOCUMENT_TYPE_NODE:
|
|
658
|
+
return "/html/doctype";
|
|
659
|
+
case Node.ELEMENT_NODE: {
|
|
660
|
+
const element = node2;
|
|
661
|
+
if (element.id) {
|
|
662
|
+
return `//*[@id="${CSS.escape(element.id)}"]`;
|
|
663
|
+
}
|
|
664
|
+
if (element.tagName.toLowerCase() === "html") return "/html";
|
|
665
|
+
if (element === document.head) return "/html/head";
|
|
666
|
+
if (element === document.body) return "/html/body";
|
|
667
|
+
const parent = element.parentNode;
|
|
668
|
+
if (!parent) return "";
|
|
669
|
+
const tag = element.tagName.toLowerCase();
|
|
670
|
+
const siblings = Array.from(parent.children).filter(
|
|
671
|
+
(el) => el.tagName.toLowerCase() === tag
|
|
672
|
+
);
|
|
673
|
+
const index2 = siblings.length > 1 ? `[${siblings.indexOf(element) + 1}]` : "";
|
|
674
|
+
return `${buildXPath(parent)}/${tag}${index2}`;
|
|
675
|
+
}
|
|
676
|
+
case Node.TEXT_NODE:
|
|
677
|
+
case Node.CDATA_SECTION_NODE:
|
|
678
|
+
case Node.COMMENT_NODE: {
|
|
679
|
+
const parent = node2.parentNode;
|
|
680
|
+
if (!parent) return "";
|
|
681
|
+
const typeMap = {
|
|
682
|
+
[Node.TEXT_NODE]: "text()",
|
|
683
|
+
[Node.CDATA_SECTION_NODE]: "text()",
|
|
684
|
+
// CDATA ≡ text() в XPath
|
|
685
|
+
[Node.COMMENT_NODE]: "comment()"
|
|
686
|
+
};
|
|
687
|
+
const sameTypeSiblings = Array.from(parent.childNodes).filter(
|
|
688
|
+
(sibling) => sibling.nodeType === node2.nodeType
|
|
689
|
+
);
|
|
690
|
+
const index2 = sameTypeSiblings.length > 1 ? `[${sameTypeSiblings.indexOf(node2)}]` : "";
|
|
691
|
+
return `${buildXPath(parent)}/${typeMap[node2.nodeType]}${index2}`;
|
|
627
692
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
);
|
|
631
|
-
const index2 = commentSiblings.length > 1 ? `[${commentSiblings.indexOf(node2) + 1}]` : "";
|
|
632
|
-
return `${getXPath(parent)}/comment()${index2}`;
|
|
693
|
+
default:
|
|
694
|
+
return "";
|
|
633
695
|
}
|
|
634
|
-
return "";
|
|
635
696
|
}
|
|
636
697
|
function isTextVisible(n2) {
|
|
637
698
|
var _a2;
|
|
@@ -647,20 +708,9 @@ function isTextVisible(n2) {
|
|
|
647
708
|
const textContent2 = (_a2 = n2.textContent) == null ? void 0 : _a2.trim();
|
|
648
709
|
return textContent2 !== "";
|
|
649
710
|
}
|
|
650
|
-
function isElementVisible(
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const style = win ? win.getComputedStyle(n2) : null;
|
|
654
|
-
const isStyleVisible = style != null && style.display !== "none" && style.visibility !== "hidden" && parseFloat(style.opacity) !== 0;
|
|
655
|
-
const rect = n2.getBoundingClientRect();
|
|
656
|
-
const result2 = isStyleVisible && isRectVisible(rect);
|
|
657
|
-
return result2;
|
|
658
|
-
}
|
|
659
|
-
function isRectVisible(rect, win = window) {
|
|
660
|
-
var _a2, _b, _c, _d;
|
|
661
|
-
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;
|
|
662
|
-
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;
|
|
663
|
-
return rect.width > 0 && rect.height > 0 && rect.top >= 0 && rect.left >= 0 && rect.bottom <= height && rect.right <= width;
|
|
711
|
+
function isElementVisible(el) {
|
|
712
|
+
const visibility = index$1.getElementVisibility(el);
|
|
713
|
+
return visibility.isVisible;
|
|
664
714
|
}
|
|
665
715
|
const interactiveEvents$1 = [
|
|
666
716
|
"change",
|
|
@@ -893,9 +943,6 @@ function transformAttribute(doc, tagName, name, value) {
|
|
|
893
943
|
function ignoreAttribute(tagName, name, _value) {
|
|
894
944
|
return (tagName === "video" || tagName === "audio") && name === "autoplay";
|
|
895
945
|
}
|
|
896
|
-
function isIncludeAttribute(name, include) {
|
|
897
|
-
return typeof include === "string" ? name.includes(include) : include.test(name);
|
|
898
|
-
}
|
|
899
946
|
function isExcludeAttribute(name, exclude) {
|
|
900
947
|
return typeof exclude === "string" ? name.includes(exclude) : exclude.test(name);
|
|
901
948
|
}
|
|
@@ -1029,7 +1076,6 @@ function serializeNode(n2, options) {
|
|
|
1029
1076
|
blockClass,
|
|
1030
1077
|
blockSelector,
|
|
1031
1078
|
excludeAttribute,
|
|
1032
|
-
includeAttribute,
|
|
1033
1079
|
needsMask,
|
|
1034
1080
|
inlineStylesheet,
|
|
1035
1081
|
maskInputOptions = {},
|
|
@@ -1043,22 +1089,19 @@ function serializeNode(n2, options) {
|
|
|
1043
1089
|
cssCaptured = false
|
|
1044
1090
|
} = options;
|
|
1045
1091
|
const rootId = getRootId(doc, mirror2);
|
|
1046
|
-
const xPath = getXPath(n2);
|
|
1047
1092
|
switch (n2.nodeType) {
|
|
1048
1093
|
case n2.DOCUMENT_NODE:
|
|
1049
1094
|
if (n2.compatMode !== "CSS1Compat") {
|
|
1050
1095
|
return {
|
|
1051
1096
|
type: NodeType$3.Document,
|
|
1052
1097
|
childNodes: [],
|
|
1053
|
-
xPath,
|
|
1054
1098
|
compatMode: n2.compatMode
|
|
1055
1099
|
// probably "BackCompat"
|
|
1056
1100
|
};
|
|
1057
1101
|
} else {
|
|
1058
1102
|
return {
|
|
1059
1103
|
type: NodeType$3.Document,
|
|
1060
|
-
childNodes: []
|
|
1061
|
-
xPath
|
|
1104
|
+
childNodes: []
|
|
1062
1105
|
};
|
|
1063
1106
|
}
|
|
1064
1107
|
case n2.DOCUMENT_TYPE_NODE:
|
|
@@ -1067,8 +1110,7 @@ function serializeNode(n2, options) {
|
|
|
1067
1110
|
name: n2.name,
|
|
1068
1111
|
publicId: n2.publicId,
|
|
1069
1112
|
systemId: n2.systemId,
|
|
1070
|
-
rootId
|
|
1071
|
-
xPath
|
|
1113
|
+
rootId
|
|
1072
1114
|
};
|
|
1073
1115
|
case n2.ELEMENT_NODE:
|
|
1074
1116
|
return serializeElementNode(n2, {
|
|
@@ -1076,7 +1118,6 @@ function serializeNode(n2, options) {
|
|
|
1076
1118
|
blockClass,
|
|
1077
1119
|
blockSelector,
|
|
1078
1120
|
excludeAttribute,
|
|
1079
|
-
includeAttribute,
|
|
1080
1121
|
inlineStylesheet,
|
|
1081
1122
|
maskInputOptions,
|
|
1082
1123
|
maskInputFn,
|
|
@@ -1085,8 +1126,7 @@ function serializeNode(n2, options) {
|
|
|
1085
1126
|
recordCanvas,
|
|
1086
1127
|
keepIframeSrcFn,
|
|
1087
1128
|
newlyAddedElement,
|
|
1088
|
-
rootId
|
|
1089
|
-
xPath
|
|
1129
|
+
rootId
|
|
1090
1130
|
});
|
|
1091
1131
|
case n2.TEXT_NODE:
|
|
1092
1132
|
return serializeTextNode(n2, {
|
|
@@ -1094,22 +1134,19 @@ function serializeNode(n2, options) {
|
|
|
1094
1134
|
needsMask,
|
|
1095
1135
|
maskTextFn,
|
|
1096
1136
|
rootId,
|
|
1097
|
-
cssCaptured
|
|
1098
|
-
xPath
|
|
1137
|
+
cssCaptured
|
|
1099
1138
|
});
|
|
1100
1139
|
case n2.CDATA_SECTION_NODE:
|
|
1101
1140
|
return {
|
|
1102
1141
|
type: NodeType$3.CDATA,
|
|
1103
1142
|
textContent: "",
|
|
1104
|
-
rootId
|
|
1105
|
-
xPath
|
|
1143
|
+
rootId
|
|
1106
1144
|
};
|
|
1107
1145
|
case n2.COMMENT_NODE:
|
|
1108
1146
|
return {
|
|
1109
1147
|
type: NodeType$3.Comment,
|
|
1110
1148
|
textContent: index$1.textContent(n2) || "",
|
|
1111
|
-
rootId
|
|
1112
|
-
xPath
|
|
1149
|
+
rootId
|
|
1113
1150
|
};
|
|
1114
1151
|
default:
|
|
1115
1152
|
return false;
|
|
@@ -1121,7 +1158,7 @@ function getRootId(doc, mirror2) {
|
|
|
1121
1158
|
return docId === 1 ? void 0 : docId;
|
|
1122
1159
|
}
|
|
1123
1160
|
function serializeTextNode(n2, options) {
|
|
1124
|
-
const { needsMask, maskTextFn, rootId, cssCaptured
|
|
1161
|
+
const { needsMask, maskTextFn, rootId, cssCaptured } = options;
|
|
1125
1162
|
const parent = index$1.parentNode(n2);
|
|
1126
1163
|
const parentTagName = parent && parent.tagName;
|
|
1127
1164
|
let textContent2 = "";
|
|
@@ -1138,15 +1175,10 @@ function serializeTextNode(n2, options) {
|
|
|
1138
1175
|
if (!isStyle && !isScript && textContent2 && needsMask) {
|
|
1139
1176
|
textContent2 = maskTextFn ? maskTextFn(textContent2, index$1.parentElement(n2)) : textContent2.replace(/[\S]/g, "*");
|
|
1140
1177
|
}
|
|
1141
|
-
const isVisible = isTextVisible(n2);
|
|
1142
|
-
const isInteractive = isElementInteractive(n2);
|
|
1143
1178
|
return {
|
|
1144
1179
|
type: NodeType$3.Text,
|
|
1145
1180
|
textContent: textContent2 || "",
|
|
1146
|
-
rootId
|
|
1147
|
-
isVisible,
|
|
1148
|
-
isInteractive,
|
|
1149
|
-
xPath
|
|
1181
|
+
rootId
|
|
1150
1182
|
};
|
|
1151
1183
|
}
|
|
1152
1184
|
function serializeElementNode(n2, options) {
|
|
@@ -1155,7 +1187,6 @@ function serializeElementNode(n2, options) {
|
|
|
1155
1187
|
blockClass,
|
|
1156
1188
|
blockSelector,
|
|
1157
1189
|
excludeAttribute,
|
|
1158
|
-
includeAttribute,
|
|
1159
1190
|
inlineStylesheet,
|
|
1160
1191
|
maskInputOptions = {},
|
|
1161
1192
|
maskInputFn,
|
|
@@ -1164,8 +1195,7 @@ function serializeElementNode(n2, options) {
|
|
|
1164
1195
|
recordCanvas,
|
|
1165
1196
|
keepIframeSrcFn,
|
|
1166
1197
|
newlyAddedElement = false,
|
|
1167
|
-
rootId
|
|
1168
|
-
xPath
|
|
1198
|
+
rootId
|
|
1169
1199
|
} = options;
|
|
1170
1200
|
const needBlock = _isBlockedElement(n2, blockClass, blockSelector);
|
|
1171
1201
|
const tagName = getValidTagName$1(n2);
|
|
@@ -1173,7 +1203,7 @@ function serializeElementNode(n2, options) {
|
|
|
1173
1203
|
const len = n2.attributes.length;
|
|
1174
1204
|
for (let i2 = 0; i2 < len; i2++) {
|
|
1175
1205
|
const attr = n2.attributes[i2];
|
|
1176
|
-
if (isExcludeAttribute(attr.name, excludeAttribute)
|
|
1206
|
+
if (isExcludeAttribute(attr.name, excludeAttribute)) {
|
|
1177
1207
|
continue;
|
|
1178
1208
|
}
|
|
1179
1209
|
if (!ignoreAttribute(tagName, attr.name, attr.value)) {
|
|
@@ -1335,8 +1365,6 @@ function serializeElementNode(n2, options) {
|
|
|
1335
1365
|
if (customElements.get(tagName)) isCustomElement = true;
|
|
1336
1366
|
} catch (e2) {
|
|
1337
1367
|
}
|
|
1338
|
-
const isVisible = isElementVisible(n2);
|
|
1339
|
-
const isInteractive = isElementInteractive(n2);
|
|
1340
1368
|
return {
|
|
1341
1369
|
type: NodeType$3.Element,
|
|
1342
1370
|
tagName,
|
|
@@ -1345,10 +1373,7 @@ function serializeElementNode(n2, options) {
|
|
|
1345
1373
|
isSVG: isSVGElement(n2) || void 0,
|
|
1346
1374
|
needBlock,
|
|
1347
1375
|
rootId,
|
|
1348
|
-
isCustom: isCustomElement
|
|
1349
|
-
isVisible,
|
|
1350
|
-
isInteractive,
|
|
1351
|
-
xPath
|
|
1376
|
+
isCustom: isCustomElement
|
|
1352
1377
|
};
|
|
1353
1378
|
}
|
|
1354
1379
|
function lowerIfExists(maybeAttr) {
|
|
@@ -1399,7 +1424,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1399
1424
|
maskTextClass,
|
|
1400
1425
|
maskTextSelector,
|
|
1401
1426
|
excludeAttribute,
|
|
1402
|
-
includeAttribute,
|
|
1403
1427
|
skipChild = false,
|
|
1404
1428
|
inlineStylesheet = true,
|
|
1405
1429
|
maskInputOptions = {},
|
|
@@ -1435,7 +1459,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1435
1459
|
blockClass,
|
|
1436
1460
|
blockSelector,
|
|
1437
1461
|
excludeAttribute,
|
|
1438
|
-
includeAttribute,
|
|
1439
1462
|
needsMask,
|
|
1440
1463
|
inlineStylesheet,
|
|
1441
1464
|
maskInputOptions,
|
|
@@ -1461,6 +1484,22 @@ function serializeNodeWithId(n2, options) {
|
|
|
1461
1484
|
id = genId();
|
|
1462
1485
|
}
|
|
1463
1486
|
const serializedNode = Object.assign(_serializedNode, { id });
|
|
1487
|
+
if (isElement(n2) || n2.nodeType === Node.TEXT_NODE) {
|
|
1488
|
+
serializedNode.xpath = buildXPath(n2);
|
|
1489
|
+
if (isElement(n2)) {
|
|
1490
|
+
const selector = buildSelector(n2);
|
|
1491
|
+
if (selector) {
|
|
1492
|
+
serializedNode.selector = selector;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
if (n2.nodeType === Node.TEXT_NODE) {
|
|
1496
|
+
serializedNode.isVisible = isTextVisible(n2);
|
|
1497
|
+
}
|
|
1498
|
+
if (n2.nodeType === Node.ELEMENT_NODE) {
|
|
1499
|
+
serializedNode.isVisible = isElementVisible(n2);
|
|
1500
|
+
serializedNode.isInteractive = isElementInteractive(n2);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1464
1503
|
mirror2.add(n2, serializedNode);
|
|
1465
1504
|
if (id === IGNORED_NODE) {
|
|
1466
1505
|
return null;
|
|
@@ -1489,7 +1528,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1489
1528
|
maskTextClass,
|
|
1490
1529
|
maskTextSelector,
|
|
1491
1530
|
excludeAttribute,
|
|
1492
|
-
includeAttribute,
|
|
1493
1531
|
skipChild,
|
|
1494
1532
|
inlineStylesheet,
|
|
1495
1533
|
maskInputOptions,
|
|
@@ -1550,7 +1588,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1550
1588
|
maskTextClass,
|
|
1551
1589
|
maskTextSelector,
|
|
1552
1590
|
excludeAttribute,
|
|
1553
|
-
includeAttribute,
|
|
1554
1591
|
skipChild: false,
|
|
1555
1592
|
inlineStylesheet,
|
|
1556
1593
|
maskInputOptions,
|
|
@@ -1593,7 +1630,6 @@ function serializeNodeWithId(n2, options) {
|
|
|
1593
1630
|
maskTextClass,
|
|
1594
1631
|
maskTextSelector,
|
|
1595
1632
|
excludeAttribute,
|
|
1596
|
-
includeAttribute,
|
|
1597
1633
|
skipChild: false,
|
|
1598
1634
|
inlineStylesheet,
|
|
1599
1635
|
maskInputOptions,
|
|
@@ -1631,8 +1667,7 @@ function snapshot(n2, options) {
|
|
|
1631
1667
|
blockSelector = null,
|
|
1632
1668
|
maskTextClass = "rr-mask",
|
|
1633
1669
|
maskTextSelector = null,
|
|
1634
|
-
excludeAttribute =
|
|
1635
|
-
includeAttribute = /.+/i,
|
|
1670
|
+
excludeAttribute = /.^/,
|
|
1636
1671
|
inlineStylesheet = true,
|
|
1637
1672
|
inlineImages = false,
|
|
1638
1673
|
recordCanvas = false,
|
|
@@ -1693,7 +1728,6 @@ function snapshot(n2, options) {
|
|
|
1693
1728
|
maskTextClass,
|
|
1694
1729
|
maskTextSelector,
|
|
1695
1730
|
excludeAttribute,
|
|
1696
|
-
includeAttribute,
|
|
1697
1731
|
skipChild: false,
|
|
1698
1732
|
inlineStylesheet,
|
|
1699
1733
|
maskInputOptions,
|
|
@@ -10832,6 +10866,41 @@ function patch(source, name, replacement) {
|
|
|
10832
10866
|
};
|
|
10833
10867
|
}
|
|
10834
10868
|
}
|
|
10869
|
+
function describeNode(el) {
|
|
10870
|
+
const tag = el.tagName.toLowerCase();
|
|
10871
|
+
const id = el.id ? `#${el.id}` : "";
|
|
10872
|
+
const classes = el.classList.length ? "." + Array.from(el.classList).join(".") : "";
|
|
10873
|
+
return `${tag}${id}${classes}`;
|
|
10874
|
+
}
|
|
10875
|
+
function getElementVisibility(el) {
|
|
10876
|
+
var _a2, _b;
|
|
10877
|
+
const win = ((_a2 = el.ownerDocument) == null ? void 0 : _a2.defaultView) ?? window;
|
|
10878
|
+
const rect = el.getBoundingClientRect();
|
|
10879
|
+
const viewportWidth = win.innerWidth || win.document.documentElement.clientWidth || 0;
|
|
10880
|
+
const viewportHeight = win.innerHeight || win.document.documentElement.clientHeight || 0;
|
|
10881
|
+
const isRectVisible = rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth;
|
|
10882
|
+
const style = (_b = win.getComputedStyle) == null ? void 0 : _b.call(win, el);
|
|
10883
|
+
const isStyleVisible2 = !!style && style.display !== "none" && style.visibility !== "hidden" && (parseFloat(style.opacity) || 0) > 0;
|
|
10884
|
+
const isVisible = isStyleVisible2 && isRectVisible;
|
|
10885
|
+
let ratio = 0;
|
|
10886
|
+
if (isVisible) {
|
|
10887
|
+
const xOverlap = Math.max(
|
|
10888
|
+
0,
|
|
10889
|
+
Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0)
|
|
10890
|
+
);
|
|
10891
|
+
const yOverlap = Math.max(
|
|
10892
|
+
0,
|
|
10893
|
+
Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0)
|
|
10894
|
+
);
|
|
10895
|
+
const intersectionArea = xOverlap * yOverlap;
|
|
10896
|
+
const elementArea = rect.width * rect.height;
|
|
10897
|
+
ratio = elementArea > 0 ? intersectionArea / elementArea : 0;
|
|
10898
|
+
}
|
|
10899
|
+
return {
|
|
10900
|
+
isVisible,
|
|
10901
|
+
ratio
|
|
10902
|
+
};
|
|
10903
|
+
}
|
|
10835
10904
|
const index = {
|
|
10836
10905
|
childNodes,
|
|
10837
10906
|
parentNode,
|
|
@@ -10845,7 +10914,9 @@ const index = {
|
|
|
10845
10914
|
querySelector,
|
|
10846
10915
|
querySelectorAll,
|
|
10847
10916
|
mutationObserver: mutationObserverCtor,
|
|
10848
|
-
patch
|
|
10917
|
+
patch,
|
|
10918
|
+
describeNode,
|
|
10919
|
+
getElementVisibility
|
|
10849
10920
|
};
|
|
10850
10921
|
function on(type, fn, target = document) {
|
|
10851
10922
|
const options = { capture: true, passive: true };
|
|
@@ -11246,6 +11317,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
|
|
|
11246
11317
|
IncrementalSource2[IncrementalSource2["Selection"] = 14] = "Selection";
|
|
11247
11318
|
IncrementalSource2[IncrementalSource2["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
|
|
11248
11319
|
IncrementalSource2[IncrementalSource2["CustomElement"] = 16] = "CustomElement";
|
|
11320
|
+
IncrementalSource2[IncrementalSource2["VisibilityMutation"] = 17] = "VisibilityMutation";
|
|
11249
11321
|
return IncrementalSource2;
|
|
11250
11322
|
})(IncrementalSource || {});
|
|
11251
11323
|
var MouseInteractions = /* @__PURE__ */ ((MouseInteractions2) => {
|
|
@@ -11406,11 +11478,11 @@ class MutationBuffer {
|
|
|
11406
11478
|
* the browser MutationObserver emits multiple mutations after
|
|
11407
11479
|
* a delay for performance reasons, making tracing added nodes hard
|
|
11408
11480
|
* in our `processMutations` callback function.
|
|
11409
|
-
* For example, if we append an element el_1 into body
|
|
11481
|
+
* For example, if we append an element el_1 into body and then append
|
|
11410
11482
|
* another element el_2 into el_1, these two mutations may be passed to the
|
|
11411
11483
|
* callback function together when the two operations were done.
|
|
11412
|
-
* Generally we need to trace child nodes of newly added nodes, but in this
|
|
11413
|
-
* case if we count el_2 as el_1's child node in the first mutation record,
|
|
11484
|
+
* Generally, we need to trace child nodes of newly added nodes, but in this
|
|
11485
|
+
* case, if we count el_2 as el_1's child node in the first mutation record,
|
|
11414
11486
|
* then we will count el_2 again in the second mutation record which was
|
|
11415
11487
|
* duplicated.
|
|
11416
11488
|
* To avoid of duplicate counting added nodes, we use a Set to store
|
|
@@ -11429,7 +11501,6 @@ class MutationBuffer {
|
|
|
11429
11501
|
__publicField(this, "maskTextClass");
|
|
11430
11502
|
__publicField(this, "maskTextSelector");
|
|
11431
11503
|
__publicField(this, "excludeAttribute");
|
|
11432
|
-
__publicField(this, "includeAttribute");
|
|
11433
11504
|
__publicField(this, "inlineStylesheet");
|
|
11434
11505
|
__publicField(this, "maskInputOptions");
|
|
11435
11506
|
__publicField(this, "maskTextFn");
|
|
@@ -11445,6 +11516,7 @@ class MutationBuffer {
|
|
|
11445
11516
|
__publicField(this, "stylesheetManager");
|
|
11446
11517
|
__publicField(this, "shadowDomManager");
|
|
11447
11518
|
__publicField(this, "canvasManager");
|
|
11519
|
+
__publicField(this, "visibilityManager");
|
|
11448
11520
|
__publicField(this, "processedNodeManager");
|
|
11449
11521
|
__publicField(this, "unattachedDoc");
|
|
11450
11522
|
__publicField(this, "processMutations", (mutations) => {
|
|
@@ -11494,7 +11566,6 @@ class MutationBuffer {
|
|
|
11494
11566
|
maskTextClass: this.maskTextClass,
|
|
11495
11567
|
maskTextSelector: this.maskTextSelector,
|
|
11496
11568
|
excludeAttribute: this.excludeAttribute,
|
|
11497
|
-
includeAttribute: this.includeAttribute,
|
|
11498
11569
|
skipChild: true,
|
|
11499
11570
|
newlyAddedElement: true,
|
|
11500
11571
|
inlineStylesheet: this.inlineStylesheet,
|
|
@@ -11540,7 +11611,8 @@ class MutationBuffer {
|
|
|
11540
11611
|
this.mirror.removeNodeFromMap(this.mapRemoves.shift());
|
|
11541
11612
|
}
|
|
11542
11613
|
for (const n2 of this.movedSet) {
|
|
11543
|
-
if (isParentRemoved(this.removesSubTreeCache, n2, this.mirror) &&
|
|
11614
|
+
if (isParentRemoved(this.removesSubTreeCache, n2, this.mirror) && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
11615
|
+
!this.movedSet.has(index.parentNode(n2))) {
|
|
11544
11616
|
continue;
|
|
11545
11617
|
}
|
|
11546
11618
|
pushAdd(n2);
|
|
@@ -11696,12 +11768,60 @@ class MutationBuffer {
|
|
|
11696
11768
|
const target = m.target;
|
|
11697
11769
|
let attributeName = m.attributeName;
|
|
11698
11770
|
let value = m.target.getAttribute(attributeName);
|
|
11699
|
-
const
|
|
11700
|
-
const
|
|
11771
|
+
const attrKey = attributeName;
|
|
11772
|
+
const propValue = target[attrKey];
|
|
11773
|
+
const isBooleanAttr = typeof propValue === "boolean";
|
|
11774
|
+
const inDOM = document.contains(target);
|
|
11775
|
+
const isVisible = isElementVisible(target);
|
|
11776
|
+
const isExcludeAttributeName = isExcludeAttribute(attributeName, this.excludeAttribute);
|
|
11777
|
+
const isPhantomAttributeMutation = value === null && // текущего атрибута нет
|
|
11778
|
+
!target.hasAttribute(attributeName) && // явно подтверждаем отсутствие
|
|
11779
|
+
m.oldValue !== null && // раньше он был
|
|
11780
|
+
(propValue === "" || // свойство = пустая строка
|
|
11781
|
+
propValue === null || // или null
|
|
11782
|
+
typeof propValue === "undefined");
|
|
11701
11783
|
if (isPhantomAttributeMutation) {
|
|
11784
|
+
console.debug(
|
|
11785
|
+
`[${nowTimestamp()}] [rrweb:record/mutation] ⛔ phantom attribute mutation ignored`,
|
|
11786
|
+
{
|
|
11787
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call
|
|
11788
|
+
node: index.describeNode(target),
|
|
11789
|
+
tag: target.tagName,
|
|
11790
|
+
nodeType: target.nodeType,
|
|
11791
|
+
attribute: attributeName,
|
|
11792
|
+
value,
|
|
11793
|
+
oldValue: m.oldValue,
|
|
11794
|
+
excludeAttribute: this.excludeAttribute,
|
|
11795
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
11796
|
+
propValue,
|
|
11797
|
+
isBooleanAttr,
|
|
11798
|
+
inDOM,
|
|
11799
|
+
isVisible,
|
|
11800
|
+
isExcludeAttributeName
|
|
11801
|
+
}
|
|
11802
|
+
);
|
|
11702
11803
|
return;
|
|
11703
11804
|
}
|
|
11704
11805
|
if (isExcludeAttribute(attributeName, this.excludeAttribute)) {
|
|
11806
|
+
console.debug(
|
|
11807
|
+
`[${nowTimestamp()}] [rrweb:record/mutation] ⛔ excluded attribute mutation ignored`,
|
|
11808
|
+
{
|
|
11809
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call
|
|
11810
|
+
node: index.describeNode(target),
|
|
11811
|
+
tag: target.tagName,
|
|
11812
|
+
nodeType: target.nodeType,
|
|
11813
|
+
attribute: attributeName,
|
|
11814
|
+
value,
|
|
11815
|
+
oldValue: m.oldValue,
|
|
11816
|
+
excludeAttribute: this.excludeAttribute,
|
|
11817
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
11818
|
+
propValue,
|
|
11819
|
+
isBooleanAttr,
|
|
11820
|
+
inDOM,
|
|
11821
|
+
isVisible,
|
|
11822
|
+
isExcludeAttributeName
|
|
11823
|
+
}
|
|
11824
|
+
);
|
|
11705
11825
|
return;
|
|
11706
11826
|
}
|
|
11707
11827
|
if (attributeName === "value") {
|
|
@@ -11746,9 +11866,35 @@ class MutationBuffer {
|
|
|
11746
11866
|
toLowerCase(attributeName),
|
|
11747
11867
|
value
|
|
11748
11868
|
);
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11869
|
+
const isSuspiciousClassMutation = attributeName !== "class" && (m.oldValue === null || // ранее не было класса
|
|
11870
|
+
value === "" || // класс удалён
|
|
11871
|
+
value !== m.oldValue);
|
|
11872
|
+
if (isSuspiciousClassMutation) {
|
|
11873
|
+
console.debug(
|
|
11874
|
+
`[${nowTimestamp()}] [rrweb:record/mutation] ⚠️ suspicious attribute mutation`,
|
|
11875
|
+
{
|
|
11876
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call
|
|
11877
|
+
reason: [
|
|
11878
|
+
value === m.oldValue ? "no change in value" : null,
|
|
11879
|
+
value === propValue ? "mirrored in DOM property" : null,
|
|
11880
|
+
value === item.attributes[attributeName] ? "redundant assignment" : null
|
|
11881
|
+
].filter(Boolean).join(", ") || "uncategorized",
|
|
11882
|
+
node: index.describeNode(target),
|
|
11883
|
+
tag: target.tagName,
|
|
11884
|
+
nodeType: target.nodeType,
|
|
11885
|
+
attribute: attributeName,
|
|
11886
|
+
value,
|
|
11887
|
+
oldValue: m.oldValue,
|
|
11888
|
+
transformedValue: item.attributes[attributeName],
|
|
11889
|
+
excludeAttribute: this.excludeAttribute,
|
|
11890
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
11891
|
+
propValue,
|
|
11892
|
+
isBooleanAttr,
|
|
11893
|
+
inDOM,
|
|
11894
|
+
isVisible,
|
|
11895
|
+
isExcludeAttributeName
|
|
11896
|
+
}
|
|
11897
|
+
);
|
|
11752
11898
|
}
|
|
11753
11899
|
if (attributeName === "style") {
|
|
11754
11900
|
if (!this.unattachedDoc) {
|
|
@@ -11866,7 +12012,6 @@ class MutationBuffer {
|
|
|
11866
12012
|
"maskTextClass",
|
|
11867
12013
|
"maskTextSelector",
|
|
11868
12014
|
"excludeAttribute",
|
|
11869
|
-
"includeAttribute",
|
|
11870
12015
|
"inlineStylesheet",
|
|
11871
12016
|
"maskInputOptions",
|
|
11872
12017
|
"maskTextFn",
|
|
@@ -11882,6 +12027,7 @@ class MutationBuffer {
|
|
|
11882
12027
|
"stylesheetManager",
|
|
11883
12028
|
"shadowDomManager",
|
|
11884
12029
|
"canvasManager",
|
|
12030
|
+
"visibilityManager",
|
|
11885
12031
|
"processedNodeManager"
|
|
11886
12032
|
].forEach((key) => {
|
|
11887
12033
|
this[key] = options[key];
|
|
@@ -11890,10 +12036,12 @@ class MutationBuffer {
|
|
|
11890
12036
|
freeze() {
|
|
11891
12037
|
this.frozen = true;
|
|
11892
12038
|
this.canvasManager.freeze();
|
|
12039
|
+
this.visibilityManager.freeze();
|
|
11893
12040
|
}
|
|
11894
12041
|
unfreeze() {
|
|
11895
12042
|
this.frozen = false;
|
|
11896
12043
|
this.canvasManager.unfreeze();
|
|
12044
|
+
this.visibilityManager.unfreeze();
|
|
11897
12045
|
this.emit();
|
|
11898
12046
|
}
|
|
11899
12047
|
isFrozen() {
|
|
@@ -11902,15 +12050,18 @@ class MutationBuffer {
|
|
|
11902
12050
|
lock() {
|
|
11903
12051
|
this.locked = true;
|
|
11904
12052
|
this.canvasManager.lock();
|
|
12053
|
+
this.visibilityManager.lock();
|
|
11905
12054
|
}
|
|
11906
12055
|
unlock() {
|
|
11907
12056
|
this.locked = false;
|
|
11908
12057
|
this.canvasManager.unlock();
|
|
12058
|
+
this.visibilityManager.unlock();
|
|
11909
12059
|
this.emit();
|
|
11910
12060
|
}
|
|
11911
12061
|
reset() {
|
|
11912
12062
|
this.shadowDomManager.reset();
|
|
11913
12063
|
this.canvasManager.reset();
|
|
12064
|
+
this.visibilityManager.reset();
|
|
11914
12065
|
}
|
|
11915
12066
|
}
|
|
11916
12067
|
function deepDelete(addsSet, n2) {
|
|
@@ -12844,6 +12995,7 @@ function mergeHooks(o2, hooks) {
|
|
|
12844
12995
|
styleSheetRuleCb,
|
|
12845
12996
|
styleDeclarationCb,
|
|
12846
12997
|
canvasMutationCb,
|
|
12998
|
+
visibilityMutationCb,
|
|
12847
12999
|
fontCb,
|
|
12848
13000
|
selectionCb,
|
|
12849
13001
|
customElementCb
|
|
@@ -12908,6 +13060,12 @@ function mergeHooks(o2, hooks) {
|
|
|
12908
13060
|
}
|
|
12909
13061
|
canvasMutationCb(...p);
|
|
12910
13062
|
};
|
|
13063
|
+
o2.visibilityMutationCb = (...p) => {
|
|
13064
|
+
if (hooks.visibilityMutation) {
|
|
13065
|
+
hooks.visibilityMutation(...p);
|
|
13066
|
+
}
|
|
13067
|
+
visibilityMutationCb(...p);
|
|
13068
|
+
};
|
|
12911
13069
|
o2.fontCb = (...p) => {
|
|
12912
13070
|
if (hooks.font) {
|
|
12913
13071
|
hooks.font(...p);
|
|
@@ -14041,11 +14199,249 @@ class ProcessedNodeManager {
|
|
|
14041
14199
|
destroy() {
|
|
14042
14200
|
}
|
|
14043
14201
|
}
|
|
14202
|
+
function computeVisibility(elements, previous, options) {
|
|
14203
|
+
const root2 = (options == null ? void 0 : options.root) ?? null;
|
|
14204
|
+
const threshold = (options == null ? void 0 : options.threshold) ?? 0.5;
|
|
14205
|
+
const sensitivity = (options == null ? void 0 : options.sensitivity) ?? 0.05;
|
|
14206
|
+
const rootMarginFn = parseRootMargin((options == null ? void 0 : options.rootMargin) ?? "0px");
|
|
14207
|
+
const current = /* @__PURE__ */ new Map();
|
|
14208
|
+
const rootRect = getRootRect(root2);
|
|
14209
|
+
const expandedRoot = expandRootRect(rootRect, rootMarginFn);
|
|
14210
|
+
for (const el of elements) {
|
|
14211
|
+
const elRect = el.getBoundingClientRect();
|
|
14212
|
+
let intersectionRect = emptyRect();
|
|
14213
|
+
let intersectionRatio = 0;
|
|
14214
|
+
if (elRect.width > 0 && elRect.height > 0) {
|
|
14215
|
+
intersectionRect = computeIntersectionRect(elRect, expandedRoot);
|
|
14216
|
+
intersectionRatio = computeIntersectionRatio(elRect, intersectionRect);
|
|
14217
|
+
intersectionRatio = Math.round(intersectionRatio * 100) / 100;
|
|
14218
|
+
}
|
|
14219
|
+
const isStyle = isStyleVisible(el);
|
|
14220
|
+
const old = previous.get(el) ?? null;
|
|
14221
|
+
const prevRatio = (old == null ? void 0 : old.intersectionRatio) ?? 0;
|
|
14222
|
+
const currRatio = intersectionRatio;
|
|
14223
|
+
const wasVisible = (old == null ? void 0 : old.isStyleVisible) && prevRatio > threshold;
|
|
14224
|
+
const nowVisible = isStyle && currRatio > threshold;
|
|
14225
|
+
const changed = !old || wasVisible !== nowVisible || wasVisible !== nowVisible && Math.abs(currRatio - prevRatio) > sensitivity;
|
|
14226
|
+
if (changed) {
|
|
14227
|
+
current.set(el, {
|
|
14228
|
+
target: el,
|
|
14229
|
+
isVisible: nowVisible,
|
|
14230
|
+
isStyleVisible: isStyle,
|
|
14231
|
+
intersectionRatio: currRatio,
|
|
14232
|
+
intersectionRect,
|
|
14233
|
+
oldValue: old
|
|
14234
|
+
});
|
|
14235
|
+
} else {
|
|
14236
|
+
current.set(el, old);
|
|
14237
|
+
}
|
|
14238
|
+
}
|
|
14239
|
+
return current;
|
|
14240
|
+
}
|
|
14241
|
+
function parseRootMargin(marginStr) {
|
|
14242
|
+
const parts = marginStr.trim().split(/\s+/);
|
|
14243
|
+
const getValue = (val, size) => val.endsWith("%") ? parseFloat(val) / 100 * size : parseFloat(val) || 0;
|
|
14244
|
+
return function(rootRect) {
|
|
14245
|
+
const top = getValue(parts[0] || "0px", rootRect.height);
|
|
14246
|
+
const right = getValue(parts[1] || parts[0] || "0px", rootRect.width);
|
|
14247
|
+
const bottom = getValue(parts[2] || parts[0] || "0px", rootRect.height);
|
|
14248
|
+
const left = getValue(parts[3] || parts[1] || parts[0] || "0px", rootRect.width);
|
|
14249
|
+
return { top, right, bottom, left, width: 0, height: 0 };
|
|
14250
|
+
};
|
|
14251
|
+
}
|
|
14252
|
+
function getRootRect(root2) {
|
|
14253
|
+
return root2 ? root2.getBoundingClientRect() : new DOMRect(0, 0, window.innerWidth, window.innerHeight);
|
|
14254
|
+
}
|
|
14255
|
+
function expandRootRect(rect, marginFn) {
|
|
14256
|
+
const margin = marginFn(rect);
|
|
14257
|
+
return new DOMRect(
|
|
14258
|
+
rect.left - margin.left,
|
|
14259
|
+
rect.top - margin.top,
|
|
14260
|
+
rect.width + margin.left + margin.right,
|
|
14261
|
+
rect.height + margin.top + margin.bottom
|
|
14262
|
+
);
|
|
14263
|
+
}
|
|
14264
|
+
function computeIntersectionRect(a2, b) {
|
|
14265
|
+
const top = Math.max(a2.top, b.top);
|
|
14266
|
+
const left = Math.max(a2.left, b.left);
|
|
14267
|
+
const bottom = Math.min(a2.bottom, b.bottom);
|
|
14268
|
+
const right = Math.min(a2.right, b.right);
|
|
14269
|
+
const width = Math.max(0, right - left);
|
|
14270
|
+
const height = Math.max(0, bottom - top);
|
|
14271
|
+
return { top, left, bottom, right, width, height };
|
|
14272
|
+
}
|
|
14273
|
+
function computeIntersectionRatio(elRect, intersectionRect) {
|
|
14274
|
+
const elArea = elRect.width * elRect.height;
|
|
14275
|
+
const intArea = intersectionRect.width * intersectionRect.height;
|
|
14276
|
+
return elArea > 0 ? intArea / elArea : 0;
|
|
14277
|
+
}
|
|
14278
|
+
function emptyRect() {
|
|
14279
|
+
return { top: 0, left: 0, right: 0, bottom: 0, width: 0, height: 0 };
|
|
14280
|
+
}
|
|
14281
|
+
function isStyleVisible(el) {
|
|
14282
|
+
const style = getComputedStyle(el);
|
|
14283
|
+
return style && style.display !== "none" && style.visibility !== "hidden" && parseFloat(style.opacity || "1") > 0;
|
|
14284
|
+
}
|
|
14285
|
+
class VisibilityManager {
|
|
14286
|
+
constructor(options) {
|
|
14287
|
+
__publicField(this, "frozen", false);
|
|
14288
|
+
__publicField(this, "locked", false);
|
|
14289
|
+
__publicField(this, "pending", /* @__PURE__ */ new Map());
|
|
14290
|
+
__publicField(this, "mirror");
|
|
14291
|
+
__publicField(this, "mutationCb");
|
|
14292
|
+
__publicField(this, "rafId", null);
|
|
14293
|
+
__publicField(this, "rafThrottle");
|
|
14294
|
+
__publicField(this, "lastFlushTime", 0);
|
|
14295
|
+
__publicField(this, "elements", /* @__PURE__ */ new Set());
|
|
14296
|
+
__publicField(this, "previousState", /* @__PURE__ */ new Map());
|
|
14297
|
+
__publicField(this, "root", null);
|
|
14298
|
+
__publicField(this, "threshold");
|
|
14299
|
+
__publicField(this, "sensitivity");
|
|
14300
|
+
__publicField(this, "rootMargin");
|
|
14301
|
+
__publicField(this, "hasInitialized", false);
|
|
14302
|
+
__publicField(this, "mode", "none");
|
|
14303
|
+
__publicField(this, "debounce", 50);
|
|
14304
|
+
__publicField(this, "throttle", 100);
|
|
14305
|
+
__publicField(this, "buffer", /* @__PURE__ */ new Map());
|
|
14306
|
+
__publicField(this, "debounceTimer", null);
|
|
14307
|
+
__publicField(this, "lastThrottleTime", 0);
|
|
14308
|
+
__publicField(this, "disabled", false);
|
|
14309
|
+
__publicField(this, "notifyActivity");
|
|
14310
|
+
const { doc, mirror: mirror2, sampling, mutationCb, notifyActivity } = options;
|
|
14311
|
+
this.mirror = mirror2;
|
|
14312
|
+
this.mutationCb = mutationCb;
|
|
14313
|
+
this.notifyActivity = notifyActivity;
|
|
14314
|
+
this.rootMargin = "0px";
|
|
14315
|
+
if (sampling === false) {
|
|
14316
|
+
this.disabled = true;
|
|
14317
|
+
return;
|
|
14318
|
+
}
|
|
14319
|
+
const visibilitySampling = typeof sampling === "object" && sampling !== null ? sampling : {};
|
|
14320
|
+
this.mode = (visibilitySampling == null ? void 0 : visibilitySampling.mode) ?? "none";
|
|
14321
|
+
this.debounce = Number((visibilitySampling == null ? void 0 : visibilitySampling.debounce) ?? 100);
|
|
14322
|
+
this.throttle = Number((visibilitySampling == null ? void 0 : visibilitySampling.throttle) ?? 100);
|
|
14323
|
+
this.threshold = Number((visibilitySampling == null ? void 0 : visibilitySampling.threshold) ?? 0.5);
|
|
14324
|
+
this.sensitivity = Number((visibilitySampling == null ? void 0 : visibilitySampling.sensitivity) ?? 0.05);
|
|
14325
|
+
this.rafThrottle = Number((visibilitySampling == null ? void 0 : visibilitySampling.rafThrottle) ?? 100);
|
|
14326
|
+
doc.querySelectorAll("*").forEach((el) => this.observe(el));
|
|
14327
|
+
const mo = new MutationObserver((mutations) => {
|
|
14328
|
+
mutations.forEach((m) => {
|
|
14329
|
+
m.addedNodes.forEach((n2) => {
|
|
14330
|
+
if (n2.nodeType === Node.ELEMENT_NODE) {
|
|
14331
|
+
this.observe(n2);
|
|
14332
|
+
n2.querySelectorAll("*").forEach((el) => this.observe(el));
|
|
14333
|
+
}
|
|
14334
|
+
});
|
|
14335
|
+
m.removedNodes.forEach((n2) => {
|
|
14336
|
+
if (n2.nodeType === Node.ELEMENT_NODE) {
|
|
14337
|
+
this.unobserve(n2);
|
|
14338
|
+
}
|
|
14339
|
+
});
|
|
14340
|
+
});
|
|
14341
|
+
});
|
|
14342
|
+
mo.observe(doc.body, { childList: true, subtree: true });
|
|
14343
|
+
this.startPendingFlushLoop();
|
|
14344
|
+
}
|
|
14345
|
+
startPendingFlushLoop() {
|
|
14346
|
+
if (this.disabled) return;
|
|
14347
|
+
const loop = (timestamp) => {
|
|
14348
|
+
if (timestamp - this.lastFlushTime >= this.rafThrottle) {
|
|
14349
|
+
this.lastFlushTime = timestamp;
|
|
14350
|
+
this.flushPendingVisibilityMutations();
|
|
14351
|
+
}
|
|
14352
|
+
this.rafId = requestAnimationFrame(loop);
|
|
14353
|
+
};
|
|
14354
|
+
this.rafId = requestAnimationFrame(loop);
|
|
14355
|
+
}
|
|
14356
|
+
flushPendingVisibilityMutations() {
|
|
14357
|
+
if (this.disabled) return;
|
|
14358
|
+
if (this.frozen || this.locked || this.elements.size === 0) return;
|
|
14359
|
+
const state = computeVisibility(this.elements, this.previousState, {
|
|
14360
|
+
root: this.root,
|
|
14361
|
+
threshold: this.threshold,
|
|
14362
|
+
sensitivity: this.sensitivity,
|
|
14363
|
+
rootMargin: this.rootMargin
|
|
14364
|
+
});
|
|
14365
|
+
for (const [el, entry] of state.entries()) {
|
|
14366
|
+
const old = this.previousState.get(el);
|
|
14367
|
+
const changed = !old || old.isVisible !== entry.isVisible || Math.abs(old.intersectionRatio - entry.intersectionRatio) > this.sensitivity;
|
|
14368
|
+
if (changed) {
|
|
14369
|
+
const id = this.mirror.getId(el);
|
|
14370
|
+
if (id !== -1) {
|
|
14371
|
+
this.buffer.set(el, {
|
|
14372
|
+
id,
|
|
14373
|
+
isVisible: entry.isVisible,
|
|
14374
|
+
ratio: entry.intersectionRatio
|
|
14375
|
+
});
|
|
14376
|
+
}
|
|
14377
|
+
this.previousState.set(el, entry);
|
|
14378
|
+
}
|
|
14379
|
+
}
|
|
14380
|
+
this.previousState = state;
|
|
14381
|
+
if (!this.hasInitialized) {
|
|
14382
|
+
this.hasInitialized = true;
|
|
14383
|
+
this.buffer.clear();
|
|
14384
|
+
return;
|
|
14385
|
+
}
|
|
14386
|
+
this.scheduleEmit();
|
|
14387
|
+
}
|
|
14388
|
+
scheduleEmit() {
|
|
14389
|
+
if (this.mode === "debounce") {
|
|
14390
|
+
clearTimeout(this.debounceTimer);
|
|
14391
|
+
this.debounceTimer = setTimeout(() => this.flushBuffer(), this.debounce);
|
|
14392
|
+
} else if (this.mode === "throttle") {
|
|
14393
|
+
const now = performance.now();
|
|
14394
|
+
if (now - this.lastThrottleTime >= this.throttle) {
|
|
14395
|
+
this.lastThrottleTime = now;
|
|
14396
|
+
this.flushBuffer();
|
|
14397
|
+
}
|
|
14398
|
+
} else {
|
|
14399
|
+
this.flushBuffer();
|
|
14400
|
+
}
|
|
14401
|
+
}
|
|
14402
|
+
flushBuffer() {
|
|
14403
|
+
var _a2;
|
|
14404
|
+
if (this.buffer.size === 0) return;
|
|
14405
|
+
(_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, this.buffer.size);
|
|
14406
|
+
this.mutationCb({ mutations: Array.from(this.buffer.values()) });
|
|
14407
|
+
this.buffer.clear();
|
|
14408
|
+
}
|
|
14409
|
+
observe(el) {
|
|
14410
|
+
if (this.disabled) return;
|
|
14411
|
+
this.elements.add(el);
|
|
14412
|
+
}
|
|
14413
|
+
unobserve(el) {
|
|
14414
|
+
if (this.disabled) return;
|
|
14415
|
+
this.elements.delete(el);
|
|
14416
|
+
this.previousState.delete(el);
|
|
14417
|
+
this.pending.delete(el);
|
|
14418
|
+
}
|
|
14419
|
+
freeze() {
|
|
14420
|
+
this.frozen = true;
|
|
14421
|
+
}
|
|
14422
|
+
unfreeze() {
|
|
14423
|
+
this.frozen = false;
|
|
14424
|
+
}
|
|
14425
|
+
lock() {
|
|
14426
|
+
this.locked = true;
|
|
14427
|
+
}
|
|
14428
|
+
unlock() {
|
|
14429
|
+
this.locked = false;
|
|
14430
|
+
}
|
|
14431
|
+
reset() {
|
|
14432
|
+
this.elements.clear();
|
|
14433
|
+
this.previousState.clear();
|
|
14434
|
+
this.pending.clear();
|
|
14435
|
+
if (this.rafId) cancelAnimationFrame(this.rafId);
|
|
14436
|
+
}
|
|
14437
|
+
}
|
|
14044
14438
|
let wrappedEmit;
|
|
14045
14439
|
let takeFullSnapshot$1;
|
|
14046
14440
|
let canvasManager;
|
|
14441
|
+
let visibilityManager;
|
|
14047
14442
|
let recording = false;
|
|
14048
|
-
const
|
|
14443
|
+
const customEventQueue = [];
|
|
14444
|
+
let flushCustomEventQueue;
|
|
14049
14445
|
try {
|
|
14050
14446
|
if (Array.from([1], (x2) => x2 * 2)[0] !== 2) {
|
|
14051
14447
|
const cleanFrame = document.createElement("iframe");
|
|
@@ -14062,12 +14458,12 @@ function record(options = {}) {
|
|
|
14062
14458
|
emit,
|
|
14063
14459
|
checkoutEveryNms,
|
|
14064
14460
|
checkoutEveryNth,
|
|
14461
|
+
checkoutEveryNvm,
|
|
14065
14462
|
blockClass = "rr-block",
|
|
14066
14463
|
blockSelector = null,
|
|
14067
14464
|
ignoreClass = "rr-ignore",
|
|
14068
14465
|
ignoreSelector = null,
|
|
14069
14466
|
excludeAttribute: _excludeAttribute,
|
|
14070
|
-
includeAttribute: _includeAttribute,
|
|
14071
14467
|
maskTextClass = "rr-mask",
|
|
14072
14468
|
maskTextSelector = null,
|
|
14073
14469
|
inlineStylesheet = true,
|
|
@@ -14085,7 +14481,7 @@ function record(options = {}) {
|
|
|
14085
14481
|
recordCanvas = false,
|
|
14086
14482
|
recordCrossOriginIframes = false,
|
|
14087
14483
|
recordAfter = options.recordAfter === "DOMContentLoaded" ? options.recordAfter : "load",
|
|
14088
|
-
|
|
14484
|
+
flushCustomEvent = options.flushCustomEvent !== void 0 ? options.flushCustomEvent : "after",
|
|
14089
14485
|
userTriggeredOnInput = false,
|
|
14090
14486
|
collectFonts = false,
|
|
14091
14487
|
inlineImages = false,
|
|
@@ -14117,8 +14513,7 @@ function record(options = {}) {
|
|
|
14117
14513
|
sampling.mousemove = mousemoveWait;
|
|
14118
14514
|
}
|
|
14119
14515
|
mirror.reset();
|
|
14120
|
-
const excludeAttribute = _excludeAttribute === void 0 ?
|
|
14121
|
-
const includeAttribute = _includeAttribute === void 0 ? /.+/i : _includeAttribute;
|
|
14516
|
+
const excludeAttribute = _excludeAttribute === void 0 ? /.^/ : _excludeAttribute;
|
|
14122
14517
|
const maskInputOptions = maskAllInputs === true ? {
|
|
14123
14518
|
color: true,
|
|
14124
14519
|
date: true,
|
|
@@ -14155,6 +14550,10 @@ function record(options = {}) {
|
|
|
14155
14550
|
polyfill$1();
|
|
14156
14551
|
let lastFullSnapshotEvent;
|
|
14157
14552
|
let incrementalSnapshotCount = 0;
|
|
14553
|
+
let recentVisibilityChanges = 0;
|
|
14554
|
+
const onVisibilityActivity = (count) => {
|
|
14555
|
+
recentVisibilityChanges += count;
|
|
14556
|
+
};
|
|
14158
14557
|
const eventProcessor = (e2) => {
|
|
14159
14558
|
for (const plugin3 of plugins || []) {
|
|
14160
14559
|
if (plugin3.eventProcessor) {
|
|
@@ -14195,7 +14594,11 @@ function record(options = {}) {
|
|
|
14195
14594
|
incrementalSnapshotCount++;
|
|
14196
14595
|
const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
|
|
14197
14596
|
const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
|
|
14198
|
-
|
|
14597
|
+
const exceedVisibility = checkoutEveryNvm && recentVisibilityChanges >= checkoutEveryNvm;
|
|
14598
|
+
if (exceedCount || exceedTime || exceedVisibility) {
|
|
14599
|
+
if (exceedVisibility) {
|
|
14600
|
+
recentVisibilityChanges = 0;
|
|
14601
|
+
}
|
|
14199
14602
|
takeFullSnapshot$1(true);
|
|
14200
14603
|
}
|
|
14201
14604
|
}
|
|
@@ -14223,6 +14626,17 @@ function record(options = {}) {
|
|
|
14223
14626
|
...p
|
|
14224
14627
|
}
|
|
14225
14628
|
});
|
|
14629
|
+
const wrappedVisibilityMutationEmit = (p) => {
|
|
14630
|
+
var _a2;
|
|
14631
|
+
(_a2 = hooks == null ? void 0 : hooks.visibilityMutation) == null ? void 0 : _a2.call(hooks, p);
|
|
14632
|
+
wrappedEmit({
|
|
14633
|
+
type: EventType.IncrementalSnapshot,
|
|
14634
|
+
data: {
|
|
14635
|
+
source: IncrementalSource.VisibilityMutation,
|
|
14636
|
+
...p
|
|
14637
|
+
}
|
|
14638
|
+
});
|
|
14639
|
+
};
|
|
14226
14640
|
const wrappedAdoptedStyleSheetEmit = (a2) => wrappedEmit({
|
|
14227
14641
|
type: EventType.IncrementalSnapshot,
|
|
14228
14642
|
data: {
|
|
@@ -14260,6 +14674,13 @@ function record(options = {}) {
|
|
|
14260
14674
|
sampling: sampling.canvas,
|
|
14261
14675
|
dataURLOptions
|
|
14262
14676
|
});
|
|
14677
|
+
visibilityManager = new VisibilityManager({
|
|
14678
|
+
doc: window.document,
|
|
14679
|
+
mirror,
|
|
14680
|
+
sampling: sampling.visibility,
|
|
14681
|
+
mutationCb: wrappedVisibilityMutationEmit,
|
|
14682
|
+
notifyActivity: onVisibilityActivity
|
|
14683
|
+
});
|
|
14263
14684
|
const shadowDomManager = new ShadowDomManager({
|
|
14264
14685
|
mutationCb: wrappedMutationEmit,
|
|
14265
14686
|
scrollCb: wrappedScrollEmit,
|
|
@@ -14269,7 +14690,6 @@ function record(options = {}) {
|
|
|
14269
14690
|
maskTextClass,
|
|
14270
14691
|
maskTextSelector,
|
|
14271
14692
|
excludeAttribute,
|
|
14272
|
-
includeAttribute,
|
|
14273
14693
|
inlineStylesheet,
|
|
14274
14694
|
maskInputOptions,
|
|
14275
14695
|
dataURLOptions,
|
|
@@ -14282,6 +14702,7 @@ function record(options = {}) {
|
|
|
14282
14702
|
iframeManager,
|
|
14283
14703
|
stylesheetManager,
|
|
14284
14704
|
canvasManager,
|
|
14705
|
+
visibilityManager,
|
|
14285
14706
|
keepIframeSrcFn,
|
|
14286
14707
|
processedNodeManager
|
|
14287
14708
|
},
|
|
@@ -14312,7 +14733,6 @@ function record(options = {}) {
|
|
|
14312
14733
|
maskTextClass,
|
|
14313
14734
|
maskTextSelector,
|
|
14314
14735
|
excludeAttribute,
|
|
14315
|
-
includeAttribute,
|
|
14316
14736
|
inlineStylesheet,
|
|
14317
14737
|
maskAllInputs: maskInputOptions,
|
|
14318
14738
|
maskTextFn,
|
|
@@ -14361,6 +14781,12 @@ function record(options = {}) {
|
|
|
14361
14781
|
mirror.getId(document)
|
|
14362
14782
|
);
|
|
14363
14783
|
};
|
|
14784
|
+
flushCustomEventQueue = () => {
|
|
14785
|
+
for (const e2 of customEventQueue) {
|
|
14786
|
+
wrappedEmit(e2);
|
|
14787
|
+
}
|
|
14788
|
+
customEventQueue.length = 0;
|
|
14789
|
+
};
|
|
14364
14790
|
try {
|
|
14365
14791
|
const handlers = [];
|
|
14366
14792
|
const observe = (doc) => {
|
|
@@ -14419,6 +14845,7 @@ function record(options = {}) {
|
|
|
14419
14845
|
}
|
|
14420
14846
|
}),
|
|
14421
14847
|
canvasMutationCb: wrappedCanvasMutationEmit,
|
|
14848
|
+
visibilityMutationCb: wrappedVisibilityMutationEmit,
|
|
14422
14849
|
fontCb: (p) => wrappedEmit({
|
|
14423
14850
|
type: EventType.IncrementalSnapshot,
|
|
14424
14851
|
data: {
|
|
@@ -14450,7 +14877,6 @@ function record(options = {}) {
|
|
|
14450
14877
|
maskTextClass,
|
|
14451
14878
|
maskTextSelector,
|
|
14452
14879
|
excludeAttribute,
|
|
14453
|
-
includeAttribute,
|
|
14454
14880
|
maskInputOptions,
|
|
14455
14881
|
inlineStylesheet,
|
|
14456
14882
|
sampling,
|
|
@@ -14472,6 +14898,7 @@ function record(options = {}) {
|
|
|
14472
14898
|
shadowDomManager,
|
|
14473
14899
|
processedNodeManager,
|
|
14474
14900
|
canvasManager,
|
|
14901
|
+
visibilityManager,
|
|
14475
14902
|
ignoreCSSAttributes,
|
|
14476
14903
|
plugins: ((_a2 = plugins == null ? void 0 : plugins.filter((p) => p.observer)) == null ? void 0 : _a2.map((p) => ({
|
|
14477
14904
|
observer: p.observer,
|
|
@@ -14496,14 +14923,14 @@ function record(options = {}) {
|
|
|
14496
14923
|
}
|
|
14497
14924
|
});
|
|
14498
14925
|
const init = () => {
|
|
14499
|
-
if (
|
|
14500
|
-
|
|
14926
|
+
if (flushCustomEvent === "before") {
|
|
14927
|
+
flushCustomEventQueue();
|
|
14501
14928
|
}
|
|
14502
14929
|
takeFullSnapshot$1();
|
|
14503
14930
|
handlers.push(observe(document));
|
|
14504
14931
|
recording = true;
|
|
14505
|
-
if (
|
|
14506
|
-
|
|
14932
|
+
if (flushCustomEvent === "after") {
|
|
14933
|
+
flushCustomEventQueue();
|
|
14507
14934
|
}
|
|
14508
14935
|
};
|
|
14509
14936
|
if (document.readyState === "interactive" || document.readyState === "complete") {
|
|
@@ -14533,7 +14960,7 @@ function record(options = {}) {
|
|
|
14533
14960
|
);
|
|
14534
14961
|
}
|
|
14535
14962
|
return () => {
|
|
14536
|
-
|
|
14963
|
+
flushCustomEventQueue();
|
|
14537
14964
|
handlers.forEach((h) => h());
|
|
14538
14965
|
processedNodeManager.destroy();
|
|
14539
14966
|
recording = false;
|
|
@@ -14543,12 +14970,10 @@ function record(options = {}) {
|
|
|
14543
14970
|
console.warn(error);
|
|
14544
14971
|
}
|
|
14545
14972
|
}
|
|
14546
|
-
|
|
14547
|
-
|
|
14548
|
-
|
|
14549
|
-
|
|
14550
|
-
preRecordingCustomEvents.length = 0;
|
|
14551
|
-
}
|
|
14973
|
+
record.flushCustomEventQueue = () => {
|
|
14974
|
+
console.warn(`[rrweb] CustomEvent flushing: ${customEventQueue.length} events`);
|
|
14975
|
+
flushCustomEventQueue();
|
|
14976
|
+
};
|
|
14552
14977
|
record.addCustomEvent = (tag, payload) => {
|
|
14553
14978
|
const customEvent = {
|
|
14554
14979
|
type: EventType.Custom,
|
|
@@ -14558,8 +14983,8 @@ record.addCustomEvent = (tag, payload) => {
|
|
|
14558
14983
|
}
|
|
14559
14984
|
};
|
|
14560
14985
|
if (!recording) {
|
|
14561
|
-
console.warn(`[rrweb] CustomEvent buffered before recording start: ${tag}`);
|
|
14562
|
-
|
|
14986
|
+
console.warn(`[rrweb] CustomEvent buffered before/after recording start: ${tag}`);
|
|
14987
|
+
customEventQueue.push(customEvent);
|
|
14563
14988
|
return;
|
|
14564
14989
|
}
|
|
14565
14990
|
wrappedEmit(customEvent);
|