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:
committed by
GitHub
parent
a5d1215bd1
commit
b0dc3885d9
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user