| |
| |
| const splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/; |
|
|
| function splitPath(filename: string) { |
| return splitPathRe.exec(filename).slice(1); |
| } |
|
|
| |
| |
| |
| |
| function normalizeArray(parts: string[], allowAboveRoot?: boolean) { |
| const res = []; |
| for (let i = 0; i < parts.length; i += 1) { |
| const p = parts[i]; |
|
|
| |
| if (!p || p === '.') continue; |
|
|
| if (p === '..') { |
| if (res.length && res[res.length - 1] !== '..') { |
| res.pop(); |
| } else if (allowAboveRoot) { |
| res.push('..'); |
| } |
| } else { |
| res.push(p); |
| } |
| } |
|
|
| return res; |
| } |
|
|
| export function isAbsolute(path: string) { |
| return path.charAt(0) === '/'; |
| } |
|
|
| export function normalize(path: string) { |
| const isAbs = isAbsolute(path); |
| const trailingSlash = path && path[path.length - 1] === '/'; |
| let newPath = path; |
|
|
| |
| newPath = normalizeArray(newPath.split('/'), !isAbs).join('/'); |
|
|
| if (!newPath && !isAbs) { |
| newPath = '.'; |
| } |
| if (newPath && trailingSlash) { |
| newPath += '/'; |
| } |
|
|
| return (isAbs ? '/' : '') + newPath; |
| } |
|
|
| export function join(...paths: Array<any>) { |
| let path = ''; |
| for (let i = 0; i < paths.length; i += 1) { |
| const segment = paths[i]; |
|
|
| if (typeof segment !== 'string') { |
| throw new TypeError('Arguments to path.join must be strings'); |
| } |
| if (segment) { |
| if (!path) { |
| path += segment; |
| } else { |
| path += `/${segment}`; |
| } |
| } |
| } |
| return normalize(path); |
| } |
|
|
| export function dirname(path: string) { |
| const result = splitPath(path); |
| const root = result[0]; |
| let dir = result[1]; |
|
|
| if (!root && !dir) { |
| |
| return '.'; |
| } |
|
|
| if (dir) { |
| |
| dir = dir.substr(0, dir.length - 1); |
| } |
|
|
| return root + dir; |
| } |
|
|
| export function basename(p: string, ext: string = '') { |
| |
| if (p === '') { |
| return p; |
| } |
| |
| const path = normalize(p); |
| |
| const sections = path.split('/'); |
| const lastPart = sections[sections.length - 1]; |
| |
| |
| if (lastPart === '' && sections.length > 1) { |
| return sections[sections.length - 2]; |
| } |
| |
| if (ext.length > 0) { |
| const lastPartExt = lastPart.substr(lastPart.length - ext.length); |
| if (lastPartExt === ext) { |
| return lastPart.substr(0, lastPart.length - ext.length); |
| } |
| } |
| return lastPart; |
| } |
|
|
| export function absolute(path: string) { |
| if (path.startsWith('/')) { |
| return path; |
| } |
|
|
| if (path.startsWith('./')) { |
| return path.replace('./', '/'); |
| } |
|
|
| return '/' + path; |
| } |
|
|
| function assertPath(path) { |
| if (typeof path !== 'string') { |
| throw new TypeError( |
| 'Path must be a string. Received ' + JSON.stringify(path) |
| ); |
| } |
| } |
|
|
| export function extname(path: string): string { |
| assertPath(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 === 47) { |
| |
| |
| if (!matchedSlash) { |
| startPart = i + 1; |
| break; |
| } |
| |
| continue; |
| } |
| if (end === -1) { |
| |
| |
| matchedSlash = false; |
| end = i + 1; |
| } |
| if (code === 46 ) { |
| |
| 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.slice(startDot, end); |
| } |
|
|
| export function resolve(...args) { |
| let resolvedPath = ''; |
| let resolvedAbsolute = false; |
|
|
| for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) { |
| const path = i >= 0 ? args[i] : process.cwd(); |
|
|
| |
| if (typeof path !== 'string') { |
| throw new TypeError('Arguments to path.resolve must be strings'); |
| } else if (!path) { |
| continue; |
| } |
|
|
| resolvedPath = path + '/' + resolvedPath; |
| resolvedAbsolute = path[0] === '/'; |
| } |
|
|
| |
| |
|
|
| |
| resolvedPath = normalizeArray( |
| resolvedPath.split('/'), |
| !resolvedAbsolute |
| ).join('/'); |
|
|
| return (resolvedAbsolute ? '/' : '') + resolvedPath || '.'; |
| } |
|
|
| function trimArray(arr) { |
| const lastIndex = arr.length - 1; |
| let start = 0; |
| for (; start <= lastIndex; start++) { |
| if (arr[start]) break; |
| } |
|
|
| let end = lastIndex; |
| for (; end >= 0; end--) { |
| if (arr[end]) break; |
| } |
|
|
| if (start === 0 && end === lastIndex) return arr; |
| if (start > end) return []; |
| return arr.slice(start, end + 1); |
| } |
|
|
| export function relative(from: string, to: string) { |
| from = resolve(from).substr(1); |
| to = resolve(to).substr(1); |
|
|
| const fromParts = trimArray(from.split('/')); |
| const toParts = trimArray(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('/'); |
| } |
|
|