Projekt

Obecné

Profil

Stáhnout (8.54 KB) Statistiky
| Větev: | Revize:
1
// .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1,
2
// backported and transplited with Babel, with backwards-compat fixes
3

    
4
// Copyright Joyent, Inc. and other Node contributors.
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining a
7
// copy of this software and associated documentation files (the
8
// "Software"), to deal in the Software without restriction, including
9
// without limitation the rights to use, copy, modify, merge, publish,
10
// distribute, sublicense, and/or sell copies of the Software, and to permit
11
// persons to whom the Software is furnished to do so, subject to the
12
// following conditions:
13
//
14
// The above copyright notice and this permission notice shall be included
15
// in all copies or substantial portions of the Software.
16
//
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23
// USE OR OTHER DEALINGS IN THE SOFTWARE.
24

    
25
// resolves . and .. elements in a path array with directory names there
26
// must be no slashes, empty elements, or device names (c:\) in the array
27
// (so also no leading and trailing slashes - it does not distinguish
28
// relative and absolute paths)
29
function normalizeArray(parts, allowAboveRoot) {
30
  // if the path tries to go above the root, `up` ends up > 0
31
  var up = 0;
32
  for (var i = parts.length - 1; i >= 0; i--) {
33
    var last = parts[i];
34
    if (last === '.') {
35
      parts.splice(i, 1);
36
    } else if (last === '..') {
37
      parts.splice(i, 1);
38
      up++;
39
    } else if (up) {
40
      parts.splice(i, 1);
41
      up--;
42
    }
43
  }
44

    
45
  // if the path is allowed to go above the root, restore leading ..s
46
  if (allowAboveRoot) {
47
    for (; up--; up) {
48
      parts.unshift('..');
49
    }
50
  }
51

    
52
  return parts;
53
}
54

    
55
// path.resolve([from ...], to)
56
// posix version
57
exports.resolve = function() {
58
  var resolvedPath = '',
59
      resolvedAbsolute = false;
60

    
61
  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
62
    var path = (i >= 0) ? arguments[i] : process.cwd();
63

    
64
    // Skip empty and invalid entries
65
    if (typeof path !== 'string') {
66
      throw new TypeError('Arguments to path.resolve must be strings');
67
    } else if (!path) {
68
      continue;
69
    }
70

    
71
    resolvedPath = path + '/' + resolvedPath;
72
    resolvedAbsolute = path.charAt(0) === '/';
73
  }
74

    
75
  // At this point the path should be resolved to a full absolute path, but
76
  // handle relative paths to be safe (might happen when process.cwd() fails)
77

    
78
  // Normalize the path
79
  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
80
    return !!p;
81
  }), !resolvedAbsolute).join('/');
82

    
83
  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
