{"ScriptPreparationCode":null,"TestCases":[{"Name":"Create template","Code":"/**\r\n * Creates a virtual DOM tree from an HTML string.\r\n *\r\n * @param {string} htmlString - The HTML string to parse.\r\n * @return {Object} The root node of the virtual DOM tree.\r\n */\r\nfunction createVirtualDOM(htmlString) {\r\n\r\n /**\r\n * Recursively creates a virtual DOM node from a DOM element.\r\n *\r\n * @param {Element} element - The DOM element to create a virtual node from.\r\n * @return {Object} The virtual DOM node.\r\n */\r\n function createNode(element) {\r\n //console.log(elements)\r\n // Create a virtual DOM node with the element\u0027s tag name and attributes\r\n \r\n const node = {\r\n tagName: element.tagName,\r\n attributes: {}\r\n };\r\n\r\n \r\n // Add the element\u0027s attributes to the virtual node\r\n for (let i = 0; i \u003C element.attributes.length; i\u002B\u002B) {\r\n const attribute = element.attributes[i];\r\n node.attributes[attribute.name] = attribute.value;\r\n }\r\n\r\n // If the element has child nodes, create virtual nodes for them as well\r\n if (element.childNodes.length \u003E 0) {\r\n node.children = [];\r\n for (let i = 0; i \u003C element.childNodes.length; i\u002B\u002B) {\r\n const child = element.childNodes[i];\r\n\r\n if (child.nodeType === Node.ELEMENT_NODE) {\r\n // Recursively create a virtual node for the child element\r\n node.children.push(createNode(child));\r\n } else if (child.nodeType === Node.TEXT_NODE) {\r\n // Skip whitespace\r\n if (child.textContent.trim().length === 0) continue;\r\n // Create a virtual node for the child text node\r\n node.children.push({\r\n //tagName: null,\r\n text: child.textContent\r\n });\r\n }\r\n }\r\n }\r\n \r\n return node;\r\n \r\n }\r\n\r\n \r\n var t = document.createElement(\u0027template\u0027);\r\n t.innerHTML = \u0060\u003Ct\u003E${htmlString}\u003C/t\u003E\u0060;\r\n const nodes = [];\r\n t.content.querySelectorAll(\u0027t \u003E *\u0027).forEach(element =\u003E nodes.push(createNode(element)));\r\n \r\n // Return the root virtual DOM node\r\n return nodes;\r\n}\r\n\r\nconst vdom = createVirtualDOM(\u0060\u003Cdiv\u003E\r\n \u003Ch4\u003EIncome\u003C/h4\u003E\r\n \u003Cp id=\u0022money-plus\u0022 class=\u0022money plus\u0022\u003E\u003Cplaceholder data-id=\u0022income\u0022/\u003E\u003C/p\u003E\r\n \u003C/div\u003E\r\n \u003Cdiv\u003E\r\n \u003Ch4\u003EExpense\u003C/h4\u003E\r\n \u003Cp id=\u0022money-minus\u0022 class=\u0022money minus\u0022\u003E\u003Cplaceholder data-id=\u0022expense\u0022/\u003E\u003C/p\u003E\r\n \u003Cinput type=\u0022checkbox\u0022 name=\u0022testcheck\u0022 value=\u0022checkme\u0022 checked /\u003E\r\n \u003Cdiv class=\u0022inner\u0022\u003EText \u003Ca href=\u0022#\u0022\u003Ewith\u003C/a\u003E link\u003C/div\u003E\r\n \u003C/div\u003E\u0060);","IsDeferred":false},{"Name":"Regex","Code":"\r\nlookup = {\r\n \u0022area\u0022: true,\r\n \u0022base\u0022: true,\r\n \u0022br\u0022: true,\r\n \u0022col\u0022: true,\r\n \u0022embed\u0022: true,\r\n \u0022hr\u0022: true,\r\n \u0022img\u0022: true,\r\n \u0022input\u0022: true,\r\n \u0022link\u0022: true,\r\n \u0022meta\u0022: true,\r\n \u0022param\u0022: true,\r\n \u0022source\u0022: true,\r\n \u0022track\u0022: true,\r\n \u0022wbr\u0022: true\r\n};\r\n\r\n\r\nconst attrRE = /\\s([^\u0027\u0022/\\s\u003E\u003C]\u002B?)[\\s/\u003E]|([^\\s=]\u002B)=\\s?(\u0022.*?\u0022|\u0027.*?\u0027)/g\r\n\r\nfunction parseTag(tag) {\r\n let voidElement = false\r\n\r\n const res = {\r\n tagName: \u0027\u0027,\r\n attributes: {},\r\n children: [],\r\n }\r\n\r\n const tagMatch = tag.match(/\u003C\\/?([^\\s]\u002B?)[/\\s\u003E]/)\r\n if (tagMatch) {\r\n res.tagName = tagMatch[1]\r\n if (lookup[tagMatch[1]] || tag.charAt(tag.length - 2) === \u0027/\u0027) {\r\n voidElement = true\r\n }\r\n }\r\n\r\n const reg = new RegExp(attrRE)\r\n let result = null\r\n for (;;) {\r\n result = reg.exec(tag)\r\n\r\n if (result === null) {\r\n break\r\n }\r\n\r\n if (!result[0].trim()) {\r\n continue\r\n }\r\n\r\n if (result[1]) {\r\n const attr = result[1].trim()\r\n let arr = [attr, true]\r\n\r\n if (attr.indexOf(\u0027=\u0027) \u003E -1) {\r\n arr = attr.split(\u0027=\u0027)\r\n }\r\n\r\n res.attributes[arr[0]] = arr[1]\r\n reg.lastIndex--\r\n } else if (result[2]) {\r\n res.attributes[result[2]] = result[3].trim().substring(1, result[3].length - 1)\r\n }\r\n }\r\n\r\n return [ res, voidElement ]\r\n}\r\n\r\n\r\nconst tagRE = /\u003C[a-zA-Z0-9\\-\\!\\/](?:\u0022[^\u0022]*\u0022|\u0027[^\u0027]*\u0027|[^\u0027\u0022\u003E])*\u003E/g\r\nconst whitespaceRE = /^\\s*$/\r\n\r\n// re-used obj for quick lookups of components\r\nconst empty = Object.create(null)\r\n\r\nfunction parse(html) {\r\n const result = []\r\n const arr = []\r\n let current\r\n let level = -1\r\n let voidElement\r\n \r\n // handle text at top level\r\n if (html.indexOf(\u0027\u003C\u0027) !== 0) {\r\n var end = html.indexOf(\u0027\u003C\u0027)\r\n result.push({\r\n text: end === -1 ? html : html.substring(0, end)\r\n })\r\n }\r\n\r\n html.replace(tagRE, (tag, index) =\u003E {\r\n let isOpen = tag.charAt(1) !== \u0027/\u0027\r\n const start = index \u002B tag.length\r\n const nextChar = html.charAt(start)\r\n let parent\r\n\r\n // Skip comments\r\n if (tag.startsWith(\u0027\u003C!--\u0027)) {\r\n // Add following text node (if any)\r\n const text = html.slice(start, html.indexOf(\u0027\u003C\u0027, start)).trim();\r\n if (text.length \u003E 0) {\r\n \r\n if (level === -1) {\r\n result.push({ text })\r\n } else {\r\n parent = arr[level]\r\n if (parent) {\r\n parent.children.push({ text })\r\n }\r\n //arr[level \u002B 1] = { text }\r\n } \r\n }\r\n return \u0027\u0027\r\n }\r\n \r\n if (isOpen) {\r\n level\u002B\u002B\r\n\r\n [ current, voidElement ] = parseTag(tag)\r\n \r\n if (!voidElement \u0026\u0026 nextChar \u0026\u0026 nextChar !== \u0027\u003C\u0027) {\r\n let text = html.slice(start, html.indexOf(\u0027\u003C\u0027, start)).trim()\r\n if (text != \u0027\u0027) {\r\n current.children.push({ text })\r\n }\r\n }\r\n\r\n // if we\u0027re at root, push new base node\r\n if (level === 0) {\r\n result.push(current)\r\n }\r\n\r\n parent = arr[level - 1]\r\n\r\n if (parent) {\r\n parent.children.push(current)\r\n }\r\n\r\n arr[level] = current\r\n }\r\n\r\n if (!isOpen || voidElement) {\r\n if (level \u003E -1 \u0026\u0026 (voidElement || current.tagName === tag.slice(2, -1))) {\r\n level--\r\n // move current up a level to match the end tag\r\n current = level === -1 ? result : arr[level]\r\n }\r\n if (nextChar !== \u0027\u003C\u0027 \u0026\u0026 nextChar) {\r\n // trailing text node\r\n // if we\u0027re at the root, push a base text node. otherwise add as\r\n // a child to the current node.\r\n parent = level === -1 ? result : arr[level].children\r\n\r\n // calculate correct end of the content slice in case there\u0027s\r\n // no tag after the text node.\r\n const end = html.indexOf(\u0027\u003C\u0027, start)\r\n let content = html.slice(start, end === -1 ? undefined : end)\r\n // if a node is nothing but whitespace, collapse it as the spec states:\r\n // https://www.w3.org/TR/html4/struct/text.html#h-9.1\r\n if (whitespaceRE.test(content)) {\r\n content = \u0027\u0027\r\n }\r\n // don\u0027t add whitespace-only text nodes if they would be trailing text nodes\r\n // or if they would be leading whitespace-only text nodes:\r\n // * end \u003E -1 indicates this is not a trailing text node\r\n // * leading node is when level is -1 and parent has length 0\r\n if ((end \u003E -1 \u0026\u0026 level \u002B parent.length \u003E= 0 \u0026\u0026 content !== \u0027\u0027) || content !== \u0027\u0027) {\r\n parent.push({\r\n text: content,\r\n })\r\n }\r\n }\r\n }\r\n })\r\n\r\n return result\r\n}\r\n\r\n\r\nconst vdom = parse(\u0060\u003Cdiv\u003E\r\n \u003Ch4\u003EIncome\u003C/h4\u003E\r\n \u003Cp id=\u0022money-plus\u0022 class=\u0022money plus\u0022\u003E\u003Cplaceholder data-id=\u0022income\u0022/\u003E\u003C/p\u003E\r\n \u003C/div\u003E\r\n \u003Cdiv\u003E\r\n \u003Ch4\u003EExpense\u003C/h4\u003E\r\n \u003Cp id=\u0022money-minus\u0022 class=\u0022money minus\u0022\u003E\u003Cplaceholder data-id=\u0022expense\u0022/\u003E\u003C/p\u003E\r\n \u003Cinput type=\u0022checkbox\u0022 name=\u0022testcheck\u0022 value=\u0022checkme\u0022 checked /\u003E\r\n \u003Cdiv class=\u0022inner\u0022\u003EText \u003Ca href=\u0022#\u0022\u003Ewith\u003C/a\u003E link\u003C/div\u003E\r\n \u003C/div\u003E\u0060);","IsDeferred":false}]}