import { hasOwn, isPlainObject } from 'uni-shared' const TAGS = { a: '', abbr: '', b: '', blockquote: '', br: '', code: '', col: ['span', 'width'], colgroup: ['span', 'width'], dd: '', del: '', div: '', dl: '', dt: '', em: '', fieldset: '', h1: '', h2: '', h3: '', h4: '', h5: '', h6: '', hr: '', i: '', img: ['alt', 'src', 'height', 'width'], ins: '', label: '', legend: '', li: '', ol: ['start', 'type'], p: '', q: '', span: '', strong: '', sub: '', sup: '', table: ['width'], tbody: '', td: ['colspan', 'rowspan', 'height', 'width'], tfoot: '', th: ['colspan', 'rowspan', 'height', 'width'], thead: '', tr: '', ul: '' } const CHARS = { amp: '&', gt: '>', lt: '<', nbsp: ' ', quot: '"', apos: "'" } function decodeEntities (htmlString) { return htmlString.replace(/&(([a-zA-Z]+)|(#x{0,1}[\da-zA-Z]+));/gi, function (match, stage) { if (hasOwn(CHARS, stage) && CHARS[stage]) { return CHARS[stage] } if (/^#[0-9]{1,4}$/.test(stage)) { return String.fromCharCode(stage.slice(1)) } if (/^#x[0-9a-f]{1,4}$/i.test(stage)) { return String.fromCharCode('0' + stage.slice(1)) } const wrap = document.createElement('div') wrap.innerHTML = match return wrap.innerText || wrap.textContent }) } export default function parseNodes (nodes, parentNode) { nodes.forEach(function (node) { if (!isPlainObject(node)) { return } if (!hasOwn(node, 'type') || node.type === 'node') { if (!(typeof node.name === 'string' && node.name)) { return } const tagName = node.name.toLowerCase() if (!hasOwn(TAGS, tagName)) { return } const elem = document.createElement(tagName) if (!elem) { return } const attrs = node.attrs if (isPlainObject(attrs)) { const tagAttrs = TAGS[tagName] || [] Object.keys(attrs).forEach(function (name) { let value = attrs[name] switch (name) { case 'class': /* eslint-disable no-fallthrough */ Array.isArray(value) && (value = value.join(' ')) case 'style': elem.setAttribute(name, value) break default: if (tagAttrs.indexOf(name) !== -1) { elem.setAttribute(name, value) } } }) } const children = node.children if (Array.isArray(children) && children.length) { parseNodes(node.children, elem) } parentNode.appendChild(elem) } else { if (node.type === 'text' && typeof node.text === 'string' && node.text !== '') { parentNode.appendChild(document.createTextNode(decodeEntities(node.text))) } } }) return parentNode }