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(
59 'Invalid Path argument must be string or array:' + strOrArray
60 );
61 }
62}
63
64Path.prototype.toString = function() {
65 return this.v.join('/');
66};
67
68Path.prototype.hasParent = function() {
69 return this.v.length > 0;
70};
71
72Path.prototype.parent = function() {
73 if (!this.hasParent()) {
74 throw new Error('Unable to get parent for 0 elem path');
75 }
76 var p = this.v.slice();
77 p.pop();
78 return new Path(p);
79};
80
81Path.prototype.elements = function() {
82 return this.v.slice();
83};
84
85Path.prototype.contains = function(other) {
86 var i;
87 if (other.length > this.length) {
88 return false;
89 }
90 for (i = 0; i < other.length; i += 1) {
91 if (this.v[i] !== other.v[i]) {
92 return false;
93 }
94 }
95 return true;
96};
97
98Path.prototype.ancestorOf = function(other) {
99 return other.contains(this) && other.length !== this.length;
100};
101
102Path.prototype.descendantOf = function(other) {
103 return this.contains(other) && other.length !== this.length;
104};
105
106Path.prototype.commonPrefixPath = function(other) {
107 var len = this.length > other.length ? other.length : this.length,
108 i,
109 ret = [];
110
111 for (i = 0; i < len; i += 1) {
112 if (this.v[i] === other.v[i]) {
113 ret.push(this.v[i]);
114 } else {
115 break;
116 }
117 }
118 return new Path(ret);
119};
120
121['push', 'pop', 'shift', 'unshift', 'splice'].forEach(function(f) {
122 Path.prototype[f] = function() {
123 var args = Array.prototype.slice.call(arguments),
124 v = this.v;
125 return v[f].apply(v, args);
126 };
127});
128
129Path.compare = function(a, b) {
130 var al = a.length,
131 bl = b.length,
132 astr,
133 bstr;
134 if (al < bl) {
135 return -1;
136 }
137 if (al > bl) {
138 return 1;
139 }
140 astr = a.toString();
141 bstr = b.toString();
142 return astr < bstr ? -1 : astr > bstr ? 1 : 0;
143};
144
145Object.defineProperty(Path.prototype, 'length', {
146 enumerable: true,
147 get: function() {
148 return this.v.length;
149 }
150});
151
152module.exports = Path;
153Path.tester = {
154 setParserAndSep: function(p, sep) {
155 parsePath = p;
156 SEP = sep;
157 },
158 reset: function() {
159 parsePath = origParser;
160 SEP = origSep;
161 }
162};