packages/postsvg/lib/tree.js (44 lines of code) (raw):

const clone = require('clone'); const { match, walk } = require('posthtml/lib/api'); const matchHelper = require('posthtml-match-helper'); const renderer = require('./renderer'); /** * @typedef {Object} Node * @property {string} tag * @property {Object} [attrs] * @property {Array<Node|string>} [content] */ class PostSvgTree extends Array { /** * @param {Array} array * @return {PostSvgTree} */ static createFromArray(array) { let wrapper = new PostSvgTree(); wrapper = wrapper.concat(array); return wrapper; } /** * @return {Node} */ get root() { return this.find(node => typeof node === 'object' && 'tag' in node); } /** * @return {string} */ toString() { return renderer(this, this.options); } /** * @return {PostSvgTree} */ clone() { return PostSvgTree.createFromArray(clone(this)); } match(expression, callback) { return match.call(this, expression, callback); } walk(callback) { return walk.call(this, callback); } /** * @param {string} selector * @return {Node[]} */ select(selector) { const nodes = []; const selectAllNodes = typeof selector === 'undefined' || selector === '*'; const matcher = selectAllNodes ? { tag: /\.*/ } : matchHelper(selector); match.call(this, matcher, node => { nodes.push(node); return node; }); return nodes; } /** * @param {string|function(node): void} selector * @param {function(node): void} [callback] * @return {Node[]} */ each(selector, callback) { const hasSelector = typeof selector === 'string'; const nodes = this.select(hasSelector ? selector : '*'); return selector ? nodes.forEach(typeof selector === 'function' ? selector : callback) : nodes; } } module.exports = PostSvgTree;