| const os = require('bare-os') | |
| const { normalizeString } = require('./shared') | |
| const { | |
| CHAR_DOT, | |
| CHAR_FORWARD_SLASH | |
| } = require('./constants') | |
| function isPosixPathSeparator (code) { | |
| return code === CHAR_FORWARD_SLASH | |
| } | |
| exports.win32 = require('./win32') | |
| exports.posix = exports | |
| exports.sep = '/' | |
| exports.delimiter = ':' | |
| exports.resolve = function resolve (...args) { | |
| let resolvedPath = '' | |
| let resolvedAbsolute = false | |
| for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) { | |
| const path = i >= 0 ? args[i] : os.cwd() | |
| if (path.length === 0) { | |
| continue | |
| } | |
| resolvedPath = `${path}/${resolvedPath}` | |
| resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH | |
| } | |
| resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', isPosixPathSeparator) | |
| if (resolvedAbsolute) { | |
| return `/${resolvedPath}` | |
| } | |
| return resolvedPath.length > 0 ? resolvedPath : '.' | |
| } | |
| exports.normalize = function normalize (path) { | |
| if (path.length === 0) return '.' | |
| const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH | |
| const trailingSeparator = path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH | |
| path = normalizeString(path, !isAbsolute, '/', isPosixPathSeparator) | |
| if (path.length === 0) { | |
| if (isAbsolute) return '/' | |
| return trailingSeparator ? './' : '.' | |
| } | |
| if (trailingSeparator) path += '/' | |
| return isAbsolute ? `/${path}` : path | |
| } | |
| exports.isAbsolute = function isAbsolute (path) { | |
| return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH | |
| } | |
| exports.join = function join (...args) { | |
| if (args.length === 0) return '.' | |
| let joined | |
| for (let i = 0; i < args.length; ++i) { | |
| const arg = args[i] | |
| if (arg.length > 0) { | |
| if (joined === undefined) joined = arg | |
| else joined += `/${arg}` | |
| } | |
| } | |
| if (joined === undefined) return '.' | |
| return exports.normalize(joined) | |
| } | |
| exports.relative = function relative (from, to) { | |
| if (from === to) return '' | |
| from = exports.resolve(from) | |
| to = exports.resolve(to) | |
| if (from === to) return '' | |
| const fromStart = 1 | |
| const fromEnd = from.length | |
| const fromLen = fromEnd - fromStart | |
| const toStart = 1 | |
| const toLen = to.length - toStart | |
| const length = (fromLen < toLen ? fromLen : toLen) | |
| let lastCommonSep = -1 | |
| let i = 0 | |
| for (; i < length; i++) { | |
| const fromCode = from.charCodeAt(fromStart + i) | |
| if (fromCode !== to.charCodeAt(toStart + i)) { | |
| break | |
| } else if (fromCode === CHAR_FORWARD_SLASH) { | |
| lastCommonSep = i | |
| } | |
| } | |
| if (i === length) { | |
| if (toLen > length) { | |
| if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) { | |
| return to.substring(toStart + i + 1) | |
| } | |
| if (i === 0) { | |
| return to.substring(toStart + i) | |
| } | |
| } else if (fromLen > length) { | |
| if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) { | |
| lastCommonSep = i | |
| } else if (i === 0) { | |
| lastCommonSep = 0 | |
| } | |
| } | |
| } | |
| let out = '' | |
| for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { | |
| if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) { | |
| out += out.length === 0 ? '..' : '/..' | |
| } | |
| } | |
| return `${out}${to.substring(toStart + lastCommonSep)}` | |
| } | |
| exports.toNamespacedPath = function toNamespacedPath (path) { | |
| return path | |
| } | |
| exports.dirname = function dirname (path) { | |
| if (path.length === 0) return '.' | |
| const hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH | |
| let end = -1 | |
| let matchedSlash = true | |
| for (let i = path.length - 1; i >= 1; --i) { | |
| if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { | |
| if (!matchedSlash) { | |
| end = i | |
| break | |
| } | |
| } else { | |
| matchedSlash = false | |
| } | |
| } | |
| if (end === -1) return hasRoot ? '/' : '.' | |
| if (hasRoot && end === 1) return '//' | |
| return path.substring(0, end) | |
| } | |
| exports.basename = function basename (path, suffix) { | |
| let start = 0 | |
| let end = -1 | |
| let matchedSlash = true | |
| if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) { | |
| if (suffix === path) { return '' } | |
| let extIdx = suffix.length - 1 | |
| let firstNonSlashEnd = -1 | |
| for (let i = path.length - 1; i >= 0; --i) { | |
| const code = path.charCodeAt(i) | |
| if (code === CHAR_FORWARD_SLASH) { | |
| if (!matchedSlash) { | |
| start = i + 1 | |
| break | |
| } | |
| } else { | |
| if (firstNonSlashEnd === -1) { | |
| matchedSlash = false | |
| firstNonSlashEnd = i + 1 | |
| } | |
| if (extIdx >= 0) { | |
| if (code === suffix.charCodeAt(extIdx)) { | |
| if (--extIdx === -1) { | |
| end = i | |
| } | |
| } else { | |
| extIdx = -1 | |
| end = firstNonSlashEnd | |
| } | |
| } | |
| } | |
| } | |
| if (start === end) end = firstNonSlashEnd | |
| else if (end === -1) end = path.length | |
| return path.substring(start, end) | |
| } | |
| for (let i = path.length - 1; i >= 0; --i) { | |
| if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { | |
| if (!matchedSlash) { | |
| start = i + 1 | |
| break | |
| } | |
| } else if (end === -1) { | |
| matchedSlash = false | |
| end = i + 1 | |
| } | |
| } | |
| if (end === -1) return '' | |
| return path.substring(start, end) | |
| } | |
| exports.extname = function extname (path) { | |
| let startDot = -1 | |
| let startPart = 0 | |
| let end = -1 | |
| let matchedSlash = true | |
| let preDotState = 0 | |
| for (let i = path.length - 1; i >= 0; --i) { | |
| const code = path.charCodeAt(i) | |
| if (code === CHAR_FORWARD_SLASH) { | |
| if (!matchedSlash) { | |
| startPart = i + 1 | |
| break | |
| } | |
| continue | |
| } | |
| if (end === -1) { | |
| matchedSlash = false | |
| end = i + 1 | |
| } | |
| if (code === CHAR_DOT) { | |
| if (startDot === -1) startDot = i | |
| else if (preDotState !== 1) preDotState = 1 | |
| } else if (startDot !== -1) { | |
| preDotState = -1 | |
| } | |
| } | |
| if (startDot === -1 || end === -1 || preDotState === 0 || (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) { | |
| return '' | |
| } | |
| return path.substring(startDot, end) | |
| } | |