├── .gitignore ├── LICENSE ├── README.md ├── package.json └── path.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 | Permission is hereby granted, free of charge, to any person obtaining a copy 3 | of this software and associated documentation files (the "Software"), to 4 | deal in the Software without restriction, including without limitation the 5 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 6 | sell copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in 10 | all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 18 | IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # path 2 | 3 | This is an exact copy of the NodeJS ’path’ module published to the NPM registry. 4 | 5 | [Documentation](http://nodejs.org/docs/latest/api/path.html) 6 | 7 | ## Install 8 | 9 | ```sh 10 | $ npm install --save path 11 | ``` 12 | 13 | ## License 14 | 15 | MIT 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Joyent", 4 | "url": "http://www.joyent.com" 5 | }, 6 | "name": "path", 7 | "description": "Node.JS path module", 8 | "keywords": [ 9 | "ender", 10 | "path" 11 | ], 12 | "license": "MIT", 13 | "version": "0.12.7", 14 | "homepage": "http://nodejs.org/docs/latest/api/path.html", 15 | "repository": { 16 | "type": "git", 17 | "url": "git://github.com/jinder/path.git" 18 | }, 19 | "main": "./path.js", 20 | "dependencies": { 21 | "process": "^0.11.1", 22 | "util": "^0.10.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /path.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 'use strict'; 23 | 24 | 25 | var isWindows = process.platform === 'win32'; 26 | var util = require('util'); 27 | 28 | 29 | // resolves . and .. elements in a path array with directory names there 30 | // must be no slashes or device names (c:\) in the array 31 | // (so also no leading and trailing slashes - it does not distinguish 32 | // relative and absolute paths) 33 | function normalizeArray(parts, allowAboveRoot) { 34 | var res = []; 35 | for (var i = 0; i < parts.length; i++) { 36 | var p = parts[i]; 37 | 38 | // ignore empty parts 39 | if (!p || p === '.') 40 | continue; 41 | 42 | if (p === '..') { 43 | if (res.length && res[res.length - 1] !== '..') { 44 | res.pop(); 45 | } else if (allowAboveRoot) { 46 | res.push('..'); 47 | } 48 | } else { 49 | res.push(p); 50 | } 51 | } 52 | 53 | return res; 54 | } 55 | 56 | // returns an array with empty elements removed from either end of the input 57 | // array or the original array if no elements need to be removed 58 | function trimArray(arr) { 59 | var lastIndex = arr.length - 1; 60 | var start = 0; 61 | for (; start <= lastIndex; start++) { 62 | if (arr[start]) 63 | break; 64 | } 65 | 66 | var end = lastIndex; 67 | for (; end >= 0; end--) { 68 | if (arr[end]) 69 | break; 70 | } 71 | 72 | if (start === 0 && end === lastIndex) 73 | return arr; 74 | if (start > end) 75 | return []; 76 | return arr.slice(start, end + 1); 77 | } 78 | 79 | // Regex to split a windows path into three parts: [*, device, slash, 80 | // tail] windows-only 81 | var splitDeviceRe = 82 | /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; 83 | 84 | // Regex to split the tail part of the above into [*, dir, basename, ext] 85 | var splitTailRe = 86 | /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; 87 | 88 | var win32 = {}; 89 | 90 | // Function to split a filename into [root, dir, basename, ext] 91 | function win32SplitPath(filename) { 92 | // Separate device+slash from tail 93 | var result = splitDeviceRe.exec(filename), 94 | device = (result[1] || '') + (result[2] || ''), 95 | tail = result[3] || ''; 96 | // Split the tail into dir, basename and extension 97 | var result2 = splitTailRe.exec(tail), 98 | dir = result2[1], 99 | basename = result2[2], 100 | ext = result2[3]; 101 | return [device, dir, basename, ext]; 102 | } 103 | 104 | function win32StatPath(path) { 105 | var result = splitDeviceRe.exec(path), 106 | device = result[1] || '', 107 | isUnc = !!device && device[1] !== ':'; 108 | return { 109 | device: device, 110 | isUnc: isUnc, 111 | isAbsolute: isUnc || !!result[2], // UNC paths are always absolute 112 | tail: result[3] 113 | }; 114 | } 115 | 116 | function normalizeUNCRoot(device) { 117 | return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\'); 118 | } 119 | 120 | // path.resolve([from ...], to) 121 | win32.resolve = function() { 122 | var resolvedDevice = '', 123 | resolvedTail = '', 124 | resolvedAbsolute = false; 125 | 126 | for (var i = arguments.length - 1; i >= -1; i--) { 127 | var path; 128 | if (i >= 0) { 129 | path = arguments[i]; 130 | } else if (!resolvedDevice) { 131 | path = process.cwd(); 132 | } else { 133 | // Windows has the concept of drive-specific current working 134 | // directories. If we've resolved a drive letter but not yet an 135 | // absolute path, get cwd for that drive. We're sure the device is not 136 | // an unc path at this points, because unc paths are always absolute. 137 | path = process.env['=' + resolvedDevice]; 138 | // Verify that a drive-local cwd was found and that it actually points 139 | // to our drive. If not, default to the drive's root. 140 | if (!path || path.substr(0, 3).toLowerCase() !== 141 | resolvedDevice.toLowerCase() + '\\') { 142 | path = resolvedDevice + '\\'; 143 | } 144 | } 145 | 146 | // Skip empty and invalid entries 147 | if (!util.isString(path)) { 148 | throw new TypeError('Arguments to path.resolve must be strings'); 149 | } else if (!path) { 150 | continue; 151 | } 152 | 153 | var result = win32StatPath(path), 154 | device = result.device, 155 | isUnc = result.isUnc, 156 | isAbsolute = result.isAbsolute, 157 | tail = result.tail; 158 | 159 | if (device && 160 | resolvedDevice && 161 | device.toLowerCase() !== resolvedDevice.toLowerCase()) { 162 | // This path points to another device so it is not applicable 163 | continue; 164 | } 165 | 166 | if (!resolvedDevice) { 167 | resolvedDevice = device; 168 | } 169 | if (!resolvedAbsolute) { 170 | resolvedTail = tail + '\\' + resolvedTail; 171 | resolvedAbsolute = isAbsolute; 172 | } 173 | 174 | if (resolvedDevice && resolvedAbsolute) { 175 | break; 176 | } 177 | } 178 | 179 | // Convert slashes to backslashes when `resolvedDevice` points to an UNC 180 | // root. Also squash multiple slashes into a single one where appropriate. 181 | if (isUnc) { 182 | resolvedDevice = normalizeUNCRoot(resolvedDevice); 183 | } 184 | 185 | // At this point the path should be resolved to a full absolute path, 186 | // but handle relative paths to be safe (might happen when process.cwd() 187 | // fails) 188 | 189 | // Normalize the tail path 190 | resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/), 191 | !resolvedAbsolute).join('\\'); 192 | 193 | return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || 194 | '.'; 195 | }; 196 | 197 | 198 | win32.normalize = function(path) { 199 | var result = win32StatPath(path), 200 | device = result.device, 201 | isUnc = result.isUnc, 202 | isAbsolute = result.isAbsolute, 203 | tail = result.tail, 204 | trailingSlash = /[\\\/]$/.test(tail); 205 | 206 | // Normalize the tail path 207 | tail = normalizeArray(tail.split(/[\\\/]+/), !isAbsolute).join('\\'); 208 | 209 | if (!tail && !isAbsolute) { 210 | tail = '.'; 211 | } 212 | if (tail && trailingSlash) { 213 | tail += '\\'; 214 | } 215 | 216 | // Convert slashes to backslashes when `device` points to an UNC root. 217 | // Also squash multiple slashes into a single one where appropriate. 218 | if (isUnc) { 219 | device = normalizeUNCRoot(device); 220 | } 221 | 222 | return device + (isAbsolute ? '\\' : '') + tail; 223 | }; 224 | 225 | 226 | win32.isAbsolute = function(path) { 227 | return win32StatPath(path).isAbsolute; 228 | }; 229 | 230 | win32.join = function() { 231 | var paths = []; 232 | for (var i = 0; i < arguments.length; i++) { 233 | var arg = arguments[i]; 234 | if (!util.isString(arg)) { 235 | throw new TypeError('Arguments to path.join must be strings'); 236 | } 237 | if (arg) { 238 | paths.push(arg); 239 | } 240 | } 241 | 242 | var joined = paths.join('\\'); 243 | 244 | // Make sure that the joined path doesn't start with two slashes, because 245 | // normalize() will mistake it for an UNC path then. 246 | // 247 | // This step is skipped when it is very clear that the user actually 248 | // intended to point at an UNC path. This is assumed when the first 249 | // non-empty string arguments starts with exactly two slashes followed by 250 | // at least one more non-slash character. 251 | // 252 | // Note that for normalize() to treat a path as an UNC path it needs to 253 | // have at least 2 components, so we don't filter for that here. 254 | // This means that the user can use join to construct UNC paths from 255 | // a server name and a share name; for example: 256 | // path.join('//server', 'share') -> '\\\\server\\share\') 257 | if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) { 258 | joined = joined.replace(/^[\\\/]{2,}/, '\\'); 259 | } 260 | 261 | return win32.normalize(joined); 262 | }; 263 | 264 | 265 | // path.relative(from, to) 266 | // it will solve the relative path from 'from' to 'to', for instance: 267 | // from = 'C:\\orandea\\test\\aaa' 268 | // to = 'C:\\orandea\\impl\\bbb' 269 | // The output of the function should be: '..\\..\\impl\\bbb' 270 | win32.relative = function(from, to) { 271 | from = win32.resolve(from); 272 | to = win32.resolve(to); 273 | 274 | // windows is not case sensitive 275 | var lowerFrom = from.toLowerCase(); 276 | var lowerTo = to.toLowerCase(); 277 | 278 | var toParts = trimArray(to.split('\\')); 279 | 280 | var lowerFromParts = trimArray(lowerFrom.split('\\')); 281 | var lowerToParts = trimArray(lowerTo.split('\\')); 282 | 283 | var length = Math.min(lowerFromParts.length, lowerToParts.length); 284 | var samePartsLength = length; 285 | for (var i = 0; i < length; i++) { 286 | if (lowerFromParts[i] !== lowerToParts[i]) { 287 | samePartsLength = i; 288 | break; 289 | } 290 | } 291 | 292 | if (samePartsLength == 0) { 293 | return to; 294 | } 295 | 296 | var outputParts = []; 297 | for (var i = samePartsLength; i < lowerFromParts.length; i++) { 298 | outputParts.push('..'); 299 | } 300 | 301 | outputParts = outputParts.concat(toParts.slice(samePartsLength)); 302 | 303 | return outputParts.join('\\'); 304 | }; 305 | 306 | 307 | win32._makeLong = function(path) { 308 | // Note: this will *probably* throw somewhere. 309 | if (!util.isString(path)) 310 | return path; 311 | 312 | if (!path) { 313 | return ''; 314 | } 315 | 316 | var resolvedPath = win32.resolve(path); 317 | 318 | if (/^[a-zA-Z]\:\\/.test(resolvedPath)) { 319 | // path is local filesystem path, which needs to be converted 320 | // to long UNC path. 321 | return '\\\\?\\' + resolvedPath; 322 | } else if (/^\\\\[^?.]/.test(resolvedPath)) { 323 | // path is network UNC path, which needs to be converted 324 | // to long UNC path. 325 | return '\\\\?\\UNC\\' + resolvedPath.substring(2); 326 | } 327 | 328 | return path; 329 | }; 330 | 331 | 332 | win32.dirname = function(path) { 333 | var result = win32SplitPath(path), 334 | root = result[0], 335 | dir = result[1]; 336 | 337 | if (!root && !dir) { 338 | // No dirname whatsoever 339 | return '.'; 340 | } 341 | 342 | if (dir) { 343 | // It has a dirname, strip trailing slash 344 | dir = dir.substr(0, dir.length - 1); 345 | } 346 | 347 | return root + dir; 348 | }; 349 | 350 | 351 | win32.basename = function(path, ext) { 352 | var f = win32SplitPath(path)[2]; 353 | // TODO: make this comparison case-insensitive on windows? 354 | if (ext && f.substr(-1 * ext.length) === ext) { 355 | f = f.substr(0, f.length - ext.length); 356 | } 357 | return f; 358 | }; 359 | 360 | 361 | win32.extname = function(path) { 362 | return win32SplitPath(path)[3]; 363 | }; 364 | 365 | 366 | win32.format = function(pathObject) { 367 | if (!util.isObject(pathObject)) { 368 | throw new TypeError( 369 | "Parameter 'pathObject' must be an object, not " + typeof pathObject 370 | ); 371 | } 372 | 373 | var root = pathObject.root || ''; 374 | 375 | if (!util.isString(root)) { 376 | throw new TypeError( 377 | "'pathObject.root' must be a string or undefined, not " + 378 | typeof pathObject.root 379 | ); 380 | } 381 | 382 | var dir = pathObject.dir; 383 | var base = pathObject.base || ''; 384 | if (!dir) { 385 | return base; 386 | } 387 | if (dir[dir.length - 1] === win32.sep) { 388 | return dir + base; 389 | } 390 | return dir + win32.sep + base; 391 | }; 392 | 393 | 394 | win32.parse = function(pathString) { 395 | if (!util.isString(pathString)) { 396 | throw new TypeError( 397 | "Parameter 'pathString' must be a string, not " + typeof pathString 398 | ); 399 | } 400 | var allParts = win32SplitPath(pathString); 401 | if (!allParts || allParts.length !== 4) { 402 | throw new TypeError("Invalid path '" + pathString + "'"); 403 | } 404 | return { 405 | root: allParts[0], 406 | dir: allParts[0] + allParts[1].slice(0, -1), 407 | base: allParts[2], 408 | ext: allParts[3], 409 | name: allParts[2].slice(0, allParts[2].length - allParts[3].length) 410 | }; 411 | }; 412 | 413 | 414 | win32.sep = '\\'; 415 | win32.delimiter = ';'; 416 | 417 | 418 | // Split a filename into [root, dir, basename, ext], unix version 419 | // 'root' is just a slash, or nothing. 420 | var splitPathRe = 421 | /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; 422 | var posix = {}; 423 | 424 | 425 | function posixSplitPath(filename) { 426 | return splitPathRe.exec(filename).slice(1); 427 | } 428 | 429 | 430 | // path.resolve([from ...], to) 431 | // posix version 432 | posix.resolve = function() { 433 | var resolvedPath = '', 434 | resolvedAbsolute = false; 435 | 436 | for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { 437 | var path = (i >= 0) ? arguments[i] : process.cwd(); 438 | 439 | // Skip empty and invalid entries 440 | if (!util.isString(path)) { 441 | throw new TypeError('Arguments to path.resolve must be strings'); 442 | } else if (!path) { 443 | continue; 444 | } 445 | 446 | resolvedPath = path + '/' + resolvedPath; 447 | resolvedAbsolute = path[0] === '/'; 448 | } 449 | 450 | // At this point the path should be resolved to a full absolute path, but 451 | // handle relative paths to be safe (might happen when process.cwd() fails) 452 | 453 | // Normalize the path 454 | resolvedPath = normalizeArray(resolvedPath.split('/'), 455 | !resolvedAbsolute).join('/'); 456 | 457 | return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; 458 | }; 459 | 460 | // path.normalize(path) 461 | // posix version 462 | posix.normalize = function(path) { 463 | var isAbsolute = posix.isAbsolute(path), 464 | trailingSlash = path && path[path.length - 1] === '/'; 465 | 466 | // Normalize the path 467 | path = normalizeArray(path.split('/'), !isAbsolute).join('/'); 468 | 469 | if (!path && !isAbsolute) { 470 | path = '.'; 471 | } 472 | if (path && trailingSlash) { 473 | path += '/'; 474 | } 475 | 476 | return (isAbsolute ? '/' : '') + path; 477 | }; 478 | 479 | // posix version 480 | posix.isAbsolute = function(path) { 481 | return path.charAt(0) === '/'; 482 | }; 483 | 484 | // posix version 485 | posix.join = function() { 486 | var path = ''; 487 | for (var i = 0; i < arguments.length; i++) { 488 | var segment = arguments[i]; 489 | if (!util.isString(segment)) { 490 | throw new TypeError('Arguments to path.join must be strings'); 491 | } 492 | if (segment) { 493 | if (!path) { 494 | path += segment; 495 | } else { 496 | path += '/' + segment; 497 | } 498 | } 499 | } 500 | return posix.normalize(path); 501 | }; 502 | 503 | 504 | // path.relative(from, to) 505 | // posix version 506 | posix.relative = function(from, to) { 507 | from = posix.resolve(from).substr(1); 508 | to = posix.resolve(to).substr(1); 509 | 510 | var fromParts = trimArray(from.split('/')); 511 | var toParts = trimArray(to.split('/')); 512 | 513 | var length = Math.min(fromParts.length, toParts.length); 514 | var samePartsLength = length; 515 | for (var i = 0; i < length; i++) { 516 | if (fromParts[i] !== toParts[i]) { 517 | samePartsLength = i; 518 | break; 519 | } 520 | } 521 | 522 | var outputParts = []; 523 | for (var i = samePartsLength; i < fromParts.length; i++) { 524 | outputParts.push('..'); 525 | } 526 | 527 | outputParts = outputParts.concat(toParts.slice(samePartsLength)); 528 | 529 | return outputParts.join('/'); 530 | }; 531 | 532 | 533 | posix._makeLong = function(path) { 534 | return path; 535 | }; 536 | 537 | 538 | posix.dirname = function(path) { 539 | var result = posixSplitPath(path), 540 | root = result[0], 541 | dir = result[1]; 542 | 543 | if (!root && !dir) { 544 | // No dirname whatsoever 545 | return '.'; 546 | } 547 | 548 | if (dir) { 549 | // It has a dirname, strip trailing slash 550 | dir = dir.substr(0, dir.length - 1); 551 | } 552 | 553 | return root + dir; 554 | }; 555 | 556 | 557 | posix.basename = function(path, ext) { 558 | var f = posixSplitPath(path)[2]; 559 | // TODO: make this comparison case-insensitive on windows? 560 | if (ext && f.substr(-1 * ext.length) === ext) { 561 | f = f.substr(0, f.length - ext.length); 562 | } 563 | return f; 564 | }; 565 | 566 | 567 | posix.extname = function(path) { 568 | return posixSplitPath(path)[3]; 569 | }; 570 | 571 | 572 | posix.format = function(pathObject) { 573 | if (!util.isObject(pathObject)) { 574 | throw new TypeError( 575 | "Parameter 'pathObject' must be an object, not " + typeof pathObject 576 | ); 577 | } 578 | 579 | var root = pathObject.root || ''; 580 | 581 | if (!util.isString(root)) { 582 | throw new TypeError( 583 | "'pathObject.root' must be a string or undefined, not " + 584 | typeof pathObject.root 585 | ); 586 | } 587 | 588 | var dir = pathObject.dir ? pathObject.dir + posix.sep : ''; 589 | var base = pathObject.base || ''; 590 | return dir + base; 591 | }; 592 | 593 | 594 | posix.parse = function(pathString) { 595 | if (!util.isString(pathString)) { 596 | throw new TypeError( 597 | "Parameter 'pathString' must be a string, not " + typeof pathString 598 | ); 599 | } 600 | var allParts = posixSplitPath(pathString); 601 | if (!allParts || allParts.length !== 4) { 602 | throw new TypeError("Invalid path '" + pathString + "'"); 603 | } 604 | allParts[1] = allParts[1] || ''; 605 | allParts[2] = allParts[2] || ''; 606 | allParts[3] = allParts[3] || ''; 607 | 608 | return { 609 | root: allParts[0], 610 | dir: allParts[0] + allParts[1].slice(0, -1), 611 | base: allParts[2], 612 | ext: allParts[3], 613 | name: allParts[2].slice(0, allParts[2].length - allParts[3].length) 614 | }; 615 | }; 616 | 617 | 618 | posix.sep = '/'; 619 | posix.delimiter = ':'; 620 | 621 | 622 | if (isWindows) 623 | module.exports = win32; 624 | else /* posix */ 625 | module.exports = posix; 626 | 627 | module.exports.posix = posix; 628 | module.exports.win32 = win32; 629 | --------------------------------------------------------------------------------