'use strict' // A derivative work based on: // . // Which is licensed: // // MIT License // // Copyright (c) 2013 James Halliday // // 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. // A derivative work based on: // // Parts of that are extracted from Node’s internal `path` module: // . // Which is licensed: // // 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. exports.basename = basename exports.dirname = dirname exports.extname = extname exports.join = join exports.sep = '/' function basename(path, ext) { var start = 0 var end = -1 var index var firstNonSlashEnd var seenNonSlash var extIndex if (ext !== undefined && typeof ext !== 'string') { throw new TypeError('"ext" argument must be a string') } assertPath(path) index = path.length if (ext === undefined || !ext.length || ext.length > path.length) { while (index--) { if (path.charCodeAt(index) === 47 /* `/` */) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now. if (seenNonSlash) { start = index + 1 break } } else if (end < 0) { // We saw the first non-path separator, mark this as the end of our // path component. seenNonSlash = true end = index + 1 } } return end < 0 ? '' : path.slice(start, end) } if (ext === path) { return '' } firstNonSlashEnd = -1 extIndex = ext.length - 1 while (index--) { if (path.charCodeAt(index) === 47 /* `/` */) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now. if (seenNonSlash) { start = index + 1 break } } else { if (firstNonSlashEnd < 0) { // We saw the first non-path separator, remember this index in case // we need it if the extension ends up not matching. seenNonSlash = true firstNonSlashEnd = index + 1 } if (extIndex > -1) { // Try to match the explicit extension. if (path.charCodeAt(index) === ext.charCodeAt(extIndex--)) { if (extIndex < 0) { // We matched the extension, so mark this as the end of our path // component end = index } } else { // Extension does not match, so our result is the entire path // component extIndex = -1 end = firstNonSlashEnd } } } } if (start === end) { end = firstNonSlashEnd } else if (end < 0) { end = path.length } return path.slice(start, end) } function dirname(path) { var end var unmatchedSlash var index assertPath(path) if (!path.length) { return '.' } end = -1 index = path.length // Prefix `--` is important to not run on `0`. while (--index) { if (path.charCodeAt(index) === 47 /* `/` */) { if (unmatchedSlash) { end = index break } } else if (!unmatchedSlash) { // We saw the first non-path separator unmatchedSlash = true } } return end < 0 ? path.charCodeAt(0) === 47 /* `/` */ ? '/' : '.' : end === 1 && path.charCodeAt(0) === 47 /* `/` */ ? '//' : path.slice(0, end) } function extname(path) { var startDot = -1 var startPart = 0 var end = -1 // Track the state of characters (if any) we see before our first dot and // after any path separator we find. var preDotState = 0 var unmatchedSlash var code var index assertPath(path) index = path.length while (index--) { code = path.charCodeAt(index) if (code === 47 /* `/` */) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now. if (unmatchedSlash) { startPart = index + 1 break } continue } if (end < 0) { // We saw the first non-path separator, mark this as the end of our // extension. unmatchedSlash = true end = index + 1 } if (code === 46 /* `.` */) { // If this is our first dot, mark it as the start of our extension. if (startDot < 0) { startDot = index } else if (preDotState !== 1) { preDotState = 1 } } else if (startDot > -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension. preDotState = -1 } } if ( startDot < 0 || end < 0 || // We saw a non-dot character immediately before the dot. preDotState === 0 || // The (right-most) trimmed path component is exactly `..`. (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) ) { return '' } return path.slice(startDot, end) } function join() { var index = -1 var joined while (++index < arguments.length) { assertPath(arguments[index]) if (arguments[index]) { joined = joined === undefined ? arguments[index] : joined + '/' + arguments[index] } } return joined === undefined ? '.' : normalize(joined) } // Note: `normalize` is not exposed as `path.normalize`, so some code is // manually removed from it. function normalize(path) { var absolute var value assertPath(path) absolute = path.charCodeAt(0) === 47 /* `/` */ // Normalize the path according to POSIX rules. value = normalizeString(path, !absolute) if (!value.length && !absolute) { value = '.' } if (value.length && path.charCodeAt(path.length - 1) === 47 /* / */) { value += '/' } return absolute ? '/' + value : value } // Resolve `.` and `..` elements in a path with directory names. function normalizeString(path, allowAboveRoot) { var result = '' var lastSegmentLength = 0 var lastSlash = -1 var dots = 0 var index = -1 var code var lastSlashIndex while (++index <= path.length) { if (index < path.length) { code = path.charCodeAt(index) } else if (code === 47 /* `/` */) { break } else { code = 47 /* `/` */ } if (code === 47 /* `/` */) { if (lastSlash === index - 1 || dots === 1) { // Empty. } else if (lastSlash !== index - 1 && dots === 2) { if ( result.length < 2 || lastSegmentLength !== 2 || result.charCodeAt(result.length - 1) !== 46 /* `.` */ || result.charCodeAt(result.length - 2) !== 46 /* `.` */ ) { if (result.length > 2) { lastSlashIndex = result.lastIndexOf('/') /* istanbul ignore else - No clue how to cover it. */ if (lastSlashIndex !== result.length - 1) { if (lastSlashIndex < 0) { result = '' lastSegmentLength = 0 } else { result = result.slice(0, lastSlashIndex) lastSegmentLength = result.length - 1 - result.lastIndexOf('/') } lastSlash = index dots = 0 continue } } else if (result.length) { result = '' lastSegmentLength = 0 lastSlash = index dots = 0 continue } } if (allowAboveRoot) { result = result.length ? result + '/..' : '..' lastSegmentLength = 2 } } else { if (result.length) { result += '/' + path.slice(lastSlash + 1, index) } else { result = path.slice(lastSlash + 1, index) } lastSegmentLength = index - lastSlash - 1 } lastSlash = index dots = 0 } else if (code === 46 /* `.` */ && dots > -1) { dots++ } else { dots = -1 } } return result } function assertPath(path) { if (typeof path !== 'string') { throw new TypeError( 'Path must be a string. Received ' + JSON.stringify(path) ) } }