UNPKG

react-scripts

Version:
663 lines (522 loc) 17.9 kB
/** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * */ /*! * fast-path - index.js * MIT License * * Copyright Joyent, Inc. and other Node contributors. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, subject to the * following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * original author: dead_horse <dead_horse@qq.com> * ported by: yaycmyk <evan@yaycmyk.com> * * VERSION 1.2.0 */ 'use strict'; const fs = require('fs'); const path = require('path'); const util = require('util'); // fastpath is only useful on older versions of nodejs. if ( process.versions.node && parseInt(process.versions.node.split('.')[0], 10) >= 5) { module.exports = Object.assign( {}, { replace: () => {} }, path); } else { const IS_WINDOWS = process.platform === 'win32'; function isString(arg) { return typeof arg === 'string'; } const splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; function getDevice(filename) { const result = splitDeviceRe.exec(filename); return (result[1] || '') + (result[2] || ''); } // resolves . and .. elements in a path array with directory names there // must be no slashes, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray( parts, allowAboveRoot) { const nonEmptyParts = []; let nonBack = true; for (let i = 0; i < parts.length; i++) { const p = parts[i]; if (p && p !== '.') { nonEmptyParts.push(p); } if (p === '..') { nonBack = false; } } parts = nonEmptyParts; // if the path does not contain .. if (nonBack) { return parts; } // if the path tries to go ab ove the root, `up` ends up > 0 let up = 0; const res = []; for (let i = parts.length - 1; i >= 0; i--) { if (parts[i] === '..') { up++; } else if (up) { up--; } else { res.push(parts[i]); } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { res.push('..'); } } return res.reverse(); } function trim(arr) { let start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') {break;} } let end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') {break;} } return start <= end ? arr.slice(start, end + 1) : []; } function normalizeUNCRoot(device) { return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\'); } const sep = IS_WINDOWS ? '\\' : '/'; exports.sep = sep; exports.delimiter = IS_WINDOWS ? ';' : ':'; if (IS_WINDOWS) { // path.resolve([from ...], to) // windows version exports.resolve = function resolveWIN32() { let resolvedDevice = ''; let resolvedTail = ''; let resolvedAbsolute = false; for (let i = arguments.length - 1; i >= -1; i--) { let path; if (i >= 0) { path = arguments[i]; } else if (!resolvedDevice) { path = process.cwd(); } else { // Windows has the concept of drive-specific current working // directories. If we've resolved a drive letter but not yet an // absolute path, get cwd for that drive. We're sure the device is not // an unc path at this points, because unc paths are always absolute. path = process.env['=' + resolvedDevice]; // Verify that a drive-local cwd was found and that it actually points // to our drive. If not, default to the drive's root. if (!path || path.substr(0, 3).toLowerCase() !== resolvedDevice.toLowerCase() + '\\') { path = resolvedDevice + '\\'; } } // Skip empty and invalid entries if (!isString(path)) { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } const result = splitDeviceRe.exec(path); const device = result[1] || ''; const isUnc = device && device.charAt(1) !== ':'; const isAbsolute = exports.isAbsolute(path); const tail = result[3]; if (device && resolvedDevice && device.toLowerCase() !== resolvedDevice.toLowerCase()) { // This path points to another device so it is not applicable continue; } if (!resolvedDevice) { resolvedDevice = device; } if (!resolvedAbsolute) { resolvedTail = tail + '\\' + resolvedTail; resolvedAbsolute = isAbsolute; } // Convert slashes to backslashes when `resolvedDevice` points to an UNC // root. Also squash multiple slashes into a single one where // appropriate. if (isUnc) { resolvedDevice = normalizeUNCRoot(resolvedDevice); } if (resolvedDevice && resolvedAbsolute) { break; } } // At this point the path should be resolved to a full absolute path, // but handle relative paths to be safe (might happen when process.cwd() // fails) // Normalize the tail path resolvedTail = normalizeArray( resolvedTail.split(/[\\\/]+/), !resolvedAbsolute). join('\\'); return resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail || '.'; }; // windows version exports.normalize = function normalizeWIN32(path) { const result = splitDeviceRe.exec(path); let device = result[1] || ''; const isUnc = device && device.charAt(1) !== ':'; const isAbsolute = exports.isAbsolute(path); let tail = result[3]; const trailingSlash = /[\\\/]$/.test(tail); // Normalize the tail path tail = normalizeArray(tail.split(/[\\\/]+/), !isAbsolute).join('\\'); if (!tail && !isAbsolute) { tail = '.'; } if (tail && trailingSlash) { tail += '\\'; } // Convert slashes to backslashes when `device` points to an UNC root. // Also squash multiple slashes into a single one where appropriate. if (isUnc) { device = normalizeUNCRoot(device); } return device + (isAbsolute ? '\\' : '') + tail; }; // windows version exports.isAbsolute = function isAbsoluteWIN32(path) { const result = splitDeviceRe.exec(path); const device = result[1] || ''; const isUnc = !!device && device.charAt(1) !== ':'; // UNC paths are always absolute return !!result[2] || isUnc; }; // windows version exports.join = function joinWIN32() { function f(p) { if (!isString(p)) { throw new TypeError('Arguments to path.join must be strings'); } return p; } const paths = Array.prototype.filter.call(arguments, f); let joined = paths.join('\\'); // Make sure that the joined path doesn't start with two slashes, because // normalize() will mistake it for an UNC path then. // // This step is skipped when it is very clear that the user actually // intended to point at an UNC path. This is assumed when the first // non-empty string arguments starts with exactly two slashes followed by // at least one more non-slash character. // // Note that for normalize() to treat a path as an UNC path it needs to // have at least 2 components, so we don't filter for that here. // This means that the user can use join to construct UNC paths from // a server name and a share name; for example: // path.join('//server', 'share') -> '\\\\server\\share\') if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) { joined = joined.replace(/^[\\\/]{2,}/, '\\'); } return exports.normalize(joined); }; // path.relative(from, to) // it will solve the relative path from 'from' to 'to', for instance: // from = 'C:\\orandea\\test\\aaa' // to = 'C:\\orandea\\impl\\bbb' // The output of the function should be: '..\\..\\impl\\bbb' // windows version exports.relative = function relativeWIN32( from, to) { from = exports.resolve(from); to = exports.resolve(to); // windows is not case sensitive const lowerFrom = from.toLowerCase(); const lowerTo = to.toLowerCase(); const toParts = trim(to.split('\\')); const lowerFromParts = trim(lowerFrom.split('\\')); const lowerToParts = trim(lowerTo.split('\\')); const length = Math.min(lowerFromParts.length, lowerToParts.length); let samePartsLength = length; for (let i = 0; i < length; i++) { if (lowerFromParts[i] !== lowerToParts[i]) { samePartsLength = i; break; } } if (samePartsLength == 0) { return to; } let outputParts = []; for (let i = samePartsLength; i < lowerFromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('\\'); }; } else /* posix */{ // path.resolve([from ...], to) // posix version exports.resolve = function resolvePOSIX() { let resolvedPath = ''; let resolvedAbsolute = false; for (let i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { const path = i >= 0 ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (!isString(path)) { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() // fails) // Normalize the path resolvedPath = normalizeArray( resolvedPath.split('/'), !resolvedAbsolute). join('/'); return (resolvedAbsolute ? '/' : '') + resolvedPath || '.'; }; // path.normalize(path) // posix version exports.normalize = function normalizePOSIX(path) { const isAbsolute = exports.isAbsolute(path); const trailingSlash = path[path.length - 1] === '/'; // normalize the path path = normalizeArray(path.split('/'), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.isAbsolute = function isAbsolutePOSIX(path) { return path.charAt(0) === '/'; }; // posix version exports.join = function joinPOSIX() { let path = ''; for (let i = 0; i < arguments.length; i++) { const segment = arguments[i]; if (!isString(segment)) { throw new TypeError('Arguments to path.join must be strings'); } if (segment) { path += `${ path ? '/' : '' }${ segment }`; } } return exports.normalize(path); }; // path.relative(from, to) // posix version exports.relative = function relativePOSIX( from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); const fromParts = trim(from.split('/')); const toParts = trim(to.split('/')); const length = Math.min(fromParts.length, toParts.length); let samePartsLength = length; for (let i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } let outputParts = []; for (let i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; } exports.exists = util.deprecate( (path, callback) => fs.exists(path, callback), 'path.exists is now called `fs.exists`.'); exports.existsSync = util.deprecate( path => fs.existsSync(path), 'path.existsSync is now called `fs.existsSync`.'); if (IS_WINDOWS) { exports._makeLong = function _makeLongWIN32(path) { // Note: this will *probably* throw somewhere. if (!isString(path)) {return path;} if (!path) {return '';} const resolvedPath = exports.resolve(path); if (/^[a-zA-Z]\:\\/.test(resolvedPath)) { // path is local filesystem path, which needs to be converted // to long UNC path. return '\\\\?\\' + resolvedPath; } else if (/^\\\\[^?.]/.test(resolvedPath)) { // path is network UNC path, which needs to be converted // to long UNC path. return '\\\\?\\UNC\\' + resolvedPath.substring(2); } return path; }; } else { exports._makeLong = function _makeLongPOSIX(path) { return path; }; } exports.extname = function _extname(filename) { if (!filename) {return '';} // /a.js/// let end = filename.length; let c = filename[end - 1]; while (c === sep || c === '/') { end--; c = filename[end - 1]; } let lastDot = -1; let lastSep = -1; for (let i = end; i--;) { const ch = filename[i]; if (lastDot === -1 && ch === '.') { lastDot = i; } else if (lastSep === -1 && ch === '/') { lastSep = i; } else if (IS_WINDOWS && lastSep === -1 && ch === '\\') { lastSep = i; } // /xxx if (lastSep !== -1 && lastDot === -1) {return '';} // /*.js if (lastDot !== -1 && i === lastDot - 2) {break;} // /.js if (lastSep !== -1 && lastDot !== -1) {break;} } // ./js and /.js if (lastDot < lastSep + 2) {return '';} const extname = filename.slice(lastDot, end); if (extname === '.' && filename[lastDot - 1] === '.') { // .. if (lastDot === 1) {return '';} const pre = filename[lastDot - 2]; // [//\/].. if (pre === '/' || pre === sep) {return '';} } return extname; }; exports.basename = function _basename( filename, ext) { if (!filename) {return '';} // /a.js/// let end = filename.length; let c = filename[end - 1]; while (c === sep || c === '/') { end--; c = filename[end - 1]; } let lastSep = -1; for (let i = end; i--;) { const ch = filename[i]; if (lastSep === -1 && ch === '/') { lastSep = i; break; } if (IS_WINDOWS && lastSep === -1 && ch === '\\') { lastSep = i; break; } } const basename = filename.slice(lastSep + 1, end); if (ext) { const match = basename.lastIndexOf(ext); if (match === -1 || match !== basename.length - ext.length) { return basename; } return basename.slice(0, basename.length - ext.length); } return basename; }; exports.dirname = function _dirname(filename) { if (!filename) {return '.';} let start = 0; let device = ''; if (IS_WINDOWS) { // need to get device in windows device = getDevice(filename); if (device) {start = device.length;} } // /a.js/// let end = filename.length; let c = filename[end - 1]; while (end >= start && c === sep || c === '/') { end--; c = filename[end - 1]; } let lastSep = -1; for (let i = end; i-- > start;) { const ch = filename[i]; if (lastSep === -1 && ch === '/') { lastSep = i; break; } if (IS_WINDOWS && lastSep === -1 && ch === '\\') { lastSep = i; break; } } if (lastSep <= start) { if (device) { return device; } if (filename[0] === '/' || filename[0] === sep) { return filename[0]; } return '.'; } return device + filename.slice(start, lastSep); }; exports.replace = function () { Object.keys(exports). filter(name => name !== 'replace'). forEach(name => path[name] = exports[name]); }; }