84
};
85

    
86
// path.normalize(path)
87
// posix version
88
exports.normalize = function(path) {
89
  var isAbsolute = exports.isAbsolute(path),
90
      trailingSlash = substr(path, -1) === '/';
91

    
92
  // Normalize the path
93
  path = normalizeArray(filter(path.split('/'), function(p) {
94
    return !!p;
95
  }), !isAbsolute).join('/');
96

    
97
  if (!path && !isAbsolute) {
98
    path = '.';
99
  }
100
  if (path && trailingSlash) {
101
    path += '/';
102
  }
103

    
104
  return (isAbsolute ? '/' : '') + path;
105
};
106

    
107
// posix version
108
exports.isAbsolute = function(path) {
109
  return path.charAt(0) === '/';
110
};
111

    
112
// posix version
113
exports.join = function() {
114
  var paths = Array.prototype.slice.call(arguments, 0);
115
  return exports.normalize(filter(paths, function(p, index) {
116
    if (typeof p !== 'string') {
117
      throw new TypeError('Arguments to path.join must be strings');
118
    }
119
    return p;
120
  }).join('/'));
121
};
122

    
123

    
124
// path.relative(from, to)
125
// posix version
126
exports.relative = function(from, to) {
127
  from = exports.resolve(from).substr(1);
128
  to = exports.resolve(to).substr(1);
129

    
130
  function trim(arr) {
131
    var start = 0;
132
    for (; start < arr.length; start++) {
133
      if (arr[start] !== '') break;
134
    }
135

    
136
    var end = arr.length - 1;
137
    for (; end >= 0; end--) {
138
      if (arr[end] !== '') break;
139
    }
140

    
141
    if (start > end) return [];
142
    return arr.slice(start, end - start + 1);
143
  }
144

    
145
  var fromParts = trim(from.split('/'));
146
  var toParts = trim(to.split('/'));
147

    
148
  var length = Math.min(fromParts.length, toParts.length);
149
  var samePartsLength = length;
150
  for (var i = 0; i < length; i++) {
151
    if (fromParts[i] !== toParts[i]) {
152
      samePartsLength = i;
153
      break;
154
    }
155
  }
156

    
157
  var outputParts = [];
158
  for (var i = samePartsLength; i < fromParts.length; i++) {
159
    outputParts.push('..');
160
  }
161

    
162
  outputParts = outputParts.concat(toParts.slice(samePartsLength));
163

    
164
  return outputParts.join('/');
165
};
166

    
167
exports.sep = '/';
168
exports.delimiter = ':';
169

    
170
exports.dirname = function (path) {
171
  if (typeof path !== 'string') path = path + '';
172
  if (path.length === 0) return '.';
173
  var code = path.charCodeAt(0);
174
  var hasRoot = code === 47 /*/*/;
175
  var end = -1;
176
  var matchedSlash = true;
177
  for (var i = path.length - 1; i >= 1; --i) {
178
    code = path.charCodeAt(i);
179
    if (code === 47 /*/*/) {
180
        if (!matchedSlash) {
181
          end = i;
182
          break;
183
        }
184
      } else {
185
      // We saw the first non-path separator
186
      matchedSlash = false;
187
    }
188
  }
189

    
190
  if (end === -1) return hasRoot ? '/' : '.';
191
  if (hasRoot && end === 1) {
192
    // return '//';
193
    // Backwards-compat fix:
194
    return '/';
195
  }
196
  return path.slice(0, end);
197
};
198

    
199
function basename(path) {
200
  if (typeof path !== 'string') path = path + '';
201

    
202
  var start = 0;
203
  var end = -1;
204
  var matchedSlash = true;
205
  var i;
206

    
207
  for (i = path.length - 1; i >= 0; --i) {
208
    if (path.charCodeAt(i) === 47 /*/*/) {
209
        // If we reached a path separator that was not part of a set of path
210
        // separators at the end of the string, stop now
211
        if (!matchedSlash) {
212
          start = i + 1;
213
          break;
214
        }
215
      } else if (end === -1) {
216
      // We saw the first non-path separator, mark this as the end of our
217
      // path component
218
      matchedSlash = false;
219
      end = i + 1;
220
    }
221
  }
222

    
223
  if (end === -1) return '';
224
  return path.slice(start, end);
225
}
226

    
227
// Uses a mixed approach for backwards-compatibility, as ext behavior changed
228
// in new Node.js versions, so only basename() above is backported here
229
exports.basename = function (path, ext) {
230
  var f = basename(path);
231
  if (ext && f.substr(-1 * ext.length) === ext) {
232
    f = f.substr(0, f.length - ext.length);
233
  }
234
  return f;
235
};
236

    
237
exports.extname = function (path) {
238
  if (typeof path !== 'string') path = path + '';
239
  var startDot = -1;
240
  var startPart = 0;
241
  var end = -1;
242
  var matchedSlash = true;
243
  // Track the state of characters (if any) we see before our first dot and
244
  // after any path separator we find
245
  var preDotState = 0;
246
  for (var i = path.length - 1; i >= 0; --i) {
247
    var code = path.charCodeAt(i);
248
    if (code === 47 /*/*/) {
249
        // If we reached a path separator that was not part of a set of path
250
        // separators at the end of the string, stop now
251
        if (!matchedSlash) {
252
          startPart = i + 1;
253
          break;
254
        }
255
        continue;
256
      }
257
    if (end === -1) {
258
      // We saw the first non-path separator, mark this as the end of our
259
      // extension
260
      matchedSlash = false;
261
      end = i + 1;
262
    }
263
    if (code === 46 /*.*/) {
264
        // If this is our first dot, mark it as the start of our extension
265
        if (startDot === -1)
266
          startDot = i;
267
        else if (preDotState !== 1)
268
          preDotState = 1;
269
    } else if (startDot !== -1) {
270
      // We saw a non-dot and non-path separator before our dot, so we should
271
      // have a good chance at having a non-empty extension
272
      preDotState = -1;
273
    }
274
  }
275

    
276
  if (startDot === -1 || end === -1 ||
277
      // We saw a non-dot character immediately before the dot
278
      preDotState === 0 ||
279
      // The (right-most) trimmed path component is exactly '..'
280
      preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
281
    return '';
282
  }
283
  return path.slice(startDot, end);
284
};
285

    
286
function filter (xs, f) {
287
    if (xs.filter) return xs.filter(f);
288
    var res = [];
289
    for (var i = 0; i < xs.length; i++) {
290
        if (f(xs[i], i, xs)) res.push(xs[i]);
291
    }
292
    return res;
293
}
294

    
295
// String.prototype.substr - negative index don't work in IE8
296
var substr = 'ab'.substr(-1) === 'b'
297
    ? function (str, start, len) { return str.substr(start, len) }
298
    : function (str, start, len) {
299
        if (start < 0) start = str.length + start;
300
        return str.substr(start, len);
301
    }
302
;
(2-2/4)