UNPKG

rrweb

Version:
1,466 lines (1,464 loc) 194 kB
var rrwebReplay = (function (exports) { 'use strict'; var NodeType$2; (function(NodeType2) { NodeType2[NodeType2["Document"] = 0] = "Document"; NodeType2[NodeType2["DocumentType"] = 1] = "DocumentType"; NodeType2[NodeType2["Element"] = 2] = "Element"; NodeType2[NodeType2["Text"] = 3] = "Text"; NodeType2[NodeType2["CDATA"] = 4] = "CDATA"; NodeType2[NodeType2["Comment"] = 5] = "Comment"; })(NodeType$2 || (NodeType$2 = {})); function isElement(n) { return n.nodeType === n.ELEMENT_NODE; } class Mirror$2 { constructor() { this.idNodeMap = /* @__PURE__ */ new Map(); this.nodeMetaMap = /* @__PURE__ */ new WeakMap(); } getId(n) { var _a; if (!n) return -1; const id = (_a = this.getMeta(n)) === null || _a === void 0 ? void 0 : _a.id; return id !== null && id !== void 0 ? id : -1; } getNode(id) { return this.idNodeMap.get(id) || null; } getIds() { return Array.from(this.idNodeMap.keys()); } getMeta(n) { return this.nodeMetaMap.get(n) || null; } removeNodeFromMap(n) { const id = this.getId(n); this.idNodeMap.delete(id); if (n.childNodes) { n.childNodes.forEach((childNode) => this.removeNodeFromMap(childNode)); } } has(id) { return this.idNodeMap.has(id); } hasNode(node) { return this.nodeMetaMap.has(node); } add(n, meta) { const id = meta.id; this.idNodeMap.set(id, n); this.nodeMetaMap.set(n, meta); } replace(id, n) { const oldNode = this.getNode(id); if (oldNode) { const meta = this.nodeMetaMap.get(oldNode); if (meta) this.nodeMetaMap.set(n, meta); } this.idNodeMap.set(id, n); } reset() { this.idNodeMap = /* @__PURE__ */ new Map(); this.nodeMetaMap = /* @__PURE__ */ new WeakMap(); } } function createMirror$2() { return new Mirror$2(); } function toLowerCase(str) { return str.toLowerCase(); } function isNodeMetaEqual(a, b) { if (!a || !b || a.type !== b.type) return false; if (a.type === NodeType$2.Document) return a.compatMode === b.compatMode; else if (a.type === NodeType$2.DocumentType) return a.name === b.name && a.publicId === b.publicId && a.systemId === b.systemId; else if (a.type === NodeType$2.Comment || a.type === NodeType$2.Text || a.type === NodeType$2.CDATA) return a.textContent === b.textContent; else if (a.type === NodeType$2.Element) return a.tagName === b.tagName && JSON.stringify(a.attributes) === JSON.stringify(b.attributes) && a.isSVG === b.isSVG && a.needBlock === b.needBlock; return false; } const commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; function parse(css, options = {}) { let lineno = 1; let column = 1; function updatePosition(str) { const lines = str.match(/\n/g); if (lines) { lineno += lines.length; } const i = str.lastIndexOf("\n"); column = i === -1 ? column + str.length : str.length - i; } function position() { const start = { line: lineno, column }; return (node) => { node.position = new Position(start); whitespace(); return node; }; } class Position { constructor(start) { this.start = start; this.end = { line: lineno, column }; this.source = options.source; } } Position.prototype.content = css; const errorsList = []; function error(msg) { const err = new Error(`${options.source || ""}:${lineno}:${column}: ${msg}`); err.reason = msg; err.filename = options.source; err.line = lineno; err.column = column; err.source = css; if (options.silent) { errorsList.push(err); } else { throw err; } } function stylesheet() { const rulesList = rules(); return { type: "stylesheet", stylesheet: { source: options.source, rules: rulesList, parsingErrors: errorsList } }; } function open() { return match(/^{\s*/); } function close() { return match(/^}/); } function rules() { let node; const rules2 = []; whitespace(); comments(rules2); while (css.length && css.charAt(0) !== "}" && (node = atrule() || rule())) { if (node) { rules2.push(node); comments(rules2); } } return rules2; } function match(re) { const m = re.exec(css); if (!m) { return; } const str = m[0]; updatePosition(str); css = css.slice(str.length); return m; } function whitespace() { match(/^\s*/); } function comments(rules2 = []) { let c; while (c = comment()) { if (c) { rules2.push(c); } c = comment(); } return rules2; } function comment() { const pos = position(); if (css.charAt(0) !== "/" || css.charAt(1) !== "*") { return; } let i = 2; while (css.charAt(i) !== "" && (css.charAt(i) !== "*" || css.charAt(i + 1) !== "/")) { ++i; } i += 2; if (css.charAt(i - 1) === "") { return error("End of comment missing"); } const str = css.slice(2, i - 2); column += 2; updatePosition(str); css = css.slice(i); column += 2; return pos({ type: "comment", comment: str }); } function selector() { const m = match(/^([^{]+)/); if (!m) { return; } return trim(m[0]).replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, "").replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, (m2) => { return m2.replace(/,/g, "\u200C"); }).split(/\s*(?![^(]*\)),\s*/).map((s) => { return s.replace(/\u200C/g, ","); }); } function declaration() { const pos = position(); const propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); if (!propMatch) { return; } const prop = trim(propMatch[0]); if (!match(/^:\s*/)) { return error(`property missing ':'`); } const val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); const ret = pos({ type: "declaration", property: prop.replace(commentre, ""), value: val ? trim(val[0]).replace(commentre, "") : "" }); match(/^[;\s]*/); return ret; } function declarations() { const decls = []; if (!open()) { return error(`missing '{'`); } comments(decls); let decl; while (decl = declaration()) { if (decl !== false) { decls.push(decl); comments(decls); } decl = declaration(); } if (!close()) { return error(`missing '}'`); } return decls; } function keyframe() { let m; const vals = []; const pos = position(); while (m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) { vals.push(m[1]); match(/^,\s*/); } if (!vals.length) { return; } return pos({ type: "keyframe", values: vals, declarations: declarations() }); } function atkeyframes() { const pos = position(); let m = match(/^@([-\w]+)?keyframes\s*/); if (!m) { return; } const vendor = m[1]; m = match(/^([-\w]+)\s*/); if (!m) { return error("@keyframes missing name"); } const name = m[1]; if (!open()) { return error(`@keyframes missing '{'`); } let frame; let frames = comments(); while (frame = keyframe()) { frames.push(frame); frames = frames.concat(comments()); } if (!close()) { return error(`@keyframes missing '}'`); } return pos({ type: "keyframes", name, vendor, keyframes: frames }); } function atsupports() { const pos = position(); const m = match(/^@supports *([^{]+)/); if (!m) { return; } const supports = trim(m[1]); if (!open()) { return error(`@supports missing '{'`); } const style = comments().concat(rules()); if (!close()) { return error(`@supports missing '}'`); } return pos({ type: "supports", supports, rules: style }); } function athost() { const pos = position(); const m = match(/^@host\s*/); if (!m) { return; } if (!open()) { return error(`@host missing '{'`); } const style = comments().concat(rules()); if (!close()) { return error(`@host missing '}'`); } return pos({ type: "host", rules: style }); } function atmedia() { const pos = position(); const m = match(/^@media *([^{]+)/); if (!m) { return; } const media = trim(m[1]); if (!open()) { return error(`@media missing '{'`); } const style = comments().concat(rules()); if (!close()) { return error(`@media missing '}'`); } return pos({ type: "media", media, rules: style }); } function atcustommedia() { const pos = position(); const m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); if (!m) { return; } return pos({ type: "custom-media", name: trim(m[1]), media: trim(m[2]) }); } function atpage() { const pos = position(); const m = match(/^@page */); if (!m) { return; } const sel = selector() || []; if (!open()) { return error(`@page missing '{'`); } let decls = comments(); let decl; while (decl = declaration()) { decls.push(decl); decls = decls.concat(comments()); } if (!close()) { return error(`@page missing '}'`); } return pos({ type: "page", selectors: sel, declarations: decls }); } function atdocument() { const pos = position(); const m = match(/^@([-\w]+)?document *([^{]+)/); if (!m) { return; } const vendor = trim(m[1]); const doc = trim(m[2]); if (!open()) { return error(`@document missing '{'`); } const style = comments().concat(rules()); if (!close()) { return error(`@document missing '}'`); } return pos({ type: "document", document: doc, vendor, rules: style }); } function atfontface() { const pos = position(); const m = match(/^@font-face\s*/); if (!m) { return; } if (!open()) { return error(`@font-face missing '{'`); } let decls = comments(); let decl; while (decl = declaration()) { decls.push(decl); decls = decls.concat(comments()); } if (!close()) { return error(`@font-face missing '}'`); } return pos({ type: "font-face", declarations: decls }); } const atimport = _compileAtrule("import"); const atcharset = _compileAtrule("charset"); const atnamespace = _compileAtrule("namespace"); function _compileAtrule(name) { const re = new RegExp("^@" + name + "\\s*([^;]+);"); return () => { const pos = position(); const m = match(re); if (!m) { return; } const ret = { type: name }; ret[name] = m[1].trim(); return pos(ret); }; } function atrule() { if (css[0] !== "@") { return; } return atkeyframes() || atmedia() || atcustommedia() || atsupports() || atimport() || atcharset() || atnamespace() || atdocument() || atpage() || athost() || atfontface(); } function rule() { const pos = position(); const sel = selector(); if (!sel) { return error("selector missing"); } comments(); return pos({ type: "rule", selectors: sel, declarations: declarations() }); } return addParent(stylesheet()); } function trim(str) { return str ? str.replace(/^\s+|\s+$/g, "") : ""; } function addParent(obj, parent) { const isNode = obj && typeof obj.type === "string"; const childParent = isNode ? obj : parent; for (const k of Object.keys(obj)) { const value = obj[k]; if (Array.isArray(value)) { value.forEach((v) => { addParent(v, childParent); }); } else if (value && typeof value === "object") { addParent(value, childParent); } } if (isNode) { Object.defineProperty(obj, "parent", { configurable: true, writable: true, enumerable: false, value: parent || null }); } return obj; } const tagMap = { script: "noscript", altglyph: "altGlyph", altglyphdef: "altGlyphDef", altglyphitem: "altGlyphItem", animatecolor: "animateColor", animatemotion: "animateMotion", animatetransform: "animateTransform", clippath: "clipPath", feblend: "feBlend", fecolormatrix: "feColorMatrix", fecomponenttransfer: "feComponentTransfer", fecomposite: "feComposite", feconvolvematrix: "feConvolveMatrix", fediffuselighting: "feDiffuseLighting", fedisplacementmap: "feDisplacementMap", fedistantlight: "feDistantLight", fedropshadow: "feDropShadow", feflood: "feFlood", fefunca: "feFuncA", fefuncb: "feFuncB", fefuncg: "feFuncG", fefuncr: "feFuncR", fegaussianblur: "feGaussianBlur", feimage: "feImage", femerge: "feMerge", femergenode: "feMergeNode", femorphology: "feMorphology", feoffset: "feOffset", fepointlight: "fePointLight", fespecularlighting: "feSpecularLighting", fespotlight: "feSpotLight", fetile: "feTile", feturbulence: "feTurbulence", foreignobject: "foreignObject", glyphref: "glyphRef", lineargradient: "linearGradient", radialgradient: "radialGradient" }; function getTagName(n) { let tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; if (tagName === "link" && n.attributes._cssText) { tagName = "style"; } return tagName; } function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } const MEDIA_SELECTOR = /(max|min)-device-(width|height)/; const MEDIA_SELECTOR_GLOBAL = new RegExp(MEDIA_SELECTOR.source, "g"); const HOVER_SELECTOR = /([^\\]):hover/; const HOVER_SELECTOR_GLOBAL = new RegExp(HOVER_SELECTOR.source, "g"); function adaptCssForReplay(cssText, cache) { const cachedStyle = cache === null || cache === void 0 ? void 0 : cache.stylesWithHoverClass.get(cssText); if (cachedStyle) return cachedStyle; const ast = parse(cssText, { silent: true }); if (!ast.stylesheet) { return cssText; } const selectors = []; const medias = []; function getSelectors(rule) { if ("selectors" in rule && rule.selectors) { rule.selectors.forEach((selector) => { if (HOVER_SELECTOR.test(selector)) { selectors.push(selector); } }); } if ("media" in rule && rule.media && MEDIA_SELECTOR.test(rule.media)) { medias.push(rule.media); } if ("rules" in rule && rule.rules) { rule.rules.forEach(getSelectors); } } getSelectors(ast.stylesheet); let result = cssText; if (selectors.length > 0) { const selectorMatcher = new RegExp(selectors.filter((selector, index) => selectors.indexOf(selector) === index).sort((a, b) => b.length - a.length).map((selector) => { return escapeRegExp(selector); }).join("|"), "g"); result = result.replace(selectorMatcher, (selector) => { const newSelector = selector.replace(HOVER_SELECTOR_GLOBAL, "$1.\\:hover"); return `${selector}, ${newSelector}`; }); } if (medias.length > 0) { const mediaMatcher = new RegExp(medias.filter((media, index) => medias.indexOf(media) === index).sort((a, b) => b.length - a.length).map((media) => { return escapeRegExp(media); }).join("|"), "g"); result = result.replace(mediaMatcher, (media) => { return media.replace(MEDIA_SELECTOR_GLOBAL, "$1-$2"); }); } cache === null || cache === void 0 ? void 0 : cache.stylesWithHoverClass.set(cssText, result); return result; } function createCache() { const stylesWithHoverClass = /* @__PURE__ */ new Map(); return { stylesWithHoverClass }; } function buildNode(n, options) { var _a; const { doc, hackCss, cache } = options; switch (n.type) { case NodeType$2.Document: return doc.implementation.createDocument(null, "", null); case NodeType$2.DocumentType: return doc.implementation.createDocumentType(n.name || "html", n.publicId, n.systemId); case NodeType$2.Element: { const tagName = getTagName(n); let node; if (n.isSVG) { node = doc.createElementNS("http://www.w3.org/2000/svg", tagName); } else { if (n.isCustom && ((_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.customElements) && !doc.defaultView.customElements.get(n.tagName)) doc.defaultView.customElements.define(n.tagName, class extends doc.defaultView.HTMLElement { }); node = doc.createElement(tagName); } const specialAttributes = {}; for (const name in n.attributes) { if (!Object.prototype.hasOwnProperty.call(n.attributes, name)) { continue; } let value = n.attributes[name]; if (tagName === "option" && name === "selected" && value === false) { continue; } if (value === null) { continue; } if (value === true) value = ""; if (name.startsWith("rr_")) { specialAttributes[name] = value; continue; } const isTextarea = tagName === "textarea" && name === "value"; const isRemoteOrDynamicCss = tagName === "style" && name === "_cssText"; if (isRemoteOrDynamicCss && hackCss && typeof value === "string") { value = adaptCssForReplay(value, cache); } if ((isTextarea || isRemoteOrDynamicCss) && typeof value === "string") { node.appendChild(doc.createTextNode(value)); n.childNodes = []; continue; } try { if (n.isSVG && name === "xlink:href") { node.setAttributeNS("http://www.w3.org/1999/xlink", name, value.toString()); } else if (name === "onload" || name === "onclick" || name.substring(0, 7) === "onmouse") { node.setAttribute("_" + name, value.toString()); } else if (tagName === "meta" && n.attributes["http-equiv"] === "Content-Security-Policy" && name === "content") { node.setAttribute("csp-content", value.toString()); continue; } else if (tagName === "link" && (n.attributes.rel === "preload" || n.attributes.rel === "modulepreload") && n.attributes.as === "script") { } else if (tagName === "link" && n.attributes.rel === "prefetch" && typeof n.attributes.href === "string" && n.attributes.href.endsWith(".js")) { } else if (tagName === "img" && n.attributes.srcset && n.attributes.rr_dataURL) { node.setAttribute("rrweb-original-srcset", n.attributes.srcset); } else { node.setAttribute(name, value.toString()); } } catch (error) { } } for (const name in specialAttributes) { const value = specialAttributes[name]; if (tagName === "canvas" && name === "rr_dataURL") { const image = document.createElement("img"); image.onload = () => { const ctx = node.getContext("2d"); if (ctx) { ctx.drawImage(image, 0, 0, image.width, image.height); } }; image.src = value.toString(); if (node.RRNodeType) node.rr_dataURL = value.toString(); } else if (tagName === "img" && name === "rr_dataURL") { const image = node; if (!image.currentSrc.startsWith("data:")) { image.setAttribute("rrweb-original-src", n.attributes.src); image.src = value.toString(); } } if (name === "rr_width") { node.style.width = value.toString(); } else if (name === "rr_height") { node.style.height = value.toString(); } else if (name === "rr_mediaCurrentTime" && typeof value === "number") { node.currentTime = value; } else if (name === "rr_mediaState") { switch (value) { case "played": node.play().catch((e) => console.warn("media playback error", e)); break; case "paused": node.pause(); break; } } } if (n.isShadowHost) { if (!node.shadowRoot) { node.attachShadow({ mode: "open" }); } else { while (node.shadowRoot.firstChild) { node.shadowRoot.removeChild(node.shadowRoot.firstChild); } } } return node; } case NodeType$2.Text: return doc.createTextNode(n.isStyle && hackCss ? adaptCssForReplay(n.textContent, cache) : n.textContent); case NodeType$2.CDATA: return doc.createCDATASection(n.textContent); case NodeType$2.Comment: return doc.createComment(n.textContent); default: return null; } } function buildNodeWithSN(n, options) { const { doc, mirror, skipChild = false, hackCss = true, afterAppend, cache } = options; if (mirror.has(n.id)) { const nodeInMirror = mirror.getNode(n.id); const meta = mirror.getMeta(nodeInMirror); if (isNodeMetaEqual(meta, n)) return mirror.getNode(n.id); } let node = buildNode(n, { doc, hackCss, cache }); if (!node) { return null; } if (n.rootId && mirror.getNode(n.rootId) !== doc) { mirror.replace(n.rootId, doc); } if (n.type === NodeType$2.Document) { doc.close(); doc.open(); if (n.compatMode === "BackCompat" && n.childNodes && n.childNodes[0].type !== NodeType$2.DocumentType) { if (n.childNodes[0].type === NodeType$2.Element && "xmlns" in n.childNodes[0].attributes && n.childNodes[0].attributes.xmlns === "http://www.w3.org/1999/xhtml") { doc.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">'); } else { doc.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "">'); } } node = doc; } mirror.add(node, n); if ((n.type === NodeType$2.Document || n.type === NodeType$2.Element) && !skipChild) { for (const childN of n.childNodes) { const childNode = buildNodeWithSN(childN, { doc, mirror, skipChild: false, hackCss, afterAppend, cache }); if (!childNode) { console.warn("Failed to rebuild", childN); continue; } if (childN.isShadow && isElement(node) && node.shadowRoot) { node.shadowRoot.appendChild(childNode); } else if (n.type === NodeType$2.Document && childN.type == NodeType$2.Element) { const htmlElement = childNode; let body = null; htmlElement.childNodes.forEach((child) => { if (child.nodeName === "BODY") body = child; }); if (body) { htmlElement.removeChild(body); node.appendChild(childNode); htmlElement.appendChild(body); } else { node.appendChild(childNode); } } else { node.appendChild(childNode); } if (afterAppend) { afterAppend(childNode, childN.id); } } } return node; } function visit(mirror, onVisit) { function walk(node) { onVisit(node); } for (const id of mirror.getIds()) { if (mirror.has(id)) { walk(mirror.getNode(id)); } } } function handleScroll(node, mirror) { const n = mirror.getMeta(node); if ((n === null || n === void 0 ? void 0 : n.type) !== NodeType$2.Element) { return; } const el = node; for (const name in n.attributes) { if (!(Object.prototype.hasOwnProperty.call(n.attributes, name) && name.startsWith("rr_"))) { continue; } const value = n.attributes[name]; if (name === "rr_scrollLeft") { el.scrollLeft = value; } if (name === "rr_scrollTop") { el.scrollTop = value; } } } function rebuild(n, options) { const { doc, onVisit, hackCss = true, afterAppend, cache, mirror = new Mirror$2() } = options; const node = buildNodeWithSN(n, { doc, mirror, skipChild: false, hackCss, afterAppend, cache }); visit(mirror, (visitedNode) => { if (onVisit) { onVisit(visitedNode); } handleScroll(visitedNode, mirror); }); return node; } var NodeType$1; (function(NodeType2) { NodeType2[NodeType2["Document"] = 0] = "Document"; NodeType2[NodeType2["DocumentType"] = 1] = "DocumentType"; NodeType2[NodeType2["Element"] = 2] = "Element"; NodeType2[NodeType2["Text"] = 3] = "Text"; NodeType2[NodeType2["CDATA"] = 4] = "CDATA"; NodeType2[NodeType2["Comment"] = 5] = "Comment"; })(NodeType$1 || (NodeType$1 = {})); class Mirror$1 { constructor() { this.idNodeMap = /* @__PURE__ */ new Map(); this.nodeMetaMap = /* @__PURE__ */ new WeakMap(); } getId(n) { var _a; if (!n) return -1; const id = (_a = this.getMeta(n)) === null || _a === void 0 ? void 0 : _a.id; return id !== null && id !== void 0 ? id : -1; } getNode(id) { return this.idNodeMap.get(id) || null; } getIds() { return Array.from(this.idNodeMap.keys()); } getMeta(n) { return this.nodeMetaMap.get(n) || null; } removeNodeFromMap(n) { const id = this.getId(n); this.idNodeMap.delete(id); if (n.childNodes) { n.childNodes.forEach((childNode) => this.removeNodeFromMap(childNode)); } } has(id) { return this.idNodeMap.has(id); } hasNode(node) { return this.nodeMetaMap.has(node); } add(n, meta) { const id = meta.id; this.idNodeMap.set(id, n); this.nodeMetaMap.set(n, meta); } replace(id, n) { const oldNode = this.getNode(id); if (oldNode) { const meta = this.nodeMetaMap.get(oldNode); if (meta) this.nodeMetaMap.set(n, meta); } this.idNodeMap.set(id, n); } reset() { this.idNodeMap = /* @__PURE__ */ new Map(); this.nodeMetaMap = /* @__PURE__ */ new WeakMap(); } } function createMirror$1() { return new Mirror$1(); } function parseCSSText(cssText) { const res = {}; const listDelimiter = /;(?![^(]*\))/g; const propertyDelimiter = /:(.+)/; const comment = /\/\*.*?\*\//g; cssText.replace(comment, "").split(listDelimiter).forEach(function(item) { if (item) { const tmp = item.split(propertyDelimiter); tmp.length > 1 && (res[camelize(tmp[0].trim())] = tmp[1].trim()); } }); return res; } function toCSSText(style) { const properties = []; for (const name in style) { const value = style[name]; if (typeof value !== "string") continue; const normalizedName = hyphenate(name); properties.push(`${normalizedName}: ${value};`); } return properties.join(" "); } const camelizeRE = /-([a-z])/g; const CUSTOM_PROPERTY_REGEX = /^--[a-zA-Z0-9-]+$/; const camelize = (str) => { if (CUSTOM_PROPERTY_REGEX.test(str)) return str; return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); }; const hyphenateRE = /\B([A-Z])/g; const hyphenate = (str) => { return str.replace(hyphenateRE, "-$1").toLowerCase(); }; class BaseRRNode { constructor(..._args) { this.parentElement = null; this.parentNode = null; this.firstChild = null; this.lastChild = null; this.previousSibling = null; this.nextSibling = null; this.ELEMENT_NODE = NodeType.ELEMENT_NODE; this.TEXT_NODE = NodeType.TEXT_NODE; } get childNodes() { const childNodes = []; let childIterator = this.firstChild; while (childIterator) { childNodes.push(childIterator); childIterator = childIterator.nextSibling; } return childNodes; } contains(node) { if (!(node instanceof BaseRRNode)) return false; else if (node.ownerDocument !== this.ownerDocument) return false; else if (node === this) return true; while (node.parentNode) { if (node.parentNode === this) return true; node = node.parentNode; } return false; } appendChild(_newChild) { throw new Error(`RRDomException: Failed to execute 'appendChild' on 'RRNode': This RRNode type does not support this method.`); } insertBefore(_newChild, _refChild) { throw new Error(`RRDomException: Failed to execute 'insertBefore' on 'RRNode': This RRNode type does not support this method.`); } removeChild(_node) { throw new Error(`RRDomException: Failed to execute 'removeChild' on 'RRNode': This RRNode type does not support this method.`); } toString() { return "RRNode"; } } function BaseRRDocumentImpl(RRNodeClass) { return class BaseRRDocument extends RRNodeClass { constructor(...args) { super(args); this.nodeType = NodeType.DOCUMENT_NODE; this.nodeName = "#document"; this.compatMode = "CSS1Compat"; this.RRNodeType = NodeType$1.Document; this.textContent = null; this.ownerDocument = this; } get documentElement() { return this.childNodes.find((node) => node.RRNodeType === NodeType$1.Element && node.tagName === "HTML") || null; } get body() { var _a; return ((_a = this.documentElement) === null || _a === void 0 ? void 0 : _a.childNodes.find((node) => node.RRNodeType === NodeType$1.Element && node.tagName === "BODY")) || null; } get head() { var _a; return ((_a = this.documentElement) === null || _a === void 0 ? void 0 : _a.childNodes.find((node) => node.RRNodeType === NodeType$1.Element && node.tagName === "HEAD")) || null; } get implementation() { return this; } get firstElementChild() { return this.documentElement; } appendChild(newChild) { const nodeType = newChild.RRNodeType; if (nodeType === NodeType$1.Element || nodeType === NodeType$1.DocumentType) { if (this.childNodes.some((s) => s.RRNodeType === nodeType)) { throw new Error(`RRDomException: Failed to execute 'appendChild' on 'RRNode': Only one ${nodeType === NodeType$1.Element ? "RRElement" : "RRDoctype"} on RRDocument allowed.`); } } const child = appendChild(this, newChild); child.parentElement = null; return child; } insertBefore(newChild, refChild) { const nodeType = newChild.RRNodeType; if (nodeType === NodeType$1.Element || nodeType === NodeType$1.DocumentType) { if (this.childNodes.some((s) => s.RRNodeType === nodeType)) { throw new Error(`RRDomException: Failed to execute 'insertBefore' on 'RRNode': Only one ${nodeType === NodeType$1.Element ? "RRElement" : "RRDoctype"} on RRDocument allowed.`); } } const child = insertBefore(this, newChild, refChild); child.parentElement = null; return child; } removeChild(node) { return removeChild(this, node); } open() { this.firstChild = null; this.lastChild = null; } close() { } write(content) { let publicId; if (content === '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">') publicId = "-//W3C//DTD XHTML 1.0 Transitional//EN"; else if (content === '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "">') publicId = "-//W3C//DTD HTML 4.0 Transitional//EN"; if (publicId) { const doctype = this.createDocumentType("html", publicId, ""); this.open(); this.appendChild(doctype); } } createDocument(_namespace, _qualifiedName, _doctype) { return new BaseRRDocument(); } createDocumentType(qualifiedName, publicId, systemId) { const doctype = new (BaseRRDocumentTypeImpl(BaseRRNode))(qualifiedName, publicId, systemId); doctype.ownerDocument = this; return doctype; } createElement(tagName) { const element = new (BaseRRElementImpl(BaseRRNode))(tagName); element.ownerDocument = this; return element; } createElementNS(_namespaceURI, qualifiedName) { return this.createElement(qualifiedName); } createTextNode(data) { const text = new (BaseRRTextImpl(BaseRRNode))(data); text.ownerDocument = this; return text; } createComment(data) { const comment = new (BaseRRCommentImpl(BaseRRNode))(data); comment.ownerDocument = this; return comment; } createCDATASection(data) { const CDATASection = new (BaseRRCDATASectionImpl(BaseRRNode))(data); CDATASection.ownerDocument = this; return CDATASection; } toString() { return "RRDocument"; } }; } function BaseRRDocumentTypeImpl(RRNodeClass) { return class BaseRRDocumentType extends RRNodeClass { constructor(qualifiedName, publicId, systemId) { super(); this.nodeType = NodeType.DOCUMENT_TYPE_NODE; this.RRNodeType = NodeType$1.DocumentType; this.name = qualifiedName; this.publicId = publicId; this.systemId = systemId; this.nodeName = qualifiedName; this.textContent = null; } toString() { return "RRDocumentType"; } }; } function BaseRRElementImpl(RRNodeClass) { return class BaseRRElement extends RRNodeClass { constructor(tagName) { super(); this.nodeType = NodeType.ELEMENT_NODE; this.RRNodeType = NodeType$1.Element; this.attributes = {}; this.shadowRoot = null; this.tagName = tagName.toUpperCase(); this.nodeName = tagName.toUpperCase(); } get textContent() { let result = ""; this.childNodes.forEach((node) => result += node.textContent); return result; } set textContent(textContent) { this.firstChild = null; this.lastChild = null; this.appendChild(this.ownerDocument.createTextNode(textContent)); } get classList() { return new ClassList(this.attributes.class, (newClassName) => { this.attributes.class = newClassName; }); } get id() { return this.attributes.id || ""; } get className() { return this.attributes.class || ""; } get style() { const style = this.attributes.style ? parseCSSText(this.attributes.style) : {}; const hyphenateRE2 = /\B([A-Z])/g; style.setProperty = (name, value, priority) => { if (hyphenateRE2.test(name)) return; const normalizedName = camelize(name); if (!value) delete style[normalizedName]; else style[normalizedName] = value; if (priority === "important") style[normalizedName] += " !important"; this.attributes.style = toCSSText(style); }; style.removeProperty = (name) => { if (hyphenateRE2.test(name)) return ""; const normalizedName = camelize(name); const value = style[normalizedName] || ""; delete style[normalizedName]; this.attributes.style = toCSSText(style); return value; }; return style; } getAttribute(name) { return this.attributes[name] || null; } setAttribute(name, attribute) { this.attributes[name] = attribute; } setAttributeNS(_namespace, qualifiedName, value) { this.setAttribute(qualifiedName, value); } removeAttribute(name) { delete this.attributes[name]; } appendChild(newChild) { return appendChild(this, newChild); } insertBefore(newChild, refChild) { return insertBefore(this, newChild, refChild); } removeChild(node) { return removeChild(this, node); } attachShadow(_init) { const shadowRoot = this.ownerDocument.createElement("SHADOWROOT"); this.shadowRoot = shadowRoot; return shadowRoot; } dispatchEvent(_event) { return true; } toString() { let attributeString = ""; for (const attribute in this.attributes) { attributeString += `${attribute}="${this.attributes[attribute]}" `; } return `${this.tagName} ${attributeString}`; } }; } function BaseRRMediaElementImpl(RRElementClass) { return class BaseRRMediaElement extends RRElementClass { attachShadow(_init) { throw new Error(`RRDomException: Failed to execute 'attachShadow' on 'RRElement': This RRElement does not support attachShadow`); } play() { this.paused = false; } pause() { this.paused = true; } }; } function BaseRRTextImpl(RRNodeClass) { return class BaseRRText extends RRNodeClass { constructor(data) { super(); this.nodeType = NodeType.TEXT_NODE; this.nodeName = "#text"; this.RRNodeType = NodeType$1.Text; this.data = data; } get textContent() { return this.data; } set textContent(textContent) { this.data = textContent; } toString() { return `RRText text=${JSON.stringify(this.data)}`; } }; } function BaseRRCommentImpl(RRNodeClass) { return class BaseRRComment extends RRNodeClass { constructor(data) { super(); this.nodeType = NodeType.COMMENT_NODE; this.nodeName = "#comment"; this.RRNodeType = NodeType$1.Comment; this.data = data; } get textContent() { return this.data; } set textContent(textContent) { this.data = textContent; } toString() { return `RRComment text=${JSON.stringify(this.data)}`; } }; } function BaseRRCDATASectionImpl(RRNodeClass) { return class BaseRRCDATASection extends RRNodeClass { constructor(data) { super(); this.nodeName = "#cdata-section"; this.nodeType = NodeType.CDATA_SECTION_NODE; this.RRNodeType = NodeType$1.CDATA; this.data = data; } get textContent() { return this.data; } set textContent(textContent) { this.data = textContent; } toString() { return `RRCDATASection data=${JSON.stringify(this.data)}`; } }; } class ClassList { constructor(classText, onChange) { this.classes = []; this.add = (...classNames) => { for (const item of classNames) { const className = String(item); if (this.classes.indexOf(className) >= 0) continue; this.classes.push(className); } this.onChange && this.onChange(this.classes.join(" ")); }; this.remove = (...classNames) => { this.classes = this.classes.filter((item) => classNames.indexOf(item) === -1); this.onChange && this.onChange(this.classes.join(" ")); }; if (classText) { const classes = classText.trim().split(/\s+/); this.classes.push(...classes); } this.onChange = onChange; } } function appendChild(parent, newChild) { if (newChild.parentNode) newChild.parentNode.removeChild(newChild); if (parent.lastChild) { parent.lastChild.nextSibling = newChild; newChild.previousSibling = parent.lastChild; } else { parent.firstChild = newChild; newChild.previousSibling = null; } parent.lastChild = newChild; newChild.nextSibling = null; newChild.parentNode = parent; newChild.parentElement = parent; newChild.ownerDocument = parent.ownerDocument; return newChild; } function insertBefore(parent, newChild, refChild) { if (!refChild) return appendChild(parent, newChild); if (refChild.parentNode !== parent) throw new Error("Failed to execute 'insertBefore' on 'RRNode': The RRNode before which the new node is to be inserted is not a child of this RRNode."); if (newChild === refChild) return newChild; if (newChild.parentNode) newChild.parentNode.removeChild(newChild); newChild.previousSibling = refChild.previousSibling; refChild.previousSibling = newChild; newChild.nextSibling = refChild; if (newChild.previousSibling) newChild.previousSibling.nextSibling = newChild; else parent.firstChild = newChild; newChild.parentElement = parent; newChild.parentNode = parent; newChild.ownerDocument = parent.ownerDocument; return newChild; } function removeChild(parent, child) { if (child.parentNode !== parent) throw new Error("Failed to execute 'removeChild' on 'RRNode': The RRNode to be removed is not a child of this RRNode."); if (child.previousSibling) child.previousSibling.nextSibling = child.nextSibling; else parent.firstChild = child.nextSibling; if (child.nextSibling) child.nextSibling.previousSibling = child.previousSibling; else parent.lastChild = child.previousSibling; child.previousSibling = null; child.nextSibling = null; child.parentElement = null; child.parentNode = null; return child; } var NodeType; (function(NodeType2) { NodeType2[NodeType2["PLACEHOLDER"] = 0] = "PLACEHOLDER"; NodeType2[NodeType2["ELEMENT_NODE"] = 1] = "ELEMENT_NODE"; NodeType2[NodeType2["ATTRIBUTE_NODE"] = 2] = "ATTRIBUTE_NODE"; NodeType2[NodeType2["TEXT_NODE"] = 3] = "TEXT_NODE"; NodeType2[NodeType2["CDATA_SECTION_NODE"] = 4] = "CDATA_SECTION_NODE"; NodeType2[NodeType2["ENTITY_REFERENCE_NODE"] = 5] = "ENTITY_REFERENCE_NODE"; NodeType2[NodeType2["ENTITY_NODE"] = 6] = "ENTITY_NODE"; NodeType2[NodeType2["PROCESSING_INSTRUCTION_NODE"] = 7] = "PROCESSING_INSTRUCTION_NODE"; NodeType2[NodeType2["COMMENT_NODE"] = 8] = "COMMENT_NODE"; NodeType2[NodeType2["DOCUMENT_NODE"] = 9] = "DOCUMENT_NODE"; NodeType2[NodeType2["DOCUMENT_TYPE_NODE"] = 10] = "DOCUMENT_TYPE_NODE"; NodeType2[NodeType2["DOCUMENT_FRAGMENT_NODE"] = 11] = "DOCUMENT_FRAGMENT_NODE"; })(NodeType || (NodeType = {})); const NAMESPACES = { svg: "http://www.w3.org/2000/svg", "xlink:href": "http://www.w3.org/1999/xlink", xmlns: "http://www.w3.org/2000/xmlns/" }; const SVGTagMap = { altglyph: "altGlyph", altglyphdef: "altGlyphDef", altglyphitem: "altGlyphItem", animatecolor: "animateColor", animatemotion: "animateMotion", animatetransform: "animateTransform", clippath: "clipPath", feblend: "feBlend", fecolormatrix: "feColorMatrix", fecomponenttransfer: "feComponentTransfer", fecomposite: "feComposite", feconvolvematrix: "feConvolveMatrix", fediffuselighting: "feDiffuseLighting", fedisplacementmap: "feDisplacementMap", fedistantlight: "feDistantLight", fedropshadow: "feDropShadow", feflood: "feFlood", fefunca: "feFuncA", fefuncb: "feFuncB", fefuncg: "feFuncG", fefuncr: "feFuncR", fegaussianblur: "feGaussianBlur", feimage: "feImage", femerge: "feMerge", femergenode: "feMergeNode", femorphology: "feMorphology", feoffset: "feOffset", fepointlight: "fePointLight", fespecularlighting: "feSpecularLighting", fespotlight: "feSpotLight", fetile: "feTile", feturbulence: "feTurbulence", foreignobject: "foreignObject", glyphref: "glyphRef", lineargradient: "linearGradient", radialgradient: "radialGradient" }; let createdNodeSet = null; function diff(oldTree, newTree, replayer, rrnodeMirror = newTree.mirror || newTree.ownerDocument.mirror) { oldTree = diffBeforeUpdatingChildren(oldTree, newTree, replayer, rrnodeMirror); diffChildren(oldTree, newTree, replayer, rrnodeMirror); diffAfterUpdatingChildren(oldTree, newTree, replayer); } function diffBeforeUpdatingChildren(oldTree, newTree, replayer, rrnodeMirror) { var _a; if (replayer.afterAppend && !createdNodeSet) { createdNodeSet = /* @__PURE__ */ new WeakSet(); setTimeout(() => { createdNodeSet = null; }, 0); } if (!sameNodeType(oldTree, newTree)) { const calibratedOldTree = createOrGetNode(newTree, replayer.mirror, rrnodeMirror); (_a = oldTree.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(calibratedOldTree, oldTree); oldTree = calibratedOldTree; } switch (newTree.RRNodeType) { case NodeType$1.Document: { if (!nodeMatching(oldTree, newTree, replayer.mirror, rrnodeMirror)) { const newMeta = rrnodeMirror.getMeta(newTree); if (newMeta) { replayer.mirror.removeNodeFromMap(oldTree); oldTree.close(); oldTree.open(); replayer.mirror.add(oldTree, newMeta); createdNodeSet === null || createdNodeSet === void 0 ? void 0 : createdNodeSet.add(oldTree); } } break; } case NodeType$1.Element: { const oldElement = oldTree; const newRRElement = newTree; switch (newRRElement.tagName) { case "