@posthog/rrweb-snapshot 0.0.49 → 0.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -612,7 +612,9 @@ function slimDOMExcluded(sn, slimDOMOptions) {
612
612
  return true;
613
613
  } else if (slimDOMOptions.headFavicon && (sn.tagName === "link" && sn.attributes.rel === "shortcut icon" || sn.tagName === "meta" && (lowerIfExists(sn.attributes.name).match(
614
614
  /^msapplication-tile(image|color)$/
615
- ) || lowerIfExists(sn.attributes.name) === "application-name" || lowerIfExists(sn.attributes.rel) === "icon" || lowerIfExists(sn.attributes.rel) === "apple-touch-icon" || lowerIfExists(sn.attributes.rel) === "shortcut icon"))) {
615
+ ) || lowerIfExists(sn.attributes.name) === "application-name" || ["icon", "apple-touch-icon", "shortcut icon"].includes(
616
+ lowerIfExists(sn.attributes.rel)
617
+ )))) {
616
618
  return true;
617
619
  } else if (sn.tagName === "meta") {
618
620
  if (slimDOMOptions.headMetaDescKeywords && lowerIfExists(sn.attributes.name).match(/^description|keywords$/)) {
@@ -620,13 +622,25 @@ function slimDOMExcluded(sn, slimDOMOptions) {
620
622
  } else if (slimDOMOptions.headMetaSocial && (lowerIfExists(sn.attributes.property).match(/^(og|twitter|fb):/) || // og = opengraph (facebook)
621
623
  lowerIfExists(sn.attributes.name).match(/^(og|twitter):/) || lowerIfExists(sn.attributes.name) === "pinterest")) {
622
624
  return true;
623
- } else if (slimDOMOptions.headMetaRobots && (lowerIfExists(sn.attributes.name) === "robots" || lowerIfExists(sn.attributes.name) === "googlebot" || lowerIfExists(sn.attributes.name) === "bingbot")) {
625
+ } else if (slimDOMOptions.headMetaRobots && ["robots", "googlebot", "bingbot"].includes(
626
+ lowerIfExists(sn.attributes.name)
627
+ )) {
624
628
  return true;
625
629
  } else if (slimDOMOptions.headMetaHttpEquiv && sn.attributes["http-equiv"] !== void 0) {
626
630
  return true;
627
- } 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:/))) {
631
+ } else if (slimDOMOptions.headMetaAuthorship && (["author", "generator", "framework", "publisher", "progid"].includes(
632
+ lowerIfExists(sn.attributes.name)
633
+ ) || lowerIfExists(sn.attributes.property).match(/^article:/) || lowerIfExists(sn.attributes.property).match(/^product:/))) {
628
634
  return true;
629
- } 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")) {
635
+ } else if (slimDOMOptions.headMetaVerification && [
636
+ "google-site-verification",
637
+ "yandex-verification",
638
+ "csrf-token",
639
+ "p:domain_verify",
640
+ "verify-v1",
641
+ "verification",
642
+ "shopify-checkout-api-token"
643
+ ].includes(lowerIfExists(sn.attributes.name))) {
630
644
  return true;
631
645
  }
632
646
  }
@@ -879,6 +893,27 @@ function serializeNodeWithId(n, options) {
879
893
  }
880
894
  return serializedNode;
881
895
  }
