@posthog/rrweb-snapshot 0.0.39 → 0.0.41

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.
package/dist/record.cjs CHANGED
@@ -634,6 +634,12 @@ function slimDOMExcluded(sn, slimDOMOptions) {
634
634
  }
635
635
  return false;
636
636
  }
637
+ const DEFAULT_MAX_DEPTH = 50;
638
+ let _maxDepthWarned = false;
639
+ let _maxDepthReached = false;
640
+ function wasMaxDepthReached() {
641
+ return _maxDepthReached;
642
+ }
637
643
  function serializeNodeWithId(n, options) {
638
644
  const {
639
645
  doc,
@@ -657,10 +663,22 @@ function serializeNodeWithId(n, options) {
657
663
  onStylesheetLoad,
658
664
  stylesheetLoadTimeout = 5e3,
659
665
  keepIframeSrcFn = () => false,
660
- newlyAddedElement = false
666
+ newlyAddedElement = false,
667
+ depth = 0,
668
+ maxDepth = DEFAULT_MAX_DEPTH
661
669
  } = options;
662
670
  let { needsMask } = options;
663
671
  let { preserveWhiteSpace = true } = options;
672
+ if (depth >= maxDepth) {
673
+ _maxDepthReached = true;
674
+ if (!_maxDepthWarned) {
675
+ _maxDepthWarned = true;
676
+ console.warn(
677
+ `[rrweb-snapshot] DOM tree depth exceeded max depth of ${maxDepth}. Children beyond this depth will not be recorded. This may indicate deeply nested DOM structures.`
678
+ );
679
+ }
680
+ return null;
681
+ }
664
682
  if (!needsMask) {
665
683
  const checkAncestors = needsMask === void 0;
666
684
  needsMask = needMaskingText(
@@ -741,7 +759,9 @@ function serializeNodeWithId(n, options) {
741
759
  iframeLoadTimeout,
742
760
  onStylesheetLoad,
743
761
  stylesheetLoadTimeout,
744
- keepIframeSrcFn
762
+ keepIframeSrcFn,
763
+ depth: depth + 1,
764
+ maxDepth
745
765
  };
746
766
  if (serializedNode.type === types.NodeType$1.Element && serializedNode.tagName === "textarea" && serializedNode.attributes.value !== void 0) ;
747
767
  else {
@@ -796,7 +816,9 @@ function serializeNodeWithId(n, options) {
796
816
  iframeLoadTimeout,
797
817
  onStylesheetLoad,
798
818
  stylesheetLoadTimeout,
799
- keepIframeSrcFn
819
+ keepIframeSrcFn,
820
+ depth: depth + 1,
821
+ maxDepth
800
822
  });
801
823
  if (serializedIframeNode) {
802
824
  onIframeLoad(
@@ -837,7 +859,9 @@ function serializeNodeWithId(n, options) {
837
859
  iframeLoadTimeout,
838
860
  onStylesheetLoad,
839
861
  stylesheetLoadTimeout,
840
- keepIframeSrcFn
862
+ keepIframeSrcFn,
863
+ depth,
864
+ maxDepth
841
865
  });
842
866
  if (serializedLinkNode) {
843
867
  onStylesheetLoad(
@@ -873,7 +897,8 @@ function snapshot(n, options) {
873
897
  iframeLoadTimeout,
874
898
  onStylesheetLoad,
875
899
  stylesheetLoadTimeout,
876
- keepIframeSrcFn = () => false
900
+ keepIframeSrcFn = () => false,
901
+ maxDepth
877
902
  } = options || {};
878
903
  const maskInputOptions = maskAllInputs === true ? {
879
904
  color: true,
@@ -934,7 +959,8 @@ function snapshot(n, options) {
934
959
  onStylesheetLoad,
935
960
  stylesheetLoadTimeout,
936
961
  keepIframeSrcFn,
937
- newlyAddedElement: false
962
+ newlyAddedElement: false,
963
+ maxDepth
938
964
  });
939
965
  }
940
966
  function visitSnapshot(node, onVisit) {
@@ -970,6 +996,7 @@ exports.recompressBase64Image = types.recompressBase64Image;
970
996
  exports.stringifyRule = types.stringifyRule;
971
997
  exports.stringifyStylesheet = types.stringifyStylesheet;
972
998
  exports.toLowerCase = types.toLowerCase;
999
+ exports.DEFAULT_MAX_DEPTH = DEFAULT_MAX_DEPTH;
973
1000
  exports.IGNORED_NODE = IGNORED_NODE;
974
1001
  exports.classMatchesRegex = classMatchesRegex;
975
1002
  exports.cleanupSnapshot = cleanupSnapshot;
@@ -980,4 +1007,5 @@ exports.serializeNodeWithId = serializeNodeWithId;
980
1007
  exports.snapshot = snapshot;
981
1008
  exports.transformAttribute = transformAttribute;
982
1009
  exports.visitSnapshot = visitSnapshot;
1010
+ exports.wasMaxDepthReached = wasMaxDepthReached;
983
1011
  //# sourceMappingURL=record.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"record.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 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,\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 },\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 } = options;\n let { needsMask } = options;\n let { preserveWhiteSpace = true } = options;\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 };\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 });\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 });\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\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 },\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 } = 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 =\n slimDOM === true || slimDOM === '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: slimDOM === 'all', // destructive\n headMetaSocial: true,\n headMetaRobots: true,\n headMetaHttpEquiv: true,\n headMetaAuthorship: true,\n headMetaVerification: true,\n }\n : slimDOM === false\n ? {}\n : 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 });\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":";;;AAoCA,IAAI,MAAM;AACV,MAAM,eAAe,IAAI,OAAO,cAAc;AAEvC,MAAM,eAAe;AAErB,SAAS,QAAgB;AAC9B,SAAO;AACT;AAEA,SAAS,gBAAgB,SAAyC;AAChE,MAAI,mBAAmB,iBAAiB;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,mBAAmBA,MAAAA,YAAY,QAAQ,OAAO;AAEpD,MAAI,aAAa,KAAK,gBAAgB,GAAG;AAIvC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,IAAI;AACJ,IAAI;AAGJ,MAAM,oBAAoB;AAE1B,MAAM,0BAA0B;AAEhC,SAAS,wBAAwB,KAAe,gBAAwB;AAStE,MAAI,eAAe,KAAA,MAAW,IAAI;AAChC,WAAO;AAAA,EACT;AAEA,MAAI,MAAM;AAEV,WAAS,kBAAkB,OAAe;AACxC,QAAI;AACJ,UAAM,QAAQ,MAAM,KAAK,eAAe,UAAU,GAAG,CAAC;AACtD,QAAI,OAAO;AACT,cAAQ,MAAM,CAAC;AACf,aAAO,MAAM;AACb,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,CAAA;AAEf,SAAO,MAAM;AACX,sBAAkB,uBAAuB;AACzC,QAAI,OAAO,eAAe,QAAQ;AAChC;AAAA,IACF;AAEA,QAAI,MAAM,kBAAkB,iBAAiB;AAC7C,QAAI,IAAI,MAAM,EAAE,MAAM,KAAK;AAEzB,YAAM,cAAc,KAAK,IAAI,UAAU,GAAG,IAAI,SAAS,CAAC,CAAC;AAGzD,aAAO,KAAK,GAAG;AAAA,IACjB,OAAO;AACL,UAAI,iBAAiB;AACrB,YAAM,cAAc,KAAK,GAAG;AAC5B,UAAI,WAAW;AAEf,aAAO,MAAM;AACX,cAAM,IAAI,eAAe,OAAO,GAAG;AACnC,YAAI,MAAM,IAAI;AACZ,iBAAO,MAAM,MAAM,gBAAgB,KAAA,CAAM;AACzC;AAAA,QACF,WAAW,CAAC,UAAU;AACpB,cAAI,MAAM,KAAK;AACb,mBAAO;AACP,mBAAO,MAAM,MAAM,gBAAgB,KAAA,CAAM;AACzC;AAAA,UACF,WAAW,MAAM,KAAK;AACpB,uBAAW;AAAA,UACb;AAAA,QACF,OAAO;AAGL,cAAI,MAAM,KAAK;AACb,uBAAW;AAAA,UACb;AAAA,QACF;AACA,0BAAkB;AAClB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,KAAK,IAAI;AACzB;AAEA,MAAM,qCAAqB,QAAA;AAEpB,SAAS,cAAc,KAAe,gBAAgC;AAC3E,MAAI,CAAC,kBAAkB,eAAe,KAAA,MAAW,IAAI;AACnD,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,KAAK,cAAc;AACpC;AAEA,SAAS,aAAa,IAAsB;AAC1C,SAAO,QAAQ,GAAG,YAAY,SAAU,GAAkB,eAAe;AAC3E;AAEA,SAAS,QAAQ,KAAe,YAAqB;AACnD,MAAI,IAAI,eAAe,IAAI,GAAG;AAC9B,MAAI,CAAC,GAAG;AACN,QAAI,IAAI,cAAc,GAAG;AACzB,mBAAe,IAAI,KAAK,CAAC;AAAA,EAC3B;AACA,MAAI,CAAC,YAAY;AACf,iBAAa;AAAA,EACf,WAAW,WAAW,WAAW,OAAO,KAAK,WAAW,WAAW,OAAO,GAAG;AAC3E,WAAO;AAAA,EACT;AAEA,IAAE,aAAa,QAAQ,UAAU;AACjC,SAAO,EAAE;AACX;AAEO,SAAS,mBACd,KACA,SACA,MACA,OACA,SACA,gBACe;AACf,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAGA,MACE,SAAS,SACR,SAAS,UAAU,EAAE,YAAY,SAAS,MAAM,CAAC,MAAM,MACxD;AAEA,UAAM,mBAAmB,cAAc,KAAK,KAAK;AAEjD,QAAI,YAAY,SAAS,iBAAiB,WAAW,OAAO,KAAK,SAAS;AACxE,YAAM,MAAM;AAEZ,UAAI,mBAAmB;AAEvB,WAAI,iDAAgB,UAAQ,iDAAgB,aAAY,QAAW;AACjE,2BAAmBC,MAAAA;AAAAA,UACjB;AAAA,UACA;AAAA,UACA,eAAe;AAAA,UACf,eAAe;AAAA,QAAA;AAAA,MAEnB;AAEA,UAAI,iDAAgB,sBAAsB;AACxC,2BAAmBC,MAAAA;AAAAA,UACjB;AAAA,UACA,eAAe;AAAA,QAAA;AAAA,MAEnB;AAEA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,WAAW,SAAS,gBAAgB,MAAM,CAAC,MAAM,KAAK;AAEpD,WAAO,cAAc,KAAK,KAAK;AAAA,EACjC,WACE,SAAS,iBACR,YAAY,WAAW,YAAY,QAAQ,YAAY,OACxD;AACA,WAAO,cAAc,KAAK,KAAK;AAAA,EACjC,WAAW,SAAS,UAAU;AAC5B,WAAO,wBAAwB,KAAK,KAAK;AAAA,EAC3C,WAAW,SAAS,SAAS;AAC3B,WAAOC,qBAAe,OAAO,QAAQ,GAAG,CAAC;AAAA,EAC3C,WAAW,YAAY,YAAY,SAAS,QAAQ;AAClD,WAAO,cAAc,KAAK,KAAK;AAAA,EACjC;AAEA,SAAO;AACT;AAEO,SAAS,gBACd,SACA,MAEA,QACS;AACT,UAAQ,YAAY,WAAW,YAAY,YAAY,SAAS;AAClE;AAEO,SAAS,kBACd,SACA,YACA,eACS;AACT,MAAI;AACF,QAAI,OAAO,eAAe,UAAU;AAClC,UAAI,QAAQ,UAAU,SAAS,UAAU,GAAG;AAC1C,eAAO;AAAA,MACT;AAAA,IACF,OAAO;AACL,eAAS,SAAS,QAAQ,UAAU,QAAQ,YAAY;AACtD,cAAM,YAAY,QAAQ,UAAU,MAAM;AAC1C,YAAI,WAAW,KAAK,SAAS,GAAG;AAC9B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,QAAI,eAAe;AACjB,aAAO,QAAQ,QAAQ,aAAa;AAAA,IACtC;AAAA,EACF,SAAS,GAAG;AAAA,EAEZ;AAEA,SAAO;AACT;AAEO,SAAS,kBACd,MACA,OACA,gBACS;AACT,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,aAAa,KAAK,cAAc;AACvC,QAAI,CAAC,eAAgB,QAAO;AAC5B,WAAO,kBAAkBC,MAAAA,MAAI,WAAW,IAAI,GAAG,OAAO,cAAc;AAAA,EACtE;AAEA,WAAS,SAAU,KAAqB,UAAU,QAAQ,YAAY;AACpE,UAAM,YAAa,KAAqB,UAAU,MAAM;AACxD,QAAI,MAAM,KAAK,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,CAAC,eAAgB,QAAO;AAC5B,SAAO,kBAAkBA,MAAAA,MAAI,WAAW,IAAI,GAAG,OAAO,cAAc;AACtE;AAEO,SAAS,gBACd,MACA,eACA,kBACA,gBACS;AACT,MAAI;AACJ,MAAIC,MAAAA,UAAU,IAAI,GAAG;AACnB,SAAK;AACL,QAAI,CAACD,MAAAA,MAAI,WAAW,EAAE,EAAE,QAAQ;AAG9B,aAAO;AAAA,IACT;AAAA,EACF,WAAWA,MAAAA,MAAI,cAAc,IAAI,MAAM,MAAM;AAE3C,WAAO;AAAA,EACT,OAAO;AACL,SAAKA,MAAAA,MAAI,cAAc,IAAI;AAAA,EAC7B;AACA,MAAI;AACF,QAAI,OAAO,kBAAkB,UAAU;AACrC,UAAI,gBAAgB;AAClB,YAAI,GAAG,QAAQ,IAAI,aAAa,EAAE,EAAG,QAAO;AAAA,MAC9C,OAAO;AACL,YAAI,GAAG,UAAU,SAAS,aAAa,EAAG,QAAO;AAAA,MACnD;AAAA,IACF,OAAO;AACL,UAAI,kBAAkB,IAAI,eAAe,cAAc,EAAG,QAAO;AAAA,IACnE;AACA,QAAI,kBAAkB;AACpB,UAAI,gBAAgB;AAClB,YAAI,GAAG,QAAQ,gBAAgB,EAAG,QAAO;AAAA,MAC3C,OAAO;AACL,YAAI,GAAG,QAAQ,gBAAgB,EAAG,QAAO;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AAAA,EAEZ;AACA,SAAO;AACT;AAGA,SAAS,iBACP,UACA,UACA,mBACA;AACA,QAAM,MAAM,SAAS;AACrB,MAAI,CAAC,KAAK;AACR;AAAA,EACF;AAEA,MAAI,QAAQ;AAEZ,MAAI;AACJ,MAAI;AACF,iBAAa,IAAI,SAAS;AAAA,EAC5B,SAAS,OAAO;AACd;AAAA,EACF;AACA,MAAI,eAAe,YAAY;AAC7B,UAAM,QAAQ,WAAW,MAAM;AAC7B,UAAI,CAAC,OAAO;AACV,iBAAA;AACA,gBAAQ;AAAA,MACV;AAAA,IACF,GAAG,iBAAiB;AACpB,aAAS,iBAAiB,QAAQ,MAAM;AACtC,mBAAa,KAAK;AAClB,cAAQ;AACR,eAAA;AAAA,IACF,CAAC;AACD;AAAA,EACF;AAEA,QAAM,WAAW;AACjB,MACE,IAAI,SAAS,SAAS,YACtB,SAAS,QAAQ,YACjB,SAAS,QAAQ,IACjB;AAGA,eAAW,UAAU,CAAC;AAEtB,WAAO,SAAS,iBAAiB,QAAQ,QAAQ;AAAA,EACnD;AAEA,WAAS,iBAAiB,QAAQ,QAAQ;AAC5C;AAEA,SAAS,qBACP,MACA,UACA,uBACA;AACA,MAAI,QAAQ;AACZ,MAAI;AACJ,MAAI;AACF,uBAAmB,KAAK;AAAA,EAC1B,SAAS,OAAO;AACd;AAAA,EACF;AAEA,MAAI,iBAAkB;AAEtB,QAAM,QAAQ,WAAW,MAAM;AAC7B,QAAI,CAAC,OAAO;AACV,eAAA;AACA,cAAQ;AAAA,IACV;AAAA,EACF,GAAG,qBAAqB;AAExB,OAAK,iBAAiB,QAAQ,MAAM;AAClC,iBAAa,KAAK;AAClB,YAAQ;AACR,aAAA;AAAA,EACF,CAAC;AACH;AAEA,SAAS,cACP,GACA,SAmBwB;AACxB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,CAAA;AAAA,IACnB;AAAA,IACA;AAAA,IACA,iBAAiB,CAAA;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,EAAA,IAClB;AAEJ,QAAM,SAAS,UAAU,KAAK,MAAM;AACpC,UAAQ,EAAE,UAAA;AAAA,IACR,KAAK,EAAE;AACL,UAAK,EAAe,eAAe,cAAc;AAC/C,eAAO;AAAA,UACL,MAAME,MAAAA,WAAS;AAAA,UACf,YAAY,CAAA;AAAA,UACZ,YAAa,EAAe;AAAA;AAAA,QAAA;AAAA,MAEhC,OAAO;AACL,eAAO;AAAA,UACL,MAAMA,MAAAA,WAAS;AAAA,UACf,YAAY,CAAA;AAAA,QAAC;AAAA,MAEjB;AAAA,IACF,KAAK,EAAE;AACL,aAAO;AAAA,QACL,MAAMA,MAAAA,WAAS;AAAA,QACf,MAAO,EAAmB;AAAA,QAC1B,UAAW,EAAmB;AAAA,QAC9B,UAAW,EAAmB;AAAA,QAC9B;AAAA,MAAA;AAAA,IAEJ,KAAK,EAAE;AACL,aAAO,qBAAqB,GAAkB;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH,KAAK,EAAE;AACL,aAAO,kBAAkB,GAAW;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH,KAAK,EAAE;AACL,aAAO;AAAA,QACL,MAAMA,MAAAA,WAAS;AAAA,QACf,aAAa;AAAA,QACb;AAAA,MAAA;AAAA,IAEJ,KAAK,EAAE;AACL,aAAO;AAAA,QACL,MAAMA,MAAAA,WAAS;AAAA,QACf,aAAaF,MAAAA,MAAI,YAAY,CAAY,KAAK;AAAA,QAC9C;AAAA,MAAA;AAAA,IAEJ;AACE,aAAO;AAAA,EAAA;AAEb;AAEA,SAAS,UAAU,KAAe,QAAoC;AACpE,MAAI,CAAC,OAAO,QAAQ,GAAG,EAAG,QAAO;AACjC,QAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,SAAO,UAAU,IAAI,SAAY;AACnC;AAEA,SAAS,kBACP,GACA,SAMgB;;AAChB,QAAM,EAAE,WAAW,YAAY,OAAA,IAAW;AAG1C,QAAM,SAASA,MAAAA,MAAI,WAAW,CAAC;AAC/B,QAAM,gBAAgB,UAAW,OAAuB;AACxD,MAAI,OAAOA,MAAAA,MAAI,YAAY,CAAC;AAC5B,QAAM,UAAU,kBAAkB,UAAU,OAAO;AACnD,QAAM,WAAW,kBAAkB,WAAW,OAAO;AACrD,MAAI,WAAW,MAAM;AACnB,QAAI;AAEF,UAAI,EAAE,eAAe,EAAE,iBAAiB;AAAA,MAKxC,YAAY,YAA4B,UAA5B,mBAAmC,UAAU;AACvD,eAAOG,MAAAA,oBAAqB,OAA4B,KAAM;AAAA,MAChE;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN,wDAAwD,GAAa;AAAA,QACrE;AAAA,MAAA;AAAA,IAEJ;AACA,WAAOJ,MAAAA,eAAe,MAAM,QAAQ,QAAQ,GAAG,CAAC;AAAA,EAClD;AACA,MAAI,UAAU;AACZ,WAAO;AAAA,EACT;AACA,MAAI,CAAC,WAAW,CAAC,YAAY,QAAQ,WAAW;AAC9C,WAAO,aACH,WAAW,MAAMC,MAAAA,MAAI,cAAc,CAAC,CAAC,IACrC,KAAK,QAAQ,SAAS,GAAG;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL,MAAME,MAAAA,WAAS;AAAA,IACf,aAAa,QAAQ;AAAA,IACrB;AAAA,IACA;AAAA,EAAA;AAEJ;AAEA,SAAS,eAAe,KAAe,MAAc;AACnD,SAAO,MAAM,KAAK,IAAI,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAChE;AAUA,SAAS,SAAS,GAAgC;AAChD,SAAQ,EAAsB;AAChC;AAEA,SAAS,qBACP,GACA,SAiBwB;;AACxB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,CAAA;AAAA,IACnB;AAAA,IACA,iBAAiB,CAAA;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,IACpB;AAAA,EAAA,IACE;AACJ,QAAM,YAAY,kBAAkB,GAAG,YAAY,aAAa;AAChE,QAAM,UAAU,gBAAgB,CAAC;AACjC,MAAI,aAAyB,CAAA;AAC7B,QAAM,MAAM,EAAE,WAAW;AACzB,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,UAAM,OAAO,EAAE,WAAW,CAAC;AAC3B,QAAI,CAAC,gBAAgB,SAAS,KAAK,MAAM,KAAK,KAAK,GAAG;AACpD,iBAAW,KAAK,IAAI,IAAI;AAAA,QACtB;AAAA,QACA;AAAA,QACAN,MAAAA,YAAY,KAAK,IAAI;AAAA,QACrB,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAEA,MAAI,YAAY,UAAU,kBAAkB;AAE1C,UAAM,OAA2B,SAAS,CAAC;AAC3C,QAAI,MAAM;AACR,UAAI,aAAa,eAAe,KAAK,IAAI;AACzC,UAAI,CAAC,cAAc,KAAK,SAAS,MAAM,GAAG;AACxC,cAAM,aAAa,OAAO,SAAS;AACnC,cAAM,iBAAiB,KAAK,QAAQ,OAAO,SAAS,MAAM,EAAE;AAC5D,cAAM,0BAA0B,aAAa,MAAM;AACnD,qBAAa,eAAe,KAAK,uBAAuB;AAAA,MAC1D;AACA,UAAI,UAAyB;AAC7B,UAAI,YAAY;AACd,kBAAUO,MAAAA,oBAAoB,UAAU;AAAA,MAC1C;AACA,UAAI,SAAS;AACX,eAAO,WAAW;AAClB,eAAO,WAAW;AAClB,mBAAW,WAAW;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAEA,MACE,YAAY,WACX,EAAuB;AAAA,EAExB,EAAE,EAAE,aAAaH,YAAI,YAAY,CAAC,KAAK,IAAI,KAAA,EAAO,QAClD;AACA,UAAM,UAAUG,MAAAA;AAAAA,MACb,EAAuB;AAAA,IAAA;AAE1B,QAAI,SAAS;AACX,iBAAW,WAAW;AAAA,IACxB;AAAA,EACF;AAEA,MAAI,YAAY,WAAW,YAAY,cAAc,YAAY,UAAU;AACzE,UAAM,QAAS,EAA6C;AAC5D,UAAM,UAAW,EAAuB;AACxC,QACE,WAAW,SAAS,WACpB,WAAW,SAAS,cACpB,WAAW,SAAS,YACpB,WAAW,SAAS,YACpB,OACA;AACA,iBAAW,QAAQC,qBAAe;AAAA,QAChC,SAAS;AAAA,QACT,MAAMC,MAAAA,aAAa,CAAC;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH,WAAW,SAAS;AAClB,iBAAW,UAAU;AAAA,IACvB;AAAA,EACF;AACA,MAAI,YAAY,UAAU;AACxB,QAAK,EAAwB,YAAY,CAAC,iBAAiB,QAAQ,GAAG;AACpE,iBAAW,WAAW;AAAA,IACxB,OAAO;AAGL,aAAO,WAAW;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,YAAY,YAAa,EAAwB,MAAM;AAIzD,QAAI;AACD,iBAAgC,eAAe,EAAE,QAAQ,cAAc,IACpE,UACA;AAAA,IACN,QAAQ;AAIN,iBAAW,eAAe;AAC1B,iBAAW,+BAA+B;AAAA,IAC5C;AAAA,EACF;AAGA,MAAI,YAAY,YAAY,cAAc;AACxC,QAAK,EAAc,cAAc,MAAM;AAErC,UAAI,CAACC,MAAAA,gBAAgB,CAAsB,GAAG;AAC5C,mBAAW,aAAc,EAAwB;AAAA,UAC/C,eAAe;AAAA,UACf,eAAe;AAAA,QAAA;AAAA,MAEnB;AAAA,IACF,WAAW,EAAE,eAAe,IAAI;AAE9B,YAAM,gBAAiB,EAAwB;AAAA,QAC7C,eAAe;AAAA,QACf,eAAe;AAAA,MAAA;AAIjB,YAAM,cAAc,IAAI,cAAc,QAAQ;AAC9C,kBAAY,QAAS,EAAwB;AAC7C,kBAAY,SAAU,EAAwB;AAC9C,YAAM,qBAAqB,YAAY;AAAA,QACrC,eAAe;AAAA,QACf,eAAe;AAAA,MAAA;AAIjB,UAAI,kBAAkB,oBAAoB;AACxC,mBAAW,aAAa;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,cAAc;AACrC,QAAI,CAAC,eAAe;AAClB,sBAAgB,IAAI,cAAc,QAAQ;AAC1C,kBAAY,cAAc,WAAW,IAAI;AAAA,IAC3C;AACA,UAAM,QAAQ;AACd,UAAM,WACJ,MAAM,cAAc,MAAM,aAAa,KAAK,KAAK;AACnD,UAAM,mBAAmB,MAAM;AAC/B,UAAM,oBAAoB,MAAM;AAC9B,YAAM,oBAAoB,QAAQ,iBAAiB;AACnD,UAAI;AACF,sBAAe,QAAQ,MAAM;AAC7B,sBAAe,SAAS,MAAM;AAC9B,kBAAW,UAAU,OAAO,GAAG,CAAC;AAChC,mBAAW,aAAa,cAAe;AAAA,UACrC,eAAe;AAAA,UACf,eAAe;AAAA,QAAA;AAAA,MAEnB,SAAS,KAAK;AACZ,YAAI,MAAM,gBAAgB,aAAa;AACrC,gBAAM,cAAc;AACpB,cAAI,MAAM,YAAY,MAAM,iBAAiB;AAC3C,8BAAA;AAAA,cACG,OAAM,iBAAiB,QAAQ,iBAAiB;AACrD;AAAA,QACF,OAAO;AACL,kBAAQ;AAAA,YACN,yBAAyB,QAAQ,YAAY,GAAa;AAAA,UAAA;AAAA,QAE9D;AAAA,MACF;AACA,UAAI,MAAM,gBAAgB,aAAa;AACrC,2BACK,WAAW,cAAc,mBAC1B,MAAM,gBAAgB,aAAa;AAAA,MACzC;AAAA,IACF;AAEA,QAAI,MAAM,YAAY,MAAM,iBAAiB,EAAG,mBAAA;AAAA,QAC3C,OAAM,iBAAiB,QAAQ,iBAAiB;AAAA,EACvD;AAEA,MAAI,YAAY,WAAW,YAAY,SAAS;AAC9C,UAAM,kBAAkB;AACxB,oBAAgB,gBAAiB,EAAuB,SACpD,WACA;AACJ,oBAAgB,sBAAuB,EAAuB;AAC9D,oBAAgB,uBAAwB,EAAuB;AAC/D,oBAAgB,gBAAiB,EAAuB;AACxD,oBAAgB,eAAgB,EAAuB;AACvD,oBAAgB,iBAAkB,EAAuB;AAAA,EAC3D;AAEA,MAAI,CAAC,mBAAmB;AAKtB,QAAI,EAAE,YAAY;AAChB,iBAAW,gBAAgB,EAAE;AAAA,IAC/B;AACA,QAAI,EAAE,WAAW;AACf,iBAAW,eAAe,EAAE;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,WAAW;AACb,UAAM,EAAE,OAAO,QAAQ,MAAM,IAAA,IAAQ,EAAE,sBAAA;AACvC,iBAAa;AAAA,MACX,OAAO,WAAW;AAAA,MAClB,UAAU,GAAG,KAAK;AAAA,MAClB,WAAW,GAAG,MAAM;AAAA,MACpB,SAAS,GAAG,KAAK,MAAM,UAAQ,SAAI,gBAAJ,mBAAiB,YAAW,EAAE,CAAC;AAAA,MAC9D,QAAQ,GAAG,KAAK,MAAM,SAAO,SAAI,gBAAJ,mBAAiB,YAAW,EAAE,CAAC;AAAA,IAAA;AAAA,EAEhE;AAEA,MAAI,YAAY,YAAY,CAAC,gBAAgB,WAAW,GAAa,GAAG;AACtE,QAAI,CAAE,EAAwB,iBAAiB;AAG7C,iBAAW,SAAS,WAAW;AAAA,IACjC;AACA,WAAO,WAAW;AAAA,EACpB;AAEA,MAAI;AACJ,MAAI;AACF,QAAI,eAAe,IAAI,OAAO,EAAG,mBAAkB;AAAA,EACrD,SAAS,GAAG;AAAA,EAEZ;AAEA,SAAO;AAAA,IACL,MAAMJ,MAAAA,WAAS;AAAA,IACf;AAAA,IACA;AAAA,IACA,YAAY,CAAA;AAAA,IACZ,OAAO,aAAa,CAAY,KAAK;AAAA,IACrC;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EAAA;AAEd;AAEA,SAAS,cACP,WACQ;AACR,MAAI,cAAc,UAAa,cAAc,MAAM;AACjD,WAAO;AAAA,EACT,OAAO;AACL,WAAQ,UAAqB,YAAA;AAAA,EAC/B;AACF;AAEA,SAAS,gBACP,IACA,gBACS;AACT,MAAI,eAAe,WAAW,GAAG,SAASA,MAAAA,WAAS,SAAS;AAE1D,WAAO;AAAA,EACT,WAAW,GAAG,SAASA,MAAAA,WAAS,SAAS;AACvC,QACE,eAAe;AAAA,KAEd,GAAG,YAAY;AAAA,IAEb,GAAG,YAAY,WACZ,GAAG,WAAW,QAAQ,aAAa,GAAG,WAAW,OAAO,YACxD,GAAG,WAAW,QAAQ;AAAA,IAEzB,GAAG,YAAY,UACd,GAAG,WAAW,QAAQ,cACtB,OAAO,GAAG,WAAW,SAAS,YAC9BK,2BAAqB,GAAG,WAAW,IAAI,MAAM,OACjD;AACA,aAAO;AAAA,IACT,WACE,eAAe,gBACb,GAAG,YAAY,UAAU,GAAG,WAAW,QAAQ,mBAC9C,GAAG,YAAY,WACb,cAAc,GAAG,WAAW,IAAI,EAAE;AAAA,MACjC;AAAA,IAAA,KAEA,cAAc,GAAG,WAAW,IAAI,MAAM,sBACtC,cAAc,GAAG,WAAW,GAAG,MAAM,UACrC,cAAc,GAAG,WAAW,GAAG,MAAM,sBACrC,cAAc,GAAG,WAAW,GAAG,MAAM,mBAC3C;AACA,aAAO;AAAA,IACT,WAAW,GAAG,YAAY,QAAQ;AAChC,UACE,eAAe,wBACf,cAAc,GAAG,WAAW,IAAI,EAAE,MAAM,wBAAwB,GAChE;AACA,eAAO;AAAA,MACT,WACE,eAAe,mBACd,cAAc,GAAG,WAAW,QAAQ,EAAE,MAAM,mBAAmB;AAAA,MAC9D,cAAc,GAAG,WAAW,IAAI,EAAE,MAAM,gBAAgB,KACxD,cAAc,GAAG,WAAW,IAAI,MAAM,cACxC;AACA,eAAO;AAAA,MACT,WACE,eAAe,mBACd,cAAc,GAAG,WAAW,IAAI,MAAM,YACrC,cAAc,GAAG,WAAW,IAAI,MAAM,eACtC,cAAc,GAAG,WAAW,IAAI,MAAM,YACxC;AACA,eAAO;AAAA,MACT,WACE,eAAe,qBACf,GAAG,WAAW,YAAY,MAAM,QAChC;AAGA,eAAO;AAAA,MACT,WACE,eAAe,uBACd,cAAc,GAAG,WAAW,IAAI,MAAM,YACrC,cAAc,GAAG,WAAW,IAAI,MAAM,eACtC,cAAc,GAAG,WAAW,IAAI,MAAM,eACtC,cAAc,GAAG,WAAW,IAAI,MAAM,eACtC,cAAc,GAAG,WAAW,IAAI,MAAM,YACtC,cAAc,GAAG,WAAW,QAAQ,EAAE,MAAM,WAAW,KACvD,cAAc,GAAG,WAAW,QAAQ,EAAE,MAAM,WAAW,IACzD;AACA,eAAO;AAAA,MACT,WACE,eAAe,yBACd,cAAc,GAAG,WAAW,IAAI,MAAM,8BACrC,cAAc,GAAG,WAAW,IAAI,MAAM,yBACtC,cAAc,GAAG,WAAW,IAAI,MAAM,gBACtC,cAAc,GAAG,WAAW,IAAI,MAAM,qBACtC,cAAc,GAAG,WAAW,IAAI,MAAM,eACtC,cAAc,GAAG,WAAW,IAAI,MAAM,kBACtC,cAAc,GAAG,WAAW,IAAI,MAAM,+BACxC;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,oBACd,GACA,SAgC6B;AAC7B,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,mBAAmB,CAAA;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,CAAA;AAAA,IACjB,eAAe;AAAA,IACf,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,IACpB;AAAA,IACA,wBAAwB;AAAA,IACxB,kBAAkB,MAAM;AAAA,IACxB,oBAAoB;AAAA,EAAA,IAClB;AACJ,MAAI,EAAE,cAAc;AACpB,MAAI,EAAE,qBAAqB,KAAA,IAAS;AAEpC,MAAI,CAAC,WAAW;AAEd,UAAM,iBAAiB,cAAc;AACrC,gBAAY;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,kBAAkB,cAAc,GAAG;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AACD,MAAI,CAAC,iBAAiB;AAEpB,YAAQ,KAAK,GAAG,gBAAgB;AAChC,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI,OAAO,QAAQ,CAAC,GAAG;AAErB,SAAK,OAAO,MAAM,CAAC;AAAA,EACrB,WACE,gBAAgB,iBAAiB,cAAc,KAC9C,CAAC,sBACA,gBAAgB,SAASL,MAAAA,WAAS,QAClC,CAAC,gBAAgB,WACjB,CAAC,gBAAgB,YAAY,QAAQ,eAAe,EAAE,EAAE,QAC1D;AACA,SAAK;AAAA,EACP,OAAO;AACL,SAAK,MAAA;AAAA,EACP;AAEA,QAAM,iBAAiB,OAAO,OAAO,iBAAiB,EAAE,IAAI;AAE5D,SAAO,IAAI,GAAG,cAAc;AAE5B,MAAI,OAAO,cAAc;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,aAAa;AACf,gBAAY,CAAC;AAAA,EACf;AACA,MAAI,cAAc,CAAC;AACnB,MAAI,eAAe,SAASA,MAAAA,WAAS,SAAS;AAC5C,kBAAc,eAAe,CAAC,eAAe;AAE7C,WAAO,eAAe;AACtB,UAAM,eAAeF,MAAAA,MAAI,WAAW,CAAC;AACrC,QAAI,gBAAgBQ,MAAAA,kBAAkB,YAAY;AAChD,qBAAe,eAAe;AAAA,EAClC;AACA,OACG,eAAe,SAASN,iBAAS,YAChC,eAAe,SAASA,MAAAA,WAAS,YACnC,aACA;AACA,QACE,eAAe,kBACf,eAAe,SAASA,MAAAA,WAAS,WACjC,eAAe,YAAY,QAE3B;AACA,2BAAqB;AAAA,IACvB;AACA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAGF,QACE,eAAe,SAASA,iBAAS,WACjC,eAAe,YAAY,cAC1B,eAA+B,WAAW,UAAU,OACrD;AAAA,SAEK;AACL,iBAAW,UAAU,MAAM,KAAKF,MAAAA,MAAI,WAAW,CAAC,CAAC,GAAG;AAClD,cAAM,sBAAsB,oBAAoB,QAAQ,aAAa;AACrE,YAAI,qBAAqB;AACvB,yBAAe,WAAW,KAAK,mBAAmB;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAkC;AACtC,QAAIC,MAAAA,UAAU,CAAC,MAAM,eAAeD,MAAAA,MAAI,WAAW,CAAC,IAAI;AACtD,iBAAW,UAAU,MAAM,KAAKA,MAAAA,MAAI,WAAW,YAAY,CAAC,GAAG;AAC7D,cAAM,sBAAsB,oBAAoB,QAAQ,aAAa;AACrE,YAAI,qBAAqB;AACvBQ,gBAAAA,kBAAkB,YAAY,MAC3B,oBAAoB,WAAW;AAClC,yBAAe,WAAW,KAAK,mBAAmB;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAASR,MAAAA,MAAI,WAAW,CAAC;AAC/B,MAAI,UAAUS,MAAAA,aAAa,MAAM,KAAKD,MAAAA,kBAAkB,MAAM,GAAG;AAC/D,mBAAe,WAAW;AAAA,EAC5B;AAEA,MACE,eAAe,SAASN,MAAAA,WAAS,WACjC,eAAe,YAAY,UAC3B;AACA;AAAA,MACE;AAAA,MACA,MAAM;AACJ,cAAM,YAAa,EAAwB;AAC3C,YAAI,aAAa,cAAc;AAC7B,gBAAM,uBAAuB,oBAAoB,WAAW;AAAA,YAC1D,KAAK;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,WAAW;AAAA,YACX;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA,CACD;AAED,cAAI,sBAAsB;AACxB;AAAA,cACE;AAAA,cACA;AAAA,YAAA;AAAA,UAEJ;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAGA,MACE,eAAe,SAASA,MAAAA,WAAS,WACjC,eAAe,YAAY,UAC3B,OAAO,eAAe,WAAW,QAAQ,aACxC,eAAe,WAAW,QAAQ,gBAChC,eAAe,WAAW,QAAQ,aACjC,OAAO,eAAe,WAAW,SAAS,YAC1CK,MAAAA,qBAAqB,eAAe,WAAW,IAAI,MAAM,QAC7D;AACA;AAAA,MACE;AAAA,MACA,MAAM;AACJ,YAAI,kBAAkB;AACpB,gBAAM,qBAAqB,oBAAoB,GAAG;AAAA,YAChD;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,WAAW;AAAA,YACX;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA,CACD;AAED,cAAI,oBAAoB;AACtB;AAAA,cACE;AAAA,cACA;AAAA,YAAA;AAAA,UAEJ;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AACT;AAEA,SAAS,SACP,GACA,SA4B6B;AAC7B,QAAM;AAAA,IACJ,SAAS,IAAIG,MAAAA,OAAA;AAAA,IACb,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,MAAM;AAAA,EAAA,IACtB,WAAW,CAAA;AACf,QAAM,mBACJ,kBAAkB,OACd;AAAA,IACE,OAAO;AAAA,IACP,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,EAAA,IAEZ,kBAAkB,QAClB;AAAA,IACE,UAAU;AAAA,EAAA,IAEZ;AACN,QAAM,iBACJ,YAAY,QAAQ,YAAY;AAAA;AAAA,IAE5B;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,sBAAsB,YAAY;AAAA;AAAA,MAClC,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,MACpB,sBAAsB;AAAA,IAAA;AAAA,MAExB,YAAY,QACZ,CAAA,IACA;AACN,SAAO,oBAAoB,GAAG;AAAA,IAC5B,KAAK;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,EAAA,CACpB;AACH;AAEO,SAAS,cACd,MACA,SACA;AACA,WAAS,KAAK,SAA+B;AAC3C,YAAQ,OAAO;AACf,QACE,QAAQ,SAASR,iBAAS,YAC1B,QAAQ,SAASA,MAAAA,WAAS,SAC1B;AACA,cAAQ,WAAW,QAAQ,IAAI;AAAA,IACjC;AAAA,EACF;AAEA,OAAK,IAAI;AACX;AAEO,SAAS,kBAAkB;AAEhC,QAAM;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"record.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 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 const DEFAULT_MAX_DEPTH = 50;\n\nlet _maxDepthWarned = false;\nlet _maxDepthReached = false;\n\nexport function wasMaxDepthReached(): boolean {\n return _maxDepthReached;\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\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 =\n slimDOM === true || slimDOM === '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: slimDOM === 'all', // destructive\n headMetaSocial: true,\n headMetaRobots: true,\n headMetaHttpEquiv: true,\n headMetaAuthorship: true,\n headMetaVerification: true,\n }\n : slimDOM === false\n ? {}\n : 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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"}
package/dist/record.d.cts CHANGED
@@ -40,6 +40,8 @@ declare interface CSSImportRule_2 extends CSSRule {
40
40
  readonly supportsText?: string | null;
41
41
  }
42
42
 
43
+ export declare const DEFAULT_MAX_DEPTH = 50;
44
+
43
45
  export declare type DialogAttributes = {
44
46
  open: string;
45
47
  rr_open_mode: 'modal' | 'non-modal';
@@ -203,6 +205,9 @@ export declare function serializeNodeWithId(n: Node, options: {
203
205
  iframeLoadTimeout?: number;
204
206
  onStylesheetLoad?: (linkNode: HTMLLinkElement, node: serializedElementNodeWithId_2) => unknown;
205
207
  stylesheetLoadTimeout?: number;
208
+ depth?: number;
209
+ maxDepth?: number;
210
+ onMaxDepthReached?: () => void;
206
211
  }): serializedNodeWithId | null;
207
212
 
208
213
  export declare type SlimDOMOptions = Partial<{
@@ -240,6 +245,7 @@ export declare function snapshot(n: Document, options?: {
240
245
  onStylesheetLoad?: (linkNode: HTMLLinkElement, node: serializedElementNodeWithId_2) => unknown;
241
246
  stylesheetLoadTimeout?: number;
242
247
  keepIframeSrcFn?: KeepIframeSrcFn;
248
+ maxDepth?: number;
243
249
  }): serializedNodeWithId | null;
244
250
 
245
251
  export declare function stringifyRule(rule: CSSRule, sheetHref: string | null): string;
@@ -262,4 +268,6 @@ export declare function transformAttribute(doc: Document, tagName: Lowercase<str
262
268
 
263
269
  export declare function visitSnapshot(node: serializedNodeWithId, onVisit: (node: serializedNodeWithId) => unknown): void;
264
270
 
271
+ export declare function wasMaxDepthReached(): boolean;
272
+
265
273
  export { }
package/dist/record.d.ts CHANGED
@@ -40,6 +40,8 @@ declare interface CSSImportRule_2 extends CSSRule {
40
40
  readonly supportsText?: string | null;
41
41
  }
42
42
 
43
+ export declare const DEFAULT_MAX_DEPTH = 50;
44
+
43
45
  export declare type DialogAttributes = {
44
46
  open: string;
45
47
  rr_open_mode: 'modal' | 'non-modal';
@@ -203,6 +205,9 @@ export declare function serializeNodeWithId(n: Node, options: {
203
205
  iframeLoadTimeout?: number;
204
206
  onStylesheetLoad?: (linkNode: HTMLLinkElement, node: serializedElementNodeWithId_2) => unknown;
205
207
  stylesheetLoadTimeout?: number;
208
+ depth?: number;
209
+ maxDepth?: number;
210
+ onMaxDepthReached?: () => void;
206
211
  }): serializedNodeWithId | null;
207
212
 
208
213
  export declare type SlimDOMOptions = Partial<{
@@ -240,6 +245,7 @@ export declare function snapshot(n: Document, options?: {
240
245
  onStylesheetLoad?: (linkNode: HTMLLinkElement, node: serializedElementNodeWithId_2) => unknown;
241
246
  stylesheetLoadTimeout?: number;
242
247
  keepIframeSrcFn?: KeepIframeSrcFn;
248
+ maxDepth?: number;
243
249
  }): serializedNodeWithId | null;
244
250
 
245
251
  export declare function stringifyRule(rule: CSSRule, sheetHref: string | null): string;
@@ -262,4 +268,6 @@ export declare function transformAttribute(doc: Document, tagName: Lowercase<str
262
268
 
263
269
  export declare function visitSnapshot(node: serializedNodeWithId, onVisit: (node: serializedNodeWithId) => unknown): void;
264
270
 
271
+ export declare function wasMaxDepthReached(): boolean;
272
+
265
273
  export { }
package/dist/record.js CHANGED
@@ -633,6 +633,12 @@ function slimDOMExcluded(sn, slimDOMOptions) {
633
633
  }
634
634
  return false;
635
635
  }
636
+ const DEFAULT_MAX_DEPTH = 50;
637
+ let _maxDepthWarned = false;
638
+ let _maxDepthReached = false;
639
+ function wasMaxDepthReached() {
640
+ return _maxDepthReached;
641
+ }
636
642
  function serializeNodeWithId(n, options) {
637
643
  const {
638
644
  doc,
@@ -656,10 +662,22 @@ function serializeNodeWithId(n, options) {
656
662
  onStylesheetLoad,
657
663
  stylesheetLoadTimeout = 5e3,
658
664
  keepIframeSrcFn = () => false,
659
- newlyAddedElement = false
665
+ newlyAddedElement = false,
666
+ depth = 0,
667
+ maxDepth = DEFAULT_MAX_DEPTH
660
668
  } = options;
661
669
  let { needsMask } = options;
662
670
  let { preserveWhiteSpace = true } = options;
671
+ if (depth >= maxDepth) {
672
+ _maxDepthReached = true;
673
+ if (!_maxDepthWarned) {
674
+ _maxDepthWarned = true;
675
+ console.warn(
676
+ `[rrweb-snapshot] DOM tree depth exceeded max depth of ${maxDepth}. Children beyond this depth will not be recorded. This may indicate deeply nested DOM structures.`
677
+ );
678
+ }
679
+ return null;
680
+ }
663
681
  if (!needsMask) {
664
682
  const checkAncestors = needsMask === void 0;
665
683
  needsMask = needMaskingText(
@@ -740,7 +758,9 @@ function serializeNodeWithId(n, options) {
740
758
  iframeLoadTimeout,
741
759
  onStylesheetLoad,
742
760
  stylesheetLoadTimeout,
743
- keepIframeSrcFn
761
+ keepIframeSrcFn,
762
+ depth: depth + 1,
763
+ maxDepth
744
764
  };
745
765
  if (serializedNode.type === NodeType.Element && serializedNode.tagName === "textarea" && serializedNode.attributes.value !== void 0) ;
746
766
  else {
@@ -795,7 +815,9 @@ function serializeNodeWithId(n, options) {
795
815
  iframeLoadTimeout,
796
816
  onStylesheetLoad,
797
817
  stylesheetLoadTimeout,
798
- keepIframeSrcFn
818
+ keepIframeSrcFn,
819
+ depth: depth + 1,
820
+ maxDepth
799
821
  });
800
822
  if (serializedIframeNode) {
801
823
  onIframeLoad(
@@ -836,7 +858,9 @@ function serializeNodeWithId(n, options) {
836
858
  iframeLoadTimeout,
837
859
  onStylesheetLoad,
838
860
  stylesheetLoadTimeout,
839
- keepIframeSrcFn
861
+ keepIframeSrcFn,
862
+ depth,
863
+ maxDepth
840
864
  });
841
865
  if (serializedLinkNode) {
842
866
  onStylesheetLoad(
@@ -872,7 +896,8 @@ function snapshot(n, options) {
872
896
  iframeLoadTimeout,
873
897
  onStylesheetLoad,
874
898
  stylesheetLoadTimeout,
875
- keepIframeSrcFn = () => false
899
+ keepIframeSrcFn = () => false,
900
+ maxDepth
876
901
  } = options || {};
877
902
  const maskInputOptions = maskAllInputs === true ? {
878
903
  color: true,
@@ -933,7 +958,8 @@ function snapshot(n, options) {
933
958
  onStylesheetLoad,
934
959
  stylesheetLoadTimeout,
935
960
  keepIframeSrcFn,
936
- newlyAddedElement: false
961
+ newlyAddedElement: false,
962
+ maxDepth
937
963
  });
938
964
  }
939
965
  function visitSnapshot(node, onVisit) {
@@ -949,6 +975,7 @@ function cleanupSnapshot() {
949
975
  _id = 1;
950
976
  }
951
977
  export {
978
+ DEFAULT_MAX_DEPTH,
952
979
  IGNORED_NODE,
953
980
  Mirror,
954
981
  N as NodeType,
@@ -979,6 +1006,7 @@ export {
979
1006
  stringifyStylesheet,
980
1007
  toLowerCase,
981
1008
  transformAttribute,
982
- visitSnapshot
1009
+ visitSnapshot,
1010
+ wasMaxDepthReached
983
1011
  };
984
1012
  //# sourceMappingURL=record.js.map