(html, fragment, doc)
| 4815 | }); |
| 4816 | } |
| 4817 | function parseHTMLToFragment(html, fragment, doc) { |
| 4818 | const stack = [fragment]; |
| 4819 | const tokenRe = /<!--[\s\S]*?-->|<!doctype[^>]*>|<\/?[a-zA-Z][^>]*>|[^<]+/gi; |
| 4820 | let match; |
| 4821 | while ((match = tokenRe.exec(html))) { |
| 4822 | const token = match[0]; |
| 4823 | if (token[0] !== '<') { |
| 4824 | const text = decodeEntities(token); |
| 4825 | if (text) stack[stack.length - 1].appendChild(doc.createTextNode(text)); |
| 4826 | continue; |
| 4827 | } |
| 4828 | if (token.indexOf('<!--') === 0) { |
| 4829 | continue; |
| 4830 | } |
| 4831 | if (/^<!doctype/i.test(token)) { |
| 4832 | continue; |
| 4833 | } |
| 4834 | if (token[1] === '/') { |
| 4835 | const tag = token.slice(2, -1).trim().toLowerCase(); |
| 4836 | for (let i = stack.length - 1; i > 0; i--) { |
| 4837 | const node = stack[i]; |
| 4838 | if (node.nodeType === 1 && node.nodeName.toLowerCase() === tag) { |
| 4839 | stack.length = i; |
| 4840 | break; |
| 4841 | } |
| 4842 | } |
| 4843 | continue; |
| 4844 | } |
| 4845 | const tagMatch = /^<\s*([^\s/>]+)/.exec(token); |
| 4846 | if (!tagMatch) continue; |
| 4847 | const rawName = tagMatch[1]; |
| 4848 | const tagName = rawName.toLowerCase(); |
| 4849 | const parent = stack[stack.length - 1]; |
| 4850 | const parentIsSvg = parent.nodeType === 1 && parent.namespaceURI === SVG_NS; |
| 4851 | const isSvg = parentIsSvg || tagName === 'svg'; |
| 4852 | const el = isSvg ? doc.createElementNS(SVG_NS, rawName) : doc.createElement(tagName); |
| 4853 | const attrPart = token.replace(/^<\s*[^\s/>]+/, '').replace(/\/?>$/, ''); |
| 4854 | if (attrPart) { |
| 4855 | const attrRe = /([^\s=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g; |
| 4856 | let attrMatch; |
| 4857 | while ((attrMatch = attrRe.exec(attrPart))) { |
| 4858 | const name = attrMatch[1]; |
| 4859 | const value = decodeEntities(attrMatch[2] || attrMatch[3] || attrMatch[4] || ''); |
| 4860 | el.setAttribute(name, value); |
| 4861 | } |
| 4862 | } |
| 4863 | parent.appendChild(el); |
| 4864 | const selfClosing = token.endsWith('/>'); |
| 4865 | if (!selfClosing && !VOID_TAGS[tagName]) { |
| 4866 | stack.push(el); |
| 4867 | if (RAW_TEXT_TAGS[tagName]) { |
| 4868 | const closeRe = new RegExp('<\\/\\s*' + tagName + '\\s*>', 'ig'); |
| 4869 | closeRe.lastIndex = tokenRe.lastIndex; |
| 4870 | const closeMatch = closeRe.exec(html); |
| 4871 | if (closeMatch) { |
| 4872 | const rawText = html.slice(tokenRe.lastIndex, closeMatch.index); |
| 4873 | if (rawText) el.appendChild(doc.createTextNode(rawText)); |
| 4874 | tokenRe.lastIndex = closeMatch.index + closeMatch[0].length; |
no test coverage detected