UNPKG

salve-annos

Version:

A fork with support for documentation of Salve, a Javascript library which implements a validator able to validate an XML document on the basis of a subset of RelaxNG.

178 lines 6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.XHTML_URI = exports.ANNOS_URI = exports.RELAXNG_URI = void 0; exports.findChildrenByLocalName = findChildrenByLocalName; exports.findDescendantsByLocalName = findDescendantsByLocalName; exports._findDescendantsByLocalName = _findDescendantsByLocalName; exports.findMultiDescendantsByLocalName = findMultiDescendantsByLocalName; exports.findMultiNames = findMultiNames; exports.indexBy = indexBy; exports.groupBy = groupBy; exports.getName = getName; exports.removeUnreferencedDefs = removeUnreferencedDefs; /** * Utilities for simplification support for trees produced by the parser module. * @author Louis-Dominique Dubeau * @license MPL 2.0 * @copyright 2013, 2014 Mangalam Research Center for Buddhist Languages */ const parser_1 = require("../parser"); // tslint:disable-next-line:no-http-string exports.RELAXNG_URI = "http://relaxng.org/ns/structure/1.0"; // tslint:disable-next-line:no-http-string exports.ANNOS_URI = "http://relaxng.org/ns/compatibility/annotations/1.0"; // tslint:disable-next-line:no-http-string exports.XHTML_URI = "http://www.w3.org/1999/xhtml"; function findChildrenByLocalName(el, name) { return el .children .filter(child => (0, parser_1.isElement)(child) && child.local === name); } function findDescendantsByLocalName(el, name) { const ret = []; _findDescendantsByLocalName(el, name, ret); return ret; } function _findDescendantsByLocalName(el, name, ret) { for (const child of el.children) { if (!(0, parser_1.isElement)(child)) { continue; } if (child.local === name) { ret.push(child); } _findDescendantsByLocalName(child, name, ret); } } function findMultiDescendantsByLocalName(el, names) { const ret = Object.create(null); for (const name of names) { ret[name] = []; } _findMultiDescendantsByLocalName(el, names, ret); return ret; } function _findMultiDescendantsByLocalName(el, names, ret) { for (const child of el.children) { if (!(0, parser_1.isElement)(child)) { continue; } const name = child.local; if (names.includes(name)) { ret[name].push(child); } _findMultiDescendantsByLocalName(child, names, ret); } } /** * This is a specialized version of [[findMultiDescendantsByLocalName]] that * searches through the first child element and its descendants. ``element`` and * ``attribute`` elements during simplification get their name class recorded as * their first child element. * * @param el The element in which to search. * * @param names The name class elements to look for. * * @returns A map of name to element list. */ function findMultiNames(el, names) { const nameClass = el.children[0]; const descendants = findMultiDescendantsByLocalName(nameClass, names); const name = nameClass.local; if (names.includes(name)) { if (!(name in descendants)) { descendants[name] = [nameClass]; } else { descendants[name].unshift(nameClass); } } return descendants; } /** * Index the elements of ``arr`` by the keys obtained through calling * ``makeKey``. If two elements resolve to the same key, the later element * overwrites the earlier. * * @param arr The array to index. * * @param makeKey A function that takes an array element and makes a key by * which this element will be indexed. * * @return The indexed elements. */ function indexBy(arr, makeKey) { const ret = new Map(); for (const x of arr) { ret.set(makeKey(x), x); } return ret; } /** * Group the elements of ``arr`` by the keys obtained through calling * ``makeKey``. Contrarily to [[indexBy]], this function allows for multiple * elements with the same key to coexist in the results because the resulting * object maps keys to arrays of elements rather than keys to single elements. * * @param arr The array to index. * * @param makeKey A function that takes an array element and makes a key by * which this element will be indexed. * * @return The grouped elements. */ function groupBy(arr, makeKey) { const ret = new Map(); for (const x of arr) { const key = makeKey(x); let list = ret.get(key); if (list === undefined) { list = []; ret.set(key, list); } list.push(x); } return ret; } /** * Get the value of the @name attribute. * * @param el The element to process. */ function getName(el) { return el.mustGetAttribute("name"); } /** * Removes unreferenced ``define`` elements from a grammar. * * **Important**: this is a very ad-hoc function, not meant for general * consumption. For one thing, this function works only if called with ``el`` * pointing to a top-level ``grammar`` element **after** all ``grammar`` * elements have been reduced to a single ``grammar``, all ``define`` elements * moved to that single ``grammar``, and ``grammar`` contains ``start`` as the * first element, and the rest of the children are all ``define`` elements. * * This function does no check these constraints!!! You must call it from a * stage where these constraints hold. * * This function does not guard against misuse. It must be called from steps * that execute after the above assumption holds. * * @param el The element that contains the ``define`` elements. * * @param seen A set of ``define`` names. If the name is in the set, then there * was a reference to the name, and the ``define`` is kept. Otherwise, the * ``define`` is removed. */ function removeUnreferencedDefs(el, seen) { const children = el.children; for (let ix = 1; ix < children.length; ++ix) { if (seen.has(children[ix].mustGetAttribute("name"))) { continue; } el.removeChildAt(ix); --ix; } } //# sourceMappingURL=util.js.map