Fixes and tweaks (#795)

* Implemented image restore from rr_dataURL

* Implement saving images in the snapshot

* Fixed image saving, added a test

* Rename data-src to data-rrweb-src

* Updated the guide

* Rename recordImages to inlineImages and try catch

* A fix, some tweaks and 2 new log warnings

* Handle CORS errors when reading CSS rules

* Fix after merge

* Improve try catch for the inline image

* PR comments tweaks

* Fix typescript lint

* Small tweaks

* Fix a log warning
This commit is contained in:
Cristi Constantin
2022-01-28 02:26:23 +00:00
committed by GitHub
parent a5d1215bd1
commit b0dc3885d9

View File

@@ -64,8 +64,16 @@ function isCSSImportRule(rule: CSSRule): rule is CSSImportRule {
return 'styleSheet' in rule; return 'styleSheet' in rule;
} }
function stringifyStyleSheet(sheet: CSSStyleSheet): string {
return sheet.cssRules
? Array.from(sheet.cssRules)
.map((rule) => rule.cssText || '')
.join('')
: '';
}
function extractOrigin(url: string): string { function extractOrigin(url: string): string {
let origin; let origin = '';
if (url.indexOf('//') > -1) { if (url.indexOf('//') > -1) {
origin = url.split('/').slice(0, 3).join('/'); origin = url.split('/').slice(0, 3).join('/');
} else { } else {
@@ -352,14 +360,6 @@ function onceIframeLoaded(
iframeEl.addEventListener('load', listener); iframeEl.addEventListener('load', listener);
} }
function stringifyStyleSheet(sheet: CSSStyleSheet): string {
return sheet.cssRules
? Array.from(sheet.cssRules)
.map((rule) => rule.cssText || '')
.join('')
: '';
}
function serializeNode( function serializeNode(
n: Node, n: Node,
options: { options: {
@@ -437,7 +437,10 @@ function serializeNode(
const stylesheet = Array.from(doc.styleSheets).find((s) => { const stylesheet = Array.from(doc.styleSheets).find((s) => {
return s.href === (n as HTMLLinkElement).href; return s.href === (n as HTMLLinkElement).href;
}); });
const cssText = getCssRulesString(stylesheet as CSSStyleSheet); let cssText: string | null = null;
if (stylesheet) {
cssText = getCssRulesString(stylesheet as CSSStyleSheet);
}
if (cssText) { if (cssText) {
delete attributes.rel; delete attributes.rel;
delete attributes.href; delete attributes.href;
@@ -512,12 +515,17 @@ function serializeNode(
const image = n as HTMLImageElement; const image = n as HTMLImageElement;
const oldValue = image.crossOrigin; const oldValue = image.crossOrigin;
image.crossOrigin = 'anonymous'; image.crossOrigin = 'anonymous';
try {
const recordInlineImage = () => { const recordInlineImage = () => {
try {
canvasService!.width = image.naturalWidth; canvasService!.width = image.naturalWidth;
canvasService!.height = image.naturalHeight; canvasService!.height = image.naturalHeight;
canvasCtx!.drawImage(image, 0, 0); canvasCtx!.drawImage(image, 0, 0);
attributes.rr_dataURL = canvasService!.toDataURL(); attributes.rr_dataURL = canvasService!.toDataURL();
} catch (err) {
console.warn(
`Cannot inline img src=${image.currentSrc}! Error: ${err}`,
);
}
oldValue oldValue
? (attributes.crossOrigin = oldValue) ? (attributes.crossOrigin = oldValue)
: delete attributes.crossOrigin; : delete attributes.crossOrigin;
@@ -525,9 +533,6 @@ function serializeNode(
// The image content may not have finished loading yet. // The image content may not have finished loading yet.
if (image.complete && image.naturalWidth !== 0) recordInlineImage(); if (image.complete && image.naturalWidth !== 0) recordInlineImage();
else image.onload = recordInlineImage; else image.onload = recordInlineImage;
} catch {
// ignore error
}
} }
// media elements // media elements
if (tagName === 'audio' || tagName === 'video') { if (tagName === 'audio' || tagName === 'video') {
@@ -586,8 +591,8 @@ function serializeNode(
(n.parentNode as HTMLStyleElement).sheet!, (n.parentNode as HTMLStyleElement).sheet!,
); );
} }
} catch { } catch (err) {
// ignore error console.warn(`Cannot get CSS styles from text's parentNode. Error: ${err}`, n);
} }
textContent = absoluteToStylesheet(textContent, getHref()); textContent = absoluteToStylesheet(textContent, getHref());
} }