UNPKG

@xysfe/memento-snapshot

Version:

rrweb's component to take a snapshot of DOM, aka DOM serializer

1,047 lines (1,042 loc) 36 kB
var NodeType; (function (NodeType) { NodeType[NodeType["Document"] = 0] = "Document"; NodeType[NodeType["DocumentType"] = 1] = "DocumentType"; NodeType[NodeType["Element"] = 2] = "Element"; NodeType[NodeType["Text"] = 3] = "Text"; NodeType[NodeType["CDATA"] = 4] = "CDATA"; NodeType[NodeType["Comment"] = 5] = "Comment"; })(NodeType || (NodeType = {})); var _id = 1; var symbolAndNumberRegex = RegExp('[^a-z1-6-]'); function genId() { return _id++; } function getValidTagName(tagName) { var processedTagName = tagName.toLowerCase().trim(); if (symbolAndNumberRegex.test(processedTagName)) { return 'div'; } return processedTagName; } function getCssRulesString(s) { try { var rules = s.rules || s.cssRules; return rules ? Array.from(rules).reduce(function (prev, cur) { return prev + getCssRuleString(cur); }, '') : null; } catch (error) { return null; } } function getCssRuleString(rule) { return isCSSImportRule(rule) ? getCssRulesString(rule.styleSheet) || '' : rule.cssText; } function isCSSImportRule(rule) { return 'styleSheet' in rule; } function extractOrigin(url) { var origin; if (url.indexOf('//') > -1) { origin = url.split('/').slice(0, 3).join('/'); } else { origin = url.split('/')[0]; } origin = origin.split('?')[0]; return origin; } var URL_IN_CSS_REF = /url\((?:'([^']*)'|"([^"]*)"|([^)]*))\)/gm; var RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*/; var DATA_URI = /^(data:)([\w\/\+\-]+);(charset=[\w-]+|base64).*,(.*)/i; function absoluteToStylesheet(cssText, href) { return (cssText || '').replace(URL_IN_CSS_REF, function (origin, path1, path2, path3) { var filePath = path1 || path2 || path3; if (!filePath) { return origin; } if (!RELATIVE_PATH.test(filePath)) { return "url('" + filePath + "')"; } if (DATA_URI.test(filePath)) { return "url(" + filePath + ")"; } if (filePath[0] === '/') { return "url('" + (extractOrigin(href) + filePath) + "')"; } var stack = href.split('/'); var parts = filePath.split('/'); stack.pop(); for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { var part = parts_1[_i]; if (part === '.') { continue; } else if (part === '..') { stack.pop(); } else { stack.push(part); } } return "url('" + stack.join('/') + "')"; }); } function getAbsoluteSrcsetString(doc, attributeValue) { if (attributeValue.trim() === '') { return attributeValue; } var srcsetValues = attributeValue.split(','); var resultingSrcsetString = srcsetValues .map(function (srcItem) { var trimmedSrcItem = srcItem.trimLeft().trimRight(); var urlAndSize = trimmedSrcItem.split(' '); if (urlAndSize.length === 2) { var absUrl = absoluteToDoc(doc, urlAndSize[0]); return absUrl + " " + urlAndSize[1]; } else if (urlAndSize.length === 1) { var absUrl = absoluteToDoc(doc, urlAndSize[0]); return "" + absUrl; } return ''; }) .join(', '); return resultingSrcsetString; } function absoluteToDoc(doc, attributeValue) { if (!attributeValue || attributeValue.trim() === '') { return attributeValue; } var a = doc.createElement('a'); a.href = attributeValue; return a.href; } function isSVGElement(el) { return el.tagName === 'svg' || el instanceof SVGElement; } function transformAttribute(doc, name, value) { if (name === 'src' || (name === 'href' && value)) { return absoluteToDoc(doc, value); } else if (name === 'srcset' && value) { return getAbsoluteSrcsetString(doc, value); } else if (name === 'style' && value) { return absoluteToStylesheet(value, location.href); } else { return value; } } function serializeNode(n, doc, blockClass, inlineStylesheet, maskInputOptions, blockElements, recordCanvas) { if (maskInputOptions === void 0) { maskInputOptions = {}; } if (blockElements === void 0) { blockElements = []; } if (recordCanvas === void 0) { recordCanvas = false; } switch (n.nodeType) { case n.DOCUMENT_NODE: return { type: NodeType.Document, childNodes: [], }; case n.DOCUMENT_TYPE_NODE: return { type: NodeType.DocumentType, name: n.name, publicId: n.publicId, systemId: n.systemId, }; case n.ELEMENT_NODE: var needBlock_1 = false; var placeholder = ''; if (typeof blockClass === 'string') { needBlock_1 = n.classList.contains(blockClass); } else if (n.classList && !!(n.classList.forEach)) { n.classList.forEach(function (className) { if (blockClass.test(className)) { needBlock_1 = true; } }); } var tagName = getValidTagName(n.tagName); if (!needBlock_1) { for (var _i = 0, blockElements_1 = blockElements; _i < blockElements_1.length; _i++) { var blockElement = blockElements_1[_i]; if (tagName === blockElement.tagName) { needBlock_1 = true; if (blockElement.placeholder) { placeholder = blockElement.placeholder; } break; } } } var attributes_1 = {}; for (var _a = 0, _b = Array.from(n.attributes); _a < _b.length; _a++) { var _c = _b[_a], name = _c.name, value = _c.value; attributes_1[name] = transformAttribute(doc, name, value); var isStaticRes = (tagName === 'img' && name === 'src') || (tagName === 'link' && name === 'href'); var rel_1 = n.rel; var isPreload_1 = rel_1 === 'dns-prefetch' || rel_1 === 'preload'; if (isStaticRes && !isPreload_1 && !/^data:image/i.test(attributes_1[name])) { attributes_1["_memimage_" + name] = attributes_1[name]; } } var rel = n.rel; var isPreload = rel === 'dns-prefetch' || rel === 'preload' || rel === 'prefetch'; if (tagName === 'link' && !isPreload && inlineStylesheet) { var stylesheet = Array.from(doc.styleSheets).find(function (s) { return s.href === n.href; }); var cssText = getCssRulesString(stylesheet); if (cssText) { delete attributes_1.rel; delete attributes_1.href; if ('_memimage_href' in attributes_1) { delete attributes_1._memimage_href; } attributes_1._cssText = absoluteToStylesheet(cssText, stylesheet.href); } } if (tagName === 'style' && n.sheet && !(n.innerText || n.textContent || '').trim().length) { var cssText = getCssRulesString(n.sheet); if (cssText) { attributes_1._cssText = absoluteToStylesheet(cssText, location.href); } } if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') { var value = n.value; if (attributes_1.type !== 'radio' && attributes_1.type !== 'checkbox' && attributes_1.type !== 'submit' && attributes_1.type !== 'button' && value) { attributes_1.value = maskInputOptions[attributes_1.type] || maskInputOptions[tagName] ? '*'.repeat(value.length) : value; } else if (n.checked) { attributes_1.checked = n.checked; } } if (tagName === 'option') { var selectValue = n.parentElement; if (attributes_1.value === selectValue.value) { attributes_1.selected = n.selected; } } if (tagName === 'canvas' && recordCanvas) { attributes_1.mem_dataURL = n.toDataURL(); } if (n.scrollLeft) { attributes_1.mem_scrollLeft = n.scrollLeft; } if (n.scrollTop) { attributes_1.mem_scrollTop = n.scrollTop; } if (needBlock_1) { var _d = n.getBoundingClientRect(), width = _d.width, height = _d.height; attributes_1.mem_width = width + "px"; attributes_1.mem_height = height + "px"; if (placeholder) { attributes_1.mem_placeholder = placeholder; } } return { type: NodeType.Element, tagName: tagName, attributes: attributes_1, childNodes: [], isSVG: isSVGElement(n) || undefined, needBlock: needBlock_1, }; case n.TEXT_NODE: var parentTagName = n.parentNode && n.parentNode.tagName; var textContent = n.textContent; var isStyle = parentTagName === 'STYLE' ? true : undefined; if (isStyle && textContent) { textContent = absoluteToStylesheet(textContent, location.href); } if (parentTagName === 'SCRIPT') { textContent = 'SCRIPT_PLACEHOLDER'; } return { type: NodeType.Text, textContent: textContent || '', isStyle: isStyle, }; case n.CDATA_SECTION_NODE: return { type: NodeType.CDATA, textContent: '', }; case n.COMMENT_NODE: return { type: NodeType.Comment, textContent: n.textContent || '', }; default: return false; } } function serializeNodeWithId(n, doc, map, blockClass, skipChild, inlineStylesheet, maskInputOptions, blockElements, recordCanvas) { if (skipChild === void 0) { skipChild = false; } if (inlineStylesheet === void 0) { inlineStylesheet = true; } if (blockElements === void 0) { blockElements = []; } if (recordCanvas === void 0) { recordCanvas = false; } var _serializedNode = serializeNode(n, doc, blockClass, inlineStylesheet, maskInputOptions, blockElements, recordCanvas); if (!_serializedNode) { console.warn(n, 'not serialized'); return null; } var id; if ('__sn' in n) { id = n.__sn.id; } else { id = genId(); } var serializedNode = Object.assign(_serializedNode, { id: id }); n.__sn = serializedNode; map[id] = n; var recordChild = !skipChild; if (serializedNode.type === NodeType.Element) { recordChild = recordChild && !serializedNode.needBlock; delete serializedNode.needBlock; } if ((serializedNode.type === NodeType.Document || serializedNode.type === NodeType.Element) && recordChild) { for (var _i = 0, _a = Array.from(n.childNodes); _i < _a.length; _i++) { var childN = _a[_i]; var serializedChildNode = serializeNodeWithId(childN, doc, map, blockClass, skipChild, inlineStylesheet, maskInputOptions, blockElements, recordCanvas); if (serializedChildNode) { serializedNode.childNodes.push(serializedChildNode); } } } return serializedNode; } function snapshot(n, blockClass, inlineStylesheet, maskAllInputsOrOptions, blockElements, recordCanvas) { if (blockClass === void 0) { blockClass = 'mem-block'; } if (inlineStylesheet === void 0) { inlineStylesheet = true; } if (blockElements === void 0) { blockElements = []; } if (recordCanvas === void 0) { recordCanvas = false; } var idNodeMap = {}; var maskInputOptions = maskAllInputsOrOptions === 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, } : maskAllInputsOrOptions === false ? {} : maskAllInputsOrOptions; return [ serializeNodeWithId(n, n, idNodeMap, blockClass, false, inlineStylesheet, maskInputOptions, blockElements, recordCanvas), idNodeMap, ]; } var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; function parse(css, options) { if (options === void 0) { options = {}; } var lineno = 1; var column = 1; function updatePosition(str) { var lines = str.match(/\n/g); if (lines) { lineno += lines.length; } var i = str.lastIndexOf('\n'); column = i === -1 ? column + str.length : str.length - i; } function position() { var start = { line: lineno, column: column }; return function (node) { node.position = new Position(start); whitespace(); return node; }; } var Position = (function () { function Position(start) { this.start = start; this.end = { line: lineno, column: column }; this.source = options.source; } return Position; }()); Position.prototype.content = css; var errorsList = []; function error(msg) { var 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() { var rulesList = rules(); return { type: 'stylesheet', stylesheet: { source: options.source, rules: rulesList, parsingErrors: errorsList, }, }; } function open() { return match(/^{\s*/); } function close() { return match(/^}/); } function rules() { var node; var rules = []; whitespace(); comments(rules); while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { if (node !== false) { rules.push(node); comments(rules); } } return rules; } function match(re) { var m = re.exec(css); if (!m) { return; } var str = m[0]; updatePosition(str); css = css.slice(str.length); return m; } function whitespace() { match(/^\s*/); } function comments(rules) { if (rules === void 0) { rules = []; } var c; while ((c = comment())) { if (c !== false) { rules.push(c); } c = comment(); } return rules; } function comment() { var pos = position(); if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { return; } var 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'); } var str = css.slice(2, i - 2); column += 2; updatePosition(str); css = css.slice(i); column += 2; return pos({ type: 'comment', comment: str, }); } function selector() { var m = match(/^([^{]+)/); if (!m) { return; } return trim(m[0]) .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) { return m.replace(/,/g, '\u200C'); }) .split(/\s*(?![^(]*\)),\s*/) .map(function (s) { return s.replace(/\u200C/g, ','); }); } function declaration() { var pos = position(); var propMatch = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); if (!propMatch) { return; } var prop = trim(propMatch[0]); if (!match(/^:\s*/)) { return error("property missing ':'"); } var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); var ret = pos({ type: 'declaration', property: prop.replace(commentre, ''), value: val ? trim(val[0]).replace(commentre, '') : '', }); match(/^[;\s]*/); return ret; } function declarations() { var decls = []; if (!open()) { return error("missing '{'"); } comments(decls); var decl; while ((decl = declaration())) { if (decl !== false) { decls.push(decl); comments(decls); } decl = declaration(); } if (!close()) { return error("missing '}'"); } return decls; } function keyframe() { var m; var vals = []; var 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() { var pos = position(); var m = match(/^@([-\w]+)?keyframes\s*/); if (!m) { return; } var vendor = m[1]; m = match(/^([-\w]+)\s*/); if (!m) { return error('@keyframes missing name'); } var name = m[1]; if (!open()) { return error("@keyframes missing '{'"); } var frame; var frames = comments(); while ((frame = keyframe())) { frames.push(frame); frames = frames.concat(comments()); } if (!close()) { return error("@keyframes missing '}'"); } return pos({ type: 'keyframes', name: name, vendor: vendor, keyframes: frames, }); } function atsupports() { var pos = position(); var m = match(/^@supports *([^{]+)/); if (!m) { return; } var supports = trim(m[1]); if (!open()) { return error("@supports missing '{'"); } var style = comments().concat(rules()); if (!close()) { return error("@supports missing '}'"); } return pos({ type: 'supports', supports: supports, rules: style, }); } function athost() { var pos = position(); var m = match(/^@host\s*/); if (!m) { return; } if (!open()) { return error("@host missing '{'"); } var style = comments().concat(rules()); if (!close()) { return error("@host missing '}'"); } return pos({ type: 'host', rules: style, }); } function atmedia() { var pos = position(); var m = match(/^@media *([^{]+)/); if (!m) { return; } var media = trim(m[1]); if (!open()) { return error("@media missing '{'"); } var style = comments().concat(rules()); if (!close()) { return error("@media missing '}'"); } return pos({ type: 'media', media: media, rules: style, }); } function atcustommedia() { var pos = position(); var 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() { var pos = position(); var m = match(/^@page */); if (!m) { return; } var sel = selector() || []; if (!open()) { return error("@page missing '{'"); } var decls = comments(); var 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() { var pos = position(); var m = match(/^@([-\w]+)?document *([^{]+)/); if (!m) { return; } var vendor = trim(m[1]); var doc = trim(m[2]); if (!open()) { return error("@document missing '{'"); } var style = comments().concat(rules()); if (!close()) { return error("@document missing '}'"); } return pos({ type: 'document', document: doc, vendor: vendor, rules: style, }); } function atfontface() { var pos = position(); var m = match(/^@font-face\s*/); if (!m) { return; } if (!open()) { return error("@font-face missing '{'"); } var decls = comments(); var 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, }); } var atimport = _compileAtrule('import'); var atcharset = _compileAtrule('charset'); var atnamespace = _compileAtrule('namespace'); function _compileAtrule(name) { var re = new RegExp('^@' + name + '\\s*([^;]+);'); return function () { var pos = position(); var m = match(re); if (!m) { return; } var 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() { var pos = position(); var 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) { var isNode = obj && typeof obj.type === 'string'; var childParent = isNode ? obj : parent; for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { var k = _a[_i]; var value = obj[k]; if (Array.isArray(value)) { value.forEach(function (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; } var 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) { var tagName = tagMap[n.tagName] ? tagMap[n.tagName] : n.tagName; if (tagName === 'link' && n.attributes._cssText) { tagName = 'style'; } return tagName; } var HOVER_SELECTOR = /([^\\]):hover/g; var WECHAT_DEVELOPER_INSET_BUG = /(\s|;|\{)inset\s*:([^;}]+)/ig; function addHoverClass(cssText) { var ast = parse(cssText, { silent: true }); if (!ast.stylesheet || !ast.stylesheet.rules) { return cssText; } ast.stylesheet.rules.forEach(function (rule) { if ('selectors' in rule) { (rule.selectors || []).forEach(function (selector) { if (HOVER_SELECTOR.test(selector)) { var newSelector = selector.replace(HOVER_SELECTOR, '$1.\\:hover'); cssText = cssText.replace(selector, selector + ", " + newSelector); } }); } }); return cssText.replace(WECHAT_DEVELOPER_INSET_BUG, '$1top: $2; right: $2; bottom: $2; left: $2;'); } var DATA_SVG_URI = /url\((data:image\/svg\+xml;charset=[\w-].*?)\)\s*(;|\}|$)/ig; function addQuotationMarkForDataSvg(cssText) { return cssText ? cssText.replace(DATA_SVG_URI, function ($0, $1, $2) { return "url(\"" + $1 + "\")" + $2; }) : cssText; } function buildNode(n, doc, HACK_CSS, cdnHttps) { if (cdnHttps === void 0) { cdnHttps = true; } switch (n.type) { case NodeType.Document: return doc.implementation.createDocument(null, '', null); case NodeType.DocumentType: return doc.implementation.createDocumentType(n.name, n.publicId, n.systemId); case NodeType.Element: var tagName = getTagName(n); var node_1; if (n.isSVG) { node_1 = doc.createElementNS('http://www.w3.org/2000/svg', tagName); } else { node_1 = doc.createElement(tagName); } var _loop_1 = function (name) { if (!n.attributes.hasOwnProperty(name)) { return "continue"; } if (n.attributes.hasOwnProperty("_memimage_" + name)) { return "continue"; } var value = n.attributes[name]; value = typeof value === 'boolean' || typeof value === 'number' ? '' : value; var originAttrbuteName = name; name = name.replace('_memimage_', ''); if (!name.startsWith('mem_')) { var isTextarea = tagName === 'textarea' && name === 'value'; var isRemoteOrDynamicCss = tagName === 'style' && name === '_cssText'; if (isRemoteOrDynamicCss && HACK_CSS) { value = addHoverClass(value); value = addQuotationMarkForDataSvg(value); } if (isTextarea || isRemoteOrDynamicCss) { var child = doc.createTextNode(value); for (var _i = 0, _a = Array.from(node_1.childNodes); _i < _a.length; _i++) { var c = _a[_i]; if (c.nodeType === node_1.TEXT_NODE) { node_1.removeChild(c); } } node_1.appendChild(child); return "continue"; } if (tagName === 'iframe' && name === 'src') { return "continue"; } try { if (n.isSVG && name === 'xlink:href') { node_1.setAttributeNS('http://www.w3.org/1999/xlink', name, value); } else if (name === 'onload' || name === 'onclick' || name.substring(0, 7) === 'onmouse') { node_1.setAttribute('_' + name, value); } else { if (cdnHttps && tagName === 'link' && originAttrbuteName === '_memimage_href') { if (value && value.match(/memento\.oss/)) { value = value.replace(/^http\:\/\//, 'https://'); } } node_1.setAttribute(name, value); } } catch (error) { } } else { if (tagName === 'canvas' && name === 'mem_dataURL') { var image_1 = document.createElement('img'); image_1.src = value; image_1.onload = function () { var ctx = node_1.getContext('2d'); if (ctx) { ctx.drawImage(image_1, 0, 0, image_1.width, image_1.height); } }; } if (name === 'mem_imgwidth') { node_1.style.width = value; } else if (name === 'mem_width') { node_1.style.width = value; } else if (name === 'mem_imgheight') { node_1.style.height = value; } else if (name === 'mem_height') { node_1.style.height = value; } else if (tagName === 'video' && originAttrbuteName === 'mem_placeholder') { node_1.style.background = "center / cover no-repeat url(" + value + ") !important"; } } }; for (var name in n.attributes) { _loop_1(name); } return node_1; case NodeType.Text: var textContent = n.isStyle ? addQuotationMarkForDataSvg(n.textContent) : n.textContent; return doc.createTextNode(n.isStyle && HACK_CSS ? addHoverClass(textContent) : textContent); case NodeType.CDATA: return doc.createCDATASection(n.textContent); case NodeType.Comment: return doc.createComment(n.textContent); default: return null; } } function buildNodeWithSN(n, doc, map, skipChild, HACK_CSS, cdnHttps) { if (skipChild === void 0) { skipChild = false; } if (HACK_CSS === void 0) { HACK_CSS = true; } if (cdnHttps === void 0) { cdnHttps = true; } var node = buildNode(n, doc, HACK_CSS, cdnHttps); if (!node) { return null; } if (n.type === NodeType.Document) { doc.close(); doc.open(); node = doc; } node.__sn = n; map[n.id] = node; if ((n.type === NodeType.Document || n.type === NodeType.Element) && !skipChild) { for (var _i = 0, _a = n.childNodes; _i < _a.length; _i++) { var childN = _a[_i]; var childNode = buildNodeWithSN(childN, doc, map, false, HACK_CSS, cdnHttps); if (!childNode) { console.warn('Failed to rebuild', childN); } else { node.appendChild(childNode); } } } return node; } function sideEffects(idNodeMap) { for (var id in idNodeMap) { var node = idNodeMap[id]; var n = node.__sn; if (n.type !== NodeType.Element) { continue; } var el = node; for (var name in n.attributes) { if (!(n.attributes.hasOwnProperty(name) && name.startsWith('mem_'))) { continue; } var value = n.attributes[name]; if (name === 'mem_scrollLeft') { el.scrollLeft = value; } if (name === 'mem_scrollTop') { el.scrollTop = value; } } } } function rebuild(n, doc, HACK_CSS, cdnHttps) { if (HACK_CSS === void 0) { HACK_CSS = true; } if (cdnHttps === void 0) { cdnHttps = true; } var idNodeMap = {}; var node = buildNodeWithSN(n, doc, idNodeMap, false, HACK_CSS, cdnHttps); sideEffects(idNodeMap); return [node, idNodeMap]; } export { snapshot, serializeNodeWithId, rebuild, buildNodeWithSN, addHoverClass, transformAttribute, NodeType };