@posthog/rrweb-record 0.0.28 → 0.0.30
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 +177 -94
- package/dist/rrweb-record.cjs.map +1 -1
- package/dist/rrweb-record.js +177 -94
- package/dist/rrweb-record.js.map +1 -1
- package/dist/rrweb-record.umd.cjs +176 -94
- package/dist/rrweb-record.umd.cjs.map +2 -2
- package/dist/rrweb-record.umd.min.cjs +35 -35
- package/dist/rrweb-record.umd.min.cjs.map +3 -3
- package/package.json +1 -1
package/dist/rrweb-record.cjs
CHANGED
|
@@ -207,6 +207,91 @@ function isShadowRoot(n2) {
|
|
|
207
207
|
function isNativeShadowDom(shadowRoot2) {
|
|
208
208
|
return Object.prototype.toString.call(shadowRoot2) === "[object ShadowRoot]";
|
|
209
209
|
}
|
|
210
|
+
function fixBrowserCompatibilityIssuesInCSS(cssText) {
|
|
211
|
+
if (cssText.includes(" background-clip: text;") && !cssText.includes(" -webkit-background-clip: text;")) {
|
|
212
|
+
cssText = cssText.replace(
|
|
213
|
+
/\sbackground-clip:\s*text;/g,
|
|
214
|
+
" -webkit-background-clip: text; background-clip: text;"
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
return cssText;
|
|
218
|
+
}
|
|
219
|
+
function escapeImportStatement(rule2) {
|
|
220
|
+
const { cssText } = rule2;
|
|
221
|
+
if (cssText.split('"').length < 3) return cssText;
|
|
222
|
+
const statement = ["@import", `url(${JSON.stringify(rule2.href)})`];
|
|
223
|
+
if (rule2.layerName === "") {
|
|
224
|
+
statement.push(`layer`);
|
|
225
|
+
} else if (rule2.layerName) {
|
|
226
|
+
statement.push(`layer(${rule2.layerName})`);
|
|
227
|
+
}
|
|
228
|
+
if (rule2.supportsText) {
|
|
229
|
+
statement.push(`supports(${rule2.supportsText})`);
|
|
230
|
+
}
|
|
231
|
+
if (rule2.media.length) {
|
|
232
|
+
statement.push(rule2.media.mediaText);
|
|
233
|
+
}
|
|
234
|
+
return statement.join(" ") + ";";
|
|
235
|
+
}
|
|
236
|
+
function stringifyStylesheet(s2) {
|
|
237
|
+
try {
|
|
238
|
+
const rules2 = s2.rules || s2.cssRules;
|
|
239
|
+
if (!rules2) {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
let sheetHref = s2.href;
|
|
243
|
+
if (!sheetHref && s2.ownerNode) {
|
|
244
|
+
sheetHref = s2.ownerNode.baseURI;
|
|
245
|
+
}
|
|
246
|
+
const stringifiedRules = Array.from(
|
|
247
|
+
rules2,
|
|
248
|
+
(rule2) => stringifyRule(rule2, sheetHref)
|
|
249
|
+
).join("");
|
|
250
|
+
return fixBrowserCompatibilityIssuesInCSS(stringifiedRules);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function stringifyRule(rule2, sheetHref) {
|
|
256
|
+
var _a2;
|
|
257
|
+
if (isCSSImportRule(rule2)) {
|
|
258
|
+
let importStringified;
|
|
259
|
+
try {
|
|
260
|
+
importStringified = // for same-origin stylesheets,
|
|
261
|
+
// we can access the imported stylesheet rules directly
|
|
262
|
+
stringifyStylesheet(rule2.styleSheet) || // work around browser issues with the raw string `@import url(...)` statement
|
|
263
|
+
escapeImportStatement(rule2);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
importStringified = rule2.cssText;
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
if (importStringified && ((_a2 = rule2.styleSheet) == null ? void 0 : _a2.href)) {
|
|
269
|
+
return absolutifyURLs(importStringified, rule2.styleSheet.href);
|
|
270
|
+
}
|
|
271
|
+
} catch {
|
|
272
|
+
}
|
|
273
|
+
return importStringified;
|
|
274
|
+
} else {
|
|
275
|
+
let ruleStringified = rule2.cssText;
|
|
276
|
+
if (isCSSStyleRule(rule2) && rule2.selectorText.includes(":")) {
|
|
277
|
+
ruleStringified = fixSafariColons(ruleStringified);
|
|
278
|
+
}
|
|
279
|
+
if (sheetHref) {
|
|
280
|
+
return absolutifyURLs(ruleStringified, sheetHref);
|
|
281
|
+
}
|
|
282
|
+
return ruleStringified;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function fixSafariColons(cssStringified) {
|
|
286
|
+
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
287
|
+
return cssStringified.replace(regex, "$1\\$2");
|
|
288
|
+
}
|
|
289
|
+
function isCSSImportRule(rule2) {
|
|
290
|
+
return "styleSheet" in rule2;
|
|
291
|
+
}
|
|
292
|
+
function isCSSStyleRule(rule2) {
|
|
293
|
+
return "selectorText" in rule2;
|
|
294
|
+
}
|
|
210
295
|
class Mirror {
|
|
211
296
|
constructor() {
|
|
212
297
|
__publicField$1(this, "idNodeMap", /* @__PURE__ */ new Map());
|
|
@@ -329,91 +414,6 @@ function extractFileExtension(path, baseURL) {
|
|
|
329
414
|
const match = url.pathname.match(regex);
|
|
330
415
|
return (match == null ? void 0 : match[1]) ?? null;
|
|
331
416
|
}
|
|
332
|
-
function fixBrowserCompatibilityIssuesInCSS(cssText) {
|
|
333
|
-
if (cssText.includes(" background-clip: text;") && !cssText.includes(" -webkit-background-clip: text;")) {
|
|
334
|
-
cssText = cssText.replace(
|
|
335
|
-
/\sbackground-clip:\s*text;/g,
|
|
336
|
-
" -webkit-background-clip: text; background-clip: text;"
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
return cssText;
|
|
340
|
-
}
|
|
341
|
-
function escapeImportStatement(rule2) {
|
|
342
|
-
const { cssText } = rule2;
|
|
343
|
-
if (cssText.split('"').length < 3) return cssText;
|
|
344
|
-
const statement = ["@import", `url(${JSON.stringify(rule2.href)})`];
|
|
345
|
-
if (rule2.layerName === "") {
|
|
346
|
-
statement.push(`layer`);
|
|
347
|
-
} else if (rule2.layerName) {
|
|
348
|
-
statement.push(`layer(${rule2.layerName})`);
|
|
349
|
-
}
|
|
350
|
-
if (rule2.supportsText) {
|
|
351
|
-
statement.push(`supports(${rule2.supportsText})`);
|
|
352
|
-
}
|
|
353
|
-
if (rule2.media.length) {
|
|
354
|
-
statement.push(rule2.media.mediaText);
|
|
355
|
-
}
|
|
356
|
-
return statement.join(" ") + ";";
|
|
357
|
-
}
|
|
358
|
-
function stringifyStylesheet(s2) {
|
|
359
|
-
try {
|
|
360
|
-
const rules2 = s2.rules || s2.cssRules;
|
|
361
|
-
if (!rules2) {
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
let sheetHref = s2.href;
|
|
365
|
-
if (!sheetHref && s2.ownerNode) {
|
|
366
|
-
sheetHref = s2.ownerNode.baseURI;
|
|
367
|
-
}
|
|
368
|
-
const stringifiedRules = Array.from(
|
|
369
|
-
rules2,
|
|
370
|
-
(rule2) => stringifyRule(rule2, sheetHref)
|
|
371
|
-
).join("");
|
|
372
|
-
return fixBrowserCompatibilityIssuesInCSS(stringifiedRules);
|
|
373
|
-
} catch (error) {
|
|
374
|
-
return null;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
function stringifyRule(rule2, sheetHref) {
|
|
378
|
-
var _a2;
|
|
379
|
-
if (isCSSImportRule(rule2)) {
|
|
380
|
-
let importStringified;
|
|
381
|
-
try {
|
|
382
|
-
importStringified = // for same-origin stylesheets,
|
|
383
|
-
// we can access the imported stylesheet rules directly
|
|
384
|
-
stringifyStylesheet(rule2.styleSheet) || // work around browser issues with the raw string `@import url(...)` statement
|
|
385
|
-
escapeImportStatement(rule2);
|
|
386
|
-
} catch (error) {
|
|
387
|
-
importStringified = rule2.cssText;
|
|
388
|
-
}
|
|
389
|
-
try {
|
|
390
|
-
if (importStringified && ((_a2 = rule2.styleSheet) == null ? void 0 : _a2.href)) {
|
|
391
|
-
return absolutifyURLs(importStringified, rule2.styleSheet.href);
|
|
392
|
-
}
|
|
393
|
-
} catch {
|
|
394
|
-
}
|
|
395
|
-
return importStringified;
|
|
396
|
-
} else {
|
|
397
|
-
let ruleStringified = rule2.cssText;
|
|
398
|
-
if (isCSSStyleRule(rule2) && rule2.selectorText.includes(":")) {
|
|
399
|
-
ruleStringified = fixSafariColons(ruleStringified);
|
|
400
|
-
}
|
|
401
|
-
if (sheetHref) {
|
|
402
|
-
return absolutifyURLs(ruleStringified, sheetHref);
|
|
403
|
-
}
|
|
404
|
-
return ruleStringified;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
function fixSafariColons(cssStringified) {
|
|
408
|
-
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
409
|
-
return cssStringified.replace(regex, "$1\\$2");
|
|
410
|
-
}
|
|
411
|
-
function isCSSImportRule(rule2) {
|
|
412
|
-
return "styleSheet" in rule2;
|
|
413
|
-
}
|
|
414
|
-
function isCSSStyleRule(rule2) {
|
|
415
|
-
return "selectorText" in rule2;
|
|
416
|
-
}
|
|
417
417
|
function extractOrigin(url) {
|
|
418
418
|
let origin = "";
|
|
419
419
|
if (url.indexOf("//") > -1) {
|
|
@@ -462,6 +462,36 @@ function absolutifyURLs(cssText, href) {
|
|
|
462
462
|
}
|
|
463
463
|
);
|
|
464
464
|
}
|
|
465
|
+
const STRIPED_PLACEHOLDER_SVG = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxkZWZzPgogICAgPHBhdHRlcm4gaWQ9InN0cmlwZXMiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+CiAgICAgIDxyZWN0IHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iYmxhY2siLz4KICAgICAgPHBhdGggZD0iTTggMEgxNkwwIDE2VjhMOCAwWiIgZmlsbD0iIzJEMkQyRCIvPgogICAgICA8cGF0aCBkPSJNMTYgOFYxNkg4TDE2IDhaIiBmaWxsPSIjMkQyRDJEIi8+CiAgICA8L3BhdHRlcm4+CiAgPC9kZWZzPgogIDxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjc3RyaXBlcykiLz4KPC9zdmc+Cg==";
|
|
466
|
+
const MAX_IMAGE_DIMENSION_FOR_RECOMPRESSION = 4096;
|
|
467
|
+
function recompressBase64Image(img, dataURL, type, quality) {
|
|
468
|
+
if (!img.complete || img.naturalWidth === 0) {
|
|
469
|
+
return dataURL;
|
|
470
|
+
}
|
|
471
|
+
if (img.naturalWidth > MAX_IMAGE_DIMENSION_FOR_RECOMPRESSION || img.naturalHeight > MAX_IMAGE_DIMENSION_FOR_RECOMPRESSION) {
|
|
472
|
+
return dataURL;
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
const canvas = document.createElement("canvas");
|
|
476
|
+
canvas.width = img.naturalWidth;
|
|
477
|
+
canvas.height = img.naturalHeight;
|
|
478
|
+
const ctx = canvas.getContext("2d");
|
|
479
|
+
if (!ctx) {
|
|
480
|
+
return dataURL;
|
|
481
|
+
}
|
|
482
|
+
ctx.drawImage(img, 0, 0);
|
|
483
|
+
const recompressed = canvas.toDataURL(type || "image/webp", quality ?? 0.4);
|
|
484
|
+
return recompressed;
|
|
485
|
+
} catch (err) {
|
|
486
|
+
return dataURL;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function checkDataURLSize(dataURL, maxLength) {
|
|
490
|
+
if (!maxLength || dataURL.length <= maxLength) {
|
|
491
|
+
return dataURL;
|
|
492
|
+
}
|
|
493
|
+
return STRIPED_PLACEHOLDER_SVG;
|
|
494
|
+
}
|
|
465
495
|
let _id = 1;
|
|
466
496
|
const tagNameRegex = new RegExp("[^a-z0-9-_:]");
|
|
467
497
|
const IGNORED_NODE = -2;
|
|
@@ -560,12 +590,32 @@ function getHref(doc, customHref) {
|
|
|
560
590
|
a2.setAttribute("href", customHref);
|
|
561
591
|
return a2.href;
|
|
562
592
|
}
|
|
563
|
-
function transformAttribute(doc, tagName, name, value) {
|
|
593
|
+
function transformAttribute(doc, tagName, name, value, element, dataURLOptions) {
|
|
564
594
|
if (!value) {
|
|
565
595
|
return value;
|
|
566
596
|
}
|
|
567
597
|
if (name === "src" || name === "href" && !(tagName === "use" && value[0] === "#")) {
|
|
568
|
-
|
|
598
|
+
const transformedValue = absoluteToDoc(doc, value);
|
|
599
|
+
if (tagName === "img" && transformedValue.startsWith("data:") && element) {
|
|
600
|
+
const img = element;
|
|
601
|
+
let processedDataURL = transformedValue;
|
|
602
|
+
if ((dataURLOptions == null ? void 0 : dataURLOptions.type) || (dataURLOptions == null ? void 0 : dataURLOptions.quality) !== void 0) {
|
|
603
|
+
processedDataURL = recompressBase64Image(
|
|
604
|
+
img,
|
|
605
|
+
transformedValue,
|
|
606
|
+
dataURLOptions.type,
|
|
607
|
+
dataURLOptions.quality
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
if (dataURLOptions == null ? void 0 : dataURLOptions.maxBase64ImageLength) {
|
|
611
|
+
processedDataURL = checkDataURLSize(
|
|
612
|
+
processedDataURL,
|
|
613
|
+
dataURLOptions.maxBase64ImageLength
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
return processedDataURL;
|
|
617
|
+
}
|
|
618
|
+
return transformedValue;
|
|
569
619
|
} else if (name === "xlink:href" && value[0] !== "#") {
|
|
570
620
|
return absoluteToDoc(doc, value);
|
|
571
621
|
} else if (name === "background" && (tagName === "table" || tagName === "td" || tagName === "th")) {
|
|
@@ -856,7 +906,9 @@ function serializeElementNode(n2, options) {
|
|
|
856
906
|
doc,
|
|
857
907
|
tagName,
|
|
858
908
|
toLowerCase(attr.name),
|
|
859
|
-
attr.value
|
|
909
|
+
attr.value,
|
|
910
|
+
n2,
|
|
911
|
+
dataURLOptions
|
|
860
912
|
);
|
|
861
913
|
}
|
|
862
914
|
}
|
|
@@ -10134,7 +10186,9 @@ class MutationBuffer {
|
|
|
10134
10186
|
this.doc,
|
|
10135
10187
|
toLowerCase(target.tagName),
|
|
10136
10188
|
toLowerCase(attributeName),
|
|
10137
|
-
value
|
|
10189
|
+
value,
|
|
10190
|
+
target,
|
|
10191
|
+
this.dataURLOptions
|
|
10138
10192
|
);
|
|
10139
10193
|
if (attributeName === "style") {
|
|
10140
10194
|
if (!this.unattachedDoc) {
|
|
@@ -10293,6 +10347,11 @@ class MutationBuffer {
|
|
|
10293
10347
|
this.shadowDomManager.reset();
|
|
10294
10348
|
this.canvasManager.reset();
|
|
10295
10349
|
}
|
|
10350
|
+
destroy() {
|
|
10351
|
+
while (this.mapRemoves.length) {
|
|
10352
|
+
this.mirror.removeNodeFromMap(this.mapRemoves.shift());
|
|
10353
|
+
}
|
|
10354
|
+
}
|
|
10296
10355
|
}
|
|
10297
10356
|
function deepDelete(addsSet, n2) {
|
|
10298
10357
|
addsSet.delete(n2);
|
|
@@ -11339,6 +11398,7 @@ function initObservers(o2, hooks = {}) {
|
|
|
11339
11398
|
);
|
|
11340
11399
|
}
|
|
11341
11400
|
return callbackWrapper(() => {
|
|
11401
|
+
mutationBuffers.forEach((b) => b.destroy());
|
|
11342
11402
|
mutationBuffers.forEach((b) => b.reset());
|
|
11343
11403
|
mutationObserver == null ? void 0 : mutationObserver.disconnect();
|
|
11344
11404
|
mousemoveHandler();
|
|
@@ -11676,6 +11736,8 @@ class IframeManager {
|
|
|
11676
11736
|
contentWindow.removeEventListener("message", handler);
|
|
11677
11737
|
});
|
|
11678
11738
|
this.nestedIframeListeners.clear();
|
|
11739
|
+
this.crossOriginIframeMirror.reset();
|
|
11740
|
+
this.crossOriginIframeStyleMirror.reset();
|
|
11679
11741
|
}
|
|
11680
11742
|
}
|
|
11681
11743
|
class ShadowDomManager {
|
|
@@ -12134,6 +12196,8 @@ class CanvasManager {
|
|
|
12134
12196
|
__publicField(this, "resetObservers");
|
|
12135
12197
|
__publicField(this, "frozen", false);
|
|
12136
12198
|
__publicField(this, "locked", false);
|
|
12199
|
+
__publicField(this, "rafIdTimestamp", null);
|
|
12200
|
+
__publicField(this, "rafIdFlush", null);
|
|
12137
12201
|
__publicField(this, "processMutation", (target, mutation) => {
|
|
12138
12202
|
const newFrame = this.rafStamps.invokeId && this.rafStamps.latestId !== this.rafStamps.invokeId;
|
|
12139
12203
|
if (newFrame || !this.rafStamps.invokeId)
|
|
@@ -12168,6 +12232,14 @@ class CanvasManager {
|
|
|
12168
12232
|
reset() {
|
|
12169
12233
|
this.pendingCanvasMutations.clear();
|
|
12170
12234
|
this.resetObservers && this.resetObservers();
|
|
12235
|
+
if (this.rafIdTimestamp !== null) {
|
|
12236
|
+
cancelAnimationFrame(this.rafIdTimestamp);
|
|
12237
|
+
this.rafIdTimestamp = null;
|
|
12238
|
+
}
|
|
12239
|
+
if (this.rafIdFlush !== null) {
|
|
12240
|
+
cancelAnimationFrame(this.rafIdFlush);
|
|
12241
|
+
this.rafIdFlush = null;
|
|
12242
|
+
}
|
|
12171
12243
|
}
|
|
12172
12244
|
freeze() {
|
|
12173
12245
|
this.frozen = true;
|
|
@@ -12318,14 +12390,16 @@ class CanvasManager {
|
|
|
12318
12390
|
};
|
|
12319
12391
|
}
|
|
12320
12392
|
startPendingCanvasMutationFlusher() {
|
|
12321
|
-
|
|
12393
|
+
this.rafIdFlush = requestAnimationFrame(
|
|
12394
|
+
() => this.flushPendingCanvasMutations()
|
|
12395
|
+
);
|
|
12322
12396
|
}
|
|
12323
12397
|
startRAFTimestamping() {
|
|
12324
12398
|
const setLatestRAFTimestamp = (timestamp) => {
|
|
12325
12399
|
this.rafStamps.latestId = timestamp;
|
|
12326
|
-
requestAnimationFrame(setLatestRAFTimestamp);
|
|
12400
|
+
this.rafIdTimestamp = requestAnimationFrame(setLatestRAFTimestamp);
|
|
12327
12401
|
};
|
|
12328
|
-
requestAnimationFrame(setLatestRAFTimestamp);
|
|
12402
|
+
this.rafIdTimestamp = requestAnimationFrame(setLatestRAFTimestamp);
|
|
12329
12403
|
}
|
|
12330
12404
|
flushPendingCanvasMutations() {
|
|
12331
12405
|
this.pendingCanvasMutations.forEach(
|
|
@@ -12334,7 +12408,9 @@ class CanvasManager {
|
|
|
12334
12408
|
this.flushPendingCanvasMutationFor(canvas, id);
|
|
12335
12409
|
}
|
|
12336
12410
|
);
|
|
12337
|
-
|
|
12411
|
+
this.rafIdFlush = requestAnimationFrame(
|
|
12412
|
+
() => this.flushPendingCanvasMutations()
|
|
12413
|
+
);
|
|
12338
12414
|
}
|
|
12339
12415
|
flushPendingCanvasMutationFor(canvas, id) {
|
|
12340
12416
|
if (this.frozen || this.locked) {
|
|
@@ -12469,7 +12545,7 @@ function record(options = {}) {
|
|
|
12469
12545
|
hooks,
|
|
12470
12546
|
packFn,
|
|
12471
12547
|
sampling = {},
|
|
12472
|
-
dataURLOptions = {},
|
|
12548
|
+
dataURLOptions: _dataURLOptions = {},
|
|
12473
12549
|
mousemoveWait,
|
|
12474
12550
|
recordDOM = true,
|
|
12475
12551
|
recordCanvas = false,
|
|
@@ -12484,6 +12560,12 @@ function record(options = {}) {
|
|
|
12484
12560
|
errorHandler: errorHandler2
|
|
12485
12561
|
} = options;
|
|
12486
12562
|
registerErrorHandler(errorHandler2);
|
|
12563
|
+
const dataURLOptions = {
|
|
12564
|
+
type: "image/webp",
|
|
12565
|
+
quality: 0.4,
|
|
12566
|
+
maxBase64ImageLength: 1048576,
|
|
12567
|
+
..._dataURLOptions
|
|
12568
|
+
};
|
|
12487
12569
|
const inEmittingFrame = recordCrossOriginIframes ? window.parent === window : true;
|
|
12488
12570
|
let passEmitsToParent = false;
|
|
12489
12571
|
if (!inEmittingFrame) {
|
|
@@ -12913,6 +12995,7 @@ function record(options = {}) {
|
|
|
12913
12995
|
processedNodeManager.destroy();
|
|
12914
12996
|
iframeManager.removeLoadListener();
|
|
12915
12997
|
iframeManager.destroy();
|
|
12998
|
+
mirror.reset();
|
|
12916
12999
|
recording = false;
|
|
12917
13000
|
unregisterErrorHandler();
|
|
12918
13001
|
};
|