rrweb
Version:
record and replay the web
1,466 lines (1,464 loc) • 194 kB
JavaScript
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 "