uhtml
Version:
A micro HTML/SVG render
59 lines (51 loc) • 1.57 kB
JavaScript
;
const { ELEMENT_NODE } = require('domconstants/constants');
const { escape } = require('html-escaper');
const Attribute = (require('./attribute.js'));
const Element = (require('./element.js'));
const { cloned, isSVG } = require('./utils.js');
const {
attributes,
name,
value,
localName,
childNodes,
ownerDocument,
parentNode
} = require('./symbols.js');
module.exports = class SVGElement extends Element {
constructor(name, owner = null) {
super(ELEMENT_NODE, owner)[localName] = name;
}
get ownerSVGElement() {
let { [parentNode]: parent } = this;
while (parent && !isSVG(parent[localName]))
parent = parent[parentNode];
return parent;
}
cloneNode(deep = false) {
const svg = new SVGElement(this[localName], this[ownerDocument]);
const { [attributes]: attrs, [childNodes]: nodes } = this;
if (attrs) {
const map = (svg[attributes] = new Map);
for (const { [name]: key, [value]: val } of this[attributes].values())
map.set(key, new Attribute(key, val, svg));
}
if (deep && nodes.length)
svg[childNodes] = nodes.map(cloned, svg);
return svg;
}
toString() {
const { [localName]: name, [childNodes]: nodes, [attributes]: attrs } = this;
const svg = ['<', name];
if (attrs?.size) {
for (const { name, value } of attrs.values())
svg.push(' ', name, '="', escape(value), '"');
}
if (nodes.length || isSVG(name))
svg.push('>', ...nodes, '</', name, '>');
else
svg.push(' />');
return svg.join('');
}
}