From 3b7a8ad0acd27aba6e7699932d8a48a3721f957e Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Fri, 30 Oct 2020 14:49:35 +0800 Subject: [PATCH 1/6] pick nested branch --- src/rebuild.ts | 72 +++++++++++++++++++++++++++++++++++++++++++------ src/snapshot.ts | 37 +++++++++++++++++++++++++ src/types.ts | 9 +++++-- 3 files changed, 108 insertions(+), 10 deletions(-) diff --git a/src/rebuild.ts b/src/rebuild.ts index b09d423..e1b2785 100644 --- a/src/rebuild.ts +++ b/src/rebuild.ts @@ -6,6 +6,7 @@ import { elementNode, idNodeMap, INode, + CallbackArray, } from './types'; const tagMap: tagMap = { @@ -75,6 +76,32 @@ export function addHoverClass(cssText: string): string { return cssText; } +function isIframe(n: serializedNodeWithId) { + return n.type === NodeType.Element && n.tagName === 'iframe'; +} + +function buildIframe( + iframe: HTMLIFrameElement, + childNodes: serializedNodeWithId[], + options: { + map: idNodeMap; + cbs: CallbackArray; + hackCss: boolean; + }, +) { + const { map, cbs, hackCss } = options; + const targetDoc = iframe.contentDocument!; + for (const childN of childNodes) { + buildNodeWithSN(childN, { + doc: targetDoc, + map, + cbs, + skipChild: false, + hackCss, + }); + } +} + function buildNode( n: serializedNodeWithId, options: { @@ -196,14 +223,21 @@ export function buildNodeWithSN( options: { doc: Document; map: idNodeMap; + cbs: CallbackArray; skipChild?: boolean; hackCss: boolean; }, -): INode | null { - const { doc, map, skipChild = false, hackCss = true } = options; +): [INode | null, serializedNodeWithId[]] { + const { doc, map, skipChild = false, hackCss = true, cbs } = options; let node = buildNode(n, { doc, hackCss }); if (!node) { - return null; + return [null, []]; + } + if (n.rootId) { + console.assert( + ((map[n.rootId] as unknown) as Document) === doc, + 'Target document should has the same root id.', + ); } // use target document as root document if (n.type === NodeType.Document) { @@ -219,21 +253,40 @@ export function buildNodeWithSN( (n.type === NodeType.Document || n.type === NodeType.Element) && !skipChild ) { + const nodeIsIframe = isIframe(n); + if (nodeIsIframe) { + return [node as INode, n.childNodes]; + } for (const childN of n.childNodes) { - const childNode = buildNodeWithSN(childN, { + const [childNode, nestedNodes] = buildNodeWithSN(childN, { doc, map, + cbs, skipChild: false, hackCss, }); if (!childNode) { console.warn('Failed to rebuild', childN); - } else { - node.appendChild(childNode); + continue; + } + + node.appendChild(childNode); + if (nestedNodes.length === 0) { + continue; + } + const childNodeIsIframe = isIframe(childN); + if (childNodeIsIframe) { + cbs.push(() => + buildIframe( + (childNode as unknown) as HTMLIFrameElement, + nestedNodes, + { map, cbs, hackCss }, + ), + ); } } } - return node as INode; + return [node as INode, []]; } function visit(idNodeMap: idNodeMap, onVisit: (node: INode) => void) { @@ -278,12 +331,15 @@ function rebuild( ): [Node | null, idNodeMap] { const { doc, onVisit, hackCss = true } = options; const idNodeMap: idNodeMap = {}; - const node = buildNodeWithSN(n, { + const callbackArray: CallbackArray = []; + const [node] = buildNodeWithSN(n, { doc, map: idNodeMap, + cbs: callbackArray, skipChild: false, hackCss, }); + callbackArray.forEach((f) => f()); visit(idNodeMap, (visitedNode) => { if (onVisit) { onVisit(visitedNode); diff --git a/src/snapshot.ts b/src/snapshot.ts index fcfb9f5..f2c9bd4 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -215,11 +215,18 @@ function serializeNode( maskInputOptions = {}, recordCanvas, } = options; + // Only record root id when document object is not the base document + let rootId: number | undefined; + if (((doc as unknown) as INode).__sn) { + const docId = ((doc as unknown) as INode).__sn.id; + rootId = docId === 1 ? undefined : docId; + } switch (n.nodeType) { case n.DOCUMENT_NODE: return { type: NodeType.Document, childNodes: [], + rootId, }; case n.DOCUMENT_TYPE_NODE: return { @@ -227,6 +234,7 @@ function serializeNode( name: (n as DocumentType).name, publicId: (n as DocumentType).publicId, systemId: (n as DocumentType).systemId, + rootId, }; case n.ELEMENT_NODE: const needBlock = _isBlockedElement( @@ -333,6 +341,7 @@ function serializeNode( childNodes: [], isSVG: isSVGElement(n as Element) || undefined, needBlock, + rootId, }; case n.TEXT_NODE: // The parent node may not be a html element which has a tagName attribute. @@ -351,16 +360,19 @@ function serializeNode( type: NodeType.Text, textContent: textContent || '', isStyle, + rootId, }; case n.CDATA_SECTION_NODE: return { type: NodeType.CDATA, textContent: '', + rootId, }; case n.COMMENT_NODE: return { type: NodeType.Comment, textContent: (n as Comment).textContent || '', + rootId, }; default: return false; @@ -558,6 +570,31 @@ export function serializeNodeWithId( } } } + + if ( + serializedNode.type === NodeType.Element && + serializedNode.tagName === 'iframe' + ) { + const iframeDoc = (n as HTMLIFrameElement).contentDocument; + if (iframeDoc) { + const serializedIframeNode = serializeNodeWithId(iframeDoc, { + doc: iframeDoc, + map, + blockClass, + blockSelector, + skipChild: false, + inlineStylesheet, + maskInputOptions, + slimDOMOptions, + recordCanvas, + preserveWhiteSpace, + }); + if (serializedIframeNode) { + serializedNode.childNodes.push(serializedIframeNode); + } + } + } + return serializedNode; } diff --git a/src/types.ts b/src/types.ts index 9a53c01..12aed75 100644 --- a/src/types.ts +++ b/src/types.ts @@ -47,13 +47,16 @@ export type commentNode = { textContent: string; }; -export type serializedNode = +export type serializedNode = ( | documentNode | documentTypeNode | elementNode | textNode | cdataNode - | commentNode; + | commentNode +) & { + rootId?: number; +}; export type serializedNodeWithId = serializedNode & { id: number }; @@ -100,3 +103,5 @@ export type SlimDOMOptions = Partial<{ headMetaAuthorship: boolean; headMetaVerification: boolean; }>; + +export type CallbackArray = T[]; From 62ff5cd0d561b8a57025f3f6c75fa0cd673de921 Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Wed, 4 Nov 2020 14:25:28 +0800 Subject: [PATCH 2/6] iframe snapshot --- src/rebuild.ts | 10 ++++++---- src/snapshot.ts | 11 +++++++++++ typings/rebuild.d.ts | 5 +++-- typings/snapshot.d.ts | 3 +++ typings/types.d.ts | 5 ++++- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/rebuild.ts b/src/rebuild.ts index e1b2785..8471492 100644 --- a/src/rebuild.ts +++ b/src/rebuild.ts @@ -249,14 +249,16 @@ export function buildNodeWithSN( (node as INode).__sn = n; map[n.id] = node as INode; + + const nodeIsIframe = isIframe(n); + if (n.type === NodeType.Element && nodeIsIframe) { + return [node as INode, n.childNodes]; + } + if ( (n.type === NodeType.Document || n.type === NodeType.Element) && !skipChild ) { - const nodeIsIframe = isIframe(n); - if (nodeIsIframe) { - return [node as INode, n.childNodes]; - } for (const childN of n.childNodes) { const [childNode, nestedNodes] = buildNodeWithSN(childN, { doc, diff --git a/src/snapshot.ts b/src/snapshot.ts index f2c9bd4..a29c046 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -484,6 +484,7 @@ export function serializeNodeWithId( slimDOMOptions: SlimDOMOptions; recordCanvas?: boolean; preserveWhiteSpace?: boolean; + onSerialize?: (n: INode) => unknown; }, ): serializedNodeWithId | null { const { @@ -496,6 +497,7 @@ export function serializeNodeWithId( maskInputOptions = {}, slimDOMOptions, recordCanvas = false, + onSerialize, } = options; let { preserveWhiteSpace = true } = options; const _serializedNode = serializeNode(n, { @@ -533,6 +535,9 @@ export function serializeNodeWithId( return null; // slimDOM } map[id] = n as INode; + if (onSerialize) { + onSerialize(n as INode); + } let recordChild = !skipChild; if (serializedNode.type === NodeType.Element) { recordChild = recordChild && !serializedNode.needBlock; @@ -607,6 +612,8 @@ function snapshot( slimDOM?: boolean | SlimDOMOptions; recordCanvas?: boolean; blockSelector?: string | null; + preserveWhiteSpace?: boolean; + onSerialize?: (n: INode) => unknown; }, ): [serializedNodeWithId | null, idNodeMap] { const { @@ -616,6 +623,8 @@ function snapshot( blockSelector = null, maskAllInputs = false, slimDOM = false, + preserveWhiteSpace, + onSerialize, } = options || {}; const idNodeMap: idNodeMap = {}; const maskInputOptions: MaskInputOptions = @@ -669,6 +678,8 @@ function snapshot( maskInputOptions, slimDOMOptions, recordCanvas, + preserveWhiteSpace, + onSerialize, }), idNodeMap, ]; diff --git a/typings/rebuild.d.ts b/typings/rebuild.d.ts index 35eb602..ad26d99 100644 --- a/typings/rebuild.d.ts +++ b/typings/rebuild.d.ts @@ -1,11 +1,12 @@ -import { serializedNodeWithId, idNodeMap, INode } from './types'; +import { serializedNodeWithId, idNodeMap, INode, CallbackArray } from './types'; export declare function addHoverClass(cssText: string): string; export declare function buildNodeWithSN(n: serializedNodeWithId, options: { doc: Document; map: idNodeMap; + cbs: CallbackArray; skipChild?: boolean; hackCss: boolean; -}): INode | null; +}): [INode | null, serializedNodeWithId[]]; declare function rebuild(n: serializedNodeWithId, options: { doc: Document; onVisit?: (node: INode) => unknown; diff --git a/typings/snapshot.d.ts b/typings/snapshot.d.ts index 8ae27a3..db2bff7 100644 --- a/typings/snapshot.d.ts +++ b/typings/snapshot.d.ts @@ -15,6 +15,7 @@ export declare function serializeNodeWithId(n: Node | INode, options: { slimDOMOptions: SlimDOMOptions; recordCanvas?: boolean; preserveWhiteSpace?: boolean; + onSerialize?: (n: INode) => unknown; }): serializedNodeWithId | null; declare function snapshot(n: Document, options?: { blockClass?: string | RegExp; @@ -23,6 +24,8 @@ declare function snapshot(n: Document, options?: { slimDOM?: boolean | SlimDOMOptions; recordCanvas?: boolean; blockSelector?: string | null; + preserveWhiteSpace?: boolean; + onSerialize?: (n: INode) => unknown; }): [serializedNodeWithId | null, idNodeMap]; export declare function visitSnapshot(node: serializedNodeWithId, onVisit: (node: serializedNodeWithId) => unknown): void; export declare function cleanupSnapshot(): void; diff --git a/typings/types.d.ts b/typings/types.d.ts index 256abba..1516929 100644 --- a/typings/types.d.ts +++ b/typings/types.d.ts @@ -40,7 +40,9 @@ export declare type commentNode = { type: NodeType.Comment; textContent: string; }; -export declare type serializedNode = documentNode | documentTypeNode | elementNode | textNode | cdataNode | commentNode; +export declare type serializedNode = (documentNode | documentTypeNode | elementNode | textNode | cdataNode | commentNode) & { + rootId?: number; +}; export declare type serializedNodeWithId = serializedNode & { id: number; }; @@ -82,3 +84,4 @@ export declare type SlimDOMOptions = Partial<{ headMetaAuthorship: boolean; headMetaVerification: boolean; }>; +export declare type CallbackArray = T[]; From 05d405004a8a389d1874c8976fddc8fd3ae7ae4a Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Wed, 4 Nov 2020 14:26:02 +0800 Subject: [PATCH 3/6] temp: add bundle file to git --- .gitignore | 6 +- dist/rrweb-snapshot.js | 1214 ++++++++++++++++++++++++++++++++ dist/rrweb-snapshot.min.js | 2 + dist/rrweb-snapshot.min.js.map | 1 + es/rrweb-snapshot.js | 1200 +++++++++++++++++++++++++++++++ es/rrweb-snapshot.min.js | 2 + es/rrweb-snapshot.min.js.map | 1 + lib/rrweb-snapshot.js | 1211 +++++++++++++++++++++++++++++++ 8 files changed, 3634 insertions(+), 3 deletions(-) create mode 100644 dist/rrweb-snapshot.js create mode 100644 dist/rrweb-snapshot.min.js create mode 100644 dist/rrweb-snapshot.min.js.map create mode 100644 es/rrweb-snapshot.js create mode 100644 es/rrweb-snapshot.min.js create mode 100644 es/rrweb-snapshot.min.js.map create mode 100644 lib/rrweb-snapshot.js diff --git a/.gitignore b/.gitignore index 2c597d0..8a1f68e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,6 @@ node_modules package-lock.json build -dist -es -lib +# dist +# es +# lib diff --git a/dist/rrweb-snapshot.js b/dist/rrweb-snapshot.js new file mode 100644 index 0000000..596e720 --- /dev/null +++ b/dist/rrweb-snapshot.js @@ -0,0 +1,1214 @@ +var rrwebSnapshot = (function (exports) { + 'use strict'; + + (function (NodeType) { + NodeType[NodeType["Document"] = 0] = "Document"; + NodeType[NodeType["DocumentType"] = 1] = "DocumentType"; + NodeType[NodeType["Element"] = 2] = "Element"; + NodeType[NodeType["Text"] = 3] = "Text"; + NodeType[NodeType["CDATA"] = 4] = "CDATA"; + NodeType[NodeType["Comment"] = 5] = "Comment"; + })(exports.NodeType || (exports.NodeType = {})); + + var _id = 1; + var tagNameRegex = RegExp('[^a-z1-6-_]'); + var IGNORED_NODE = -2; + function genId() { + return _id++; + } + function getValidTagName(tagName) { + var processedTagName = tagName.toLowerCase().trim(); + if (tagNameRegex.test(processedTagName)) { + return 'div'; + } + return processedTagName; + } + function getCssRulesString(s) { + try { + var rules = s.rules || s.cssRules; + return rules ? Array.from(rules).map(getCssRuleString).join('') : null; + } + catch (error) { + return null; + } + } + function getCssRuleString(rule) { + return isCSSImportRule(rule) + ? getCssRulesString(rule.styleSheet) || '' + : rule.cssText; + } + function isCSSImportRule(rule) { + return 'styleSheet' in rule; + } + function extractOrigin(url) { + var origin; + if (url.indexOf('//') > -1) { + origin = url.split('/').slice(0, 3).join('/'); + } + else { + origin = url.split('/')[0]; + } + origin = origin.split('?')[0]; + return origin; + } + var URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm; + var RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/; + var DATA_URI = /^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i; + function absoluteToStylesheet(cssText, href) { + return (cssText || '').replace(URL_IN_CSS_REF, function (origin, quote1, path1, quote2, path2, path3) { + var filePath = path1 || path2 || path3; + var maybe_quote = quote1 || quote2 || ''; + if (!filePath) { + return origin; + } + if (!RELATIVE_PATH.test(filePath)) { + return "url(" + maybe_quote + filePath + maybe_quote + ")"; + } + if (DATA_URI.test(filePath)) { + return "url(" + maybe_quote + filePath + maybe_quote + ")"; + } + if (filePath[0] === '/') { + return "url(" + maybe_quote + (extractOrigin(href) + filePath) + maybe_quote + ")"; + } + var stack = href.split('/'); + var parts = filePath.split('/'); + stack.pop(); + for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { + var part = parts_1[_i]; + if (part === '.') { + continue; + } + else if (part === '..') { + stack.pop(); + } + else { + stack.push(part); + } + } + return "url(" + maybe_quote + stack.join('/') + maybe_quote + ")"; + }); + } + function getAbsoluteSrcsetString(doc, attributeValue) { + if (attributeValue.trim() === '') { + return attributeValue; + } + var srcsetValues = attributeValue.split(','); + var resultingSrcsetString = srcsetValues + .map(function (srcItem) { + var trimmedSrcItem = srcItem.trimLeft().trimRight(); + var urlAndSize = trimmedSrcItem.split(' '); + if (urlAndSize.length === 2) { + var absUrl = absoluteToDoc(doc, urlAndSize[0]); + return absUrl + " " + urlAndSize[1]; + } + else if (urlAndSize.length === 1) { + var absUrl = absoluteToDoc(doc, urlAndSize[0]); + return "" + absUrl; + } + return ''; + }) + .join(', '); + return resultingSrcsetString; + } + function absoluteToDoc(doc, attributeValue) { + if (!attributeValue || attributeValue.trim() === '') { + return attributeValue; + } + var a = doc.createElement('a'); + a.href = attributeValue; + return a.href; + } + function isSVGElement(el) { + return el.tagName === 'svg' || el instanceof SVGElement; + } + function transformAttribute(doc, name, value) { + if (name === 'src' || (name === 'href' && value)) { + return absoluteToDoc(doc, value); + } + else if (name === 'srcset' && value) { + return getAbsoluteSrcsetString(doc, value); + } + else if (name === 'style' && value) { + return absoluteToStylesheet(value, location.href); + } + else { + return value; + } + } + function _isBlockedElement(element, blockClass, blockSelector) { + if (typeof blockClass === 'string') { + if (element.classList.contains(blockClass)) { + return true; + } + } + else { + element.classList.forEach(function (className) { + if (blockClass.test(className)) { + return true; + } + }); + } + if (blockSelector) { + return element.matches(blockSelector); + } + return false; + } + function serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas) { + if (maskInputOptions === void 0) { maskInputOptions = {}; } + var rootId; + if (doc.__sn) { + var docId = doc.__sn.id; + rootId = docId === 1 ? undefined : docId; + } + switch (n.nodeType) { + case n.DOCUMENT_NODE: + return { + type: exports.NodeType.Document, + childNodes: [], + rootId: rootId + }; + case n.DOCUMENT_TYPE_NODE: + return { + type: exports.NodeType.DocumentType, + name: n.name, + publicId: n.publicId, + systemId: n.systemId, + rootId: rootId + }; + case n.ELEMENT_NODE: + var needBlock = _isBlockedElement(n, blockClass, blockSelector); + var tagName = getValidTagName(n.tagName); + var attributes_1 = {}; + for (var _i = 0, _a = Array.from(n.attributes); _i < _a.length; _i++) { + var _b = _a[_i], name = _b.name, value = _b.value; + attributes_1[name] = transformAttribute(doc, name, value); + } + if (tagName === 'link' && inlineStylesheet) { + var stylesheet = Array.from(doc.styleSheets).find(function (s) { + return s.href === n.href; + }); + var cssText = getCssRulesString(stylesheet); + if (cssText) { + delete attributes_1.rel; + delete attributes_1.href; + attributes_1._cssText = absoluteToStylesheet(cssText, stylesheet.href); + } + } + if (tagName === 'style' && + n.sheet && + !(n.innerText || + n.textContent || + '').trim().length) { + var cssText = getCssRulesString(n.sheet); + if (cssText) { + attributes_1._cssText = absoluteToStylesheet(cssText, location.href); + } + } + if (tagName === 'input' || + tagName === 'textarea' || + tagName === 'select') { + var value = n.value; + if (attributes_1.type !== 'radio' && + attributes_1.type !== 'checkbox' && + attributes_1.type !== 'submit' && + attributes_1.type !== 'button' && + value) { + attributes_1.value = + maskInputOptions[attributes_1.type] || + maskInputOptions[tagName] + ? '*'.repeat(value.length) + : value; + } + else if (n.checked) { + attributes_1.checked = n.checked; + } + } + if (tagName === 'option') { + var selectValue = n.parentElement; + if (attributes_1.value === selectValue.value) { + attributes_1.selected = n.selected; + } + } + if (tagName === 'canvas' && recordCanvas) { + attributes_1.rr_dataURL = n.toDataURL(); + } + if (tagName === 'audio' || tagName === 'video') { + attributes_1.rr_mediaState = n.paused + ? 'paused' + : 'played'; + } + if (n.scrollLeft) { + attributes_1.rr_scrollLeft = n.scrollLeft; + } + if (n.scrollTop) { + attributes_1.rr_scrollTop = n.scrollTop; + } + if (needBlock) { + var _c = n.getBoundingClientRect(), width = _c.width, height = _c.height; + attributes_1.rr_width = width + "px"; + attributes_1.rr_height = height + "px"; + } + return { + type: exports.NodeType.Element, + tagName: tagName, + attributes: attributes_1, + childNodes: [], + isSVG: isSVGElement(n) || undefined, + needBlock: needBlock, + rootId: rootId + }; + case n.TEXT_NODE: + var parentTagName = n.parentNode && n.parentNode.tagName; + var textContent = n.textContent; + var isStyle = parentTagName === 'STYLE' ? true : undefined; + if (isStyle && textContent) { + textContent = absoluteToStylesheet(textContent, location.href); + } + if (parentTagName === 'SCRIPT') { + textContent = 'SCRIPT_PLACEHOLDER'; + } + return { + type: exports.NodeType.Text, + textContent: textContent || '', + isStyle: isStyle, + rootId: rootId + }; + case n.CDATA_SECTION_NODE: + return { + type: exports.NodeType.CDATA, + textContent: '', + rootId: rootId + }; + case n.COMMENT_NODE: + return { + type: exports.NodeType.Comment, + textContent: n.textContent || '', + rootId: rootId + }; + default: + return false; + } + } + function lowerIfExists(maybeAttr) { + if (maybeAttr === undefined) { + return ''; + } + else { + return maybeAttr.toLowerCase(); + } + } + function slimDOMExcluded(sn, slimDOMOptions) { + if (slimDOMOptions.comment && sn.type === exports.NodeType.Comment) { + return true; + } + else if (sn.type === exports.NodeType.Element) { + if (slimDOMOptions.script && + (sn.tagName === 'script' || + (sn.tagName === 'link' && + sn.attributes.rel === 'preload' && + sn.attributes['as'] === 'script'))) { + return true; + } + else if (slimDOMOptions.headFavicon && + ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') || + (sn.tagName === 'meta' && + (lowerIfExists(sn.attributes['name']).match(/^msapplication-tile(image|color)$/) || + lowerIfExists(sn.attributes['name']) === 'application-name' || + lowerIfExists(sn.attributes['rel']) === 'icon' || + lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' || + lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))) { + return true; + } + else if (sn.tagName === 'meta') { + if (slimDOMOptions.headMetaDescKeywords && + lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)) { + return true; + } + else if (slimDOMOptions.headMetaSocial && + (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || + lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) || + lowerIfExists(sn.attributes['name']) === 'pinterest')) { + return true; + } + else if (slimDOMOptions.headMetaRobots && + (lowerIfExists(sn.attributes['name']) === 'robots' || + lowerIfExists(sn.attributes['name']) === 'googlebot' || + lowerIfExists(sn.attributes['name']) === 'bingbot')) { + return true; + } + else if (slimDOMOptions.headMetaHttpEquiv && + sn.attributes['http-equiv'] !== undefined) { + return true; + } + else if (slimDOMOptions.headMetaAuthorship && + (lowerIfExists(sn.attributes['name']) === 'author' || + lowerIfExists(sn.attributes['name']) === 'generator' || + lowerIfExists(sn.attributes['name']) === 'framework' || + lowerIfExists(sn.attributes['name']) === 'publisher' || + lowerIfExists(sn.attributes['name']) === 'progid' || + lowerIfExists(sn.attributes['property']).match(/^article:/) || + lowerIfExists(sn.attributes['property']).match(/^product:/))) { + return true; + } + else if (slimDOMOptions.headMetaVerification && + (lowerIfExists(sn.attributes['name']) === 'google-site-verification' || + lowerIfExists(sn.attributes['name']) === 'yandex-verification' || + lowerIfExists(sn.attributes['name']) === 'csrf-token' || + lowerIfExists(sn.attributes['name']) === 'p:domain_verify' || + lowerIfExists(sn.attributes['name']) === 'verify-v1' || + lowerIfExists(sn.attributes['name']) === 'verification' || + lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')) { + return true; + } + } + } + return false; + } + function serializeNodeWithId(n, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize) { + if (skipChild === void 0) { skipChild = false; } + if (inlineStylesheet === void 0) { inlineStylesheet = true; } + if (slimDOMOptions === void 0) { slimDOMOptions = {}; } + if (preserveWhiteSpace === void 0) { preserveWhiteSpace = true; } + var _serializedNode = serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas || false); + if (!_serializedNode) { + console.warn(n, 'not serialized'); + return null; + } + var id; + if ('__sn' in n) { + id = n.__sn.id; + } + else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || + (!preserveWhiteSpace && + _serializedNode.type === exports.NodeType.Text && + !_serializedNode.isStyle && + !_serializedNode.textContent.replace(/^\s+|\s+$/gm, '').length)) { + id = IGNORED_NODE; + } + else { + id = genId(); + } + var serializedNode = Object.assign(_serializedNode, { id: id }); + n.__sn = serializedNode; + if (id === IGNORED_NODE) { + return null; + } + map[id] = n; + if (onSerialize) { + onSerialize(n); + } + var recordChild = !skipChild; + if (serializedNode.type === exports.NodeType.Element) { + recordChild = recordChild && !serializedNode.needBlock; + delete serializedNode.needBlock; + } + if ((serializedNode.type === exports.NodeType.Document || + serializedNode.type === exports.NodeType.Element) && + recordChild) { + if (slimDOMOptions.headWhitespace && + _serializedNode.type === exports.NodeType.Element && + _serializedNode.tagName == 'head') { + preserveWhiteSpace = false; + } + for (var _i = 0, _a = Array.from(n.childNodes); _i < _a.length; _i++) { + var childN = _a[_i]; + var serializedChildNode = serializeNodeWithId(childN, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace); + if (serializedChildNode) { + serializedNode.childNodes.push(serializedChildNode); + } + } + } + if (serializedNode.type === exports.NodeType.Element && + serializedNode.tagName === 'iframe') { + var iframeDoc = n.contentDocument; + if (iframeDoc) { + var serializedIframeNode = serializeNodeWithId(iframeDoc, iframeDoc, map, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas); + if (serializedIframeNode) { + serializedNode.childNodes.push(serializedIframeNode); + } + } + } + return serializedNode; + } + function snapshot(n, blockClass, inlineStylesheet, maskAllInputsOrOptions, slimDOMSensibleOrOptions, recordCanvas, blockSelector, preserveWhiteSpace, onSerialize) { + if (blockClass === void 0) { blockClass = 'rr-block'; } + if (inlineStylesheet === void 0) { inlineStylesheet = true; } + if (blockSelector === void 0) { blockSelector = null; } + var idNodeMap = {}; + var maskInputOptions = maskAllInputsOrOptions === true + ? { + color: true, + date: true, + 'datetime-local': true, + email: true, + month: true, + number: true, + range: true, + search: true, + tel: true, + text: true, + time: true, + url: true, + week: true, + textarea: true, + select: true + } + : maskAllInputsOrOptions === false + ? {} + : maskAllInputsOrOptions; + var slimDOMOptions = slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all' + ? + { + script: true, + comment: true, + headFavicon: true, + headWhitespace: true, + headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', + headMetaSocial: true, + headMetaRobots: true, + headMetaHttpEquiv: true, + headMetaAuthorship: true, + headMetaVerification: true + } + : slimDOMSensibleOrOptions === false + ? {} + : slimDOMSensibleOrOptions; + return [ + serializeNodeWithId(n, n, idNodeMap, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize), + idNodeMap, + ]; + } + function visitSnapshot(node, onVisit) { + function walk(current) { + onVisit(current); + if (current.type === exports.NodeType.Document || + current.type === exports.NodeType.Element) { + current.childNodes.forEach(walk); + } + } + walk(node); + } + function cleanupSnapshot() { + _id = 1; + } + + var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; + function parse(css, options) { + if (options === void 0) { options = {}; } + var lineno = 1; + var column = 1; + function updatePosition(str) { + var lines = str.match(/\n/g); + if (lines) { + lineno += lines.length; + } + var i = str.lastIndexOf('\n'); + column = i === -1 ? column + str.length : str.length - i; + } + function position() { + var start = { line: lineno, column: column }; + return function (node) { + node.position = new Position(start); + whitespace(); + return node; + }; + } + var Position = (function () { + function Position(start) { + this.start = start; + this.end = { line: lineno, column: column }; + this.source = options.source; + } + return Position; + }()); + Position.prototype.content = css; + var errorsList = []; + function error(msg) { + var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); + err.reason = msg; + err.filename = options.source; + err.line = lineno; + err.column = column; + err.source = css; + if (options.silent) { + errorsList.push(err); + } + else { + throw err; + } + } + function stylesheet() { + var rulesList = rules(); + return { + type: 'stylesheet', + stylesheet: { + source: options.source, + rules: rulesList, + parsingErrors: errorsList + } + }; + } + function open() { + return match(/^{\s*/); + } + function close() { + return match(/^}/); + } + function rules() { + var node; + var rules = []; + whitespace(); + comments(rules); + while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { + if (node !== false) { + rules.push(node); + comments(rules); + } + } + return rules; + } + function match(re) { + var m = re.exec(css); + if (!m) { + return; + } + var str = m[0]; + updatePosition(str); + css = css.slice(str.length); + return m; + } + function whitespace() { + match(/^\s*/); + } + function comments(rules) { + if (rules === void 0) { rules = []; } + var c; + while ((c = comment())) { + if (c !== false) { + rules.push(c); + } + c = comment(); + } + return rules; + } + function comment() { + var pos = position(); + if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { + return; + } + var i = 2; + while ('' !== css.charAt(i) && + ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))) { + ++i; + } + i += 2; + if ('' === css.charAt(i - 1)) { + return error('End of comment missing'); + } + var str = css.slice(2, i - 2); + column += 2; + updatePosition(str); + css = css.slice(i); + column += 2; + return pos({ + type: 'comment', + comment: str + }); + } + function selector() { + var m = match(/^([^{]+)/); + if (!m) { + return; + } + return trim(m[0]) + .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') + .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) { + return m.replace(/,/g, '\u200C'); + }) + .split(/\s*(?![^(]*\)),\s*/) + .map(function (s) { + return s.replace(/\u200C/g, ','); + }); + } + function declaration() { + var pos = position(); + var propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); + if (!propMatch) { + return; + } + var prop = trim(propMatch[0]); + if (!match(/^:\s*/)) { + return error("property missing ':'"); + } + var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); + var ret = pos({ + type: 'declaration', + property: prop.replace(commentre, ''), + value: val ? trim(val[0]).replace(commentre, '') : '' + }); + match(/^[;\s]*/); + return ret; + } + function declarations() { + var decls = []; + if (!open()) { + return error("missing '{'"); + } + comments(decls); + var decl; + while ((decl = declaration())) { + if (decl !== false) { + decls.push(decl); + comments(decls); + } + decl = declaration(); + } + if (!close()) { + return error("missing '}'"); + } + return decls; + } + function keyframe() { + var m; + var vals = []; + var pos = position(); + while ((m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/))) { + vals.push(m[1]); + match(/^,\s*/); + } + if (!vals.length) { + return; + } + return pos({ + type: 'keyframe', + values: vals, + declarations: declarations() + }); + } + function atkeyframes() { + var pos = position(); + var m = match(/^@([-\w]+)?keyframes\s*/); + if (!m) { + return; + } + var vendor = m[1]; + m = match(/^([-\w]+)\s*/); + if (!m) { + return error('@keyframes missing name'); + } + var name = m[1]; + if (!open()) { + return error("@keyframes missing '{'"); + } + var frame; + var frames = comments(); + while ((frame = keyframe())) { + frames.push(frame); + frames = frames.concat(comments()); + } + if (!close()) { + return error("@keyframes missing '}'"); + } + return pos({ + type: 'keyframes', + name: name, + vendor: vendor, + keyframes: frames + }); + } + function atsupports() { + var pos = position(); + var m = match(/^@supports *([^{]+)/); + if (!m) { + return; + } + var supports = trim(m[1]); + if (!open()) { + return error("@supports missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@supports missing '}'"); + } + return pos({ + type: 'supports', + supports: supports, + rules: style + }); + } + function athost() { + var pos = position(); + var m = match(/^@host\s*/); + if (!m) { + return; + } + if (!open()) { + return error("@host missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@host missing '}'"); + } + return pos({ + type: 'host', + rules: style + }); + } + function atmedia() { + var pos = position(); + var m = match(/^@media *([^{]+)/); + if (!m) { + return; + } + var media = trim(m[1]); + if (!open()) { + return error("@media missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@media missing '}'"); + } + return pos({ + type: 'media', + media: media, + rules: style + }); + } + function atcustommedia() { + var pos = position(); + var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); + if (!m) { + return; + } + return pos({ + type: 'custom-media', + name: trim(m[1]), + media: trim(m[2]) + }); + } + function atpage() { + var pos = position(); + var m = match(/^@page */); + if (!m) { + return; + } + var sel = selector() || []; + if (!open()) { + return error("@page missing '{'"); + } + var decls = comments(); + var decl; + while ((decl = declaration())) { + decls.push(decl); + decls = decls.concat(comments()); + } + if (!close()) { + return error("@page missing '}'"); + } + return pos({ + type: 'page', + selectors: sel, + declarations: decls + }); + } + function atdocument() { + var pos = position(); + var m = match(/^@([-\w]+)?document *([^{]+)/); + if (!m) { + return; + } + var vendor = trim(m[1]); + var doc = trim(m[2]); + if (!open()) { + return error("@document missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@document missing '}'"); + } + return pos({ + type: 'document', + document: doc, + vendor: vendor, + rules: style + }); + } + function atfontface() { + var pos = position(); + var m = match(/^@font-face\s*/); + if (!m) { + return; + } + if (!open()) { + return error("@font-face missing '{'"); + } + var decls = comments(); + var decl; + while ((decl = declaration())) { + decls.push(decl); + decls = decls.concat(comments()); + } + if (!close()) { + return error("@font-face missing '}'"); + } + return pos({ + type: 'font-face', + declarations: decls + }); + } + var atimport = _compileAtrule('import'); + var atcharset = _compileAtrule('charset'); + var atnamespace = _compileAtrule('namespace'); + function _compileAtrule(name) { + var re = new RegExp('^@' + name + '\\s*([^;]+);'); + return function () { + var pos = position(); + var m = match(re); + if (!m) { + return; + } + var ret = { type: name }; + ret[name] = m[1].trim(); + return pos(ret); + }; + } + function atrule() { + if (css[0] !== '@') { + return; + } + return (atkeyframes() || + atmedia() || + atcustommedia() || + atsupports() || + atimport() || + atcharset() || + atnamespace() || + atdocument() || + atpage() || + athost() || + atfontface()); + } + function rule() { + var pos = position(); + var sel = selector(); + if (!sel) { + return error('selector missing'); + } + comments(); + return pos({ + type: 'rule', + selectors: sel, + declarations: declarations() + }); + } + return addParent(stylesheet()); + } + function trim(str) { + return str ? str.replace(/^\s+|\s+$/g, '') : ''; + } + function addParent(obj, parent) { + var isNode = obj && typeof obj.type === 'string'; + var childParent = isNode ? obj : parent; + for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { + var k = _a[_i]; + var value = obj[k]; + if (Array.isArray(value)) { + value.forEach(function (v) { + addParent(v, childParent); + }); + } + else if (value && typeof value === 'object') { + addParent(value, childParent); + } + } + if (isNode) { + Object.defineProperty(obj, 'parent', { + configurable: true, + writable: true, + enumerable: false, + value: parent || null + }); + } + return obj; + } + + var tagMap = { + script: 'noscript', + altglyph: 'altGlyph', + altglyphdef: 'altGlyphDef', + altglyphitem: 'altGlyphItem', + animatecolor: 'animateColor', + animatemotion: 'animateMotion', + animatetransform: 'animateTransform', + clippath: 'clipPath', + feblend: 'feBlend', + fecolormatrix: 'feColorMatrix', + fecomponenttransfer: 'feComponentTransfer', + fecomposite: 'feComposite', + feconvolvematrix: 'feConvolveMatrix', + fediffuselighting: 'feDiffuseLighting', + fedisplacementmap: 'feDisplacementMap', + fedistantlight: 'feDistantLight', + fedropshadow: 'feDropShadow', + feflood: 'feFlood', + fefunca: 'feFuncA', + fefuncb: 'feFuncB', + fefuncg: 'feFuncG', + fefuncr: 'feFuncR', + fegaussianblur: 'feGaussianBlur', + feimage: 'feImage', + femerge: 'feMerge', + femergenode: 'feMergeNode', + femorphology: 'feMorphology', + feoffset: 'feOffset', + fepointlight: 'fePointLight', + fespecularlighting: 'feSpecularLighting', + fespotlight: 'feSpotLight', + fetile: 'feTile', + feturbulence: 'feTurbulence', + foreignobject: 'foreignObject', + glyphref: 'glyphRef', + lineargradient: 'linearGradient', + radialgradient: 'radialGradient' + }; + function getTagName(n) { + var tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; + if (tagName === 'link' && n.attributes._cssText) { + tagName = 'style'; + } + return tagName; + } + var HOVER_SELECTOR = /([^\\]):hover/g; + function addHoverClass(cssText) { + var ast = parse(cssText, { silent: true }); + if (!ast.stylesheet) { + return cssText; + } + ast.stylesheet.rules.forEach(function (rule) { + if ('selectors' in rule) { + (rule.selectors || []).forEach(function (selector) { + if (HOVER_SELECTOR.test(selector)) { + var newSelector = selector.replace(HOVER_SELECTOR, '$1.\\:hover'); + cssText = cssText.replace(selector, selector + ", " + newSelector); + } + }); + } + }); + return cssText; + } + function isIframe(n) { + return n.type === exports.NodeType.Element && n.tagName === 'iframe'; + } + function buildIframe(iframe, childNodes, map, cbs, HACK_CSS) { + var targetDoc = iframe.contentDocument; + for (var _i = 0, childNodes_1 = childNodes; _i < childNodes_1.length; _i++) { + var childN = childNodes_1[_i]; + console.log('build iframe', childN); + buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS); + } + } + function buildNode(n, doc, HACK_CSS) { + switch (n.type) { + case exports.NodeType.Document: + return doc.implementation.createDocument(null, '', null); + case exports.NodeType.DocumentType: + return doc.implementation.createDocumentType(n.name || 'html', n.publicId, n.systemId); + case exports.NodeType.Element: + var tagName = getTagName(n); + var node_1; + if (n.isSVG) { + node_1 = doc.createElementNS('http://www.w3.org/2000/svg', tagName); + } + else { + node_1 = doc.createElement(tagName); + } + var _loop_1 = function (name) { + if (!n.attributes.hasOwnProperty(name)) { + return "continue"; + } + var value = n.attributes[name]; + value = + typeof value === 'boolean' || typeof value === 'number' ? '' : value; + if (!name.startsWith('rr_')) { + var isTextarea = tagName === 'textarea' && name === 'value'; + var isRemoteOrDynamicCss = tagName === 'style' && name === '_cssText'; + if (isRemoteOrDynamicCss && HACK_CSS) { + value = addHoverClass(value); + } + if (isTextarea || isRemoteOrDynamicCss) { + var child = doc.createTextNode(value); + for (var _i = 0, _a = Array.from(node_1.childNodes); _i < _a.length; _i++) { + var c = _a[_i]; + if (c.nodeType === node_1.TEXT_NODE) { + node_1.removeChild(c); + } + } + node_1.appendChild(child); + return "continue"; + } + if (tagName === 'iframe' && name === 'src') { + return "continue"; + } + try { + if (n.isSVG && name === 'xlink:href') { + node_1.setAttributeNS('http://www.w3.org/1999/xlink', name, value); + } + else if (name === 'onload' || + name === 'onclick' || + name.substring(0, 7) === 'onmouse') { + node_1.setAttribute('_' + name, value); + } + else { + node_1.setAttribute(name, value); + } + } + catch (error) { + } + } + else { + if (tagName === 'canvas' && name === 'rr_dataURL') { + var image_1 = document.createElement('img'); + image_1.src = value; + image_1.onload = function () { + var ctx = node_1.getContext('2d'); + if (ctx) { + ctx.drawImage(image_1, 0, 0, image_1.width, image_1.height); + } + }; + } + if (name === 'rr_width') { + node_1.style.width = value; + } + if (name === 'rr_height') { + node_1.style.height = value; + } + if (name === 'rr_mediaState') { + switch (value) { + case 'played': + node_1.play(); + case 'paused': + node_1.pause(); + break; + default: + } + } + } + }; + for (var name in n.attributes) { + _loop_1(name); + } + return node_1; + case exports.NodeType.Text: + return doc.createTextNode(n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent); + case exports.NodeType.CDATA: + return doc.createCDATASection(n.textContent); + case exports.NodeType.Comment: + return doc.createComment(n.textContent); + default: + return null; + } + } + function buildNodeWithSN(n, doc, map, cbs, skipChild, HACK_CSS) { + if (skipChild === void 0) { skipChild = false; } + if (HACK_CSS === void 0) { HACK_CSS = true; } + var node = buildNode(n, doc, HACK_CSS); + if (!node) { + return [null, []]; + } + if (n.rootId) { + console.assert(map[n.rootId] === doc, 'Target document should has the same root id.'); + } + if (n.type === exports.NodeType.Document) { + doc.close(); + doc.open(); + node = doc; + } + node.__sn = n; + map[n.id] = node; + var nodeIsIframe = isIframe(n); + if (n.type === exports.NodeType.Element && nodeIsIframe) { + return [node, n.childNodes]; + } + if ((n.type === exports.NodeType.Document || n.type === exports.NodeType.Element) && + !skipChild) { + var _loop_2 = function (childN) { + var _a = buildNodeWithSN(childN, doc, map, cbs, false, HACK_CSS), childNode = _a[0], nestedNodes = _a[1]; + if (!childNode) { + console.warn('Failed to rebuild', childN); + return "continue"; + } + node.appendChild(childNode); + if (nestedNodes.length === 0) { + return "continue"; + } + var childNodeIsIframe = isIframe(childN); + if (childNodeIsIframe) { + cbs.push(function () { + return buildIframe(childNode, nestedNodes, map, cbs, HACK_CSS); + }); + } + }; + for (var _i = 0, _a = n.childNodes; _i < _a.length; _i++) { + var childN = _a[_i]; + _loop_2(childN); + } + } + return [node, []]; + } + function visit(idNodeMap, onVisit) { + function walk(node) { + onVisit(node); + } + for (var key in idNodeMap) { + if (idNodeMap[key]) { + walk(idNodeMap[key]); + } + } + } + function handleScroll(node) { + var n = node.__sn; + if (n.type !== exports.NodeType.Element) { + return; + } + var el = node; + for (var name in n.attributes) { + if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) { + continue; + } + var value = n.attributes[name]; + if (name === 'rr_scrollLeft') { + el.scrollLeft = value; + } + if (name === 'rr_scrollTop') { + el.scrollTop = value; + } + } + } + function rebuild(n, doc, onVisit, HACK_CSS) { + if (HACK_CSS === void 0) { HACK_CSS = true; } + var idNodeMap = {}; + var callbackArray = []; + var node = buildNodeWithSN(n, doc, idNodeMap, callbackArray, false, HACK_CSS)[0]; + callbackArray.forEach(function (f) { return f(); }); + visit(idNodeMap, function (visitedNode) { + if (onVisit) { + onVisit(visitedNode); + } + handleScroll(visitedNode); + }); + return [node, idNodeMap]; + } + + exports.snapshot = snapshot; + exports.serializeNodeWithId = serializeNodeWithId; + exports.rebuild = rebuild; + exports.buildNodeWithSN = buildNodeWithSN; + exports.addHoverClass = addHoverClass; + exports.transformAttribute = transformAttribute; + exports.visitSnapshot = visitSnapshot; + exports.cleanupSnapshot = cleanupSnapshot; + exports.IGNORED_NODE = IGNORED_NODE; + + return exports; + +}({})); diff --git a/dist/rrweb-snapshot.min.js b/dist/rrweb-snapshot.min.js new file mode 100644 index 0000000..d539c8e --- /dev/null +++ b/dist/rrweb-snapshot.min.js @@ -0,0 +1,2 @@ +var rrwebSnapshot=function(e){"use strict";var t;(t=e.NodeType||(e.NodeType={}))[t.Document=0]="Document",t[t.DocumentType=1]="DocumentType",t[t.Element=2]="Element",t[t.Text=3]="Text",t[t.CDATA=4]="CDATA",t[t.Comment=5]="Comment";var r=1,n=RegExp("[^a-z1-6-_]"),a=-2;function i(e){try{var t=e.rules||e.cssRules;return t?Array.from(t).map(o).join(""):null}catch(e){return null}}function o(e){return function(e){return"styleSheet"in e}(e)?i(e.styleSheet)||"":e.cssText}var s=/url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm,u=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/,c=/^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i;function f(e,t){return(e||"").replace(s,function(e,r,n,a,i,o){var s,f=n||i||o,l=r||a||"";if(!f)return e;if(!u.test(f))return"url("+l+f+l+")";if(c.test(f))return"url("+l+f+l+")";if("/"===f[0])return"url("+l+(((s=t).indexOf("//")>-1?s.split("/").slice(0,3).join("/"):s.split("/")[0]).split("?")[0]+f)+l+")";var p=t.split("/"),m=f.split("/");p.pop();for(var d=0,h=m;d;\n\nexport type SlimDOMOptions = Partial<{\n script: boolean;\n comment: boolean;\n headFavicon: boolean;\n headWhitespace: boolean;\n headMetaDescKeywords: boolean;\n headMetaSocial: boolean;\n headMetaRobots: boolean;\n headMetaHttpEquiv: boolean;\n headMetaAuthorship: boolean;\n headMetaVerification: boolean;\n}>;\n\nexport type CallbackArray = T[];\n","import {\n serializedNode,\n serializedNodeWithId,\n NodeType,\n attributes,\n INode,\n idNodeMap,\n MaskInputOptions,\n SlimDOMOptions,\n} from './types';\n\nlet _id = 1;\nconst tagNameRegex = RegExp('[^a-z1-6-_]');\n\nexport const IGNORED_NODE = -2;\n\nfunction genId(): number {\n return _id++;\n}\n\nfunction getValidTagName(tagName: string): string {\n const processedTagName = tagName.toLowerCase().trim();\n\n if (tagNameRegex.test(processedTagName)) {\n // if the tag name is odd and we cannot extract\n // anything from the string, then we return a\n // generic div\n return 'div';\n }\n\n return processedTagName;\n}\n\nfunction getCssRulesString(s: CSSStyleSheet): string | null {\n try {\n const rules = s.rules || s.cssRules;\n return rules ? Array.from(rules).map(getCssRuleString).join('') : null;\n } catch (error) {\n return null;\n }\n}\n\nfunction getCssRuleString(rule: CSSRule): string {\n return isCSSImportRule(rule)\n ? getCssRulesString(rule.styleSheet) || ''\n : rule.cssText;\n}\n\nfunction isCSSImportRule(rule: CSSRule): rule is CSSImportRule {\n return 'styleSheet' in rule;\n}\n\nfunction extractOrigin(url: string): string {\n let origin;\n if (url.indexOf('//') > -1) {\n origin = url.split('/').slice(0, 3).join('/');\n } else {\n origin = url.split('/')[0];\n }\n origin = origin.split('?')[0];\n return origin;\n}\n\nconst URL_IN_CSS_REF = /url\\((?:(')([^']*)'|(\")([^\"]*)\"|([^)]*))\\)/gm;\nconst RELATIVE_PATH = /^(?!www\\.|(?:http|ftp)s?:\\/\\/|[A-Za-z]:\\\\|\\/\\/).*/;\nconst DATA_URI = /^(data:)([\\w\\/\\+\\-]+);(charset=[\\w-]+|base64|utf-?8).*,(.*)/i;\nexport function absoluteToStylesheet(\n cssText: string | null,\n href: string,\n): string {\n return (cssText || '').replace(\n URL_IN_CSS_REF,\n (origin, quote1, path1, quote2, path2, path3) => {\n const filePath = path1 || path2 || path3;\n const maybe_quote = quote1 || quote2 || '';\n if (!filePath) {\n return origin;\n }\n if (!RELATIVE_PATH.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (DATA_URI.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (filePath[0] === '/') {\n return `url(${maybe_quote}${\n extractOrigin(href) + filePath\n }${maybe_quote})`;\n }\n const stack = href.split('/');\n const parts = filePath.split('/');\n stack.pop();\n for (const part of parts) {\n if (part === '.') {\n continue;\n } else if (part === '..') {\n stack.pop();\n } else {\n stack.push(part);\n }\n }\n return `url(${maybe_quote}${stack.join('/')}${maybe_quote})`;\n },\n );\n}\n\nfunction getAbsoluteSrcsetString(doc: Document, attributeValue: string) {\n if (attributeValue.trim() === '') {\n return attributeValue;\n }\n\n const srcsetValues = attributeValue.split(',');\n // srcset attributes is defined as such:\n // srcset = \"url size,url1 size1\"\n const resultingSrcsetString = srcsetValues\n .map((srcItem) => {\n // removing all but middle spaces\n const trimmedSrcItem = srcItem.trimLeft().trimRight();\n const urlAndSize = trimmedSrcItem.split(' ');\n // this means we have both 0:url and 1:size\n if (urlAndSize.length === 2) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl} ${urlAndSize[1]}`;\n } else if (urlAndSize.length === 1) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl}`;\n }\n return '';\n })\n .join(', ');\n\n return resultingSrcsetString;\n}\n\nexport function absoluteToDoc(doc: Document, attributeValue: string): string {\n if (!attributeValue || attributeValue.trim() === '') {\n return attributeValue;\n }\n const a: HTMLAnchorElement = doc.createElement('a');\n a.href = attributeValue;\n return a.href;\n}\n\nfunction isSVGElement(el: Element): boolean {\n return el.tagName === 'svg' || el instanceof SVGElement;\n}\n\nexport function transformAttribute(\n doc: Document,\n name: string,\n value: string,\n): string {\n // relative path in attribute\n if (name === 'src' || (name === 'href' && value)) {\n return absoluteToDoc(doc, value);\n } else if (name === 'srcset' && value) {\n return getAbsoluteSrcsetString(doc, value);\n } else if (name === 'style' && value) {\n return absoluteToStylesheet(value, location.href);\n } else {\n return value;\n }\n}\n\nexport function _isBlockedElement(\n element: HTMLElement,\n blockClass: string | RegExp,\n blockSelector: string | null,\n): boolean {\n if (typeof blockClass === 'string') {\n if (element.classList.contains(blockClass)) {\n return true;\n }\n } else {\n element.classList.forEach((className) => {\n if (blockClass.test(className)) {\n return true;\n }\n });\n }\n if (blockSelector) {\n return element.matches(blockSelector);\n }\n\n return false;\n}\n\nfunction serializeNode(\n n: Node,\n doc: Document,\n blockClass: string | RegExp,\n blockSelector: string | null,\n inlineStylesheet: boolean,\n maskInputOptions: MaskInputOptions = {},\n recordCanvas: boolean,\n): serializedNode | false {\n // Only record root id when document object is not the base document\n let rootId: number | undefined;\n if (((doc as unknown) as INode).__sn) {\n const docId = ((doc as unknown) as INode).__sn.id;\n rootId = docId === 1 ? undefined : docId;\n }\n switch (n.nodeType) {\n case n.DOCUMENT_NODE:\n return {\n type: NodeType.Document,\n childNodes: [],\n rootId,\n };\n case n.DOCUMENT_TYPE_NODE:\n return {\n type: NodeType.DocumentType,\n name: (n as DocumentType).name,\n publicId: (n as DocumentType).publicId,\n systemId: (n as DocumentType).systemId,\n rootId,\n };\n case n.ELEMENT_NODE:\n const needBlock = _isBlockedElement(\n n as HTMLElement,\n blockClass,\n blockSelector,\n );\n const tagName = getValidTagName((n as HTMLElement).tagName);\n let attributes: attributes = {};\n for (const { name, value } of Array.from((n as HTMLElement).attributes)) {\n attributes[name] = transformAttribute(doc, name, value);\n }\n // remote css\n if (tagName === 'link' && inlineStylesheet) {\n const stylesheet = Array.from(doc.styleSheets).find((s) => {\n return s.href === (n as HTMLLinkElement).href;\n });\n const cssText = getCssRulesString(stylesheet as CSSStyleSheet);\n if (cssText) {\n delete attributes.rel;\n delete attributes.href;\n attributes._cssText = absoluteToStylesheet(\n cssText,\n stylesheet!.href!,\n );\n }\n }\n // dynamic stylesheet\n if (\n tagName === 'style' &&\n (n as HTMLStyleElement).sheet &&\n // TODO: Currently we only try to get dynamic stylesheet when it is an empty style element\n !(\n (n as HTMLElement).innerText ||\n (n as HTMLElement).textContent ||\n ''\n ).trim().length\n ) {\n const cssText = getCssRulesString(\n (n as HTMLStyleElement).sheet as CSSStyleSheet,\n );\n if (cssText) {\n attributes._cssText = absoluteToStylesheet(cssText, location.href);\n }\n }\n // form fields\n if (\n tagName === 'input' ||\n tagName === 'textarea' ||\n tagName === 'select'\n ) {\n const value = (n as HTMLInputElement | HTMLTextAreaElement).value;\n if (\n attributes.type !== 'radio' &&\n attributes.type !== 'checkbox' &&\n attributes.type !== 'submit' &&\n attributes.type !== 'button' &&\n value\n ) {\n attributes.value =\n maskInputOptions[attributes.type as keyof MaskInputOptions] ||\n maskInputOptions[tagName as keyof MaskInputOptions]\n ? '*'.repeat(value.length)\n : value;\n } else if ((n as HTMLInputElement).checked) {\n attributes.checked = (n as HTMLInputElement).checked;\n }\n }\n if (tagName === 'option') {\n const selectValue = (n as HTMLOptionElement).parentElement;\n if (attributes.value === (selectValue as HTMLSelectElement).value) {\n attributes.selected = (n as HTMLOptionElement).selected;\n }\n }\n // canvas image data\n if (tagName === 'canvas' && recordCanvas) {\n attributes.rr_dataURL = (n as HTMLCanvasElement).toDataURL();\n }\n // media elements\n if (tagName === 'audio' || tagName === 'video') {\n attributes.rr_mediaState = (n as HTMLMediaElement).paused\n ? 'paused'\n : 'played';\n }\n // scroll\n if ((n as HTMLElement).scrollLeft) {\n attributes.rr_scrollLeft = (n as HTMLElement).scrollLeft;\n }\n if ((n as HTMLElement).scrollTop) {\n attributes.rr_scrollTop = (n as HTMLElement).scrollTop;\n }\n if (needBlock) {\n const { width, height } = (n as HTMLElement).getBoundingClientRect();\n attributes.rr_width = `${width}px`;\n attributes.rr_height = `${height}px`;\n }\n return {\n type: NodeType.Element,\n tagName,\n attributes,\n childNodes: [],\n isSVG: isSVGElement(n as Element) || undefined,\n needBlock,\n rootId,\n };\n case n.TEXT_NODE:\n // The parent node may not be a html element which has a tagName attribute.\n // So just let it be undefined which is ok in this use case.\n const parentTagName =\n n.parentNode && (n.parentNode as HTMLElement).tagName;\n let textContent = (n as Text).textContent;\n const isStyle = parentTagName === 'STYLE' ? true : undefined;\n if (isStyle && textContent) {\n textContent = absoluteToStylesheet(textContent, location.href);\n }\n if (parentTagName === 'SCRIPT') {\n textContent = 'SCRIPT_PLACEHOLDER';\n }\n return {\n type: NodeType.Text,\n textContent: textContent || '',\n isStyle,\n rootId,\n };\n case n.CDATA_SECTION_NODE:\n return {\n type: NodeType.CDATA,\n textContent: '',\n rootId,\n };\n case n.COMMENT_NODE:\n return {\n type: NodeType.Comment,\n textContent: (n as Comment).textContent || '',\n rootId,\n };\n default:\n return false;\n }\n}\n\nfunction lowerIfExists(maybeAttr: string | number | boolean): string {\n if (maybeAttr === undefined) {\n return '';\n } else {\n return (maybeAttr as string).toLowerCase();\n }\n}\n\nfunction slimDOMExcluded(\n sn: serializedNode,\n slimDOMOptions: SlimDOMOptions,\n): boolean {\n if (slimDOMOptions.comment && sn.type === NodeType.Comment) {\n // TODO: convert IE conditional comments to real nodes\n return true;\n } else if (sn.type === NodeType.Element) {\n if (\n slimDOMOptions.script &&\n (sn.tagName === 'script' ||\n (sn.tagName === 'link' &&\n sn.attributes.rel === 'preload' &&\n sn.attributes['as'] === 'script'))\n ) {\n return true;\n } else if (\n slimDOMOptions.headFavicon &&\n ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') ||\n (sn.tagName === 'meta' &&\n (lowerIfExists(sn.attributes['name']).match(\n /^msapplication-tile(image|color)$/,\n ) ||\n lowerIfExists(sn.attributes['name']) === 'application-name' ||\n lowerIfExists(sn.attributes['rel']) === 'icon' ||\n lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' ||\n lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))\n ) {\n return true;\n } else if (sn.tagName === 'meta') {\n if (\n slimDOMOptions.headMetaDescKeywords &&\n lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaSocial &&\n (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || // og = opengraph (facebook)\n lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) ||\n lowerIfExists(sn.attributes['name']) === 'pinterest')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaRobots &&\n (lowerIfExists(sn.attributes['name']) === 'robots' ||\n lowerIfExists(sn.attributes['name']) === 'googlebot' ||\n lowerIfExists(sn.attributes['name']) === 'bingbot')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaHttpEquiv &&\n sn.attributes['http-equiv'] !== undefined\n ) {\n // e.g. X-UA-Compatible, Content-Type, Content-Language,\n // cache-control, X-Translated-By\n return true;\n } else if (\n slimDOMOptions.headMetaAuthorship &&\n (lowerIfExists(sn.attributes['name']) === 'author' ||\n lowerIfExists(sn.attributes['name']) === 'generator' ||\n lowerIfExists(sn.attributes['name']) === 'framework' ||\n lowerIfExists(sn.attributes['name']) === 'publisher' ||\n lowerIfExists(sn.attributes['name']) === 'progid' ||\n lowerIfExists(sn.attributes['property']).match(/^article:/) ||\n lowerIfExists(sn.attributes['property']).match(/^product:/))\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaVerification &&\n (lowerIfExists(sn.attributes['name']) === 'google-site-verification' ||\n lowerIfExists(sn.attributes['name']) === 'yandex-verification' ||\n lowerIfExists(sn.attributes['name']) === 'csrf-token' ||\n lowerIfExists(sn.attributes['name']) === 'p:domain_verify' ||\n lowerIfExists(sn.attributes['name']) === 'verify-v1' ||\n lowerIfExists(sn.attributes['name']) === 'verification' ||\n lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nexport function serializeNodeWithId(\n n: Node | INode,\n doc: Document,\n map: idNodeMap,\n blockClass: string | RegExp,\n blockSelector: string | null,\n skipChild = false,\n inlineStylesheet = true,\n maskInputOptions?: MaskInputOptions,\n slimDOMOptions: SlimDOMOptions = {},\n recordCanvas?: boolean,\n preserveWhiteSpace = true,\n onSerialize?: (n: INode) => unknown,\n): serializedNodeWithId | null {\n const _serializedNode = serializeNode(\n n,\n doc,\n blockClass,\n blockSelector,\n inlineStylesheet,\n maskInputOptions,\n recordCanvas || false,\n );\n if (!_serializedNode) {\n // TODO: dev only\n console.warn(n, 'not serialized');\n return null;\n }\n\n let id;\n // Try to reuse the previous id\n if ('__sn' in n) {\n id = n.__sn.id;\n } else if (\n slimDOMExcluded(_serializedNode, slimDOMOptions) ||\n (!preserveWhiteSpace &&\n _serializedNode.type === NodeType.Text &&\n !_serializedNode.isStyle &&\n !_serializedNode.textContent.replace(/^\\s+|\\s+$/gm, '').length)\n ) {\n id = IGNORED_NODE;\n } else {\n id = genId();\n }\n const serializedNode = Object.assign(_serializedNode, { id });\n (n as INode).__sn = serializedNode;\n if (id === IGNORED_NODE) {\n return null; // slimDOM\n }\n map[id] = n as INode;\n if (onSerialize) {\n onSerialize(n as INode);\n }\n let recordChild = !skipChild;\n if (serializedNode.type === NodeType.Element) {\n recordChild = recordChild && !serializedNode.needBlock;\n // this property was not needed in replay side\n delete serializedNode.needBlock;\n }\n if (\n (serializedNode.type === NodeType.Document ||\n serializedNode.type === NodeType.Element) &&\n recordChild\n ) {\n if (\n slimDOMOptions.headWhitespace &&\n _serializedNode.type === NodeType.Element &&\n _serializedNode.tagName == 'head'\n // would impede performance: || getComputedStyle(n)['white-space'] === 'normal'\n ) {\n preserveWhiteSpace = false;\n }\n for (const childN of Array.from(n.childNodes)) {\n const serializedChildNode = serializeNodeWithId(\n childN,\n doc,\n map,\n blockClass,\n blockSelector,\n skipChild,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n );\n if (serializedChildNode) {\n serializedNode.childNodes.push(serializedChildNode);\n }\n }\n }\n\n if (\n serializedNode.type === NodeType.Element &&\n serializedNode.tagName === 'iframe'\n ) {\n const iframeDoc = (n as HTMLIFrameElement).contentDocument;\n if (iframeDoc) {\n const serializedIframeNode = serializeNodeWithId(\n iframeDoc,\n iframeDoc,\n map,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n );\n if (serializedIframeNode) {\n serializedNode.childNodes.push(serializedIframeNode);\n }\n }\n }\n\n return serializedNode;\n}\n\nfunction snapshot(\n n: Document,\n blockClass: string | RegExp = 'rr-block',\n inlineStylesheet = true,\n maskAllInputsOrOptions: boolean | MaskInputOptions,\n slimDOMSensibleOrOptions: boolean | SlimDOMOptions,\n recordCanvas?: boolean,\n blockSelector: string | null = null,\n preserveWhiteSpace?: boolean,\n onSerialize?: (n: INode) => unknown,\n): [serializedNodeWithId | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const maskInputOptions: MaskInputOptions =\n maskAllInputsOrOptions === true\n ? {\n color: true,\n date: true,\n 'datetime-local': true,\n email: true,\n month: true,\n number: true,\n range: true,\n search: true,\n tel: true,\n text: true,\n time: true,\n url: true,\n week: true,\n textarea: true,\n select: true,\n }\n : maskAllInputsOrOptions === false\n ? {}\n : maskAllInputsOrOptions;\n const slimDOMOptions: SlimDOMOptions =\n slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all'\n ? // if true: set of sensible options that should not throw away any information\n {\n script: true,\n comment: true,\n headFavicon: true,\n headWhitespace: true,\n headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', // destructive\n headMetaSocial: true,\n headMetaRobots: true,\n headMetaHttpEquiv: true,\n headMetaAuthorship: true,\n headMetaVerification: true,\n }\n : slimDOMSensibleOrOptions === false\n ? {}\n : slimDOMSensibleOrOptions;\n return [\n serializeNodeWithId(\n n,\n n,\n idNodeMap,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n ),\n idNodeMap,\n ];\n}\n\nexport function visitSnapshot(\n node: serializedNodeWithId,\n onVisit: (node: serializedNodeWithId) => unknown,\n) {\n function walk(current: serializedNodeWithId) {\n onVisit(current);\n if (\n current.type === NodeType.Document ||\n current.type === NodeType.Element\n ) {\n current.childNodes.forEach(walk);\n }\n }\n\n walk(node);\n}\n\nexport function cleanupSnapshot() {\n // allow a new recording to start numbering nodes from scratch\n _id = 1;\n}\n\nexport default snapshot;\n","/**\n * This file is a fork of https://github.com/reworkcss/css/blob/master/lib/parse/index.js\n * I fork it because:\n * 1. The css library was built for node.js which does not have tree-shaking supports.\n * 2. Rewrites into typescript give us a better type interface.\n */\n\n/* tslint:disable no-conditional-assignment interface-name no-shadowed-variable */\n\nexport interface ParserOptions {\n /** Silently fail on parse errors */\n silent?: boolean;\n /**\n * The path to the file containing css.\n * Makes errors and source maps more helpful, by letting them know where code comes from.\n */\n source?: string;\n}\n\n/**\n * Error thrown during parsing.\n */\nexport interface ParserError {\n /** The full error message with the source position. */\n message?: string;\n /** The error message without position. */\n reason?: string;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n filename?: string;\n line?: number;\n column?: number;\n /** The portion of code that couldn't be parsed. */\n source?: string;\n}\n\nexport interface Loc {\n line?: number;\n column?: number;\n}\n\n/**\n * Base AST Tree Node.\n */\nexport interface Node {\n /** The possible values are the ones listed in the Types section on https://github.com/reworkcss/css page. */\n type?: string;\n /** A reference to the parent node, or null if the node has no parent. */\n parent?: Node;\n /** Information about the position in the source string that corresponds to the node. */\n position?: {\n start?: Loc;\n end?: Loc;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n source?: string;\n /** The full source string passed to css.parse. */\n content?: string;\n };\n}\n\nexport interface Rule extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\nexport interface Declaration extends Node {\n /** The property name, trimmed from whitespace and comments. May not be empty. */\n property?: string;\n /** The value of the property, trimmed from whitespace and comments. Empty values are allowed. */\n value?: string;\n}\n\n/**\n * A rule-level or declaration-level comment. Comments inside selectors, properties and values etc. are lost.\n */\nexport interface Comment extends Node {\n comment?: string;\n}\n\n/**\n * The @charset at-rule.\n */\nexport interface Charset extends Node {\n /** The part following @charset. */\n charset?: string;\n}\n\n/**\n * The @custom-media at-rule\n */\nexport interface CustomMedia extends Node {\n /** The ---prefixed name. */\n name?: string;\n /** The part following the name. */\n media?: string;\n}\n\n/**\n * The @document at-rule.\n */\nexport interface Document extends Node {\n /** The part following @document. */\n document?: string;\n /** The vendor prefix in @document, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @font-face at-rule.\n */\nexport interface FontFace extends Node {\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @host at-rule.\n */\nexport interface Host extends Node {\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @import at-rule.\n */\nexport interface Import extends Node {\n /** The part following @import. */\n import?: string;\n}\n\n/**\n * The @keyframes at-rule.\n */\nexport interface KeyFrames extends Node {\n /** The name of the keyframes rule. */\n name?: string;\n /** The vendor prefix in @keyframes, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types keyframe and comment. */\n keyframes?: Array;\n}\n\nexport interface KeyFrame extends Node {\n /** The list of \"selectors\" of the keyframe rule, split on commas. Each “selector” is trimmed from whitespace. */\n values?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @media at-rule.\n */\nexport interface Media extends Node {\n /** The part following @media. */\n media?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @namespace at-rule.\n */\nexport interface Namespace extends Node {\n /** The part following @namespace. */\n namespace?: string;\n}\n\n/**\n * The @page at-rule.\n */\nexport interface Page extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @supports at-rule.\n */\nexport interface Supports extends Node {\n /** The part following @supports. */\n supports?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/** All at-rules. */\nexport type AtRule =\n | Charset\n | CustomMedia\n | Document\n | FontFace\n | Host\n | Import\n | KeyFrames\n | Media\n | Namespace\n | Page\n | Supports;\n\n/**\n * A collection of rules\n */\nexport interface StyleRules {\n source?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules: Array;\n /** Array of Errors. Errors collected during parsing when option silent is true. */\n parsingErrors?: ParserError[];\n}\n\n/**\n * The root node returned by css.parse.\n */\nexport interface Stylesheet extends Node {\n stylesheet?: StyleRules;\n}\n\n// http://www.w3.org/TR/CSS21/grammar.html\n// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027\nconst commentre = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//g;\n\nexport function parse(css: string, options: ParserOptions = {}) {\n /**\n * Positional.\n */\n\n let lineno = 1;\n let column = 1;\n\n /**\n * Update lineno and column based on `str`.\n */\n\n function updatePosition(str: string) {\n const lines = str.match(/\\n/g);\n if (lines) {\n lineno += lines.length;\n }\n let i = str.lastIndexOf('\\n');\n column = i === -1 ? column + str.length : str.length - i;\n }\n\n /**\n * Mark position and patch `node.position`.\n */\n\n function position() {\n const start = { line: lineno, column };\n return (\n node: Rule | Declaration | Comment | AtRule | Stylesheet | KeyFrame,\n ) => {\n node.position = new Position(start);\n whitespace();\n return node;\n };\n }\n\n /**\n * Store position information for a node\n */\n\n class Position {\n public content!: string;\n public start!: Loc;\n public end!: Loc;\n public source?: string;\n\n constructor(start: Loc) {\n this.start = start;\n this.end = { line: lineno, column };\n this.source = options.source;\n }\n }\n\n /**\n * Non-enumerable source string\n */\n\n Position.prototype.content = css;\n\n const errorsList: ParserError[] = [];\n\n function error(msg: string) {\n const err = new Error(\n options.source + ':' + lineno + ':' + column + ': ' + msg,\n ) as ParserError;\n err.reason = msg;\n err.filename = options.source;\n err.line = lineno;\n err.column = column;\n err.source = css;\n\n if (options.silent) {\n errorsList.push(err);\n } else {\n throw err;\n }\n }\n\n /**\n * Parse stylesheet.\n */\n\n function stylesheet(): Stylesheet {\n const rulesList = rules();\n\n return {\n type: 'stylesheet',\n stylesheet: {\n source: options.source,\n rules: rulesList,\n parsingErrors: errorsList,\n },\n };\n }\n\n /**\n * Opening brace.\n */\n\n function open() {\n return match(/^{\\s*/);\n }\n\n /**\n * Closing brace.\n */\n\n function close() {\n return match(/^}/);\n }\n\n /**\n * Parse ruleset.\n */\n\n function rules() {\n let node: Rule | void;\n const rules: Rule[] = [];\n whitespace();\n comments(rules);\n while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) {\n if (node !== false) {\n rules.push(node);\n comments(rules);\n }\n }\n return rules;\n }\n\n /**\n * Match `re` and return captures.\n */\n\n function match(re: RegExp) {\n const m = re.exec(css);\n if (!m) {\n return;\n }\n const str = m[0];\n updatePosition(str);\n css = css.slice(str.length);\n return m;\n }\n\n /**\n * Parse whitespace.\n */\n\n function whitespace() {\n match(/^\\s*/);\n }\n\n /**\n * Parse comments;\n */\n\n function comments(rules: Rule[] = []) {\n let c: Comment | void;\n while ((c = comment())) {\n if (c !== false) {\n rules.push(c);\n }\n c = comment();\n }\n return rules;\n }\n\n /**\n * Parse comment.\n */\n\n function comment() {\n const pos = position();\n if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) {\n return;\n }\n\n let i = 2;\n while (\n '' !== css.charAt(i) &&\n ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))\n ) {\n ++i;\n }\n i += 2;\n\n if ('' === css.charAt(i - 1)) {\n return error('End of comment missing');\n }\n\n const str = css.slice(2, i - 2);\n column += 2;\n updatePosition(str);\n css = css.slice(i);\n column += 2;\n\n return pos({\n type: 'comment',\n comment: str,\n });\n }\n\n /**\n * Parse selector.\n */\n\n function selector() {\n const m = match(/^([^{]+)/);\n if (!m) {\n return;\n }\n /* @fix Remove all comments from selectors\n * http://ostermiller.org/findcomment.html */\n return trim(m[0])\n .replace(/\\/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*\\/+/g, '')\n .replace(/\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*'/g, m => {\n return m.replace(/,/g, '\\u200C');\n })\n .split(/\\s*(?![^(]*\\)),\\s*/)\n .map(s => {\n return s.replace(/\\u200C/g, ',');\n });\n }\n\n /**\n * Parse declaration.\n */\n\n function declaration(): Declaration | void | never {\n const pos = position();\n\n // prop\n let propMatch = match(/^(\\*?[-#\\/\\*\\\\\\w]+(\\[[0-9a-z_-]+\\])?)\\s*/);\n if (!propMatch) {\n return;\n }\n const prop = trim(propMatch[0]);\n\n // :\n if (!match(/^:\\s*/)) {\n return error(`property missing ':'`);\n }\n\n // val\n const val = match(/^((?:'(?:\\\\'|.)*?'|\"(?:\\\\\"|.)*?\"|\\([^\\)]*?\\)|[^};])+)/);\n\n const ret = pos({\n type: 'declaration',\n property: prop.replace(commentre, ''),\n value: val ? trim(val[0]).replace(commentre, '') : '',\n });\n\n // ;\n match(/^[;\\s]*/);\n\n return ret;\n }\n\n /**\n * Parse declarations.\n */\n\n function declarations() {\n const decls: Array = [];\n\n if (!open()) {\n return error(`missing '{'`);\n }\n comments(decls);\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n if ((decl as unknown) !== false) {\n decls.push(decl);\n comments(decls);\n }\n decl = declaration();\n }\n\n if (!close()) {\n return error(`missing '}'`);\n }\n return decls;\n }\n\n /**\n * Parse keyframe.\n */\n\n function keyframe() {\n let m;\n const vals = [];\n const pos = position();\n\n while ((m = match(/^((\\d+\\.\\d+|\\.\\d+|\\d+)%?|[a-z]+)\\s*/))) {\n vals.push(m[1]);\n match(/^,\\s*/);\n }\n\n if (!vals.length) {\n return;\n }\n\n return pos({\n type: 'keyframe',\n values: vals,\n declarations: declarations() as Declaration[],\n });\n }\n\n /**\n * Parse keyframes.\n */\n\n function atkeyframes() {\n const pos = position();\n let m = match(/^@([-\\w]+)?keyframes\\s*/);\n\n if (!m) {\n return;\n }\n const vendor = m[1];\n\n // identifier\n m = match(/^([-\\w]+)\\s*/);\n if (!m) {\n return error('@keyframes missing name');\n }\n const name = m[1];\n\n if (!open()) {\n return error(`@keyframes missing '{'`);\n }\n\n let frame;\n let frames = comments();\n while ((frame = keyframe())) {\n frames.push(frame);\n frames = frames.concat(comments());\n }\n\n if (!close()) {\n return error(`@keyframes missing '}'`);\n }\n\n return pos({\n type: 'keyframes',\n name,\n vendor,\n keyframes: frames,\n });\n }\n\n /**\n * Parse supports.\n */\n\n function atsupports() {\n const pos = position();\n const m = match(/^@supports *([^{]+)/);\n\n if (!m) {\n return;\n }\n const supports = trim(m[1]);\n\n if (!open()) {\n return error(`@supports missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@supports missing '}'`);\n }\n\n return pos({\n type: 'supports',\n supports,\n rules: style,\n });\n }\n\n /**\n * Parse host.\n */\n\n function athost() {\n const pos = position();\n const m = match(/^@host\\s*/);\n\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@host missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@host missing '}'`);\n }\n\n return pos({\n type: 'host',\n rules: style,\n });\n }\n\n /**\n * Parse media.\n */\n\n function atmedia() {\n const pos = position();\n const m = match(/^@media *([^{]+)/);\n\n if (!m) {\n return;\n }\n const media = trim(m[1]);\n\n if (!open()) {\n return error(`@media missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@media missing '}'`);\n }\n\n return pos({\n type: 'media',\n media,\n rules: style,\n });\n }\n\n /**\n * Parse custom-media.\n */\n\n function atcustommedia() {\n const pos = position();\n const m = match(/^@custom-media\\s+(--[^\\s]+)\\s*([^{;]+);/);\n if (!m) {\n return;\n }\n\n return pos({\n type: 'custom-media',\n name: trim(m[1]),\n media: trim(m[2]),\n });\n }\n\n /**\n * Parse paged media.\n */\n\n function atpage() {\n const pos = position();\n const m = match(/^@page */);\n if (!m) {\n return;\n }\n\n const sel = selector() || [];\n\n if (!open()) {\n return error(`@page missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@page missing '}'`);\n }\n\n return pos({\n type: 'page',\n selectors: sel,\n declarations: decls,\n });\n }\n\n /**\n * Parse document.\n */\n\n function atdocument() {\n const pos = position();\n const m = match(/^@([-\\w]+)?document *([^{]+)/);\n if (!m) {\n return;\n }\n\n const vendor = trim(m[1]);\n const doc = trim(m[2]);\n\n if (!open()) {\n return error(`@document missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@document missing '}'`);\n }\n\n return pos({\n type: 'document',\n document: doc,\n vendor,\n rules: style,\n });\n }\n\n /**\n * Parse font-face.\n */\n\n function atfontface() {\n const pos = position();\n const m = match(/^@font-face\\s*/);\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@font-face missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@font-face missing '}'`);\n }\n\n return pos({\n type: 'font-face',\n declarations: decls,\n });\n }\n\n /**\n * Parse import\n */\n\n const atimport = _compileAtrule('import');\n\n /**\n * Parse charset\n */\n\n const atcharset = _compileAtrule('charset');\n\n /**\n * Parse namespace\n */\n\n const atnamespace = _compileAtrule('namespace');\n\n /**\n * Parse non-block at-rules\n */\n\n function _compileAtrule(name: string) {\n const re = new RegExp('^@' + name + '\\\\s*([^;]+);');\n return () => {\n const pos = position();\n const m = match(re);\n if (!m) {\n return;\n }\n const ret: Record = { type: name };\n ret[name] = m[1].trim();\n return pos(ret);\n };\n }\n\n /**\n * Parse at rule.\n */\n\n function atrule() {\n if (css[0] !== '@') {\n return;\n }\n\n return (\n atkeyframes() ||\n atmedia() ||\n atcustommedia() ||\n atsupports() ||\n atimport() ||\n atcharset() ||\n atnamespace() ||\n atdocument() ||\n atpage() ||\n athost() ||\n atfontface()\n );\n }\n\n /**\n * Parse rule.\n */\n\n function rule() {\n const pos = position();\n const sel = selector();\n\n if (!sel) {\n return error('selector missing');\n }\n comments();\n\n return pos({\n type: 'rule',\n selectors: sel,\n declarations: declarations() as Declaration[],\n });\n }\n\n return addParent(stylesheet());\n}\n\n/**\n * Trim `str`.\n */\n\nfunction trim(str: string) {\n return str ? str.replace(/^\\s+|\\s+$/g, '') : '';\n}\n\n/**\n * Adds non-enumerable parent node reference to each node.\n */\n\nfunction addParent(obj: Stylesheet, parent?: Stylesheet) {\n const isNode = obj && typeof obj.type === 'string';\n const childParent = isNode ? obj : parent;\n\n for (const k of Object.keys(obj)) {\n const value = obj[k as keyof Stylesheet];\n if (Array.isArray(value)) {\n value.forEach(v => {\n addParent(v, childParent);\n });\n } else if (value && typeof value === 'object') {\n addParent((value as unknown) as Stylesheet, childParent);\n }\n }\n\n if (isNode) {\n Object.defineProperty(obj, 'parent', {\n configurable: true,\n writable: true,\n enumerable: false,\n value: parent || null,\n });\n }\n\n return obj;\n}\n","import { parse } from './css';\nimport {\n serializedNodeWithId,\n NodeType,\n tagMap,\n elementNode,\n idNodeMap,\n INode,\n CallbackArray,\n} from './types';\n\nconst tagMap: tagMap = {\n script: 'noscript',\n // camel case svg element tag names\n altglyph: 'altGlyph',\n altglyphdef: 'altGlyphDef',\n altglyphitem: 'altGlyphItem',\n animatecolor: 'animateColor',\n animatemotion: 'animateMotion',\n animatetransform: 'animateTransform',\n clippath: 'clipPath',\n feblend: 'feBlend',\n fecolormatrix: 'feColorMatrix',\n fecomponenttransfer: 'feComponentTransfer',\n fecomposite: 'feComposite',\n feconvolvematrix: 'feConvolveMatrix',\n fediffuselighting: 'feDiffuseLighting',\n fedisplacementmap: 'feDisplacementMap',\n fedistantlight: 'feDistantLight',\n fedropshadow: 'feDropShadow',\n feflood: 'feFlood',\n fefunca: 'feFuncA',\n fefuncb: 'feFuncB',\n fefuncg: 'feFuncG',\n fefuncr: 'feFuncR',\n fegaussianblur: 'feGaussianBlur',\n feimage: 'feImage',\n femerge: 'feMerge',\n femergenode: 'feMergeNode',\n femorphology: 'feMorphology',\n feoffset: 'feOffset',\n fepointlight: 'fePointLight',\n fespecularlighting: 'feSpecularLighting',\n fespotlight: 'feSpotLight',\n fetile: 'feTile',\n feturbulence: 'feTurbulence',\n foreignobject: 'foreignObject',\n glyphref: 'glyphRef',\n lineargradient: 'linearGradient',\n radialgradient: 'radialGradient',\n};\nfunction getTagName(n: elementNode): string {\n let tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName;\n if (tagName === 'link' && n.attributes._cssText) {\n tagName = 'style';\n }\n return tagName;\n}\n\nconst HOVER_SELECTOR = /([^\\\\]):hover/g;\nexport function addHoverClass(cssText: string): string {\n const ast = parse(cssText, { silent: true });\n if (!ast.stylesheet) {\n return cssText;\n }\n ast.stylesheet.rules.forEach((rule) => {\n if ('selectors' in rule) {\n (rule.selectors || []).forEach((selector: string) => {\n if (HOVER_SELECTOR.test(selector)) {\n const newSelector = selector.replace(HOVER_SELECTOR, '$1.\\\\:hover');\n cssText = cssText.replace(selector, `${selector}, ${newSelector}`);\n }\n });\n }\n });\n return cssText;\n}\n\nfunction isIframe(n: serializedNodeWithId) {\n return n.type === NodeType.Element && n.tagName === 'iframe';\n}\n\nfunction buildIframe(\n iframe: HTMLIFrameElement,\n childNodes: serializedNodeWithId[],\n map: idNodeMap,\n cbs: CallbackArray,\n HACK_CSS: boolean,\n) {\n const targetDoc = iframe.contentDocument!;\n for (const childN of childNodes) {\n console.log('build iframe', childN);\n buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS);\n }\n}\n\nfunction buildNode(\n n: serializedNodeWithId,\n doc: Document,\n HACK_CSS: boolean,\n): Node | null {\n switch (n.type) {\n case NodeType.Document:\n return doc.implementation.createDocument(null, '', null);\n case NodeType.DocumentType:\n return doc.implementation.createDocumentType(\n n.name || 'html',\n n.publicId,\n n.systemId,\n );\n case NodeType.Element:\n const tagName = getTagName(n);\n let node: Element;\n if (n.isSVG) {\n node = doc.createElementNS('http://www.w3.org/2000/svg', tagName);\n } else {\n node = doc.createElement(tagName);\n }\n for (const name in n.attributes) {\n if (!n.attributes.hasOwnProperty(name)) {\n continue;\n }\n let value = n.attributes[name];\n value =\n typeof value === 'boolean' || typeof value === 'number' ? '' : value;\n // attribute names start with rr_ are internal attributes added by rrweb\n if (!name.startsWith('rr_')) {\n const isTextarea = tagName === 'textarea' && name === 'value';\n const isRemoteOrDynamicCss =\n tagName === 'style' && name === '_cssText';\n if (isRemoteOrDynamicCss && HACK_CSS) {\n value = addHoverClass(value);\n }\n if (isTextarea || isRemoteOrDynamicCss) {\n const child = doc.createTextNode(value);\n // https://github.com/rrweb-io/rrweb/issues/112\n for (const c of Array.from(node.childNodes)) {\n if (c.nodeType === node.TEXT_NODE) {\n node.removeChild(c);\n }\n }\n node.appendChild(child);\n continue;\n }\n if (tagName === 'iframe' && name === 'src') {\n continue;\n }\n try {\n if (n.isSVG && name === 'xlink:href') {\n node.setAttributeNS('http://www.w3.org/1999/xlink', name, value);\n } else if (\n name === 'onload' ||\n name === 'onclick' ||\n name.substring(0, 7) === 'onmouse'\n ) {\n // Rename some of the more common atttributes from https://www.w3schools.com/tags/ref_eventattributes.asp\n // as setting them triggers a console.error (which shows up despite the try/catch)\n // Assumption: these attributes are not used to css\n node.setAttribute('_' + name, value);\n } else {\n node.setAttribute(name, value);\n }\n } catch (error) {\n // skip invalid attribute\n }\n } else {\n // handle internal attributes\n if (tagName === 'canvas' && name === 'rr_dataURL') {\n const image = document.createElement('img');\n image.src = value;\n image.onload = () => {\n const ctx = (node as HTMLCanvasElement).getContext('2d');\n if (ctx) {\n ctx.drawImage(image, 0, 0, image.width, image.height);\n }\n };\n }\n if (name === 'rr_width') {\n (node as HTMLElement).style.width = value;\n }\n if (name === 'rr_height') {\n (node as HTMLElement).style.height = value;\n }\n if (name === 'rr_mediaState') {\n switch (value) {\n case 'played':\n (node as HTMLMediaElement).play();\n case 'paused':\n (node as HTMLMediaElement).pause();\n break;\n default:\n }\n }\n }\n }\n return node;\n case NodeType.Text:\n return doc.createTextNode(\n n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent,\n );\n case NodeType.CDATA:\n return doc.createCDATASection(n.textContent);\n case NodeType.Comment:\n return doc.createComment(n.textContent);\n default:\n return null;\n }\n}\n\nexport function buildNodeWithSN(\n n: serializedNodeWithId,\n doc: Document,\n map: idNodeMap,\n cbs: CallbackArray,\n skipChild = false,\n HACK_CSS = true,\n): [INode | null, serializedNodeWithId[]] {\n let node = buildNode(n, doc, HACK_CSS);\n if (!node) {\n return [null, []];\n }\n if (n.rootId) {\n console.assert(\n ((map[n.rootId] as unknown) as Document) === doc,\n 'Target document should has the same root id.',\n );\n }\n // use target document as root document\n if (n.type === NodeType.Document) {\n // close before open to make sure document was closed\n doc.close();\n doc.open();\n node = doc;\n }\n\n (node as INode).__sn = n;\n map[n.id] = node as INode;\n\n const nodeIsIframe = isIframe(n);\n if (n.type === NodeType.Element && nodeIsIframe) {\n return [node as INode, n.childNodes];\n }\n\n if (\n (n.type === NodeType.Document || n.type === NodeType.Element) &&\n !skipChild\n ) {\n for (const childN of n.childNodes) {\n const [childNode, nestedNodes] = buildNodeWithSN(\n childN,\n doc,\n map,\n cbs,\n false,\n HACK_CSS,\n );\n if (!childNode) {\n console.warn('Failed to rebuild', childN);\n continue;\n }\n\n node.appendChild(childNode);\n if (nestedNodes.length === 0) {\n continue;\n }\n const childNodeIsIframe = isIframe(childN);\n if (childNodeIsIframe) {\n cbs.push(() =>\n buildIframe(\n (childNode as unknown) as HTMLIFrameElement,\n nestedNodes,\n map,\n cbs,\n HACK_CSS,\n ),\n );\n }\n }\n }\n return [node as INode, []];\n}\n\nfunction visit(idNodeMap: idNodeMap, onVisit: (node: INode) => void) {\n function walk(node: INode) {\n onVisit(node);\n }\n\n for (const key in idNodeMap) {\n if (idNodeMap[key]) {\n walk(idNodeMap[key]);\n }\n }\n}\n\nfunction handleScroll(node: INode) {\n const n = node.__sn;\n if (n.type !== NodeType.Element) {\n return;\n }\n const el = (node as Node) as HTMLElement;\n for (const name in n.attributes) {\n if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) {\n continue;\n }\n const value = n.attributes[name];\n if (name === 'rr_scrollLeft') {\n el.scrollLeft = value as number;\n }\n if (name === 'rr_scrollTop') {\n el.scrollTop = value as number;\n }\n }\n}\n\nfunction rebuild(\n n: serializedNodeWithId,\n doc: Document,\n onVisit?: (node: INode) => unknown,\n /**\n * This is not a public API yet, just for POC\n */\n HACK_CSS: boolean = true,\n): [Node | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const callbackArray: CallbackArray = [];\n const [node] = buildNodeWithSN(\n n,\n doc,\n idNodeMap,\n callbackArray,\n false,\n HACK_CSS,\n );\n callbackArray.forEach((f) => f());\n visit(idNodeMap, (visitedNode) => {\n if (onVisit) {\n onVisit(visitedNode);\n }\n handleScroll(visitedNode);\n });\n return [node, idNodeMap];\n}\n\nexport default rebuild;\n"],"names":["NodeType","_id","tagNameRegex","RegExp","IGNORED_NODE","getCssRulesString","s","rules","cssRules","Array","from","map","getCssRuleString","join","error","rule","isCSSImportRule","styleSheet","cssText","URL_IN_CSS_REF","RELATIVE_PATH","DATA_URI","absoluteToStylesheet","href","replace","origin","quote1","path1","quote2","path2","path3","url","filePath","maybe_quote","test","indexOf","split","slice","stack","parts","pop","parts_1","_i","part","push","absoluteToDoc","doc","attributeValue","trim","a","createElement","transformAttribute","name","value","srcItem","urlAndSize","trimLeft","trimRight","length","getAbsoluteSrcsetString","location","serializeNode","n","blockClass","blockSelector","inlineStylesheet","maskInputOptions","recordCanvas","rootId","el","__sn","docId","id","undefined","nodeType","DOCUMENT_NODE","type","Document","childNodes","DOCUMENT_TYPE_NODE","DocumentType","publicId","systemId","ELEMENT_NODE","needBlock","element","classList","contains","forEach","className","matches","_isBlockedElement","tagName","processedTagName","toLowerCase","getValidTagName","attributes_1","_a","attributes","_b","stylesheet","styleSheets","find","rel","_cssText","sheet","innerText","textContent","repeat","checked","selectValue","parentElement","selected","rr_dataURL","toDataURL","rr_mediaState","paused","scrollLeft","rr_scrollLeft","scrollTop","rr_scrollTop","_c","width","height","rr_width","rr_height","Element","isSVG","SVGElement","TEXT_NODE","parentTagName","parentNode","isStyle","Text","CDATA_SECTION_NODE","CDATA","COMMENT_NODE","Comment","lowerIfExists","maybeAttr","serializeNodeWithId","skipChild","slimDOMOptions","preserveWhiteSpace","onSerialize","_serializedNode","console","warn","sn","comment","script","headFavicon","match","headMetaDescKeywords","headMetaSocial","headMetaRobots","headMetaHttpEquiv","headMetaAuthorship","headMetaVerification","slimDOMExcluded","serializedNode","Object","assign","recordChild","headWhitespace","serializedChildNode","iframeDoc","contentDocument","serializedIframeNode","commentre","parse","css","options","lineno","column","updatePosition","str","lines","i","lastIndexOf","position","start","line","node","Position","whitespace","this","end","source","prototype","content","errorsList","msg","err","Error","reason","filename","silent","open","close","comments","charAt","atrule","re","m","exec","c","pos","selector","declaration","propMatch","prop","val","ret","property","declarations","decl","decls","keyframe","vals","values","rulesList","atimport","_compileAtrule","atcharset","atnamespace","vendor","frame","frames","concat","keyframes","atkeyframes","media","style","atmedia","atcustommedia","supports","atsupports","document","atdocument","sel","selectors","atpage","athost","atfontface","addParent","obj","parent","isNode","childParent","keys","k","isArray","v","defineProperty","configurable","writable","enumerable","parsingErrors","tagMap","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","clippath","feblend","fecolormatrix","fecomponenttransfer","fecomposite","feconvolvematrix","fediffuselighting","fedisplacementmap","fedistantlight","fedropshadow","feflood","fefunca","fefuncb","fefuncg","fefuncr","fegaussianblur","feimage","femerge","femergenode","femorphology","feoffset","fepointlight","fespecularlighting","fespotlight","fetile","feturbulence","foreignobject","glyphref","lineargradient","radialgradient","HOVER_SELECTOR","addHoverClass","ast","newSelector","isIframe","buildNode","HACK_CSS","implementation","createDocument","createDocumentType","node_1","getTagName","createElementNS","hasOwnProperty","startsWith","image_1","src","onload","ctx","getContext","drawImage","play","pause","isTextarea","isRemoteOrDynamicCss","child","createTextNode","removeChild","appendChild","setAttributeNS","substring","setAttribute","createCDATASection","createComment","buildNodeWithSN","cbs","assert","nodeIsIframe","childN","childNode","nestedNodes","iframe","targetDoc","childNodes_1","log","buildIframe","maskAllInputsOrOptions","slimDOMSensibleOrOptions","idNodeMap","color","date","datetime-local","email","month","number","range","search","tel","text","time","week","textarea","select","onVisit","callbackArray","f","key","visit","visitedNode","handleScroll","walk","current"],"mappings":"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"} \ No newline at end of file diff --git a/es/rrweb-snapshot.js b/es/rrweb-snapshot.js new file mode 100644 index 0000000..6e564e4 --- /dev/null +++ b/es/rrweb-snapshot.js @@ -0,0 +1,1200 @@ +var NodeType; +(function (NodeType) { + NodeType[NodeType["Document"] = 0] = "Document"; + NodeType[NodeType["DocumentType"] = 1] = "DocumentType"; + NodeType[NodeType["Element"] = 2] = "Element"; + NodeType[NodeType["Text"] = 3] = "Text"; + NodeType[NodeType["CDATA"] = 4] = "CDATA"; + NodeType[NodeType["Comment"] = 5] = "Comment"; +})(NodeType || (NodeType = {})); + +var _id = 1; +var tagNameRegex = RegExp('[^a-z1-6-_]'); +var IGNORED_NODE = -2; +function genId() { + return _id++; +} +function getValidTagName(tagName) { + var processedTagName = tagName.toLowerCase().trim(); + if (tagNameRegex.test(processedTagName)) { + return 'div'; + } + return processedTagName; +} +function getCssRulesString(s) { + try { + var rules = s.rules || s.cssRules; + return rules ? Array.from(rules).map(getCssRuleString).join('') : null; + } + catch (error) { + return null; + } +} +function getCssRuleString(rule) { + return isCSSImportRule(rule) + ? getCssRulesString(rule.styleSheet) || '' + : rule.cssText; +} +function isCSSImportRule(rule) { + return 'styleSheet' in rule; +} +function extractOrigin(url) { + var origin; + if (url.indexOf('//') > -1) { + origin = url.split('/').slice(0, 3).join('/'); + } + else { + origin = url.split('/')[0]; + } + origin = origin.split('?')[0]; + return origin; +} +var URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm; +var RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/; +var DATA_URI = /^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i; +function absoluteToStylesheet(cssText, href) { + return (cssText || '').replace(URL_IN_CSS_REF, function (origin, quote1, path1, quote2, path2, path3) { + var filePath = path1 || path2 || path3; + var maybe_quote = quote1 || quote2 || ''; + if (!filePath) { + return origin; + } + if (!RELATIVE_PATH.test(filePath)) { + return "url(" + maybe_quote + filePath + maybe_quote + ")"; + } + if (DATA_URI.test(filePath)) { + return "url(" + maybe_quote + filePath + maybe_quote + ")"; + } + if (filePath[0] === '/') { + return "url(" + maybe_quote + (extractOrigin(href) + filePath) + maybe_quote + ")"; + } + var stack = href.split('/'); + var parts = filePath.split('/'); + stack.pop(); + for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { + var part = parts_1[_i]; + if (part === '.') { + continue; + } + else if (part === '..') { + stack.pop(); + } + else { + stack.push(part); + } + } + return "url(" + maybe_quote + stack.join('/') + maybe_quote + ")"; + }); +} +function getAbsoluteSrcsetString(doc, attributeValue) { + if (attributeValue.trim() === '') { + return attributeValue; + } + var srcsetValues = attributeValue.split(','); + var resultingSrcsetString = srcsetValues + .map(function (srcItem) { + var trimmedSrcItem = srcItem.trimLeft().trimRight(); + var urlAndSize = trimmedSrcItem.split(' '); + if (urlAndSize.length === 2) { + var absUrl = absoluteToDoc(doc, urlAndSize[0]); + return absUrl + " " + urlAndSize[1]; + } + else if (urlAndSize.length === 1) { + var absUrl = absoluteToDoc(doc, urlAndSize[0]); + return "" + absUrl; + } + return ''; + }) + .join(', '); + return resultingSrcsetString; +} +function absoluteToDoc(doc, attributeValue) { + if (!attributeValue || attributeValue.trim() === '') { + return attributeValue; + } + var a = doc.createElement('a'); + a.href = attributeValue; + return a.href; +} +function isSVGElement(el) { + return el.tagName === 'svg' || el instanceof SVGElement; +} +function transformAttribute(doc, name, value) { + if (name === 'src' || (name === 'href' && value)) { + return absoluteToDoc(doc, value); + } + else if (name === 'srcset' && value) { + return getAbsoluteSrcsetString(doc, value); + } + else if (name === 'style' && value) { + return absoluteToStylesheet(value, location.href); + } + else { + return value; + } +} +function _isBlockedElement(element, blockClass, blockSelector) { + if (typeof blockClass === 'string') { + if (element.classList.contains(blockClass)) { + return true; + } + } + else { + element.classList.forEach(function (className) { + if (blockClass.test(className)) { + return true; + } + }); + } + if (blockSelector) { + return element.matches(blockSelector); + } + return false; +} +function serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas) { + if (maskInputOptions === void 0) { maskInputOptions = {}; } + var rootId; + if (doc.__sn) { + var docId = doc.__sn.id; + rootId = docId === 1 ? undefined : docId; + } + switch (n.nodeType) { + case n.DOCUMENT_NODE: + return { + type: NodeType.Document, + childNodes: [], + rootId: rootId + }; + case n.DOCUMENT_TYPE_NODE: + return { + type: NodeType.DocumentType, + name: n.name, + publicId: n.publicId, + systemId: n.systemId, + rootId: rootId + }; + case n.ELEMENT_NODE: + var needBlock = _isBlockedElement(n, blockClass, blockSelector); + var tagName = getValidTagName(n.tagName); + var attributes_1 = {}; + for (var _i = 0, _a = Array.from(n.attributes); _i < _a.length; _i++) { + var _b = _a[_i], name = _b.name, value = _b.value; + attributes_1[name] = transformAttribute(doc, name, value); + } + if (tagName === 'link' && inlineStylesheet) { + var stylesheet = Array.from(doc.styleSheets).find(function (s) { + return s.href === n.href; + }); + var cssText = getCssRulesString(stylesheet); + if (cssText) { + delete attributes_1.rel; + delete attributes_1.href; + attributes_1._cssText = absoluteToStylesheet(cssText, stylesheet.href); + } + } + if (tagName === 'style' && + n.sheet && + !(n.innerText || + n.textContent || + '').trim().length) { + var cssText = getCssRulesString(n.sheet); + if (cssText) { + attributes_1._cssText = absoluteToStylesheet(cssText, location.href); + } + } + if (tagName === 'input' || + tagName === 'textarea' || + tagName === 'select') { + var value = n.value; + if (attributes_1.type !== 'radio' && + attributes_1.type !== 'checkbox' && + attributes_1.type !== 'submit' && + attributes_1.type !== 'button' && + value) { + attributes_1.value = + maskInputOptions[attributes_1.type] || + maskInputOptions[tagName] + ? '*'.repeat(value.length) + : value; + } + else if (n.checked) { + attributes_1.checked = n.checked; + } + } + if (tagName === 'option') { + var selectValue = n.parentElement; + if (attributes_1.value === selectValue.value) { + attributes_1.selected = n.selected; + } + } + if (tagName === 'canvas' && recordCanvas) { + attributes_1.rr_dataURL = n.toDataURL(); + } + if (tagName === 'audio' || tagName === 'video') { + attributes_1.rr_mediaState = n.paused + ? 'paused' + : 'played'; + } + if (n.scrollLeft) { + attributes_1.rr_scrollLeft = n.scrollLeft; + } + if (n.scrollTop) { + attributes_1.rr_scrollTop = n.scrollTop; + } + if (needBlock) { + var _c = n.getBoundingClientRect(), width = _c.width, height = _c.height; + attributes_1.rr_width = width + "px"; + attributes_1.rr_height = height + "px"; + } + return { + type: NodeType.Element, + tagName: tagName, + attributes: attributes_1, + childNodes: [], + isSVG: isSVGElement(n) || undefined, + needBlock: needBlock, + rootId: rootId + }; + case n.TEXT_NODE: + var parentTagName = n.parentNode && n.parentNode.tagName; + var textContent = n.textContent; + var isStyle = parentTagName === 'STYLE' ? true : undefined; + if (isStyle && textContent) { + textContent = absoluteToStylesheet(textContent, location.href); + } + if (parentTagName === 'SCRIPT') { + textContent = 'SCRIPT_PLACEHOLDER'; + } + return { + type: NodeType.Text, + textContent: textContent || '', + isStyle: isStyle, + rootId: rootId + }; + case n.CDATA_SECTION_NODE: + return { + type: NodeType.CDATA, + textContent: '', + rootId: rootId + }; + case n.COMMENT_NODE: + return { + type: NodeType.Comment, + textContent: n.textContent || '', + rootId: rootId + }; + default: + return false; + } +} +function lowerIfExists(maybeAttr) { + if (maybeAttr === undefined) { + return ''; + } + else { + return maybeAttr.toLowerCase(); + } +} +function slimDOMExcluded(sn, slimDOMOptions) { + if (slimDOMOptions.comment && sn.type === NodeType.Comment) { + return true; + } + else if (sn.type === NodeType.Element) { + if (slimDOMOptions.script && + (sn.tagName === 'script' || + (sn.tagName === 'link' && + sn.attributes.rel === 'preload' && + sn.attributes['as'] === 'script'))) { + return true; + } + else if (slimDOMOptions.headFavicon && + ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') || + (sn.tagName === 'meta' && + (lowerIfExists(sn.attributes['name']).match(/^msapplication-tile(image|color)$/) || + lowerIfExists(sn.attributes['name']) === 'application-name' || + lowerIfExists(sn.attributes['rel']) === 'icon' || + lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' || + lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))) { + return true; + } + else if (sn.tagName === 'meta') { + if (slimDOMOptions.headMetaDescKeywords && + lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)) { + return true; + } + else if (slimDOMOptions.headMetaSocial && + (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || + lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) || + lowerIfExists(sn.attributes['name']) === 'pinterest')) { + return true; + } + else if (slimDOMOptions.headMetaRobots && + (lowerIfExists(sn.attributes['name']) === 'robots' || + lowerIfExists(sn.attributes['name']) === 'googlebot' || + lowerIfExists(sn.attributes['name']) === 'bingbot')) { + return true; + } + else if (slimDOMOptions.headMetaHttpEquiv && + sn.attributes['http-equiv'] !== undefined) { + return true; + } + else if (slimDOMOptions.headMetaAuthorship && + (lowerIfExists(sn.attributes['name']) === 'author' || + lowerIfExists(sn.attributes['name']) === 'generator' || + lowerIfExists(sn.attributes['name']) === 'framework' || + lowerIfExists(sn.attributes['name']) === 'publisher' || + lowerIfExists(sn.attributes['name']) === 'progid' || + lowerIfExists(sn.attributes['property']).match(/^article:/) || + lowerIfExists(sn.attributes['property']).match(/^product:/))) { + return true; + } + else if (slimDOMOptions.headMetaVerification && + (lowerIfExists(sn.attributes['name']) === 'google-site-verification' || + lowerIfExists(sn.attributes['name']) === 'yandex-verification' || + lowerIfExists(sn.attributes['name']) === 'csrf-token' || + lowerIfExists(sn.attributes['name']) === 'p:domain_verify' || + lowerIfExists(sn.attributes['name']) === 'verify-v1' || + lowerIfExists(sn.attributes['name']) === 'verification' || + lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')) { + return true; + } + } + } + return false; +} +function serializeNodeWithId(n, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize) { + if (skipChild === void 0) { skipChild = false; } + if (inlineStylesheet === void 0) { inlineStylesheet = true; } + if (slimDOMOptions === void 0) { slimDOMOptions = {}; } + if (preserveWhiteSpace === void 0) { preserveWhiteSpace = true; } + var _serializedNode = serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas || false); + if (!_serializedNode) { + console.warn(n, 'not serialized'); + return null; + } + var id; + if ('__sn' in n) { + id = n.__sn.id; + } + else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || + (!preserveWhiteSpace && + _serializedNode.type === NodeType.Text && + !_serializedNode.isStyle && + !_serializedNode.textContent.replace(/^\s+|\s+$/gm, '').length)) { + id = IGNORED_NODE; + } + else { + id = genId(); + } + var serializedNode = Object.assign(_serializedNode, { id: id }); + n.__sn = serializedNode; + if (id === IGNORED_NODE) { + return null; + } + map[id] = n; + if (onSerialize) { + onSerialize(n); + } + var recordChild = !skipChild; + if (serializedNode.type === NodeType.Element) { + recordChild = recordChild && !serializedNode.needBlock; + delete serializedNode.needBlock; + } + if ((serializedNode.type === NodeType.Document || + serializedNode.type === NodeType.Element) && + recordChild) { + if (slimDOMOptions.headWhitespace && + _serializedNode.type === NodeType.Element && + _serializedNode.tagName == 'head') { + preserveWhiteSpace = false; + } + for (var _i = 0, _a = Array.from(n.childNodes); _i < _a.length; _i++) { + var childN = _a[_i]; + var serializedChildNode = serializeNodeWithId(childN, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace); + if (serializedChildNode) { + serializedNode.childNodes.push(serializedChildNode); + } + } + } + if (serializedNode.type === NodeType.Element && + serializedNode.tagName === 'iframe') { + var iframeDoc = n.contentDocument; + if (iframeDoc) { + var serializedIframeNode = serializeNodeWithId(iframeDoc, iframeDoc, map, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas); + if (serializedIframeNode) { + serializedNode.childNodes.push(serializedIframeNode); + } + } + } + return serializedNode; +} +function snapshot(n, blockClass, inlineStylesheet, maskAllInputsOrOptions, slimDOMSensibleOrOptions, recordCanvas, blockSelector, preserveWhiteSpace, onSerialize) { + if (blockClass === void 0) { blockClass = 'rr-block'; } + if (inlineStylesheet === void 0) { inlineStylesheet = true; } + if (blockSelector === void 0) { blockSelector = null; } + var idNodeMap = {}; + var maskInputOptions = maskAllInputsOrOptions === true + ? { + color: true, + date: true, + 'datetime-local': true, + email: true, + month: true, + number: true, + range: true, + search: true, + tel: true, + text: true, + time: true, + url: true, + week: true, + textarea: true, + select: true + } + : maskAllInputsOrOptions === false + ? {} + : maskAllInputsOrOptions; + var slimDOMOptions = slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all' + ? + { + script: true, + comment: true, + headFavicon: true, + headWhitespace: true, + headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', + headMetaSocial: true, + headMetaRobots: true, + headMetaHttpEquiv: true, + headMetaAuthorship: true, + headMetaVerification: true + } + : slimDOMSensibleOrOptions === false + ? {} + : slimDOMSensibleOrOptions; + return [ + serializeNodeWithId(n, n, idNodeMap, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize), + idNodeMap, + ]; +} +function visitSnapshot(node, onVisit) { + function walk(current) { + onVisit(current); + if (current.type === NodeType.Document || + current.type === NodeType.Element) { + current.childNodes.forEach(walk); + } + } + walk(node); +} +function cleanupSnapshot() { + _id = 1; +} + +var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; +function parse(css, options) { + if (options === void 0) { options = {}; } + var lineno = 1; + var column = 1; + function updatePosition(str) { + var lines = str.match(/\n/g); + if (lines) { + lineno += lines.length; + } + var i = str.lastIndexOf('\n'); + column = i === -1 ? column + str.length : str.length - i; + } + function position() { + var start = { line: lineno, column: column }; + return function (node) { + node.position = new Position(start); + whitespace(); + return node; + }; + } + var Position = (function () { + function Position(start) { + this.start = start; + this.end = { line: lineno, column: column }; + this.source = options.source; + } + return Position; + }()); + Position.prototype.content = css; + var errorsList = []; + function error(msg) { + var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); + err.reason = msg; + err.filename = options.source; + err.line = lineno; + err.column = column; + err.source = css; + if (options.silent) { + errorsList.push(err); + } + else { + throw err; + } + } + function stylesheet() { + var rulesList = rules(); + return { + type: 'stylesheet', + stylesheet: { + source: options.source, + rules: rulesList, + parsingErrors: errorsList + } + }; + } + function open() { + return match(/^{\s*/); + } + function close() { + return match(/^}/); + } + function rules() { + var node; + var rules = []; + whitespace(); + comments(rules); + while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { + if (node !== false) { + rules.push(node); + comments(rules); + } + } + return rules; + } + function match(re) { + var m = re.exec(css); + if (!m) { + return; + } + var str = m[0]; + updatePosition(str); + css = css.slice(str.length); + return m; + } + function whitespace() { + match(/^\s*/); + } + function comments(rules) { + if (rules === void 0) { rules = []; } + var c; + while ((c = comment())) { + if (c !== false) { + rules.push(c); + } + c = comment(); + } + return rules; + } + function comment() { + var pos = position(); + if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { + return; + } + var i = 2; + while ('' !== css.charAt(i) && + ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))) { + ++i; + } + i += 2; + if ('' === css.charAt(i - 1)) { + return error('End of comment missing'); + } + var str = css.slice(2, i - 2); + column += 2; + updatePosition(str); + css = css.slice(i); + column += 2; + return pos({ + type: 'comment', + comment: str + }); + } + function selector() { + var m = match(/^([^{]+)/); + if (!m) { + return; + } + return trim(m[0]) + .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') + .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) { + return m.replace(/,/g, '\u200C'); + }) + .split(/\s*(?![^(]*\)),\s*/) + .map(function (s) { + return s.replace(/\u200C/g, ','); + }); + } + function declaration() { + var pos = position(); + var propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); + if (!propMatch) { + return; + } + var prop = trim(propMatch[0]); + if (!match(/^:\s*/)) { + return error("property missing ':'"); + } + var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); + var ret = pos({ + type: 'declaration', + property: prop.replace(commentre, ''), + value: val ? trim(val[0]).replace(commentre, '') : '' + }); + match(/^[;\s]*/); + return ret; + } + function declarations() { + var decls = []; + if (!open()) { + return error("missing '{'"); + } + comments(decls); + var decl; + while ((decl = declaration())) { + if (decl !== false) { + decls.push(decl); + comments(decls); + } + decl = declaration(); + } + if (!close()) { + return error("missing '}'"); + } + return decls; + } + function keyframe() { + var m; + var vals = []; + var pos = position(); + while ((m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/))) { + vals.push(m[1]); + match(/^,\s*/); + } + if (!vals.length) { + return; + } + return pos({ + type: 'keyframe', + values: vals, + declarations: declarations() + }); + } + function atkeyframes() { + var pos = position(); + var m = match(/^@([-\w]+)?keyframes\s*/); + if (!m) { + return; + } + var vendor = m[1]; + m = match(/^([-\w]+)\s*/); + if (!m) { + return error('@keyframes missing name'); + } + var name = m[1]; + if (!open()) { + return error("@keyframes missing '{'"); + } + var frame; + var frames = comments(); + while ((frame = keyframe())) { + frames.push(frame); + frames = frames.concat(comments()); + } + if (!close()) { + return error("@keyframes missing '}'"); + } + return pos({ + type: 'keyframes', + name: name, + vendor: vendor, + keyframes: frames + }); + } + function atsupports() { + var pos = position(); + var m = match(/^@supports *([^{]+)/); + if (!m) { + return; + } + var supports = trim(m[1]); + if (!open()) { + return error("@supports missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@supports missing '}'"); + } + return pos({ + type: 'supports', + supports: supports, + rules: style + }); + } + function athost() { + var pos = position(); + var m = match(/^@host\s*/); + if (!m) { + return; + } + if (!open()) { + return error("@host missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@host missing '}'"); + } + return pos({ + type: 'host', + rules: style + }); + } + function atmedia() { + var pos = position(); + var m = match(/^@media *([^{]+)/); + if (!m) { + return; + } + var media = trim(m[1]); + if (!open()) { + return error("@media missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@media missing '}'"); + } + return pos({ + type: 'media', + media: media, + rules: style + }); + } + function atcustommedia() { + var pos = position(); + var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); + if (!m) { + return; + } + return pos({ + type: 'custom-media', + name: trim(m[1]), + media: trim(m[2]) + }); + } + function atpage() { + var pos = position(); + var m = match(/^@page */); + if (!m) { + return; + } + var sel = selector() || []; + if (!open()) { + return error("@page missing '{'"); + } + var decls = comments(); + var decl; + while ((decl = declaration())) { + decls.push(decl); + decls = decls.concat(comments()); + } + if (!close()) { + return error("@page missing '}'"); + } + return pos({ + type: 'page', + selectors: sel, + declarations: decls + }); + } + function atdocument() { + var pos = position(); + var m = match(/^@([-\w]+)?document *([^{]+)/); + if (!m) { + return; + } + var vendor = trim(m[1]); + var doc = trim(m[2]); + if (!open()) { + return error("@document missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@document missing '}'"); + } + return pos({ + type: 'document', + document: doc, + vendor: vendor, + rules: style + }); + } + function atfontface() { + var pos = position(); + var m = match(/^@font-face\s*/); + if (!m) { + return; + } + if (!open()) { + return error("@font-face missing '{'"); + } + var decls = comments(); + var decl; + while ((decl = declaration())) { + decls.push(decl); + decls = decls.concat(comments()); + } + if (!close()) { + return error("@font-face missing '}'"); + } + return pos({ + type: 'font-face', + declarations: decls + }); + } + var atimport = _compileAtrule('import'); + var atcharset = _compileAtrule('charset'); + var atnamespace = _compileAtrule('namespace'); + function _compileAtrule(name) { + var re = new RegExp('^@' + name + '\\s*([^;]+);'); + return function () { + var pos = position(); + var m = match(re); + if (!m) { + return; + } + var ret = { type: name }; + ret[name] = m[1].trim(); + return pos(ret); + }; + } + function atrule() { + if (css[0] !== '@') { + return; + } + return (atkeyframes() || + atmedia() || + atcustommedia() || + atsupports() || + atimport() || + atcharset() || + atnamespace() || + atdocument() || + atpage() || + athost() || + atfontface()); + } + function rule() { + var pos = position(); + var sel = selector(); + if (!sel) { + return error('selector missing'); + } + comments(); + return pos({ + type: 'rule', + selectors: sel, + declarations: declarations() + }); + } + return addParent(stylesheet()); +} +function trim(str) { + return str ? str.replace(/^\s+|\s+$/g, '') : ''; +} +function addParent(obj, parent) { + var isNode = obj && typeof obj.type === 'string'; + var childParent = isNode ? obj : parent; + for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { + var k = _a[_i]; + var value = obj[k]; + if (Array.isArray(value)) { + value.forEach(function (v) { + addParent(v, childParent); + }); + } + else if (value && typeof value === 'object') { + addParent(value, childParent); + } + } + if (isNode) { + Object.defineProperty(obj, 'parent', { + configurable: true, + writable: true, + enumerable: false, + value: parent || null + }); + } + return obj; +} + +var tagMap = { + script: 'noscript', + altglyph: 'altGlyph', + altglyphdef: 'altGlyphDef', + altglyphitem: 'altGlyphItem', + animatecolor: 'animateColor', + animatemotion: 'animateMotion', + animatetransform: 'animateTransform', + clippath: 'clipPath', + feblend: 'feBlend', + fecolormatrix: 'feColorMatrix', + fecomponenttransfer: 'feComponentTransfer', + fecomposite: 'feComposite', + feconvolvematrix: 'feConvolveMatrix', + fediffuselighting: 'feDiffuseLighting', + fedisplacementmap: 'feDisplacementMap', + fedistantlight: 'feDistantLight', + fedropshadow: 'feDropShadow', + feflood: 'feFlood', + fefunca: 'feFuncA', + fefuncb: 'feFuncB', + fefuncg: 'feFuncG', + fefuncr: 'feFuncR', + fegaussianblur: 'feGaussianBlur', + feimage: 'feImage', + femerge: 'feMerge', + femergenode: 'feMergeNode', + femorphology: 'feMorphology', + feoffset: 'feOffset', + fepointlight: 'fePointLight', + fespecularlighting: 'feSpecularLighting', + fespotlight: 'feSpotLight', + fetile: 'feTile', + feturbulence: 'feTurbulence', + foreignobject: 'foreignObject', + glyphref: 'glyphRef', + lineargradient: 'linearGradient', + radialgradient: 'radialGradient' +}; +function getTagName(n) { + var tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; + if (tagName === 'link' && n.attributes._cssText) { + tagName = 'style'; + } + return tagName; +} +var HOVER_SELECTOR = /([^\\]):hover/g; +function addHoverClass(cssText) { + var ast = parse(cssText, { silent: true }); + if (!ast.stylesheet) { + return cssText; + } + ast.stylesheet.rules.forEach(function (rule) { + if ('selectors' in rule) { + (rule.selectors || []).forEach(function (selector) { + if (HOVER_SELECTOR.test(selector)) { + var newSelector = selector.replace(HOVER_SELECTOR, '$1.\\:hover'); + cssText = cssText.replace(selector, selector + ", " + newSelector); + } + }); + } + }); + return cssText; +} +function isIframe(n) { + return n.type === NodeType.Element && n.tagName === 'iframe'; +} +function buildIframe(iframe, childNodes, map, cbs, HACK_CSS) { + var targetDoc = iframe.contentDocument; + for (var _i = 0, childNodes_1 = childNodes; _i < childNodes_1.length; _i++) { + var childN = childNodes_1[_i]; + console.log('build iframe', childN); + buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS); + } +} +function buildNode(n, doc, HACK_CSS) { + switch (n.type) { + case NodeType.Document: + return doc.implementation.createDocument(null, '', null); + case NodeType.DocumentType: + return doc.implementation.createDocumentType(n.name || 'html', n.publicId, n.systemId); + case NodeType.Element: + var tagName = getTagName(n); + var node_1; + if (n.isSVG) { + node_1 = doc.createElementNS('http://www.w3.org/2000/svg', tagName); + } + else { + node_1 = doc.createElement(tagName); + } + var _loop_1 = function (name) { + if (!n.attributes.hasOwnProperty(name)) { + return "continue"; + } + var value = n.attributes[name]; + value = + typeof value === 'boolean' || typeof value === 'number' ? '' : value; + if (!name.startsWith('rr_')) { + var isTextarea = tagName === 'textarea' && name === 'value'; + var isRemoteOrDynamicCss = tagName === 'style' && name === '_cssText'; + if (isRemoteOrDynamicCss && HACK_CSS) { + value = addHoverClass(value); + } + if (isTextarea || isRemoteOrDynamicCss) { + var child = doc.createTextNode(value); + for (var _i = 0, _a = Array.from(node_1.childNodes); _i < _a.length; _i++) { + var c = _a[_i]; + if (c.nodeType === node_1.TEXT_NODE) { + node_1.removeChild(c); + } + } + node_1.appendChild(child); + return "continue"; + } + if (tagName === 'iframe' && name === 'src') { + return "continue"; + } + try { + if (n.isSVG && name === 'xlink:href') { + node_1.setAttributeNS('http://www.w3.org/1999/xlink', name, value); + } + else if (name === 'onload' || + name === 'onclick' || + name.substring(0, 7) === 'onmouse') { + node_1.setAttribute('_' + name, value); + } + else { + node_1.setAttribute(name, value); + } + } + catch (error) { + } + } + else { + if (tagName === 'canvas' && name === 'rr_dataURL') { + var image_1 = document.createElement('img'); + image_1.src = value; + image_1.onload = function () { + var ctx = node_1.getContext('2d'); + if (ctx) { + ctx.drawImage(image_1, 0, 0, image_1.width, image_1.height); + } + }; + } + if (name === 'rr_width') { + node_1.style.width = value; + } + if (name === 'rr_height') { + node_1.style.height = value; + } + if (name === 'rr_mediaState') { + switch (value) { + case 'played': + node_1.play(); + case 'paused': + node_1.pause(); + break; + default: + } + } + } + }; + for (var name in n.attributes) { + _loop_1(name); + } + return node_1; + case NodeType.Text: + return doc.createTextNode(n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent); + case NodeType.CDATA: + return doc.createCDATASection(n.textContent); + case NodeType.Comment: + return doc.createComment(n.textContent); + default: + return null; + } +} +function buildNodeWithSN(n, doc, map, cbs, skipChild, HACK_CSS) { + if (skipChild === void 0) { skipChild = false; } + if (HACK_CSS === void 0) { HACK_CSS = true; } + var node = buildNode(n, doc, HACK_CSS); + if (!node) { + return [null, []]; + } + if (n.rootId) { + console.assert(map[n.rootId] === doc, 'Target document should has the same root id.'); + } + if (n.type === NodeType.Document) { + doc.close(); + doc.open(); + node = doc; + } + node.__sn = n; + map[n.id] = node; + var nodeIsIframe = isIframe(n); + if (n.type === NodeType.Element && nodeIsIframe) { + return [node, n.childNodes]; + } + if ((n.type === NodeType.Document || n.type === NodeType.Element) && + !skipChild) { + var _loop_2 = function (childN) { + var _a = buildNodeWithSN(childN, doc, map, cbs, false, HACK_CSS), childNode = _a[0], nestedNodes = _a[1]; + if (!childNode) { + console.warn('Failed to rebuild', childN); + return "continue"; + } + node.appendChild(childNode); + if (nestedNodes.length === 0) { + return "continue"; + } + var childNodeIsIframe = isIframe(childN); + if (childNodeIsIframe) { + cbs.push(function () { + return buildIframe(childNode, nestedNodes, map, cbs, HACK_CSS); + }); + } + }; + for (var _i = 0, _a = n.childNodes; _i < _a.length; _i++) { + var childN = _a[_i]; + _loop_2(childN); + } + } + return [node, []]; +} +function visit(idNodeMap, onVisit) { + function walk(node) { + onVisit(node); + } + for (var key in idNodeMap) { + if (idNodeMap[key]) { + walk(idNodeMap[key]); + } + } +} +function handleScroll(node) { + var n = node.__sn; + if (n.type !== NodeType.Element) { + return; + } + var el = node; + for (var name in n.attributes) { + if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) { + continue; + } + var value = n.attributes[name]; + if (name === 'rr_scrollLeft') { + el.scrollLeft = value; + } + if (name === 'rr_scrollTop') { + el.scrollTop = value; + } + } +} +function rebuild(n, doc, onVisit, HACK_CSS) { + if (HACK_CSS === void 0) { HACK_CSS = true; } + var idNodeMap = {}; + var callbackArray = []; + var node = buildNodeWithSN(n, doc, idNodeMap, callbackArray, false, HACK_CSS)[0]; + callbackArray.forEach(function (f) { return f(); }); + visit(idNodeMap, function (visitedNode) { + if (onVisit) { + onVisit(visitedNode); + } + handleScroll(visitedNode); + }); + return [node, idNodeMap]; +} + +export { snapshot, serializeNodeWithId, rebuild, buildNodeWithSN, addHoverClass, transformAttribute, visitSnapshot, cleanupSnapshot, IGNORED_NODE, NodeType }; diff --git a/es/rrweb-snapshot.min.js b/es/rrweb-snapshot.min.js new file mode 100644 index 0000000..4c11836 --- /dev/null +++ b/es/rrweb-snapshot.min.js @@ -0,0 +1,2 @@ +var NodeType;!function(e){e[e.Document=0]="Document",e[e.DocumentType=1]="DocumentType",e[e.Element=2]="Element",e[e.Text=3]="Text",e[e.CDATA=4]="CDATA",e[e.Comment=5]="Comment"}(NodeType||(NodeType={}));var _id=1,tagNameRegex=RegExp("[^a-z1-6-_]"),IGNORED_NODE=-2;function genId(){return _id++}function getValidTagName(e){var t=e.toLowerCase().trim();return tagNameRegex.test(t)?"div":t}function getCssRulesString(e){try{var t=e.rules||e.cssRules;return t?Array.from(t).map(getCssRuleString).join(""):null}catch(e){return null}}function getCssRuleString(e){return isCSSImportRule(e)?getCssRulesString(e.styleSheet)||"":e.cssText}function isCSSImportRule(e){return"styleSheet"in e}function extractOrigin(e){return(e.indexOf("//")>-1?e.split("/").slice(0,3).join("/"):e.split("/")[0]).split("?")[0]}var URL_IN_CSS_REF=/url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm,RELATIVE_PATH=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/,DATA_URI=/^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i;function absoluteToStylesheet(e,t){return(e||"").replace(URL_IN_CSS_REF,function(e,r,n,i,a,o){var s=n||a||o,u=r||i||"";if(!s)return e;if(!RELATIVE_PATH.test(s))return"url("+u+s+u+")";if(DATA_URI.test(s))return"url("+u+s+u+")";if("/"===s[0])return"url("+u+(extractOrigin(t)+s)+u+")";var l=t.split("/"),c=s.split("/");l.pop();for(var f=0,d=c;f;\n\nexport type SlimDOMOptions = Partial<{\n script: boolean;\n comment: boolean;\n headFavicon: boolean;\n headWhitespace: boolean;\n headMetaDescKeywords: boolean;\n headMetaSocial: boolean;\n headMetaRobots: boolean;\n headMetaHttpEquiv: boolean;\n headMetaAuthorship: boolean;\n headMetaVerification: boolean;\n}>;\n\nexport type CallbackArray = T[];\n","import {\n serializedNode,\n serializedNodeWithId,\n NodeType,\n attributes,\n INode,\n idNodeMap,\n MaskInputOptions,\n SlimDOMOptions,\n} from './types';\n\nlet _id = 1;\nconst tagNameRegex = RegExp('[^a-z1-6-_]');\n\nexport const IGNORED_NODE = -2;\n\nfunction genId(): number {\n return _id++;\n}\n\nfunction getValidTagName(tagName: string): string {\n const processedTagName = tagName.toLowerCase().trim();\n\n if (tagNameRegex.test(processedTagName)) {\n // if the tag name is odd and we cannot extract\n // anything from the string, then we return a\n // generic div\n return 'div';\n }\n\n return processedTagName;\n}\n\nfunction getCssRulesString(s: CSSStyleSheet): string | null {\n try {\n const rules = s.rules || s.cssRules;\n return rules ? Array.from(rules).map(getCssRuleString).join('') : null;\n } catch (error) {\n return null;\n }\n}\n\nfunction getCssRuleString(rule: CSSRule): string {\n return isCSSImportRule(rule)\n ? getCssRulesString(rule.styleSheet) || ''\n : rule.cssText;\n}\n\nfunction isCSSImportRule(rule: CSSRule): rule is CSSImportRule {\n return 'styleSheet' in rule;\n}\n\nfunction extractOrigin(url: string): string {\n let origin;\n if (url.indexOf('//') > -1) {\n origin = url.split('/').slice(0, 3).join('/');\n } else {\n origin = url.split('/')[0];\n }\n origin = origin.split('?')[0];\n return origin;\n}\n\nconst URL_IN_CSS_REF = /url\\((?:(')([^']*)'|(\")([^\"]*)\"|([^)]*))\\)/gm;\nconst RELATIVE_PATH = /^(?!www\\.|(?:http|ftp)s?:\\/\\/|[A-Za-z]:\\\\|\\/\\/).*/;\nconst DATA_URI = /^(data:)([\\w\\/\\+\\-]+);(charset=[\\w-]+|base64|utf-?8).*,(.*)/i;\nexport function absoluteToStylesheet(\n cssText: string | null,\n href: string,\n): string {\n return (cssText || '').replace(\n URL_IN_CSS_REF,\n (origin, quote1, path1, quote2, path2, path3) => {\n const filePath = path1 || path2 || path3;\n const maybe_quote = quote1 || quote2 || '';\n if (!filePath) {\n return origin;\n }\n if (!RELATIVE_PATH.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (DATA_URI.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (filePath[0] === '/') {\n return `url(${maybe_quote}${\n extractOrigin(href) + filePath\n }${maybe_quote})`;\n }\n const stack = href.split('/');\n const parts = filePath.split('/');\n stack.pop();\n for (const part of parts) {\n if (part === '.') {\n continue;\n } else if (part === '..') {\n stack.pop();\n } else {\n stack.push(part);\n }\n }\n return `url(${maybe_quote}${stack.join('/')}${maybe_quote})`;\n },\n );\n}\n\nfunction getAbsoluteSrcsetString(doc: Document, attributeValue: string) {\n if (attributeValue.trim() === '') {\n return attributeValue;\n }\n\n const srcsetValues = attributeValue.split(',');\n // srcset attributes is defined as such:\n // srcset = \"url size,url1 size1\"\n const resultingSrcsetString = srcsetValues\n .map((srcItem) => {\n // removing all but middle spaces\n const trimmedSrcItem = srcItem.trimLeft().trimRight();\n const urlAndSize = trimmedSrcItem.split(' ');\n // this means we have both 0:url and 1:size\n if (urlAndSize.length === 2) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl} ${urlAndSize[1]}`;\n } else if (urlAndSize.length === 1) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl}`;\n }\n return '';\n })\n .join(', ');\n\n return resultingSrcsetString;\n}\n\nexport function absoluteToDoc(doc: Document, attributeValue: string): string {\n if (!attributeValue || attributeValue.trim() === '') {\n return attributeValue;\n }\n const a: HTMLAnchorElement = doc.createElement('a');\n a.href = attributeValue;\n return a.href;\n}\n\nfunction isSVGElement(el: Element): boolean {\n return el.tagName === 'svg' || el instanceof SVGElement;\n}\n\nexport function transformAttribute(\n doc: Document,\n name: string,\n value: string,\n): string {\n // relative path in attribute\n if (name === 'src' || (name === 'href' && value)) {\n return absoluteToDoc(doc, value);\n } else if (name === 'srcset' && value) {\n return getAbsoluteSrcsetString(doc, value);\n } else if (name === 'style' && value) {\n return absoluteToStylesheet(value, location.href);\n } else {\n return value;\n }\n}\n\nexport function _isBlockedElement(\n element: HTMLElement,\n blockClass: string | RegExp,\n blockSelector: string | null,\n): boolean {\n if (typeof blockClass === 'string') {\n if (element.classList.contains(blockClass)) {\n return true;\n }\n } else {\n element.classList.forEach((className) => {\n if (blockClass.test(className)) {\n return true;\n }\n });\n }\n if (blockSelector) {\n return element.matches(blockSelector);\n }\n\n return false;\n}\n\nfunction serializeNode(\n n: Node,\n doc: Document,\n blockClass: string | RegExp,\n blockSelector: string | null,\n inlineStylesheet: boolean,\n maskInputOptions: MaskInputOptions = {},\n recordCanvas: boolean,\n): serializedNode | false {\n // Only record root id when document object is not the base document\n let rootId: number | undefined;\n if (((doc as unknown) as INode).__sn) {\n const docId = ((doc as unknown) as INode).__sn.id;\n rootId = docId === 1 ? undefined : docId;\n }\n switch (n.nodeType) {\n case n.DOCUMENT_NODE:\n return {\n type: NodeType.Document,\n childNodes: [],\n rootId,\n };\n case n.DOCUMENT_TYPE_NODE:\n return {\n type: NodeType.DocumentType,\n name: (n as DocumentType).name,\n publicId: (n as DocumentType).publicId,\n systemId: (n as DocumentType).systemId,\n rootId,\n };\n case n.ELEMENT_NODE:\n const needBlock = _isBlockedElement(\n n as HTMLElement,\n blockClass,\n blockSelector,\n );\n const tagName = getValidTagName((n as HTMLElement).tagName);\n let attributes: attributes = {};\n for (const { name, value } of Array.from((n as HTMLElement).attributes)) {\n attributes[name] = transformAttribute(doc, name, value);\n }\n // remote css\n if (tagName === 'link' && inlineStylesheet) {\n const stylesheet = Array.from(doc.styleSheets).find((s) => {\n return s.href === (n as HTMLLinkElement).href;\n });\n const cssText = getCssRulesString(stylesheet as CSSStyleSheet);\n if (cssText) {\n delete attributes.rel;\n delete attributes.href;\n attributes._cssText = absoluteToStylesheet(\n cssText,\n stylesheet!.href!,\n );\n }\n }\n // dynamic stylesheet\n if (\n tagName === 'style' &&\n (n as HTMLStyleElement).sheet &&\n // TODO: Currently we only try to get dynamic stylesheet when it is an empty style element\n !(\n (n as HTMLElement).innerText ||\n (n as HTMLElement).textContent ||\n ''\n ).trim().length\n ) {\n const cssText = getCssRulesString(\n (n as HTMLStyleElement).sheet as CSSStyleSheet,\n );\n if (cssText) {\n attributes._cssText = absoluteToStylesheet(cssText, location.href);\n }\n }\n // form fields\n if (\n tagName === 'input' ||\n tagName === 'textarea' ||\n tagName === 'select'\n ) {\n const value = (n as HTMLInputElement | HTMLTextAreaElement).value;\n if (\n attributes.type !== 'radio' &&\n attributes.type !== 'checkbox' &&\n attributes.type !== 'submit' &&\n attributes.type !== 'button' &&\n value\n ) {\n attributes.value =\n maskInputOptions[attributes.type as keyof MaskInputOptions] ||\n maskInputOptions[tagName as keyof MaskInputOptions]\n ? '*'.repeat(value.length)\n : value;\n } else if ((n as HTMLInputElement).checked) {\n attributes.checked = (n as HTMLInputElement).checked;\n }\n }\n if (tagName === 'option') {\n const selectValue = (n as HTMLOptionElement).parentElement;\n if (attributes.value === (selectValue as HTMLSelectElement).value) {\n attributes.selected = (n as HTMLOptionElement).selected;\n }\n }\n // canvas image data\n if (tagName === 'canvas' && recordCanvas) {\n attributes.rr_dataURL = (n as HTMLCanvasElement).toDataURL();\n }\n // media elements\n if (tagName === 'audio' || tagName === 'video') {\n attributes.rr_mediaState = (n as HTMLMediaElement).paused\n ? 'paused'\n : 'played';\n }\n // scroll\n if ((n as HTMLElement).scrollLeft) {\n attributes.rr_scrollLeft = (n as HTMLElement).scrollLeft;\n }\n if ((n as HTMLElement).scrollTop) {\n attributes.rr_scrollTop = (n as HTMLElement).scrollTop;\n }\n if (needBlock) {\n const { width, height } = (n as HTMLElement).getBoundingClientRect();\n attributes.rr_width = `${width}px`;\n attributes.rr_height = `${height}px`;\n }\n return {\n type: NodeType.Element,\n tagName,\n attributes,\n childNodes: [],\n isSVG: isSVGElement(n as Element) || undefined,\n needBlock,\n rootId,\n };\n case n.TEXT_NODE:\n // The parent node may not be a html element which has a tagName attribute.\n // So just let it be undefined which is ok in this use case.\n const parentTagName =\n n.parentNode && (n.parentNode as HTMLElement).tagName;\n let textContent = (n as Text).textContent;\n const isStyle = parentTagName === 'STYLE' ? true : undefined;\n if (isStyle && textContent) {\n textContent = absoluteToStylesheet(textContent, location.href);\n }\n if (parentTagName === 'SCRIPT') {\n textContent = 'SCRIPT_PLACEHOLDER';\n }\n return {\n type: NodeType.Text,\n textContent: textContent || '',\n isStyle,\n rootId,\n };\n case n.CDATA_SECTION_NODE:\n return {\n type: NodeType.CDATA,\n textContent: '',\n rootId,\n };\n case n.COMMENT_NODE:\n return {\n type: NodeType.Comment,\n textContent: (n as Comment).textContent || '',\n rootId,\n };\n default:\n return false;\n }\n}\n\nfunction lowerIfExists(maybeAttr: string | number | boolean): string {\n if (maybeAttr === undefined) {\n return '';\n } else {\n return (maybeAttr as string).toLowerCase();\n }\n}\n\nfunction slimDOMExcluded(\n sn: serializedNode,\n slimDOMOptions: SlimDOMOptions,\n): boolean {\n if (slimDOMOptions.comment && sn.type === NodeType.Comment) {\n // TODO: convert IE conditional comments to real nodes\n return true;\n } else if (sn.type === NodeType.Element) {\n if (\n slimDOMOptions.script &&\n (sn.tagName === 'script' ||\n (sn.tagName === 'link' &&\n sn.attributes.rel === 'preload' &&\n sn.attributes['as'] === 'script'))\n ) {\n return true;\n } else if (\n slimDOMOptions.headFavicon &&\n ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') ||\n (sn.tagName === 'meta' &&\n (lowerIfExists(sn.attributes['name']).match(\n /^msapplication-tile(image|color)$/,\n ) ||\n lowerIfExists(sn.attributes['name']) === 'application-name' ||\n lowerIfExists(sn.attributes['rel']) === 'icon' ||\n lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' ||\n lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))\n ) {\n return true;\n } else if (sn.tagName === 'meta') {\n if (\n slimDOMOptions.headMetaDescKeywords &&\n lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaSocial &&\n (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || // og = opengraph (facebook)\n lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) ||\n lowerIfExists(sn.attributes['name']) === 'pinterest')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaRobots &&\n (lowerIfExists(sn.attributes['name']) === 'robots' ||\n lowerIfExists(sn.attributes['name']) === 'googlebot' ||\n lowerIfExists(sn.attributes['name']) === 'bingbot')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaHttpEquiv &&\n sn.attributes['http-equiv'] !== undefined\n ) {\n // e.g. X-UA-Compatible, Content-Type, Content-Language,\n // cache-control, X-Translated-By\n return true;\n } else if (\n slimDOMOptions.headMetaAuthorship &&\n (lowerIfExists(sn.attributes['name']) === 'author' ||\n lowerIfExists(sn.attributes['name']) === 'generator' ||\n lowerIfExists(sn.attributes['name']) === 'framework' ||\n lowerIfExists(sn.attributes['name']) === 'publisher' ||\n lowerIfExists(sn.attributes['name']) === 'progid' ||\n lowerIfExists(sn.attributes['property']).match(/^article:/) ||\n lowerIfExists(sn.attributes['property']).match(/^product:/))\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaVerification &&\n (lowerIfExists(sn.attributes['name']) === 'google-site-verification' ||\n lowerIfExists(sn.attributes['name']) === 'yandex-verification' ||\n lowerIfExists(sn.attributes['name']) === 'csrf-token' ||\n lowerIfExists(sn.attributes['name']) === 'p:domain_verify' ||\n lowerIfExists(sn.attributes['name']) === 'verify-v1' ||\n lowerIfExists(sn.attributes['name']) === 'verification' ||\n lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nexport function serializeNodeWithId(\n n: Node | INode,\n doc: Document,\n map: idNodeMap,\n blockClass: string | RegExp,\n blockSelector: string | null,\n skipChild = false,\n inlineStylesheet = true,\n maskInputOptions?: MaskInputOptions,\n slimDOMOptions: SlimDOMOptions = {},\n recordCanvas?: boolean,\n preserveWhiteSpace = true,\n onSerialize?: (n: INode) => unknown,\n): serializedNodeWithId | null {\n const _serializedNode = serializeNode(\n n,\n doc,\n blockClass,\n blockSelector,\n inlineStylesheet,\n maskInputOptions,\n recordCanvas || false,\n );\n if (!_serializedNode) {\n // TODO: dev only\n console.warn(n, 'not serialized');\n return null;\n }\n\n let id;\n // Try to reuse the previous id\n if ('__sn' in n) {\n id = n.__sn.id;\n } else if (\n slimDOMExcluded(_serializedNode, slimDOMOptions) ||\n (!preserveWhiteSpace &&\n _serializedNode.type === NodeType.Text &&\n !_serializedNode.isStyle &&\n !_serializedNode.textContent.replace(/^\\s+|\\s+$/gm, '').length)\n ) {\n id = IGNORED_NODE;\n } else {\n id = genId();\n }\n const serializedNode = Object.assign(_serializedNode, { id });\n (n as INode).__sn = serializedNode;\n if (id === IGNORED_NODE) {\n return null; // slimDOM\n }\n map[id] = n as INode;\n if (onSerialize) {\n onSerialize(n as INode);\n }\n let recordChild = !skipChild;\n if (serializedNode.type === NodeType.Element) {\n recordChild = recordChild && !serializedNode.needBlock;\n // this property was not needed in replay side\n delete serializedNode.needBlock;\n }\n if (\n (serializedNode.type === NodeType.Document ||\n serializedNode.type === NodeType.Element) &&\n recordChild\n ) {\n if (\n slimDOMOptions.headWhitespace &&\n _serializedNode.type === NodeType.Element &&\n _serializedNode.tagName == 'head'\n // would impede performance: || getComputedStyle(n)['white-space'] === 'normal'\n ) {\n preserveWhiteSpace = false;\n }\n for (const childN of Array.from(n.childNodes)) {\n const serializedChildNode = serializeNodeWithId(\n childN,\n doc,\n map,\n blockClass,\n blockSelector,\n skipChild,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n );\n if (serializedChildNode) {\n serializedNode.childNodes.push(serializedChildNode);\n }\n }\n }\n\n if (\n serializedNode.type === NodeType.Element &&\n serializedNode.tagName === 'iframe'\n ) {\n const iframeDoc = (n as HTMLIFrameElement).contentDocument;\n if (iframeDoc) {\n const serializedIframeNode = serializeNodeWithId(\n iframeDoc,\n iframeDoc,\n map,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n );\n if (serializedIframeNode) {\n serializedNode.childNodes.push(serializedIframeNode);\n }\n }\n }\n\n return serializedNode;\n}\n\nfunction snapshot(\n n: Document,\n blockClass: string | RegExp = 'rr-block',\n inlineStylesheet = true,\n maskAllInputsOrOptions: boolean | MaskInputOptions,\n slimDOMSensibleOrOptions: boolean | SlimDOMOptions,\n recordCanvas?: boolean,\n blockSelector: string | null = null,\n preserveWhiteSpace?: boolean,\n onSerialize?: (n: INode) => unknown,\n): [serializedNodeWithId | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const maskInputOptions: MaskInputOptions =\n maskAllInputsOrOptions === true\n ? {\n color: true,\n date: true,\n 'datetime-local': true,\n email: true,\n month: true,\n number: true,\n range: true,\n search: true,\n tel: true,\n text: true,\n time: true,\n url: true,\n week: true,\n textarea: true,\n select: true,\n }\n : maskAllInputsOrOptions === false\n ? {}\n : maskAllInputsOrOptions;\n const slimDOMOptions: SlimDOMOptions =\n slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all'\n ? // if true: set of sensible options that should not throw away any information\n {\n script: true,\n comment: true,\n headFavicon: true,\n headWhitespace: true,\n headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', // destructive\n headMetaSocial: true,\n headMetaRobots: true,\n headMetaHttpEquiv: true,\n headMetaAuthorship: true,\n headMetaVerification: true,\n }\n : slimDOMSensibleOrOptions === false\n ? {}\n : slimDOMSensibleOrOptions;\n return [\n serializeNodeWithId(\n n,\n n,\n idNodeMap,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n ),\n idNodeMap,\n ];\n}\n\nexport function visitSnapshot(\n node: serializedNodeWithId,\n onVisit: (node: serializedNodeWithId) => unknown,\n) {\n function walk(current: serializedNodeWithId) {\n onVisit(current);\n if (\n current.type === NodeType.Document ||\n current.type === NodeType.Element\n ) {\n current.childNodes.forEach(walk);\n }\n }\n\n walk(node);\n}\n\nexport function cleanupSnapshot() {\n // allow a new recording to start numbering nodes from scratch\n _id = 1;\n}\n\nexport default snapshot;\n","/**\n * This file is a fork of https://github.com/reworkcss/css/blob/master/lib/parse/index.js\n * I fork it because:\n * 1. The css library was built for node.js which does not have tree-shaking supports.\n * 2. Rewrites into typescript give us a better type interface.\n */\n\n/* tslint:disable no-conditional-assignment interface-name no-shadowed-variable */\n\nexport interface ParserOptions {\n /** Silently fail on parse errors */\n silent?: boolean;\n /**\n * The path to the file containing css.\n * Makes errors and source maps more helpful, by letting them know where code comes from.\n */\n source?: string;\n}\n\n/**\n * Error thrown during parsing.\n */\nexport interface ParserError {\n /** The full error message with the source position. */\n message?: string;\n /** The error message without position. */\n reason?: string;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n filename?: string;\n line?: number;\n column?: number;\n /** The portion of code that couldn't be parsed. */\n source?: string;\n}\n\nexport interface Loc {\n line?: number;\n column?: number;\n}\n\n/**\n * Base AST Tree Node.\n */\nexport interface Node {\n /** The possible values are the ones listed in the Types section on https://github.com/reworkcss/css page. */\n type?: string;\n /** A reference to the parent node, or null if the node has no parent. */\n parent?: Node;\n /** Information about the position in the source string that corresponds to the node. */\n position?: {\n start?: Loc;\n end?: Loc;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n source?: string;\n /** The full source string passed to css.parse. */\n content?: string;\n };\n}\n\nexport interface Rule extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\nexport interface Declaration extends Node {\n /** The property name, trimmed from whitespace and comments. May not be empty. */\n property?: string;\n /** The value of the property, trimmed from whitespace and comments. Empty values are allowed. */\n value?: string;\n}\n\n/**\n * A rule-level or declaration-level comment. Comments inside selectors, properties and values etc. are lost.\n */\nexport interface Comment extends Node {\n comment?: string;\n}\n\n/**\n * The @charset at-rule.\n */\nexport interface Charset extends Node {\n /** The part following @charset. */\n charset?: string;\n}\n\n/**\n * The @custom-media at-rule\n */\nexport interface CustomMedia extends Node {\n /** The ---prefixed name. */\n name?: string;\n /** The part following the name. */\n media?: string;\n}\n\n/**\n * The @document at-rule.\n */\nexport interface Document extends Node {\n /** The part following @document. */\n document?: string;\n /** The vendor prefix in @document, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @font-face at-rule.\n */\nexport interface FontFace extends Node {\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @host at-rule.\n */\nexport interface Host extends Node {\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @import at-rule.\n */\nexport interface Import extends Node {\n /** The part following @import. */\n import?: string;\n}\n\n/**\n * The @keyframes at-rule.\n */\nexport interface KeyFrames extends Node {\n /** The name of the keyframes rule. */\n name?: string;\n /** The vendor prefix in @keyframes, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types keyframe and comment. */\n keyframes?: Array;\n}\n\nexport interface KeyFrame extends Node {\n /** The list of \"selectors\" of the keyframe rule, split on commas. Each “selector” is trimmed from whitespace. */\n values?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @media at-rule.\n */\nexport interface Media extends Node {\n /** The part following @media. */\n media?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @namespace at-rule.\n */\nexport interface Namespace extends Node {\n /** The part following @namespace. */\n namespace?: string;\n}\n\n/**\n * The @page at-rule.\n */\nexport interface Page extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @supports at-rule.\n */\nexport interface Supports extends Node {\n /** The part following @supports. */\n supports?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/** All at-rules. */\nexport type AtRule =\n | Charset\n | CustomMedia\n | Document\n | FontFace\n | Host\n | Import\n | KeyFrames\n | Media\n | Namespace\n | Page\n | Supports;\n\n/**\n * A collection of rules\n */\nexport interface StyleRules {\n source?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules: Array;\n /** Array of Errors. Errors collected during parsing when option silent is true. */\n parsingErrors?: ParserError[];\n}\n\n/**\n * The root node returned by css.parse.\n */\nexport interface Stylesheet extends Node {\n stylesheet?: StyleRules;\n}\n\n// http://www.w3.org/TR/CSS21/grammar.html\n// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027\nconst commentre = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//g;\n\nexport function parse(css: string, options: ParserOptions = {}) {\n /**\n * Positional.\n */\n\n let lineno = 1;\n let column = 1;\n\n /**\n * Update lineno and column based on `str`.\n */\n\n function updatePosition(str: string) {\n const lines = str.match(/\\n/g);\n if (lines) {\n lineno += lines.length;\n }\n let i = str.lastIndexOf('\\n');\n column = i === -1 ? column + str.length : str.length - i;\n }\n\n /**\n * Mark position and patch `node.position`.\n */\n\n function position() {\n const start = { line: lineno, column };\n return (\n node: Rule | Declaration | Comment | AtRule | Stylesheet | KeyFrame,\n ) => {\n node.position = new Position(start);\n whitespace();\n return node;\n };\n }\n\n /**\n * Store position information for a node\n */\n\n class Position {\n public content!: string;\n public start!: Loc;\n public end!: Loc;\n public source?: string;\n\n constructor(start: Loc) {\n this.start = start;\n this.end = { line: lineno, column };\n this.source = options.source;\n }\n }\n\n /**\n * Non-enumerable source string\n */\n\n Position.prototype.content = css;\n\n const errorsList: ParserError[] = [];\n\n function error(msg: string) {\n const err = new Error(\n options.source + ':' + lineno + ':' + column + ': ' + msg,\n ) as ParserError;\n err.reason = msg;\n err.filename = options.source;\n err.line = lineno;\n err.column = column;\n err.source = css;\n\n if (options.silent) {\n errorsList.push(err);\n } else {\n throw err;\n }\n }\n\n /**\n * Parse stylesheet.\n */\n\n function stylesheet(): Stylesheet {\n const rulesList = rules();\n\n return {\n type: 'stylesheet',\n stylesheet: {\n source: options.source,\n rules: rulesList,\n parsingErrors: errorsList,\n },\n };\n }\n\n /**\n * Opening brace.\n */\n\n function open() {\n return match(/^{\\s*/);\n }\n\n /**\n * Closing brace.\n */\n\n function close() {\n return match(/^}/);\n }\n\n /**\n * Parse ruleset.\n */\n\n function rules() {\n let node: Rule | void;\n const rules: Rule[] = [];\n whitespace();\n comments(rules);\n while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) {\n if (node !== false) {\n rules.push(node);\n comments(rules);\n }\n }\n return rules;\n }\n\n /**\n * Match `re` and return captures.\n */\n\n function match(re: RegExp) {\n const m = re.exec(css);\n if (!m) {\n return;\n }\n const str = m[0];\n updatePosition(str);\n css = css.slice(str.length);\n return m;\n }\n\n /**\n * Parse whitespace.\n */\n\n function whitespace() {\n match(/^\\s*/);\n }\n\n /**\n * Parse comments;\n */\n\n function comments(rules: Rule[] = []) {\n let c: Comment | void;\n while ((c = comment())) {\n if (c !== false) {\n rules.push(c);\n }\n c = comment();\n }\n return rules;\n }\n\n /**\n * Parse comment.\n */\n\n function comment() {\n const pos = position();\n if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) {\n return;\n }\n\n let i = 2;\n while (\n '' !== css.charAt(i) &&\n ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))\n ) {\n ++i;\n }\n i += 2;\n\n if ('' === css.charAt(i - 1)) {\n return error('End of comment missing');\n }\n\n const str = css.slice(2, i - 2);\n column += 2;\n updatePosition(str);\n css = css.slice(i);\n column += 2;\n\n return pos({\n type: 'comment',\n comment: str,\n });\n }\n\n /**\n * Parse selector.\n */\n\n function selector() {\n const m = match(/^([^{]+)/);\n if (!m) {\n return;\n }\n /* @fix Remove all comments from selectors\n * http://ostermiller.org/findcomment.html */\n return trim(m[0])\n .replace(/\\/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*\\/+/g, '')\n .replace(/\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*'/g, m => {\n return m.replace(/,/g, '\\u200C');\n })\n .split(/\\s*(?![^(]*\\)),\\s*/)\n .map(s => {\n return s.replace(/\\u200C/g, ',');\n });\n }\n\n /**\n * Parse declaration.\n */\n\n function declaration(): Declaration | void | never {\n const pos = position();\n\n // prop\n let propMatch = match(/^(\\*?[-#\\/\\*\\\\\\w]+(\\[[0-9a-z_-]+\\])?)\\s*/);\n if (!propMatch) {\n return;\n }\n const prop = trim(propMatch[0]);\n\n // :\n if (!match(/^:\\s*/)) {\n return error(`property missing ':'`);\n }\n\n // val\n const val = match(/^((?:'(?:\\\\'|.)*?'|\"(?:\\\\\"|.)*?\"|\\([^\\)]*?\\)|[^};])+)/);\n\n const ret = pos({\n type: 'declaration',\n property: prop.replace(commentre, ''),\n value: val ? trim(val[0]).replace(commentre, '') : '',\n });\n\n // ;\n match(/^[;\\s]*/);\n\n return ret;\n }\n\n /**\n * Parse declarations.\n */\n\n function declarations() {\n const decls: Array = [];\n\n if (!open()) {\n return error(`missing '{'`);\n }\n comments(decls);\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n if ((decl as unknown) !== false) {\n decls.push(decl);\n comments(decls);\n }\n decl = declaration();\n }\n\n if (!close()) {\n return error(`missing '}'`);\n }\n return decls;\n }\n\n /**\n * Parse keyframe.\n */\n\n function keyframe() {\n let m;\n const vals = [];\n const pos = position();\n\n while ((m = match(/^((\\d+\\.\\d+|\\.\\d+|\\d+)%?|[a-z]+)\\s*/))) {\n vals.push(m[1]);\n match(/^,\\s*/);\n }\n\n if (!vals.length) {\n return;\n }\n\n return pos({\n type: 'keyframe',\n values: vals,\n declarations: declarations() as Declaration[],\n });\n }\n\n /**\n * Parse keyframes.\n */\n\n function atkeyframes() {\n const pos = position();\n let m = match(/^@([-\\w]+)?keyframes\\s*/);\n\n if (!m) {\n return;\n }\n const vendor = m[1];\n\n // identifier\n m = match(/^([-\\w]+)\\s*/);\n if (!m) {\n return error('@keyframes missing name');\n }\n const name = m[1];\n\n if (!open()) {\n return error(`@keyframes missing '{'`);\n }\n\n let frame;\n let frames = comments();\n while ((frame = keyframe())) {\n frames.push(frame);\n frames = frames.concat(comments());\n }\n\n if (!close()) {\n return error(`@keyframes missing '}'`);\n }\n\n return pos({\n type: 'keyframes',\n name,\n vendor,\n keyframes: frames,\n });\n }\n\n /**\n * Parse supports.\n */\n\n function atsupports() {\n const pos = position();\n const m = match(/^@supports *([^{]+)/);\n\n if (!m) {\n return;\n }\n const supports = trim(m[1]);\n\n if (!open()) {\n return error(`@supports missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@supports missing '}'`);\n }\n\n return pos({\n type: 'supports',\n supports,\n rules: style,\n });\n }\n\n /**\n * Parse host.\n */\n\n function athost() {\n const pos = position();\n const m = match(/^@host\\s*/);\n\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@host missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@host missing '}'`);\n }\n\n return pos({\n type: 'host',\n rules: style,\n });\n }\n\n /**\n * Parse media.\n */\n\n function atmedia() {\n const pos = position();\n const m = match(/^@media *([^{]+)/);\n\n if (!m) {\n return;\n }\n const media = trim(m[1]);\n\n if (!open()) {\n return error(`@media missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@media missing '}'`);\n }\n\n return pos({\n type: 'media',\n media,\n rules: style,\n });\n }\n\n /**\n * Parse custom-media.\n */\n\n function atcustommedia() {\n const pos = position();\n const m = match(/^@custom-media\\s+(--[^\\s]+)\\s*([^{;]+);/);\n if (!m) {\n return;\n }\n\n return pos({\n type: 'custom-media',\n name: trim(m[1]),\n media: trim(m[2]),\n });\n }\n\n /**\n * Parse paged media.\n */\n\n function atpage() {\n const pos = position();\n const m = match(/^@page */);\n if (!m) {\n return;\n }\n\n const sel = selector() || [];\n\n if (!open()) {\n return error(`@page missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@page missing '}'`);\n }\n\n return pos({\n type: 'page',\n selectors: sel,\n declarations: decls,\n });\n }\n\n /**\n * Parse document.\n */\n\n function atdocument() {\n const pos = position();\n const m = match(/^@([-\\w]+)?document *([^{]+)/);\n if (!m) {\n return;\n }\n\n const vendor = trim(m[1]);\n const doc = trim(m[2]);\n\n if (!open()) {\n return error(`@document missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@document missing '}'`);\n }\n\n return pos({\n type: 'document',\n document: doc,\n vendor,\n rules: style,\n });\n }\n\n /**\n * Parse font-face.\n */\n\n function atfontface() {\n const pos = position();\n const m = match(/^@font-face\\s*/);\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@font-face missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@font-face missing '}'`);\n }\n\n return pos({\n type: 'font-face',\n declarations: decls,\n });\n }\n\n /**\n * Parse import\n */\n\n const atimport = _compileAtrule('import');\n\n /**\n * Parse charset\n */\n\n const atcharset = _compileAtrule('charset');\n\n /**\n * Parse namespace\n */\n\n const atnamespace = _compileAtrule('namespace');\n\n /**\n * Parse non-block at-rules\n */\n\n function _compileAtrule(name: string) {\n const re = new RegExp('^@' + name + '\\\\s*([^;]+);');\n return () => {\n const pos = position();\n const m = match(re);\n if (!m) {\n return;\n }\n const ret: Record = { type: name };\n ret[name] = m[1].trim();\n return pos(ret);\n };\n }\n\n /**\n * Parse at rule.\n */\n\n function atrule() {\n if (css[0] !== '@') {\n return;\n }\n\n return (\n atkeyframes() ||\n atmedia() ||\n atcustommedia() ||\n atsupports() ||\n atimport() ||\n atcharset() ||\n atnamespace() ||\n atdocument() ||\n atpage() ||\n athost() ||\n atfontface()\n );\n }\n\n /**\n * Parse rule.\n */\n\n function rule() {\n const pos = position();\n const sel = selector();\n\n if (!sel) {\n return error('selector missing');\n }\n comments();\n\n return pos({\n type: 'rule',\n selectors: sel,\n declarations: declarations() as Declaration[],\n });\n }\n\n return addParent(stylesheet());\n}\n\n/**\n * Trim `str`.\n */\n\nfunction trim(str: string) {\n return str ? str.replace(/^\\s+|\\s+$/g, '') : '';\n}\n\n/**\n * Adds non-enumerable parent node reference to each node.\n */\n\nfunction addParent(obj: Stylesheet, parent?: Stylesheet) {\n const isNode = obj && typeof obj.type === 'string';\n const childParent = isNode ? obj : parent;\n\n for (const k of Object.keys(obj)) {\n const value = obj[k as keyof Stylesheet];\n if (Array.isArray(value)) {\n value.forEach(v => {\n addParent(v, childParent);\n });\n } else if (value && typeof value === 'object') {\n addParent((value as unknown) as Stylesheet, childParent);\n }\n }\n\n if (isNode) {\n Object.defineProperty(obj, 'parent', {\n configurable: true,\n writable: true,\n enumerable: false,\n value: parent || null,\n });\n }\n\n return obj;\n}\n","import { parse } from './css';\nimport {\n serializedNodeWithId,\n NodeType,\n tagMap,\n elementNode,\n idNodeMap,\n INode,\n CallbackArray,\n} from './types';\n\nconst tagMap: tagMap = {\n script: 'noscript',\n // camel case svg element tag names\n altglyph: 'altGlyph',\n altglyphdef: 'altGlyphDef',\n altglyphitem: 'altGlyphItem',\n animatecolor: 'animateColor',\n animatemotion: 'animateMotion',\n animatetransform: 'animateTransform',\n clippath: 'clipPath',\n feblend: 'feBlend',\n fecolormatrix: 'feColorMatrix',\n fecomponenttransfer: 'feComponentTransfer',\n fecomposite: 'feComposite',\n feconvolvematrix: 'feConvolveMatrix',\n fediffuselighting: 'feDiffuseLighting',\n fedisplacementmap: 'feDisplacementMap',\n fedistantlight: 'feDistantLight',\n fedropshadow: 'feDropShadow',\n feflood: 'feFlood',\n fefunca: 'feFuncA',\n fefuncb: 'feFuncB',\n fefuncg: 'feFuncG',\n fefuncr: 'feFuncR',\n fegaussianblur: 'feGaussianBlur',\n feimage: 'feImage',\n femerge: 'feMerge',\n femergenode: 'feMergeNode',\n femorphology: 'feMorphology',\n feoffset: 'feOffset',\n fepointlight: 'fePointLight',\n fespecularlighting: 'feSpecularLighting',\n fespotlight: 'feSpotLight',\n fetile: 'feTile',\n feturbulence: 'feTurbulence',\n foreignobject: 'foreignObject',\n glyphref: 'glyphRef',\n lineargradient: 'linearGradient',\n radialgradient: 'radialGradient',\n};\nfunction getTagName(n: elementNode): string {\n let tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName;\n if (tagName === 'link' && n.attributes._cssText) {\n tagName = 'style';\n }\n return tagName;\n}\n\nconst HOVER_SELECTOR = /([^\\\\]):hover/g;\nexport function addHoverClass(cssText: string): string {\n const ast = parse(cssText, { silent: true });\n if (!ast.stylesheet) {\n return cssText;\n }\n ast.stylesheet.rules.forEach((rule) => {\n if ('selectors' in rule) {\n (rule.selectors || []).forEach((selector: string) => {\n if (HOVER_SELECTOR.test(selector)) {\n const newSelector = selector.replace(HOVER_SELECTOR, '$1.\\\\:hover');\n cssText = cssText.replace(selector, `${selector}, ${newSelector}`);\n }\n });\n }\n });\n return cssText;\n}\n\nfunction isIframe(n: serializedNodeWithId) {\n return n.type === NodeType.Element && n.tagName === 'iframe';\n}\n\nfunction buildIframe(\n iframe: HTMLIFrameElement,\n childNodes: serializedNodeWithId[],\n map: idNodeMap,\n cbs: CallbackArray,\n HACK_CSS: boolean,\n) {\n const targetDoc = iframe.contentDocument!;\n for (const childN of childNodes) {\n console.log('build iframe', childN);\n buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS);\n }\n}\n\nfunction buildNode(\n n: serializedNodeWithId,\n doc: Document,\n HACK_CSS: boolean,\n): Node | null {\n switch (n.type) {\n case NodeType.Document:\n return doc.implementation.createDocument(null, '', null);\n case NodeType.DocumentType:\n return doc.implementation.createDocumentType(\n n.name || 'html',\n n.publicId,\n n.systemId,\n );\n case NodeType.Element:\n const tagName = getTagName(n);\n let node: Element;\n if (n.isSVG) {\n node = doc.createElementNS('http://www.w3.org/2000/svg', tagName);\n } else {\n node = doc.createElement(tagName);\n }\n for (const name in n.attributes) {\n if (!n.attributes.hasOwnProperty(name)) {\n continue;\n }\n let value = n.attributes[name];\n value =\n typeof value === 'boolean' || typeof value === 'number' ? '' : value;\n // attribute names start with rr_ are internal attributes added by rrweb\n if (!name.startsWith('rr_')) {\n const isTextarea = tagName === 'textarea' && name === 'value';\n const isRemoteOrDynamicCss =\n tagName === 'style' && name === '_cssText';\n if (isRemoteOrDynamicCss && HACK_CSS) {\n value = addHoverClass(value);\n }\n if (isTextarea || isRemoteOrDynamicCss) {\n const child = doc.createTextNode(value);\n // https://github.com/rrweb-io/rrweb/issues/112\n for (const c of Array.from(node.childNodes)) {\n if (c.nodeType === node.TEXT_NODE) {\n node.removeChild(c);\n }\n }\n node.appendChild(child);\n continue;\n }\n if (tagName === 'iframe' && name === 'src') {\n continue;\n }\n try {\n if (n.isSVG && name === 'xlink:href') {\n node.setAttributeNS('http://www.w3.org/1999/xlink', name, value);\n } else if (\n name === 'onload' ||\n name === 'onclick' ||\n name.substring(0, 7) === 'onmouse'\n ) {\n // Rename some of the more common atttributes from https://www.w3schools.com/tags/ref_eventattributes.asp\n // as setting them triggers a console.error (which shows up despite the try/catch)\n // Assumption: these attributes are not used to css\n node.setAttribute('_' + name, value);\n } else {\n node.setAttribute(name, value);\n }\n } catch (error) {\n // skip invalid attribute\n }\n } else {\n // handle internal attributes\n if (tagName === 'canvas' && name === 'rr_dataURL') {\n const image = document.createElement('img');\n image.src = value;\n image.onload = () => {\n const ctx = (node as HTMLCanvasElement).getContext('2d');\n if (ctx) {\n ctx.drawImage(image, 0, 0, image.width, image.height);\n }\n };\n }\n if (name === 'rr_width') {\n (node as HTMLElement).style.width = value;\n }\n if (name === 'rr_height') {\n (node as HTMLElement).style.height = value;\n }\n if (name === 'rr_mediaState') {\n switch (value) {\n case 'played':\n (node as HTMLMediaElement).play();\n case 'paused':\n (node as HTMLMediaElement).pause();\n break;\n default:\n }\n }\n }\n }\n return node;\n case NodeType.Text:\n return doc.createTextNode(\n n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent,\n );\n case NodeType.CDATA:\n return doc.createCDATASection(n.textContent);\n case NodeType.Comment:\n return doc.createComment(n.textContent);\n default:\n return null;\n }\n}\n\nexport function buildNodeWithSN(\n n: serializedNodeWithId,\n doc: Document,\n map: idNodeMap,\n cbs: CallbackArray,\n skipChild = false,\n HACK_CSS = true,\n): [INode | null, serializedNodeWithId[]] {\n let node = buildNode(n, doc, HACK_CSS);\n if (!node) {\n return [null, []];\n }\n if (n.rootId) {\n console.assert(\n ((map[n.rootId] as unknown) as Document) === doc,\n 'Target document should has the same root id.',\n );\n }\n // use target document as root document\n if (n.type === NodeType.Document) {\n // close before open to make sure document was closed\n doc.close();\n doc.open();\n node = doc;\n }\n\n (node as INode).__sn = n;\n map[n.id] = node as INode;\n\n const nodeIsIframe = isIframe(n);\n if (n.type === NodeType.Element && nodeIsIframe) {\n return [node as INode, n.childNodes];\n }\n\n if (\n (n.type === NodeType.Document || n.type === NodeType.Element) &&\n !skipChild\n ) {\n for (const childN of n.childNodes) {\n const [childNode, nestedNodes] = buildNodeWithSN(\n childN,\n doc,\n map,\n cbs,\n false,\n HACK_CSS,\n );\n if (!childNode) {\n console.warn('Failed to rebuild', childN);\n continue;\n }\n\n node.appendChild(childNode);\n if (nestedNodes.length === 0) {\n continue;\n }\n const childNodeIsIframe = isIframe(childN);\n if (childNodeIsIframe) {\n cbs.push(() =>\n buildIframe(\n (childNode as unknown) as HTMLIFrameElement,\n nestedNodes,\n map,\n cbs,\n HACK_CSS,\n ),\n );\n }\n }\n }\n return [node as INode, []];\n}\n\nfunction visit(idNodeMap: idNodeMap, onVisit: (node: INode) => void) {\n function walk(node: INode) {\n onVisit(node);\n }\n\n for (const key in idNodeMap) {\n if (idNodeMap[key]) {\n walk(idNodeMap[key]);\n }\n }\n}\n\nfunction handleScroll(node: INode) {\n const n = node.__sn;\n if (n.type !== NodeType.Element) {\n return;\n }\n const el = (node as Node) as HTMLElement;\n for (const name in n.attributes) {\n if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) {\n continue;\n }\n const value = n.attributes[name];\n if (name === 'rr_scrollLeft') {\n el.scrollLeft = value as number;\n }\n if (name === 'rr_scrollTop') {\n el.scrollTop = value as number;\n }\n }\n}\n\nfunction rebuild(\n n: serializedNodeWithId,\n doc: Document,\n onVisit?: (node: INode) => unknown,\n /**\n * This is not a public API yet, just for POC\n */\n HACK_CSS: boolean = true,\n): [Node | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const callbackArray: CallbackArray = [];\n const [node] = buildNodeWithSN(\n n,\n doc,\n idNodeMap,\n callbackArray,\n false,\n HACK_CSS,\n );\n callbackArray.forEach((f) => f());\n visit(idNodeMap, (visitedNode) => {\n if (onVisit) {\n onVisit(visitedNode);\n }\n handleScroll(visitedNode);\n });\n return [node, idNodeMap];\n}\n\nexport default rebuild;\n"],"names":["NodeType","_id","tagNameRegex","RegExp","IGNORED_NODE","genId","getValidTagName","tagName","processedTagName","toLowerCase","trim","test","getCssRulesString","s","rules","cssRules","Array","from","map","getCssRuleString","join","error","rule","isCSSImportRule","styleSheet","cssText","extractOrigin","url","indexOf","split","slice","URL_IN_CSS_REF","RELATIVE_PATH","DATA_URI","absoluteToStylesheet","href","replace","origin","quote1","path1","quote2","path2","path3","filePath","maybe_quote","stack","parts","pop","parts_1","_i","part","push","getAbsoluteSrcsetString","doc","attributeValue","srcItem","urlAndSize","trimLeft","trimRight","length","absoluteToDoc","a","createElement","isSVGElement","el","SVGElement","transformAttribute","name","value","location","_isBlockedElement","element","blockClass","blockSelector","classList","contains","forEach","className","matches","serializeNode","n","inlineStylesheet","maskInputOptions","recordCanvas","rootId","__sn","docId","id","undefined","nodeType","DOCUMENT_NODE","type","Document","childNodes","DOCUMENT_TYPE_NODE","DocumentType","publicId","systemId","ELEMENT_NODE","needBlock","attributes_1","_a","attributes","_b","stylesheet","styleSheets","find","rel","_cssText","sheet","innerText","textContent","repeat","checked","selectValue","parentElement","selected","rr_dataURL","toDataURL","rr_mediaState","paused","scrollLeft","rr_scrollLeft","scrollTop","rr_scrollTop","_c","width","height","rr_width","rr_height","Element","isSVG","TEXT_NODE","parentTagName","parentNode","isStyle","Text","CDATA_SECTION_NODE","CDATA","COMMENT_NODE","Comment","lowerIfExists","maybeAttr","slimDOMExcluded","sn","slimDOMOptions","comment","script","headFavicon","match","headMetaDescKeywords","headMetaSocial","headMetaRobots","headMetaHttpEquiv","headMetaAuthorship","headMetaVerification","serializeNodeWithId","skipChild","preserveWhiteSpace","onSerialize","_serializedNode","console","warn","serializedNode","Object","assign","recordChild","headWhitespace","serializedChildNode","iframeDoc","contentDocument","serializedIframeNode","snapshot","maskAllInputsOrOptions","slimDOMSensibleOrOptions","idNodeMap","color","date","datetime-local","email","month","number","range","search","tel","text","time","week","textarea","select","visitSnapshot","node","onVisit","walk","current","cleanupSnapshot","commentre","parse","css","options","lineno","column","updatePosition","str","lines","i","lastIndexOf","position","start","line","Position","whitespace","this","end","source","prototype","content","errorsList","msg","err","Error","reason","filename","silent","open","close","comments","charAt","atrule","re","m","exec","c","pos","selector","declaration","propMatch","prop","val","ret","property","declarations","decl","decls","keyframe","vals","values","rulesList","atimport","_compileAtrule","atcharset","atnamespace","vendor","frame","frames","concat","keyframes","atkeyframes","media","style","atmedia","atcustommedia","supports","atsupports","document","atdocument","sel","selectors","atpage","athost","atfontface","addParent","parsingErrors","obj","parent","isNode","childParent","keys","isArray","v","defineProperty","configurable","writable","enumerable","tagMap","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","clippath","feblend","fecolormatrix","fecomponenttransfer","fecomposite","feconvolvematrix","fediffuselighting","fedisplacementmap","fedistantlight","fedropshadow","feflood","fefunca","fefuncb","fefuncg","fefuncr","fegaussianblur","feimage","femerge","femergenode","femorphology","feoffset","fepointlight","fespecularlighting","fespotlight","fetile","feturbulence","foreignobject","glyphref","lineargradient","radialgradient","getTagName","HOVER_SELECTOR","addHoverClass","ast","newSelector","isIframe","buildIframe","iframe","cbs","HACK_CSS","targetDoc","childNodes_1","childN","log","buildNodeWithSN","buildNode","implementation","createDocument","createDocumentType","node_1","createElementNS","hasOwnProperty","startsWith","image_1","src","onload","ctx","getContext","drawImage","play","pause","isTextarea","isRemoteOrDynamicCss","child","createTextNode","removeChild","appendChild","setAttributeNS","substring","setAttribute","createCDATASection","createComment","assert","nodeIsIframe","childNode","nestedNodes","visit","key","handleScroll","rebuild","callbackArray","f","visitedNode"],"mappings":"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"} \ No newline at end of file diff --git a/lib/rrweb-snapshot.js b/lib/rrweb-snapshot.js new file mode 100644 index 0000000..e3c5309 --- /dev/null +++ b/lib/rrweb-snapshot.js @@ -0,0 +1,1211 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +(function (NodeType) { + NodeType[NodeType["Document"] = 0] = "Document"; + NodeType[NodeType["DocumentType"] = 1] = "DocumentType"; + NodeType[NodeType["Element"] = 2] = "Element"; + NodeType[NodeType["Text"] = 3] = "Text"; + NodeType[NodeType["CDATA"] = 4] = "CDATA"; + NodeType[NodeType["Comment"] = 5] = "Comment"; +})(exports.NodeType || (exports.NodeType = {})); + +var _id = 1; +var tagNameRegex = RegExp('[^a-z1-6-_]'); +var IGNORED_NODE = -2; +function genId() { + return _id++; +} +function getValidTagName(tagName) { + var processedTagName = tagName.toLowerCase().trim(); + if (tagNameRegex.test(processedTagName)) { + return 'div'; + } + return processedTagName; +} +function getCssRulesString(s) { + try { + var rules = s.rules || s.cssRules; + return rules ? Array.from(rules).map(getCssRuleString).join('') : null; + } + catch (error) { + return null; + } +} +function getCssRuleString(rule) { + return isCSSImportRule(rule) + ? getCssRulesString(rule.styleSheet) || '' + : rule.cssText; +} +function isCSSImportRule(rule) { + return 'styleSheet' in rule; +} +function extractOrigin(url) { + var origin; + if (url.indexOf('//') > -1) { + origin = url.split('/').slice(0, 3).join('/'); + } + else { + origin = url.split('/')[0]; + } + origin = origin.split('?')[0]; + return origin; +} +var URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm; +var RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/; +var DATA_URI = /^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i; +function absoluteToStylesheet(cssText, href) { + return (cssText || '').replace(URL_IN_CSS_REF, function (origin, quote1, path1, quote2, path2, path3) { + var filePath = path1 || path2 || path3; + var maybe_quote = quote1 || quote2 || ''; + if (!filePath) { + return origin; + } + if (!RELATIVE_PATH.test(filePath)) { + return "url(" + maybe_quote + filePath + maybe_quote + ")"; + } + if (DATA_URI.test(filePath)) { + return "url(" + maybe_quote + filePath + maybe_quote + ")"; + } + if (filePath[0] === '/') { + return "url(" + maybe_quote + (extractOrigin(href) + filePath) + maybe_quote + ")"; + } + var stack = href.split('/'); + var parts = filePath.split('/'); + stack.pop(); + for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { + var part = parts_1[_i]; + if (part === '.') { + continue; + } + else if (part === '..') { + stack.pop(); + } + else { + stack.push(part); + } + } + return "url(" + maybe_quote + stack.join('/') + maybe_quote + ")"; + }); +} +function getAbsoluteSrcsetString(doc, attributeValue) { + if (attributeValue.trim() === '') { + return attributeValue; + } + var srcsetValues = attributeValue.split(','); + var resultingSrcsetString = srcsetValues + .map(function (srcItem) { + var trimmedSrcItem = srcItem.trimLeft().trimRight(); + var urlAndSize = trimmedSrcItem.split(' '); + if (urlAndSize.length === 2) { + var absUrl = absoluteToDoc(doc, urlAndSize[0]); + return absUrl + " " + urlAndSize[1]; + } + else if (urlAndSize.length === 1) { + var absUrl = absoluteToDoc(doc, urlAndSize[0]); + return "" + absUrl; + } + return ''; + }) + .join(', '); + return resultingSrcsetString; +} +function absoluteToDoc(doc, attributeValue) { + if (!attributeValue || attributeValue.trim() === '') { + return attributeValue; + } + var a = doc.createElement('a'); + a.href = attributeValue; + return a.href; +} +function isSVGElement(el) { + return el.tagName === 'svg' || el instanceof SVGElement; +} +function transformAttribute(doc, name, value) { + if (name === 'src' || (name === 'href' && value)) { + return absoluteToDoc(doc, value); + } + else if (name === 'srcset' && value) { + return getAbsoluteSrcsetString(doc, value); + } + else if (name === 'style' && value) { + return absoluteToStylesheet(value, location.href); + } + else { + return value; + } +} +function _isBlockedElement(element, blockClass, blockSelector) { + if (typeof blockClass === 'string') { + if (element.classList.contains(blockClass)) { + return true; + } + } + else { + element.classList.forEach(function (className) { + if (blockClass.test(className)) { + return true; + } + }); + } + if (blockSelector) { + return element.matches(blockSelector); + } + return false; +} +function serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas) { + if (maskInputOptions === void 0) { maskInputOptions = {}; } + var rootId; + if (doc.__sn) { + var docId = doc.__sn.id; + rootId = docId === 1 ? undefined : docId; + } + switch (n.nodeType) { + case n.DOCUMENT_NODE: + return { + type: exports.NodeType.Document, + childNodes: [], + rootId: rootId + }; + case n.DOCUMENT_TYPE_NODE: + return { + type: exports.NodeType.DocumentType, + name: n.name, + publicId: n.publicId, + systemId: n.systemId, + rootId: rootId + }; + case n.ELEMENT_NODE: + var needBlock = _isBlockedElement(n, blockClass, blockSelector); + var tagName = getValidTagName(n.tagName); + var attributes_1 = {}; + for (var _i = 0, _a = Array.from(n.attributes); _i < _a.length; _i++) { + var _b = _a[_i], name = _b.name, value = _b.value; + attributes_1[name] = transformAttribute(doc, name, value); + } + if (tagName === 'link' && inlineStylesheet) { + var stylesheet = Array.from(doc.styleSheets).find(function (s) { + return s.href === n.href; + }); + var cssText = getCssRulesString(stylesheet); + if (cssText) { + delete attributes_1.rel; + delete attributes_1.href; + attributes_1._cssText = absoluteToStylesheet(cssText, stylesheet.href); + } + } + if (tagName === 'style' && + n.sheet && + !(n.innerText || + n.textContent || + '').trim().length) { + var cssText = getCssRulesString(n.sheet); + if (cssText) { + attributes_1._cssText = absoluteToStylesheet(cssText, location.href); + } + } + if (tagName === 'input' || + tagName === 'textarea' || + tagName === 'select') { + var value = n.value; + if (attributes_1.type !== 'radio' && + attributes_1.type !== 'checkbox' && + attributes_1.type !== 'submit' && + attributes_1.type !== 'button' && + value) { + attributes_1.value = + maskInputOptions[attributes_1.type] || + maskInputOptions[tagName] + ? '*'.repeat(value.length) + : value; + } + else if (n.checked) { + attributes_1.checked = n.checked; + } + } + if (tagName === 'option') { + var selectValue = n.parentElement; + if (attributes_1.value === selectValue.value) { + attributes_1.selected = n.selected; + } + } + if (tagName === 'canvas' && recordCanvas) { + attributes_1.rr_dataURL = n.toDataURL(); + } + if (tagName === 'audio' || tagName === 'video') { + attributes_1.rr_mediaState = n.paused + ? 'paused' + : 'played'; + } + if (n.scrollLeft) { + attributes_1.rr_scrollLeft = n.scrollLeft; + } + if (n.scrollTop) { + attributes_1.rr_scrollTop = n.scrollTop; + } + if (needBlock) { + var _c = n.getBoundingClientRect(), width = _c.width, height = _c.height; + attributes_1.rr_width = width + "px"; + attributes_1.rr_height = height + "px"; + } + return { + type: exports.NodeType.Element, + tagName: tagName, + attributes: attributes_1, + childNodes: [], + isSVG: isSVGElement(n) || undefined, + needBlock: needBlock, + rootId: rootId + }; + case n.TEXT_NODE: + var parentTagName = n.parentNode && n.parentNode.tagName; + var textContent = n.textContent; + var isStyle = parentTagName === 'STYLE' ? true : undefined; + if (isStyle && textContent) { + textContent = absoluteToStylesheet(textContent, location.href); + } + if (parentTagName === 'SCRIPT') { + textContent = 'SCRIPT_PLACEHOLDER'; + } + return { + type: exports.NodeType.Text, + textContent: textContent || '', + isStyle: isStyle, + rootId: rootId + }; + case n.CDATA_SECTION_NODE: + return { + type: exports.NodeType.CDATA, + textContent: '', + rootId: rootId + }; + case n.COMMENT_NODE: + return { + type: exports.NodeType.Comment, + textContent: n.textContent || '', + rootId: rootId + }; + default: + return false; + } +} +function lowerIfExists(maybeAttr) { + if (maybeAttr === undefined) { + return ''; + } + else { + return maybeAttr.toLowerCase(); + } +} +function slimDOMExcluded(sn, slimDOMOptions) { + if (slimDOMOptions.comment && sn.type === exports.NodeType.Comment) { + return true; + } + else if (sn.type === exports.NodeType.Element) { + if (slimDOMOptions.script && + (sn.tagName === 'script' || + (sn.tagName === 'link' && + sn.attributes.rel === 'preload' && + sn.attributes['as'] === 'script'))) { + return true; + } + else if (slimDOMOptions.headFavicon && + ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') || + (sn.tagName === 'meta' && + (lowerIfExists(sn.attributes['name']).match(/^msapplication-tile(image|color)$/) || + lowerIfExists(sn.attributes['name']) === 'application-name' || + lowerIfExists(sn.attributes['rel']) === 'icon' || + lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' || + lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))) { + return true; + } + else if (sn.tagName === 'meta') { + if (slimDOMOptions.headMetaDescKeywords && + lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)) { + return true; + } + else if (slimDOMOptions.headMetaSocial && + (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || + lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) || + lowerIfExists(sn.attributes['name']) === 'pinterest')) { + return true; + } + else if (slimDOMOptions.headMetaRobots && + (lowerIfExists(sn.attributes['name']) === 'robots' || + lowerIfExists(sn.attributes['name']) === 'googlebot' || + lowerIfExists(sn.attributes['name']) === 'bingbot')) { + return true; + } + else if (slimDOMOptions.headMetaHttpEquiv && + sn.attributes['http-equiv'] !== undefined) { + return true; + } + else if (slimDOMOptions.headMetaAuthorship && + (lowerIfExists(sn.attributes['name']) === 'author' || + lowerIfExists(sn.attributes['name']) === 'generator' || + lowerIfExists(sn.attributes['name']) === 'framework' || + lowerIfExists(sn.attributes['name']) === 'publisher' || + lowerIfExists(sn.attributes['name']) === 'progid' || + lowerIfExists(sn.attributes['property']).match(/^article:/) || + lowerIfExists(sn.attributes['property']).match(/^product:/))) { + return true; + } + else if (slimDOMOptions.headMetaVerification && + (lowerIfExists(sn.attributes['name']) === 'google-site-verification' || + lowerIfExists(sn.attributes['name']) === 'yandex-verification' || + lowerIfExists(sn.attributes['name']) === 'csrf-token' || + lowerIfExists(sn.attributes['name']) === 'p:domain_verify' || + lowerIfExists(sn.attributes['name']) === 'verify-v1' || + lowerIfExists(sn.attributes['name']) === 'verification' || + lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')) { + return true; + } + } + } + return false; +} +function serializeNodeWithId(n, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize) { + if (skipChild === void 0) { skipChild = false; } + if (inlineStylesheet === void 0) { inlineStylesheet = true; } + if (slimDOMOptions === void 0) { slimDOMOptions = {}; } + if (preserveWhiteSpace === void 0) { preserveWhiteSpace = true; } + var _serializedNode = serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas || false); + if (!_serializedNode) { + console.warn(n, 'not serialized'); + return null; + } + var id; + if ('__sn' in n) { + id = n.__sn.id; + } + else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || + (!preserveWhiteSpace && + _serializedNode.type === exports.NodeType.Text && + !_serializedNode.isStyle && + !_serializedNode.textContent.replace(/^\s+|\s+$/gm, '').length)) { + id = IGNORED_NODE; + } + else { + id = genId(); + } + var serializedNode = Object.assign(_serializedNode, { id: id }); + n.__sn = serializedNode; + if (id === IGNORED_NODE) { + return null; + } + map[id] = n; + if (onSerialize) { + onSerialize(n); + } + var recordChild = !skipChild; + if (serializedNode.type === exports.NodeType.Element) { + recordChild = recordChild && !serializedNode.needBlock; + delete serializedNode.needBlock; + } + if ((serializedNode.type === exports.NodeType.Document || + serializedNode.type === exports.NodeType.Element) && + recordChild) { + if (slimDOMOptions.headWhitespace && + _serializedNode.type === exports.NodeType.Element && + _serializedNode.tagName == 'head') { + preserveWhiteSpace = false; + } + for (var _i = 0, _a = Array.from(n.childNodes); _i < _a.length; _i++) { + var childN = _a[_i]; + var serializedChildNode = serializeNodeWithId(childN, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace); + if (serializedChildNode) { + serializedNode.childNodes.push(serializedChildNode); + } + } + } + if (serializedNode.type === exports.NodeType.Element && + serializedNode.tagName === 'iframe') { + var iframeDoc = n.contentDocument; + if (iframeDoc) { + var serializedIframeNode = serializeNodeWithId(iframeDoc, iframeDoc, map, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas); + if (serializedIframeNode) { + serializedNode.childNodes.push(serializedIframeNode); + } + } + } + return serializedNode; +} +function snapshot(n, blockClass, inlineStylesheet, maskAllInputsOrOptions, slimDOMSensibleOrOptions, recordCanvas, blockSelector, preserveWhiteSpace, onSerialize) { + if (blockClass === void 0) { blockClass = 'rr-block'; } + if (inlineStylesheet === void 0) { inlineStylesheet = true; } + if (blockSelector === void 0) { blockSelector = null; } + var idNodeMap = {}; + var maskInputOptions = maskAllInputsOrOptions === true + ? { + color: true, + date: true, + 'datetime-local': true, + email: true, + month: true, + number: true, + range: true, + search: true, + tel: true, + text: true, + time: true, + url: true, + week: true, + textarea: true, + select: true + } + : maskAllInputsOrOptions === false + ? {} + : maskAllInputsOrOptions; + var slimDOMOptions = slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all' + ? + { + script: true, + comment: true, + headFavicon: true, + headWhitespace: true, + headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', + headMetaSocial: true, + headMetaRobots: true, + headMetaHttpEquiv: true, + headMetaAuthorship: true, + headMetaVerification: true + } + : slimDOMSensibleOrOptions === false + ? {} + : slimDOMSensibleOrOptions; + return [ + serializeNodeWithId(n, n, idNodeMap, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize), + idNodeMap, + ]; +} +function visitSnapshot(node, onVisit) { + function walk(current) { + onVisit(current); + if (current.type === exports.NodeType.Document || + current.type === exports.NodeType.Element) { + current.childNodes.forEach(walk); + } + } + walk(node); +} +function cleanupSnapshot() { + _id = 1; +} + +var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; +function parse(css, options) { + if (options === void 0) { options = {}; } + var lineno = 1; + var column = 1; + function updatePosition(str) { + var lines = str.match(/\n/g); + if (lines) { + lineno += lines.length; + } + var i = str.lastIndexOf('\n'); + column = i === -1 ? column + str.length : str.length - i; + } + function position() { + var start = { line: lineno, column: column }; + return function (node) { + node.position = new Position(start); + whitespace(); + return node; + }; + } + var Position = (function () { + function Position(start) { + this.start = start; + this.end = { line: lineno, column: column }; + this.source = options.source; + } + return Position; + }()); + Position.prototype.content = css; + var errorsList = []; + function error(msg) { + var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); + err.reason = msg; + err.filename = options.source; + err.line = lineno; + err.column = column; + err.source = css; + if (options.silent) { + errorsList.push(err); + } + else { + throw err; + } + } + function stylesheet() { + var rulesList = rules(); + return { + type: 'stylesheet', + stylesheet: { + source: options.source, + rules: rulesList, + parsingErrors: errorsList + } + }; + } + function open() { + return match(/^{\s*/); + } + function close() { + return match(/^}/); + } + function rules() { + var node; + var rules = []; + whitespace(); + comments(rules); + while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { + if (node !== false) { + rules.push(node); + comments(rules); + } + } + return rules; + } + function match(re) { + var m = re.exec(css); + if (!m) { + return; + } + var str = m[0]; + updatePosition(str); + css = css.slice(str.length); + return m; + } + function whitespace() { + match(/^\s*/); + } + function comments(rules) { + if (rules === void 0) { rules = []; } + var c; + while ((c = comment())) { + if (c !== false) { + rules.push(c); + } + c = comment(); + } + return rules; + } + function comment() { + var pos = position(); + if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { + return; + } + var i = 2; + while ('' !== css.charAt(i) && + ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))) { + ++i; + } + i += 2; + if ('' === css.charAt(i - 1)) { + return error('End of comment missing'); + } + var str = css.slice(2, i - 2); + column += 2; + updatePosition(str); + css = css.slice(i); + column += 2; + return pos({ + type: 'comment', + comment: str + }); + } + function selector() { + var m = match(/^([^{]+)/); + if (!m) { + return; + } + return trim(m[0]) + .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') + .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) { + return m.replace(/,/g, '\u200C'); + }) + .split(/\s*(?![^(]*\)),\s*/) + .map(function (s) { + return s.replace(/\u200C/g, ','); + }); + } + function declaration() { + var pos = position(); + var propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); + if (!propMatch) { + return; + } + var prop = trim(propMatch[0]); + if (!match(/^:\s*/)) { + return error("property missing ':'"); + } + var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); + var ret = pos({ + type: 'declaration', + property: prop.replace(commentre, ''), + value: val ? trim(val[0]).replace(commentre, '') : '' + }); + match(/^[;\s]*/); + return ret; + } + function declarations() { + var decls = []; + if (!open()) { + return error("missing '{'"); + } + comments(decls); + var decl; + while ((decl = declaration())) { + if (decl !== false) { + decls.push(decl); + comments(decls); + } + decl = declaration(); + } + if (!close()) { + return error("missing '}'"); + } + return decls; + } + function keyframe() { + var m; + var vals = []; + var pos = position(); + while ((m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/))) { + vals.push(m[1]); + match(/^,\s*/); + } + if (!vals.length) { + return; + } + return pos({ + type: 'keyframe', + values: vals, + declarations: declarations() + }); + } + function atkeyframes() { + var pos = position(); + var m = match(/^@([-\w]+)?keyframes\s*/); + if (!m) { + return; + } + var vendor = m[1]; + m = match(/^([-\w]+)\s*/); + if (!m) { + return error('@keyframes missing name'); + } + var name = m[1]; + if (!open()) { + return error("@keyframes missing '{'"); + } + var frame; + var frames = comments(); + while ((frame = keyframe())) { + frames.push(frame); + frames = frames.concat(comments()); + } + if (!close()) { + return error("@keyframes missing '}'"); + } + return pos({ + type: 'keyframes', + name: name, + vendor: vendor, + keyframes: frames + }); + } + function atsupports() { + var pos = position(); + var m = match(/^@supports *([^{]+)/); + if (!m) { + return; + } + var supports = trim(m[1]); + if (!open()) { + return error("@supports missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@supports missing '}'"); + } + return pos({ + type: 'supports', + supports: supports, + rules: style + }); + } + function athost() { + var pos = position(); + var m = match(/^@host\s*/); + if (!m) { + return; + } + if (!open()) { + return error("@host missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@host missing '}'"); + } + return pos({ + type: 'host', + rules: style + }); + } + function atmedia() { + var pos = position(); + var m = match(/^@media *([^{]+)/); + if (!m) { + return; + } + var media = trim(m[1]); + if (!open()) { + return error("@media missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@media missing '}'"); + } + return pos({ + type: 'media', + media: media, + rules: style + }); + } + function atcustommedia() { + var pos = position(); + var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); + if (!m) { + return; + } + return pos({ + type: 'custom-media', + name: trim(m[1]), + media: trim(m[2]) + }); + } + function atpage() { + var pos = position(); + var m = match(/^@page */); + if (!m) { + return; + } + var sel = selector() || []; + if (!open()) { + return error("@page missing '{'"); + } + var decls = comments(); + var decl; + while ((decl = declaration())) { + decls.push(decl); + decls = decls.concat(comments()); + } + if (!close()) { + return error("@page missing '}'"); + } + return pos({ + type: 'page', + selectors: sel, + declarations: decls + }); + } + function atdocument() { + var pos = position(); + var m = match(/^@([-\w]+)?document *([^{]+)/); + if (!m) { + return; + } + var vendor = trim(m[1]); + var doc = trim(m[2]); + if (!open()) { + return error("@document missing '{'"); + } + var style = comments().concat(rules()); + if (!close()) { + return error("@document missing '}'"); + } + return pos({ + type: 'document', + document: doc, + vendor: vendor, + rules: style + }); + } + function atfontface() { + var pos = position(); + var m = match(/^@font-face\s*/); + if (!m) { + return; + } + if (!open()) { + return error("@font-face missing '{'"); + } + var decls = comments(); + var decl; + while ((decl = declaration())) { + decls.push(decl); + decls = decls.concat(comments()); + } + if (!close()) { + return error("@font-face missing '}'"); + } + return pos({ + type: 'font-face', + declarations: decls + }); + } + var atimport = _compileAtrule('import'); + var atcharset = _compileAtrule('charset'); + var atnamespace = _compileAtrule('namespace'); + function _compileAtrule(name) { + var re = new RegExp('^@' + name + '\\s*([^;]+);'); + return function () { + var pos = position(); + var m = match(re); + if (!m) { + return; + } + var ret = { type: name }; + ret[name] = m[1].trim(); + return pos(ret); + }; + } + function atrule() { + if (css[0] !== '@') { + return; + } + return (atkeyframes() || + atmedia() || + atcustommedia() || + atsupports() || + atimport() || + atcharset() || + atnamespace() || + atdocument() || + atpage() || + athost() || + atfontface()); + } + function rule() { + var pos = position(); + var sel = selector(); + if (!sel) { + return error('selector missing'); + } + comments(); + return pos({ + type: 'rule', + selectors: sel, + declarations: declarations() + }); + } + return addParent(stylesheet()); +} +function trim(str) { + return str ? str.replace(/^\s+|\s+$/g, '') : ''; +} +function addParent(obj, parent) { + var isNode = obj && typeof obj.type === 'string'; + var childParent = isNode ? obj : parent; + for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { + var k = _a[_i]; + var value = obj[k]; + if (Array.isArray(value)) { + value.forEach(function (v) { + addParent(v, childParent); + }); + } + else if (value && typeof value === 'object') { + addParent(value, childParent); + } + } + if (isNode) { + Object.defineProperty(obj, 'parent', { + configurable: true, + writable: true, + enumerable: false, + value: parent || null + }); + } + return obj; +} + +var tagMap = { + script: 'noscript', + altglyph: 'altGlyph', + altglyphdef: 'altGlyphDef', + altglyphitem: 'altGlyphItem', + animatecolor: 'animateColor', + animatemotion: 'animateMotion', + animatetransform: 'animateTransform', + clippath: 'clipPath', + feblend: 'feBlend', + fecolormatrix: 'feColorMatrix', + fecomponenttransfer: 'feComponentTransfer', + fecomposite: 'feComposite', + feconvolvematrix: 'feConvolveMatrix', + fediffuselighting: 'feDiffuseLighting', + fedisplacementmap: 'feDisplacementMap', + fedistantlight: 'feDistantLight', + fedropshadow: 'feDropShadow', + feflood: 'feFlood', + fefunca: 'feFuncA', + fefuncb: 'feFuncB', + fefuncg: 'feFuncG', + fefuncr: 'feFuncR', + fegaussianblur: 'feGaussianBlur', + feimage: 'feImage', + femerge: 'feMerge', + femergenode: 'feMergeNode', + femorphology: 'feMorphology', + feoffset: 'feOffset', + fepointlight: 'fePointLight', + fespecularlighting: 'feSpecularLighting', + fespotlight: 'feSpotLight', + fetile: 'feTile', + feturbulence: 'feTurbulence', + foreignobject: 'foreignObject', + glyphref: 'glyphRef', + lineargradient: 'linearGradient', + radialgradient: 'radialGradient' +}; +function getTagName(n) { + var tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; + if (tagName === 'link' && n.attributes._cssText) { + tagName = 'style'; + } + return tagName; +} +var HOVER_SELECTOR = /([^\\]):hover/g; +function addHoverClass(cssText) { + var ast = parse(cssText, { silent: true }); + if (!ast.stylesheet) { + return cssText; + } + ast.stylesheet.rules.forEach(function (rule) { + if ('selectors' in rule) { + (rule.selectors || []).forEach(function (selector) { + if (HOVER_SELECTOR.test(selector)) { + var newSelector = selector.replace(HOVER_SELECTOR, '$1.\\:hover'); + cssText = cssText.replace(selector, selector + ", " + newSelector); + } + }); + } + }); + return cssText; +} +function isIframe(n) { + return n.type === exports.NodeType.Element && n.tagName === 'iframe'; +} +function buildIframe(iframe, childNodes, map, cbs, HACK_CSS) { + var targetDoc = iframe.contentDocument; + for (var _i = 0, childNodes_1 = childNodes; _i < childNodes_1.length; _i++) { + var childN = childNodes_1[_i]; + console.log('build iframe', childN); + buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS); + } +} +function buildNode(n, doc, HACK_CSS) { + switch (n.type) { + case exports.NodeType.Document: + return doc.implementation.createDocument(null, '', null); + case exports.NodeType.DocumentType: + return doc.implementation.createDocumentType(n.name || 'html', n.publicId, n.systemId); + case exports.NodeType.Element: + var tagName = getTagName(n); + var node_1; + if (n.isSVG) { + node_1 = doc.createElementNS('http://www.w3.org/2000/svg', tagName); + } + else { + node_1 = doc.createElement(tagName); + } + var _loop_1 = function (name) { + if (!n.attributes.hasOwnProperty(name)) { + return "continue"; + } + var value = n.attributes[name]; + value = + typeof value === 'boolean' || typeof value === 'number' ? '' : value; + if (!name.startsWith('rr_')) { + var isTextarea = tagName === 'textarea' && name === 'value'; + var isRemoteOrDynamicCss = tagName === 'style' && name === '_cssText'; + if (isRemoteOrDynamicCss && HACK_CSS) { + value = addHoverClass(value); + } + if (isTextarea || isRemoteOrDynamicCss) { + var child = doc.createTextNode(value); + for (var _i = 0, _a = Array.from(node_1.childNodes); _i < _a.length; _i++) { + var c = _a[_i]; + if (c.nodeType === node_1.TEXT_NODE) { + node_1.removeChild(c); + } + } + node_1.appendChild(child); + return "continue"; + } + if (tagName === 'iframe' && name === 'src') { + return "continue"; + } + try { + if (n.isSVG && name === 'xlink:href') { + node_1.setAttributeNS('http://www.w3.org/1999/xlink', name, value); + } + else if (name === 'onload' || + name === 'onclick' || + name.substring(0, 7) === 'onmouse') { + node_1.setAttribute('_' + name, value); + } + else { + node_1.setAttribute(name, value); + } + } + catch (error) { + } + } + else { + if (tagName === 'canvas' && name === 'rr_dataURL') { + var image_1 = document.createElement('img'); + image_1.src = value; + image_1.onload = function () { + var ctx = node_1.getContext('2d'); + if (ctx) { + ctx.drawImage(image_1, 0, 0, image_1.width, image_1.height); + } + }; + } + if (name === 'rr_width') { + node_1.style.width = value; + } + if (name === 'rr_height') { + node_1.style.height = value; + } + if (name === 'rr_mediaState') { + switch (value) { + case 'played': + node_1.play(); + case 'paused': + node_1.pause(); + break; + default: + } + } + } + }; + for (var name in n.attributes) { + _loop_1(name); + } + return node_1; + case exports.NodeType.Text: + return doc.createTextNode(n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent); + case exports.NodeType.CDATA: + return doc.createCDATASection(n.textContent); + case exports.NodeType.Comment: + return doc.createComment(n.textContent); + default: + return null; + } +} +function buildNodeWithSN(n, doc, map, cbs, skipChild, HACK_CSS) { + if (skipChild === void 0) { skipChild = false; } + if (HACK_CSS === void 0) { HACK_CSS = true; } + var node = buildNode(n, doc, HACK_CSS); + if (!node) { + return [null, []]; + } + if (n.rootId) { + console.assert(map[n.rootId] === doc, 'Target document should has the same root id.'); + } + if (n.type === exports.NodeType.Document) { + doc.close(); + doc.open(); + node = doc; + } + node.__sn = n; + map[n.id] = node; + var nodeIsIframe = isIframe(n); + if (n.type === exports.NodeType.Element && nodeIsIframe) { + return [node, n.childNodes]; + } + if ((n.type === exports.NodeType.Document || n.type === exports.NodeType.Element) && + !skipChild) { + var _loop_2 = function (childN) { + var _a = buildNodeWithSN(childN, doc, map, cbs, false, HACK_CSS), childNode = _a[0], nestedNodes = _a[1]; + if (!childNode) { + console.warn('Failed to rebuild', childN); + return "continue"; + } + node.appendChild(childNode); + if (nestedNodes.length === 0) { + return "continue"; + } + var childNodeIsIframe = isIframe(childN); + if (childNodeIsIframe) { + cbs.push(function () { + return buildIframe(childNode, nestedNodes, map, cbs, HACK_CSS); + }); + } + }; + for (var _i = 0, _a = n.childNodes; _i < _a.length; _i++) { + var childN = _a[_i]; + _loop_2(childN); + } + } + return [node, []]; +} +function visit(idNodeMap, onVisit) { + function walk(node) { + onVisit(node); + } + for (var key in idNodeMap) { + if (idNodeMap[key]) { + walk(idNodeMap[key]); + } + } +} +function handleScroll(node) { + var n = node.__sn; + if (n.type !== exports.NodeType.Element) { + return; + } + var el = node; + for (var name in n.attributes) { + if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) { + continue; + } + var value = n.attributes[name]; + if (name === 'rr_scrollLeft') { + el.scrollLeft = value; + } + if (name === 'rr_scrollTop') { + el.scrollTop = value; + } + } +} +function rebuild(n, doc, onVisit, HACK_CSS) { + if (HACK_CSS === void 0) { HACK_CSS = true; } + var idNodeMap = {}; + var callbackArray = []; + var node = buildNodeWithSN(n, doc, idNodeMap, callbackArray, false, HACK_CSS)[0]; + callbackArray.forEach(function (f) { return f(); }); + visit(idNodeMap, function (visitedNode) { + if (onVisit) { + onVisit(visitedNode); + } + handleScroll(visitedNode); + }); + return [node, idNodeMap]; +} + +exports.snapshot = snapshot; +exports.serializeNodeWithId = serializeNodeWithId; +exports.rebuild = rebuild; +exports.buildNodeWithSN = buildNodeWithSN; +exports.addHoverClass = addHoverClass; +exports.transformAttribute = transformAttribute; +exports.visitSnapshot = visitSnapshot; +exports.cleanupSnapshot = cleanupSnapshot; +exports.IGNORED_NODE = IGNORED_NODE; From 56accd8c1439461c740f8cfef5ef4a2643c0e73e Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Sat, 6 Feb 2021 11:08:23 +0800 Subject: [PATCH 4/6] revert ignore file --- .gitignore | 6 +- dist/rrweb-snapshot.js | 1214 -------------------------------- dist/rrweb-snapshot.min.js | 2 - dist/rrweb-snapshot.min.js.map | 1 - es/rrweb-snapshot.js | 1200 ------------------------------- es/rrweb-snapshot.min.js | 2 - es/rrweb-snapshot.min.js.map | 1 - lib/rrweb-snapshot.js | 1211 ------------------------------- 8 files changed, 3 insertions(+), 3634 deletions(-) delete mode 100644 dist/rrweb-snapshot.js delete mode 100644 dist/rrweb-snapshot.min.js delete mode 100644 dist/rrweb-snapshot.min.js.map delete mode 100644 es/rrweb-snapshot.js delete mode 100644 es/rrweb-snapshot.min.js delete mode 100644 es/rrweb-snapshot.min.js.map delete mode 100644 lib/rrweb-snapshot.js diff --git a/.gitignore b/.gitignore index 8a1f68e..2c597d0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,6 @@ node_modules package-lock.json build -# dist -# es -# lib +dist +es +lib diff --git a/dist/rrweb-snapshot.js b/dist/rrweb-snapshot.js deleted file mode 100644 index 596e720..0000000 --- a/dist/rrweb-snapshot.js +++ /dev/null @@ -1,1214 +0,0 @@ -var rrwebSnapshot = (function (exports) { - 'use strict'; - - (function (NodeType) { - NodeType[NodeType["Document"] = 0] = "Document"; - NodeType[NodeType["DocumentType"] = 1] = "DocumentType"; - NodeType[NodeType["Element"] = 2] = "Element"; - NodeType[NodeType["Text"] = 3] = "Text"; - NodeType[NodeType["CDATA"] = 4] = "CDATA"; - NodeType[NodeType["Comment"] = 5] = "Comment"; - })(exports.NodeType || (exports.NodeType = {})); - - var _id = 1; - var tagNameRegex = RegExp('[^a-z1-6-_]'); - var IGNORED_NODE = -2; - function genId() { - return _id++; - } - function getValidTagName(tagName) { - var processedTagName = tagName.toLowerCase().trim(); - if (tagNameRegex.test(processedTagName)) { - return 'div'; - } - return processedTagName; - } - function getCssRulesString(s) { - try { - var rules = s.rules || s.cssRules; - return rules ? Array.from(rules).map(getCssRuleString).join('') : null; - } - catch (error) { - return null; - } - } - function getCssRuleString(rule) { - return isCSSImportRule(rule) - ? getCssRulesString(rule.styleSheet) || '' - : rule.cssText; - } - function isCSSImportRule(rule) { - return 'styleSheet' in rule; - } - function extractOrigin(url) { - var origin; - if (url.indexOf('//') > -1) { - origin = url.split('/').slice(0, 3).join('/'); - } - else { - origin = url.split('/')[0]; - } - origin = origin.split('?')[0]; - return origin; - } - var URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm; - var RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/; - var DATA_URI = /^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i; - function absoluteToStylesheet(cssText, href) { - return (cssText || '').replace(URL_IN_CSS_REF, function (origin, quote1, path1, quote2, path2, path3) { - var filePath = path1 || path2 || path3; - var maybe_quote = quote1 || quote2 || ''; - if (!filePath) { - return origin; - } - if (!RELATIVE_PATH.test(filePath)) { - return "url(" + maybe_quote + filePath + maybe_quote + ")"; - } - if (DATA_URI.test(filePath)) { - return "url(" + maybe_quote + filePath + maybe_quote + ")"; - } - if (filePath[0] === '/') { - return "url(" + maybe_quote + (extractOrigin(href) + filePath) + maybe_quote + ")"; - } - var stack = href.split('/'); - var parts = filePath.split('/'); - stack.pop(); - for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { - var part = parts_1[_i]; - if (part === '.') { - continue; - } - else if (part === '..') { - stack.pop(); - } - else { - stack.push(part); - } - } - return "url(" + maybe_quote + stack.join('/') + maybe_quote + ")"; - }); - } - function getAbsoluteSrcsetString(doc, attributeValue) { - if (attributeValue.trim() === '') { - return attributeValue; - } - var srcsetValues = attributeValue.split(','); - var resultingSrcsetString = srcsetValues - .map(function (srcItem) { - var trimmedSrcItem = srcItem.trimLeft().trimRight(); - var urlAndSize = trimmedSrcItem.split(' '); - if (urlAndSize.length === 2) { - var absUrl = absoluteToDoc(doc, urlAndSize[0]); - return absUrl + " " + urlAndSize[1]; - } - else if (urlAndSize.length === 1) { - var absUrl = absoluteToDoc(doc, urlAndSize[0]); - return "" + absUrl; - } - return ''; - }) - .join(', '); - return resultingSrcsetString; - } - function absoluteToDoc(doc, attributeValue) { - if (!attributeValue || attributeValue.trim() === '') { - return attributeValue; - } - var a = doc.createElement('a'); - a.href = attributeValue; - return a.href; - } - function isSVGElement(el) { - return el.tagName === 'svg' || el instanceof SVGElement; - } - function transformAttribute(doc, name, value) { - if (name === 'src' || (name === 'href' && value)) { - return absoluteToDoc(doc, value); - } - else if (name === 'srcset' && value) { - return getAbsoluteSrcsetString(doc, value); - } - else if (name === 'style' && value) { - return absoluteToStylesheet(value, location.href); - } - else { - return value; - } - } - function _isBlockedElement(element, blockClass, blockSelector) { - if (typeof blockClass === 'string') { - if (element.classList.contains(blockClass)) { - return true; - } - } - else { - element.classList.forEach(function (className) { - if (blockClass.test(className)) { - return true; - } - }); - } - if (blockSelector) { - return element.matches(blockSelector); - } - return false; - } - function serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas) { - if (maskInputOptions === void 0) { maskInputOptions = {}; } - var rootId; - if (doc.__sn) { - var docId = doc.__sn.id; - rootId = docId === 1 ? undefined : docId; - } - switch (n.nodeType) { - case n.DOCUMENT_NODE: - return { - type: exports.NodeType.Document, - childNodes: [], - rootId: rootId - }; - case n.DOCUMENT_TYPE_NODE: - return { - type: exports.NodeType.DocumentType, - name: n.name, - publicId: n.publicId, - systemId: n.systemId, - rootId: rootId - }; - case n.ELEMENT_NODE: - var needBlock = _isBlockedElement(n, blockClass, blockSelector); - var tagName = getValidTagName(n.tagName); - var attributes_1 = {}; - for (var _i = 0, _a = Array.from(n.attributes); _i < _a.length; _i++) { - var _b = _a[_i], name = _b.name, value = _b.value; - attributes_1[name] = transformAttribute(doc, name, value); - } - if (tagName === 'link' && inlineStylesheet) { - var stylesheet = Array.from(doc.styleSheets).find(function (s) { - return s.href === n.href; - }); - var cssText = getCssRulesString(stylesheet); - if (cssText) { - delete attributes_1.rel; - delete attributes_1.href; - attributes_1._cssText = absoluteToStylesheet(cssText, stylesheet.href); - } - } - if (tagName === 'style' && - n.sheet && - !(n.innerText || - n.textContent || - '').trim().length) { - var cssText = getCssRulesString(n.sheet); - if (cssText) { - attributes_1._cssText = absoluteToStylesheet(cssText, location.href); - } - } - if (tagName === 'input' || - tagName === 'textarea' || - tagName === 'select') { - var value = n.value; - if (attributes_1.type !== 'radio' && - attributes_1.type !== 'checkbox' && - attributes_1.type !== 'submit' && - attributes_1.type !== 'button' && - value) { - attributes_1.value = - maskInputOptions[attributes_1.type] || - maskInputOptions[tagName] - ? '*'.repeat(value.length) - : value; - } - else if (n.checked) { - attributes_1.checked = n.checked; - } - } - if (tagName === 'option') { - var selectValue = n.parentElement; - if (attributes_1.value === selectValue.value) { - attributes_1.selected = n.selected; - } - } - if (tagName === 'canvas' && recordCanvas) { - attributes_1.rr_dataURL = n.toDataURL(); - } - if (tagName === 'audio' || tagName === 'video') { - attributes_1.rr_mediaState = n.paused - ? 'paused' - : 'played'; - } - if (n.scrollLeft) { - attributes_1.rr_scrollLeft = n.scrollLeft; - } - if (n.scrollTop) { - attributes_1.rr_scrollTop = n.scrollTop; - } - if (needBlock) { - var _c = n.getBoundingClientRect(), width = _c.width, height = _c.height; - attributes_1.rr_width = width + "px"; - attributes_1.rr_height = height + "px"; - } - return { - type: exports.NodeType.Element, - tagName: tagName, - attributes: attributes_1, - childNodes: [], - isSVG: isSVGElement(n) || undefined, - needBlock: needBlock, - rootId: rootId - }; - case n.TEXT_NODE: - var parentTagName = n.parentNode && n.parentNode.tagName; - var textContent = n.textContent; - var isStyle = parentTagName === 'STYLE' ? true : undefined; - if (isStyle && textContent) { - textContent = absoluteToStylesheet(textContent, location.href); - } - if (parentTagName === 'SCRIPT') { - textContent = 'SCRIPT_PLACEHOLDER'; - } - return { - type: exports.NodeType.Text, - textContent: textContent || '', - isStyle: isStyle, - rootId: rootId - }; - case n.CDATA_SECTION_NODE: - return { - type: exports.NodeType.CDATA, - textContent: '', - rootId: rootId - }; - case n.COMMENT_NODE: - return { - type: exports.NodeType.Comment, - textContent: n.textContent || '', - rootId: rootId - }; - default: - return false; - } - } - function lowerIfExists(maybeAttr) { - if (maybeAttr === undefined) { - return ''; - } - else { - return maybeAttr.toLowerCase(); - } - } - function slimDOMExcluded(sn, slimDOMOptions) { - if (slimDOMOptions.comment && sn.type === exports.NodeType.Comment) { - return true; - } - else if (sn.type === exports.NodeType.Element) { - if (slimDOMOptions.script && - (sn.tagName === 'script' || - (sn.tagName === 'link' && - sn.attributes.rel === 'preload' && - sn.attributes['as'] === 'script'))) { - return true; - } - else if (slimDOMOptions.headFavicon && - ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') || - (sn.tagName === 'meta' && - (lowerIfExists(sn.attributes['name']).match(/^msapplication-tile(image|color)$/) || - lowerIfExists(sn.attributes['name']) === 'application-name' || - lowerIfExists(sn.attributes['rel']) === 'icon' || - lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' || - lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))) { - return true; - } - else if (sn.tagName === 'meta') { - if (slimDOMOptions.headMetaDescKeywords && - lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)) { - return true; - } - else if (slimDOMOptions.headMetaSocial && - (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || - lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) || - lowerIfExists(sn.attributes['name']) === 'pinterest')) { - return true; - } - else if (slimDOMOptions.headMetaRobots && - (lowerIfExists(sn.attributes['name']) === 'robots' || - lowerIfExists(sn.attributes['name']) === 'googlebot' || - lowerIfExists(sn.attributes['name']) === 'bingbot')) { - return true; - } - else if (slimDOMOptions.headMetaHttpEquiv && - sn.attributes['http-equiv'] !== undefined) { - return true; - } - else if (slimDOMOptions.headMetaAuthorship && - (lowerIfExists(sn.attributes['name']) === 'author' || - lowerIfExists(sn.attributes['name']) === 'generator' || - lowerIfExists(sn.attributes['name']) === 'framework' || - lowerIfExists(sn.attributes['name']) === 'publisher' || - lowerIfExists(sn.attributes['name']) === 'progid' || - lowerIfExists(sn.attributes['property']).match(/^article:/) || - lowerIfExists(sn.attributes['property']).match(/^product:/))) { - return true; - } - else if (slimDOMOptions.headMetaVerification && - (lowerIfExists(sn.attributes['name']) === 'google-site-verification' || - lowerIfExists(sn.attributes['name']) === 'yandex-verification' || - lowerIfExists(sn.attributes['name']) === 'csrf-token' || - lowerIfExists(sn.attributes['name']) === 'p:domain_verify' || - lowerIfExists(sn.attributes['name']) === 'verify-v1' || - lowerIfExists(sn.attributes['name']) === 'verification' || - lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')) { - return true; - } - } - } - return false; - } - function serializeNodeWithId(n, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize) { - if (skipChild === void 0) { skipChild = false; } - if (inlineStylesheet === void 0) { inlineStylesheet = true; } - if (slimDOMOptions === void 0) { slimDOMOptions = {}; } - if (preserveWhiteSpace === void 0) { preserveWhiteSpace = true; } - var _serializedNode = serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas || false); - if (!_serializedNode) { - console.warn(n, 'not serialized'); - return null; - } - var id; - if ('__sn' in n) { - id = n.__sn.id; - } - else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || - (!preserveWhiteSpace && - _serializedNode.type === exports.NodeType.Text && - !_serializedNode.isStyle && - !_serializedNode.textContent.replace(/^\s+|\s+$/gm, '').length)) { - id = IGNORED_NODE; - } - else { - id = genId(); - } - var serializedNode = Object.assign(_serializedNode, { id: id }); - n.__sn = serializedNode; - if (id === IGNORED_NODE) { - return null; - } - map[id] = n; - if (onSerialize) { - onSerialize(n); - } - var recordChild = !skipChild; - if (serializedNode.type === exports.NodeType.Element) { - recordChild = recordChild && !serializedNode.needBlock; - delete serializedNode.needBlock; - } - if ((serializedNode.type === exports.NodeType.Document || - serializedNode.type === exports.NodeType.Element) && - recordChild) { - if (slimDOMOptions.headWhitespace && - _serializedNode.type === exports.NodeType.Element && - _serializedNode.tagName == 'head') { - preserveWhiteSpace = false; - } - for (var _i = 0, _a = Array.from(n.childNodes); _i < _a.length; _i++) { - var childN = _a[_i]; - var serializedChildNode = serializeNodeWithId(childN, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace); - if (serializedChildNode) { - serializedNode.childNodes.push(serializedChildNode); - } - } - } - if (serializedNode.type === exports.NodeType.Element && - serializedNode.tagName === 'iframe') { - var iframeDoc = n.contentDocument; - if (iframeDoc) { - var serializedIframeNode = serializeNodeWithId(iframeDoc, iframeDoc, map, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas); - if (serializedIframeNode) { - serializedNode.childNodes.push(serializedIframeNode); - } - } - } - return serializedNode; - } - function snapshot(n, blockClass, inlineStylesheet, maskAllInputsOrOptions, slimDOMSensibleOrOptions, recordCanvas, blockSelector, preserveWhiteSpace, onSerialize) { - if (blockClass === void 0) { blockClass = 'rr-block'; } - if (inlineStylesheet === void 0) { inlineStylesheet = true; } - if (blockSelector === void 0) { blockSelector = null; } - var idNodeMap = {}; - var maskInputOptions = maskAllInputsOrOptions === true - ? { - color: true, - date: true, - 'datetime-local': true, - email: true, - month: true, - number: true, - range: true, - search: true, - tel: true, - text: true, - time: true, - url: true, - week: true, - textarea: true, - select: true - } - : maskAllInputsOrOptions === false - ? {} - : maskAllInputsOrOptions; - var slimDOMOptions = slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all' - ? - { - script: true, - comment: true, - headFavicon: true, - headWhitespace: true, - headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', - headMetaSocial: true, - headMetaRobots: true, - headMetaHttpEquiv: true, - headMetaAuthorship: true, - headMetaVerification: true - } - : slimDOMSensibleOrOptions === false - ? {} - : slimDOMSensibleOrOptions; - return [ - serializeNodeWithId(n, n, idNodeMap, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize), - idNodeMap, - ]; - } - function visitSnapshot(node, onVisit) { - function walk(current) { - onVisit(current); - if (current.type === exports.NodeType.Document || - current.type === exports.NodeType.Element) { - current.childNodes.forEach(walk); - } - } - walk(node); - } - function cleanupSnapshot() { - _id = 1; - } - - var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; - function parse(css, options) { - if (options === void 0) { options = {}; } - var lineno = 1; - var column = 1; - function updatePosition(str) { - var lines = str.match(/\n/g); - if (lines) { - lineno += lines.length; - } - var i = str.lastIndexOf('\n'); - column = i === -1 ? column + str.length : str.length - i; - } - function position() { - var start = { line: lineno, column: column }; - return function (node) { - node.position = new Position(start); - whitespace(); - return node; - }; - } - var Position = (function () { - function Position(start) { - this.start = start; - this.end = { line: lineno, column: column }; - this.source = options.source; - } - return Position; - }()); - Position.prototype.content = css; - var errorsList = []; - function error(msg) { - var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); - err.reason = msg; - err.filename = options.source; - err.line = lineno; - err.column = column; - err.source = css; - if (options.silent) { - errorsList.push(err); - } - else { - throw err; - } - } - function stylesheet() { - var rulesList = rules(); - return { - type: 'stylesheet', - stylesheet: { - source: options.source, - rules: rulesList, - parsingErrors: errorsList - } - }; - } - function open() { - return match(/^{\s*/); - } - function close() { - return match(/^}/); - } - function rules() { - var node; - var rules = []; - whitespace(); - comments(rules); - while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { - if (node !== false) { - rules.push(node); - comments(rules); - } - } - return rules; - } - function match(re) { - var m = re.exec(css); - if (!m) { - return; - } - var str = m[0]; - updatePosition(str); - css = css.slice(str.length); - return m; - } - function whitespace() { - match(/^\s*/); - } - function comments(rules) { - if (rules === void 0) { rules = []; } - var c; - while ((c = comment())) { - if (c !== false) { - rules.push(c); - } - c = comment(); - } - return rules; - } - function comment() { - var pos = position(); - if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { - return; - } - var i = 2; - while ('' !== css.charAt(i) && - ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))) { - ++i; - } - i += 2; - if ('' === css.charAt(i - 1)) { - return error('End of comment missing'); - } - var str = css.slice(2, i - 2); - column += 2; - updatePosition(str); - css = css.slice(i); - column += 2; - return pos({ - type: 'comment', - comment: str - }); - } - function selector() { - var m = match(/^([^{]+)/); - if (!m) { - return; - } - return trim(m[0]) - .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') - .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) { - return m.replace(/,/g, '\u200C'); - }) - .split(/\s*(?![^(]*\)),\s*/) - .map(function (s) { - return s.replace(/\u200C/g, ','); - }); - } - function declaration() { - var pos = position(); - var propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); - if (!propMatch) { - return; - } - var prop = trim(propMatch[0]); - if (!match(/^:\s*/)) { - return error("property missing ':'"); - } - var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); - var ret = pos({ - type: 'declaration', - property: prop.replace(commentre, ''), - value: val ? trim(val[0]).replace(commentre, '') : '' - }); - match(/^[;\s]*/); - return ret; - } - function declarations() { - var decls = []; - if (!open()) { - return error("missing '{'"); - } - comments(decls); - var decl; - while ((decl = declaration())) { - if (decl !== false) { - decls.push(decl); - comments(decls); - } - decl = declaration(); - } - if (!close()) { - return error("missing '}'"); - } - return decls; - } - function keyframe() { - var m; - var vals = []; - var pos = position(); - while ((m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/))) { - vals.push(m[1]); - match(/^,\s*/); - } - if (!vals.length) { - return; - } - return pos({ - type: 'keyframe', - values: vals, - declarations: declarations() - }); - } - function atkeyframes() { - var pos = position(); - var m = match(/^@([-\w]+)?keyframes\s*/); - if (!m) { - return; - } - var vendor = m[1]; - m = match(/^([-\w]+)\s*/); - if (!m) { - return error('@keyframes missing name'); - } - var name = m[1]; - if (!open()) { - return error("@keyframes missing '{'"); - } - var frame; - var frames = comments(); - while ((frame = keyframe())) { - frames.push(frame); - frames = frames.concat(comments()); - } - if (!close()) { - return error("@keyframes missing '}'"); - } - return pos({ - type: 'keyframes', - name: name, - vendor: vendor, - keyframes: frames - }); - } - function atsupports() { - var pos = position(); - var m = match(/^@supports *([^{]+)/); - if (!m) { - return; - } - var supports = trim(m[1]); - if (!open()) { - return error("@supports missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@supports missing '}'"); - } - return pos({ - type: 'supports', - supports: supports, - rules: style - }); - } - function athost() { - var pos = position(); - var m = match(/^@host\s*/); - if (!m) { - return; - } - if (!open()) { - return error("@host missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@host missing '}'"); - } - return pos({ - type: 'host', - rules: style - }); - } - function atmedia() { - var pos = position(); - var m = match(/^@media *([^{]+)/); - if (!m) { - return; - } - var media = trim(m[1]); - if (!open()) { - return error("@media missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@media missing '}'"); - } - return pos({ - type: 'media', - media: media, - rules: style - }); - } - function atcustommedia() { - var pos = position(); - var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); - if (!m) { - return; - } - return pos({ - type: 'custom-media', - name: trim(m[1]), - media: trim(m[2]) - }); - } - function atpage() { - var pos = position(); - var m = match(/^@page */); - if (!m) { - return; - } - var sel = selector() || []; - if (!open()) { - return error("@page missing '{'"); - } - var decls = comments(); - var decl; - while ((decl = declaration())) { - decls.push(decl); - decls = decls.concat(comments()); - } - if (!close()) { - return error("@page missing '}'"); - } - return pos({ - type: 'page', - selectors: sel, - declarations: decls - }); - } - function atdocument() { - var pos = position(); - var m = match(/^@([-\w]+)?document *([^{]+)/); - if (!m) { - return; - } - var vendor = trim(m[1]); - var doc = trim(m[2]); - if (!open()) { - return error("@document missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@document missing '}'"); - } - return pos({ - type: 'document', - document: doc, - vendor: vendor, - rules: style - }); - } - function atfontface() { - var pos = position(); - var m = match(/^@font-face\s*/); - if (!m) { - return; - } - if (!open()) { - return error("@font-face missing '{'"); - } - var decls = comments(); - var decl; - while ((decl = declaration())) { - decls.push(decl); - decls = decls.concat(comments()); - } - if (!close()) { - return error("@font-face missing '}'"); - } - return pos({ - type: 'font-face', - declarations: decls - }); - } - var atimport = _compileAtrule('import'); - var atcharset = _compileAtrule('charset'); - var atnamespace = _compileAtrule('namespace'); - function _compileAtrule(name) { - var re = new RegExp('^@' + name + '\\s*([^;]+);'); - return function () { - var pos = position(); - var m = match(re); - if (!m) { - return; - } - var ret = { type: name }; - ret[name] = m[1].trim(); - return pos(ret); - }; - } - function atrule() { - if (css[0] !== '@') { - return; - } - return (atkeyframes() || - atmedia() || - atcustommedia() || - atsupports() || - atimport() || - atcharset() || - atnamespace() || - atdocument() || - atpage() || - athost() || - atfontface()); - } - function rule() { - var pos = position(); - var sel = selector(); - if (!sel) { - return error('selector missing'); - } - comments(); - return pos({ - type: 'rule', - selectors: sel, - declarations: declarations() - }); - } - return addParent(stylesheet()); - } - function trim(str) { - return str ? str.replace(/^\s+|\s+$/g, '') : ''; - } - function addParent(obj, parent) { - var isNode = obj && typeof obj.type === 'string'; - var childParent = isNode ? obj : parent; - for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { - var k = _a[_i]; - var value = obj[k]; - if (Array.isArray(value)) { - value.forEach(function (v) { - addParent(v, childParent); - }); - } - else if (value && typeof value === 'object') { - addParent(value, childParent); - } - } - if (isNode) { - Object.defineProperty(obj, 'parent', { - configurable: true, - writable: true, - enumerable: false, - value: parent || null - }); - } - return obj; - } - - var tagMap = { - script: 'noscript', - altglyph: 'altGlyph', - altglyphdef: 'altGlyphDef', - altglyphitem: 'altGlyphItem', - animatecolor: 'animateColor', - animatemotion: 'animateMotion', - animatetransform: 'animateTransform', - clippath: 'clipPath', - feblend: 'feBlend', - fecolormatrix: 'feColorMatrix', - fecomponenttransfer: 'feComponentTransfer', - fecomposite: 'feComposite', - feconvolvematrix: 'feConvolveMatrix', - fediffuselighting: 'feDiffuseLighting', - fedisplacementmap: 'feDisplacementMap', - fedistantlight: 'feDistantLight', - fedropshadow: 'feDropShadow', - feflood: 'feFlood', - fefunca: 'feFuncA', - fefuncb: 'feFuncB', - fefuncg: 'feFuncG', - fefuncr: 'feFuncR', - fegaussianblur: 'feGaussianBlur', - feimage: 'feImage', - femerge: 'feMerge', - femergenode: 'feMergeNode', - femorphology: 'feMorphology', - feoffset: 'feOffset', - fepointlight: 'fePointLight', - fespecularlighting: 'feSpecularLighting', - fespotlight: 'feSpotLight', - fetile: 'feTile', - feturbulence: 'feTurbulence', - foreignobject: 'foreignObject', - glyphref: 'glyphRef', - lineargradient: 'linearGradient', - radialgradient: 'radialGradient' - }; - function getTagName(n) { - var tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; - if (tagName === 'link' && n.attributes._cssText) { - tagName = 'style'; - } - return tagName; - } - var HOVER_SELECTOR = /([^\\]):hover/g; - function addHoverClass(cssText) { - var ast = parse(cssText, { silent: true }); - if (!ast.stylesheet) { - return cssText; - } - ast.stylesheet.rules.forEach(function (rule) { - if ('selectors' in rule) { - (rule.selectors || []).forEach(function (selector) { - if (HOVER_SELECTOR.test(selector)) { - var newSelector = selector.replace(HOVER_SELECTOR, '$1.\\:hover'); - cssText = cssText.replace(selector, selector + ", " + newSelector); - } - }); - } - }); - return cssText; - } - function isIframe(n) { - return n.type === exports.NodeType.Element && n.tagName === 'iframe'; - } - function buildIframe(iframe, childNodes, map, cbs, HACK_CSS) { - var targetDoc = iframe.contentDocument; - for (var _i = 0, childNodes_1 = childNodes; _i < childNodes_1.length; _i++) { - var childN = childNodes_1[_i]; - console.log('build iframe', childN); - buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS); - } - } - function buildNode(n, doc, HACK_CSS) { - switch (n.type) { - case exports.NodeType.Document: - return doc.implementation.createDocument(null, '', null); - case exports.NodeType.DocumentType: - return doc.implementation.createDocumentType(n.name || 'html', n.publicId, n.systemId); - case exports.NodeType.Element: - var tagName = getTagName(n); - var node_1; - if (n.isSVG) { - node_1 = doc.createElementNS('http://www.w3.org/2000/svg', tagName); - } - else { - node_1 = doc.createElement(tagName); - } - var _loop_1 = function (name) { - if (!n.attributes.hasOwnProperty(name)) { - return "continue"; - } - var value = n.attributes[name]; - value = - typeof value === 'boolean' || typeof value === 'number' ? '' : value; - if (!name.startsWith('rr_')) { - var isTextarea = tagName === 'textarea' && name === 'value'; - var isRemoteOrDynamicCss = tagName === 'style' && name === '_cssText'; - if (isRemoteOrDynamicCss && HACK_CSS) { - value = addHoverClass(value); - } - if (isTextarea || isRemoteOrDynamicCss) { - var child = doc.createTextNode(value); - for (var _i = 0, _a = Array.from(node_1.childNodes); _i < _a.length; _i++) { - var c = _a[_i]; - if (c.nodeType === node_1.TEXT_NODE) { - node_1.removeChild(c); - } - } - node_1.appendChild(child); - return "continue"; - } - if (tagName === 'iframe' && name === 'src') { - return "continue"; - } - try { - if (n.isSVG && name === 'xlink:href') { - node_1.setAttributeNS('http://www.w3.org/1999/xlink', name, value); - } - else if (name === 'onload' || - name === 'onclick' || - name.substring(0, 7) === 'onmouse') { - node_1.setAttribute('_' + name, value); - } - else { - node_1.setAttribute(name, value); - } - } - catch (error) { - } - } - else { - if (tagName === 'canvas' && name === 'rr_dataURL') { - var image_1 = document.createElement('img'); - image_1.src = value; - image_1.onload = function () { - var ctx = node_1.getContext('2d'); - if (ctx) { - ctx.drawImage(image_1, 0, 0, image_1.width, image_1.height); - } - }; - } - if (name === 'rr_width') { - node_1.style.width = value; - } - if (name === 'rr_height') { - node_1.style.height = value; - } - if (name === 'rr_mediaState') { - switch (value) { - case 'played': - node_1.play(); - case 'paused': - node_1.pause(); - break; - default: - } - } - } - }; - for (var name in n.attributes) { - _loop_1(name); - } - return node_1; - case exports.NodeType.Text: - return doc.createTextNode(n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent); - case exports.NodeType.CDATA: - return doc.createCDATASection(n.textContent); - case exports.NodeType.Comment: - return doc.createComment(n.textContent); - default: - return null; - } - } - function buildNodeWithSN(n, doc, map, cbs, skipChild, HACK_CSS) { - if (skipChild === void 0) { skipChild = false; } - if (HACK_CSS === void 0) { HACK_CSS = true; } - var node = buildNode(n, doc, HACK_CSS); - if (!node) { - return [null, []]; - } - if (n.rootId) { - console.assert(map[n.rootId] === doc, 'Target document should has the same root id.'); - } - if (n.type === exports.NodeType.Document) { - doc.close(); - doc.open(); - node = doc; - } - node.__sn = n; - map[n.id] = node; - var nodeIsIframe = isIframe(n); - if (n.type === exports.NodeType.Element && nodeIsIframe) { - return [node, n.childNodes]; - } - if ((n.type === exports.NodeType.Document || n.type === exports.NodeType.Element) && - !skipChild) { - var _loop_2 = function (childN) { - var _a = buildNodeWithSN(childN, doc, map, cbs, false, HACK_CSS), childNode = _a[0], nestedNodes = _a[1]; - if (!childNode) { - console.warn('Failed to rebuild', childN); - return "continue"; - } - node.appendChild(childNode); - if (nestedNodes.length === 0) { - return "continue"; - } - var childNodeIsIframe = isIframe(childN); - if (childNodeIsIframe) { - cbs.push(function () { - return buildIframe(childNode, nestedNodes, map, cbs, HACK_CSS); - }); - } - }; - for (var _i = 0, _a = n.childNodes; _i < _a.length; _i++) { - var childN = _a[_i]; - _loop_2(childN); - } - } - return [node, []]; - } - function visit(idNodeMap, onVisit) { - function walk(node) { - onVisit(node); - } - for (var key in idNodeMap) { - if (idNodeMap[key]) { - walk(idNodeMap[key]); - } - } - } - function handleScroll(node) { - var n = node.__sn; - if (n.type !== exports.NodeType.Element) { - return; - } - var el = node; - for (var name in n.attributes) { - if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) { - continue; - } - var value = n.attributes[name]; - if (name === 'rr_scrollLeft') { - el.scrollLeft = value; - } - if (name === 'rr_scrollTop') { - el.scrollTop = value; - } - } - } - function rebuild(n, doc, onVisit, HACK_CSS) { - if (HACK_CSS === void 0) { HACK_CSS = true; } - var idNodeMap = {}; - var callbackArray = []; - var node = buildNodeWithSN(n, doc, idNodeMap, callbackArray, false, HACK_CSS)[0]; - callbackArray.forEach(function (f) { return f(); }); - visit(idNodeMap, function (visitedNode) { - if (onVisit) { - onVisit(visitedNode); - } - handleScroll(visitedNode); - }); - return [node, idNodeMap]; - } - - exports.snapshot = snapshot; - exports.serializeNodeWithId = serializeNodeWithId; - exports.rebuild = rebuild; - exports.buildNodeWithSN = buildNodeWithSN; - exports.addHoverClass = addHoverClass; - exports.transformAttribute = transformAttribute; - exports.visitSnapshot = visitSnapshot; - exports.cleanupSnapshot = cleanupSnapshot; - exports.IGNORED_NODE = IGNORED_NODE; - - return exports; - -}({})); diff --git a/dist/rrweb-snapshot.min.js b/dist/rrweb-snapshot.min.js deleted file mode 100644 index d539c8e..0000000 --- a/dist/rrweb-snapshot.min.js +++ /dev/null @@ -1,2 +0,0 @@ -var rrwebSnapshot=function(e){"use strict";var t;(t=e.NodeType||(e.NodeType={}))[t.Document=0]="Document",t[t.DocumentType=1]="DocumentType",t[t.Element=2]="Element",t[t.Text=3]="Text",t[t.CDATA=4]="CDATA",t[t.Comment=5]="Comment";var r=1,n=RegExp("[^a-z1-6-_]"),a=-2;function i(e){try{var t=e.rules||e.cssRules;return t?Array.from(t).map(o).join(""):null}catch(e){return null}}function o(e){return function(e){return"styleSheet"in e}(e)?i(e.styleSheet)||"":e.cssText}var s=/url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm,u=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/,c=/^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i;function f(e,t){return(e||"").replace(s,function(e,r,n,a,i,o){var s,f=n||i||o,l=r||a||"";if(!f)return e;if(!u.test(f))return"url("+l+f+l+")";if(c.test(f))return"url("+l+f+l+")";if("/"===f[0])return"url("+l+(((s=t).indexOf("//")>-1?s.split("/").slice(0,3).join("/"):s.split("/")[0]).split("?")[0]+f)+l+")";var p=t.split("/"),m=f.split("/");p.pop();for(var d=0,h=m;d;\n\nexport type SlimDOMOptions = Partial<{\n script: boolean;\n comment: boolean;\n headFavicon: boolean;\n headWhitespace: boolean;\n headMetaDescKeywords: boolean;\n headMetaSocial: boolean;\n headMetaRobots: boolean;\n headMetaHttpEquiv: boolean;\n headMetaAuthorship: boolean;\n headMetaVerification: boolean;\n}>;\n\nexport type CallbackArray = T[];\n","import {\n serializedNode,\n serializedNodeWithId,\n NodeType,\n attributes,\n INode,\n idNodeMap,\n MaskInputOptions,\n SlimDOMOptions,\n} from './types';\n\nlet _id = 1;\nconst tagNameRegex = RegExp('[^a-z1-6-_]');\n\nexport const IGNORED_NODE = -2;\n\nfunction genId(): number {\n return _id++;\n}\n\nfunction getValidTagName(tagName: string): string {\n const processedTagName = tagName.toLowerCase().trim();\n\n if (tagNameRegex.test(processedTagName)) {\n // if the tag name is odd and we cannot extract\n // anything from the string, then we return a\n // generic div\n return 'div';\n }\n\n return processedTagName;\n}\n\nfunction getCssRulesString(s: CSSStyleSheet): string | null {\n try {\n const rules = s.rules || s.cssRules;\n return rules ? Array.from(rules).map(getCssRuleString).join('') : null;\n } catch (error) {\n return null;\n }\n}\n\nfunction getCssRuleString(rule: CSSRule): string {\n return isCSSImportRule(rule)\n ? getCssRulesString(rule.styleSheet) || ''\n : rule.cssText;\n}\n\nfunction isCSSImportRule(rule: CSSRule): rule is CSSImportRule {\n return 'styleSheet' in rule;\n}\n\nfunction extractOrigin(url: string): string {\n let origin;\n if (url.indexOf('//') > -1) {\n origin = url.split('/').slice(0, 3).join('/');\n } else {\n origin = url.split('/')[0];\n }\n origin = origin.split('?')[0];\n return origin;\n}\n\nconst URL_IN_CSS_REF = /url\\((?:(')([^']*)'|(\")([^\"]*)\"|([^)]*))\\)/gm;\nconst RELATIVE_PATH = /^(?!www\\.|(?:http|ftp)s?:\\/\\/|[A-Za-z]:\\\\|\\/\\/).*/;\nconst DATA_URI = /^(data:)([\\w\\/\\+\\-]+);(charset=[\\w-]+|base64|utf-?8).*,(.*)/i;\nexport function absoluteToStylesheet(\n cssText: string | null,\n href: string,\n): string {\n return (cssText || '').replace(\n URL_IN_CSS_REF,\n (origin, quote1, path1, quote2, path2, path3) => {\n const filePath = path1 || path2 || path3;\n const maybe_quote = quote1 || quote2 || '';\n if (!filePath) {\n return origin;\n }\n if (!RELATIVE_PATH.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (DATA_URI.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (filePath[0] === '/') {\n return `url(${maybe_quote}${\n extractOrigin(href) + filePath\n }${maybe_quote})`;\n }\n const stack = href.split('/');\n const parts = filePath.split('/');\n stack.pop();\n for (const part of parts) {\n if (part === '.') {\n continue;\n } else if (part === '..') {\n stack.pop();\n } else {\n stack.push(part);\n }\n }\n return `url(${maybe_quote}${stack.join('/')}${maybe_quote})`;\n },\n );\n}\n\nfunction getAbsoluteSrcsetString(doc: Document, attributeValue: string) {\n if (attributeValue.trim() === '') {\n return attributeValue;\n }\n\n const srcsetValues = attributeValue.split(',');\n // srcset attributes is defined as such:\n // srcset = \"url size,url1 size1\"\n const resultingSrcsetString = srcsetValues\n .map((srcItem) => {\n // removing all but middle spaces\n const trimmedSrcItem = srcItem.trimLeft().trimRight();\n const urlAndSize = trimmedSrcItem.split(' ');\n // this means we have both 0:url and 1:size\n if (urlAndSize.length === 2) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl} ${urlAndSize[1]}`;\n } else if (urlAndSize.length === 1) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl}`;\n }\n return '';\n })\n .join(', ');\n\n return resultingSrcsetString;\n}\n\nexport function absoluteToDoc(doc: Document, attributeValue: string): string {\n if (!attributeValue || attributeValue.trim() === '') {\n return attributeValue;\n }\n const a: HTMLAnchorElement = doc.createElement('a');\n a.href = attributeValue;\n return a.href;\n}\n\nfunction isSVGElement(el: Element): boolean {\n return el.tagName === 'svg' || el instanceof SVGElement;\n}\n\nexport function transformAttribute(\n doc: Document,\n name: string,\n value: string,\n): string {\n // relative path in attribute\n if (name === 'src' || (name === 'href' && value)) {\n return absoluteToDoc(doc, value);\n } else if (name === 'srcset' && value) {\n return getAbsoluteSrcsetString(doc, value);\n } else if (name === 'style' && value) {\n return absoluteToStylesheet(value, location.href);\n } else {\n return value;\n }\n}\n\nexport function _isBlockedElement(\n element: HTMLElement,\n blockClass: string | RegExp,\n blockSelector: string | null,\n): boolean {\n if (typeof blockClass === 'string') {\n if (element.classList.contains(blockClass)) {\n return true;\n }\n } else {\n element.classList.forEach((className) => {\n if (blockClass.test(className)) {\n return true;\n }\n });\n }\n if (blockSelector) {\n return element.matches(blockSelector);\n }\n\n return false;\n}\n\nfunction serializeNode(\n n: Node,\n doc: Document,\n blockClass: string | RegExp,\n blockSelector: string | null,\n inlineStylesheet: boolean,\n maskInputOptions: MaskInputOptions = {},\n recordCanvas: boolean,\n): serializedNode | false {\n // Only record root id when document object is not the base document\n let rootId: number | undefined;\n if (((doc as unknown) as INode).__sn) {\n const docId = ((doc as unknown) as INode).__sn.id;\n rootId = docId === 1 ? undefined : docId;\n }\n switch (n.nodeType) {\n case n.DOCUMENT_NODE:\n return {\n type: NodeType.Document,\n childNodes: [],\n rootId,\n };\n case n.DOCUMENT_TYPE_NODE:\n return {\n type: NodeType.DocumentType,\n name: (n as DocumentType).name,\n publicId: (n as DocumentType).publicId,\n systemId: (n as DocumentType).systemId,\n rootId,\n };\n case n.ELEMENT_NODE:\n const needBlock = _isBlockedElement(\n n as HTMLElement,\n blockClass,\n blockSelector,\n );\n const tagName = getValidTagName((n as HTMLElement).tagName);\n let attributes: attributes = {};\n for (const { name, value } of Array.from((n as HTMLElement).attributes)) {\n attributes[name] = transformAttribute(doc, name, value);\n }\n // remote css\n if (tagName === 'link' && inlineStylesheet) {\n const stylesheet = Array.from(doc.styleSheets).find((s) => {\n return s.href === (n as HTMLLinkElement).href;\n });\n const cssText = getCssRulesString(stylesheet as CSSStyleSheet);\n if (cssText) {\n delete attributes.rel;\n delete attributes.href;\n attributes._cssText = absoluteToStylesheet(\n cssText,\n stylesheet!.href!,\n );\n }\n }\n // dynamic stylesheet\n if (\n tagName === 'style' &&\n (n as HTMLStyleElement).sheet &&\n // TODO: Currently we only try to get dynamic stylesheet when it is an empty style element\n !(\n (n as HTMLElement).innerText ||\n (n as HTMLElement).textContent ||\n ''\n ).trim().length\n ) {\n const cssText = getCssRulesString(\n (n as HTMLStyleElement).sheet as CSSStyleSheet,\n );\n if (cssText) {\n attributes._cssText = absoluteToStylesheet(cssText, location.href);\n }\n }\n // form fields\n if (\n tagName === 'input' ||\n tagName === 'textarea' ||\n tagName === 'select'\n ) {\n const value = (n as HTMLInputElement | HTMLTextAreaElement).value;\n if (\n attributes.type !== 'radio' &&\n attributes.type !== 'checkbox' &&\n attributes.type !== 'submit' &&\n attributes.type !== 'button' &&\n value\n ) {\n attributes.value =\n maskInputOptions[attributes.type as keyof MaskInputOptions] ||\n maskInputOptions[tagName as keyof MaskInputOptions]\n ? '*'.repeat(value.length)\n : value;\n } else if ((n as HTMLInputElement).checked) {\n attributes.checked = (n as HTMLInputElement).checked;\n }\n }\n if (tagName === 'option') {\n const selectValue = (n as HTMLOptionElement).parentElement;\n if (attributes.value === (selectValue as HTMLSelectElement).value) {\n attributes.selected = (n as HTMLOptionElement).selected;\n }\n }\n // canvas image data\n if (tagName === 'canvas' && recordCanvas) {\n attributes.rr_dataURL = (n as HTMLCanvasElement).toDataURL();\n }\n // media elements\n if (tagName === 'audio' || tagName === 'video') {\n attributes.rr_mediaState = (n as HTMLMediaElement).paused\n ? 'paused'\n : 'played';\n }\n // scroll\n if ((n as HTMLElement).scrollLeft) {\n attributes.rr_scrollLeft = (n as HTMLElement).scrollLeft;\n }\n if ((n as HTMLElement).scrollTop) {\n attributes.rr_scrollTop = (n as HTMLElement).scrollTop;\n }\n if (needBlock) {\n const { width, height } = (n as HTMLElement).getBoundingClientRect();\n attributes.rr_width = `${width}px`;\n attributes.rr_height = `${height}px`;\n }\n return {\n type: NodeType.Element,\n tagName,\n attributes,\n childNodes: [],\n isSVG: isSVGElement(n as Element) || undefined,\n needBlock,\n rootId,\n };\n case n.TEXT_NODE:\n // The parent node may not be a html element which has a tagName attribute.\n // So just let it be undefined which is ok in this use case.\n const parentTagName =\n n.parentNode && (n.parentNode as HTMLElement).tagName;\n let textContent = (n as Text).textContent;\n const isStyle = parentTagName === 'STYLE' ? true : undefined;\n if (isStyle && textContent) {\n textContent = absoluteToStylesheet(textContent, location.href);\n }\n if (parentTagName === 'SCRIPT') {\n textContent = 'SCRIPT_PLACEHOLDER';\n }\n return {\n type: NodeType.Text,\n textContent: textContent || '',\n isStyle,\n rootId,\n };\n case n.CDATA_SECTION_NODE:\n return {\n type: NodeType.CDATA,\n textContent: '',\n rootId,\n };\n case n.COMMENT_NODE:\n return {\n type: NodeType.Comment,\n textContent: (n as Comment).textContent || '',\n rootId,\n };\n default:\n return false;\n }\n}\n\nfunction lowerIfExists(maybeAttr: string | number | boolean): string {\n if (maybeAttr === undefined) {\n return '';\n } else {\n return (maybeAttr as string).toLowerCase();\n }\n}\n\nfunction slimDOMExcluded(\n sn: serializedNode,\n slimDOMOptions: SlimDOMOptions,\n): boolean {\n if (slimDOMOptions.comment && sn.type === NodeType.Comment) {\n // TODO: convert IE conditional comments to real nodes\n return true;\n } else if (sn.type === NodeType.Element) {\n if (\n slimDOMOptions.script &&\n (sn.tagName === 'script' ||\n (sn.tagName === 'link' &&\n sn.attributes.rel === 'preload' &&\n sn.attributes['as'] === 'script'))\n ) {\n return true;\n } else if (\n slimDOMOptions.headFavicon &&\n ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') ||\n (sn.tagName === 'meta' &&\n (lowerIfExists(sn.attributes['name']).match(\n /^msapplication-tile(image|color)$/,\n ) ||\n lowerIfExists(sn.attributes['name']) === 'application-name' ||\n lowerIfExists(sn.attributes['rel']) === 'icon' ||\n lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' ||\n lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))\n ) {\n return true;\n } else if (sn.tagName === 'meta') {\n if (\n slimDOMOptions.headMetaDescKeywords &&\n lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaSocial &&\n (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || // og = opengraph (facebook)\n lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) ||\n lowerIfExists(sn.attributes['name']) === 'pinterest')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaRobots &&\n (lowerIfExists(sn.attributes['name']) === 'robots' ||\n lowerIfExists(sn.attributes['name']) === 'googlebot' ||\n lowerIfExists(sn.attributes['name']) === 'bingbot')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaHttpEquiv &&\n sn.attributes['http-equiv'] !== undefined\n ) {\n // e.g. X-UA-Compatible, Content-Type, Content-Language,\n // cache-control, X-Translated-By\n return true;\n } else if (\n slimDOMOptions.headMetaAuthorship &&\n (lowerIfExists(sn.attributes['name']) === 'author' ||\n lowerIfExists(sn.attributes['name']) === 'generator' ||\n lowerIfExists(sn.attributes['name']) === 'framework' ||\n lowerIfExists(sn.attributes['name']) === 'publisher' ||\n lowerIfExists(sn.attributes['name']) === 'progid' ||\n lowerIfExists(sn.attributes['property']).match(/^article:/) ||\n lowerIfExists(sn.attributes['property']).match(/^product:/))\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaVerification &&\n (lowerIfExists(sn.attributes['name']) === 'google-site-verification' ||\n lowerIfExists(sn.attributes['name']) === 'yandex-verification' ||\n lowerIfExists(sn.attributes['name']) === 'csrf-token' ||\n lowerIfExists(sn.attributes['name']) === 'p:domain_verify' ||\n lowerIfExists(sn.attributes['name']) === 'verify-v1' ||\n lowerIfExists(sn.attributes['name']) === 'verification' ||\n lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nexport function serializeNodeWithId(\n n: Node | INode,\n doc: Document,\n map: idNodeMap,\n blockClass: string | RegExp,\n blockSelector: string | null,\n skipChild = false,\n inlineStylesheet = true,\n maskInputOptions?: MaskInputOptions,\n slimDOMOptions: SlimDOMOptions = {},\n recordCanvas?: boolean,\n preserveWhiteSpace = true,\n onSerialize?: (n: INode) => unknown,\n): serializedNodeWithId | null {\n const _serializedNode = serializeNode(\n n,\n doc,\n blockClass,\n blockSelector,\n inlineStylesheet,\n maskInputOptions,\n recordCanvas || false,\n );\n if (!_serializedNode) {\n // TODO: dev only\n console.warn(n, 'not serialized');\n return null;\n }\n\n let id;\n // Try to reuse the previous id\n if ('__sn' in n) {\n id = n.__sn.id;\n } else if (\n slimDOMExcluded(_serializedNode, slimDOMOptions) ||\n (!preserveWhiteSpace &&\n _serializedNode.type === NodeType.Text &&\n !_serializedNode.isStyle &&\n !_serializedNode.textContent.replace(/^\\s+|\\s+$/gm, '').length)\n ) {\n id = IGNORED_NODE;\n } else {\n id = genId();\n }\n const serializedNode = Object.assign(_serializedNode, { id });\n (n as INode).__sn = serializedNode;\n if (id === IGNORED_NODE) {\n return null; // slimDOM\n }\n map[id] = n as INode;\n if (onSerialize) {\n onSerialize(n as INode);\n }\n let recordChild = !skipChild;\n if (serializedNode.type === NodeType.Element) {\n recordChild = recordChild && !serializedNode.needBlock;\n // this property was not needed in replay side\n delete serializedNode.needBlock;\n }\n if (\n (serializedNode.type === NodeType.Document ||\n serializedNode.type === NodeType.Element) &&\n recordChild\n ) {\n if (\n slimDOMOptions.headWhitespace &&\n _serializedNode.type === NodeType.Element &&\n _serializedNode.tagName == 'head'\n // would impede performance: || getComputedStyle(n)['white-space'] === 'normal'\n ) {\n preserveWhiteSpace = false;\n }\n for (const childN of Array.from(n.childNodes)) {\n const serializedChildNode = serializeNodeWithId(\n childN,\n doc,\n map,\n blockClass,\n blockSelector,\n skipChild,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n );\n if (serializedChildNode) {\n serializedNode.childNodes.push(serializedChildNode);\n }\n }\n }\n\n if (\n serializedNode.type === NodeType.Element &&\n serializedNode.tagName === 'iframe'\n ) {\n const iframeDoc = (n as HTMLIFrameElement).contentDocument;\n if (iframeDoc) {\n const serializedIframeNode = serializeNodeWithId(\n iframeDoc,\n iframeDoc,\n map,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n );\n if (serializedIframeNode) {\n serializedNode.childNodes.push(serializedIframeNode);\n }\n }\n }\n\n return serializedNode;\n}\n\nfunction snapshot(\n n: Document,\n blockClass: string | RegExp = 'rr-block',\n inlineStylesheet = true,\n maskAllInputsOrOptions: boolean | MaskInputOptions,\n slimDOMSensibleOrOptions: boolean | SlimDOMOptions,\n recordCanvas?: boolean,\n blockSelector: string | null = null,\n preserveWhiteSpace?: boolean,\n onSerialize?: (n: INode) => unknown,\n): [serializedNodeWithId | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const maskInputOptions: MaskInputOptions =\n maskAllInputsOrOptions === true\n ? {\n color: true,\n date: true,\n 'datetime-local': true,\n email: true,\n month: true,\n number: true,\n range: true,\n search: true,\n tel: true,\n text: true,\n time: true,\n url: true,\n week: true,\n textarea: true,\n select: true,\n }\n : maskAllInputsOrOptions === false\n ? {}\n : maskAllInputsOrOptions;\n const slimDOMOptions: SlimDOMOptions =\n slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all'\n ? // if true: set of sensible options that should not throw away any information\n {\n script: true,\n comment: true,\n headFavicon: true,\n headWhitespace: true,\n headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', // destructive\n headMetaSocial: true,\n headMetaRobots: true,\n headMetaHttpEquiv: true,\n headMetaAuthorship: true,\n headMetaVerification: true,\n }\n : slimDOMSensibleOrOptions === false\n ? {}\n : slimDOMSensibleOrOptions;\n return [\n serializeNodeWithId(\n n,\n n,\n idNodeMap,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n ),\n idNodeMap,\n ];\n}\n\nexport function visitSnapshot(\n node: serializedNodeWithId,\n onVisit: (node: serializedNodeWithId) => unknown,\n) {\n function walk(current: serializedNodeWithId) {\n onVisit(current);\n if (\n current.type === NodeType.Document ||\n current.type === NodeType.Element\n ) {\n current.childNodes.forEach(walk);\n }\n }\n\n walk(node);\n}\n\nexport function cleanupSnapshot() {\n // allow a new recording to start numbering nodes from scratch\n _id = 1;\n}\n\nexport default snapshot;\n","/**\n * This file is a fork of https://github.com/reworkcss/css/blob/master/lib/parse/index.js\n * I fork it because:\n * 1. The css library was built for node.js which does not have tree-shaking supports.\n * 2. Rewrites into typescript give us a better type interface.\n */\n\n/* tslint:disable no-conditional-assignment interface-name no-shadowed-variable */\n\nexport interface ParserOptions {\n /** Silently fail on parse errors */\n silent?: boolean;\n /**\n * The path to the file containing css.\n * Makes errors and source maps more helpful, by letting them know where code comes from.\n */\n source?: string;\n}\n\n/**\n * Error thrown during parsing.\n */\nexport interface ParserError {\n /** The full error message with the source position. */\n message?: string;\n /** The error message without position. */\n reason?: string;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n filename?: string;\n line?: number;\n column?: number;\n /** The portion of code that couldn't be parsed. */\n source?: string;\n}\n\nexport interface Loc {\n line?: number;\n column?: number;\n}\n\n/**\n * Base AST Tree Node.\n */\nexport interface Node {\n /** The possible values are the ones listed in the Types section on https://github.com/reworkcss/css page. */\n type?: string;\n /** A reference to the parent node, or null if the node has no parent. */\n parent?: Node;\n /** Information about the position in the source string that corresponds to the node. */\n position?: {\n start?: Loc;\n end?: Loc;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n source?: string;\n /** The full source string passed to css.parse. */\n content?: string;\n };\n}\n\nexport interface Rule extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\nexport interface Declaration extends Node {\n /** The property name, trimmed from whitespace and comments. May not be empty. */\n property?: string;\n /** The value of the property, trimmed from whitespace and comments. Empty values are allowed. */\n value?: string;\n}\n\n/**\n * A rule-level or declaration-level comment. Comments inside selectors, properties and values etc. are lost.\n */\nexport interface Comment extends Node {\n comment?: string;\n}\n\n/**\n * The @charset at-rule.\n */\nexport interface Charset extends Node {\n /** The part following @charset. */\n charset?: string;\n}\n\n/**\n * The @custom-media at-rule\n */\nexport interface CustomMedia extends Node {\n /** The ---prefixed name. */\n name?: string;\n /** The part following the name. */\n media?: string;\n}\n\n/**\n * The @document at-rule.\n */\nexport interface Document extends Node {\n /** The part following @document. */\n document?: string;\n /** The vendor prefix in @document, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @font-face at-rule.\n */\nexport interface FontFace extends Node {\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @host at-rule.\n */\nexport interface Host extends Node {\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @import at-rule.\n */\nexport interface Import extends Node {\n /** The part following @import. */\n import?: string;\n}\n\n/**\n * The @keyframes at-rule.\n */\nexport interface KeyFrames extends Node {\n /** The name of the keyframes rule. */\n name?: string;\n /** The vendor prefix in @keyframes, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types keyframe and comment. */\n keyframes?: Array;\n}\n\nexport interface KeyFrame extends Node {\n /** The list of \"selectors\" of the keyframe rule, split on commas. Each “selector” is trimmed from whitespace. */\n values?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @media at-rule.\n */\nexport interface Media extends Node {\n /** The part following @media. */\n media?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @namespace at-rule.\n */\nexport interface Namespace extends Node {\n /** The part following @namespace. */\n namespace?: string;\n}\n\n/**\n * The @page at-rule.\n */\nexport interface Page extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @supports at-rule.\n */\nexport interface Supports extends Node {\n /** The part following @supports. */\n supports?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/** All at-rules. */\nexport type AtRule =\n | Charset\n | CustomMedia\n | Document\n | FontFace\n | Host\n | Import\n | KeyFrames\n | Media\n | Namespace\n | Page\n | Supports;\n\n/**\n * A collection of rules\n */\nexport interface StyleRules {\n source?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules: Array;\n /** Array of Errors. Errors collected during parsing when option silent is true. */\n parsingErrors?: ParserError[];\n}\n\n/**\n * The root node returned by css.parse.\n */\nexport interface Stylesheet extends Node {\n stylesheet?: StyleRules;\n}\n\n// http://www.w3.org/TR/CSS21/grammar.html\n// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027\nconst commentre = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//g;\n\nexport function parse(css: string, options: ParserOptions = {}) {\n /**\n * Positional.\n */\n\n let lineno = 1;\n let column = 1;\n\n /**\n * Update lineno and column based on `str`.\n */\n\n function updatePosition(str: string) {\n const lines = str.match(/\\n/g);\n if (lines) {\n lineno += lines.length;\n }\n let i = str.lastIndexOf('\\n');\n column = i === -1 ? column + str.length : str.length - i;\n }\n\n /**\n * Mark position and patch `node.position`.\n */\n\n function position() {\n const start = { line: lineno, column };\n return (\n node: Rule | Declaration | Comment | AtRule | Stylesheet | KeyFrame,\n ) => {\n node.position = new Position(start);\n whitespace();\n return node;\n };\n }\n\n /**\n * Store position information for a node\n */\n\n class Position {\n public content!: string;\n public start!: Loc;\n public end!: Loc;\n public source?: string;\n\n constructor(start: Loc) {\n this.start = start;\n this.end = { line: lineno, column };\n this.source = options.source;\n }\n }\n\n /**\n * Non-enumerable source string\n */\n\n Position.prototype.content = css;\n\n const errorsList: ParserError[] = [];\n\n function error(msg: string) {\n const err = new Error(\n options.source + ':' + lineno + ':' + column + ': ' + msg,\n ) as ParserError;\n err.reason = msg;\n err.filename = options.source;\n err.line = lineno;\n err.column = column;\n err.source = css;\n\n if (options.silent) {\n errorsList.push(err);\n } else {\n throw err;\n }\n }\n\n /**\n * Parse stylesheet.\n */\n\n function stylesheet(): Stylesheet {\n const rulesList = rules();\n\n return {\n type: 'stylesheet',\n stylesheet: {\n source: options.source,\n rules: rulesList,\n parsingErrors: errorsList,\n },\n };\n }\n\n /**\n * Opening brace.\n */\n\n function open() {\n return match(/^{\\s*/);\n }\n\n /**\n * Closing brace.\n */\n\n function close() {\n return match(/^}/);\n }\n\n /**\n * Parse ruleset.\n */\n\n function rules() {\n let node: Rule | void;\n const rules: Rule[] = [];\n whitespace();\n comments(rules);\n while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) {\n if (node !== false) {\n rules.push(node);\n comments(rules);\n }\n }\n return rules;\n }\n\n /**\n * Match `re` and return captures.\n */\n\n function match(re: RegExp) {\n const m = re.exec(css);\n if (!m) {\n return;\n }\n const str = m[0];\n updatePosition(str);\n css = css.slice(str.length);\n return m;\n }\n\n /**\n * Parse whitespace.\n */\n\n function whitespace() {\n match(/^\\s*/);\n }\n\n /**\n * Parse comments;\n */\n\n function comments(rules: Rule[] = []) {\n let c: Comment | void;\n while ((c = comment())) {\n if (c !== false) {\n rules.push(c);\n }\n c = comment();\n }\n return rules;\n }\n\n /**\n * Parse comment.\n */\n\n function comment() {\n const pos = position();\n if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) {\n return;\n }\n\n let i = 2;\n while (\n '' !== css.charAt(i) &&\n ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))\n ) {\n ++i;\n }\n i += 2;\n\n if ('' === css.charAt(i - 1)) {\n return error('End of comment missing');\n }\n\n const str = css.slice(2, i - 2);\n column += 2;\n updatePosition(str);\n css = css.slice(i);\n column += 2;\n\n return pos({\n type: 'comment',\n comment: str,\n });\n }\n\n /**\n * Parse selector.\n */\n\n function selector() {\n const m = match(/^([^{]+)/);\n if (!m) {\n return;\n }\n /* @fix Remove all comments from selectors\n * http://ostermiller.org/findcomment.html */\n return trim(m[0])\n .replace(/\\/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*\\/+/g, '')\n .replace(/\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*'/g, m => {\n return m.replace(/,/g, '\\u200C');\n })\n .split(/\\s*(?![^(]*\\)),\\s*/)\n .map(s => {\n return s.replace(/\\u200C/g, ',');\n });\n }\n\n /**\n * Parse declaration.\n */\n\n function declaration(): Declaration | void | never {\n const pos = position();\n\n // prop\n let propMatch = match(/^(\\*?[-#\\/\\*\\\\\\w]+(\\[[0-9a-z_-]+\\])?)\\s*/);\n if (!propMatch) {\n return;\n }\n const prop = trim(propMatch[0]);\n\n // :\n if (!match(/^:\\s*/)) {\n return error(`property missing ':'`);\n }\n\n // val\n const val = match(/^((?:'(?:\\\\'|.)*?'|\"(?:\\\\\"|.)*?\"|\\([^\\)]*?\\)|[^};])+)/);\n\n const ret = pos({\n type: 'declaration',\n property: prop.replace(commentre, ''),\n value: val ? trim(val[0]).replace(commentre, '') : '',\n });\n\n // ;\n match(/^[;\\s]*/);\n\n return ret;\n }\n\n /**\n * Parse declarations.\n */\n\n function declarations() {\n const decls: Array = [];\n\n if (!open()) {\n return error(`missing '{'`);\n }\n comments(decls);\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n if ((decl as unknown) !== false) {\n decls.push(decl);\n comments(decls);\n }\n decl = declaration();\n }\n\n if (!close()) {\n return error(`missing '}'`);\n }\n return decls;\n }\n\n /**\n * Parse keyframe.\n */\n\n function keyframe() {\n let m;\n const vals = [];\n const pos = position();\n\n while ((m = match(/^((\\d+\\.\\d+|\\.\\d+|\\d+)%?|[a-z]+)\\s*/))) {\n vals.push(m[1]);\n match(/^,\\s*/);\n }\n\n if (!vals.length) {\n return;\n }\n\n return pos({\n type: 'keyframe',\n values: vals,\n declarations: declarations() as Declaration[],\n });\n }\n\n /**\n * Parse keyframes.\n */\n\n function atkeyframes() {\n const pos = position();\n let m = match(/^@([-\\w]+)?keyframes\\s*/);\n\n if (!m) {\n return;\n }\n const vendor = m[1];\n\n // identifier\n m = match(/^([-\\w]+)\\s*/);\n if (!m) {\n return error('@keyframes missing name');\n }\n const name = m[1];\n\n if (!open()) {\n return error(`@keyframes missing '{'`);\n }\n\n let frame;\n let frames = comments();\n while ((frame = keyframe())) {\n frames.push(frame);\n frames = frames.concat(comments());\n }\n\n if (!close()) {\n return error(`@keyframes missing '}'`);\n }\n\n return pos({\n type: 'keyframes',\n name,\n vendor,\n keyframes: frames,\n });\n }\n\n /**\n * Parse supports.\n */\n\n function atsupports() {\n const pos = position();\n const m = match(/^@supports *([^{]+)/);\n\n if (!m) {\n return;\n }\n const supports = trim(m[1]);\n\n if (!open()) {\n return error(`@supports missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@supports missing '}'`);\n }\n\n return pos({\n type: 'supports',\n supports,\n rules: style,\n });\n }\n\n /**\n * Parse host.\n */\n\n function athost() {\n const pos = position();\n const m = match(/^@host\\s*/);\n\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@host missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@host missing '}'`);\n }\n\n return pos({\n type: 'host',\n rules: style,\n });\n }\n\n /**\n * Parse media.\n */\n\n function atmedia() {\n const pos = position();\n const m = match(/^@media *([^{]+)/);\n\n if (!m) {\n return;\n }\n const media = trim(m[1]);\n\n if (!open()) {\n return error(`@media missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@media missing '}'`);\n }\n\n return pos({\n type: 'media',\n media,\n rules: style,\n });\n }\n\n /**\n * Parse custom-media.\n */\n\n function atcustommedia() {\n const pos = position();\n const m = match(/^@custom-media\\s+(--[^\\s]+)\\s*([^{;]+);/);\n if (!m) {\n return;\n }\n\n return pos({\n type: 'custom-media',\n name: trim(m[1]),\n media: trim(m[2]),\n });\n }\n\n /**\n * Parse paged media.\n */\n\n function atpage() {\n const pos = position();\n const m = match(/^@page */);\n if (!m) {\n return;\n }\n\n const sel = selector() || [];\n\n if (!open()) {\n return error(`@page missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@page missing '}'`);\n }\n\n return pos({\n type: 'page',\n selectors: sel,\n declarations: decls,\n });\n }\n\n /**\n * Parse document.\n */\n\n function atdocument() {\n const pos = position();\n const m = match(/^@([-\\w]+)?document *([^{]+)/);\n if (!m) {\n return;\n }\n\n const vendor = trim(m[1]);\n const doc = trim(m[2]);\n\n if (!open()) {\n return error(`@document missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@document missing '}'`);\n }\n\n return pos({\n type: 'document',\n document: doc,\n vendor,\n rules: style,\n });\n }\n\n /**\n * Parse font-face.\n */\n\n function atfontface() {\n const pos = position();\n const m = match(/^@font-face\\s*/);\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@font-face missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@font-face missing '}'`);\n }\n\n return pos({\n type: 'font-face',\n declarations: decls,\n });\n }\n\n /**\n * Parse import\n */\n\n const atimport = _compileAtrule('import');\n\n /**\n * Parse charset\n */\n\n const atcharset = _compileAtrule('charset');\n\n /**\n * Parse namespace\n */\n\n const atnamespace = _compileAtrule('namespace');\n\n /**\n * Parse non-block at-rules\n */\n\n function _compileAtrule(name: string) {\n const re = new RegExp('^@' + name + '\\\\s*([^;]+);');\n return () => {\n const pos = position();\n const m = match(re);\n if (!m) {\n return;\n }\n const ret: Record = { type: name };\n ret[name] = m[1].trim();\n return pos(ret);\n };\n }\n\n /**\n * Parse at rule.\n */\n\n function atrule() {\n if (css[0] !== '@') {\n return;\n }\n\n return (\n atkeyframes() ||\n atmedia() ||\n atcustommedia() ||\n atsupports() ||\n atimport() ||\n atcharset() ||\n atnamespace() ||\n atdocument() ||\n atpage() ||\n athost() ||\n atfontface()\n );\n }\n\n /**\n * Parse rule.\n */\n\n function rule() {\n const pos = position();\n const sel = selector();\n\n if (!sel) {\n return error('selector missing');\n }\n comments();\n\n return pos({\n type: 'rule',\n selectors: sel,\n declarations: declarations() as Declaration[],\n });\n }\n\n return addParent(stylesheet());\n}\n\n/**\n * Trim `str`.\n */\n\nfunction trim(str: string) {\n return str ? str.replace(/^\\s+|\\s+$/g, '') : '';\n}\n\n/**\n * Adds non-enumerable parent node reference to each node.\n */\n\nfunction addParent(obj: Stylesheet, parent?: Stylesheet) {\n const isNode = obj && typeof obj.type === 'string';\n const childParent = isNode ? obj : parent;\n\n for (const k of Object.keys(obj)) {\n const value = obj[k as keyof Stylesheet];\n if (Array.isArray(value)) {\n value.forEach(v => {\n addParent(v, childParent);\n });\n } else if (value && typeof value === 'object') {\n addParent((value as unknown) as Stylesheet, childParent);\n }\n }\n\n if (isNode) {\n Object.defineProperty(obj, 'parent', {\n configurable: true,\n writable: true,\n enumerable: false,\n value: parent || null,\n });\n }\n\n return obj;\n}\n","import { parse } from './css';\nimport {\n serializedNodeWithId,\n NodeType,\n tagMap,\n elementNode,\n idNodeMap,\n INode,\n CallbackArray,\n} from './types';\n\nconst tagMap: tagMap = {\n script: 'noscript',\n // camel case svg element tag names\n altglyph: 'altGlyph',\n altglyphdef: 'altGlyphDef',\n altglyphitem: 'altGlyphItem',\n animatecolor: 'animateColor',\n animatemotion: 'animateMotion',\n animatetransform: 'animateTransform',\n clippath: 'clipPath',\n feblend: 'feBlend',\n fecolormatrix: 'feColorMatrix',\n fecomponenttransfer: 'feComponentTransfer',\n fecomposite: 'feComposite',\n feconvolvematrix: 'feConvolveMatrix',\n fediffuselighting: 'feDiffuseLighting',\n fedisplacementmap: 'feDisplacementMap',\n fedistantlight: 'feDistantLight',\n fedropshadow: 'feDropShadow',\n feflood: 'feFlood',\n fefunca: 'feFuncA',\n fefuncb: 'feFuncB',\n fefuncg: 'feFuncG',\n fefuncr: 'feFuncR',\n fegaussianblur: 'feGaussianBlur',\n feimage: 'feImage',\n femerge: 'feMerge',\n femergenode: 'feMergeNode',\n femorphology: 'feMorphology',\n feoffset: 'feOffset',\n fepointlight: 'fePointLight',\n fespecularlighting: 'feSpecularLighting',\n fespotlight: 'feSpotLight',\n fetile: 'feTile',\n feturbulence: 'feTurbulence',\n foreignobject: 'foreignObject',\n glyphref: 'glyphRef',\n lineargradient: 'linearGradient',\n radialgradient: 'radialGradient',\n};\nfunction getTagName(n: elementNode): string {\n let tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName;\n if (tagName === 'link' && n.attributes._cssText) {\n tagName = 'style';\n }\n return tagName;\n}\n\nconst HOVER_SELECTOR = /([^\\\\]):hover/g;\nexport function addHoverClass(cssText: string): string {\n const ast = parse(cssText, { silent: true });\n if (!ast.stylesheet) {\n return cssText;\n }\n ast.stylesheet.rules.forEach((rule) => {\n if ('selectors' in rule) {\n (rule.selectors || []).forEach((selector: string) => {\n if (HOVER_SELECTOR.test(selector)) {\n const newSelector = selector.replace(HOVER_SELECTOR, '$1.\\\\:hover');\n cssText = cssText.replace(selector, `${selector}, ${newSelector}`);\n }\n });\n }\n });\n return cssText;\n}\n\nfunction isIframe(n: serializedNodeWithId) {\n return n.type === NodeType.Element && n.tagName === 'iframe';\n}\n\nfunction buildIframe(\n iframe: HTMLIFrameElement,\n childNodes: serializedNodeWithId[],\n map: idNodeMap,\n cbs: CallbackArray,\n HACK_CSS: boolean,\n) {\n const targetDoc = iframe.contentDocument!;\n for (const childN of childNodes) {\n console.log('build iframe', childN);\n buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS);\n }\n}\n\nfunction buildNode(\n n: serializedNodeWithId,\n doc: Document,\n HACK_CSS: boolean,\n): Node | null {\n switch (n.type) {\n case NodeType.Document:\n return doc.implementation.createDocument(null, '', null);\n case NodeType.DocumentType:\n return doc.implementation.createDocumentType(\n n.name || 'html',\n n.publicId,\n n.systemId,\n );\n case NodeType.Element:\n const tagName = getTagName(n);\n let node: Element;\n if (n.isSVG) {\n node = doc.createElementNS('http://www.w3.org/2000/svg', tagName);\n } else {\n node = doc.createElement(tagName);\n }\n for (const name in n.attributes) {\n if (!n.attributes.hasOwnProperty(name)) {\n continue;\n }\n let value = n.attributes[name];\n value =\n typeof value === 'boolean' || typeof value === 'number' ? '' : value;\n // attribute names start with rr_ are internal attributes added by rrweb\n if (!name.startsWith('rr_')) {\n const isTextarea = tagName === 'textarea' && name === 'value';\n const isRemoteOrDynamicCss =\n tagName === 'style' && name === '_cssText';\n if (isRemoteOrDynamicCss && HACK_CSS) {\n value = addHoverClass(value);\n }\n if (isTextarea || isRemoteOrDynamicCss) {\n const child = doc.createTextNode(value);\n // https://github.com/rrweb-io/rrweb/issues/112\n for (const c of Array.from(node.childNodes)) {\n if (c.nodeType === node.TEXT_NODE) {\n node.removeChild(c);\n }\n }\n node.appendChild(child);\n continue;\n }\n if (tagName === 'iframe' && name === 'src') {\n continue;\n }\n try {\n if (n.isSVG && name === 'xlink:href') {\n node.setAttributeNS('http://www.w3.org/1999/xlink', name, value);\n } else if (\n name === 'onload' ||\n name === 'onclick' ||\n name.substring(0, 7) === 'onmouse'\n ) {\n // Rename some of the more common atttributes from https://www.w3schools.com/tags/ref_eventattributes.asp\n // as setting them triggers a console.error (which shows up despite the try/catch)\n // Assumption: these attributes are not used to css\n node.setAttribute('_' + name, value);\n } else {\n node.setAttribute(name, value);\n }\n } catch (error) {\n // skip invalid attribute\n }\n } else {\n // handle internal attributes\n if (tagName === 'canvas' && name === 'rr_dataURL') {\n const image = document.createElement('img');\n image.src = value;\n image.onload = () => {\n const ctx = (node as HTMLCanvasElement).getContext('2d');\n if (ctx) {\n ctx.drawImage(image, 0, 0, image.width, image.height);\n }\n };\n }\n if (name === 'rr_width') {\n (node as HTMLElement).style.width = value;\n }\n if (name === 'rr_height') {\n (node as HTMLElement).style.height = value;\n }\n if (name === 'rr_mediaState') {\n switch (value) {\n case 'played':\n (node as HTMLMediaElement).play();\n case 'paused':\n (node as HTMLMediaElement).pause();\n break;\n default:\n }\n }\n }\n }\n return node;\n case NodeType.Text:\n return doc.createTextNode(\n n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent,\n );\n case NodeType.CDATA:\n return doc.createCDATASection(n.textContent);\n case NodeType.Comment:\n return doc.createComment(n.textContent);\n default:\n return null;\n }\n}\n\nexport function buildNodeWithSN(\n n: serializedNodeWithId,\n doc: Document,\n map: idNodeMap,\n cbs: CallbackArray,\n skipChild = false,\n HACK_CSS = true,\n): [INode | null, serializedNodeWithId[]] {\n let node = buildNode(n, doc, HACK_CSS);\n if (!node) {\n return [null, []];\n }\n if (n.rootId) {\n console.assert(\n ((map[n.rootId] as unknown) as Document) === doc,\n 'Target document should has the same root id.',\n );\n }\n // use target document as root document\n if (n.type === NodeType.Document) {\n // close before open to make sure document was closed\n doc.close();\n doc.open();\n node = doc;\n }\n\n (node as INode).__sn = n;\n map[n.id] = node as INode;\n\n const nodeIsIframe = isIframe(n);\n if (n.type === NodeType.Element && nodeIsIframe) {\n return [node as INode, n.childNodes];\n }\n\n if (\n (n.type === NodeType.Document || n.type === NodeType.Element) &&\n !skipChild\n ) {\n for (const childN of n.childNodes) {\n const [childNode, nestedNodes] = buildNodeWithSN(\n childN,\n doc,\n map,\n cbs,\n false,\n HACK_CSS,\n );\n if (!childNode) {\n console.warn('Failed to rebuild', childN);\n continue;\n }\n\n node.appendChild(childNode);\n if (nestedNodes.length === 0) {\n continue;\n }\n const childNodeIsIframe = isIframe(childN);\n if (childNodeIsIframe) {\n cbs.push(() =>\n buildIframe(\n (childNode as unknown) as HTMLIFrameElement,\n nestedNodes,\n map,\n cbs,\n HACK_CSS,\n ),\n );\n }\n }\n }\n return [node as INode, []];\n}\n\nfunction visit(idNodeMap: idNodeMap, onVisit: (node: INode) => void) {\n function walk(node: INode) {\n onVisit(node);\n }\n\n for (const key in idNodeMap) {\n if (idNodeMap[key]) {\n walk(idNodeMap[key]);\n }\n }\n}\n\nfunction handleScroll(node: INode) {\n const n = node.__sn;\n if (n.type !== NodeType.Element) {\n return;\n }\n const el = (node as Node) as HTMLElement;\n for (const name in n.attributes) {\n if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) {\n continue;\n }\n const value = n.attributes[name];\n if (name === 'rr_scrollLeft') {\n el.scrollLeft = value as number;\n }\n if (name === 'rr_scrollTop') {\n el.scrollTop = value as number;\n }\n }\n}\n\nfunction rebuild(\n n: serializedNodeWithId,\n doc: Document,\n onVisit?: (node: INode) => unknown,\n /**\n * This is not a public API yet, just for POC\n */\n HACK_CSS: boolean = true,\n): [Node | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const callbackArray: CallbackArray = [];\n const [node] = buildNodeWithSN(\n n,\n doc,\n idNodeMap,\n callbackArray,\n false,\n HACK_CSS,\n );\n callbackArray.forEach((f) => f());\n visit(idNodeMap, (visitedNode) => {\n if (onVisit) {\n onVisit(visitedNode);\n }\n handleScroll(visitedNode);\n });\n return [node, idNodeMap];\n}\n\nexport default rebuild;\n"],"names":["NodeType","_id","tagNameRegex","RegExp","IGNORED_NODE","getCssRulesString","s","rules","cssRules","Array","from","map","getCssRuleString","join","error","rule","isCSSImportRule","styleSheet","cssText","URL_IN_CSS_REF","RELATIVE_PATH","DATA_URI","absoluteToStylesheet","href","replace","origin","quote1","path1","quote2","path2","path3","url","filePath","maybe_quote","test","indexOf","split","slice","stack","parts","pop","parts_1","_i","part","push","absoluteToDoc","doc","attributeValue","trim","a","createElement","transformAttribute","name","value","srcItem","urlAndSize","trimLeft","trimRight","length","getAbsoluteSrcsetString","location","serializeNode","n","blockClass","blockSelector","inlineStylesheet","maskInputOptions","recordCanvas","rootId","el","__sn","docId","id","undefined","nodeType","DOCUMENT_NODE","type","Document","childNodes","DOCUMENT_TYPE_NODE","DocumentType","publicId","systemId","ELEMENT_NODE","needBlock","element","classList","contains","forEach","className","matches","_isBlockedElement","tagName","processedTagName","toLowerCase","getValidTagName","attributes_1","_a","attributes","_b","stylesheet","styleSheets","find","rel","_cssText","sheet","innerText","textContent","repeat","checked","selectValue","parentElement","selected","rr_dataURL","toDataURL","rr_mediaState","paused","scrollLeft","rr_scrollLeft","scrollTop","rr_scrollTop","_c","width","height","rr_width","rr_height","Element","isSVG","SVGElement","TEXT_NODE","parentTagName","parentNode","isStyle","Text","CDATA_SECTION_NODE","CDATA","COMMENT_NODE","Comment","lowerIfExists","maybeAttr","serializeNodeWithId","skipChild","slimDOMOptions","preserveWhiteSpace","onSerialize","_serializedNode","console","warn","sn","comment","script","headFavicon","match","headMetaDescKeywords","headMetaSocial","headMetaRobots","headMetaHttpEquiv","headMetaAuthorship","headMetaVerification","slimDOMExcluded","serializedNode","Object","assign","recordChild","headWhitespace","serializedChildNode","iframeDoc","contentDocument","serializedIframeNode","commentre","parse","css","options","lineno","column","updatePosition","str","lines","i","lastIndexOf","position","start","line","node","Position","whitespace","this","end","source","prototype","content","errorsList","msg","err","Error","reason","filename","silent","open","close","comments","charAt","atrule","re","m","exec","c","pos","selector","declaration","propMatch","prop","val","ret","property","declarations","decl","decls","keyframe","vals","values","rulesList","atimport","_compileAtrule","atcharset","atnamespace","vendor","frame","frames","concat","keyframes","atkeyframes","media","style","atmedia","atcustommedia","supports","atsupports","document","atdocument","sel","selectors","atpage","athost","atfontface","addParent","obj","parent","isNode","childParent","keys","k","isArray","v","defineProperty","configurable","writable","enumerable","parsingErrors","tagMap","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","clippath","feblend","fecolormatrix","fecomponenttransfer","fecomposite","feconvolvematrix","fediffuselighting","fedisplacementmap","fedistantlight","fedropshadow","feflood","fefunca","fefuncb","fefuncg","fefuncr","fegaussianblur","feimage","femerge","femergenode","femorphology","feoffset","fepointlight","fespecularlighting","fespotlight","fetile","feturbulence","foreignobject","glyphref","lineargradient","radialgradient","HOVER_SELECTOR","addHoverClass","ast","newSelector","isIframe","buildNode","HACK_CSS","implementation","createDocument","createDocumentType","node_1","getTagName","createElementNS","hasOwnProperty","startsWith","image_1","src","onload","ctx","getContext","drawImage","play","pause","isTextarea","isRemoteOrDynamicCss","child","createTextNode","removeChild","appendChild","setAttributeNS","substring","setAttribute","createCDATASection","createComment","buildNodeWithSN","cbs","assert","nodeIsIframe","childN","childNode","nestedNodes","iframe","targetDoc","childNodes_1","log","buildIframe","maskAllInputsOrOptions","slimDOMSensibleOrOptions","idNodeMap","color","date","datetime-local","email","month","number","range","search","tel","text","time","week","textarea","select","onVisit","callbackArray","f","key","visit","visitedNode","handleScroll","walk","current"],"mappings":"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"} \ No newline at end of file diff --git a/es/rrweb-snapshot.js b/es/rrweb-snapshot.js deleted file mode 100644 index 6e564e4..0000000 --- a/es/rrweb-snapshot.js +++ /dev/null @@ -1,1200 +0,0 @@ -var NodeType; -(function (NodeType) { - NodeType[NodeType["Document"] = 0] = "Document"; - NodeType[NodeType["DocumentType"] = 1] = "DocumentType"; - NodeType[NodeType["Element"] = 2] = "Element"; - NodeType[NodeType["Text"] = 3] = "Text"; - NodeType[NodeType["CDATA"] = 4] = "CDATA"; - NodeType[NodeType["Comment"] = 5] = "Comment"; -})(NodeType || (NodeType = {})); - -var _id = 1; -var tagNameRegex = RegExp('[^a-z1-6-_]'); -var IGNORED_NODE = -2; -function genId() { - return _id++; -} -function getValidTagName(tagName) { - var processedTagName = tagName.toLowerCase().trim(); - if (tagNameRegex.test(processedTagName)) { - return 'div'; - } - return processedTagName; -} -function getCssRulesString(s) { - try { - var rules = s.rules || s.cssRules; - return rules ? Array.from(rules).map(getCssRuleString).join('') : null; - } - catch (error) { - return null; - } -} -function getCssRuleString(rule) { - return isCSSImportRule(rule) - ? getCssRulesString(rule.styleSheet) || '' - : rule.cssText; -} -function isCSSImportRule(rule) { - return 'styleSheet' in rule; -} -function extractOrigin(url) { - var origin; - if (url.indexOf('//') > -1) { - origin = url.split('/').slice(0, 3).join('/'); - } - else { - origin = url.split('/')[0]; - } - origin = origin.split('?')[0]; - return origin; -} -var URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm; -var RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/; -var DATA_URI = /^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i; -function absoluteToStylesheet(cssText, href) { - return (cssText || '').replace(URL_IN_CSS_REF, function (origin, quote1, path1, quote2, path2, path3) { - var filePath = path1 || path2 || path3; - var maybe_quote = quote1 || quote2 || ''; - if (!filePath) { - return origin; - } - if (!RELATIVE_PATH.test(filePath)) { - return "url(" + maybe_quote + filePath + maybe_quote + ")"; - } - if (DATA_URI.test(filePath)) { - return "url(" + maybe_quote + filePath + maybe_quote + ")"; - } - if (filePath[0] === '/') { - return "url(" + maybe_quote + (extractOrigin(href) + filePath) + maybe_quote + ")"; - } - var stack = href.split('/'); - var parts = filePath.split('/'); - stack.pop(); - for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { - var part = parts_1[_i]; - if (part === '.') { - continue; - } - else if (part === '..') { - stack.pop(); - } - else { - stack.push(part); - } - } - return "url(" + maybe_quote + stack.join('/') + maybe_quote + ")"; - }); -} -function getAbsoluteSrcsetString(doc, attributeValue) { - if (attributeValue.trim() === '') { - return attributeValue; - } - var srcsetValues = attributeValue.split(','); - var resultingSrcsetString = srcsetValues - .map(function (srcItem) { - var trimmedSrcItem = srcItem.trimLeft().trimRight(); - var urlAndSize = trimmedSrcItem.split(' '); - if (urlAndSize.length === 2) { - var absUrl = absoluteToDoc(doc, urlAndSize[0]); - return absUrl + " " + urlAndSize[1]; - } - else if (urlAndSize.length === 1) { - var absUrl = absoluteToDoc(doc, urlAndSize[0]); - return "" + absUrl; - } - return ''; - }) - .join(', '); - return resultingSrcsetString; -} -function absoluteToDoc(doc, attributeValue) { - if (!attributeValue || attributeValue.trim() === '') { - return attributeValue; - } - var a = doc.createElement('a'); - a.href = attributeValue; - return a.href; -} -function isSVGElement(el) { - return el.tagName === 'svg' || el instanceof SVGElement; -} -function transformAttribute(doc, name, value) { - if (name === 'src' || (name === 'href' && value)) { - return absoluteToDoc(doc, value); - } - else if (name === 'srcset' && value) { - return getAbsoluteSrcsetString(doc, value); - } - else if (name === 'style' && value) { - return absoluteToStylesheet(value, location.href); - } - else { - return value; - } -} -function _isBlockedElement(element, blockClass, blockSelector) { - if (typeof blockClass === 'string') { - if (element.classList.contains(blockClass)) { - return true; - } - } - else { - element.classList.forEach(function (className) { - if (blockClass.test(className)) { - return true; - } - }); - } - if (blockSelector) { - return element.matches(blockSelector); - } - return false; -} -function serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas) { - if (maskInputOptions === void 0) { maskInputOptions = {}; } - var rootId; - if (doc.__sn) { - var docId = doc.__sn.id; - rootId = docId === 1 ? undefined : docId; - } - switch (n.nodeType) { - case n.DOCUMENT_NODE: - return { - type: NodeType.Document, - childNodes: [], - rootId: rootId - }; - case n.DOCUMENT_TYPE_NODE: - return { - type: NodeType.DocumentType, - name: n.name, - publicId: n.publicId, - systemId: n.systemId, - rootId: rootId - }; - case n.ELEMENT_NODE: - var needBlock = _isBlockedElement(n, blockClass, blockSelector); - var tagName = getValidTagName(n.tagName); - var attributes_1 = {}; - for (var _i = 0, _a = Array.from(n.attributes); _i < _a.length; _i++) { - var _b = _a[_i], name = _b.name, value = _b.value; - attributes_1[name] = transformAttribute(doc, name, value); - } - if (tagName === 'link' && inlineStylesheet) { - var stylesheet = Array.from(doc.styleSheets).find(function (s) { - return s.href === n.href; - }); - var cssText = getCssRulesString(stylesheet); - if (cssText) { - delete attributes_1.rel; - delete attributes_1.href; - attributes_1._cssText = absoluteToStylesheet(cssText, stylesheet.href); - } - } - if (tagName === 'style' && - n.sheet && - !(n.innerText || - n.textContent || - '').trim().length) { - var cssText = getCssRulesString(n.sheet); - if (cssText) { - attributes_1._cssText = absoluteToStylesheet(cssText, location.href); - } - } - if (tagName === 'input' || - tagName === 'textarea' || - tagName === 'select') { - var value = n.value; - if (attributes_1.type !== 'radio' && - attributes_1.type !== 'checkbox' && - attributes_1.type !== 'submit' && - attributes_1.type !== 'button' && - value) { - attributes_1.value = - maskInputOptions[attributes_1.type] || - maskInputOptions[tagName] - ? '*'.repeat(value.length) - : value; - } - else if (n.checked) { - attributes_1.checked = n.checked; - } - } - if (tagName === 'option') { - var selectValue = n.parentElement; - if (attributes_1.value === selectValue.value) { - attributes_1.selected = n.selected; - } - } - if (tagName === 'canvas' && recordCanvas) { - attributes_1.rr_dataURL = n.toDataURL(); - } - if (tagName === 'audio' || tagName === 'video') { - attributes_1.rr_mediaState = n.paused - ? 'paused' - : 'played'; - } - if (n.scrollLeft) { - attributes_1.rr_scrollLeft = n.scrollLeft; - } - if (n.scrollTop) { - attributes_1.rr_scrollTop = n.scrollTop; - } - if (needBlock) { - var _c = n.getBoundingClientRect(), width = _c.width, height = _c.height; - attributes_1.rr_width = width + "px"; - attributes_1.rr_height = height + "px"; - } - return { - type: NodeType.Element, - tagName: tagName, - attributes: attributes_1, - childNodes: [], - isSVG: isSVGElement(n) || undefined, - needBlock: needBlock, - rootId: rootId - }; - case n.TEXT_NODE: - var parentTagName = n.parentNode && n.parentNode.tagName; - var textContent = n.textContent; - var isStyle = parentTagName === 'STYLE' ? true : undefined; - if (isStyle && textContent) { - textContent = absoluteToStylesheet(textContent, location.href); - } - if (parentTagName === 'SCRIPT') { - textContent = 'SCRIPT_PLACEHOLDER'; - } - return { - type: NodeType.Text, - textContent: textContent || '', - isStyle: isStyle, - rootId: rootId - }; - case n.CDATA_SECTION_NODE: - return { - type: NodeType.CDATA, - textContent: '', - rootId: rootId - }; - case n.COMMENT_NODE: - return { - type: NodeType.Comment, - textContent: n.textContent || '', - rootId: rootId - }; - default: - return false; - } -} -function lowerIfExists(maybeAttr) { - if (maybeAttr === undefined) { - return ''; - } - else { - return maybeAttr.toLowerCase(); - } -} -function slimDOMExcluded(sn, slimDOMOptions) { - if (slimDOMOptions.comment && sn.type === NodeType.Comment) { - return true; - } - else if (sn.type === NodeType.Element) { - if (slimDOMOptions.script && - (sn.tagName === 'script' || - (sn.tagName === 'link' && - sn.attributes.rel === 'preload' && - sn.attributes['as'] === 'script'))) { - return true; - } - else if (slimDOMOptions.headFavicon && - ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') || - (sn.tagName === 'meta' && - (lowerIfExists(sn.attributes['name']).match(/^msapplication-tile(image|color)$/) || - lowerIfExists(sn.attributes['name']) === 'application-name' || - lowerIfExists(sn.attributes['rel']) === 'icon' || - lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' || - lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))) { - return true; - } - else if (sn.tagName === 'meta') { - if (slimDOMOptions.headMetaDescKeywords && - lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)) { - return true; - } - else if (slimDOMOptions.headMetaSocial && - (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || - lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) || - lowerIfExists(sn.attributes['name']) === 'pinterest')) { - return true; - } - else if (slimDOMOptions.headMetaRobots && - (lowerIfExists(sn.attributes['name']) === 'robots' || - lowerIfExists(sn.attributes['name']) === 'googlebot' || - lowerIfExists(sn.attributes['name']) === 'bingbot')) { - return true; - } - else if (slimDOMOptions.headMetaHttpEquiv && - sn.attributes['http-equiv'] !== undefined) { - return true; - } - else if (slimDOMOptions.headMetaAuthorship && - (lowerIfExists(sn.attributes['name']) === 'author' || - lowerIfExists(sn.attributes['name']) === 'generator' || - lowerIfExists(sn.attributes['name']) === 'framework' || - lowerIfExists(sn.attributes['name']) === 'publisher' || - lowerIfExists(sn.attributes['name']) === 'progid' || - lowerIfExists(sn.attributes['property']).match(/^article:/) || - lowerIfExists(sn.attributes['property']).match(/^product:/))) { - return true; - } - else if (slimDOMOptions.headMetaVerification && - (lowerIfExists(sn.attributes['name']) === 'google-site-verification' || - lowerIfExists(sn.attributes['name']) === 'yandex-verification' || - lowerIfExists(sn.attributes['name']) === 'csrf-token' || - lowerIfExists(sn.attributes['name']) === 'p:domain_verify' || - lowerIfExists(sn.attributes['name']) === 'verify-v1' || - lowerIfExists(sn.attributes['name']) === 'verification' || - lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')) { - return true; - } - } - } - return false; -} -function serializeNodeWithId(n, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize) { - if (skipChild === void 0) { skipChild = false; } - if (inlineStylesheet === void 0) { inlineStylesheet = true; } - if (slimDOMOptions === void 0) { slimDOMOptions = {}; } - if (preserveWhiteSpace === void 0) { preserveWhiteSpace = true; } - var _serializedNode = serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas || false); - if (!_serializedNode) { - console.warn(n, 'not serialized'); - return null; - } - var id; - if ('__sn' in n) { - id = n.__sn.id; - } - else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || - (!preserveWhiteSpace && - _serializedNode.type === NodeType.Text && - !_serializedNode.isStyle && - !_serializedNode.textContent.replace(/^\s+|\s+$/gm, '').length)) { - id = IGNORED_NODE; - } - else { - id = genId(); - } - var serializedNode = Object.assign(_serializedNode, { id: id }); - n.__sn = serializedNode; - if (id === IGNORED_NODE) { - return null; - } - map[id] = n; - if (onSerialize) { - onSerialize(n); - } - var recordChild = !skipChild; - if (serializedNode.type === NodeType.Element) { - recordChild = recordChild && !serializedNode.needBlock; - delete serializedNode.needBlock; - } - if ((serializedNode.type === NodeType.Document || - serializedNode.type === NodeType.Element) && - recordChild) { - if (slimDOMOptions.headWhitespace && - _serializedNode.type === NodeType.Element && - _serializedNode.tagName == 'head') { - preserveWhiteSpace = false; - } - for (var _i = 0, _a = Array.from(n.childNodes); _i < _a.length; _i++) { - var childN = _a[_i]; - var serializedChildNode = serializeNodeWithId(childN, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace); - if (serializedChildNode) { - serializedNode.childNodes.push(serializedChildNode); - } - } - } - if (serializedNode.type === NodeType.Element && - serializedNode.tagName === 'iframe') { - var iframeDoc = n.contentDocument; - if (iframeDoc) { - var serializedIframeNode = serializeNodeWithId(iframeDoc, iframeDoc, map, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas); - if (serializedIframeNode) { - serializedNode.childNodes.push(serializedIframeNode); - } - } - } - return serializedNode; -} -function snapshot(n, blockClass, inlineStylesheet, maskAllInputsOrOptions, slimDOMSensibleOrOptions, recordCanvas, blockSelector, preserveWhiteSpace, onSerialize) { - if (blockClass === void 0) { blockClass = 'rr-block'; } - if (inlineStylesheet === void 0) { inlineStylesheet = true; } - if (blockSelector === void 0) { blockSelector = null; } - var idNodeMap = {}; - var maskInputOptions = maskAllInputsOrOptions === true - ? { - color: true, - date: true, - 'datetime-local': true, - email: true, - month: true, - number: true, - range: true, - search: true, - tel: true, - text: true, - time: true, - url: true, - week: true, - textarea: true, - select: true - } - : maskAllInputsOrOptions === false - ? {} - : maskAllInputsOrOptions; - var slimDOMOptions = slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all' - ? - { - script: true, - comment: true, - headFavicon: true, - headWhitespace: true, - headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', - headMetaSocial: true, - headMetaRobots: true, - headMetaHttpEquiv: true, - headMetaAuthorship: true, - headMetaVerification: true - } - : slimDOMSensibleOrOptions === false - ? {} - : slimDOMSensibleOrOptions; - return [ - serializeNodeWithId(n, n, idNodeMap, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize), - idNodeMap, - ]; -} -function visitSnapshot(node, onVisit) { - function walk(current) { - onVisit(current); - if (current.type === NodeType.Document || - current.type === NodeType.Element) { - current.childNodes.forEach(walk); - } - } - walk(node); -} -function cleanupSnapshot() { - _id = 1; -} - -var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; -function parse(css, options) { - if (options === void 0) { options = {}; } - var lineno = 1; - var column = 1; - function updatePosition(str) { - var lines = str.match(/\n/g); - if (lines) { - lineno += lines.length; - } - var i = str.lastIndexOf('\n'); - column = i === -1 ? column + str.length : str.length - i; - } - function position() { - var start = { line: lineno, column: column }; - return function (node) { - node.position = new Position(start); - whitespace(); - return node; - }; - } - var Position = (function () { - function Position(start) { - this.start = start; - this.end = { line: lineno, column: column }; - this.source = options.source; - } - return Position; - }()); - Position.prototype.content = css; - var errorsList = []; - function error(msg) { - var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); - err.reason = msg; - err.filename = options.source; - err.line = lineno; - err.column = column; - err.source = css; - if (options.silent) { - errorsList.push(err); - } - else { - throw err; - } - } - function stylesheet() { - var rulesList = rules(); - return { - type: 'stylesheet', - stylesheet: { - source: options.source, - rules: rulesList, - parsingErrors: errorsList - } - }; - } - function open() { - return match(/^{\s*/); - } - function close() { - return match(/^}/); - } - function rules() { - var node; - var rules = []; - whitespace(); - comments(rules); - while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { - if (node !== false) { - rules.push(node); - comments(rules); - } - } - return rules; - } - function match(re) { - var m = re.exec(css); - if (!m) { - return; - } - var str = m[0]; - updatePosition(str); - css = css.slice(str.length); - return m; - } - function whitespace() { - match(/^\s*/); - } - function comments(rules) { - if (rules === void 0) { rules = []; } - var c; - while ((c = comment())) { - if (c !== false) { - rules.push(c); - } - c = comment(); - } - return rules; - } - function comment() { - var pos = position(); - if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { - return; - } - var i = 2; - while ('' !== css.charAt(i) && - ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))) { - ++i; - } - i += 2; - if ('' === css.charAt(i - 1)) { - return error('End of comment missing'); - } - var str = css.slice(2, i - 2); - column += 2; - updatePosition(str); - css = css.slice(i); - column += 2; - return pos({ - type: 'comment', - comment: str - }); - } - function selector() { - var m = match(/^([^{]+)/); - if (!m) { - return; - } - return trim(m[0]) - .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') - .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) { - return m.replace(/,/g, '\u200C'); - }) - .split(/\s*(?![^(]*\)),\s*/) - .map(function (s) { - return s.replace(/\u200C/g, ','); - }); - } - function declaration() { - var pos = position(); - var propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); - if (!propMatch) { - return; - } - var prop = trim(propMatch[0]); - if (!match(/^:\s*/)) { - return error("property missing ':'"); - } - var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); - var ret = pos({ - type: 'declaration', - property: prop.replace(commentre, ''), - value: val ? trim(val[0]).replace(commentre, '') : '' - }); - match(/^[;\s]*/); - return ret; - } - function declarations() { - var decls = []; - if (!open()) { - return error("missing '{'"); - } - comments(decls); - var decl; - while ((decl = declaration())) { - if (decl !== false) { - decls.push(decl); - comments(decls); - } - decl = declaration(); - } - if (!close()) { - return error("missing '}'"); - } - return decls; - } - function keyframe() { - var m; - var vals = []; - var pos = position(); - while ((m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/))) { - vals.push(m[1]); - match(/^,\s*/); - } - if (!vals.length) { - return; - } - return pos({ - type: 'keyframe', - values: vals, - declarations: declarations() - }); - } - function atkeyframes() { - var pos = position(); - var m = match(/^@([-\w]+)?keyframes\s*/); - if (!m) { - return; - } - var vendor = m[1]; - m = match(/^([-\w]+)\s*/); - if (!m) { - return error('@keyframes missing name'); - } - var name = m[1]; - if (!open()) { - return error("@keyframes missing '{'"); - } - var frame; - var frames = comments(); - while ((frame = keyframe())) { - frames.push(frame); - frames = frames.concat(comments()); - } - if (!close()) { - return error("@keyframes missing '}'"); - } - return pos({ - type: 'keyframes', - name: name, - vendor: vendor, - keyframes: frames - }); - } - function atsupports() { - var pos = position(); - var m = match(/^@supports *([^{]+)/); - if (!m) { - return; - } - var supports = trim(m[1]); - if (!open()) { - return error("@supports missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@supports missing '}'"); - } - return pos({ - type: 'supports', - supports: supports, - rules: style - }); - } - function athost() { - var pos = position(); - var m = match(/^@host\s*/); - if (!m) { - return; - } - if (!open()) { - return error("@host missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@host missing '}'"); - } - return pos({ - type: 'host', - rules: style - }); - } - function atmedia() { - var pos = position(); - var m = match(/^@media *([^{]+)/); - if (!m) { - return; - } - var media = trim(m[1]); - if (!open()) { - return error("@media missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@media missing '}'"); - } - return pos({ - type: 'media', - media: media, - rules: style - }); - } - function atcustommedia() { - var pos = position(); - var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); - if (!m) { - return; - } - return pos({ - type: 'custom-media', - name: trim(m[1]), - media: trim(m[2]) - }); - } - function atpage() { - var pos = position(); - var m = match(/^@page */); - if (!m) { - return; - } - var sel = selector() || []; - if (!open()) { - return error("@page missing '{'"); - } - var decls = comments(); - var decl; - while ((decl = declaration())) { - decls.push(decl); - decls = decls.concat(comments()); - } - if (!close()) { - return error("@page missing '}'"); - } - return pos({ - type: 'page', - selectors: sel, - declarations: decls - }); - } - function atdocument() { - var pos = position(); - var m = match(/^@([-\w]+)?document *([^{]+)/); - if (!m) { - return; - } - var vendor = trim(m[1]); - var doc = trim(m[2]); - if (!open()) { - return error("@document missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@document missing '}'"); - } - return pos({ - type: 'document', - document: doc, - vendor: vendor, - rules: style - }); - } - function atfontface() { - var pos = position(); - var m = match(/^@font-face\s*/); - if (!m) { - return; - } - if (!open()) { - return error("@font-face missing '{'"); - } - var decls = comments(); - var decl; - while ((decl = declaration())) { - decls.push(decl); - decls = decls.concat(comments()); - } - if (!close()) { - return error("@font-face missing '}'"); - } - return pos({ - type: 'font-face', - declarations: decls - }); - } - var atimport = _compileAtrule('import'); - var atcharset = _compileAtrule('charset'); - var atnamespace = _compileAtrule('namespace'); - function _compileAtrule(name) { - var re = new RegExp('^@' + name + '\\s*([^;]+);'); - return function () { - var pos = position(); - var m = match(re); - if (!m) { - return; - } - var ret = { type: name }; - ret[name] = m[1].trim(); - return pos(ret); - }; - } - function atrule() { - if (css[0] !== '@') { - return; - } - return (atkeyframes() || - atmedia() || - atcustommedia() || - atsupports() || - atimport() || - atcharset() || - atnamespace() || - atdocument() || - atpage() || - athost() || - atfontface()); - } - function rule() { - var pos = position(); - var sel = selector(); - if (!sel) { - return error('selector missing'); - } - comments(); - return pos({ - type: 'rule', - selectors: sel, - declarations: declarations() - }); - } - return addParent(stylesheet()); -} -function trim(str) { - return str ? str.replace(/^\s+|\s+$/g, '') : ''; -} -function addParent(obj, parent) { - var isNode = obj && typeof obj.type === 'string'; - var childParent = isNode ? obj : parent; - for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { - var k = _a[_i]; - var value = obj[k]; - if (Array.isArray(value)) { - value.forEach(function (v) { - addParent(v, childParent); - }); - } - else if (value && typeof value === 'object') { - addParent(value, childParent); - } - } - if (isNode) { - Object.defineProperty(obj, 'parent', { - configurable: true, - writable: true, - enumerable: false, - value: parent || null - }); - } - return obj; -} - -var tagMap = { - script: 'noscript', - altglyph: 'altGlyph', - altglyphdef: 'altGlyphDef', - altglyphitem: 'altGlyphItem', - animatecolor: 'animateColor', - animatemotion: 'animateMotion', - animatetransform: 'animateTransform', - clippath: 'clipPath', - feblend: 'feBlend', - fecolormatrix: 'feColorMatrix', - fecomponenttransfer: 'feComponentTransfer', - fecomposite: 'feComposite', - feconvolvematrix: 'feConvolveMatrix', - fediffuselighting: 'feDiffuseLighting', - fedisplacementmap: 'feDisplacementMap', - fedistantlight: 'feDistantLight', - fedropshadow: 'feDropShadow', - feflood: 'feFlood', - fefunca: 'feFuncA', - fefuncb: 'feFuncB', - fefuncg: 'feFuncG', - fefuncr: 'feFuncR', - fegaussianblur: 'feGaussianBlur', - feimage: 'feImage', - femerge: 'feMerge', - femergenode: 'feMergeNode', - femorphology: 'feMorphology', - feoffset: 'feOffset', - fepointlight: 'fePointLight', - fespecularlighting: 'feSpecularLighting', - fespotlight: 'feSpotLight', - fetile: 'feTile', - feturbulence: 'feTurbulence', - foreignobject: 'foreignObject', - glyphref: 'glyphRef', - lineargradient: 'linearGradient', - radialgradient: 'radialGradient' -}; -function getTagName(n) { - var tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; - if (tagName === 'link' && n.attributes._cssText) { - tagName = 'style'; - } - return tagName; -} -var HOVER_SELECTOR = /([^\\]):hover/g; -function addHoverClass(cssText) { - var ast = parse(cssText, { silent: true }); - if (!ast.stylesheet) { - return cssText; - } - ast.stylesheet.rules.forEach(function (rule) { - if ('selectors' in rule) { - (rule.selectors || []).forEach(function (selector) { - if (HOVER_SELECTOR.test(selector)) { - var newSelector = selector.replace(HOVER_SELECTOR, '$1.\\:hover'); - cssText = cssText.replace(selector, selector + ", " + newSelector); - } - }); - } - }); - return cssText; -} -function isIframe(n) { - return n.type === NodeType.Element && n.tagName === 'iframe'; -} -function buildIframe(iframe, childNodes, map, cbs, HACK_CSS) { - var targetDoc = iframe.contentDocument; - for (var _i = 0, childNodes_1 = childNodes; _i < childNodes_1.length; _i++) { - var childN = childNodes_1[_i]; - console.log('build iframe', childN); - buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS); - } -} -function buildNode(n, doc, HACK_CSS) { - switch (n.type) { - case NodeType.Document: - return doc.implementation.createDocument(null, '', null); - case NodeType.DocumentType: - return doc.implementation.createDocumentType(n.name || 'html', n.publicId, n.systemId); - case NodeType.Element: - var tagName = getTagName(n); - var node_1; - if (n.isSVG) { - node_1 = doc.createElementNS('http://www.w3.org/2000/svg', tagName); - } - else { - node_1 = doc.createElement(tagName); - } - var _loop_1 = function (name) { - if (!n.attributes.hasOwnProperty(name)) { - return "continue"; - } - var value = n.attributes[name]; - value = - typeof value === 'boolean' || typeof value === 'number' ? '' : value; - if (!name.startsWith('rr_')) { - var isTextarea = tagName === 'textarea' && name === 'value'; - var isRemoteOrDynamicCss = tagName === 'style' && name === '_cssText'; - if (isRemoteOrDynamicCss && HACK_CSS) { - value = addHoverClass(value); - } - if (isTextarea || isRemoteOrDynamicCss) { - var child = doc.createTextNode(value); - for (var _i = 0, _a = Array.from(node_1.childNodes); _i < _a.length; _i++) { - var c = _a[_i]; - if (c.nodeType === node_1.TEXT_NODE) { - node_1.removeChild(c); - } - } - node_1.appendChild(child); - return "continue"; - } - if (tagName === 'iframe' && name === 'src') { - return "continue"; - } - try { - if (n.isSVG && name === 'xlink:href') { - node_1.setAttributeNS('http://www.w3.org/1999/xlink', name, value); - } - else if (name === 'onload' || - name === 'onclick' || - name.substring(0, 7) === 'onmouse') { - node_1.setAttribute('_' + name, value); - } - else { - node_1.setAttribute(name, value); - } - } - catch (error) { - } - } - else { - if (tagName === 'canvas' && name === 'rr_dataURL') { - var image_1 = document.createElement('img'); - image_1.src = value; - image_1.onload = function () { - var ctx = node_1.getContext('2d'); - if (ctx) { - ctx.drawImage(image_1, 0, 0, image_1.width, image_1.height); - } - }; - } - if (name === 'rr_width') { - node_1.style.width = value; - } - if (name === 'rr_height') { - node_1.style.height = value; - } - if (name === 'rr_mediaState') { - switch (value) { - case 'played': - node_1.play(); - case 'paused': - node_1.pause(); - break; - default: - } - } - } - }; - for (var name in n.attributes) { - _loop_1(name); - } - return node_1; - case NodeType.Text: - return doc.createTextNode(n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent); - case NodeType.CDATA: - return doc.createCDATASection(n.textContent); - case NodeType.Comment: - return doc.createComment(n.textContent); - default: - return null; - } -} -function buildNodeWithSN(n, doc, map, cbs, skipChild, HACK_CSS) { - if (skipChild === void 0) { skipChild = false; } - if (HACK_CSS === void 0) { HACK_CSS = true; } - var node = buildNode(n, doc, HACK_CSS); - if (!node) { - return [null, []]; - } - if (n.rootId) { - console.assert(map[n.rootId] === doc, 'Target document should has the same root id.'); - } - if (n.type === NodeType.Document) { - doc.close(); - doc.open(); - node = doc; - } - node.__sn = n; - map[n.id] = node; - var nodeIsIframe = isIframe(n); - if (n.type === NodeType.Element && nodeIsIframe) { - return [node, n.childNodes]; - } - if ((n.type === NodeType.Document || n.type === NodeType.Element) && - !skipChild) { - var _loop_2 = function (childN) { - var _a = buildNodeWithSN(childN, doc, map, cbs, false, HACK_CSS), childNode = _a[0], nestedNodes = _a[1]; - if (!childNode) { - console.warn('Failed to rebuild', childN); - return "continue"; - } - node.appendChild(childNode); - if (nestedNodes.length === 0) { - return "continue"; - } - var childNodeIsIframe = isIframe(childN); - if (childNodeIsIframe) { - cbs.push(function () { - return buildIframe(childNode, nestedNodes, map, cbs, HACK_CSS); - }); - } - }; - for (var _i = 0, _a = n.childNodes; _i < _a.length; _i++) { - var childN = _a[_i]; - _loop_2(childN); - } - } - return [node, []]; -} -function visit(idNodeMap, onVisit) { - function walk(node) { - onVisit(node); - } - for (var key in idNodeMap) { - if (idNodeMap[key]) { - walk(idNodeMap[key]); - } - } -} -function handleScroll(node) { - var n = node.__sn; - if (n.type !== NodeType.Element) { - return; - } - var el = node; - for (var name in n.attributes) { - if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) { - continue; - } - var value = n.attributes[name]; - if (name === 'rr_scrollLeft') { - el.scrollLeft = value; - } - if (name === 'rr_scrollTop') { - el.scrollTop = value; - } - } -} -function rebuild(n, doc, onVisit, HACK_CSS) { - if (HACK_CSS === void 0) { HACK_CSS = true; } - var idNodeMap = {}; - var callbackArray = []; - var node = buildNodeWithSN(n, doc, idNodeMap, callbackArray, false, HACK_CSS)[0]; - callbackArray.forEach(function (f) { return f(); }); - visit(idNodeMap, function (visitedNode) { - if (onVisit) { - onVisit(visitedNode); - } - handleScroll(visitedNode); - }); - return [node, idNodeMap]; -} - -export { snapshot, serializeNodeWithId, rebuild, buildNodeWithSN, addHoverClass, transformAttribute, visitSnapshot, cleanupSnapshot, IGNORED_NODE, NodeType }; diff --git a/es/rrweb-snapshot.min.js b/es/rrweb-snapshot.min.js deleted file mode 100644 index 4c11836..0000000 --- a/es/rrweb-snapshot.min.js +++ /dev/null @@ -1,2 +0,0 @@ -var NodeType;!function(e){e[e.Document=0]="Document",e[e.DocumentType=1]="DocumentType",e[e.Element=2]="Element",e[e.Text=3]="Text",e[e.CDATA=4]="CDATA",e[e.Comment=5]="Comment"}(NodeType||(NodeType={}));var _id=1,tagNameRegex=RegExp("[^a-z1-6-_]"),IGNORED_NODE=-2;function genId(){return _id++}function getValidTagName(e){var t=e.toLowerCase().trim();return tagNameRegex.test(t)?"div":t}function getCssRulesString(e){try{var t=e.rules||e.cssRules;return t?Array.from(t).map(getCssRuleString).join(""):null}catch(e){return null}}function getCssRuleString(e){return isCSSImportRule(e)?getCssRulesString(e.styleSheet)||"":e.cssText}function isCSSImportRule(e){return"styleSheet"in e}function extractOrigin(e){return(e.indexOf("//")>-1?e.split("/").slice(0,3).join("/"):e.split("/")[0]).split("?")[0]}var URL_IN_CSS_REF=/url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm,RELATIVE_PATH=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/,DATA_URI=/^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i;function absoluteToStylesheet(e,t){return(e||"").replace(URL_IN_CSS_REF,function(e,r,n,i,a,o){var s=n||a||o,u=r||i||"";if(!s)return e;if(!RELATIVE_PATH.test(s))return"url("+u+s+u+")";if(DATA_URI.test(s))return"url("+u+s+u+")";if("/"===s[0])return"url("+u+(extractOrigin(t)+s)+u+")";var l=t.split("/"),c=s.split("/");l.pop();for(var f=0,d=c;f;\n\nexport type SlimDOMOptions = Partial<{\n script: boolean;\n comment: boolean;\n headFavicon: boolean;\n headWhitespace: boolean;\n headMetaDescKeywords: boolean;\n headMetaSocial: boolean;\n headMetaRobots: boolean;\n headMetaHttpEquiv: boolean;\n headMetaAuthorship: boolean;\n headMetaVerification: boolean;\n}>;\n\nexport type CallbackArray = T[];\n","import {\n serializedNode,\n serializedNodeWithId,\n NodeType,\n attributes,\n INode,\n idNodeMap,\n MaskInputOptions,\n SlimDOMOptions,\n} from './types';\n\nlet _id = 1;\nconst tagNameRegex = RegExp('[^a-z1-6-_]');\n\nexport const IGNORED_NODE = -2;\n\nfunction genId(): number {\n return _id++;\n}\n\nfunction getValidTagName(tagName: string): string {\n const processedTagName = tagName.toLowerCase().trim();\n\n if (tagNameRegex.test(processedTagName)) {\n // if the tag name is odd and we cannot extract\n // anything from the string, then we return a\n // generic div\n return 'div';\n }\n\n return processedTagName;\n}\n\nfunction getCssRulesString(s: CSSStyleSheet): string | null {\n try {\n const rules = s.rules || s.cssRules;\n return rules ? Array.from(rules).map(getCssRuleString).join('') : null;\n } catch (error) {\n return null;\n }\n}\n\nfunction getCssRuleString(rule: CSSRule): string {\n return isCSSImportRule(rule)\n ? getCssRulesString(rule.styleSheet) || ''\n : rule.cssText;\n}\n\nfunction isCSSImportRule(rule: CSSRule): rule is CSSImportRule {\n return 'styleSheet' in rule;\n}\n\nfunction extractOrigin(url: string): string {\n let origin;\n if (url.indexOf('//') > -1) {\n origin = url.split('/').slice(0, 3).join('/');\n } else {\n origin = url.split('/')[0];\n }\n origin = origin.split('?')[0];\n return origin;\n}\n\nconst URL_IN_CSS_REF = /url\\((?:(')([^']*)'|(\")([^\"]*)\"|([^)]*))\\)/gm;\nconst RELATIVE_PATH = /^(?!www\\.|(?:http|ftp)s?:\\/\\/|[A-Za-z]:\\\\|\\/\\/).*/;\nconst DATA_URI = /^(data:)([\\w\\/\\+\\-]+);(charset=[\\w-]+|base64|utf-?8).*,(.*)/i;\nexport function absoluteToStylesheet(\n cssText: string | null,\n href: string,\n): string {\n return (cssText || '').replace(\n URL_IN_CSS_REF,\n (origin, quote1, path1, quote2, path2, path3) => {\n const filePath = path1 || path2 || path3;\n const maybe_quote = quote1 || quote2 || '';\n if (!filePath) {\n return origin;\n }\n if (!RELATIVE_PATH.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (DATA_URI.test(filePath)) {\n return `url(${maybe_quote}${filePath}${maybe_quote})`;\n }\n if (filePath[0] === '/') {\n return `url(${maybe_quote}${\n extractOrigin(href) + filePath\n }${maybe_quote})`;\n }\n const stack = href.split('/');\n const parts = filePath.split('/');\n stack.pop();\n for (const part of parts) {\n if (part === '.') {\n continue;\n } else if (part === '..') {\n stack.pop();\n } else {\n stack.push(part);\n }\n }\n return `url(${maybe_quote}${stack.join('/')}${maybe_quote})`;\n },\n );\n}\n\nfunction getAbsoluteSrcsetString(doc: Document, attributeValue: string) {\n if (attributeValue.trim() === '') {\n return attributeValue;\n }\n\n const srcsetValues = attributeValue.split(',');\n // srcset attributes is defined as such:\n // srcset = \"url size,url1 size1\"\n const resultingSrcsetString = srcsetValues\n .map((srcItem) => {\n // removing all but middle spaces\n const trimmedSrcItem = srcItem.trimLeft().trimRight();\n const urlAndSize = trimmedSrcItem.split(' ');\n // this means we have both 0:url and 1:size\n if (urlAndSize.length === 2) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl} ${urlAndSize[1]}`;\n } else if (urlAndSize.length === 1) {\n const absUrl = absoluteToDoc(doc, urlAndSize[0]);\n return `${absUrl}`;\n }\n return '';\n })\n .join(', ');\n\n return resultingSrcsetString;\n}\n\nexport function absoluteToDoc(doc: Document, attributeValue: string): string {\n if (!attributeValue || attributeValue.trim() === '') {\n return attributeValue;\n }\n const a: HTMLAnchorElement = doc.createElement('a');\n a.href = attributeValue;\n return a.href;\n}\n\nfunction isSVGElement(el: Element): boolean {\n return el.tagName === 'svg' || el instanceof SVGElement;\n}\n\nexport function transformAttribute(\n doc: Document,\n name: string,\n value: string,\n): string {\n // relative path in attribute\n if (name === 'src' || (name === 'href' && value)) {\n return absoluteToDoc(doc, value);\n } else if (name === 'srcset' && value) {\n return getAbsoluteSrcsetString(doc, value);\n } else if (name === 'style' && value) {\n return absoluteToStylesheet(value, location.href);\n } else {\n return value;\n }\n}\n\nexport function _isBlockedElement(\n element: HTMLElement,\n blockClass: string | RegExp,\n blockSelector: string | null,\n): boolean {\n if (typeof blockClass === 'string') {\n if (element.classList.contains(blockClass)) {\n return true;\n }\n } else {\n element.classList.forEach((className) => {\n if (blockClass.test(className)) {\n return true;\n }\n });\n }\n if (blockSelector) {\n return element.matches(blockSelector);\n }\n\n return false;\n}\n\nfunction serializeNode(\n n: Node,\n doc: Document,\n blockClass: string | RegExp,\n blockSelector: string | null,\n inlineStylesheet: boolean,\n maskInputOptions: MaskInputOptions = {},\n recordCanvas: boolean,\n): serializedNode | false {\n // Only record root id when document object is not the base document\n let rootId: number | undefined;\n if (((doc as unknown) as INode).__sn) {\n const docId = ((doc as unknown) as INode).__sn.id;\n rootId = docId === 1 ? undefined : docId;\n }\n switch (n.nodeType) {\n case n.DOCUMENT_NODE:\n return {\n type: NodeType.Document,\n childNodes: [],\n rootId,\n };\n case n.DOCUMENT_TYPE_NODE:\n return {\n type: NodeType.DocumentType,\n name: (n as DocumentType).name,\n publicId: (n as DocumentType).publicId,\n systemId: (n as DocumentType).systemId,\n rootId,\n };\n case n.ELEMENT_NODE:\n const needBlock = _isBlockedElement(\n n as HTMLElement,\n blockClass,\n blockSelector,\n );\n const tagName = getValidTagName((n as HTMLElement).tagName);\n let attributes: attributes = {};\n for (const { name, value } of Array.from((n as HTMLElement).attributes)) {\n attributes[name] = transformAttribute(doc, name, value);\n }\n // remote css\n if (tagName === 'link' && inlineStylesheet) {\n const stylesheet = Array.from(doc.styleSheets).find((s) => {\n return s.href === (n as HTMLLinkElement).href;\n });\n const cssText = getCssRulesString(stylesheet as CSSStyleSheet);\n if (cssText) {\n delete attributes.rel;\n delete attributes.href;\n attributes._cssText = absoluteToStylesheet(\n cssText,\n stylesheet!.href!,\n );\n }\n }\n // dynamic stylesheet\n if (\n tagName === 'style' &&\n (n as HTMLStyleElement).sheet &&\n // TODO: Currently we only try to get dynamic stylesheet when it is an empty style element\n !(\n (n as HTMLElement).innerText ||\n (n as HTMLElement).textContent ||\n ''\n ).trim().length\n ) {\n const cssText = getCssRulesString(\n (n as HTMLStyleElement).sheet as CSSStyleSheet,\n );\n if (cssText) {\n attributes._cssText = absoluteToStylesheet(cssText, location.href);\n }\n }\n // form fields\n if (\n tagName === 'input' ||\n tagName === 'textarea' ||\n tagName === 'select'\n ) {\n const value = (n as HTMLInputElement | HTMLTextAreaElement).value;\n if (\n attributes.type !== 'radio' &&\n attributes.type !== 'checkbox' &&\n attributes.type !== 'submit' &&\n attributes.type !== 'button' &&\n value\n ) {\n attributes.value =\n maskInputOptions[attributes.type as keyof MaskInputOptions] ||\n maskInputOptions[tagName as keyof MaskInputOptions]\n ? '*'.repeat(value.length)\n : value;\n } else if ((n as HTMLInputElement).checked) {\n attributes.checked = (n as HTMLInputElement).checked;\n }\n }\n if (tagName === 'option') {\n const selectValue = (n as HTMLOptionElement).parentElement;\n if (attributes.value === (selectValue as HTMLSelectElement).value) {\n attributes.selected = (n as HTMLOptionElement).selected;\n }\n }\n // canvas image data\n if (tagName === 'canvas' && recordCanvas) {\n attributes.rr_dataURL = (n as HTMLCanvasElement).toDataURL();\n }\n // media elements\n if (tagName === 'audio' || tagName === 'video') {\n attributes.rr_mediaState = (n as HTMLMediaElement).paused\n ? 'paused'\n : 'played';\n }\n // scroll\n if ((n as HTMLElement).scrollLeft) {\n attributes.rr_scrollLeft = (n as HTMLElement).scrollLeft;\n }\n if ((n as HTMLElement).scrollTop) {\n attributes.rr_scrollTop = (n as HTMLElement).scrollTop;\n }\n if (needBlock) {\n const { width, height } = (n as HTMLElement).getBoundingClientRect();\n attributes.rr_width = `${width}px`;\n attributes.rr_height = `${height}px`;\n }\n return {\n type: NodeType.Element,\n tagName,\n attributes,\n childNodes: [],\n isSVG: isSVGElement(n as Element) || undefined,\n needBlock,\n rootId,\n };\n case n.TEXT_NODE:\n // The parent node may not be a html element which has a tagName attribute.\n // So just let it be undefined which is ok in this use case.\n const parentTagName =\n n.parentNode && (n.parentNode as HTMLElement).tagName;\n let textContent = (n as Text).textContent;\n const isStyle = parentTagName === 'STYLE' ? true : undefined;\n if (isStyle && textContent) {\n textContent = absoluteToStylesheet(textContent, location.href);\n }\n if (parentTagName === 'SCRIPT') {\n textContent = 'SCRIPT_PLACEHOLDER';\n }\n return {\n type: NodeType.Text,\n textContent: textContent || '',\n isStyle,\n rootId,\n };\n case n.CDATA_SECTION_NODE:\n return {\n type: NodeType.CDATA,\n textContent: '',\n rootId,\n };\n case n.COMMENT_NODE:\n return {\n type: NodeType.Comment,\n textContent: (n as Comment).textContent || '',\n rootId,\n };\n default:\n return false;\n }\n}\n\nfunction lowerIfExists(maybeAttr: string | number | boolean): string {\n if (maybeAttr === undefined) {\n return '';\n } else {\n return (maybeAttr as string).toLowerCase();\n }\n}\n\nfunction slimDOMExcluded(\n sn: serializedNode,\n slimDOMOptions: SlimDOMOptions,\n): boolean {\n if (slimDOMOptions.comment && sn.type === NodeType.Comment) {\n // TODO: convert IE conditional comments to real nodes\n return true;\n } else if (sn.type === NodeType.Element) {\n if (\n slimDOMOptions.script &&\n (sn.tagName === 'script' ||\n (sn.tagName === 'link' &&\n sn.attributes.rel === 'preload' &&\n sn.attributes['as'] === 'script'))\n ) {\n return true;\n } else if (\n slimDOMOptions.headFavicon &&\n ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') ||\n (sn.tagName === 'meta' &&\n (lowerIfExists(sn.attributes['name']).match(\n /^msapplication-tile(image|color)$/,\n ) ||\n lowerIfExists(sn.attributes['name']) === 'application-name' ||\n lowerIfExists(sn.attributes['rel']) === 'icon' ||\n lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' ||\n lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))\n ) {\n return true;\n } else if (sn.tagName === 'meta') {\n if (\n slimDOMOptions.headMetaDescKeywords &&\n lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaSocial &&\n (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || // og = opengraph (facebook)\n lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) ||\n lowerIfExists(sn.attributes['name']) === 'pinterest')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaRobots &&\n (lowerIfExists(sn.attributes['name']) === 'robots' ||\n lowerIfExists(sn.attributes['name']) === 'googlebot' ||\n lowerIfExists(sn.attributes['name']) === 'bingbot')\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaHttpEquiv &&\n sn.attributes['http-equiv'] !== undefined\n ) {\n // e.g. X-UA-Compatible, Content-Type, Content-Language,\n // cache-control, X-Translated-By\n return true;\n } else if (\n slimDOMOptions.headMetaAuthorship &&\n (lowerIfExists(sn.attributes['name']) === 'author' ||\n lowerIfExists(sn.attributes['name']) === 'generator' ||\n lowerIfExists(sn.attributes['name']) === 'framework' ||\n lowerIfExists(sn.attributes['name']) === 'publisher' ||\n lowerIfExists(sn.attributes['name']) === 'progid' ||\n lowerIfExists(sn.attributes['property']).match(/^article:/) ||\n lowerIfExists(sn.attributes['property']).match(/^product:/))\n ) {\n return true;\n } else if (\n slimDOMOptions.headMetaVerification &&\n (lowerIfExists(sn.attributes['name']) === 'google-site-verification' ||\n lowerIfExists(sn.attributes['name']) === 'yandex-verification' ||\n lowerIfExists(sn.attributes['name']) === 'csrf-token' ||\n lowerIfExists(sn.attributes['name']) === 'p:domain_verify' ||\n lowerIfExists(sn.attributes['name']) === 'verify-v1' ||\n lowerIfExists(sn.attributes['name']) === 'verification' ||\n lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nexport function serializeNodeWithId(\n n: Node | INode,\n doc: Document,\n map: idNodeMap,\n blockClass: string | RegExp,\n blockSelector: string | null,\n skipChild = false,\n inlineStylesheet = true,\n maskInputOptions?: MaskInputOptions,\n slimDOMOptions: SlimDOMOptions = {},\n recordCanvas?: boolean,\n preserveWhiteSpace = true,\n onSerialize?: (n: INode) => unknown,\n): serializedNodeWithId | null {\n const _serializedNode = serializeNode(\n n,\n doc,\n blockClass,\n blockSelector,\n inlineStylesheet,\n maskInputOptions,\n recordCanvas || false,\n );\n if (!_serializedNode) {\n // TODO: dev only\n console.warn(n, 'not serialized');\n return null;\n }\n\n let id;\n // Try to reuse the previous id\n if ('__sn' in n) {\n id = n.__sn.id;\n } else if (\n slimDOMExcluded(_serializedNode, slimDOMOptions) ||\n (!preserveWhiteSpace &&\n _serializedNode.type === NodeType.Text &&\n !_serializedNode.isStyle &&\n !_serializedNode.textContent.replace(/^\\s+|\\s+$/gm, '').length)\n ) {\n id = IGNORED_NODE;\n } else {\n id = genId();\n }\n const serializedNode = Object.assign(_serializedNode, { id });\n (n as INode).__sn = serializedNode;\n if (id === IGNORED_NODE) {\n return null; // slimDOM\n }\n map[id] = n as INode;\n if (onSerialize) {\n onSerialize(n as INode);\n }\n let recordChild = !skipChild;\n if (serializedNode.type === NodeType.Element) {\n recordChild = recordChild && !serializedNode.needBlock;\n // this property was not needed in replay side\n delete serializedNode.needBlock;\n }\n if (\n (serializedNode.type === NodeType.Document ||\n serializedNode.type === NodeType.Element) &&\n recordChild\n ) {\n if (\n slimDOMOptions.headWhitespace &&\n _serializedNode.type === NodeType.Element &&\n _serializedNode.tagName == 'head'\n // would impede performance: || getComputedStyle(n)['white-space'] === 'normal'\n ) {\n preserveWhiteSpace = false;\n }\n for (const childN of Array.from(n.childNodes)) {\n const serializedChildNode = serializeNodeWithId(\n childN,\n doc,\n map,\n blockClass,\n blockSelector,\n skipChild,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n );\n if (serializedChildNode) {\n serializedNode.childNodes.push(serializedChildNode);\n }\n }\n }\n\n if (\n serializedNode.type === NodeType.Element &&\n serializedNode.tagName === 'iframe'\n ) {\n const iframeDoc = (n as HTMLIFrameElement).contentDocument;\n if (iframeDoc) {\n const serializedIframeNode = serializeNodeWithId(\n iframeDoc,\n iframeDoc,\n map,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n );\n if (serializedIframeNode) {\n serializedNode.childNodes.push(serializedIframeNode);\n }\n }\n }\n\n return serializedNode;\n}\n\nfunction snapshot(\n n: Document,\n blockClass: string | RegExp = 'rr-block',\n inlineStylesheet = true,\n maskAllInputsOrOptions: boolean | MaskInputOptions,\n slimDOMSensibleOrOptions: boolean | SlimDOMOptions,\n recordCanvas?: boolean,\n blockSelector: string | null = null,\n preserveWhiteSpace?: boolean,\n onSerialize?: (n: INode) => unknown,\n): [serializedNodeWithId | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const maskInputOptions: MaskInputOptions =\n maskAllInputsOrOptions === true\n ? {\n color: true,\n date: true,\n 'datetime-local': true,\n email: true,\n month: true,\n number: true,\n range: true,\n search: true,\n tel: true,\n text: true,\n time: true,\n url: true,\n week: true,\n textarea: true,\n select: true,\n }\n : maskAllInputsOrOptions === false\n ? {}\n : maskAllInputsOrOptions;\n const slimDOMOptions: SlimDOMOptions =\n slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all'\n ? // if true: set of sensible options that should not throw away any information\n {\n script: true,\n comment: true,\n headFavicon: true,\n headWhitespace: true,\n headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', // destructive\n headMetaSocial: true,\n headMetaRobots: true,\n headMetaHttpEquiv: true,\n headMetaAuthorship: true,\n headMetaVerification: true,\n }\n : slimDOMSensibleOrOptions === false\n ? {}\n : slimDOMSensibleOrOptions;\n return [\n serializeNodeWithId(\n n,\n n,\n idNodeMap,\n blockClass,\n blockSelector,\n false,\n inlineStylesheet,\n maskInputOptions,\n slimDOMOptions,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n ),\n idNodeMap,\n ];\n}\n\nexport function visitSnapshot(\n node: serializedNodeWithId,\n onVisit: (node: serializedNodeWithId) => unknown,\n) {\n function walk(current: serializedNodeWithId) {\n onVisit(current);\n if (\n current.type === NodeType.Document ||\n current.type === NodeType.Element\n ) {\n current.childNodes.forEach(walk);\n }\n }\n\n walk(node);\n}\n\nexport function cleanupSnapshot() {\n // allow a new recording to start numbering nodes from scratch\n _id = 1;\n}\n\nexport default snapshot;\n","/**\n * This file is a fork of https://github.com/reworkcss/css/blob/master/lib/parse/index.js\n * I fork it because:\n * 1. The css library was built for node.js which does not have tree-shaking supports.\n * 2. Rewrites into typescript give us a better type interface.\n */\n\n/* tslint:disable no-conditional-assignment interface-name no-shadowed-variable */\n\nexport interface ParserOptions {\n /** Silently fail on parse errors */\n silent?: boolean;\n /**\n * The path to the file containing css.\n * Makes errors and source maps more helpful, by letting them know where code comes from.\n */\n source?: string;\n}\n\n/**\n * Error thrown during parsing.\n */\nexport interface ParserError {\n /** The full error message with the source position. */\n message?: string;\n /** The error message without position. */\n reason?: string;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n filename?: string;\n line?: number;\n column?: number;\n /** The portion of code that couldn't be parsed. */\n source?: string;\n}\n\nexport interface Loc {\n line?: number;\n column?: number;\n}\n\n/**\n * Base AST Tree Node.\n */\nexport interface Node {\n /** The possible values are the ones listed in the Types section on https://github.com/reworkcss/css page. */\n type?: string;\n /** A reference to the parent node, or null if the node has no parent. */\n parent?: Node;\n /** Information about the position in the source string that corresponds to the node. */\n position?: {\n start?: Loc;\n end?: Loc;\n /** The value of options.source if passed to css.parse. Otherwise undefined. */\n source?: string;\n /** The full source string passed to css.parse. */\n content?: string;\n };\n}\n\nexport interface Rule extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\nexport interface Declaration extends Node {\n /** The property name, trimmed from whitespace and comments. May not be empty. */\n property?: string;\n /** The value of the property, trimmed from whitespace and comments. Empty values are allowed. */\n value?: string;\n}\n\n/**\n * A rule-level or declaration-level comment. Comments inside selectors, properties and values etc. are lost.\n */\nexport interface Comment extends Node {\n comment?: string;\n}\n\n/**\n * The @charset at-rule.\n */\nexport interface Charset extends Node {\n /** The part following @charset. */\n charset?: string;\n}\n\n/**\n * The @custom-media at-rule\n */\nexport interface CustomMedia extends Node {\n /** The ---prefixed name. */\n name?: string;\n /** The part following the name. */\n media?: string;\n}\n\n/**\n * The @document at-rule.\n */\nexport interface Document extends Node {\n /** The part following @document. */\n document?: string;\n /** The vendor prefix in @document, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @font-face at-rule.\n */\nexport interface FontFace extends Node {\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @host at-rule.\n */\nexport interface Host extends Node {\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @import at-rule.\n */\nexport interface Import extends Node {\n /** The part following @import. */\n import?: string;\n}\n\n/**\n * The @keyframes at-rule.\n */\nexport interface KeyFrames extends Node {\n /** The name of the keyframes rule. */\n name?: string;\n /** The vendor prefix in @keyframes, or undefined if there is none. */\n vendor?: string;\n /** Array of nodes with the types keyframe and comment. */\n keyframes?: Array;\n}\n\nexport interface KeyFrame extends Node {\n /** The list of \"selectors\" of the keyframe rule, split on commas. Each “selector” is trimmed from whitespace. */\n values?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @media at-rule.\n */\nexport interface Media extends Node {\n /** The part following @media. */\n media?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/**\n * The @namespace at-rule.\n */\nexport interface Namespace extends Node {\n /** The part following @namespace. */\n namespace?: string;\n}\n\n/**\n * The @page at-rule.\n */\nexport interface Page extends Node {\n /** The list of selectors of the rule, split on commas. Each selector is trimmed from whitespace and comments. */\n selectors?: string[];\n /** Array of nodes with the types declaration and comment. */\n declarations?: Array;\n}\n\n/**\n * The @supports at-rule.\n */\nexport interface Supports extends Node {\n /** The part following @supports. */\n supports?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules?: Array;\n}\n\n/** All at-rules. */\nexport type AtRule =\n | Charset\n | CustomMedia\n | Document\n | FontFace\n | Host\n | Import\n | KeyFrames\n | Media\n | Namespace\n | Page\n | Supports;\n\n/**\n * A collection of rules\n */\nexport interface StyleRules {\n source?: string;\n /** Array of nodes with the types rule, comment and any of the at-rule types. */\n rules: Array;\n /** Array of Errors. Errors collected during parsing when option silent is true. */\n parsingErrors?: ParserError[];\n}\n\n/**\n * The root node returned by css.parse.\n */\nexport interface Stylesheet extends Node {\n stylesheet?: StyleRules;\n}\n\n// http://www.w3.org/TR/CSS21/grammar.html\n// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027\nconst commentre = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//g;\n\nexport function parse(css: string, options: ParserOptions = {}) {\n /**\n * Positional.\n */\n\n let lineno = 1;\n let column = 1;\n\n /**\n * Update lineno and column based on `str`.\n */\n\n function updatePosition(str: string) {\n const lines = str.match(/\\n/g);\n if (lines) {\n lineno += lines.length;\n }\n let i = str.lastIndexOf('\\n');\n column = i === -1 ? column + str.length : str.length - i;\n }\n\n /**\n * Mark position and patch `node.position`.\n */\n\n function position() {\n const start = { line: lineno, column };\n return (\n node: Rule | Declaration | Comment | AtRule | Stylesheet | KeyFrame,\n ) => {\n node.position = new Position(start);\n whitespace();\n return node;\n };\n }\n\n /**\n * Store position information for a node\n */\n\n class Position {\n public content!: string;\n public start!: Loc;\n public end!: Loc;\n public source?: string;\n\n constructor(start: Loc) {\n this.start = start;\n this.end = { line: lineno, column };\n this.source = options.source;\n }\n }\n\n /**\n * Non-enumerable source string\n */\n\n Position.prototype.content = css;\n\n const errorsList: ParserError[] = [];\n\n function error(msg: string) {\n const err = new Error(\n options.source + ':' + lineno + ':' + column + ': ' + msg,\n ) as ParserError;\n err.reason = msg;\n err.filename = options.source;\n err.line = lineno;\n err.column = column;\n err.source = css;\n\n if (options.silent) {\n errorsList.push(err);\n } else {\n throw err;\n }\n }\n\n /**\n * Parse stylesheet.\n */\n\n function stylesheet(): Stylesheet {\n const rulesList = rules();\n\n return {\n type: 'stylesheet',\n stylesheet: {\n source: options.source,\n rules: rulesList,\n parsingErrors: errorsList,\n },\n };\n }\n\n /**\n * Opening brace.\n */\n\n function open() {\n return match(/^{\\s*/);\n }\n\n /**\n * Closing brace.\n */\n\n function close() {\n return match(/^}/);\n }\n\n /**\n * Parse ruleset.\n */\n\n function rules() {\n let node: Rule | void;\n const rules: Rule[] = [];\n whitespace();\n comments(rules);\n while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) {\n if (node !== false) {\n rules.push(node);\n comments(rules);\n }\n }\n return rules;\n }\n\n /**\n * Match `re` and return captures.\n */\n\n function match(re: RegExp) {\n const m = re.exec(css);\n if (!m) {\n return;\n }\n const str = m[0];\n updatePosition(str);\n css = css.slice(str.length);\n return m;\n }\n\n /**\n * Parse whitespace.\n */\n\n function whitespace() {\n match(/^\\s*/);\n }\n\n /**\n * Parse comments;\n */\n\n function comments(rules: Rule[] = []) {\n let c: Comment | void;\n while ((c = comment())) {\n if (c !== false) {\n rules.push(c);\n }\n c = comment();\n }\n return rules;\n }\n\n /**\n * Parse comment.\n */\n\n function comment() {\n const pos = position();\n if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) {\n return;\n }\n\n let i = 2;\n while (\n '' !== css.charAt(i) &&\n ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))\n ) {\n ++i;\n }\n i += 2;\n\n if ('' === css.charAt(i - 1)) {\n return error('End of comment missing');\n }\n\n const str = css.slice(2, i - 2);\n column += 2;\n updatePosition(str);\n css = css.slice(i);\n column += 2;\n\n return pos({\n type: 'comment',\n comment: str,\n });\n }\n\n /**\n * Parse selector.\n */\n\n function selector() {\n const m = match(/^([^{]+)/);\n if (!m) {\n return;\n }\n /* @fix Remove all comments from selectors\n * http://ostermiller.org/findcomment.html */\n return trim(m[0])\n .replace(/\\/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*\\/+/g, '')\n .replace(/\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*'/g, m => {\n return m.replace(/,/g, '\\u200C');\n })\n .split(/\\s*(?![^(]*\\)),\\s*/)\n .map(s => {\n return s.replace(/\\u200C/g, ',');\n });\n }\n\n /**\n * Parse declaration.\n */\n\n function declaration(): Declaration | void | never {\n const pos = position();\n\n // prop\n let propMatch = match(/^(\\*?[-#\\/\\*\\\\\\w]+(\\[[0-9a-z_-]+\\])?)\\s*/);\n if (!propMatch) {\n return;\n }\n const prop = trim(propMatch[0]);\n\n // :\n if (!match(/^:\\s*/)) {\n return error(`property missing ':'`);\n }\n\n // val\n const val = match(/^((?:'(?:\\\\'|.)*?'|\"(?:\\\\\"|.)*?\"|\\([^\\)]*?\\)|[^};])+)/);\n\n const ret = pos({\n type: 'declaration',\n property: prop.replace(commentre, ''),\n value: val ? trim(val[0]).replace(commentre, '') : '',\n });\n\n // ;\n match(/^[;\\s]*/);\n\n return ret;\n }\n\n /**\n * Parse declarations.\n */\n\n function declarations() {\n const decls: Array = [];\n\n if (!open()) {\n return error(`missing '{'`);\n }\n comments(decls);\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n if ((decl as unknown) !== false) {\n decls.push(decl);\n comments(decls);\n }\n decl = declaration();\n }\n\n if (!close()) {\n return error(`missing '}'`);\n }\n return decls;\n }\n\n /**\n * Parse keyframe.\n */\n\n function keyframe() {\n let m;\n const vals = [];\n const pos = position();\n\n while ((m = match(/^((\\d+\\.\\d+|\\.\\d+|\\d+)%?|[a-z]+)\\s*/))) {\n vals.push(m[1]);\n match(/^,\\s*/);\n }\n\n if (!vals.length) {\n return;\n }\n\n return pos({\n type: 'keyframe',\n values: vals,\n declarations: declarations() as Declaration[],\n });\n }\n\n /**\n * Parse keyframes.\n */\n\n function atkeyframes() {\n const pos = position();\n let m = match(/^@([-\\w]+)?keyframes\\s*/);\n\n if (!m) {\n return;\n }\n const vendor = m[1];\n\n // identifier\n m = match(/^([-\\w]+)\\s*/);\n if (!m) {\n return error('@keyframes missing name');\n }\n const name = m[1];\n\n if (!open()) {\n return error(`@keyframes missing '{'`);\n }\n\n let frame;\n let frames = comments();\n while ((frame = keyframe())) {\n frames.push(frame);\n frames = frames.concat(comments());\n }\n\n if (!close()) {\n return error(`@keyframes missing '}'`);\n }\n\n return pos({\n type: 'keyframes',\n name,\n vendor,\n keyframes: frames,\n });\n }\n\n /**\n * Parse supports.\n */\n\n function atsupports() {\n const pos = position();\n const m = match(/^@supports *([^{]+)/);\n\n if (!m) {\n return;\n }\n const supports = trim(m[1]);\n\n if (!open()) {\n return error(`@supports missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@supports missing '}'`);\n }\n\n return pos({\n type: 'supports',\n supports,\n rules: style,\n });\n }\n\n /**\n * Parse host.\n */\n\n function athost() {\n const pos = position();\n const m = match(/^@host\\s*/);\n\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@host missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@host missing '}'`);\n }\n\n return pos({\n type: 'host',\n rules: style,\n });\n }\n\n /**\n * Parse media.\n */\n\n function atmedia() {\n const pos = position();\n const m = match(/^@media *([^{]+)/);\n\n if (!m) {\n return;\n }\n const media = trim(m[1]);\n\n if (!open()) {\n return error(`@media missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@media missing '}'`);\n }\n\n return pos({\n type: 'media',\n media,\n rules: style,\n });\n }\n\n /**\n * Parse custom-media.\n */\n\n function atcustommedia() {\n const pos = position();\n const m = match(/^@custom-media\\s+(--[^\\s]+)\\s*([^{;]+);/);\n if (!m) {\n return;\n }\n\n return pos({\n type: 'custom-media',\n name: trim(m[1]),\n media: trim(m[2]),\n });\n }\n\n /**\n * Parse paged media.\n */\n\n function atpage() {\n const pos = position();\n const m = match(/^@page */);\n if (!m) {\n return;\n }\n\n const sel = selector() || [];\n\n if (!open()) {\n return error(`@page missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@page missing '}'`);\n }\n\n return pos({\n type: 'page',\n selectors: sel,\n declarations: decls,\n });\n }\n\n /**\n * Parse document.\n */\n\n function atdocument() {\n const pos = position();\n const m = match(/^@([-\\w]+)?document *([^{]+)/);\n if (!m) {\n return;\n }\n\n const vendor = trim(m[1]);\n const doc = trim(m[2]);\n\n if (!open()) {\n return error(`@document missing '{'`);\n }\n\n const style = comments().concat(rules());\n\n if (!close()) {\n return error(`@document missing '}'`);\n }\n\n return pos({\n type: 'document',\n document: doc,\n vendor,\n rules: style,\n });\n }\n\n /**\n * Parse font-face.\n */\n\n function atfontface() {\n const pos = position();\n const m = match(/^@font-face\\s*/);\n if (!m) {\n return;\n }\n\n if (!open()) {\n return error(`@font-face missing '{'`);\n }\n let decls = comments();\n\n // declarations\n let decl;\n while ((decl = declaration())) {\n decls.push(decl);\n decls = decls.concat(comments());\n }\n\n if (!close()) {\n return error(`@font-face missing '}'`);\n }\n\n return pos({\n type: 'font-face',\n declarations: decls,\n });\n }\n\n /**\n * Parse import\n */\n\n const atimport = _compileAtrule('import');\n\n /**\n * Parse charset\n */\n\n const atcharset = _compileAtrule('charset');\n\n /**\n * Parse namespace\n */\n\n const atnamespace = _compileAtrule('namespace');\n\n /**\n * Parse non-block at-rules\n */\n\n function _compileAtrule(name: string) {\n const re = new RegExp('^@' + name + '\\\\s*([^;]+);');\n return () => {\n const pos = position();\n const m = match(re);\n if (!m) {\n return;\n }\n const ret: Record = { type: name };\n ret[name] = m[1].trim();\n return pos(ret);\n };\n }\n\n /**\n * Parse at rule.\n */\n\n function atrule() {\n if (css[0] !== '@') {\n return;\n }\n\n return (\n atkeyframes() ||\n atmedia() ||\n atcustommedia() ||\n atsupports() ||\n atimport() ||\n atcharset() ||\n atnamespace() ||\n atdocument() ||\n atpage() ||\n athost() ||\n atfontface()\n );\n }\n\n /**\n * Parse rule.\n */\n\n function rule() {\n const pos = position();\n const sel = selector();\n\n if (!sel) {\n return error('selector missing');\n }\n comments();\n\n return pos({\n type: 'rule',\n selectors: sel,\n declarations: declarations() as Declaration[],\n });\n }\n\n return addParent(stylesheet());\n}\n\n/**\n * Trim `str`.\n */\n\nfunction trim(str: string) {\n return str ? str.replace(/^\\s+|\\s+$/g, '') : '';\n}\n\n/**\n * Adds non-enumerable parent node reference to each node.\n */\n\nfunction addParent(obj: Stylesheet, parent?: Stylesheet) {\n const isNode = obj && typeof obj.type === 'string';\n const childParent = isNode ? obj : parent;\n\n for (const k of Object.keys(obj)) {\n const value = obj[k as keyof Stylesheet];\n if (Array.isArray(value)) {\n value.forEach(v => {\n addParent(v, childParent);\n });\n } else if (value && typeof value === 'object') {\n addParent((value as unknown) as Stylesheet, childParent);\n }\n }\n\n if (isNode) {\n Object.defineProperty(obj, 'parent', {\n configurable: true,\n writable: true,\n enumerable: false,\n value: parent || null,\n });\n }\n\n return obj;\n}\n","import { parse } from './css';\nimport {\n serializedNodeWithId,\n NodeType,\n tagMap,\n elementNode,\n idNodeMap,\n INode,\n CallbackArray,\n} from './types';\n\nconst tagMap: tagMap = {\n script: 'noscript',\n // camel case svg element tag names\n altglyph: 'altGlyph',\n altglyphdef: 'altGlyphDef',\n altglyphitem: 'altGlyphItem',\n animatecolor: 'animateColor',\n animatemotion: 'animateMotion',\n animatetransform: 'animateTransform',\n clippath: 'clipPath',\n feblend: 'feBlend',\n fecolormatrix: 'feColorMatrix',\n fecomponenttransfer: 'feComponentTransfer',\n fecomposite: 'feComposite',\n feconvolvematrix: 'feConvolveMatrix',\n fediffuselighting: 'feDiffuseLighting',\n fedisplacementmap: 'feDisplacementMap',\n fedistantlight: 'feDistantLight',\n fedropshadow: 'feDropShadow',\n feflood: 'feFlood',\n fefunca: 'feFuncA',\n fefuncb: 'feFuncB',\n fefuncg: 'feFuncG',\n fefuncr: 'feFuncR',\n fegaussianblur: 'feGaussianBlur',\n feimage: 'feImage',\n femerge: 'feMerge',\n femergenode: 'feMergeNode',\n femorphology: 'feMorphology',\n feoffset: 'feOffset',\n fepointlight: 'fePointLight',\n fespecularlighting: 'feSpecularLighting',\n fespotlight: 'feSpotLight',\n fetile: 'feTile',\n feturbulence: 'feTurbulence',\n foreignobject: 'foreignObject',\n glyphref: 'glyphRef',\n lineargradient: 'linearGradient',\n radialgradient: 'radialGradient',\n};\nfunction getTagName(n: elementNode): string {\n let tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName;\n if (tagName === 'link' && n.attributes._cssText) {\n tagName = 'style';\n }\n return tagName;\n}\n\nconst HOVER_SELECTOR = /([^\\\\]):hover/g;\nexport function addHoverClass(cssText: string): string {\n const ast = parse(cssText, { silent: true });\n if (!ast.stylesheet) {\n return cssText;\n }\n ast.stylesheet.rules.forEach((rule) => {\n if ('selectors' in rule) {\n (rule.selectors || []).forEach((selector: string) => {\n if (HOVER_SELECTOR.test(selector)) {\n const newSelector = selector.replace(HOVER_SELECTOR, '$1.\\\\:hover');\n cssText = cssText.replace(selector, `${selector}, ${newSelector}`);\n }\n });\n }\n });\n return cssText;\n}\n\nfunction isIframe(n: serializedNodeWithId) {\n return n.type === NodeType.Element && n.tagName === 'iframe';\n}\n\nfunction buildIframe(\n iframe: HTMLIFrameElement,\n childNodes: serializedNodeWithId[],\n map: idNodeMap,\n cbs: CallbackArray,\n HACK_CSS: boolean,\n) {\n const targetDoc = iframe.contentDocument!;\n for (const childN of childNodes) {\n console.log('build iframe', childN);\n buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS);\n }\n}\n\nfunction buildNode(\n n: serializedNodeWithId,\n doc: Document,\n HACK_CSS: boolean,\n): Node | null {\n switch (n.type) {\n case NodeType.Document:\n return doc.implementation.createDocument(null, '', null);\n case NodeType.DocumentType:\n return doc.implementation.createDocumentType(\n n.name || 'html',\n n.publicId,\n n.systemId,\n );\n case NodeType.Element:\n const tagName = getTagName(n);\n let node: Element;\n if (n.isSVG) {\n node = doc.createElementNS('http://www.w3.org/2000/svg', tagName);\n } else {\n node = doc.createElement(tagName);\n }\n for (const name in n.attributes) {\n if (!n.attributes.hasOwnProperty(name)) {\n continue;\n }\n let value = n.attributes[name];\n value =\n typeof value === 'boolean' || typeof value === 'number' ? '' : value;\n // attribute names start with rr_ are internal attributes added by rrweb\n if (!name.startsWith('rr_')) {\n const isTextarea = tagName === 'textarea' && name === 'value';\n const isRemoteOrDynamicCss =\n tagName === 'style' && name === '_cssText';\n if (isRemoteOrDynamicCss && HACK_CSS) {\n value = addHoverClass(value);\n }\n if (isTextarea || isRemoteOrDynamicCss) {\n const child = doc.createTextNode(value);\n // https://github.com/rrweb-io/rrweb/issues/112\n for (const c of Array.from(node.childNodes)) {\n if (c.nodeType === node.TEXT_NODE) {\n node.removeChild(c);\n }\n }\n node.appendChild(child);\n continue;\n }\n if (tagName === 'iframe' && name === 'src') {\n continue;\n }\n try {\n if (n.isSVG && name === 'xlink:href') {\n node.setAttributeNS('http://www.w3.org/1999/xlink', name, value);\n } else if (\n name === 'onload' ||\n name === 'onclick' ||\n name.substring(0, 7) === 'onmouse'\n ) {\n // Rename some of the more common atttributes from https://www.w3schools.com/tags/ref_eventattributes.asp\n // as setting them triggers a console.error (which shows up despite the try/catch)\n // Assumption: these attributes are not used to css\n node.setAttribute('_' + name, value);\n } else {\n node.setAttribute(name, value);\n }\n } catch (error) {\n // skip invalid attribute\n }\n } else {\n // handle internal attributes\n if (tagName === 'canvas' && name === 'rr_dataURL') {\n const image = document.createElement('img');\n image.src = value;\n image.onload = () => {\n const ctx = (node as HTMLCanvasElement).getContext('2d');\n if (ctx) {\n ctx.drawImage(image, 0, 0, image.width, image.height);\n }\n };\n }\n if (name === 'rr_width') {\n (node as HTMLElement).style.width = value;\n }\n if (name === 'rr_height') {\n (node as HTMLElement).style.height = value;\n }\n if (name === 'rr_mediaState') {\n switch (value) {\n case 'played':\n (node as HTMLMediaElement).play();\n case 'paused':\n (node as HTMLMediaElement).pause();\n break;\n default:\n }\n }\n }\n }\n return node;\n case NodeType.Text:\n return doc.createTextNode(\n n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent,\n );\n case NodeType.CDATA:\n return doc.createCDATASection(n.textContent);\n case NodeType.Comment:\n return doc.createComment(n.textContent);\n default:\n return null;\n }\n}\n\nexport function buildNodeWithSN(\n n: serializedNodeWithId,\n doc: Document,\n map: idNodeMap,\n cbs: CallbackArray,\n skipChild = false,\n HACK_CSS = true,\n): [INode | null, serializedNodeWithId[]] {\n let node = buildNode(n, doc, HACK_CSS);\n if (!node) {\n return [null, []];\n }\n if (n.rootId) {\n console.assert(\n ((map[n.rootId] as unknown) as Document) === doc,\n 'Target document should has the same root id.',\n );\n }\n // use target document as root document\n if (n.type === NodeType.Document) {\n // close before open to make sure document was closed\n doc.close();\n doc.open();\n node = doc;\n }\n\n (node as INode).__sn = n;\n map[n.id] = node as INode;\n\n const nodeIsIframe = isIframe(n);\n if (n.type === NodeType.Element && nodeIsIframe) {\n return [node as INode, n.childNodes];\n }\n\n if (\n (n.type === NodeType.Document || n.type === NodeType.Element) &&\n !skipChild\n ) {\n for (const childN of n.childNodes) {\n const [childNode, nestedNodes] = buildNodeWithSN(\n childN,\n doc,\n map,\n cbs,\n false,\n HACK_CSS,\n );\n if (!childNode) {\n console.warn('Failed to rebuild', childN);\n continue;\n }\n\n node.appendChild(childNode);\n if (nestedNodes.length === 0) {\n continue;\n }\n const childNodeIsIframe = isIframe(childN);\n if (childNodeIsIframe) {\n cbs.push(() =>\n buildIframe(\n (childNode as unknown) as HTMLIFrameElement,\n nestedNodes,\n map,\n cbs,\n HACK_CSS,\n ),\n );\n }\n }\n }\n return [node as INode, []];\n}\n\nfunction visit(idNodeMap: idNodeMap, onVisit: (node: INode) => void) {\n function walk(node: INode) {\n onVisit(node);\n }\n\n for (const key in idNodeMap) {\n if (idNodeMap[key]) {\n walk(idNodeMap[key]);\n }\n }\n}\n\nfunction handleScroll(node: INode) {\n const n = node.__sn;\n if (n.type !== NodeType.Element) {\n return;\n }\n const el = (node as Node) as HTMLElement;\n for (const name in n.attributes) {\n if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) {\n continue;\n }\n const value = n.attributes[name];\n if (name === 'rr_scrollLeft') {\n el.scrollLeft = value as number;\n }\n if (name === 'rr_scrollTop') {\n el.scrollTop = value as number;\n }\n }\n}\n\nfunction rebuild(\n n: serializedNodeWithId,\n doc: Document,\n onVisit?: (node: INode) => unknown,\n /**\n * This is not a public API yet, just for POC\n */\n HACK_CSS: boolean = true,\n): [Node | null, idNodeMap] {\n const idNodeMap: idNodeMap = {};\n const callbackArray: CallbackArray = [];\n const [node] = buildNodeWithSN(\n n,\n doc,\n idNodeMap,\n callbackArray,\n false,\n HACK_CSS,\n );\n callbackArray.forEach((f) => f());\n visit(idNodeMap, (visitedNode) => {\n if (onVisit) {\n onVisit(visitedNode);\n }\n handleScroll(visitedNode);\n });\n return [node, idNodeMap];\n}\n\nexport default rebuild;\n"],"names":["NodeType","_id","tagNameRegex","RegExp","IGNORED_NODE","genId","getValidTagName","tagName","processedTagName","toLowerCase","trim","test","getCssRulesString","s","rules","cssRules","Array","from","map","getCssRuleString","join","error","rule","isCSSImportRule","styleSheet","cssText","extractOrigin","url","indexOf","split","slice","URL_IN_CSS_REF","RELATIVE_PATH","DATA_URI","absoluteToStylesheet","href","replace","origin","quote1","path1","quote2","path2","path3","filePath","maybe_quote","stack","parts","pop","parts_1","_i","part","push","getAbsoluteSrcsetString","doc","attributeValue","srcItem","urlAndSize","trimLeft","trimRight","length","absoluteToDoc","a","createElement","isSVGElement","el","SVGElement","transformAttribute","name","value","location","_isBlockedElement","element","blockClass","blockSelector","classList","contains","forEach","className","matches","serializeNode","n","inlineStylesheet","maskInputOptions","recordCanvas","rootId","__sn","docId","id","undefined","nodeType","DOCUMENT_NODE","type","Document","childNodes","DOCUMENT_TYPE_NODE","DocumentType","publicId","systemId","ELEMENT_NODE","needBlock","attributes_1","_a","attributes","_b","stylesheet","styleSheets","find","rel","_cssText","sheet","innerText","textContent","repeat","checked","selectValue","parentElement","selected","rr_dataURL","toDataURL","rr_mediaState","paused","scrollLeft","rr_scrollLeft","scrollTop","rr_scrollTop","_c","width","height","rr_width","rr_height","Element","isSVG","TEXT_NODE","parentTagName","parentNode","isStyle","Text","CDATA_SECTION_NODE","CDATA","COMMENT_NODE","Comment","lowerIfExists","maybeAttr","slimDOMExcluded","sn","slimDOMOptions","comment","script","headFavicon","match","headMetaDescKeywords","headMetaSocial","headMetaRobots","headMetaHttpEquiv","headMetaAuthorship","headMetaVerification","serializeNodeWithId","skipChild","preserveWhiteSpace","onSerialize","_serializedNode","console","warn","serializedNode","Object","assign","recordChild","headWhitespace","serializedChildNode","iframeDoc","contentDocument","serializedIframeNode","snapshot","maskAllInputsOrOptions","slimDOMSensibleOrOptions","idNodeMap","color","date","datetime-local","email","month","number","range","search","tel","text","time","week","textarea","select","visitSnapshot","node","onVisit","walk","current","cleanupSnapshot","commentre","parse","css","options","lineno","column","updatePosition","str","lines","i","lastIndexOf","position","start","line","Position","whitespace","this","end","source","prototype","content","errorsList","msg","err","Error","reason","filename","silent","open","close","comments","charAt","atrule","re","m","exec","c","pos","selector","declaration","propMatch","prop","val","ret","property","declarations","decl","decls","keyframe","vals","values","rulesList","atimport","_compileAtrule","atcharset","atnamespace","vendor","frame","frames","concat","keyframes","atkeyframes","media","style","atmedia","atcustommedia","supports","atsupports","document","atdocument","sel","selectors","atpage","athost","atfontface","addParent","parsingErrors","obj","parent","isNode","childParent","keys","isArray","v","defineProperty","configurable","writable","enumerable","tagMap","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","clippath","feblend","fecolormatrix","fecomponenttransfer","fecomposite","feconvolvematrix","fediffuselighting","fedisplacementmap","fedistantlight","fedropshadow","feflood","fefunca","fefuncb","fefuncg","fefuncr","fegaussianblur","feimage","femerge","femergenode","femorphology","feoffset","fepointlight","fespecularlighting","fespotlight","fetile","feturbulence","foreignobject","glyphref","lineargradient","radialgradient","getTagName","HOVER_SELECTOR","addHoverClass","ast","newSelector","isIframe","buildIframe","iframe","cbs","HACK_CSS","targetDoc","childNodes_1","childN","log","buildNodeWithSN","buildNode","implementation","createDocument","createDocumentType","node_1","createElementNS","hasOwnProperty","startsWith","image_1","src","onload","ctx","getContext","drawImage","play","pause","isTextarea","isRemoteOrDynamicCss","child","createTextNode","removeChild","appendChild","setAttributeNS","substring","setAttribute","createCDATASection","createComment","assert","nodeIsIframe","childNode","nestedNodes","visit","key","handleScroll","rebuild","callbackArray","f","visitedNode"],"mappings":"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"} \ No newline at end of file diff --git a/lib/rrweb-snapshot.js b/lib/rrweb-snapshot.js deleted file mode 100644 index e3c5309..0000000 --- a/lib/rrweb-snapshot.js +++ /dev/null @@ -1,1211 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -(function (NodeType) { - NodeType[NodeType["Document"] = 0] = "Document"; - NodeType[NodeType["DocumentType"] = 1] = "DocumentType"; - NodeType[NodeType["Element"] = 2] = "Element"; - NodeType[NodeType["Text"] = 3] = "Text"; - NodeType[NodeType["CDATA"] = 4] = "CDATA"; - NodeType[NodeType["Comment"] = 5] = "Comment"; -})(exports.NodeType || (exports.NodeType = {})); - -var _id = 1; -var tagNameRegex = RegExp('[^a-z1-6-_]'); -var IGNORED_NODE = -2; -function genId() { - return _id++; -} -function getValidTagName(tagName) { - var processedTagName = tagName.toLowerCase().trim(); - if (tagNameRegex.test(processedTagName)) { - return 'div'; - } - return processedTagName; -} -function getCssRulesString(s) { - try { - var rules = s.rules || s.cssRules; - return rules ? Array.from(rules).map(getCssRuleString).join('') : null; - } - catch (error) { - return null; - } -} -function getCssRuleString(rule) { - return isCSSImportRule(rule) - ? getCssRulesString(rule.styleSheet) || '' - : rule.cssText; -} -function isCSSImportRule(rule) { - return 'styleSheet' in rule; -} -function extractOrigin(url) { - var origin; - if (url.indexOf('//') > -1) { - origin = url.split('/').slice(0, 3).join('/'); - } - else { - origin = url.split('/')[0]; - } - origin = origin.split('?')[0]; - return origin; -} -var URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm; -var RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/; -var DATA_URI = /^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64|utf-?8).*,(.*)/i; -function absoluteToStylesheet(cssText, href) { - return (cssText || '').replace(URL_IN_CSS_REF, function (origin, quote1, path1, quote2, path2, path3) { - var filePath = path1 || path2 || path3; - var maybe_quote = quote1 || quote2 || ''; - if (!filePath) { - return origin; - } - if (!RELATIVE_PATH.test(filePath)) { - return "url(" + maybe_quote + filePath + maybe_quote + ")"; - } - if (DATA_URI.test(filePath)) { - return "url(" + maybe_quote + filePath + maybe_quote + ")"; - } - if (filePath[0] === '/') { - return "url(" + maybe_quote + (extractOrigin(href) + filePath) + maybe_quote + ")"; - } - var stack = href.split('/'); - var parts = filePath.split('/'); - stack.pop(); - for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { - var part = parts_1[_i]; - if (part === '.') { - continue; - } - else if (part === '..') { - stack.pop(); - } - else { - stack.push(part); - } - } - return "url(" + maybe_quote + stack.join('/') + maybe_quote + ")"; - }); -} -function getAbsoluteSrcsetString(doc, attributeValue) { - if (attributeValue.trim() === '') { - return attributeValue; - } - var srcsetValues = attributeValue.split(','); - var resultingSrcsetString = srcsetValues - .map(function (srcItem) { - var trimmedSrcItem = srcItem.trimLeft().trimRight(); - var urlAndSize = trimmedSrcItem.split(' '); - if (urlAndSize.length === 2) { - var absUrl = absoluteToDoc(doc, urlAndSize[0]); - return absUrl + " " + urlAndSize[1]; - } - else if (urlAndSize.length === 1) { - var absUrl = absoluteToDoc(doc, urlAndSize[0]); - return "" + absUrl; - } - return ''; - }) - .join(', '); - return resultingSrcsetString; -} -function absoluteToDoc(doc, attributeValue) { - if (!attributeValue || attributeValue.trim() === '') { - return attributeValue; - } - var a = doc.createElement('a'); - a.href = attributeValue; - return a.href; -} -function isSVGElement(el) { - return el.tagName === 'svg' || el instanceof SVGElement; -} -function transformAttribute(doc, name, value) { - if (name === 'src' || (name === 'href' && value)) { - return absoluteToDoc(doc, value); - } - else if (name === 'srcset' && value) { - return getAbsoluteSrcsetString(doc, value); - } - else if (name === 'style' && value) { - return absoluteToStylesheet(value, location.href); - } - else { - return value; - } -} -function _isBlockedElement(element, blockClass, blockSelector) { - if (typeof blockClass === 'string') { - if (element.classList.contains(blockClass)) { - return true; - } - } - else { - element.classList.forEach(function (className) { - if (blockClass.test(className)) { - return true; - } - }); - } - if (blockSelector) { - return element.matches(blockSelector); - } - return false; -} -function serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas) { - if (maskInputOptions === void 0) { maskInputOptions = {}; } - var rootId; - if (doc.__sn) { - var docId = doc.__sn.id; - rootId = docId === 1 ? undefined : docId; - } - switch (n.nodeType) { - case n.DOCUMENT_NODE: - return { - type: exports.NodeType.Document, - childNodes: [], - rootId: rootId - }; - case n.DOCUMENT_TYPE_NODE: - return { - type: exports.NodeType.DocumentType, - name: n.name, - publicId: n.publicId, - systemId: n.systemId, - rootId: rootId - }; - case n.ELEMENT_NODE: - var needBlock = _isBlockedElement(n, blockClass, blockSelector); - var tagName = getValidTagName(n.tagName); - var attributes_1 = {}; - for (var _i = 0, _a = Array.from(n.attributes); _i < _a.length; _i++) { - var _b = _a[_i], name = _b.name, value = _b.value; - attributes_1[name] = transformAttribute(doc, name, value); - } - if (tagName === 'link' && inlineStylesheet) { - var stylesheet = Array.from(doc.styleSheets).find(function (s) { - return s.href === n.href; - }); - var cssText = getCssRulesString(stylesheet); - if (cssText) { - delete attributes_1.rel; - delete attributes_1.href; - attributes_1._cssText = absoluteToStylesheet(cssText, stylesheet.href); - } - } - if (tagName === 'style' && - n.sheet && - !(n.innerText || - n.textContent || - '').trim().length) { - var cssText = getCssRulesString(n.sheet); - if (cssText) { - attributes_1._cssText = absoluteToStylesheet(cssText, location.href); - } - } - if (tagName === 'input' || - tagName === 'textarea' || - tagName === 'select') { - var value = n.value; - if (attributes_1.type !== 'radio' && - attributes_1.type !== 'checkbox' && - attributes_1.type !== 'submit' && - attributes_1.type !== 'button' && - value) { - attributes_1.value = - maskInputOptions[attributes_1.type] || - maskInputOptions[tagName] - ? '*'.repeat(value.length) - : value; - } - else if (n.checked) { - attributes_1.checked = n.checked; - } - } - if (tagName === 'option') { - var selectValue = n.parentElement; - if (attributes_1.value === selectValue.value) { - attributes_1.selected = n.selected; - } - } - if (tagName === 'canvas' && recordCanvas) { - attributes_1.rr_dataURL = n.toDataURL(); - } - if (tagName === 'audio' || tagName === 'video') { - attributes_1.rr_mediaState = n.paused - ? 'paused' - : 'played'; - } - if (n.scrollLeft) { - attributes_1.rr_scrollLeft = n.scrollLeft; - } - if (n.scrollTop) { - attributes_1.rr_scrollTop = n.scrollTop; - } - if (needBlock) { - var _c = n.getBoundingClientRect(), width = _c.width, height = _c.height; - attributes_1.rr_width = width + "px"; - attributes_1.rr_height = height + "px"; - } - return { - type: exports.NodeType.Element, - tagName: tagName, - attributes: attributes_1, - childNodes: [], - isSVG: isSVGElement(n) || undefined, - needBlock: needBlock, - rootId: rootId - }; - case n.TEXT_NODE: - var parentTagName = n.parentNode && n.parentNode.tagName; - var textContent = n.textContent; - var isStyle = parentTagName === 'STYLE' ? true : undefined; - if (isStyle && textContent) { - textContent = absoluteToStylesheet(textContent, location.href); - } - if (parentTagName === 'SCRIPT') { - textContent = 'SCRIPT_PLACEHOLDER'; - } - return { - type: exports.NodeType.Text, - textContent: textContent || '', - isStyle: isStyle, - rootId: rootId - }; - case n.CDATA_SECTION_NODE: - return { - type: exports.NodeType.CDATA, - textContent: '', - rootId: rootId - }; - case n.COMMENT_NODE: - return { - type: exports.NodeType.Comment, - textContent: n.textContent || '', - rootId: rootId - }; - default: - return false; - } -} -function lowerIfExists(maybeAttr) { - if (maybeAttr === undefined) { - return ''; - } - else { - return maybeAttr.toLowerCase(); - } -} -function slimDOMExcluded(sn, slimDOMOptions) { - if (slimDOMOptions.comment && sn.type === exports.NodeType.Comment) { - return true; - } - else if (sn.type === exports.NodeType.Element) { - if (slimDOMOptions.script && - (sn.tagName === 'script' || - (sn.tagName === 'link' && - sn.attributes.rel === 'preload' && - sn.attributes['as'] === 'script'))) { - return true; - } - else if (slimDOMOptions.headFavicon && - ((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') || - (sn.tagName === 'meta' && - (lowerIfExists(sn.attributes['name']).match(/^msapplication-tile(image|color)$/) || - lowerIfExists(sn.attributes['name']) === 'application-name' || - lowerIfExists(sn.attributes['rel']) === 'icon' || - lowerIfExists(sn.attributes['rel']) === 'apple-touch-icon' || - lowerIfExists(sn.attributes['rel']) === 'shortcut icon')))) { - return true; - } - else if (sn.tagName === 'meta') { - if (slimDOMOptions.headMetaDescKeywords && - lowerIfExists(sn.attributes['name']).match(/^description|keywords$/)) { - return true; - } - else if (slimDOMOptions.headMetaSocial && - (lowerIfExists(sn.attributes['property']).match(/^(og|twitter|fb):/) || - lowerIfExists(sn.attributes['name']).match(/^(og|twitter):/) || - lowerIfExists(sn.attributes['name']) === 'pinterest')) { - return true; - } - else if (slimDOMOptions.headMetaRobots && - (lowerIfExists(sn.attributes['name']) === 'robots' || - lowerIfExists(sn.attributes['name']) === 'googlebot' || - lowerIfExists(sn.attributes['name']) === 'bingbot')) { - return true; - } - else if (slimDOMOptions.headMetaHttpEquiv && - sn.attributes['http-equiv'] !== undefined) { - return true; - } - else if (slimDOMOptions.headMetaAuthorship && - (lowerIfExists(sn.attributes['name']) === 'author' || - lowerIfExists(sn.attributes['name']) === 'generator' || - lowerIfExists(sn.attributes['name']) === 'framework' || - lowerIfExists(sn.attributes['name']) === 'publisher' || - lowerIfExists(sn.attributes['name']) === 'progid' || - lowerIfExists(sn.attributes['property']).match(/^article:/) || - lowerIfExists(sn.attributes['property']).match(/^product:/))) { - return true; - } - else if (slimDOMOptions.headMetaVerification && - (lowerIfExists(sn.attributes['name']) === 'google-site-verification' || - lowerIfExists(sn.attributes['name']) === 'yandex-verification' || - lowerIfExists(sn.attributes['name']) === 'csrf-token' || - lowerIfExists(sn.attributes['name']) === 'p:domain_verify' || - lowerIfExists(sn.attributes['name']) === 'verify-v1' || - lowerIfExists(sn.attributes['name']) === 'verification' || - lowerIfExists(sn.attributes['name']) === 'shopify-checkout-api-token')) { - return true; - } - } - } - return false; -} -function serializeNodeWithId(n, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize) { - if (skipChild === void 0) { skipChild = false; } - if (inlineStylesheet === void 0) { inlineStylesheet = true; } - if (slimDOMOptions === void 0) { slimDOMOptions = {}; } - if (preserveWhiteSpace === void 0) { preserveWhiteSpace = true; } - var _serializedNode = serializeNode(n, doc, blockClass, blockSelector, inlineStylesheet, maskInputOptions, recordCanvas || false); - if (!_serializedNode) { - console.warn(n, 'not serialized'); - return null; - } - var id; - if ('__sn' in n) { - id = n.__sn.id; - } - else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || - (!preserveWhiteSpace && - _serializedNode.type === exports.NodeType.Text && - !_serializedNode.isStyle && - !_serializedNode.textContent.replace(/^\s+|\s+$/gm, '').length)) { - id = IGNORED_NODE; - } - else { - id = genId(); - } - var serializedNode = Object.assign(_serializedNode, { id: id }); - n.__sn = serializedNode; - if (id === IGNORED_NODE) { - return null; - } - map[id] = n; - if (onSerialize) { - onSerialize(n); - } - var recordChild = !skipChild; - if (serializedNode.type === exports.NodeType.Element) { - recordChild = recordChild && !serializedNode.needBlock; - delete serializedNode.needBlock; - } - if ((serializedNode.type === exports.NodeType.Document || - serializedNode.type === exports.NodeType.Element) && - recordChild) { - if (slimDOMOptions.headWhitespace && - _serializedNode.type === exports.NodeType.Element && - _serializedNode.tagName == 'head') { - preserveWhiteSpace = false; - } - for (var _i = 0, _a = Array.from(n.childNodes); _i < _a.length; _i++) { - var childN = _a[_i]; - var serializedChildNode = serializeNodeWithId(childN, doc, map, blockClass, blockSelector, skipChild, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace); - if (serializedChildNode) { - serializedNode.childNodes.push(serializedChildNode); - } - } - } - if (serializedNode.type === exports.NodeType.Element && - serializedNode.tagName === 'iframe') { - var iframeDoc = n.contentDocument; - if (iframeDoc) { - var serializedIframeNode = serializeNodeWithId(iframeDoc, iframeDoc, map, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas); - if (serializedIframeNode) { - serializedNode.childNodes.push(serializedIframeNode); - } - } - } - return serializedNode; -} -function snapshot(n, blockClass, inlineStylesheet, maskAllInputsOrOptions, slimDOMSensibleOrOptions, recordCanvas, blockSelector, preserveWhiteSpace, onSerialize) { - if (blockClass === void 0) { blockClass = 'rr-block'; } - if (inlineStylesheet === void 0) { inlineStylesheet = true; } - if (blockSelector === void 0) { blockSelector = null; } - var idNodeMap = {}; - var maskInputOptions = maskAllInputsOrOptions === true - ? { - color: true, - date: true, - 'datetime-local': true, - email: true, - month: true, - number: true, - range: true, - search: true, - tel: true, - text: true, - time: true, - url: true, - week: true, - textarea: true, - select: true - } - : maskAllInputsOrOptions === false - ? {} - : maskAllInputsOrOptions; - var slimDOMOptions = slimDOMSensibleOrOptions === true || slimDOMSensibleOrOptions === 'all' - ? - { - script: true, - comment: true, - headFavicon: true, - headWhitespace: true, - headMetaDescKeywords: slimDOMSensibleOrOptions === 'all', - headMetaSocial: true, - headMetaRobots: true, - headMetaHttpEquiv: true, - headMetaAuthorship: true, - headMetaVerification: true - } - : slimDOMSensibleOrOptions === false - ? {} - : slimDOMSensibleOrOptions; - return [ - serializeNodeWithId(n, n, idNodeMap, blockClass, blockSelector, false, inlineStylesheet, maskInputOptions, slimDOMOptions, recordCanvas, preserveWhiteSpace, onSerialize), - idNodeMap, - ]; -} -function visitSnapshot(node, onVisit) { - function walk(current) { - onVisit(current); - if (current.type === exports.NodeType.Document || - current.type === exports.NodeType.Element) { - current.childNodes.forEach(walk); - } - } - walk(node); -} -function cleanupSnapshot() { - _id = 1; -} - -var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; -function parse(css, options) { - if (options === void 0) { options = {}; } - var lineno = 1; - var column = 1; - function updatePosition(str) { - var lines = str.match(/\n/g); - if (lines) { - lineno += lines.length; - } - var i = str.lastIndexOf('\n'); - column = i === -1 ? column + str.length : str.length - i; - } - function position() { - var start = { line: lineno, column: column }; - return function (node) { - node.position = new Position(start); - whitespace(); - return node; - }; - } - var Position = (function () { - function Position(start) { - this.start = start; - this.end = { line: lineno, column: column }; - this.source = options.source; - } - return Position; - }()); - Position.prototype.content = css; - var errorsList = []; - function error(msg) { - var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); - err.reason = msg; - err.filename = options.source; - err.line = lineno; - err.column = column; - err.source = css; - if (options.silent) { - errorsList.push(err); - } - else { - throw err; - } - } - function stylesheet() { - var rulesList = rules(); - return { - type: 'stylesheet', - stylesheet: { - source: options.source, - rules: rulesList, - parsingErrors: errorsList - } - }; - } - function open() { - return match(/^{\s*/); - } - function close() { - return match(/^}/); - } - function rules() { - var node; - var rules = []; - whitespace(); - comments(rules); - while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { - if (node !== false) { - rules.push(node); - comments(rules); - } - } - return rules; - } - function match(re) { - var m = re.exec(css); - if (!m) { - return; - } - var str = m[0]; - updatePosition(str); - css = css.slice(str.length); - return m; - } - function whitespace() { - match(/^\s*/); - } - function comments(rules) { - if (rules === void 0) { rules = []; } - var c; - while ((c = comment())) { - if (c !== false) { - rules.push(c); - } - c = comment(); - } - return rules; - } - function comment() { - var pos = position(); - if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { - return; - } - var i = 2; - while ('' !== css.charAt(i) && - ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))) { - ++i; - } - i += 2; - if ('' === css.charAt(i - 1)) { - return error('End of comment missing'); - } - var str = css.slice(2, i - 2); - column += 2; - updatePosition(str); - css = css.slice(i); - column += 2; - return pos({ - type: 'comment', - comment: str - }); - } - function selector() { - var m = match(/^([^{]+)/); - if (!m) { - return; - } - return trim(m[0]) - .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') - .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) { - return m.replace(/,/g, '\u200C'); - }) - .split(/\s*(?![^(]*\)),\s*/) - .map(function (s) { - return s.replace(/\u200C/g, ','); - }); - } - function declaration() { - var pos = position(); - var propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); - if (!propMatch) { - return; - } - var prop = trim(propMatch[0]); - if (!match(/^:\s*/)) { - return error("property missing ':'"); - } - var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); - var ret = pos({ - type: 'declaration', - property: prop.replace(commentre, ''), - value: val ? trim(val[0]).replace(commentre, '') : '' - }); - match(/^[;\s]*/); - return ret; - } - function declarations() { - var decls = []; - if (!open()) { - return error("missing '{'"); - } - comments(decls); - var decl; - while ((decl = declaration())) { - if (decl !== false) { - decls.push(decl); - comments(decls); - } - decl = declaration(); - } - if (!close()) { - return error("missing '}'"); - } - return decls; - } - function keyframe() { - var m; - var vals = []; - var pos = position(); - while ((m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/))) { - vals.push(m[1]); - match(/^,\s*/); - } - if (!vals.length) { - return; - } - return pos({ - type: 'keyframe', - values: vals, - declarations: declarations() - }); - } - function atkeyframes() { - var pos = position(); - var m = match(/^@([-\w]+)?keyframes\s*/); - if (!m) { - return; - } - var vendor = m[1]; - m = match(/^([-\w]+)\s*/); - if (!m) { - return error('@keyframes missing name'); - } - var name = m[1]; - if (!open()) { - return error("@keyframes missing '{'"); - } - var frame; - var frames = comments(); - while ((frame = keyframe())) { - frames.push(frame); - frames = frames.concat(comments()); - } - if (!close()) { - return error("@keyframes missing '}'"); - } - return pos({ - type: 'keyframes', - name: name, - vendor: vendor, - keyframes: frames - }); - } - function atsupports() { - var pos = position(); - var m = match(/^@supports *([^{]+)/); - if (!m) { - return; - } - var supports = trim(m[1]); - if (!open()) { - return error("@supports missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@supports missing '}'"); - } - return pos({ - type: 'supports', - supports: supports, - rules: style - }); - } - function athost() { - var pos = position(); - var m = match(/^@host\s*/); - if (!m) { - return; - } - if (!open()) { - return error("@host missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@host missing '}'"); - } - return pos({ - type: 'host', - rules: style - }); - } - function atmedia() { - var pos = position(); - var m = match(/^@media *([^{]+)/); - if (!m) { - return; - } - var media = trim(m[1]); - if (!open()) { - return error("@media missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@media missing '}'"); - } - return pos({ - type: 'media', - media: media, - rules: style - }); - } - function atcustommedia() { - var pos = position(); - var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); - if (!m) { - return; - } - return pos({ - type: 'custom-media', - name: trim(m[1]), - media: trim(m[2]) - }); - } - function atpage() { - var pos = position(); - var m = match(/^@page */); - if (!m) { - return; - } - var sel = selector() || []; - if (!open()) { - return error("@page missing '{'"); - } - var decls = comments(); - var decl; - while ((decl = declaration())) { - decls.push(decl); - decls = decls.concat(comments()); - } - if (!close()) { - return error("@page missing '}'"); - } - return pos({ - type: 'page', - selectors: sel, - declarations: decls - }); - } - function atdocument() { - var pos = position(); - var m = match(/^@([-\w]+)?document *([^{]+)/); - if (!m) { - return; - } - var vendor = trim(m[1]); - var doc = trim(m[2]); - if (!open()) { - return error("@document missing '{'"); - } - var style = comments().concat(rules()); - if (!close()) { - return error("@document missing '}'"); - } - return pos({ - type: 'document', - document: doc, - vendor: vendor, - rules: style - }); - } - function atfontface() { - var pos = position(); - var m = match(/^@font-face\s*/); - if (!m) { - return; - } - if (!open()) { - return error("@font-face missing '{'"); - } - var decls = comments(); - var decl; - while ((decl = declaration())) { - decls.push(decl); - decls = decls.concat(comments()); - } - if (!close()) { - return error("@font-face missing '}'"); - } - return pos({ - type: 'font-face', - declarations: decls - }); - } - var atimport = _compileAtrule('import'); - var atcharset = _compileAtrule('charset'); - var atnamespace = _compileAtrule('namespace'); - function _compileAtrule(name) { - var re = new RegExp('^@' + name + '\\s*([^;]+);'); - return function () { - var pos = position(); - var m = match(re); - if (!m) { - return; - } - var ret = { type: name }; - ret[name] = m[1].trim(); - return pos(ret); - }; - } - function atrule() { - if (css[0] !== '@') { - return; - } - return (atkeyframes() || - atmedia() || - atcustommedia() || - atsupports() || - atimport() || - atcharset() || - atnamespace() || - atdocument() || - atpage() || - athost() || - atfontface()); - } - function rule() { - var pos = position(); - var sel = selector(); - if (!sel) { - return error('selector missing'); - } - comments(); - return pos({ - type: 'rule', - selectors: sel, - declarations: declarations() - }); - } - return addParent(stylesheet()); -} -function trim(str) { - return str ? str.replace(/^\s+|\s+$/g, '') : ''; -} -function addParent(obj, parent) { - var isNode = obj && typeof obj.type === 'string'; - var childParent = isNode ? obj : parent; - for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { - var k = _a[_i]; - var value = obj[k]; - if (Array.isArray(value)) { - value.forEach(function (v) { - addParent(v, childParent); - }); - } - else if (value && typeof value === 'object') { - addParent(value, childParent); - } - } - if (isNode) { - Object.defineProperty(obj, 'parent', { - configurable: true, - writable: true, - enumerable: false, - value: parent || null - }); - } - return obj; -} - -var tagMap = { - script: 'noscript', - altglyph: 'altGlyph', - altglyphdef: 'altGlyphDef', - altglyphitem: 'altGlyphItem', - animatecolor: 'animateColor', - animatemotion: 'animateMotion', - animatetransform: 'animateTransform', - clippath: 'clipPath', - feblend: 'feBlend', - fecolormatrix: 'feColorMatrix', - fecomponenttransfer: 'feComponentTransfer', - fecomposite: 'feComposite', - feconvolvematrix: 'feConvolveMatrix', - fediffuselighting: 'feDiffuseLighting', - fedisplacementmap: 'feDisplacementMap', - fedistantlight: 'feDistantLight', - fedropshadow: 'feDropShadow', - feflood: 'feFlood', - fefunca: 'feFuncA', - fefuncb: 'feFuncB', - fefuncg: 'feFuncG', - fefuncr: 'feFuncR', - fegaussianblur: 'feGaussianBlur', - feimage: 'feImage', - femerge: 'feMerge', - femergenode: 'feMergeNode', - femorphology: 'feMorphology', - feoffset: 'feOffset', - fepointlight: 'fePointLight', - fespecularlighting: 'feSpecularLighting', - fespotlight: 'feSpotLight', - fetile: 'feTile', - feturbulence: 'feTurbulence', - foreignobject: 'foreignObject', - glyphref: 'glyphRef', - lineargradient: 'linearGradient', - radialgradient: 'radialGradient' -}; -function getTagName(n) { - var tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; - if (tagName === 'link' && n.attributes._cssText) { - tagName = 'style'; - } - return tagName; -} -var HOVER_SELECTOR = /([^\\]):hover/g; -function addHoverClass(cssText) { - var ast = parse(cssText, { silent: true }); - if (!ast.stylesheet) { - return cssText; - } - ast.stylesheet.rules.forEach(function (rule) { - if ('selectors' in rule) { - (rule.selectors || []).forEach(function (selector) { - if (HOVER_SELECTOR.test(selector)) { - var newSelector = selector.replace(HOVER_SELECTOR, '$1.\\:hover'); - cssText = cssText.replace(selector, selector + ", " + newSelector); - } - }); - } - }); - return cssText; -} -function isIframe(n) { - return n.type === exports.NodeType.Element && n.tagName === 'iframe'; -} -function buildIframe(iframe, childNodes, map, cbs, HACK_CSS) { - var targetDoc = iframe.contentDocument; - for (var _i = 0, childNodes_1 = childNodes; _i < childNodes_1.length; _i++) { - var childN = childNodes_1[_i]; - console.log('build iframe', childN); - buildNodeWithSN(childN, targetDoc, map, cbs, false, HACK_CSS); - } -} -function buildNode(n, doc, HACK_CSS) { - switch (n.type) { - case exports.NodeType.Document: - return doc.implementation.createDocument(null, '', null); - case exports.NodeType.DocumentType: - return doc.implementation.createDocumentType(n.name || 'html', n.publicId, n.systemId); - case exports.NodeType.Element: - var tagName = getTagName(n); - var node_1; - if (n.isSVG) { - node_1 = doc.createElementNS('http://www.w3.org/2000/svg', tagName); - } - else { - node_1 = doc.createElement(tagName); - } - var _loop_1 = function (name) { - if (!n.attributes.hasOwnProperty(name)) { - return "continue"; - } - var value = n.attributes[name]; - value = - typeof value === 'boolean' || typeof value === 'number' ? '' : value; - if (!name.startsWith('rr_')) { - var isTextarea = tagName === 'textarea' && name === 'value'; - var isRemoteOrDynamicCss = tagName === 'style' && name === '_cssText'; - if (isRemoteOrDynamicCss && HACK_CSS) { - value = addHoverClass(value); - } - if (isTextarea || isRemoteOrDynamicCss) { - var child = doc.createTextNode(value); - for (var _i = 0, _a = Array.from(node_1.childNodes); _i < _a.length; _i++) { - var c = _a[_i]; - if (c.nodeType === node_1.TEXT_NODE) { - node_1.removeChild(c); - } - } - node_1.appendChild(child); - return "continue"; - } - if (tagName === 'iframe' && name === 'src') { - return "continue"; - } - try { - if (n.isSVG && name === 'xlink:href') { - node_1.setAttributeNS('http://www.w3.org/1999/xlink', name, value); - } - else if (name === 'onload' || - name === 'onclick' || - name.substring(0, 7) === 'onmouse') { - node_1.setAttribute('_' + name, value); - } - else { - node_1.setAttribute(name, value); - } - } - catch (error) { - } - } - else { - if (tagName === 'canvas' && name === 'rr_dataURL') { - var image_1 = document.createElement('img'); - image_1.src = value; - image_1.onload = function () { - var ctx = node_1.getContext('2d'); - if (ctx) { - ctx.drawImage(image_1, 0, 0, image_1.width, image_1.height); - } - }; - } - if (name === 'rr_width') { - node_1.style.width = value; - } - if (name === 'rr_height') { - node_1.style.height = value; - } - if (name === 'rr_mediaState') { - switch (value) { - case 'played': - node_1.play(); - case 'paused': - node_1.pause(); - break; - default: - } - } - } - }; - for (var name in n.attributes) { - _loop_1(name); - } - return node_1; - case exports.NodeType.Text: - return doc.createTextNode(n.isStyle && HACK_CSS ? addHoverClass(n.textContent) : n.textContent); - case exports.NodeType.CDATA: - return doc.createCDATASection(n.textContent); - case exports.NodeType.Comment: - return doc.createComment(n.textContent); - default: - return null; - } -} -function buildNodeWithSN(n, doc, map, cbs, skipChild, HACK_CSS) { - if (skipChild === void 0) { skipChild = false; } - if (HACK_CSS === void 0) { HACK_CSS = true; } - var node = buildNode(n, doc, HACK_CSS); - if (!node) { - return [null, []]; - } - if (n.rootId) { - console.assert(map[n.rootId] === doc, 'Target document should has the same root id.'); - } - if (n.type === exports.NodeType.Document) { - doc.close(); - doc.open(); - node = doc; - } - node.__sn = n; - map[n.id] = node; - var nodeIsIframe = isIframe(n); - if (n.type === exports.NodeType.Element && nodeIsIframe) { - return [node, n.childNodes]; - } - if ((n.type === exports.NodeType.Document || n.type === exports.NodeType.Element) && - !skipChild) { - var _loop_2 = function (childN) { - var _a = buildNodeWithSN(childN, doc, map, cbs, false, HACK_CSS), childNode = _a[0], nestedNodes = _a[1]; - if (!childNode) { - console.warn('Failed to rebuild', childN); - return "continue"; - } - node.appendChild(childNode); - if (nestedNodes.length === 0) { - return "continue"; - } - var childNodeIsIframe = isIframe(childN); - if (childNodeIsIframe) { - cbs.push(function () { - return buildIframe(childNode, nestedNodes, map, cbs, HACK_CSS); - }); - } - }; - for (var _i = 0, _a = n.childNodes; _i < _a.length; _i++) { - var childN = _a[_i]; - _loop_2(childN); - } - } - return [node, []]; -} -function visit(idNodeMap, onVisit) { - function walk(node) { - onVisit(node); - } - for (var key in idNodeMap) { - if (idNodeMap[key]) { - walk(idNodeMap[key]); - } - } -} -function handleScroll(node) { - var n = node.__sn; - if (n.type !== exports.NodeType.Element) { - return; - } - var el = node; - for (var name in n.attributes) { - if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) { - continue; - } - var value = n.attributes[name]; - if (name === 'rr_scrollLeft') { - el.scrollLeft = value; - } - if (name === 'rr_scrollTop') { - el.scrollTop = value; - } - } -} -function rebuild(n, doc, onVisit, HACK_CSS) { - if (HACK_CSS === void 0) { HACK_CSS = true; } - var idNodeMap = {}; - var callbackArray = []; - var node = buildNodeWithSN(n, doc, idNodeMap, callbackArray, false, HACK_CSS)[0]; - callbackArray.forEach(function (f) { return f(); }); - visit(idNodeMap, function (visitedNode) { - if (onVisit) { - onVisit(visitedNode); - } - handleScroll(visitedNode); - }); - return [node, idNodeMap]; -} - -exports.snapshot = snapshot; -exports.serializeNodeWithId = serializeNodeWithId; -exports.rebuild = rebuild; -exports.buildNodeWithSN = buildNodeWithSN; -exports.addHoverClass = addHoverClass; -exports.transformAttribute = transformAttribute; -exports.visitSnapshot = visitSnapshot; -exports.cleanupSnapshot = cleanupSnapshot; -exports.IGNORED_NODE = IGNORED_NODE; From a4b4d08211452292007d7f0fc39305519c79a507 Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Sun, 7 Feb 2021 12:14:12 +0800 Subject: [PATCH 5/6] refactor iframe impl 1. do callback one iframe is loaded, let rrweb handle the rest 2. handle iframe as normal element in rebuild --- src/rebuild.ts | 63 ++---------- src/snapshot.ts | 79 +++++++++++---- test/__snapshots__/integration.ts.snap | 132 +++++++++++++++++++++++++ test/iframe-html/frame1.html | 13 +++ test/iframe-html/frame2.html | 11 +++ test/iframe-html/main.html | 12 +++ test/integration.ts | 47 +++++++++ typings/snapshot.d.ts | 2 + 8 files changed, 286 insertions(+), 73 deletions(-) create mode 100644 test/iframe-html/frame1.html create mode 100644 test/iframe-html/frame2.html create mode 100644 test/iframe-html/main.html diff --git a/src/rebuild.ts b/src/rebuild.ts index 8471492..ae7fd76 100644 --- a/src/rebuild.ts +++ b/src/rebuild.ts @@ -6,7 +6,6 @@ import { elementNode, idNodeMap, INode, - CallbackArray, } from './types'; const tagMap: tagMap = { @@ -76,32 +75,6 @@ export function addHoverClass(cssText: string): string { return cssText; } -function isIframe(n: serializedNodeWithId) { - return n.type === NodeType.Element && n.tagName === 'iframe'; -} - -function buildIframe( - iframe: HTMLIFrameElement, - childNodes: serializedNodeWithId[], - options: { - map: idNodeMap; - cbs: CallbackArray; - hackCss: boolean; - }, -) { - const { map, cbs, hackCss } = options; - const targetDoc = iframe.contentDocument!; - for (const childN of childNodes) { - buildNodeWithSN(childN, { - doc: targetDoc, - map, - cbs, - skipChild: false, - hackCss, - }); - } -} - function buildNode( n: serializedNodeWithId, options: { @@ -223,15 +196,14 @@ export function buildNodeWithSN( options: { doc: Document; map: idNodeMap; - cbs: CallbackArray; skipChild?: boolean; hackCss: boolean; }, -): [INode | null, serializedNodeWithId[]] { - const { doc, map, skipChild = false, hackCss = true, cbs } = options; +): INode | null { + const { doc, map, skipChild = false, hackCss = true } = options; let node = buildNode(n, { doc, hackCss }); if (!node) { - return [null, []]; + return null; } if (n.rootId) { console.assert( @@ -250,20 +222,14 @@ export function buildNodeWithSN( (node as INode).__sn = n; map[n.id] = node as INode; - const nodeIsIframe = isIframe(n); - if (n.type === NodeType.Element && nodeIsIframe) { - return [node as INode, n.childNodes]; - } - if ( (n.type === NodeType.Document || n.type === NodeType.Element) && !skipChild ) { for (const childN of n.childNodes) { - const [childNode, nestedNodes] = buildNodeWithSN(childN, { + const childNode = buildNodeWithSN(childN, { doc, map, - cbs, skipChild: false, hackCss, }); @@ -273,22 +239,10 @@ export function buildNodeWithSN( } node.appendChild(childNode); - if (nestedNodes.length === 0) { - continue; - } - const childNodeIsIframe = isIframe(childN); - if (childNodeIsIframe) { - cbs.push(() => - buildIframe( - (childNode as unknown) as HTMLIFrameElement, - nestedNodes, - { map, cbs, hackCss }, - ), - ); - } } } - return [node as INode, []]; + + return node as INode; } function visit(idNodeMap: idNodeMap, onVisit: (node: INode) => void) { @@ -333,15 +287,12 @@ function rebuild( ): [Node | null, idNodeMap] { const { doc, onVisit, hackCss = true } = options; const idNodeMap: idNodeMap = {}; - const callbackArray: CallbackArray = []; - const [node] = buildNodeWithSN(n, { + const node = buildNodeWithSN(n, { doc, map: idNodeMap, - cbs: callbackArray, skipChild: false, hackCss, }); - callbackArray.forEach((f) => f()); visit(idNodeMap, (visitedNode) => { if (onVisit) { onVisit(visitedNode); diff --git a/src/snapshot.ts b/src/snapshot.ts index a29c046..9ddc39d 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -196,6 +196,34 @@ export function _isBlockedElement( return false; } +// https://stackoverflow.com/a/36155560 +function onceIframeLoaded( + iframeEl: HTMLIFrameElement, + listener: () => unknown, +) { + const win = iframeEl.contentWindow; + if (!win) { + return; + } + // document is loading + if (win.document.readyState !== 'complete') { + iframeEl.addEventListener('load', listener); + return; + } + // check blank frame for Chrome + const blankUrl = 'about:blank'; + if ( + win.location.href !== blankUrl || + iframeEl.src === blankUrl || + iframeEl.src === '' + ) { + listener(); + return; + } + // use default listener + iframeEl.addEventListener('load', listener); +} + function serializeNode( n: Node, options: { @@ -326,6 +354,7 @@ function serializeNode( if ((n as HTMLElement).scrollTop) { attributes.rr_scrollTop = (n as HTMLElement).scrollTop; } + // block element if (needBlock) { const { width, height } = (n as HTMLElement).getBoundingClientRect(); attributes = { @@ -334,6 +363,10 @@ function serializeNode( rr_height: `${height}px`, }; } + // iframe + if (tagName === 'iframe') { + delete attributes.src; + } return { type: NodeType.Element, tagName, @@ -485,6 +518,7 @@ export function serializeNodeWithId( recordCanvas?: boolean; preserveWhiteSpace?: boolean; onSerialize?: (n: INode) => unknown; + onIframeLoad?: (iframeINode: INode, node: serializedNodeWithId) => unknown; }, ): serializedNodeWithId | null { const { @@ -498,6 +532,7 @@ export function serializeNodeWithId( slimDOMOptions, recordCanvas = false, onSerialize, + onIframeLoad, } = options; let { preserveWhiteSpace = true } = options; const _serializedNode = serializeNode(n, { @@ -569,6 +604,8 @@ export function serializeNodeWithId( slimDOMOptions, recordCanvas, preserveWhiteSpace, + onSerialize, + onIframeLoad, }); if (serializedChildNode) { serializedNode.childNodes.push(serializedChildNode); @@ -580,24 +617,29 @@ export function serializeNodeWithId( serializedNode.type === NodeType.Element && serializedNode.tagName === 'iframe' ) { - const iframeDoc = (n as HTMLIFrameElement).contentDocument; - if (iframeDoc) { - const serializedIframeNode = serializeNodeWithId(iframeDoc, { - doc: iframeDoc, - map, - blockClass, - blockSelector, - skipChild: false, - inlineStylesheet, - maskInputOptions, - slimDOMOptions, - recordCanvas, - preserveWhiteSpace, - }); - if (serializedIframeNode) { - serializedNode.childNodes.push(serializedIframeNode); + onceIframeLoaded(n as HTMLIFrameElement, () => { + const iframeDoc = (n as HTMLIFrameElement).contentDocument; + if (iframeDoc && onIframeLoad) { + const serializedIframeNode = serializeNodeWithId(iframeDoc, { + doc: iframeDoc, + map, + blockClass, + blockSelector, + skipChild: false, + inlineStylesheet, + maskInputOptions, + slimDOMOptions, + recordCanvas, + preserveWhiteSpace, + onSerialize, + onIframeLoad, + }); + + if (serializedIframeNode) { + onIframeLoad(n as INode, serializedIframeNode); + } } - } + }); } return serializedNode; @@ -614,6 +656,7 @@ function snapshot( blockSelector?: string | null; preserveWhiteSpace?: boolean; onSerialize?: (n: INode) => unknown; + onIframeLoad?: (iframeINode: INode, node: serializedNodeWithId) => unknown; }, ): [serializedNodeWithId | null, idNodeMap] { const { @@ -625,6 +668,7 @@ function snapshot( slimDOM = false, preserveWhiteSpace, onSerialize, + onIframeLoad, } = options || {}; const idNodeMap: idNodeMap = {}; const maskInputOptions: MaskInputOptions = @@ -680,6 +724,7 @@ function snapshot( recordCanvas, preserveWhiteSpace, onSerialize, + onIframeLoad, }), idNodeMap, ]; diff --git a/test/__snapshots__/integration.ts.snap b/test/__snapshots__/integration.ts.snap index d7d76c6..75734c1 100644 --- a/test/__snapshots__/integration.ts.snap +++ b/test/__snapshots__/integration.ts.snap @@ -277,3 +277,135 @@ exports[`[html file]: with-style-sheet-with-import.html 1`] = ` " `; + +exports[`iframe integration tests 1`] = ` +"{ + \\"type\\": 0, + \\"childNodes\\": [ + { + \\"type\\": 1, + \\"name\\": \\"html\\", + \\"publicId\\": \\"\\", + \\"systemId\\": \\"\\", + \\"id\\": 2 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"html\\", + \\"attributes\\": { + \\"lang\\": \\"en\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 2, + \\"tagName\\": \\"head\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 5 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"meta\\", + \\"attributes\\": { + \\"charset\\": \\"UTF-8\\" + }, + \\"childNodes\\": [], + \\"id\\": 6 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 7 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"meta\\", + \\"attributes\\": { + \\"name\\": \\"viewport\\", + \\"content\\": \\"width=device-width, initial-scale=1.0\\" + }, + \\"childNodes\\": [], + \\"id\\": 8 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 9 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"title\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"Main\\", + \\"id\\": 11 + } + ], + \\"id\\": 10 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 12 + } + ], + \\"id\\": 4 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 13 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"body\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 15 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"iframe\\", + \\"attributes\\": { + \\"id\\": \\"one\\" + }, + \\"childNodes\\": [], + \\"id\\": 16 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 17 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"iframe\\", + \\"attributes\\": { + \\"id\\": \\"two\\" + }, + \\"childNodes\\": [], + \\"id\\": 18 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\\\n\\\\n\\", + \\"id\\": 19 + } + ], + \\"id\\": 14 + } + ], + \\"id\\": 3 + } + ], + \\"id\\": 1 +}" +`; diff --git a/test/iframe-html/frame1.html b/test/iframe-html/frame1.html new file mode 100644 index 0000000..8810af4 --- /dev/null +++ b/test/iframe-html/frame1.html @@ -0,0 +1,13 @@ + + + + + + Frame 1 + + + frame 1 + + + + diff --git a/test/iframe-html/frame2.html b/test/iframe-html/frame2.html new file mode 100644 index 0000000..3432408 --- /dev/null +++ b/test/iframe-html/frame2.html @@ -0,0 +1,11 @@ + + + + + + Frame 2 + + + frame 2 + + diff --git a/test/iframe-html/main.html b/test/iframe-html/main.html new file mode 100644 index 0000000..d8e712b --- /dev/null +++ b/test/iframe-html/main.html @@ -0,0 +1,12 @@ + + + + + + Main + + + + + + diff --git a/test/integration.ts b/test/integration.ts index ddfb5bc..807639f 100644 --- a/test/integration.ts +++ b/test/integration.ts @@ -119,3 +119,50 @@ describe('integration tests', function (this: ISuite) { }).timeout(5000); } }); + +describe('iframe integration tests', function (this: ISuite) { + const iframeHtml = path.join(__dirname, 'iframe-html/main.html'); + const raw = fs.readFileSync(iframeHtml, 'utf-8'); + + before(async () => { + this.server = await server(); + this.browser = await puppeteer.launch({ + // headless: false, + }); + + const bundle = await rollup.rollup({ + input: path.resolve(__dirname, '../src/index.ts'), + plugins: [typescript()], + }); + const { code } = await bundle.generate({ + name: 'rrweb', + format: 'iife', + }); + this.code = code; + }); + + after(async () => { + await this.browser.close(); + await this.server.close(); + }); + + it('snapshot async iframes', async () => { + const page: puppeteer.Page = await this.browser.newPage(); + // console for debug + // tslint:disable-next-line: no-console + page.on('console', (msg) => console.log(msg.text())); + await page.goto(`http://localhost:3030/html`); + await page.setContent(raw, { + waitUntil: 'load', + }); + const snapshotResult = JSON.stringify( + await page.evaluate(`${this.code}; + rrweb.snapshot(document)[0]; + `), + null, + 2, + ); + const result = matchSnapshot(snapshotResult, __filename, this.title); + assert(result.pass, result.pass ? '' : result.report()); + }).timeout(5000); +}); diff --git a/typings/snapshot.d.ts b/typings/snapshot.d.ts index db2bff7..053e3a1 100644 --- a/typings/snapshot.d.ts +++ b/typings/snapshot.d.ts @@ -16,6 +16,7 @@ export declare function serializeNodeWithId(n: Node | INode, options: { recordCanvas?: boolean; preserveWhiteSpace?: boolean; onSerialize?: (n: INode) => unknown; + onIframeLoad?: (iframeINode: INode, node: serializedNodeWithId) => unknown; }): serializedNodeWithId | null; declare function snapshot(n: Document, options?: { blockClass?: string | RegExp; @@ -26,6 +27,7 @@ declare function snapshot(n: Document, options?: { blockSelector?: string | null; preserveWhiteSpace?: boolean; onSerialize?: (n: INode) => unknown; + onIframeLoad?: (iframeINode: INode, node: serializedNodeWithId) => unknown; }): [serializedNodeWithId | null, idNodeMap]; export declare function visitSnapshot(node: serializedNodeWithId, onVisit: (node: serializedNodeWithId) => unknown): void; export declare function cleanupSnapshot(): void; From cf4063c0113bc9949959b0a8a309a8922417ceac Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Sun, 7 Feb 2021 13:56:06 +0800 Subject: [PATCH 6/6] rename hook function --- src/rebuild.ts | 11 +++++++++-- src/types.ts | 2 -- typings/rebuild.d.ts | 7 ++++--- typings/types.d.ts | 1 - 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/rebuild.ts b/src/rebuild.ts index ae7fd76..8091be3 100644 --- a/src/rebuild.ts +++ b/src/rebuild.ts @@ -198,9 +198,10 @@ export function buildNodeWithSN( map: idNodeMap; skipChild?: boolean; hackCss: boolean; + afterAppend?: (n: INode) => unknown; }, ): INode | null { - const { doc, map, skipChild = false, hackCss = true } = options; + const { doc, map, skipChild = false, hackCss = true, afterAppend } = options; let node = buildNode(n, { doc, hackCss }); if (!node) { return null; @@ -232,6 +233,7 @@ export function buildNodeWithSN( map, skipChild: false, hackCss, + afterAppend, }); if (!childNode) { console.warn('Failed to rebuild', childN); @@ -239,6 +241,9 @@ export function buildNodeWithSN( } node.appendChild(childNode); + if (afterAppend) { + afterAppend(childNode); + } } } @@ -283,15 +288,17 @@ function rebuild( doc: Document; onVisit?: (node: INode) => unknown; hackCss?: boolean; + afterAppend?: (n: INode) => unknown; }, ): [Node | null, idNodeMap] { - const { doc, onVisit, hackCss = true } = options; + const { doc, onVisit, hackCss = true, afterAppend } = options; const idNodeMap: idNodeMap = {}; const node = buildNodeWithSN(n, { doc, map: idNodeMap, skipChild: false, hackCss, + afterAppend, }); visit(idNodeMap, (visitedNode) => { if (onVisit) { diff --git a/src/types.ts b/src/types.ts index 12aed75..3ae2d76 100644 --- a/src/types.ts +++ b/src/types.ts @@ -103,5 +103,3 @@ export type SlimDOMOptions = Partial<{ headMetaAuthorship: boolean; headMetaVerification: boolean; }>; - -export type CallbackArray = T[]; diff --git a/typings/rebuild.d.ts b/typings/rebuild.d.ts index ad26d99..6ab9f04 100644 --- a/typings/rebuild.d.ts +++ b/typings/rebuild.d.ts @@ -1,15 +1,16 @@ -import { serializedNodeWithId, idNodeMap, INode, CallbackArray } from './types'; +import { serializedNodeWithId, idNodeMap, INode } from './types'; export declare function addHoverClass(cssText: string): string; export declare function buildNodeWithSN(n: serializedNodeWithId, options: { doc: Document; map: idNodeMap; - cbs: CallbackArray; skipChild?: boolean; hackCss: boolean; -}): [INode | null, serializedNodeWithId[]]; + afterAppend?: (n: INode) => unknown; +}): INode | null; declare function rebuild(n: serializedNodeWithId, options: { doc: Document; onVisit?: (node: INode) => unknown; hackCss?: boolean; + afterAppend?: (n: INode) => unknown; }): [Node | null, idNodeMap]; export default rebuild; diff --git a/typings/types.d.ts b/typings/types.d.ts index 1516929..8efab81 100644 --- a/typings/types.d.ts +++ b/typings/types.d.ts @@ -84,4 +84,3 @@ export declare type SlimDOMOptions = Partial<{ headMetaAuthorship: boolean; headMetaVerification: boolean; }>; -export declare type CallbackArray = T[];