uhtml
Version:
A micro HTML/SVG render
88 lines (73 loc) • 2.09 kB
JavaScript
;
const HTMLParser2 = require('htmlparser2');
const { SVG_NAMESPACE } = require('../utils.js');
const Comment = (require('./comment.js'));
const Text = (require('./text.js'));
const { localName, ownerDocument, parentNode } = require('./symbols.js');
const { getNodes, isSVG } = require('./utils.js');
const { Parser } = HTMLParser2;
const { entries } = Object;
const setAttributes = (child, attributes) => {
for (const [name, value] of entries(attributes))
child.setAttribute(name, value);
};
exports.setAttributes = setAttributes;
const setChild = (parent, child) => {
child[parentNode] = parent;
getNodes(parent).push(child);
return child;
};
exports.setChild = setChild;
class Node {
constructor(node, svg) {
this.D = node[ownerDocument];
this.n = node;
this.s = svg;
this.d = true;
}
onopentag(name, attributes) {
const { D: document, n: node, s: svg } = this;
const asSVG = svg || isSVG(name);
this.n = setChild(
node,
asSVG ?
document.createElementNS(SVG_NAMESPACE, name) :
document.createElement(name)
);
if (asSVG) this.s = true;
setAttributes(this.n, attributes);
}
onclosetag() {
const { n: node, s: svg } = this;
this.n = node[parentNode];
if (svg && isSVG(this.n[localName]))
this.s = false;
}
oncomment(text) {
const { D: document, n: node } = this;
node.appendChild(new Comment(text, document));
}
ontext(text) {
const { D: document, n: node, d: data } = this;
if (data) node.appendChild(new Text(text, document));
}
oncdatastart() { this.d = false }
oncdataend() { this.d = true }
}
exports.Node = Node
const parse = (handler, xmlMode, text) => {
const content = new Parser(handler, {
lowerCaseAttributeNames: false,
decodeEntities: true,
recognizeCDATA: true,
xmlMode
});
content.write(text);
content.end();
};
exports.parse = parse;
const parseString = (node, xmlMode, text) => {
parse(new Node(node, xmlMode), xmlMode, text);
return node;
};
exports.parseString = parseString;