896
+ function slimDOMDefaults(slimDOM) {
897
+ if (slimDOM === true || slimDOM === "all") {
898
+ return {
899
+ script: true,
900
+ comment: true,
901
+ headFavicon: true,
902
+ headWhitespace: true,
903
+ headMetaSocial: true,
904
+ headMetaRobots: true,
905
+ headMetaHttpEquiv: true,
906
+ headMetaVerification: true,
907
+ headMetaAuthorship: slimDOM === "all",
908
+ headMetaDescKeywords: slimDOM === "all",
909
+ headTitleMutations: slimDOM === "all"
910
+ };
911
+ }
912
+ if (slimDOM === false) {
913
+ return {};
914
+ }
915
+ return slimDOM;
916
+ }
882
917
  function snapshot(n, options) {
883
918
  const {
884
919
  mirror = new types.Mirror(),
@@ -923,22 +958,7 @@ function snapshot(n, options) {
923
958
  } : maskAllInputs === false ? {
924
959
  password: true
925
960
  } : maskAllInputs;
926
- const slimDOMOptions = slimDOM === true || slimDOM === "all" ? (
927
- // if true: set of sensible options that should not throw away any information
928
- {
929
- script: true,
930
- comment: true,
931
- headFavicon: true,
932
- headWhitespace: true,
933
- headMetaDescKeywords: slimDOM === "all",
934
- // destructive
935
- headMetaSocial: true,
936
- headMetaRobots: true,
937
- headMetaHttpEquiv: true,
938
- headMetaAuthorship: true,
939
- headMetaVerification: true
940
- }
941
- ) : slimDOM === false ? {} : slimDOM;
961
+ const slimDOMOptions = slimDOMDefaults(slimDOM);
942
962
  return serializeNodeWithId(n, {
943
963
  doc: n,
944
964
  mirror,
@@ -987,8 +1007,9 @@ exports.ignoreAttribute = ignoreAttribute;
987
1007
  exports.needMaskingText = needMaskingText;
988
1008
  exports.resetMaxDepthState = resetMaxDepthState;
989
1009
  exports.serializeNodeWithId = serializeNodeWithId;
1010
+ exports.slimDOMDefaults = slimDOMDefaults;
990
1011
  exports.snapshot = snapshot;
991
1012
  exports.transformAttribute = transformAttribute;
992
1013
  exports.visitSnapshot = visitSnapshot;
993
1014
  exports.wasMaxDepthReached = wasMaxDepthReached;
994
- //# sourceMappingURL=record-oACzRSl-.cjs.map
1015
+ //# sourceMappingURL=record-BUfdSR_C.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-BUfdSR_C.cjs","sources":["../src/snapshot.ts"],"sourcesContent":["import type {\n MaskInputOptions,\n SlimDOMOptions,\n MaskTextFn,\n MaskInputFn,\n KeepIframeSrcFn,\n ICanvas,\n DialogAttributes,\n} from './types';\nimport { NodeType } from '@posthog/rrweb-types';\nimport type {\n serializedNode,\n serializedNodeWithId,\n serializedElementNodeWithId,\n elementNode,\n attributes,\n mediaAttributes,\n DataURLOptions,\n} from '@posthog/rrweb-types';\nimport {\n Mirror,\n is2DCanvasBlank,\n isElement,\n isShadowRoot,\n maskInputValue,\n isNativeShadowDom,\n stringifyStylesheet,\n getInputType,\n toLowerCase,\n extractFileExtension,\n checkDataURLSize,\n recompressBase64Image,\n absolutifyURLs,\n} from './utils';\nimport dom from '@posthog/rrweb-utils';\n\nlet _id = 1;\nconst tagNameRegex = new RegExp('[^a-z0-9-_:]');\n\nexport const IGNORED_NODE = -2;\n\nexport function genId(): number {\n return _id++;\n}\n\nfunction getValidTagName(element: HTMLElement): Lowercase<string> {\n if (element instanceof HTMLFormElement) {\n return 'form';\n }\n\n const processedTagName = toLowerCase(element.tagName);\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\nlet canvasService: HTMLCanvasElement | null;\nlet canvasCtx: CanvasRenderingContext2D | null;\n\n// eslint-disable-next-line no-control-regex\nconst SRCSET_NOT_SPACES = /^[^ \\t\\n\\r\\u000c]+/; // Don't use \\s, to avoid matching non-breaking space\n// eslint-disable-next-line no-control-regex\nconst SRCSET_COMMAS_OR_SPACES = /^[, \\t\\n\\r\\u000c]+/;\n\nfunction getAbsoluteSrcsetString(doc: Document, attributeValue: string) {\n /*\n run absoluteToDoc over every url in the srcset\n\n this is adapted from https://github.com/albell/parse-srcset/\n without the parsing of the descriptors (we return these as-is)\n parce-srcset is in turn based on\n https://html.spec.whatwg.org/multipage/embedded-content.html#parse-a-srcset-attribute\n */\n if (attributeValue.trim() === '') {\n return attributeValue;\n }\n\n let pos = 0;\n\n function collectCharacters(regEx: RegExp) {\n let chars: string;\n const match = regEx.exec(attributeValue.substring(pos));\n if (match) {\n chars = match[0];\n pos += chars.length;\n return chars;\n }\n return '';\n }\n\n const output = [];\n // eslint-disable-next-line no-constant-condition\n while (true) {\n collectCharacters(SRCSET_COMMAS_OR_SPACES);\n if (pos >= attributeValue.length) {\n break;\n }\n // don't split on commas within urls\n let url = collectCharacters(SRCSET_NOT_SPACES);\n if (url.slice(-1) === ',') {\n // aside: according to spec more than one comma at the end is a parse error, but we ignore that\n url = absoluteToDoc(doc, url.substring(0, url.length - 1));\n // the trailing comma splits the srcset, so the interpretion is that\n // another url will follow, and the descriptor is empty\n output.push(url);\n } else {\n let descriptorsStr = '';\n url = absoluteToDoc(doc, url);\n let inParens = false;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const c = attributeValue.charAt(pos);\n if (c === '') {\n output.push((url + descriptorsStr).trim());\n break;\n } else if (!inParens) {\n if (c === ',') {\n pos += 1;\n output.push((url + descriptorsStr).trim());\n break; // parse the next url\n } else if (c === '(') {\n inParens = true;\n }\n } else {\n // in parenthesis; ignore commas\n // (parenthesis may be supported by future additions to spec)\n if (c === ')') {\n inParens = false;\n }\n }\n descriptorsStr += c;\n pos += 1;\n }\n }\n }\n return output.join(', ');\n}\n\nconst cachedDocument = new WeakMap<Document, HTMLAnchorElement>();\n\nexport function absoluteToDoc(doc: Document, attributeValue: string): string {\n if (!attributeValue || attributeValue.trim() === '') {\n return attributeValue;\n }\n\n return getHref(doc, attributeValue);\n}\n\nfunction isSVGElement(el: Element): boolean {\n return Boolean(el.tagName === 'svg' || (el as SVGElement).ownerSVGElement);\n}\n\nfunction getHref(doc: Document, customHref?: string) {\n let a = cachedDocument.get(doc);\n if (!a) {\n a = doc.createElement('a');\n cachedDocument.set(doc, a);\n }\n if (!customHref) {\n customHref = '';\n } else if (customHref.startsWith('blob:') || customHref.startsWith('data:')) {\n return customHref;\n }\n // note: using `new URL` is slower. See #1434 or https://jsbench.me/uqlud17rxo/1\n a.setAttribute('href', customHref);\n return a.href;\n}\n\nexport function transformAttribute(\n doc: Document,\n tagName: Lowercase<string>,\n name: Lowercase<string>,\n value: string | null,\n element?: HTMLElement,\n dataURLOptions?: DataURLOptions,\n): string | null {\n if (!value) {\n return value;\n }\n\n // relative path in attribute\n if (\n name === 'src' ||\n (name === 'href' && !(tagName === 'use' && value[0] === '#'))\n ) {\n // href starts with a # is an id pointer for svg\n const transformedValue = absoluteToDoc(doc, value);\n\n if (tagName === 'img' && transformedValue.startsWith('data:') && element) {\n const img = element as HTMLImageElement;\n\n let processedDataURL = transformedValue;\n\n if (dataURLOptions?.type || dataURLOptions?.quality !== undefined) {\n processedDataURL = recompressBase64Image(\n img,\n transformedValue,\n dataURLOptions.type,\n dataURLOptions.quality,\n );\n }\n\n if (dataURLOptions?.maxBase64ImageLength) {\n processedDataURL = checkDataURLSize(\n processedDataURL,\n dataURLOptions.maxBase64ImageLength,\n );\n }\n\n return processedDataURL;\n }\n\n return transformedValue;\n } else if (name === 'xlink:href' && value[0] !== '#') {\n // xlink:href starts with # is an id pointer\n return absoluteToDoc(doc, value);\n } else if (\n name === 'background' &&\n (tagName === 'table' || tagName === 'td' || tagName === 'th')\n ) {\n return absoluteToDoc(doc, value);\n } else if (name === 'srcset') {\n return getAbsoluteSrcsetString(doc, value);\n } else if (name === 'style') {\n return absolutifyURLs(value, getHref(doc));\n } else if (tagName === 'object' && name === 'data') {\n return absoluteToDoc(doc, value);\n }\n\n return value;\n}\n\nexport function ignoreAttribute(\n tagName: string,\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _value: unknown,\n): boolean {\n return (tagName === 'video' || tagName === 'audio') && name === 'autoplay';\n}\n\nexport function _isBlockedElement(\n element: HTMLElement,\n blockClass: string | RegExp,\n blockSelector: string | null,\n): boolean {\n try {\n if (typeof blockClass === 'string') {\n if (element.classList.contains(blockClass)) {\n return true;\n }\n } else {\n for (let eIndex = element.classList.length; eIndex--; ) {\n const className = element.classList[eIndex];\n if (blockClass.test(className)) {\n return true;\n }\n }\n }\n if (blockSelector) {\n return element.matches(blockSelector);\n }\n } catch (e) {\n //\n }\n\n return false;\n}\n\nexport function classMatchesRegex(\n node: Node | null,\n regex: RegExp,\n checkAncestors: boolean,\n): boolean {\n if (!node) return false;\n if (node.nodeType !== node.ELEMENT_NODE) {\n if (!checkAncestors) return false;\n return classMatchesRegex(dom.parentNode(node), regex, checkAncestors);\n }\n\n for (let eIndex = (node as HTMLElement).classList.length; eIndex--; ) {\n const className = (node as HTMLElement).classList[eIndex];\n if (regex.test(className)) {\n return true;\n }\n }\n if (!checkAncestors) return false;\n return classMatchesRegex(dom.parentNode(node), regex, checkAncestors);\n}\n\nexport function needMaskingText(\n node: Node,\n maskTextClass: string | RegExp,\n maskTextSelector: string | null,\n checkAncestors: boolean,\n): boolean {\n let el: Element;\n if (isElement(node)) {\n el = node;\n if (!dom.childNodes(el).length) {\n // optimisation: we can avoid any of the below checks on leaf elements\n // as masking is applied to child text nodes only\n return false;\n }\n } else if (dom.parentElement(node) === null) {\n // should warn? maybe a text node isn't attached to a parent node yet?\n return false;\n } else {\n el = dom.parentElement(node)!;\n }\n try {\n if (typeof maskTextClass === 'string') {\n if (checkAncestors) {\n if (el.closest(`.${maskTextClass}`)) return true;\n } else {\n if (el.classList.contains(maskTextClass)) return true;\n }\n } else {\n if (classMatchesRegex(el, maskTextClass, checkAncestors)) return true;\n }\n if (maskTextSelector) {\n if (checkAncestors) {\n if (el.closest(maskTextSelector)) return true;\n } else {\n if (el.matches(maskTextSelector)) return true;\n }\n }\n } catch (e) {\n //\n }\n return false;\n}\n\n// https://stackoverflow.com/a/36155560\nfunction onceIframeLoaded(\n iframeEl: HTMLIFrameElement,\n listener: () => unknown,\n iframeLoadTimeout: number,\n) {\n const win = iframeEl.contentWindow;\n if (!win) {\n return;\n }\n // document is loading\n let fired = false;\n\n let readyState: DocumentReadyState;\n try {\n readyState = win.document.readyState;\n } catch (error) {\n return;\n }\n if (readyState !== 'complete') {\n const timer = setTimeout(() => {\n if (!fired) {\n listener();\n fired = true;\n }\n }, iframeLoadTimeout);\n iframeEl.addEventListener('load', () => {\n clearTimeout(timer);\n fired = true;\n listener();\n });\n return;\n }\n // check blank frame for Chrome\n const blankUrl = 'about:blank';\n if (\n win.location.href !== blankUrl ||\n iframeEl.src === blankUrl ||\n iframeEl.src === ''\n ) {\n // iframe was already loaded, make sure we wait to trigger the listener\n // till _after_ the mutation that found this iframe has had time to process\n setTimeout(listener, 0);\n\n return iframeEl.addEventListener('load', listener); // keep listing for future loads\n }\n // use default listener\n iframeEl.addEventListener('load', listener);\n}\n\nfunction onceStylesheetLoaded(\n link: HTMLLinkElement,\n listener: () => unknown,\n styleSheetLoadTimeout: number,\n) {\n let fired = false;\n let styleSheetLoaded: StyleSheet | null;\n try {\n styleSheetLoaded = link.sheet;\n } catch (error) {\n return;\n }\n\n if (styleSheetLoaded) return;\n\n const timer = setTimeout(() => {\n if (!fired) {\n listener();\n fired = true;\n }\n }, styleSheetLoadTimeout);\n\n link.addEventListener('load', () => {\n clearTimeout(timer);\n fired = true;\n listener();\n });\n}\n\nfunction serializeNode(\n n: Node,\n options: {\n doc: Document;\n mirror: Mirror;\n blockClass: string | RegExp;\n blockSelector: string | null;\n needsMask: boolean;\n inlineStylesheet: boolean;\n maskInputOptions: MaskInputOptions;\n maskTextFn: MaskTextFn | undefined;\n maskInputFn: MaskInputFn | undefined;\n dataURLOptions?: DataURLOptions;\n inlineImages: boolean;\n recordCanvas: boolean;\n keepIframeSrcFn: KeepIframeSrcFn;\n /**\n * `newlyAddedElement: true` skips scrollTop and scrollLeft check\n */\n newlyAddedElement?: boolean;\n },\n): serializedNode | false {\n const {\n doc,\n mirror,\n blockClass,\n blockSelector,\n needsMask,\n inlineStylesheet,\n maskInputOptions = {},\n maskTextFn,\n maskInputFn,\n dataURLOptions = {},\n inlineImages,\n recordCanvas,\n keepIframeSrcFn,\n newlyAddedElement = false,\n } = options;\n // Only record root id when document object is not the base document\n const rootId = getRootId(doc, mirror);\n switch (n.nodeType) {\n case n.DOCUMENT_NODE:\n if ((n as Document).compatMode !== 'CSS1Compat') {\n return {\n type: NodeType.Document,\n childNodes: [],\n compatMode: (n as Document).compatMode, // probably \"BackCompat\"\n };\n } else {\n return {\n type: NodeType.Document,\n childNodes: [],\n };\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 return serializeElementNode(n as HTMLElement, {\n doc,\n blockClass,\n blockSelector,\n inlineStylesheet,\n maskInputOptions,\n maskInputFn,\n dataURLOptions,\n inlineImages,\n recordCanvas,\n keepIframeSrcFn,\n newlyAddedElement,\n rootId,\n });\n case n.TEXT_NODE:\n return serializeTextNode(n as Text, {\n doc,\n needsMask,\n maskTextFn,\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: dom.textContent(n as Comment) || '',\n rootId,\n };\n default:\n return false;\n }\n}\n\nfunction getRootId(doc: Document, mirror: Mirror): number | undefined {\n if (!mirror.hasNode(doc)) return undefined;\n const docId = mirror.getId(doc);\n return docId === 1 ? undefined : docId;\n}\n\nfunction serializeTextNode(\n n: Text,\n options: {\n doc: Document;\n needsMask: boolean;\n maskTextFn: MaskTextFn | undefined;\n rootId: number | undefined;\n },\n): serializedNode {\n const { needsMask, maskTextFn, rootId } = options;\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 parent = dom.parentNode(n);\n const parentTagName = parent && (parent as HTMLElement).tagName;\n let text = dom.textContent(n);\n const isStyle = parentTagName === 'STYLE' ? true : undefined;\n const isScript = parentTagName === 'SCRIPT' ? true : undefined;\n if (isStyle && text) {\n try {\n // try to read style sheet\n if (n.nextSibling || n.previousSibling) {\n // This is not the only child of the stylesheet.\n // We can't read all of the sheet's .cssRules and expect them\n // to _only_ include the current rule(s) added by the text node.\n // So we'll be conservative and keep textContent as-is.\n } else if ((parent as HTMLStyleElement).sheet?.cssRules) {\n text = stringifyStylesheet((parent as HTMLStyleElement).sheet!);\n }\n } catch (err) {\n console.warn(\n `Cannot get CSS styles from text's parentNode. Error: ${err as string}`,\n n,\n );\n }\n text = absolutifyURLs(text, getHref(options.doc));\n }\n if (isScript) {\n text = 'SCRIPT_PLACEHOLDER';\n }\n if (!isStyle && !isScript && text && needsMask) {\n text = maskTextFn\n ? maskTextFn(text, dom.parentElement(n))\n : text.replace(/[\\S]/g, '*');\n }\n\n return {\n type: NodeType.Text,\n textContent: text || '',\n isStyle,\n rootId,\n };\n}\n\nfunction findStylesheet(doc: Document, href: string) {\n return Array.from(doc.styleSheets).find((s) => s.href === href);\n}\n\n/**\n * in production, we've seen elements like\n * `<link type=\"text/css\" rel=\"stylesheet\" id=\"dark-mode-custom-link\"></link>`\n * while HTMLLinkElement suggests an href is always present\n * the w3c spec is less specific\n * and regardless we've seen at least one instance of this in the wild\n * let's be defensive and make sure this is typed as possibly undefined\n */\nfunction hrefFrom(n: unknown): string | undefined {\n return (n as HTMLLinkElement).href;\n}\n\nfunction serializeElementNode(\n n: HTMLElement,\n options: {\n doc: Document;\n blockClass: string | RegExp;\n blockSelector: string | null;\n inlineStylesheet: boolean;\n maskInputOptions: MaskInputOptions;\n maskInputFn: MaskInputFn | undefined;\n dataURLOptions?: DataURLOptions;\n inlineImages: boolean;\n recordCanvas: boolean;\n keepIframeSrcFn: KeepIframeSrcFn;\n /**\n * `newlyAddedElement: true` skips scrollTop and scrollLeft check\n */\n newlyAddedElement?: boolean;\n rootId: number | undefined;\n },\n): serializedNode | false {\n const {\n doc,\n blockClass,\n blockSelector,\n inlineStylesheet,\n maskInputOptions = {},\n maskInputFn,\n dataURLOptions = {},\n inlineImages,\n recordCanvas,\n keepIframeSrcFn,\n newlyAddedElement = false,\n rootId,\n } = options;\n const needBlock = _isBlockedElement(n, blockClass, blockSelector);\n const tagName = getValidTagName(n);\n let attributes: attributes = {};\n const len = n.attributes.length;\n for (let i = 0; i < len; i++) {\n const attr = n.attributes[i];\n if (!ignoreAttribute(tagName, attr.name, attr.value)) {\n attributes[attr.name] = transformAttribute(\n doc,\n tagName,\n toLowerCase(attr.name),\n attr.value,\n n,\n dataURLOptions,\n );\n }\n }\n // remote css\n if (tagName === 'link' && inlineStylesheet) {\n //TODO: maybe replace this `.styleSheets` with original one\n const href: string | undefined = hrefFrom(n);\n if (href) {\n let stylesheet = findStylesheet(doc, href);\n if (!stylesheet && href.includes('.css')) {\n const rootDomain = window.location.origin;\n const stylesheetPath = href.replace(window.location.href, '');\n const potentialStylesheetHref = rootDomain + '/' + stylesheetPath;\n stylesheet = findStylesheet(doc, potentialStylesheetHref);\n }\n let cssText: string | null = null;\n if (stylesheet) {\n cssText = stringifyStylesheet(stylesheet);\n }\n if (cssText) {\n delete attributes.rel;\n delete attributes.href;\n attributes._cssText = cssText;\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.innerText || dom.textContent(n) || '').trim().length\n ) {\n const cssText = stringifyStylesheet(\n (n as HTMLStyleElement).sheet as CSSStyleSheet,\n );\n if (cssText) {\n attributes._cssText = cssText;\n }\n }\n // form fields\n if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {\n const value = (n as HTMLInputElement | HTMLTextAreaElement).value;\n const checked = (n as HTMLInputElement).checked;\n if (\n attributes.type !== 'radio' &&\n attributes.type !== 'checkbox' &&\n attributes.type !== 'submit' &&\n attributes.type !== 'button' &&\n value\n ) {\n attributes.value = maskInputValue({\n element: n,\n type: getInputType(n),\n tagName,\n value,\n maskInputOptions,\n maskInputFn,\n });\n } else if (checked) {\n attributes.checked = checked;\n }\n }\n if (tagName === 'option') {\n if ((n as HTMLOptionElement).selected && !maskInputOptions['select']) {\n attributes.selected = true;\n } else {\n // ignore the html attribute (which corresponds to DOM (n as HTMLOptionElement).defaultSelected)\n // if it's already been changed\n delete attributes.selected;\n }\n }\n\n if (tagName === 'dialog' && (n as HTMLDialogElement).open) {\n // register what type of dialog is this\n // `modal` or `non-modal`\n // this is used to trigger `showModal()` or `show()` on replay (outside of rrweb-snapshot, in rrweb)\n try {\n (attributes as DialogAttributes).rr_open_mode = n.matches('dialog:modal')\n ? 'modal'\n : 'non-modal';\n } catch {\n // likely this is safari not able to deal with the `:modal` selector\n // we can't detect whether the dialog is modal or non-modal open, so have to guess\n // hopefully this is only safari 15.4 and 15.5\n attributes.rr_open_mode = 'modal';\n attributes.ph_rr_could_not_detect_modal = true;\n }\n }\n\n // canvas image data\n if (tagName === 'canvas' && recordCanvas) {\n if ((n as ICanvas).__context === '2d') {\n // only record this on 2d canvas\n if (!is2DCanvasBlank(n as HTMLCanvasElement)) {\n attributes.rr_dataURL = (n as HTMLCanvasElement).toDataURL(\n dataURLOptions.type,\n dataURLOptions.quality,\n );\n }\n } else if (!('__context' in n)) {\n // context is unknown, better not call getContext to trigger it\n const canvasDataURL = (n as HTMLCanvasElement).toDataURL(\n dataURLOptions.type,\n dataURLOptions.quality,\n );\n\n // create blank canvas of same dimensions\n const blankCanvas = doc.createElement('canvas');\n blankCanvas.width = (n as HTMLCanvasElement).width;\n blankCanvas.height = (n as HTMLCanvasElement).height;\n const blankCanvasDataURL = blankCanvas.toDataURL(\n dataURLOptions.type,\n dataURLOptions.quality,\n );\n\n // no need to save dataURL if it's the same as blank canvas\n if (canvasDataURL !== blankCanvasDataURL) {\n attributes.rr_dataURL = canvasDataURL;\n }\n }\n }\n // save image offline\n if (tagName === 'img' && inlineImages) {\n if (!canvasService) {\n canvasService = doc.createElement('canvas');\n canvasCtx = canvasService.getContext('2d');\n }\n const image = n as HTMLImageElement;\n const imageSrc: string =\n image.currentSrc || image.getAttribute('src') || '<unknown-src>';\n const priorCrossOrigin = image.crossOrigin;\n const recordInlineImage = () => {\n image.removeEventListener('load', recordInlineImage);\n try {\n canvasService!.width = image.naturalWidth;\n canvasService!.height = image.naturalHeight;\n canvasCtx!.drawImage(image, 0, 0);\n attributes.rr_dataURL = canvasService!.toDataURL(\n dataURLOptions.type,\n dataURLOptions.quality,\n );\n } catch (err) {\n if (image.crossOrigin !== 'anonymous') {\n image.crossOrigin = 'anonymous';\n if (image.complete && image.naturalWidth !== 0)\n recordInlineImage(); // too early due to image reload\n else image.addEventListener('load', recordInlineImage);\n return;\n } else {\n console.warn(\n `Cannot inline img src=${imageSrc}! Error: ${err as string}`,\n );\n }\n }\n if (image.crossOrigin === 'anonymous') {\n priorCrossOrigin\n ? (attributes.crossOrigin = priorCrossOrigin)\n : image.removeAttribute('crossorigin');\n }\n };\n // The image content may not have finished loading yet.\n if (image.complete && image.naturalWidth !== 0) recordInlineImage();\n else image.addEventListener('load', recordInlineImage);\n }\n // media elements\n if (tagName === 'audio' || tagName === 'video') {\n const mediaAttributes = attributes as mediaAttributes;\n mediaAttributes.rr_mediaState = (n as HTMLMediaElement).paused\n ? 'paused'\n : 'played';\n mediaAttributes.rr_mediaCurrentTime = (n as HTMLMediaElement).currentTime;\n mediaAttributes.rr_mediaPlaybackRate = (n as HTMLMediaElement).playbackRate;\n mediaAttributes.rr_mediaMuted = (n as HTMLMediaElement).muted;\n mediaAttributes.rr_mediaLoop = (n as HTMLMediaElement).loop;\n mediaAttributes.rr_mediaVolume = (n as HTMLMediaElement).volume;\n }\n // Scroll\n if (!newlyAddedElement) {\n // `scrollTop` and `scrollLeft` are expensive calls because they trigger reflow.\n // Since `scrollTop` & `scrollLeft` are always 0 when an element is added to the DOM.\n // And scrolls also get picked up by rrweb's ScrollObserver\n // So we can safely skip the `scrollTop/Left` calls for newly added elements\n if (n.scrollLeft) {\n attributes.rr_scrollLeft = n.scrollLeft;\n }\n if (n.scrollTop) {\n attributes.rr_scrollTop = n.scrollTop;\n }\n }\n // block element\n if (needBlock) {\n const { width, height, left, top } = n.getBoundingClientRect();\n attributes = {\n class: attributes.class,\n rr_width: `${width}px`,\n rr_height: `${height}px`,\n rr_left: `${Math.floor(left + (doc.defaultView?.scrollX || 0))}px`,\n rr_top: `${Math.floor(top + (doc.defaultView?.scrollY || 0))}px`,\n };\n }\n // iframe\n if (tagName === 'iframe' && !keepIframeSrcFn(attributes.src as string)) {\n if (!(n as HTMLIFrameElement).contentDocument) {\n // we can't record it directly as we can't see into it\n // preserve the src attribute so a decision can be taken at replay time\n attributes.rr_src = attributes.src;\n }\n delete attributes.src; // prevent auto loading\n }\n\n let isCustomElement: true | undefined;\n try {\n if (customElements.get(tagName)) isCustomElement = true;\n } catch (e) {\n // In case old browsers don't support customElements\n }\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 isCustom: isCustomElement,\n };\n}\n\nfunction lowerIfExists(\n maybeAttr: string | number | boolean | undefined | null,\n): string {\n if (maybeAttr === undefined || maybeAttr === null) {\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 // script tag\n (sn.tagName === 'script' ||\n // (module)preload link\n (sn.tagName === 'link' &&\n ((sn.attributes.rel === 'preload' && sn.attributes.as === 'script') ||\n sn.attributes.rel === 'modulepreload')) ||\n // prefetch link\n (sn.tagName === 'link' &&\n sn.attributes.rel === 'prefetch' &&\n typeof sn.attributes.href === 'string' &&\n extractFileExtension(sn.attributes.href) === 'js'))\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 ['icon', 'apple-touch-icon', 'shortcut icon'].includes(\n lowerIfExists(sn.attributes.rel),\n ))))\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 ['robots', 'googlebot', 'bingbot'].includes(\n lowerIfExists(sn.attributes.name),\n )\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 (['author', 'generator', 'framework', 'publisher', 'progid'].includes(\n lowerIfExists(sn.attributes.name),\n ) ||\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 [\n 'google-site-verification',\n 'yandex-verification',\n 'csrf-token',\n 'p:domain_verify',\n 'verify-v1',\n 'verification',\n 'shopify-checkout-api-token',\n ].includes(lowerIfExists(sn.attributes.name))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nexport const DEFAULT_MAX_DEPTH = 50;\n\nlet _maxDepthWarned = false;\nlet _maxDepthReached = false;\n\nexport function wasMaxDepthReached(): boolean {\n return _maxDepthReached;\n}\n\nexport function resetMaxDepthState(): void {\n _maxDepthReached = false;\n _maxDepthWarned = false;\n}\n\nexport function serializeNodeWithId(\n n: Node,\n options: {\n doc: Document;\n mirror: Mirror;\n blockClass: string | RegExp;\n blockSelector: string | null;\n maskTextClass: string | RegExp;\n maskTextSelector: string | null;\n skipChild: boolean;\n inlineStylesheet: boolean;\n newlyAddedElement?: boolean;\n maskInputOptions?: MaskInputOptions;\n needsMask?: boolean;\n maskTextFn: MaskTextFn | undefined;\n maskInputFn: MaskInputFn | undefined;\n slimDOMOptions: SlimDOMOptions;\n dataURLOptions?: DataURLOptions;\n keepIframeSrcFn?: KeepIframeSrcFn;\n inlineImages?: boolean;\n recordCanvas?: boolean;\n preserveWhiteSpace?: boolean;\n onSerialize?: (n: Node) => unknown;\n onIframeLoad?: (\n iframeNode: HTMLIFrameElement,\n node: serializedElementNodeWithId,\n ) => unknown;\n iframeLoadTimeout?: number;\n onStylesheetLoad?: (\n linkNode: HTMLLinkElement,\n node: serializedElementNodeWithId,\n ) => unknown;\n stylesheetLoadTimeout?: number;\n depth?: number;\n maxDepth?: number;\n onMaxDepthReached?: () => void;\n },\n): serializedNodeWithId | null {\n const {\n doc,\n mirror,\n blockClass,\n blockSelector,\n maskTextClass,\n maskTextSelector,\n skipChild = false,\n inlineStylesheet = true,\n maskInputOptions = {},\n maskTextFn,\n maskInputFn,\n slimDOMOptions,\n dataURLOptions = {},\n inlineImages = false,\n recordCanvas = false,\n onSerialize,\n onIframeLoad,\n iframeLoadTimeout = 5000,\n onStylesheetLoad,\n stylesheetLoadTimeout = 5000,\n keepIframeSrcFn = () => false,\n newlyAddedElement = false,\n depth = 0,\n maxDepth = DEFAULT_MAX_DEPTH,\n } = options;\n let { needsMask } = options;\n let { preserveWhiteSpace = true } = options;\n\n if (depth >= maxDepth) {\n _maxDepthReached = true;\n if (!_maxDepthWarned) {\n _maxDepthWarned = true;\n console.warn(\n `[rrweb-snapshot] DOM tree depth exceeded max depth of ${maxDepth}. ` +\n `Children beyond this depth will not be recorded. ` +\n `This may indicate deeply nested DOM structures.`,\n );\n }\n return null;\n }\n\n if (!needsMask) {\n // perf: if needsMask = true, children won't also need to check\n const checkAncestors = needsMask === undefined; // if false, we've already checked ancestors\n needsMask = needMaskingText(\n n as Element,\n maskTextClass,\n maskTextSelector,\n checkAncestors,\n );\n }\n\n const _serializedNode = serializeNode(n, {\n doc,\n mirror,\n blockClass,\n blockSelector,\n needsMask,\n inlineStylesheet,\n maskInputOptions,\n maskTextFn,\n maskInputFn,\n dataURLOptions,\n inlineImages,\n recordCanvas,\n keepIframeSrcFn,\n newlyAddedElement,\n });\n if (!_serializedNode) {\n // TODO: dev only\n console.warn(n, 'not serialized');\n return null;\n }\n\n let id: number | undefined;\n if (mirror.hasNode(n)) {\n // Reuse the previous id\n id = mirror.getId(n);\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\n const serializedNode = Object.assign(_serializedNode, { id });\n // add IGNORED_NODE to mirror to track nextSiblings\n mirror.add(n, serializedNode);\n\n if (id === IGNORED_NODE) {\n return null; // slimDOM\n }\n\n if (onSerialize) {\n onSerialize(n);\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 const shadowRootEl = dom.shadowRoot(n);\n if (shadowRootEl && isNativeShadowDom(shadowRootEl))\n serializedNode.isShadowHost = true;\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 const bypassOptions = {\n doc,\n mirror,\n blockClass,\n blockSelector,\n needsMask,\n maskTextClass,\n maskTextSelector,\n skipChild,\n inlineStylesheet,\n maskInputOptions,\n maskTextFn,\n maskInputFn,\n slimDOMOptions,\n dataURLOptions,\n inlineImages,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n onIframeLoad,\n iframeLoadTimeout,\n onStylesheetLoad,\n stylesheetLoadTimeout,\n keepIframeSrcFn,\n depth: depth + 1,\n maxDepth,\n };\n\n if (\n serializedNode.type === NodeType.Element &&\n serializedNode.tagName === 'textarea' &&\n (serializedNode as elementNode).attributes.value !== undefined\n ) {\n // value parameter in DOM reflects the correct value, so ignore childNode\n } else {\n for (const childN of Array.from(dom.childNodes(n))) {\n const serializedChildNode = serializeNodeWithId(childN, bypassOptions);\n if (serializedChildNode) {\n serializedNode.childNodes.push(serializedChildNode);\n }\n }\n }\n\n let shadowRootEl: ShadowRoot | null = null;\n if (isElement(n) && (shadowRootEl = dom.shadowRoot(n))) {\n for (const childN of Array.from(dom.childNodes(shadowRootEl))) {\n const serializedChildNode = serializeNodeWithId(childN, bypassOptions);\n if (serializedChildNode) {\n isNativeShadowDom(shadowRootEl) &&\n (serializedChildNode.isShadow = true);\n serializedNode.childNodes.push(serializedChildNode);\n }\n }\n }\n }\n\n const parent = dom.parentNode(n);\n if (parent && isShadowRoot(parent) && isNativeShadowDom(parent)) {\n serializedNode.isShadow = true;\n }\n\n if (\n serializedNode.type === NodeType.Element &&\n serializedNode.tagName === 'iframe'\n ) {\n onceIframeLoaded(\n n as HTMLIFrameElement,\n () => {\n const iframeDoc = (n as HTMLIFrameElement).contentDocument;\n if (iframeDoc && onIframeLoad) {\n const serializedIframeNode = serializeNodeWithId(iframeDoc, {\n doc: iframeDoc,\n mirror,\n blockClass,\n blockSelector,\n needsMask,\n maskTextClass,\n maskTextSelector,\n skipChild: false,\n inlineStylesheet,\n maskInputOptions,\n maskTextFn,\n maskInputFn,\n slimDOMOptions,\n dataURLOptions,\n inlineImages,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n onIframeLoad,\n iframeLoadTimeout,\n onStylesheetLoad,\n stylesheetLoadTimeout,\n keepIframeSrcFn,\n depth: depth + 1,\n maxDepth,\n });\n\n if (serializedIframeNode) {\n onIframeLoad(\n n as HTMLIFrameElement,\n serializedIframeNode as serializedElementNodeWithId,\n );\n }\n }\n },\n iframeLoadTimeout,\n );\n }\n\n // <link rel=stylesheet href=...>\n if (\n serializedNode.type === NodeType.Element &&\n serializedNode.tagName === 'link' &&\n typeof serializedNode.attributes.rel === 'string' &&\n (serializedNode.attributes.rel === 'stylesheet' ||\n (serializedNode.attributes.rel === 'preload' &&\n typeof serializedNode.attributes.href === 'string' &&\n extractFileExtension(serializedNode.attributes.href) === 'css'))\n ) {\n onceStylesheetLoaded(\n n as HTMLLinkElement,\n () => {\n if (onStylesheetLoad) {\n const serializedLinkNode = serializeNodeWithId(n, {\n doc,\n mirror,\n blockClass,\n blockSelector,\n needsMask,\n maskTextClass,\n maskTextSelector,\n skipChild: false,\n inlineStylesheet,\n maskInputOptions,\n maskTextFn,\n maskInputFn,\n slimDOMOptions,\n dataURLOptions,\n inlineImages,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n onIframeLoad,\n iframeLoadTimeout,\n onStylesheetLoad,\n stylesheetLoadTimeout,\n keepIframeSrcFn,\n depth,\n maxDepth,\n });\n\n if (serializedLinkNode) {\n onStylesheetLoad(\n n as HTMLLinkElement,\n serializedLinkNode as serializedElementNodeWithId,\n );\n }\n }\n },\n stylesheetLoadTimeout,\n );\n }\n\n return serializedNode;\n}\n\nexport function slimDOMDefaults(\n slimDOM: 'all' | boolean | SlimDOMOptions,\n): SlimDOMOptions {\n if (slimDOM === true || slimDOM === 'all') {\n return {\n script: true,\n comment: true,\n headFavicon: true,\n headWhitespace: true,\n headMetaSocial: true,\n headMetaRobots: true,\n headMetaHttpEquiv: true,\n headMetaVerification: true,\n headMetaAuthorship: slimDOM === 'all',\n headMetaDescKeywords: slimDOM === 'all',\n headTitleMutations: slimDOM === 'all',\n };\n }\n if (slimDOM === false) {\n return {};\n }\n return slimDOM;\n}\n\nfunction snapshot(\n n: Document,\n options?: {\n mirror?: Mirror;\n blockClass?: string | RegExp;\n blockSelector?: string | null;\n maskTextClass?: string | RegExp;\n maskTextSelector?: string | null;\n inlineStylesheet?: boolean;\n maskAllInputs?: boolean | MaskInputOptions;\n maskTextFn?: MaskTextFn;\n maskInputFn?: MaskInputFn;\n slimDOM?: 'all' | boolean | SlimDOMOptions;\n dataURLOptions?: DataURLOptions;\n inlineImages?: boolean;\n recordCanvas?: boolean;\n preserveWhiteSpace?: boolean;\n onSerialize?: (n: Node) => unknown;\n onIframeLoad?: (\n iframeNode: HTMLIFrameElement,\n node: serializedElementNodeWithId,\n ) => unknown;\n iframeLoadTimeout?: number;\n onStylesheetLoad?: (\n linkNode: HTMLLinkElement,\n node: serializedElementNodeWithId,\n ) => unknown;\n stylesheetLoadTimeout?: number;\n keepIframeSrcFn?: KeepIframeSrcFn;\n maxDepth?: number;\n },\n): serializedNodeWithId | null {\n const {\n mirror = new Mirror(),\n blockClass = 'rr-block',\n blockSelector = null,\n maskTextClass = 'rr-mask',\n maskTextSelector = null,\n inlineStylesheet = true,\n inlineImages = false,\n recordCanvas = false,\n maskAllInputs = false,\n maskTextFn,\n maskInputFn,\n slimDOM = false,\n dataURLOptions,\n preserveWhiteSpace,\n onSerialize,\n onIframeLoad,\n iframeLoadTimeout,\n onStylesheetLoad,\n stylesheetLoadTimeout,\n keepIframeSrcFn = () => false,\n maxDepth,\n } = options || {};\n const maskInputOptions: MaskInputOptions =\n maskAllInputs === 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 password: true,\n }\n : maskAllInputs === false\n ? {\n password: true,\n }\n : maskAllInputs;\n const slimDOMOptions: SlimDOMOptions = slimDOMDefaults(slimDOM);\n return serializeNodeWithId(n, {\n doc: n,\n mirror,\n blockClass,\n blockSelector,\n maskTextClass,\n maskTextSelector,\n skipChild: false,\n inlineStylesheet,\n maskInputOptions,\n maskTextFn,\n maskInputFn,\n slimDOMOptions,\n dataURLOptions,\n inlineImages,\n recordCanvas,\n preserveWhiteSpace,\n onSerialize,\n onIframeLoad,\n iframeLoadTimeout,\n onStylesheetLoad,\n stylesheetLoadTimeout,\n keepIframeSrcFn,\n newlyAddedElement: false,\n maxDepth,\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"],"names":["toLowerCase","recompressBase64Image","checkDataURLSize","absolutifyURLs","dom","isElement","NodeType","stringifyStylesheet","maskInputValue","getInputType","is2DCanvasBlank","extractFileExtension","isNativeShadowDom","isShadowRoot","Mirror"],"mappings":"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"}
@@ -556,7 +556,7 @@ var require_types_B7TTv7Jc = __commonJS({
556
556
  }
557
557
  });
558
558
 
559
- // dist/record-oACzRSl-.cjs
559
+ // dist/record-BUfdSR_C.cjs
560
560
  var types = require_types_B7TTv7Jc();
561
561
  var _id = 1;
562
562
  var tagNameRegex = new RegExp("[^a-z0-9-_:]");
@@ -1170,7 +1170,9 @@ function slimDOMExcluded(sn, slimDOMOptions) {
1170
1170
  return true;
1171
1171
  } else if (slimDOMOptions.headFavicon && (sn.tagName === "link" && sn.attributes.rel === "shortcut icon" || sn.tagName === "meta" && (lowerIfExists(sn.attributes.name).match(
1172
1172
  /^msapplication-tile(image|color)$/
1173
- ) || lowerIfExists(sn.attributes.name) === "application-name" || lowerIfExists(sn.attributes.rel) === "icon" || lowerIfExists(sn.attributes.rel) === "apple-touch-icon" || lowerIfExists(sn.attributes.rel) === "shortcut icon"))) {
1173
+ ) || lowerIfExists(sn.attributes.name) === "application-name" || ["icon", "apple-touch-icon", "shortcut icon"].includes(
1174
+ lowerIfExists(sn.attributes.rel)
1175
+ )))) {
1174
1176
  return true;
1175
1177
  } else if (sn.tagName === "meta") {
1176
1178
  if (slimDOMOptions.headMetaDescKeywords && lowerIfExists(sn.attributes.name).match(/^description|keywords$/)) {
@@ -1178,13 +1180,25 @@ function slimDOMExcluded(sn, slimDOMOptions) {
1178
1180
  } else if (slimDOMOptions.headMetaSocial && (lowerIfExists(sn.attributes.property).match(/^(og|twitter|fb):/) || // og = opengraph (facebook)
1179
1181
  lowerIfExists(sn.attributes.name).match(/^(og|twitter):/) || lowerIfExists(sn.attributes.name) === "pinterest")) {
1180
1182
  return true;
1181
- } else if (slimDOMOptions.headMetaRobots && (lowerIfExists(sn.attributes.name) === "robots" || lowerIfExists(sn.attributes.name) === "googlebot" || lowerIfExists(sn.attributes.name) === "bingbot")) {
1183
+ } else if (slimDOMOptions.headMetaRobots && ["robots", "googlebot", "bingbot"].includes(
1184
+ lowerIfExists(sn.attributes.name)
1185
+ )) {
1182
1186
  return true;
1183
1187
  } else if (slimDOMOptions.headMetaHttpEquiv && sn.attributes["http-equiv"] !== void 0) {
1184
1188
  return true;
1185
- } 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:/))) {
1189
+ } else if (slimDOMOptions.headMetaAuthorship && (["author", "generator", "framework", "publisher", "progid"].includes(
1190
+ lowerIfExists(sn.attributes.name)
1191
+ ) || lowerIfExists(sn.attributes.property).match(/^article:/) || lowerIfExists(sn.attributes.property).match(/^product:/))) {
1186
1192
  return true;
1187
- } 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")) {
1193
+ } else if (slimDOMOptions.headMetaVerification && [
1194
+ "google-site-verification",
1195
+ "yandex-verification",
1196
+ "csrf-token",
1197
+ "p:domain_verify",
1198
+ "verify-v1",
1199
+ "verification",
1200
+ "shopify-checkout-api-token"
1201
+ ].includes(lowerIfExists(sn.attributes.name))) {
1188
1202
  return true;
1189
1203
  }
