UNPKG

owltech

Version:
176 lines 6.34 kB
"use strict"; /* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ Object.defineProperty(exports, "__esModule", { value: true }); /* * Path template utility. */ const has = require("lodash.has"); const util = require("util"); const extras = require("./parserExtras"); const parser = require('./pathTemplateParser'); class PathTemplate { get size() { return this.parseResult.size; } get segments() { return this.parseResult.segments; } /** * @param {String} data the of the template * * @constructor */ constructor(data) { this.parseResult = extras.finishParse(parser.parse(data)); } /** * Matches a fully-qualified path template string. * * @param {String} path a fully-qualified path template string * @return {Object} contains const names matched to binding values * @throws {TypeError} if path can't be matched to this template */ match(path) { const pathSegments = path.split('/'); const bindings = {}; let segmentCount = this.size; let current; let index = 0; this.segments.forEach(segment => { if (index > pathSegments.length) { return; } if (segment.kind === extras.BINDING) { current = segment.literal; } else if (segment.kind === extras.TERMINAL) { if (segment.literal === '*') { bindings[current] = pathSegments[index]; index += 1; } else if (segment.literal === '**') { const size = pathSegments.length - segmentCount + 1; segmentCount += size - 1; bindings[current] = pathSegments.slice(index, index + size).join('/'); index += size; } else if (segment.literal === pathSegments[index]) { index += 1; } else { const msg = util.format('mismatched literal (index=%d): \'%s\' != \'%s\'', index, segment.literal, pathSegments[index]); throw new TypeError(msg); } } }); if (index !== pathSegments.length || index !== segmentCount) { const msg = util.format('match error: could not instantiate a path template from %s', path); throw new TypeError(msg); } return bindings; } /** * Renders a path template using the provided bindings. * * @param {Object} bindings a mapping of const names to binding strings * @return {String} a rendered representation of the path template * @throws {TypeError} if a key is missing, or if a sub-template cannot be * parsed */ render(bindings) { const out = []; let inABinding = false; this.segments.forEach(segment => { if (segment.kind === extras.BINDING) { if (!has(bindings, segment.literal)) { const msg = util.format('Value for key %s is not provided in %s', segment.literal, bindings); throw new TypeError(msg); } const tmp = new PathTemplate(bindings[segment.literal]); Array.prototype.push.apply(out, tmp.segments); inABinding = true; } else if (segment.kind === extras.END_BINDING) { inABinding = false; } else if (inABinding) { return; } else { out.push(segment); } }); const result = formatSegments(out); this.match(result); return result; } /** * Renders the path template. * * @return {string} contains const names matched to binding values */ inspect() { return formatSegments(this.segments); } } exports.PathTemplate = PathTemplate; /** * Creates the string representattion for the segments. * @param {Object[]} segments - The array of segments. * @return {string} - A string representing segments in the path template * format. */ function formatSegments(segments) { let out = ''; let slash = true; segments.forEach(segment => { if (segment.kind === extras.TERMINAL) { if (slash) { out += '/'; } out += segment.literal; return; } slash = true; if (segment.kind === extras.BINDING) { out += '/{' + segment.literal + '='; slash = false; } else { out += segment.literal + '}'; } }); return out.substring(1); } //# sourceMappingURL=pathTemplate.js.map