Skip to content
Permalink
1cdde3eb41
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
0 contributors

Users who have contributed to this file

169 lines (145 sloc) 3.62 KB
/*
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;
}
};