UNPKG

3.67 kBJavaScriptView Raw
1/*
2 Copyright 2012-2015, Yahoo Inc.
3 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
4 */
5"use strict";
6
7var path = require('path'),
8 parsePath = path.parse,
9 SEP = path.sep || /* istanbul ignore next */ '/',
10 origParser = parsePath,
11 origSep = SEP;
12
13function makeRelativeNormalizedPath(str, sep) {
14 var parsed = parsePath(str),
15 root = parsed.root,
16 dir,
17 file = parsed.base,
18 quoted,
19 pos;
20
21 // handle a weird windows case separately
22 if (sep === '\\') {
23 pos = root.indexOf(':\\');
24 if (pos >= 0) {
25 root = root.substring(0, pos + 2);
26 }
27 }
28 dir = parsed.dir.substring(root.length);
29
30 if (str === '') {
31 return [];
32 }
33
34 if (sep !== '/') {
35 quoted = new RegExp(sep.replace(/\W/g, '\\$&'), 'g');
36 dir = dir.replace(quoted, '/');
37 file = file.replace(quoted, '/'); // excessively paranoid?
38 }
39
40 if (dir !== '') {
41 dir = dir + '/' + file;
42 } else {
43 dir = file;
44 }
45 if (dir.substring(0,1) === '/') {
46 dir = dir.substring(1);
47 }
48 dir = dir.split(/\/+/);
49 return dir;
50}
51
52function Path(strOrArray) {
53 if (Array.isArray(strOrArray)) {
54 this.v = strOrArray;
55 } else if (typeof strOrArray === "string") {
56 this.v = makeRelativeNormalizedPath(strOrArray, SEP);
57 } else {
58 throw new Error('Invalid Path argument must be string or array:' + strOrArray);
59 }
60}
61
62Path.prototype.toString = function () {
63 return this.v.join('/');
64};
65
66Path.prototype.hasParent = function () {
67 return this.v.length > 0;
68};
69
70Path.prototype.parent = function () {
71 if (!this.hasParent()) {
72 throw new Error('Unable to get parent for 0 elem path');
73 }
74 var p = this.v.slice();
75 p.pop();
76 return new Path(p);
77};
78
79Path.prototype.elements = function () {
80 return this.v.slice();
81};
82
83Path.prototype.contains = function (other) {
84 var i;
85 if (other.length > this.length) {
86 return false;
87 }
88 for (i = 0; i < other.length; i += 1) {
89 if (this.v[i] !== other.v[i]) {
90 return false;
91 }
92 }
93 return true;
94};
95
96Path.prototype.ancestorOf = function (other) {
97 return other.contains(this) && other.length !== this.length;
98};
99
100Path.prototype.descendantOf = function (other) {
101 return this.contains(other) && other.length !== this.length;
102};
103
104Path.prototype.commonPrefixPath = function (other) {
105 var len = this.length > other.length ? other.length : this.length,
106 i,
107 ret = [];
108
109 for (i = 0; i < len; i +=1 ) {
110 if (this.v[i] === other.v[i]) {
111 ret.push(this.v[i]);
112 } else {
113 break;
114 }
115 }
116 return new Path(ret);
117};
118
119['push', 'pop', 'shift', 'unshift', 'splice'].forEach(function (f) {
120 Path.prototype[f] = function () {
121 var args = Array.prototype.slice.call(arguments),
122 v = this.v;
123 return v[f].apply(v, args);
124 };
125});
126
127Path.compare = function (a, b) {
128 var al = a.length,
129 bl = b.length,
130 astr,
131 bstr;
132 if (al < bl) {
133 return -1;
134 }
135 if (al > bl) {
136 return 1;
137 }
138 astr = a.toString();
139 bstr = b.toString();
140 return astr < bstr ? -1 : astr > bstr ? 1 : 0;
141};
142
143Object.defineProperty(Path.prototype, 'length', {
144 enumerable: true,
145 get: function () {
146 return this.v.length;
147 }
148});
149
150module.exports = Path;
151Path.tester = {
152 setParserAndSep: function (p, sep) {
153 parsePath = p;
154 SEP = sep;
155 },
156 reset: function () {
157 parsePath = origParser;
158 SEP = origSep;
159 }
160};
161