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.

116 lines 4.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.step17 = step17; /** * Simplification step 17. * @author Louis-Dominique Dubeau * @license MPL 2.0 * @copyright 2013, 2014 Mangalam Research Center for Buddhist Languages */ const parser_1 = require("../parser"); const util_1 = require("./util"); // These are elements that cannot contain notAllowed and cannot contain // references. const skip = new Set(["name", "anyName", "nsName", "param", "empty", "text", "value", "notAllowed", "ref"]); function walk(el, ix, refs) { const { local, children } = el; // Skip those elements that are empty or that cannot contain notAllowed. if (children.length === 0 || skip.has(local)) { return; } // Since we walk the children first, all the transformations that pertain to // the children are applied before we deal with the parent, and there should // not be any need to process the tree multiple times. // At this stage of processing, most elements contain at most two // children. And due to the skip.has(local) test above, these children must be // Element objects. (<grammar> is the exception.) let [first, second] = children; walk(first, 0, refs); if (second !== undefined) { walk(second, 1, refs); } // Elements may be removed by the above walks. if (children.length === 0) { return; } // Reacquire. ([first, second] = children); const firstNA = first.local === "notAllowed"; const secondNA = second !== undefined && second.local === "notAllowed"; if (firstNA || secondNA) { // tslint:disable-next-line:no-non-null-assertion const parent = el.parent; // We used to have a map from which we'd get a handler to call but that // method is not faster than this switch. switch (local) { case "choice": if (firstNA && secondNA) { // A choice with two notAllowed is replaced with notAllowed. parent.replaceChildAt(ix, parser_1.Element.makeElement("notAllowed", [])); } else { // A choice with exactly one notAllowed is replaced with the other // child of the choice. parent.replaceChildAt(ix, firstNA ? second : first); } return; case "group": case "oneOrMore": case "interleave": case "attribute": case "list": // An attribute (or list, group, interleave, oneOrMore) with at least // one notAllowed is replaced with notAllowed. parent.replaceChildAt(ix, parser_1.Element.makeElement("notAllowed", [])); return; case "except": // An except with notAllowed is removed. parent.removeChildAt(ix); return; default: } } if (first.local === "ref") { refs.add(first.mustGetAttribute("name")); } if (second !== undefined && second.local === "ref") { refs.add(second.mustGetAttribute("name")); } } /** * Implements step 17 of the XSL pipeline. Namely: * * - All ``attribute``, ``list``, ``group``, ``interleave``, and ``oneOrMore`` * elements having a ``notAllowed`` child are replaced with a ``notAllowed`` * element. * * - A ``choice`` element with two ``notAllowed`` children is replaced with a * ``notAllowed`` element. * * - A ``choice`` element with a single ``notAllowed`` child is replaced with * the other child. * * - An ``except`` element with a ``notAllowed`` child is removed. * * These transformations are repeated until they no longer modify the tree. (The * way we apply the transformations obviates the need to repeat them.) * * Any ``define`` element that becomes unreachable after transformation is * removed. * * @param tree The tree to process. It is modified in-place. * * @returns The new root of the tree. */ function step17(tree) { const refs = new Set(); // The top element is necessarily <grammar>, and it has only element children. let ix = 0; for (const child of tree.children) { walk(child, ix++, refs); } (0, util_1.removeUnreferencedDefs)(tree, refs); return tree; } //# sourceMappingURL=step17.js.map