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