UNPKG

@stringsync/vexml

Version:

MusicXML to Vexflow

99 lines (98 loc) 3.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NamedElement = void 0; const value_1 = require("./value"); /** * A readonly wrapper that enforces compile-time checking on an element's name. * * For example, requiring a signature to use NamedElement<'foo'> will force the caller to assert that an element's name * is foo. As long as types aren't being dynamically casted, this is also backed by the compiler. * * It also provides convenience methods on top of the Element API. */ class NamedElement { element; name; constructor(element, name) { this.element = element; this.name = name; } /** Creates a NamedNode from a document node. */ static of(element) { return new NamedElement(element, element.nodeName); } /** Determines if the node has the given name. */ isNamed(name) { return this.name === name; } /** Casts the underlying node to an Element. */ native() { return this.element; } children(...tagNames) { let nodes; if (tagNames.length === 0) { nodes = Array.from(this.element.children); } else { const selector = tagNames.map((tagName) => `:scope > ${tagName}`).join(', '); nodes = Array.from(this.element.querySelectorAll(selector)); } return nodes.map((node) => NamedElement.of(node)); } /** Returns the first _descendant_ node matching the tag name. Defaults to null. */ first(tagName) { const element = this.element.getElementsByTagName(tagName).item(0); return element ? NamedElement.of(element) : null; } /** Returns all _descendant_ node matching the tag name. */ all(tagName) { return Array.from(this.element.getElementsByTagName(tagName)).map((node) => NamedElement.of(node)); } /** Returns the next _sibling_ node matching the tag name. */ next(tagName) { let sibling = this.element.nextElementSibling; while (sibling) { const element = NamedElement.of(sibling); if (element.isNamed(tagName)) { return element; } sibling = sibling.nextElementSibling; } return null; } /** Returns the previous _sibling_ node matching the tag name. */ previous(tagName) { let sibling = this.element.previousElementSibling; while (sibling) { const element = NamedElement.of(sibling); if (element.isNamed(tagName)) { return element; } sibling = sibling.previousElementSibling; } return null; } /** Returns the _ancestor_ matching the tag name. Defaults to null. */ ancestor(tagName) { let parent = this.element.parentElement; while (parent) { const element = NamedElement.of(parent); if (element.isNamed(tagName)) { return element; } parent = parent.parentElement; } return null; } /** Returns an attr wrapper for the attribute of the given name. */ attr(name) { const value = this.element.getAttribute(name); return value_1.Value.of(value); } /** Returns the text content of the node. */ content() { return value_1.Value.of(this.element.textContent || null); } } exports.NamedElement = NamedElement;