@posthog/rrweb 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.
@@ -251,6 +251,91 @@ function isShadowRoot(n2) {
251
251
  function isNativeShadowDom(shadowRoot2) {
252
252
  return Object.prototype.toString.call(shadowRoot2) === "[object ShadowRoot]";
253
253
  }
254
+ function fixBrowserCompatibilityIssuesInCSS(cssText) {
255
+ if (cssText.includes(" background-clip: text;") && !cssText.includes(" -webkit-background-clip: text;")) {
256
+ cssText = cssText.replace(
257
+ /\sbackground-clip:\s*text;/g,
258
+ " -webkit-background-clip: text; background-clip: text;"
259
+ );
260
+ }
261
+ return cssText;
262
+ }
263
+ function escapeImportStatement(rule2) {
264
+ const { cssText } = rule2;
265
+ if (cssText.split('"').length < 3) return cssText;
266
+ const statement = ["@import", `url(${JSON.stringify(rule2.href)})`];
267
+ if (rule2.layerName === "") {
268
+ statement.push(`layer`);
269
+ } else if (rule2.layerName) {
270
+ statement.push(`layer(${rule2.layerName})`);
271
+ }
272
+ if (rule2.supportsText) {
273
+ statement.push(`supports(${rule2.supportsText})`);
274
+ }
275
+ if (rule2.media.length) {
276
+ statement.push(rule2.media.mediaText);
277
+ }
278
+ return statement.join(" ") + ";";
279
+ }
280
+ function stringifyStylesheet(s2) {
281
+ try {
282
+ const rules2 = s2.rules || s2.cssRules;
283
+ if (!rules2) {
284
+ return null;
285
+ }
286
+ let sheetHref = s2.href;
287
+ if (!sheetHref && s2.ownerNode) {
288
+ sheetHref = s2.ownerNode.baseURI;
289
+ }
290
+ const stringifiedRules = Array.from(
291
+ rules2,
292
+ (rule2) => stringifyRule(rule2, sheetHref)
293
+ ).join("");
294
+ return fixBrowserCompatibilityIssuesInCSS(stringifiedRules);
295
+ } catch (error) {
296
+ return null;
297
+ }
298
+ }
299
+ function stringifyRule(rule2, sheetHref) {
300
+ var _a2;
301
+ if (isCSSImportRule(rule2)) {
302
+ let importStringified;
303
+ try {
304
+ importStringified = // for same-origin stylesheets,
305
+ // we can access the imported stylesheet rules directly
306
+ stringifyStylesheet(rule2.styleSheet) || // work around browser issues with the raw string `@import url(...)` statement
307
+ escapeImportStatement(rule2);
308
+ } catch (error) {
309
+ importStringified = rule2.cssText;
310
+ }
311
+ try {
312
+ if (importStringified && ((_a2 = rule2.styleSheet) == null ? void 0 : _a2.href)) {
313
+ return absolutifyURLs(importStringified, rule2.styleSheet.href);
314
+ }
315
+ } catch (e2) {
316
+ }
317
+ return importStringified;
318
+ } else {
319
+ let ruleStringified = rule2.cssText;
320
+ if (isCSSStyleRule(rule2) && rule2.selectorText.includes(":")) {
321
+ ruleStringified = fixSafariColons(ruleStringified);
322
+ }
323
+ if (sheetHref) {
324
+ return absolutifyURLs(ruleStringified, sheetHref);
325
+ }
326
+ return ruleStringified;
327
+ }
328
+ }
329
+ function fixSafariColons(cssStringified) {
330
+ const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
331
+ return cssStringified.replace(regex, "$1\\$2");
332
+ }
333
+ function isCSSImportRule(rule2) {
334
+ return "styleSheet" in rule2;
335
+ }
336
+ function isCSSStyleRule(rule2) {
337
+ return "selectorText" in rule2;
338
+ }
254
339
  class Mirror {
255
340
  constructor() {
256
341
  __publicField$1(this, "idNodeMap", /* @__PURE__ */ new Map());
@@ -386,91 +471,6 @@ function extractFileExtension(path, baseURL) {
386
471
  const match = url.pathname.match(regex);
387
472
  return (_a2 = match == null ? void 0 : match[1]) != null ? _a2 : null;
388
473
  }
389
- function fixBrowserCompatibilityIssuesInCSS(cssText) {
390
- if (cssText.includes(" background-clip: text;") && !cssText.includes(" -webkit-background-clip: text;")) {
391
- cssText = cssText.replace(
392
- /\sbackground-clip:\s*text;/g,
393
- " -webkit-background-clip: text; background-clip: text;"
394
- );
395
- }
396
- return cssText;
397
- }
398
- function escapeImportStatement(rule2) {
399
- const { cssText } = rule2;
400
- if (cssText.split('"').length < 3) return cssText;
401
- const statement = ["@import", `url(${JSON.stringify(rule2.href)})`];
402
- if (rule2.layerName === "") {
403
- statement.push(`layer`);
404
- } else if (rule2.layerName) {
405
- statement.push(`layer(${rule2.layerName})`);
406
- }
407
- if (rule2.supportsText) {
408
- statement.push(`supports(${rule2.supportsText})`);
409
- }
410
- if (rule2.media.length) {
411
- statement.push(rule2.media.mediaText);
412
- }
413
- return statement.join(" ") + ";";
414
- }
415
- function stringifyStylesheet(s2) {
416
- try {
417
- const rules2 = s2.rules || s2.cssRules;
418
- if (!rules2) {
419
- return null;
420
- }
421
- let sheetHref = s2.href;
422
- if (!sheetHref && s2.ownerNode) {
423
- sheetHref = s2.ownerNode.baseURI;
424
- }
425
- const stringifiedRules = Array.from(
426
- rules2,
427
- (rule2) => stringifyRule(rule2, sheetHref)
428
- ).join("");
429
- return fixBrowserCompatibilityIssuesInCSS(stringifiedRules);
430
- } catch (error) {
431
- return null;
432
- }
433
- }
434
- function stringifyRule(rule2, sheetHref) {
435
- var _a2;
436
- if (isCSSImportRule(rule2)) {
437
- let importStringified;
438
- try {
439
- importStringified = // for same-origin stylesheets,
440
- // we can access the imported stylesheet rules directly
441
- stringifyStylesheet(rule2.styleSheet) || // work around browser issues with the raw string `@import url(...)` statement
442
- escapeImportStatement(rule2);
443
- } catch (error) {
444
- importStringified = rule2.cssText;
445
- }
446
- try {
447
- if (importStringified && ((_a2 = rule2.styleSheet) == null ? void 0 : _a2.href)) {
448
- return absolutifyURLs(importStringified, rule2.styleSheet.href);
449
- }
450
- } catch (e2) {
451
- }
452
- return importStringified;
453
- } else {
454
- let ruleStringified = rule2.cssText;
455
- if (isCSSStyleRule(rule2) && rule2.selectorText.includes(":")) {
456
- ruleStringified = fixSafariColons(ruleStringified);
457
- }
458
- if (sheetHref) {
459
- return absolutifyURLs(ruleStringified, sheetHref);
460
- }
461
- return ruleStringified;
462
- }
463
- }
464
- function fixSafariColons(cssStringified) {
465
- const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
466
- return cssStringified.replace(regex, "$1\\$2");
467
- }
468
- function isCSSImportRule(rule2) {
469
- return "styleSheet" in rule2;
470
- }
471
- function isCSSStyleRule(rule2) {
472
- return "selectorText" in rule2;
473
- }
474
474
  function extractOrigin(url) {
475
475
  let origin = "";
476
476
  if (url.indexOf("//") > -1) {
@@ -519,6 +519,36 @@ function absolutifyURLs(cssText, href) {
519
519
  }
520
520
  );
521
521
  }
522
+ const STRIPED_PLACEHOLDER_SVG = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxkZWZzPgogICAgPHBhdHRlcm4gaWQ9InN0cmlwZXMiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+CiAgICAgIDxyZWN0IHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iYmxhY2siLz4KICAgICAgPHBhdGggZD0iTTggMEgxNkwwIDE2VjhMOCAwWiIgZmlsbD0iIzJEMkQyRCIvPgogICAgICA8cGF0aCBkPSJNMTYgOFYxNkg4TDE2IDhaIiBmaWxsPSIjMkQyRDJEIi8+CiAgICA8L3BhdHRlcm4+CiAgPC9kZWZzPgogIDxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjc3RyaXBlcykiLz4KPC9zdmc+Cg==";
523
+ const MAX_IMAGE_DIMENSION_FOR_RECOMPRESSION = 4096;
524
+ function recompressBase64Image(img, dataURL, type, quality) {
525
+ if (!img.complete || img.naturalWidth === 0) {
526
+ return dataURL;
527
+ }
528
+ if (img.naturalWidth > MAX_IMAGE_DIMENSION_FOR_RECOMPRESSION || img.naturalHeight > MAX_IMAGE_DIMENSION_FOR_RECOMPRESSION) {
529
+ return dataURL;
530
+ }
531
+ try {
532
+ const canvas = document.createElement("canvas");
533
+ canvas.width = img.naturalWidth;
534
+ canvas.height = img.naturalHeight;
535
+ const ctx = canvas.getContext("2d");
536
+ if (!ctx) {
537
+ return dataURL;
538
+ }
539
+ ctx.drawImage(img, 0, 0);
540
+ const recompressed = canvas.toDataURL(type || "image/webp", quality != null ? quality : 0.4);
541
+ return recompressed;
542
+ } catch (err) {
543
+ return dataURL;
544
+ }
545
+ }
546
+ function checkDataURLSize(dataURL, maxLength) {
547
+ if (!maxLength || dataURL.length <= maxLength) {
548
+ return dataURL;
549
+ }
550
+ return STRIPED_PLACEHOLDER_SVG;
551
+ }
522
552
  let _id = 1;
523
553
  const tagNameRegex = new RegExp("[^a-z0-9-_:]");
524
554
  const IGNORED_NODE = -2;
@@ -617,12 +647,32 @@ function getHref(doc, customHref) {
617
647
  a2.setAttribute("href", customHref);
618
648
  return a2.href;
619
649
  }
620
- function transformAttribute(doc, tagName, name, value) {
650
+ function transformAttribute(doc, tagName, name, value, element, dataURLOptions) {
621
651
  if (!value) {
622
652
  return value;
623
653
  }
624
654
  if (name === "src" || name === "href" && !(tagName === "use" && value[0] === "#")) {
625
- return absoluteToDoc(doc, value);
655
+ const transformedValue = absoluteToDoc(doc, value);
656
+ if (tagName === "img" && transformedValue.startsWith("data:") && element) {
657
+ const img = element;
658
+ let processedDataURL = transformedValue;
659
+ if ((dataURLOptions == null ? void 0 : dataURLOptions.type) || (dataURLOptions == null ? void 0 : dataURLOptions.quality) !== void 0) {
660
+ processedDataURL = recompressBase64Image(
661
+ img,
662
+ transformedValue,
663
+ dataURLOptions.type,
664
+ dataURLOptions.quality
665
+ );
666
+ }
667
+ if (dataURLOptions == null ? void 0 : dataURLOptions.maxBase64ImageLength) {
668
+ processedDataURL = checkDataURLSize(
669
+ processedDataURL,
670
+ dataURLOptions.maxBase64ImageLength
671
+ );
672
+ }
673
+ return processedDataURL;
674
+ }
675
+ return transformedValue;
626
676
  } else if (name === "xlink:href" && value[0] !== "#") {
627
677
  return absoluteToDoc(doc, value);
628
678
  } else if (name === "background" && (tagName === "table" || tagName === "td" || tagName === "th")) {
@@ -913,7 +963,9 @@ function serializeElementNode(n2, options) {
913
963
  doc,
914
964
  tagName,
915
965
  toLowerCase(attr.name),
916
- attr.value
966
+ attr.value,
967
+ n2,
968
+ dataURLOptions
917
969
  );
918
970
  }
919
971
  }
@@ -5376,22 +5428,6 @@ postcss$1.Input;
5376
5428
  postcss$1.Rule;
5377
5429
  postcss$1.Root;
5378
5430
  postcss$1.Node;
5379
- function adaptCssForReplay(cssText, cache) {
5380
- const cachedStyle = cache == null ? void 0 : cache.stylesWithHoverClass.get(cssText);
5381
- if (cachedStyle) return cachedStyle;
5382
- let result2 = cssText;
5383
- try {
5384
- const ast = postcss$1([
5385
- mediaSelectorPlugin,
5386
- pseudoClassPlugin
5387
- ]).process(cssText, { parser: safeParser });
5388
- result2 = ast.css;
5389
- } catch (error) {
5390
- console.warn("Failed to adapt css for replay", error);
5391
- }
5392
- cache == null ? void 0 : cache.stylesWithHoverClass.set(cssText, result2);
5393
- return result2;
5394
- }
5395
5431
  const tagMap = {
5396
5432
  script: "noscript",
5397
5433
  // camel case svg element tag names
@@ -5439,6 +5475,22 @@ function getTagName(n2) {
5439
5475
  }
5440
5476
  return tagName;
5441
5477
  }
5478
+ function adaptCssForReplay(cssText, cache) {
5479
+ const cachedStyle = cache == null ? void 0 : cache.stylesWithHoverClass.get(cssText);
5480
+ if (cachedStyle) return cachedStyle;
5481
+ let result2 = cssText;
5482
+ try {
5483
+ const ast = postcss$1([
5484
+ mediaSelectorPlugin,
5485
+ pseudoClassPlugin
5486
+ ]).process(cssText, { parser: safeParser });
5487
+ result2 = ast.css;
5488
+ } catch (error) {
5489
+ console.warn("Failed to adapt css for replay", error);
5490
+ }
5491
+ cache == null ? void 0 : cache.stylesWithHoverClass.set(cssText, result2);
5492
+ return result2;
5493
+ }
5442
5494
  function createCache() {
5443
5495
  const stylesWithHoverClass = /* @__PURE__ */ new Map();
5444
5496
  return {
@@ -12033,7 +12085,9 @@ class MutationBuffer {
12033
12085
  this.doc,
12034
12086
  toLowerCase(target.tagName),
12035
12087
  toLowerCase(attributeName),
12036
- value
12088
+ value,
12089
+ target,
12090
+ this.dataURLOptions
12037
12091
  );
12038
12092
  if (attributeName === "style") {
12039
12093
  if (!this.unattachedDoc) {
@@ -12192,6 +12246,11 @@ class MutationBuffer {
12192
12246
  this.shadowDomManager.reset();
12193
12247
  this.canvasManager.reset();
12194
12248
  }
12249
+ destroy() {
12250
+ while (this.mapRemoves.length) {
12251
+ this.mirror.removeNodeFromMap(this.mapRemoves.shift());
12252
+ }
12253
+ }
12195
12254
  }
12196
12255
  function deepDelete(addsSet, n2) {
12197
12256
  addsSet.delete(n2);
@@ -13236,6 +13295,7 @@ function initObservers(o2, hooks = {}) {
13236
13295
  );
13237
13296
  }
13238
13297
  return callbackWrapper(() => {
13298
+ mutationBuffers.forEach((b) => b.destroy());
13239
13299
  mutationBuffers.forEach((b) => b.reset());
13240
13300
  mutationObserver == null ? void 0 : mutationObserver.disconnect();
13241
13301
  mousemoveHandler();
@@ -13573,6 +13633,8 @@ class IframeManager {
13573
13633
  contentWindow.removeEventListener("message", handler);
13574
13634
  });
13575
13635
  this.nestedIframeListeners.clear();
13636
+ this.crossOriginIframeMirror.reset();
13637
+ this.crossOriginIframeStyleMirror.reset();
13576
13638
  }
13577
13639
  }
13578
13640
  class ShadowDomManager {
@@ -14049,6 +14111,8 @@ class CanvasManager {
14049
14111
  __publicField(this, "resetObservers");
14050
14112
  __publicField(this, "frozen", false);
14051
14113
  __publicField(this, "locked", false);
14114
+ __publicField(this, "rafIdTimestamp", null);
14115
+ __publicField(this, "rafIdFlush", null);
14052
14116
  __publicField(this, "processMutation", (target, mutation) => {
14053
14117
  const newFrame = this.rafStamps.invokeId && this.rafStamps.latestId !== this.rafStamps.invokeId;
14054
14118
  if (newFrame || !this.rafStamps.invokeId)
@@ -14083,6 +14147,14 @@ class CanvasManager {
14083
14147
  reset() {
14084
14148
  this.pendingCanvasMutations.clear();
14085
14149
  this.resetObservers && this.resetObservers();
14150
+ if (this.rafIdTimestamp !== null) {
14151
+ cancelAnimationFrame(this.rafIdTimestamp);
14152
+ this.rafIdTimestamp = null;
14153
+ }
14154
+ if (this.rafIdFlush !== null) {
14155
+ cancelAnimationFrame(this.rafIdFlush);
14156
+ this.rafIdFlush = null;
14157
+ }
14086
14158
  }
14087
14159
  freeze() {
14088
14160
  this.frozen = true;
@@ -14233,14 +14305,16 @@ class CanvasManager {
14233
14305
  };
14234
14306
  }
14235
14307
  startPendingCanvasMutationFlusher() {
14236
- requestAnimationFrame(() => this.flushPendingCanvasMutations());
14308
+ this.rafIdFlush = requestAnimationFrame(
14309
+ () => this.flushPendingCanvasMutations()
14310
+ );
14237
14311
  }
14238
14312
  startRAFTimestamping() {
14239
14313
  const setLatestRAFTimestamp = (timestamp) => {
14240
14314
  this.rafStamps.latestId = timestamp;
14241
- requestAnimationFrame(setLatestRAFTimestamp);
14315
+ this.rafIdTimestamp = requestAnimationFrame(setLatestRAFTimestamp);
14242
14316
  };
14243
- requestAnimationFrame(setLatestRAFTimestamp);
14317
+ this.rafIdTimestamp = requestAnimationFrame(setLatestRAFTimestamp);
14244
14318
  }
14245
14319
  flushPendingCanvasMutations() {
14246
14320
  this.pendingCanvasMutations.forEach(
@@ -14249,7 +14323,9 @@ class CanvasManager {
14249
14323
  this.flushPendingCanvasMutationFor(canvas, id);
14250
14324
  }
14251
14325
  );
14252
- requestAnimationFrame(() => this.flushPendingCanvasMutations());
14326
+ this.rafIdFlush = requestAnimationFrame(
14327
+ () => this.flushPendingCanvasMutations()
14328
+ );
14253
14329
  }
14254
14330
  flushPendingCanvasMutationFor(canvas, id) {
14255
14331
  if (this.frozen || this.locked) {
@@ -14384,7 +14460,7 @@ function record(options = {}) {
14384
14460
  hooks,
14385
14461
  packFn,
14386
14462
  sampling = {},
14387
- dataURLOptions = {},
14463
+ dataURLOptions: _dataURLOptions = {},
14388
14464
  mousemoveWait,
14389
14465
  recordDOM = true,
14390
14466
  recordCanvas = false,
@@ -14399,6 +14475,11 @@ function record(options = {}) {
14399
14475
  errorHandler: errorHandler2
14400
14476
  } = options;
14401
14477
  registerErrorHandler(errorHandler2);
14478
+ const dataURLOptions = __spreadValues({
14479
+ type: "image/webp",
14480
+ quality: 0.4,
14481
+ maxBase64ImageLength: 1048576
14482
+ }, _dataURLOptions);
14402
14483
  const inEmittingFrame = recordCrossOriginIframes ? window.parent === window : true;
14403
14484
  let passEmitsToParent = false;
14404
14485
  if (!inEmittingFrame) {
@@ -14815,6 +14896,7 @@ function record(options = {}) {
14815
14896
  processedNodeManager.destroy();
14816
14897
  iframeManager.removeLoadListener();
14817
14898
  iframeManager.destroy();
14899
+ mirror.reset();
14818
14900
  recording = false;
14819
14901
  unregisterErrorHandler();
14820
14902
  };