react / wstein / node_modules / browserify / node_modules / parents / node_modules / path-platform / path.js
80538 views// Copyright Joyent, Inc. and other Node contributors.1//2// Permission is hereby granted, free of charge, to any person obtaining a3// copy of this software and associated documentation files (the4// "Software"), to deal in the Software without restriction, including5// without limitation the rights to use, copy, modify, merge, publish,6// distribute, sublicense, and/or sell copies of the Software, and to permit7// persons to whom the Software is furnished to do so, subject to the8// following conditions:9//10// The above copyright notice and this permission notice shall be included11// in all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF15// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN16// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,17// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19// USE OR OTHER DEALINGS IN THE SOFTWARE.202122var isWindows = process.platform === 'win32';23var util = require('util');2425var _path = require('path');2627// we are new enough we already have this from the system, just export the28// system then29if (_path.posix) {30module.exports = _path;31return;32}3334// resolves . and .. elements in a path array with directory names there35// must be no slashes or device names (c:\) in the array36// (so also no leading and trailing slashes - it does not distinguish37// relative and absolute paths)38function normalizeArray(parts, allowAboveRoot) {39var res = [];40for (var i = 0; i < parts.length; i++) {41var p = parts[i];4243// ignore empty parts44if (!p || p === '.')45continue;4647if (p === '..') {48if (res.length && res[res.length - 1] !== '..') {49res.pop();50} else if (allowAboveRoot) {51res.push('..');52}53} else {54res.push(p);55}56}5758return res;59}6061// Regex to split a windows path into three parts: [*, device, slash,62// tail] windows-only63var splitDeviceRe =64/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;6566// Regex to split the tail part of the above into [*, dir, basename, ext]67var splitTailRe =68/^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/;6970var win32 = {};7172// Function to split a filename into [root, dir, basename, ext]73function win32SplitPath(filename) {74// Separate device+slash from tail75var result = splitDeviceRe.exec(filename),76device = (result[1] || '') + (result[2] || ''),77tail = result[3] || '';78// Split the tail into dir, basename and extension79var result2 = splitTailRe.exec(tail),80dir = result2[1],81basename = result2[2],82ext = result2[3];83return [device, dir, basename, ext];84}8586var normalizeUNCRoot = function(device) {87return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\');88};8990// path.resolve([from ...], to)91win32.resolve = function() {92var resolvedDevice = '',93resolvedTail = '',94resolvedAbsolute = false;9596for (var i = arguments.length - 1; i >= -1; i--) {97var path;98if (i >= 0) {99path = arguments[i];100} else if (!resolvedDevice) {101path = process.cwd();102} else {103// Windows has the concept of drive-specific current working104// directories. If we've resolved a drive letter but not yet an105// absolute path, get cwd for that drive. We're sure the device is not106// an unc path at this points, because unc paths are always absolute.107path = process.env['=' + resolvedDevice];108// Verify that a drive-local cwd was found and that it actually points109// to our drive. If not, default to the drive's root.110if (!path || path.substr(0, 3).toLowerCase() !==111resolvedDevice.toLowerCase() + '\\') {112path = resolvedDevice + '\\';113}114}115116// Skip empty and invalid entries117if (!util.isString(path)) {118throw new TypeError('Arguments to path.resolve must be strings');119} else if (!path) {120continue;121}122123var result = splitDeviceRe.exec(path),124device = result[1] || '',125isUnc = device && device.charAt(1) !== ':',126isAbsolute = win32.isAbsolute(path),127tail = result[3];128129if (device &&130resolvedDevice &&131device.toLowerCase() !== resolvedDevice.toLowerCase()) {132// This path points to another device so it is not applicable133continue;134}135136if (!resolvedDevice) {137resolvedDevice = device;138}139if (!resolvedAbsolute) {140resolvedTail = tail + '\\' + resolvedTail;141resolvedAbsolute = isAbsolute;142}143144if (resolvedDevice && resolvedAbsolute) {145break;146}147}148149// Convert slashes to backslashes when `resolvedDevice` points to an UNC150// root. Also squash multiple slashes into a single one where appropriate.151if (isUnc) {152resolvedDevice = normalizeUNCRoot(resolvedDevice);153}154155// At this point the path should be resolved to a full absolute path,156// but handle relative paths to be safe (might happen when process.cwd()157// fails)158159// Normalize the tail path160resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/),161!resolvedAbsolute).join('\\');162163// If device is a drive letter, we'll normalize to lower case.164if (resolvedDevice && resolvedDevice.charAt(1) === ':') {165resolvedDevice = resolvedDevice[0].toLowerCase() +166resolvedDevice.substr(1);167}168169return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) ||170'.';171};172173174win32.normalize = function(path) {175var result = splitDeviceRe.exec(path),176device = result[1] || '',177isUnc = device && device.charAt(1) !== ':',178isAbsolute = win32.isAbsolute(path),179tail = result[3],180trailingSlash = /[\\\/]$/.test(tail);181182// If device is a drive letter, we'll normalize to lower case.183if (device && device.charAt(1) === ':') {184device = device[0].toLowerCase() + device.substr(1);185}186187// Normalize the tail path188tail = normalizeArray(tail.split(/[\\\/]+/), !isAbsolute).join('\\');189190if (!tail && !isAbsolute) {191tail = '.';192}193if (tail && trailingSlash) {194tail += '\\';195}196197// Convert slashes to backslashes when `device` points to an UNC root.198// Also squash multiple slashes into a single one where appropriate.199if (isUnc) {200device = normalizeUNCRoot(device);201}202203return device + (isAbsolute ? '\\' : '') + tail;204};205206207win32.isAbsolute = function(path) {208var result = splitDeviceRe.exec(path),209device = result[1] || '',210isUnc = !!device && device.charAt(1) !== ':';211// UNC paths are always absolute212return !!result[2] || isUnc;213};214215win32.join = function() {216function f(p) {217if (!util.isString(p)) {218throw new TypeError('Arguments to path.join must be strings');219}220return p;221}222223var paths = Array.prototype.filter.call(arguments, f);224var joined = paths.join('\\');225226// Make sure that the joined path doesn't start with two slashes, because227// normalize() will mistake it for an UNC path then.228//229// This step is skipped when it is very clear that the user actually230// intended to point at an UNC path. This is assumed when the first231// non-empty string arguments starts with exactly two slashes followed by232// at least one more non-slash character.233//234// Note that for normalize() to treat a path as an UNC path it needs to235// have at least 2 components, so we don't filter for that here.236// This means that the user can use join to construct UNC paths from237// a server name and a share name; for example:238// path.join('//server', 'share') -> '\\\\server\\share\')239if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) {240joined = joined.replace(/^[\\\/]{2,}/, '\\');241}242243return win32.normalize(joined);244};245246247// path.relative(from, to)248// it will solve the relative path from 'from' to 'to', for instance:249// from = 'C:\\orandea\\test\\aaa'250// to = 'C:\\orandea\\impl\\bbb'251// The output of the function should be: '..\\..\\impl\\bbb'252win32.relative = function(from, to) {253from = win32.resolve(from);254to = win32.resolve(to);255256// windows is not case sensitive257var lowerFrom = from.toLowerCase();258var lowerTo = to.toLowerCase();259260function trim(arr) {261var start = 0;262for (; start < arr.length; start++) {263if (arr[start] !== '') break;264}265266var end = arr.length - 1;267for (; end >= 0; end--) {268if (arr[end] !== '') break;269}270271if (start > end) return [];272return arr.slice(start, end + 1);273}274275var toParts = trim(to.split('\\'));276277var lowerFromParts = trim(lowerFrom.split('\\'));278var lowerToParts = trim(lowerTo.split('\\'));279280var length = Math.min(lowerFromParts.length, lowerToParts.length);281var samePartsLength = length;282for (var i = 0; i < length; i++) {283if (lowerFromParts[i] !== lowerToParts[i]) {284samePartsLength = i;285break;286}287}288289if (samePartsLength == 0) {290return to;291}292293var outputParts = [];294for (var i = samePartsLength; i < lowerFromParts.length; i++) {295outputParts.push('..');296}297298outputParts = outputParts.concat(toParts.slice(samePartsLength));299300return outputParts.join('\\');301};302303304win32._makeLong = function(path) {305// Note: this will *probably* throw somewhere.306if (!util.isString(path))307return path;308309if (!path) {310return '';311}312313var resolvedPath = win32.resolve(path);314315if (/^[a-zA-Z]\:\\/.test(resolvedPath)) {316// path is local filesystem path, which needs to be converted317// to long UNC path.318return '\\\\?\\' + resolvedPath;319} else if (/^\\\\[^?.]/.test(resolvedPath)) {320// path is network UNC path, which needs to be converted321// to long UNC path.322return '\\\\?\\UNC\\' + resolvedPath.substring(2);323}324325return path;326};327328329win32.dirname = function(path) {330var result = win32SplitPath(path),331root = result[0],332dir = result[1];333334if (!root && !dir) {335// No dirname whatsoever336return '.';337}338339if (dir) {340// It has a dirname, strip trailing slash341dir = dir.substr(0, dir.length - 1);342}343344return root + dir;345};346347348win32.basename = function(path, ext) {349var f = win32SplitPath(path)[2];350// TODO: make this comparison case-insensitive on windows?351if (ext && f.substr(-1 * ext.length) === ext) {352f = f.substr(0, f.length - ext.length);353}354return f;355};356357358win32.extname = function(path) {359return win32SplitPath(path)[3];360};361362363win32.format = function(pathObject) {364if (!util.isObject(pathObject)) {365throw new TypeError(366"Parameter 'pathObject' must be an object, not " + typeof pathObject367);368}369370var root = pathObject.root || '';371372if (!util.isString(root)) {373throw new TypeError(374"'pathObject.root' must be a string or undefined, not " +375typeof pathObject.root376);377}378379var dir = pathObject.dir;380var base = pathObject.base || '';381if (dir.slice(dir.length - 1, dir.length) === win32.sep) {382return dir + base;383}384385if (dir) {386return dir + win32.sep + base;387}388389return base;390};391392393win32.parse = function(pathString) {394if (!util.isString(pathString)) {395throw new TypeError(396"Parameter 'pathString' must be a string, not " + typeof pathString397);398}399var allParts = win32SplitPath(pathString);400if (!allParts || allParts.length !== 4) {401throw new TypeError("Invalid path '" + pathString + "'");402}403return {404root: allParts[0],405dir: allParts[0] + allParts[1].slice(0, allParts[1].length - 1),406base: allParts[2],407ext: allParts[3],408name: allParts[2].slice(0, allParts[2].length - allParts[3].length)409};410};411412413win32.sep = '\\';414win32.delimiter = ';';415416417// Split a filename into [root, dir, basename, ext], unix version418// 'root' is just a slash, or nothing.419var splitPathRe =420/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;421var posix = {};422423424function posixSplitPath(filename) {425return splitPathRe.exec(filename).slice(1);426}427428429// path.resolve([from ...], to)430// posix version431posix.resolve = function() {432var resolvedPath = '',433resolvedAbsolute = false;434435for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {436var path = (i >= 0) ? arguments[i] : process.cwd();437438// Skip empty and invalid entries439if (!util.isString(path)) {440throw new TypeError('Arguments to path.resolve must be strings');441} else if (!path) {442continue;443}444445resolvedPath = path + '/' + resolvedPath;446resolvedAbsolute = path.charAt(0) === '/';447}448449// At this point the path should be resolved to a full absolute path, but450// handle relative paths to be safe (might happen when process.cwd() fails)451452// Normalize the path453resolvedPath = normalizeArray(resolvedPath.split('/'),454!resolvedAbsolute).join('/');455456return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';457};458459// path.normalize(path)460// posix version461posix.normalize = function(path) {462var isAbsolute = posix.isAbsolute(path),463trailingSlash = path.substr(-1) === '/';464465// Normalize the path466path = normalizeArray(path.split('/'), !isAbsolute).join('/');467468if (!path && !isAbsolute) {469path = '.';470}471if (path && trailingSlash) {472path += '/';473}474475return (isAbsolute ? '/' : '') + path;476};477478// posix version479posix.isAbsolute = function(path) {480return path.charAt(0) === '/';481};482483// posix version484posix.join = function() {485var path = '';486for (var i = 0; i < arguments.length; i++) {487var segment = arguments[i];488if (!util.isString(segment)) {489throw new TypeError('Arguments to path.join must be strings');490}491if (segment) {492if (!path) {493path += segment;494} else {495path += '/' + segment;496}497}498}499return posix.normalize(path);500};501502503// path.relative(from, to)504// posix version505posix.relative = function(from, to) {506from = posix.resolve(from).substr(1);507to = posix.resolve(to).substr(1);508509function trim(arr) {510var start = 0;511for (; start < arr.length; start++) {512if (arr[start] !== '') break;513}514515var end = arr.length - 1;516for (; end >= 0; end--) {517if (arr[end] !== '') break;518}519520if (start > end) return [];521return arr.slice(start, end + 1);522}523524var fromParts = trim(from.split('/'));525var toParts = trim(to.split('/'));526527var length = Math.min(fromParts.length, toParts.length);528var samePartsLength = length;529for (var i = 0; i < length; i++) {530if (fromParts[i] !== toParts[i]) {531samePartsLength = i;532break;533}534}535536var outputParts = [];537for (var i = samePartsLength; i < fromParts.length; i++) {538outputParts.push('..');539}540541outputParts = outputParts.concat(toParts.slice(samePartsLength));542543return outputParts.join('/');544};545546547posix._makeLong = function(path) {548return path;549};550551552posix.dirname = function(path) {553var result = posixSplitPath(path),554root = result[0],555dir = result[1];556557if (!root && !dir) {558// No dirname whatsoever559return '.';560}561562if (dir) {563// It has a dirname, strip trailing slash564dir = dir.substr(0, dir.length - 1);565}566567return root + dir;568};569570571posix.basename = function(path, ext) {572var f = posixSplitPath(path)[2];573// TODO: make this comparison case-insensitive on windows?574if (ext && f.substr(-1 * ext.length) === ext) {575f = f.substr(0, f.length - ext.length);576}577return f;578};579580581posix.extname = function(path) {582return posixSplitPath(path)[3];583};584585586posix.format = function(pathObject) {587if (!util.isObject(pathObject)) {588throw new TypeError(589"Parameter 'pathObject' must be an object, not " + typeof pathObject590);591}592593var root = pathObject.root || '';594595if (!util.isString(root)) {596throw new TypeError(597"'pathObject.root' must be a string or undefined, not " +598typeof pathObject.root599);600}601602var dir = pathObject.dir ? pathObject.dir + posix.sep : '';603var base = pathObject.base || '';604return dir + base;605};606607608posix.parse = function(pathString) {609if (!util.isString(pathString)) {610throw new TypeError(611"Parameter 'pathString' must be a string, not " + typeof pathString612);613}614var allParts = posixSplitPath(pathString);615if (!allParts || allParts.length !== 4) {616throw new TypeError("Invalid path '" + pathString + "'");617}618allParts[1] = allParts[1] || '';619allParts[2] = allParts[2] || '';620allParts[3] = allParts[3] || '';621622return {623root: allParts[0],624dir: allParts[0] + allParts[1].slice(0, allParts[1].length - 1),625base: allParts[2],626ext: allParts[3],627name: allParts[2].slice(0, allParts[2].length - allParts[3].length)628};629};630631632posix.sep = '/';633posix.delimiter = ':';634635636if (isWindows)637module.exports = win32;638else /* posix */639module.exports = posix;640641module.exports.posix = posix;642module.exports.win32 = win32;643644645