1190
1204
  }
@@ -1437,6 +1451,27 @@ function serializeNodeWithId(n, options) {
1437
1451
  }
1438
1452
  return serializedNode;
1439
1453
  }
1454
+ function slimDOMDefaults(slimDOM) {
1455
+ if (slimDOM === true || slimDOM === "all") {
1456
+ return {
1457
+ script: true,
1458
+ comment: true,
1459
+ headFavicon: true,
1460
+ headWhitespace: true,
1461
+ headMetaSocial: true,
1462
+ headMetaRobots: true,
1463
+ headMetaHttpEquiv: true,
1464
+ headMetaVerification: true,
1465
+ headMetaAuthorship: slimDOM === "all",
1466
+ headMetaDescKeywords: slimDOM === "all",
1467
+ headTitleMutations: slimDOM === "all"
1468
+ };
1469
+ }
1470
+ if (slimDOM === false) {
1471
+ return {};
1472
+ }
1473
+ return slimDOM;
1474
+ }
1440
1475
  function snapshot(n, options) {
1441
1476
  const {
1442
1477
  mirror = new types.Mirror(),
@@ -1481,22 +1516,7 @@ function snapshot(n, options) {
1481
1516
  } : maskAllInputs === false ? {
1482
1517
  password: true
1483
1518
  } : maskAllInputs;
1484
- const slimDOMOptions = slimDOM === true || slimDOM === "all" ? (
1485
- // if true: set of sensible options that should not throw away any information
1486
- {
1487
- script: true,
1488
- comment: true,
1489
- headFavicon: true,
1490
- headWhitespace: true,
1491
- headMetaDescKeywords: slimDOM === "all",
1492
- // destructive
1493
- headMetaSocial: true,
1494
- headMetaRobots: true,
1495
- headMetaHttpEquiv: true,
1496
- headMetaAuthorship: true,
1497
- headMetaVerification: true
1498
- }
1499
- ) : slimDOM === false ? {} : slimDOM;
1519
+ const slimDOMOptions = slimDOMDefaults(slimDOM);
1500
1520
  return serializeNodeWithId(n, {
1501
1521
  doc: n,
1502
1522
  mirror,
@@ -1545,6 +1565,7 @@ exports.ignoreAttribute = ignoreAttribute;
1545
1565
  exports.needMaskingText = needMaskingText;
1546
1566
  exports.resetMaxDepthState = resetMaxDepthState;
1547
1567
  exports.serializeNodeWithId = serializeNodeWithId;
1568
+ exports.slimDOMDefaults = slimDOMDefaults;
1548
1569
  exports.snapshot = snapshot;
1549
1570
  exports.transformAttribute = transformAttribute;
1550
1571
  exports.visitSnapshot = visitSnapshot;
@@ -1566,4 +1587,4 @@ exports.wasMaxDepthReached = wasMaxDepthReached;
1566
1587
  }
1567
1588
  return module.exports;
1568
1589
  }))
1569
- //# sourceMappingURL=record-oACzRSl-.umd.cjs.map
1590
+ //# sourceMappingURL=record-BUfdSR_C.umd.cjs.map