123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /*
- Copyright 2012-2015, Yahoo Inc.
- Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
- */
- 'use strict';
- const path = require('path');
- let parsePath = path.parse;
- let SEP = path.sep;
- const origParser = parsePath;
- const origSep = SEP;
- function makeRelativeNormalizedPath(str, sep) {
- const parsed = parsePath(str);
- let root = parsed.root;
- let dir;
- let file = parsed.base;
- let quoted;
- let pos;
- // handle a weird windows case separately
- if (sep === '\\') {
- pos = root.indexOf(':\\');
- if (pos >= 0) {
- root = root.substring(0, pos + 2);
- }
- }
- dir = parsed.dir.substring(root.length);
- if (str === '') {
- return [];
- }
- if (sep !== '/') {
- quoted = new RegExp(sep.replace(/\W/g, '\\$&'), 'g');
- dir = dir.replace(quoted, '/');
- file = file.replace(quoted, '/'); // excessively paranoid?
- }
- if (dir !== '') {
- dir = `${dir}/${file}`;
- } else {
- dir = file;
- }
- if (dir.substring(0, 1) === '/') {
- dir = dir.substring(1);
- }
- dir = dir.split(/\/+/);
- return dir;
- }
- class Path {
- constructor(strOrArray) {
- if (Array.isArray(strOrArray)) {
- this.v = strOrArray;
- } else if (typeof strOrArray === 'string') {
- this.v = makeRelativeNormalizedPath(strOrArray, SEP);
- } else {
- throw new Error(
- `Invalid Path argument must be string or array:${strOrArray}`
- );
- }
- }
- toString() {
- return this.v.join('/');
- }
- hasParent() {
- return this.v.length > 0;
- }
- parent() {
- if (!this.hasParent()) {
- throw new Error('Unable to get parent for 0 elem path');
- }
- const p = this.v.slice();
- p.pop();
- return new Path(p);
- }
- elements() {
- return this.v.slice();
- }
- name() {
- return this.v.slice(-1)[0];
- }
- contains(other) {
- let i;
- if (other.length > this.length) {
- return false;
- }
- for (i = 0; i < other.length; i += 1) {
- if (this.v[i] !== other.v[i]) {
- return false;
- }
- }
- return true;
- }
- ancestorOf(other) {
- return other.contains(this) && other.length !== this.length;
- }
- descendantOf(other) {
- return this.contains(other) && other.length !== this.length;
- }
- commonPrefixPath(other) {
- const len = this.length > other.length ? other.length : this.length;
- let i;
- const ret = [];
- for (i = 0; i < len; i += 1) {
- if (this.v[i] === other.v[i]) {
- ret.push(this.v[i]);
- } else {
- break;
- }
- }
- return new Path(ret);
- }
- static compare(a, b) {
- const al = a.length;
- const bl = b.length;
- if (al < bl) {
- return -1;
- }
- if (al > bl) {
- return 1;
- }
- const astr = a.toString();
- const bstr = b.toString();
- return astr < bstr ? -1 : astr > bstr ? 1 : 0;
- }
- }
- ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(fn => {
- Object.defineProperty(Path.prototype, fn, {
- value(...args) {
- return this.v[fn](...args);
- }
- });
- });
- Object.defineProperty(Path.prototype, 'length', {
- enumerable: true,
- get() {
- return this.v.length;
- }
- });
- module.exports = Path;
- Path.tester = {
- setParserAndSep(p, sep) {
- parsePath = p;
- SEP = sep;
- },
- reset() {
- parsePath = origParser;
- SEP = origSep;
- }
- };
|