UNPKG

svgdom

Version:

Straightforward DOM implementation for SVG, HTML and XML

81 lines (61 loc) 2 kB
import sax from 'sax' // TODO: Its an XMLParser not HTMLParser!! export const HTMLParser = function (str, el) { let currentTag = el // const namespaces = { xmlns: el.getAttribute('xmlns') } let document = el.ownerDocument let cdata = null // sax expects a root element but we also missuse it to parse fragments if (el.nodeType !== el.DOCUMENT_NODE) { str = '<svgdom:wrapper xmlns:svgdom="svgdom:rocks">' + str + '</svgdom:wrapper>' } else { document = el } const parser = sax.parser(true, { // lowercase: true, xmlns: true, strictEntities: true }) parser.onerror = (e) => { throw e } parser.ondoctype = () => { if (currentTag !== document) { throw new Error('Doctype can only be appended to document') } currentTag.appendChild(document.implementation.createDocumentType()) } parser.ontext = (str) => currentTag.appendChild(document.createTextNode(str)) parser.oncomment = (str) => currentTag.appendChild(document.createComment(str)) // parser.onopennamespace = ns => { // namespaces[ns.prefix] = ns.uri // } // parser.onclosenamespace = ns => { // delete namespaces[ns.prefix] // } parser.onopentag = node => { if (node.name === 'svgdom:wrapper') return const attrs = node.attributes const uri = node.uri || currentTag.lookupNamespaceURI(node.prefix || null) const newElement = document.createElementNS(uri, node.name) for (const [ name, node ] of Object.entries(attrs)) { newElement.setAttributeNS(node.uri, name, node.value) } currentTag.appendChild(newElement) currentTag = newElement } parser.onclosetag = tagName => { if (tagName === 'svgdom:wrapper') return currentTag = currentTag.parentNode } parser.onopencdata = () => { cdata = document.createCDATASection('') } parser.oncdata = (str) => { cdata.appendData(str) } parser.onclosecdata = () => { currentTag.appendChild(cdata) } parser.write(str) }