@rrweb/record
Version:
This package contains all the record related code in rrweb. See the [guide](../../guide.md) for more info on rrweb.
1,587 lines • 373 kB
JavaScript
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var _a;
var __defProp$1 = Object.defineProperty;
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
var NodeType$3 = /* @__PURE__ */ ((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";
return NodeType2;
})(NodeType$3 || {});
const testableAccessors$1 = {
Node: ["childNodes", "parentNode", "parentElement", "textContent"],
ShadowRoot: ["host", "styleSheets"],
Element: ["shadowRoot", "querySelector", "querySelectorAll"],
MutationObserver: []
};
const testableMethods$1 = {
Node: ["contains", "getRootNode"],
ShadowRoot: ["getSelection"],
Element: [],
MutationObserver: ["constructor"]
};
const untaintedBasePrototype$1 = {};
const isAngularZonePresent$1 = () => {
return !!globalThis.Zone;
};
function getUntaintedPrototype$1(key) {
if (untaintedBasePrototype$1[key])
return untaintedBasePrototype$1[key];
const defaultObj = globalThis[key];
const defaultPrototype = defaultObj.prototype;
const accessorNames = key in testableAccessors$1 ? testableAccessors$1[key] : void 0;
const isUntaintedAccessors = Boolean(
accessorNames && // @ts-expect-error 2345
accessorNames.every(
(accessor) => {
var _a2, _b;
return Boolean(
(_b = (_a2 = Object.getOwnPropertyDescriptor(defaultPrototype, accessor)) == null ? void 0 : _a2.get) == null ? void 0 : _b.toString().includes("[native code]")
);
}
)
);
const methodNames = key in testableMethods$1 ? testableMethods$1[key] : void 0;
const isUntaintedMethods = Boolean(
methodNames && methodNames.every(
// @ts-expect-error 2345
(method) => {
var _a2;
return typeof defaultPrototype[method] === "function" && ((_a2 = defaultPrototype[method]) == null ? void 0 : _a2.toString().includes("[native code]"));
}
)
);
if (isUntaintedAccessors && isUntaintedMethods && !isAngularZonePresent$1()) {
untaintedBasePrototype$1[key] = defaultObj.prototype;
return defaultObj.prototype;
}
try {
const iframeEl = document.createElement("iframe");
document.body.appendChild(iframeEl);
const win = iframeEl.contentWindow;
if (!win) return defaultObj.prototype;
const untaintedObject = win[key].prototype;
document.body.removeChild(iframeEl);
if (!untaintedObject) return defaultPrototype;
return untaintedBasePrototype$1[key] = untaintedObject;
} catch {
return defaultPrototype;
}
}
const untaintedAccessorCache$1 = {};
function getUntaintedAccessor$1(key, instance, accessor) {
var _a2;
const cacheKey = `${key}.${String(accessor)}`;
if (untaintedAccessorCache$1[cacheKey])
return untaintedAccessorCache$1[cacheKey].call(
instance
);
const untaintedPrototype = getUntaintedPrototype$1(key);
const untaintedAccessor = (_a2 = Object.getOwnPropertyDescriptor(
untaintedPrototype,
accessor
)) == null ? void 0 : _a2.get;
if (!untaintedAccessor) return instance[accessor];
untaintedAccessorCache$1[cacheKey] = untaintedAccessor;
return untaintedAccessor.call(instance);
}
const untaintedMethodCache$1 = {};
function getUntaintedMethod$1(key, instance, method) {
const cacheKey = `${key}.${String(method)}`;
if (untaintedMethodCache$1[cacheKey])
return untaintedMethodCache$1[cacheKey].bind(
instance
);
const untaintedPrototype = getUntaintedPrototype$1(key);
const untaintedMethod = untaintedPrototype[method];
if (typeof untaintedMethod !== "function") return instance[method];
untaintedMethodCache$1[cacheKey] = untaintedMethod;
return untaintedMethod.bind(instance);
}
function childNodes$1(n2) {
return getUntaintedAccessor$1("Node", n2, "childNodes");
}
function parentNode$1(n2) {
return getUntaintedAccessor$1("Node", n2, "parentNode");
}
function parentElement$1(n2) {
return getUntaintedAccessor$1("Node", n2, "parentElement");
}
function textContent$1(n2) {
return getUntaintedAccessor$1("Node", n2, "textContent");
}
function contains$1(n2, other) {
return getUntaintedMethod$1("Node", n2, "contains")(other);
}
function getRootNode$1(n2) {
return getUntaintedMethod$1("Node", n2, "getRootNode")();
}
function host$1(n2) {
if (!n2 || !("host" in n2)) return null;
return getUntaintedAccessor$1("ShadowRoot", n2, "host");
}
function styleSheets$1(n2) {
return n2.styleSheets;
}
function shadowRoot$1(n2) {
if (!n2 || !("shadowRoot" in n2)) return null;
return getUntaintedAccessor$1("Element", n2, "shadowRoot");
}
function querySelector$1(n2, selectors) {
return getUntaintedAccessor$1("Element", n2, "querySelector")(selectors);
}
function querySelectorAll$1(n2, selectors) {
return getUntaintedAccessor$1("Element", n2, "querySelectorAll")(selectors);
}
function mutationObserverCtor$1() {
return getUntaintedPrototype$1("MutationObserver").constructor;
}
const index$1 = {
childNodes: childNodes$1,
parentNode: parentNode$1,
parentElement: parentElement$1,
textContent: textContent$1,
contains: contains$1,
getRootNode: getRootNode$1,
host: host$1,
styleSheets: styleSheets$1,
shadowRoot: shadowRoot$1,
querySelector: querySelector$1,
querySelectorAll: querySelectorAll$1,
mutationObserver: mutationObserverCtor$1
};
function isElement(n2) {
return n2.nodeType === n2.ELEMENT_NODE;
}
function isShadowRoot(n2) {
const hostEl = (
// anchor and textarea elements also have a `host` property
// but only shadow roots have a `mode` property
n2 && "host" in n2 && "mode" in n2 && index$1.host(n2) || null
);
return Boolean(
hostEl && "shadowRoot" in hostEl && index$1.shadowRoot(hostEl) === n2
);
}
function isNativeShadowDom(shadowRoot2) {
return Object.prototype.toString.call(shadowRoot2) === "[object ShadowRoot]";
}
function fixBrowserCompatibilityIssuesInCSS(cssText) {
if (cssText.includes(" background-clip: text;") && !cssText.includes(" -webkit-background-clip: text;")) {
cssText = cssText.replace(
/\sbackground-clip:\s*text;/g,
" -webkit-background-clip: text; background-clip: text;"
);
}
return cssText;
}
function escapeImportStatement(rule2) {
const { cssText } = rule2;
if (cssText.split('"').length < 3) return cssText;
const statement = ["@import", `url(${JSON.stringify(rule2.href)})`];
if (rule2.layerName === "") {
statement.push(`layer`);
} else if (rule2.layerName) {
statement.push(`layer(${rule2.layerName})`);
}
if (rule2.supportsText) {
statement.push(`supports(${rule2.supportsText})`);
}
if (rule2.media.length) {
statement.push(rule2.media.mediaText);
}
return statement.join(" ") + ";";
}
function stringifyStylesheet(s2) {
try {
const rules2 = s2.rules || s2.cssRules;
if (!rules2) {
return null;
}
let sheetHref = s2.href;
if (!sheetHref && s2.ownerNode && s2.ownerNode.ownerDocument) {
sheetHref = s2.ownerNode.ownerDocument.location.href;
}
const stringifiedRules = Array.from(
rules2,
(rule2) => stringifyRule(rule2, sheetHref)
).join("");
return fixBrowserCompatibilityIssuesInCSS(stringifiedRules);
} catch (error) {
return null;
}
}
function stringifyRule(rule2, sheetHref) {
if (isCSSImportRule(rule2)) {
let importStringified;
try {
importStringified = // for same-origin stylesheets,
// we can access the imported stylesheet rules directly
stringifyStylesheet(rule2.styleSheet) || // work around browser issues with the raw string `@import url(...)` statement
escapeImportStatement(rule2);
} catch (error) {
importStringified = rule2.cssText;
}
if (rule2.styleSheet.href) {
return absolutifyURLs(importStringified, rule2.styleSheet.href);
}
return importStringified;
} else {
let ruleStringified = rule2.cssText;
if (isCSSStyleRule(rule2) && rule2.selectorText.includes(":")) {
ruleStringified = fixSafariColons(ruleStringified);
}
if (sheetHref) {
return absolutifyURLs(ruleStringified, sheetHref);
}
return ruleStringified;
}
}
function fixSafariColons(cssStringified) {
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
return cssStringified.replace(regex, "$1\\$2");
}
function isCSSImportRule(rule2) {
return "styleSheet" in rule2;
}
function isCSSStyleRule(rule2) {
return "selectorText" in rule2;
}
class Mirror {
constructor() {
__publicField$1(this, "idNodeMap", /* @__PURE__ */ new Map());
__publicField$1(this, "nodeMetaMap", /* @__PURE__ */ new WeakMap());
}
getId(n2) {
var _a2;
if (!n2) return -1;
const id = (_a2 = this.getMeta(n2)) == null ? void 0 : _a2.id;
return id ?? -1;
}
getNode(id) {
return this.idNodeMap.get(id) || null;
}
getIds() {
return Array.from(this.idNodeMap.keys());
}
getMeta(n2) {
return this.nodeMetaMap.get(n2) || null;
}
// removes the node from idNodeMap
// doesn't remove the node from nodeMetaMap
removeNodeFromMap(n2) {
const id = this.getId(n2);
this.idNodeMap.delete(id);
if (n2.childNodes) {
n2.childNodes.forEach(
(childNode) => this.removeNodeFromMap(childNode)
);
}
}
has(id) {
return this.idNodeMap.has(id);
}
hasNode(node2) {
return this.nodeMetaMap.has(node2);
}
add(n2, meta) {
const id = meta.id;
this.idNodeMap.set(id, n2);
this.nodeMetaMap.set(n2, meta);
}
replace(id, n2) {
const oldNode = this.getNode(id);
if (oldNode) {
const meta = this.nodeMetaMap.get(oldNode);
if (meta) this.nodeMetaMap.set(n2, meta);
}
this.idNodeMap.set(id, n2);
}
reset() {
this.idNodeMap = /* @__PURE__ */ new Map();
this.nodeMetaMap = /* @__PURE__ */ new WeakMap();
}
}
function createMirror$2() {
return new Mirror();
}
function maskInputValue({
element,
maskInputOptions,
tagName,
type,
value,
maskInputFn
}) {
let text = value || "";
const actualType = type && toLowerCase(type);
if (maskInputOptions[tagName.toLowerCase()] || actualType && maskInputOptions[actualType]) {
if (maskInputFn) {
text = maskInputFn(text, element);
} else {
text = "*".repeat(text.length);
}
}
return text;
}
function toLowerCase(str) {
return str.toLowerCase();
}
const ORIGINAL_ATTRIBUTE_NAME = "__rrweb_original__";
function is2DCanvasBlank(canvas) {
const ctx = canvas.getContext("2d");
if (!ctx) return true;
const chunkSize = 50;
for (let x2 = 0; x2 < canvas.width; x2 += chunkSize) {
for (let y = 0; y < canvas.height; y += chunkSize) {
const getImageData = ctx.getImageData;
const originalGetImageData = ORIGINAL_ATTRIBUTE_NAME in getImageData ? getImageData[ORIGINAL_ATTRIBUTE_NAME] : getImageData;
const pixelBuffer = new Uint32Array(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
originalGetImageData.call(
ctx,
x2,
y,
Math.min(chunkSize, canvas.width - x2),
Math.min(chunkSize, canvas.height - y)
).data.buffer
);
if (pixelBuffer.some((pixel) => pixel !== 0)) return false;
}
}
return true;
}
function getInputType(element) {
const type = element.type;
return element.hasAttribute("data-rr-is-password") ? "password" : type ? (
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
toLowerCase(type)
) : null;
}
function extractFileExtension(path, baseURL) {
let url;
try {
url = new URL(path, baseURL ?? window.location.href);
} catch (err) {
return null;
}
const regex = /\.([0-9a-z]+)(?:$)/i;
const match = url.pathname.match(regex);
return (match == null ? void 0 : match[1]) ?? null;
}
function extractOrigin(url) {
let origin = "";
if (url.indexOf("//") > -1) {
origin = url.split("/").slice(0, 3).join("/");
} else {
origin = url.split("/")[0];
}
origin = origin.split("?")[0];
return origin;
}
const URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm;
const URL_PROTOCOL_MATCH = /^(?:[a-z+]+:)?\/\//i;
const URL_WWW_MATCH = /^www\..*/i;
const DATA_URI = /^(data:)([^,]*),(.*)/i;
function absolutifyURLs(cssText, href) {
return (cssText || "").replace(
URL_IN_CSS_REF,
(origin, quote1, path1, quote2, path2, path3) => {
const filePath = path1 || path2 || path3;
const maybeQuote = quote1 || quote2 || "";
if (!filePath) {
return origin;
}
if (URL_PROTOCOL_MATCH.test(filePath) || URL_WWW_MATCH.test(filePath)) {
return `url(${maybeQuote}${filePath}${maybeQuote})`;
}
if (DATA_URI.test(filePath)) {
return `url(${maybeQuote}${filePath}${maybeQuote})`;
}
if (filePath[0] === "/") {
return `url(${maybeQuote}${extractOrigin(href) + filePath}${maybeQuote})`;
}
const stack = href.split("/");
const parts = filePath.split("/");
stack.pop();
for (const part of parts) {
if (part === ".") {
continue;
} else if (part === "..") {
stack.pop();
} else {
stack.push(part);
}
}
return `url(${maybeQuote}${stack.join("/")}${maybeQuote})`;
}
);
}
function normalizeCssString(cssText) {
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
}
function splitCssText(cssText, style) {
const childNodes2 = Array.from(style.childNodes);
const splits = [];
if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
const cssTextNorm = normalizeCssString(cssText);
for (let i2 = 1; i2 < childNodes2.length; i2++) {
if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
const textContentNorm = normalizeCssString(childNodes2[i2].textContent);
for (let j = 3; j < textContentNorm.length; j++) {
const bit = textContentNorm.substring(0, j);
if (cssTextNorm.split(bit).length === 2) {
const splitNorm = cssTextNorm.indexOf(bit);
for (let k = splitNorm; k < cssText.length; k++) {
if (normalizeCssString(cssText.substring(0, k)).length === splitNorm) {
splits.push(cssText.substring(0, k));
cssText = cssText.substring(k);
break;
}
}
break;
}
}
}
}
}
splits.push(cssText);
return splits;
}
function markCssSplits(cssText, style) {
return splitCssText(cssText, style).join("/* rr_split */");
}
let _id = 1;
const tagNameRegex = new RegExp("[^a-z0-9-_:]");
const IGNORED_NODE = -2;
function genId() {
return _id++;
}
function getValidTagName$1(element) {
if (element instanceof HTMLFormElement) {
return "form";
}
const processedTagName = toLowerCase(element.tagName);
if (tagNameRegex.test(processedTagName)) {
return "div";
}
return processedTagName;
}
let canvasService;
let canvasCtx;
const SRCSET_NOT_SPACES = /^[^ \t\n\r\u000c]+/;
const SRCSET_COMMAS_OR_SPACES = /^[, \t\n\r\u000c]+/;
function getAbsoluteSrcsetString(doc, attributeValue) {
if (attributeValue.trim() === "") {
return attributeValue;
}
let pos = 0;
function collectCharacters(regEx) {
let chars2;
const match = regEx.exec(attributeValue.substring(pos));
if (match) {
chars2 = match[0];
pos += chars2.length;
return chars2;
}
return "";
}
const output = [];
while (true) {
collectCharacters(SRCSET_COMMAS_OR_SPACES);
if (pos >= attributeValue.length) {
break;
}
let url = collectCharacters(SRCSET_NOT_SPACES);
if (url.slice(-1) === ",") {
url = absoluteToDoc(doc, url.substring(0, url.length - 1));
output.push(url);
} else {
let descriptorsStr = "";
url = absoluteToDoc(doc, url);
let inParens = false;
while (true) {
const c2 = attributeValue.charAt(pos);
if (c2 === "") {
output.push((url + descriptorsStr).trim());
break;
} else if (!inParens) {
if (c2 === ",") {
pos += 1;
output.push((url + descriptorsStr).trim());
break;
} else if (c2 === "(") {
inParens = true;
}
} else {
if (c2 === ")") {
inParens = false;
}
}
descriptorsStr += c2;
pos += 1;
}
}
}
return output.join(", ");
}
const cachedDocument = /* @__PURE__ */ new WeakMap();
function absoluteToDoc(doc, attributeValue) {
if (!attributeValue || attributeValue.trim() === "") {
return attributeValue;
}
return getHref(doc, attributeValue);
}
function isSVGElement(el) {
return Boolean(el.tagName === "svg" || el.ownerSVGElement);
}
function getHref(doc, customHref) {
let a2 = cachedDocument.get(doc);
if (!a2) {
a2 = doc.createElement("a");
cachedDocument.set(doc, a2);
}
if (!customHref) {
customHref = "";
} else if (customHref.startsWith("blob:") || customHref.startsWith("data:")) {
return customHref;
}
a2.setAttribute("href", customHref);
return a2.href;
}
function transformAttribute(doc, tagName, name, value) {
if (!value) {
return value;
}
if (name === "src" || name === "href" && !(tagName === "use" && value[0] === "#")) {
return absoluteToDoc(doc, value);
} else if (name === "xlink:href" && value[0] !== "#") {
return absoluteToDoc(doc, value);
} else if (name === "background" && (tagName === "table" || tagName === "td" || tagName === "th")) {
return absoluteToDoc(doc, value);
} else if (name === "srcset") {
return getAbsoluteSrcsetString(doc, value);
} else if (name === "style") {
return absolutifyURLs(value, getHref(doc));
} else if (tagName === "object" && name === "data") {
return absoluteToDoc(doc, value);
}
return value;
}
function ignoreAttribute(tagName, name, _value) {
return (tagName === "video" || tagName === "audio") && name === "autoplay";
}
function _isBlockedElement(element, blockClass, blockSelector) {
try {
if (typeof blockClass === "string") {
if (element.classList.contains(blockClass)) {
return true;
}
} else {
for (let eIndex = element.classList.length; eIndex--; ) {
const className = element.classList[eIndex];
if (blockClass.test(className)) {
return true;
}
}
}
if (blockSelector) {
return element.matches(blockSelector);
}
} catch (e2) {
}
return false;
}
function classMatchesRegex(node2, regex, checkAncestors) {
if (!node2) return false;
if (node2.nodeType !== node2.ELEMENT_NODE) {
if (!checkAncestors) return false;
return classMatchesRegex(index$1.parentNode(node2), regex, checkAncestors);
}
for (let eIndex = node2.classList.length; eIndex--; ) {
const className = node2.classList[eIndex];
if (regex.test(className)) {
return true;
}
}
if (!checkAncestors) return false;
return classMatchesRegex(index$1.parentNode(node2), regex, checkAncestors);
}
function needMaskingText(node2, maskTextClass, maskTextSelector, checkAncestors) {
let el;
if (isElement(node2)) {
el = node2;
if (!index$1.childNodes(el).length) {
return false;
}
} else if (index$1.parentElement(node2) === null) {
return false;
} else {
el = index$1.parentElement(node2);
}
try {
if (typeof maskTextClass === "string") {
if (checkAncestors) {
if (el.closest(`.${maskTextClass}`)) return true;
} else {
if (el.classList.contains(maskTextClass)) return true;
}
} else {
if (classMatchesRegex(el, maskTextClass, checkAncestors)) return true;
}
if (maskTextSelector) {
if (checkAncestors) {
if (el.closest(maskTextSelector)) return true;
} else {
if (el.matches(maskTextSelector)) return true;
}
}
} catch (e2) {
}
return false;
}
function onceIframeLoaded(iframeEl, listener, iframeLoadTimeout) {
const win = iframeEl.contentWindow;
if (!win) {
return;
}
let fired = false;
let readyState;
try {
readyState = win.document.readyState;
} catch (error) {
return;
}
if (readyState !== "complete") {
const timer = setTimeout(() => {
if (!fired) {
listener();
fired = true;
}
}, iframeLoadTimeout);
iframeEl.addEventListener("load", () => {
clearTimeout(timer);
fired = true;
listener();
});
return;
}
const blankUrl = "about:blank";
if (win.location.href !== blankUrl || iframeEl.src === blankUrl || iframeEl.src === "") {
setTimeout(listener, 0);
return iframeEl.addEventListener("load", listener);
}
iframeEl.addEventListener("load", listener);
}
function onceStylesheetLoaded(link, listener, styleSheetLoadTimeout) {
let fired = false;
let styleSheetLoaded;
try {
styleSheetLoaded = link.sheet;
} catch (error) {
return;
}
if (styleSheetLoaded) return;
const timer = setTimeout(() => {
if (!fired) {
listener();
fired = true;
}
}, styleSheetLoadTimeout);
link.addEventListener("load", () => {
clearTimeout(timer);
fired = true;
listener();
});
}
function serializeNode(n2, options) {
const {
doc,
mirror: mirror2,
blockClass,
blockSelector,
needsMask,
inlineStylesheet,
maskInputOptions = {},
maskTextFn,
maskInputFn,
dataURLOptions = {},
inlineImages,
recordCanvas,
keepIframeSrcFn,
newlyAddedElement = false,
cssCaptured = false
} = options;
const rootId = getRootId(doc, mirror2);
switch (n2.nodeType) {
case n2.DOCUMENT_NODE:
if (n2.compatMode !== "CSS1Compat") {
return {
type: NodeType$3.Document,
childNodes: [],
compatMode: n2.compatMode
// probably "BackCompat"
};
} else {
return {
type: NodeType$3.Document,
childNodes: []
};
}
case n2.DOCUMENT_TYPE_NODE:
return {
type: NodeType$3.DocumentType,
name: n2.name,
publicId: n2.publicId,
systemId: n2.systemId,
rootId
};
case n2.ELEMENT_NODE:
return serializeElementNode(n2, {
doc,
blockClass,
blockSelector,
inlineStylesheet,
maskInputOptions,
maskInputFn,
dataURLOptions,
inlineImages,
recordCanvas,
keepIframeSrcFn,
newlyAddedElement,
rootId
});
case n2.TEXT_NODE:
return serializeTextNode(n2, {
doc,
needsMask,
maskTextFn,
rootId,
cssCaptured
});
case n2.CDATA_SECTION_NODE:
return {
type: NodeType$3.CDATA,
textContent: "",
rootId
};
case n2.COMMENT_NODE:
return {
type: NodeType$3.Comment,
textContent: index$1.textContent(n2) || "",
rootId
};
default:
return false;
}
}
function getRootId(doc, mirror2) {
if (!mirror2.hasNode(doc)) return void 0;
const docId = mirror2.getId(doc);
return docId === 1 ? void 0 : docId;
}
function serializeTextNode(n2, options) {
const { needsMask, maskTextFn, rootId, cssCaptured } = options;
const parent = index$1.parentNode(n2);
const parentTagName = parent && parent.tagName;
let textContent2 = "";
const isStyle = parentTagName === "STYLE" ? true : void 0;
const isScript = parentTagName === "SCRIPT" ? true : void 0;
if (isScript) {
textContent2 = "SCRIPT_PLACEHOLDER";
} else if (!cssCaptured) {
textContent2 = index$1.textContent(n2);
if (isStyle && textContent2) {
textContent2 = absolutifyURLs(textContent2, getHref(options.doc));
}
}
if (!isStyle && !isScript && textContent2 && needsMask) {
textContent2 = maskTextFn ? maskTextFn(textContent2, index$1.parentElement(n2)) : textContent2.replace(/[\S]/g, "*");
}
return {
type: NodeType$3.Text,
textContent: textContent2 || "",
rootId
};
}
function serializeElementNode(n2, options) {
const {
doc,
blockClass,
blockSelector,
inlineStylesheet,
maskInputOptions = {},
maskInputFn,
dataURLOptions = {},
inlineImages,
recordCanvas,
keepIframeSrcFn,
newlyAddedElement = false,
rootId
} = options;
const needBlock = _isBlockedElement(n2, blockClass, blockSelector);
const tagName = getValidTagName$1(n2);
let attributes = {};
const len = n2.attributes.length;
for (let i2 = 0; i2 < len; i2++) {
const attr = n2.attributes[i2];
if (!ignoreAttribute(tagName, attr.name, attr.value)) {
attributes[attr.name] = transformAttribute(
doc,
tagName,
toLowerCase(attr.name),
attr.value
);
}
}
if (tagName === "link" && inlineStylesheet) {
const stylesheet = Array.from(doc.styleSheets).find((s2) => {
return s2.href === n2.href;
});
let cssText = null;
if (stylesheet) {
cssText = stringifyStylesheet(stylesheet);
}
if (cssText) {
delete attributes.rel;
delete attributes.href;
attributes._cssText = cssText;
}
}
if (tagName === "style" && n2.sheet) {
let cssText = stringifyStylesheet(
n2.sheet
);
if (cssText) {
if (n2.childNodes.length > 1) {
cssText = markCssSplits(cssText, n2);
}
attributes._cssText = cssText;
}
}
if (tagName === "input" || tagName === "textarea" || tagName === "select") {
const value = n2.value;
const checked = n2.checked;
if (attributes.type !== "radio" && attributes.type !== "checkbox" && attributes.type !== "submit" && attributes.type !== "button" && value) {
attributes.value = maskInputValue({
element: n2,
type: getInputType(n2),
tagName,
value,
maskInputOptions,
maskInputFn
});
} else if (checked) {
attributes.checked = checked;
}
}
if (tagName === "option") {
if (n2.selected && !maskInputOptions["select"]) {
attributes.selected = true;
} else {
delete attributes.selected;
}
}
if (tagName === "dialog" && n2.open) {
attributes.rr_open_mode = n2.matches("dialog:modal") ? "modal" : "non-modal";
}
if (tagName === "canvas" && recordCanvas) {
if (n2.__context === "2d") {
if (!is2DCanvasBlank(n2)) {
attributes.rr_dataURL = n2.toDataURL(
dataURLOptions.type,
dataURLOptions.quality
);
}
} else if (!("__context" in n2)) {
const canvasDataURL = n2.toDataURL(
dataURLOptions.type,
dataURLOptions.quality
);
const blankCanvas = doc.createElement("canvas");
blankCanvas.width = n2.width;
blankCanvas.height = n2.height;
const blankCanvasDataURL = blankCanvas.toDataURL(
dataURLOptions.type,
dataURLOptions.quality
);
if (canvasDataURL !== blankCanvasDataURL) {
attributes.rr_dataURL = canvasDataURL;
}
}
}
if (tagName === "img" && inlineImages) {
if (!canvasService) {
canvasService = doc.createElement("canvas");
canvasCtx = canvasService.getContext("2d");
}
const image = n2;
const imageSrc = image.currentSrc || image.getAttribute("src") || "<unknown-src>";
const priorCrossOrigin = image.crossOrigin;
const recordInlineImage = () => {
image.removeEventListener("load", recordInlineImage);
try {
canvasService.width = image.naturalWidth;
canvasService.height = image.naturalHeight;
canvasCtx.drawImage(image, 0, 0);
attributes.rr_dataURL = canvasService.toDataURL(
dataURLOptions.type,
dataURLOptions.quality
);
} catch (err) {
if (image.crossOrigin !== "anonymous") {
image.crossOrigin = "anonymous";
if (image.complete && image.naturalWidth !== 0)
recordInlineImage();
else image.addEventListener("load", recordInlineImage);
return;
} else {
console.warn(
`Cannot inline img src=${imageSrc}! Error: ${err}`
);
}
}
if (image.crossOrigin === "anonymous") {
priorCrossOrigin ? attributes.crossOrigin = priorCrossOrigin : image.removeAttribute("crossorigin");
}
};
if (image.complete && image.naturalWidth !== 0) recordInlineImage();
else image.addEventListener("load", recordInlineImage);
}
if (tagName === "audio" || tagName === "video") {
const mediaAttributes = attributes;
mediaAttributes.rr_mediaState = n2.paused ? "paused" : "played";
mediaAttributes.rr_mediaCurrentTime = n2.currentTime;
mediaAttributes.rr_mediaPlaybackRate = n2.playbackRate;
mediaAttributes.rr_mediaMuted = n2.muted;
mediaAttributes.rr_mediaLoop = n2.loop;
mediaAttributes.rr_mediaVolume = n2.volume;
}
if (!newlyAddedElement) {
if (n2.scrollLeft) {
attributes.rr_scrollLeft = n2.scrollLeft;
}
if (n2.scrollTop) {
attributes.rr_scrollTop = n2.scrollTop;
}
}
if (needBlock) {
const { width, height } = n2.getBoundingClientRect();
attributes = {
class: attributes.class,
rr_width: `${width}px`,
rr_height: `${height}px`
};
}
if (tagName === "iframe" && !keepIframeSrcFn(attributes.src)) {
if (!n2.contentDocument) {
attributes.rr_src = attributes.src;
}
delete attributes.src;
}
let isCustomElement;
try {
if (customElements.get(tagName)) isCustomElement = true;
} catch (e2) {
}
return {
type: NodeType$3.Element,
tagName,
attributes,
childNodes: [],
isSVG: isSVGElement(n2) || void 0,
needBlock,
rootId,
isCustom: isCustomElement
};
}
function lowerIfExists(maybeAttr) {
if (maybeAttr === void 0 || maybeAttr === null) {
return "";
} else {
return maybeAttr.toLowerCase();
}
}
function slimDOMExcluded(sn, slimDOMOptions) {
if (slimDOMOptions.comment && sn.type === NodeType$3.Comment) {
return true;
} else if (sn.type === NodeType$3.Element) {
if (slimDOMOptions.script && // script tag
(sn.tagName === "script" || // (module)preload link
sn.tagName === "link" && (sn.attributes.rel === "preload" || sn.attributes.rel === "modulepreload") && sn.attributes.as === "script" || // prefetch link
sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
return true;
} else if (slimDOMOptions.headFavicon && (sn.tagName === "link" && sn.attributes.rel === "shortcut icon" || sn.tagName === "meta" && (lowerIfExists(sn.attributes.name).match(
/^msapplication-tile(image|color)$/
) || lowerIfExists(sn.attributes.name) === "application-name" || lowerIfExists(sn.attributes.rel) === "icon" || lowerIfExists(sn.attributes.rel) === "apple-touch-icon" || lowerIfExists(sn.attributes.rel) === "shortcut icon"))) {
return true;
} else if (sn.tagName === "meta") {
if (slimDOMOptions.headMetaDescKeywords && lowerIfExists(sn.attributes.name).match(/^description|keywords$/)) {
return true;
} else if (slimDOMOptions.headMetaSocial && (lowerIfExists(sn.attributes.property).match(/^(og|twitter|fb):/) || // og = opengraph (facebook)
lowerIfExists(sn.attributes.name).match(/^(og|twitter):/) || lowerIfExists(sn.attributes.name) === "pinterest")) {
return true;
} else if (slimDOMOptions.headMetaRobots && (lowerIfExists(sn.attributes.name) === "robots" || lowerIfExists(sn.attributes.name) === "googlebot" || lowerIfExists(sn.attributes.name) === "bingbot")) {
return true;
} else if (slimDOMOptions.headMetaHttpEquiv && sn.attributes["http-equiv"] !== void 0) {
return true;
} else if (slimDOMOptions.headMetaAuthorship && (lowerIfExists(sn.attributes.name) === "author" || lowerIfExists(sn.attributes.name) === "generator" || lowerIfExists(sn.attributes.name) === "framework" || lowerIfExists(sn.attributes.name) === "publisher" || lowerIfExists(sn.attributes.name) === "progid" || lowerIfExists(sn.attributes.property).match(/^article:/) || lowerIfExists(sn.attributes.property).match(/^product:/))) {
return true;
} else if (slimDOMOptions.headMetaVerification && (lowerIfExists(sn.attributes.name) === "google-site-verification" || lowerIfExists(sn.attributes.name) === "yandex-verification" || lowerIfExists(sn.attributes.name) === "csrf-token" || lowerIfExists(sn.attributes.name) === "p:domain_verify" || lowerIfExists(sn.attributes.name) === "verify-v1" || lowerIfExists(sn.attributes.name) === "verification" || lowerIfExists(sn.attributes.name) === "shopify-checkout-api-token")) {
return true;
}
}
}
return false;
}
function serializeNodeWithId(n2, options) {
const {
doc,
mirror: mirror2,
blockClass,
blockSelector,
maskTextClass,
maskTextSelector,
skipChild = false,
inlineStylesheet = true,
maskInputOptions = {},
maskTextFn,
maskInputFn,
slimDOMOptions,
dataURLOptions = {},
inlineImages = false,
recordCanvas = false,
onSerialize,
onIframeLoad,
iframeLoadTimeout = 5e3,
onStylesheetLoad,
stylesheetLoadTimeout = 5e3,
keepIframeSrcFn = () => false,
newlyAddedElement = false,
cssCaptured = false
} = options;
let { needsMask } = options;
let { preserveWhiteSpace = true } = options;
if (!needsMask) {
const checkAncestors = needsMask === void 0;
needsMask = needMaskingText(
n2,
maskTextClass,
maskTextSelector,
checkAncestors
);
}
const _serializedNode = serializeNode(n2, {
doc,
mirror: mirror2,
blockClass,
blockSelector,
needsMask,
inlineStylesheet,
maskInputOptions,
maskTextFn,
maskInputFn,
dataURLOptions,
inlineImages,
recordCanvas,
keepIframeSrcFn,
newlyAddedElement,
cssCaptured
});
if (!_serializedNode) {
console.warn(n2, "not serialized");
return null;
}
let id;
if (mirror2.hasNode(n2)) {
id = mirror2.getId(n2);
} else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || !preserveWhiteSpace && _serializedNode.type === NodeType$3.Text && !_serializedNode.textContent.replace(/^\s+|\s+$/gm, "").length) {
id = IGNORED_NODE;
} else {
id = genId();
}
const serializedNode = Object.assign(_serializedNode, { id });
mirror2.add(n2, serializedNode);
if (id === IGNORED_NODE) {
return null;
}
if (onSerialize) {
onSerialize(n2);
}
let recordChild = !skipChild;
if (serializedNode.type === NodeType$3.Element) {
recordChild = recordChild && !serializedNode.needBlock;
delete serializedNode.needBlock;
const shadowRootEl = index$1.shadowRoot(n2);
if (shadowRootEl && isNativeShadowDom(shadowRootEl))
serializedNode.isShadowHost = true;
}
if ((serializedNode.type === NodeType$3.Document || serializedNode.type === NodeType$3.Element) && recordChild) {
if (slimDOMOptions.headWhitespace && serializedNode.type === NodeType$3.Element && serializedNode.tagName === "head") {
preserveWhiteSpace = false;
}
const bypassOptions = {
doc,
mirror: mirror2,
blockClass,
blockSelector,
needsMask,
maskTextClass,
maskTextSelector,
skipChild,
inlineStylesheet,
maskInputOptions,
maskTextFn,
maskInputFn,
slimDOMOptions,
dataURLOptions,
inlineImages,
recordCanvas,
preserveWhiteSpace,
onSerialize,
onIframeLoad,
iframeLoadTimeout,
onStylesheetLoad,
stylesheetLoadTimeout,
keepIframeSrcFn,
cssCaptured: false
};
if (serializedNode.type === NodeType$3.Element && serializedNode.tagName === "textarea" && serializedNode.attributes.value !== void 0) ;
else {
if (serializedNode.type === NodeType$3.Element && serializedNode.attributes._cssText !== void 0 && typeof serializedNode.attributes._cssText === "string") {
bypassOptions.cssCaptured = true;
}
for (const childN of Array.from(index$1.childNodes(n2))) {
const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
if (serializedChildNode) {
serializedNode.childNodes.push(serializedChildNode);
}
}
}
let shadowRootEl = null;
if (isElement(n2) && (shadowRootEl = index$1.shadowRoot(n2))) {
for (const childN of Array.from(index$1.childNodes(shadowRootEl))) {
const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
if (serializedChildNode) {
isNativeShadowDom(shadowRootEl) && (serializedChildNode.isShadow = true);
serializedNode.childNodes.push(serializedChildNode);
}
}
}
}
const parent = index$1.parentNode(n2);
if (parent && isShadowRoot(parent) && isNativeShadowDom(parent)) {
serializedNode.isShadow = true;
}
if (serializedNode.type === NodeType$3.Element && serializedNode.tagName === "iframe") {
onceIframeLoaded(
n2,
() => {
const iframeDoc = n2.contentDocument;
if (iframeDoc && onIframeLoad) {
const serializedIframeNode = serializeNodeWithId(iframeDoc, {
doc: iframeDoc,
mirror: mirror2,
blockClass,
blockSelector,
needsMask,
maskTextClass,
maskTextSelector,
skipChild: false,
inlineStylesheet,
maskInputOptions,
maskTextFn,
maskInputFn,
slimDOMOptions,
dataURLOptions,
inlineImages,
recordCanvas,
preserveWhiteSpace,
onSerialize,
onIframeLoad,
iframeLoadTimeout,
onStylesheetLoad,
stylesheetLoadTimeout,
keepIframeSrcFn
});
if (serializedIframeNode) {
onIframeLoad(
n2,
serializedIframeNode
);
}
}
},
iframeLoadTimeout
);
}
if (serializedNode.type === NodeType$3.Element && serializedNode.tagName === "link" && typeof serializedNode.attributes.rel === "string" && (serializedNode.attributes.rel === "stylesheet" || serializedNode.attributes.rel === "preload" && typeof serializedNode.attributes.href === "string" && extractFileExtension(serializedNode.attributes.href) === "css")) {
onceStylesheetLoaded(
n2,
() => {
if (onStylesheetLoad) {
const serializedLinkNode = serializeNodeWithId(n2, {
doc,
mirror: mirror2,
blockClass,
blockSelector,
needsMask,
maskTextClass,
maskTextSelector,
skipChild: false,
inlineStylesheet,
maskInputOptions,
maskTextFn,
maskInputFn,
slimDOMOptions,
dataURLOptions,
inlineImages,
recordCanvas,
preserveWhiteSpace,
onSerialize,
onIframeLoad,
iframeLoadTimeout,
onStylesheetLoad,
stylesheetLoadTimeout,
keepIframeSrcFn
});
if (serializedLinkNode) {
onStylesheetLoad(
n2,
serializedLinkNode
);
}
}
},
stylesheetLoadTimeout
);
}
return serializedNode;
}
function snapshot(n2, options) {
const {
mirror: mirror2 = new Mirror(),
blockClass = "rr-block",
blockSelector = null,
maskTextClass = "rr-mask",
maskTextSelector = null,
inlineStylesheet = true,
inlineImages = false,
recordCanvas = false,
maskAllInputs = false,
maskTextFn,
maskInputFn,
slimDOM = false,
dataURLOptions,
preserveWhiteSpace,
onSerialize,
onIframeLoad,
iframeLoadTimeout,
onStylesheetLoad,
stylesheetLoadTimeout,
keepIframeSrcFn = () => false
} = options || {};
const maskInputOptions = maskAllInputs === true ? {
color: true,
date: true,
"datetime-local": true,
email: true,
month: true,
number: true,
range: true,
search: true,
tel: true,
text: true,
time: true,
url: true,
week: true,
textarea: true,
select: true,
password: true
} : maskAllInputs === false ? {
password: true
} : maskAllInputs;
const slimDOMOptions = slimDOM === true || slimDOM === "all" ? (
// if true: set of sensible options that should not throw away any information
{
script: true,
comment: true,
headFavicon: true,
headWhitespace: true,
headMetaDescKeywords: slimDOM === "all",
// destructive
headMetaSocial: true,
headMetaRobots: true,
headMetaHttpEquiv: true,
headMetaAuthorship: true,
headMetaVerification: true
}
) : slimDOM === false ? {} : slimDOM;
return serializeNodeWithId(n2, {
doc: n2,
mirror: mirror2,
blockClass,
blockSelector,
maskTextClass,
maskTextSelector,
skipChild: false,
inlineStylesheet,
maskInputOptions,
maskTextFn,
maskInputFn,
slimDOMOptions,
dataURLOptions,
inlineImages,
recordCanvas,
preserveWhiteSpace,
onSerialize,
onIframeLoad,
iframeLoadTimeout,
onStylesheetLoad,
stylesheetLoadTimeout,
keepIframeSrcFn,
newlyAddedElement: false
});
}
function getDefaultExportFromCjs$1(x2) {
return x2 && x2.__esModule && Object.prototype.hasOwnProperty.call(x2, "default") ? x2["default"] : x2;
}
function getAugmentedNamespace$1(n2) {
if (n2.__esModule) return n2;
var f2 = n2.default;
if (typeof f2 == "function") {
var a2 = function a22() {
if (this instanceof a22) {
return Reflect.construct(f2, arguments, this.constructor);
}
return f2.apply(this, arguments);
};
a2.prototype = f2.prototype;
} else a2 = {};
Object.defineProperty(a2, "__esModule", { value: true });
Object.keys(n2).forEach(function(k) {
var d = Object.getOwnPropertyDescriptor(n2, k);
Object.defineProperty(a2, k, d.get ? d : {
enumerable: true,
get: function() {
return n2[k];
}
});
});
return a2;
}
var picocolors_browser$1 = { exports: {} };
var x$1 = String;
var create$1 = function() {
return { isColorSupported: false, reset: x$1, bold: x$1, dim: x$1, italic: x$1, underline: x$1, inverse: x$1, hidden: x$1, strikethrough: x$1, black: x$1, red: x$1, green: x$1, yellow: x$1, blue: x$1, magenta: x$1, cyan: x$1, white: x$1, gray: x$1, bgBlack: x$1, bgRed: x$1, bgGreen: x$1, bgYellow: x$1, bgBlue: x$1, bgMagenta: x$1, bgCyan: x$1, bgWhite: x$1 };
};
picocolors_browser$1.exports = create$1();
picocolors_browser$1.exports.createColors = create$1;
var picocolors_browserExports$1 = picocolors_browser$1.exports;
const __viteBrowserExternal$2 = {};
const __viteBrowserExternal$1$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
default: __viteBrowserExternal$2
}, Symbol.toStringTag, { value: "Module" }));
const require$$2$1 = /* @__PURE__ */ getAugmentedNamespace$1(__viteBrowserExternal$1$1);
let pico$1 = picocolors_browserExports$1;
let terminalHighlight$1$1 = require$$2$1;
let CssSyntaxError$3$1 = class CssSyntaxError extends Error {
constructor(message, line, column, source, file, plugin22) {
super(message);
this.name = "CssSyntaxError";
this.reason = message;
if (file) {
this.file = file;
}
if (source) {
this.source = source;
}
if (plugin22) {
this.plugin = plugin22;
}
if (typeof line !== "undefined" && typeof column !== "undefined") {
if (typeof line === "number") {
this.line = line;
this.column = column;
} else {
this.line = line.line;
this.column = line.column;
this.endLine = column.line;
this.endColumn = column.column;
}
}
this.setMessage();
if (Error.captureStackTrace) {
Error.captureStackTrace(this, CssSyntaxError);
}
}
setMessage() {
this.message = this.plugin ? this.plugin + ": " : "";
this.message += this.file ? this.file : "<css input>";
if (typeof this.line !== "undefined") {
this.message += ":" + this.line + ":" + this.column;
}
this.message += ": " + this.reason;
}
showSourceCode(color) {
if (!this.source) return "";
let css = this.source;
if (color == null) color = pico$1.isColorSupported;
if (terminalHighlight$1$1) {
if (color) css = terminalHighlight$1$1(css);
}
let lines = css.split(/\r?\n/);
let start = Math.max(this.line - 3, 0);
let end = Math.min(this.line + 2, lines.length);
let maxWidth = String(end).length;
let mark, aside;
if (color) {
let { bold, gray, red } = pico$1.createColors(true);
mark = (text) => bold(red(text));
aside = (text) => gray(text);
} else {
mark = aside = (str) => str;
}
return lines.slice(start, end).map((line, index2) => {
let number = start + 1 + index2;
let gutter = " " + (" " + number).slice(-maxWidth) + " | ";
if (number === this.line) {
let spacing = aside(gutter.replace(/\d/g, " ")) + line.slice(0, this.column - 1).replace(/[^\t]/g, " ");
return mark(">") + aside(gutter) + line + "\n " + spacing + mark("^");
}
return " " + aside(gutter) + line;
}).join("\n");
}
toString() {
let code = this.showSourceCode();
if (code) {
code = "\n\n" + code + "\n";
}
return this.name + ": " + this.message + code;
}
};
var cssSyntaxError$1 = CssSyntaxError$3$1;
CssSyntaxError$3$1.default = CssSyntaxError$3$1;
var symbols$1 = {};
symbols$1.isClean = Symbol("isClean");
symbols$1.my = Symbol("my");
const DEFAULT_RAW$1 = {
after: "\n",
beforeClose: "\n",
beforeComment: "\n",
beforeDecl: "\n",
beforeOpen: " ",
beforeRule: "\n",
colon: ": ",
commentLeft: " ",
commentRight: " ",
emptyBody: "",
indent: " ",
semicolon: false
};
function capitalize$1(str) {
return str[0].toUpperCase() + str.slice(1);
}
let Stringifier$2$1 = class Stringifier {
constructor(builder) {
this.builder = builder;
}
atrule(node2, semicolon) {
let name = "@" + node2.name;
let params = node2.params ? this.rawValue(node2, "params") : "";
if (typeof node2.raws.afterName !== "undefined") {
name += node2.raws.afterName;
} else if (params) {
name += " ";
}
if (node2.nodes) {
this.block(node2, name + params);
} else {
let end = (node2.raws.between || "") + (semicolon ? ";" : "");
this.builder(name + params + end, node2);
}
}
beforeAfter(node2, detect) {
let value;
if (node2.type === "decl") {
value = this.raw(node2, null, "beforeDecl");
} else if (node2.type === "comment") {
value = this.raw(node2, null, "beforeComment");
} else if (detect === "before") {
value = this.raw(node2, null, "beforeRule");
} else {
value = this.raw(node2, null, "beforeClose");
}
let buf = node2.parent;
let depth = 0;
while (buf && buf.type !== "root") {
depth += 1;
buf = buf.parent;
}
if (value.includes("\n")) {
let indent = this.raw(node2, null, "indent");
if (indent.length) {
for (let step = 0; step < depth; step++) value += indent;
}
}
return value;
}
block(node2, start) {
let between = this.raw(node2, "between", "beforeOpen");
this.builder(start + between + "{", node2, "start");
let after;
if (node2.nodes && node2.nodes.length) {
this.body(node2);
after = this.raw(node2, "after");
} else {
after = this.raw(node2, "after", "emptyBody");
}
if (after) this.builder(after);
this.builder("}", node2, "end");
}
body(node2) {
let last = node2.nodes.length - 1;
while (last > 0) {
if (node2.nodes[last].type !== "comment") break;
last -= 1;
}
let semicolon = this.raw(node2, "semicolon");
for (let i2 = 0; i2 < node2.nodes.length; i2++) {
let child = node2.nodes[i2];
let before = this.raw(child, "before");
if (before) this.builder(before);
this.stringify(child, last !== i2 || semicolon);
}
}
comment(node2) {
let left = this.raw(node2, "left", "commentLeft");
let right = this.raw(node2, "right", "commentRight");
this.builder("/*" + left + node2.text + right + "*/", node2);
}
decl(node2, semicolon) {
let between = this.raw(node2, "between", "colon");
let string = node2.prop + between + this.rawValue(node2, "value");
if (node2.important) {
string += node2.raws.important || " !important";
}
if (semicolon) string += ";";
this.builder(string, node2);
}
document(node2) {
this.body(node2);
}
raw(node2, own, detect) {
let value;
if (!detect) detect = own;
if (own) {
value = node2.raws[own];
if (typeof value !== "undefine