import { isWindows } from './platform' ; const CHAR_UPPERCASE_A = 65 ; const CHAR_LOWERCASE_A = 97 ; const CHAR_UPPERCASE_Z = 90 ; const CHAR_LOWERCASE_Z = 122 ; const CHAR_DOT = 46 ; const CHAR_FORWARD_SLASH = 47 ; const CHAR_BACKWARD_SLASH = 92 ; const CHAR_COLON = 58 ; const CHAR_QUESTION_MARK = 63 ; interface IProcess { cwd ( ) : string ; platform : string ; env : object ; } declare let process ; const safeProcess = typeof process === 'undefined' ? { cwd ( ) { return '/' ; } , env : { } , get platform ( ) { return isWindows ? 'win32' : 'posix' ; } , } : process ; class ErrorInvalidArgType extends Error { code ! : 'ERR_INVALID_ARG_TYPE' ; constructor ( name , expected , actual ) { let determiner ; if ( typeof expected === 'string' && expected . indexOf ( 'not ' ) === 0 ) { determiner = 'must not be' ; expected = expected . replace ( /^not / , '' ) ; } else { determiner = 'must be' ; } let msg ; const type = name . indexOf ( '.' ) !== - 1 ? 'property' : 'argument' ; msg = `The "${ name }" ${ type } ${ determiner } of type ${ expected }` ; msg += `. Received type ${ typeof actual }` ; super ( msg ) ; } } function validateString ( value , name ) { if ( typeof value !== 'string' ) { throw new ErrorInvalidArgType ( name , 'string' , value ) ; } } function isPathSeparator ( code ) { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH ; } function isPosixPathSeparator ( code ) { return code === CHAR_FORWARD_SLASH ; } function isWindowsDeviceRoot ( code ) { return ( ( code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z ) || ( code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z ) ) ; } function normalizeString ( path , allowAboveRoot , separator , isPathSeparator ) { let res = '' ; let lastSegmentLength = 0 ; let lastSlash = - 1 ; let dots = 0 ; let code ; for ( let i = 0 ; i <= path . length ; ++ i ) { if ( i < path . length ) { code = path . charCodeAt ( i ) ; } else if ( isPathSeparator ( code ) ) { break ; } else { code = CHAR_FORWARD_SLASH ; } if ( isPathSeparator ( code ) ) { if ( lastSlash === i - 1 || dots === 1 ) { } else if ( lastSlash !== i - 1 && dots === 2 ) { if ( res . length < 2 || lastSegmentLength !== 2 || res . charCodeAt ( res . length - 1 ) !== CHAR_DOT || res . charCodeAt ( res . length - 2 ) !== CHAR_DOT ) { if ( res . length > 2 ) { const lastSlashIndex = res . lastIndexOf ( separator ) ; if ( lastSlashIndex === - 1 ) { res = '' ; lastSegmentLength = 0 ; } else { res = res . slice ( 0 , lastSlashIndex ) ; lastSegmentLength = res . length - 1 - res . lastIndexOf ( separator ) ; } lastSlash = i ; dots = 0 ; continue ; } else if ( res . length === 2 || res . length === 1 ) { res = '' ; lastSegmentLength = 0 ; lastSlash = i ; dots = 0 ; continue ; } } if ( allowAboveRoot ) { if ( res . length > 0 ) { res += `${ separator }..` ; } else { res = '..' ; } lastSegmentLength = 2 ; } } else { if ( res . length > 0 ) { res += separator + path . slice ( lastSlash + 1 , i ) ; } else { res = path . slice ( lastSlash + 1 , i ) ; } lastSegmentLength = i - lastSlash - 1 ; } lastSlash = i ; dots = 0 ; } else if ( code === CHAR_DOT && dots !== - 1 ) { ++ dots ; } else { dots = - 1 ; } } return res ; } function _format ( sep , pathObject ) { const dir = pathObject . dir || pathObject . root ; const base = pathObject . base || ( pathObject . name || '' ) + ( pathObject . ext || '' ) ; if ( ! dir ) { return base ; } if ( dir === pathObject . root ) { return dir + base ; } return dir + sep + base ; } interface ParsedPath { root : string ; dir : string ; base : string ; ext : string ; name : string ; } interface IPath { normalize ( path ) : string ; isAbsolute ( path ) : boolean ; join ( ... paths ) : string ; resolve ( ... pathSegments ) : string ; relative ( from , to ) : string ; dirname ( path ) : string ; basename ( path , ext ? ) : string ; extname ( path ) : string ; format ( pathObject ) : string ; parse ( path ) : ParsedPath ; toNamespacedPath ( path ) : string ; sep : '\\' | '/' ; delimiter : string ; win32 : IPath | null ; posix : IPath | null ; } interface IExportedPath extends IPath { win32 : IPath ; posix : IPath ; } const win32 = { resolve ( ... pathSegments ) { let resolvedDevice = '' ; let resolvedTail = '' ; let resolvedAbsolute = false ; for ( let i = pathSegments . length - 1 ; i >= - 1 ; i -- ) { let path ; if ( i >= 0 ) { path = pathSegments [ i ] ; } else if ( ! resolvedDevice ) { path = safeProcess . cwd ( ) ; } else { path = ( safeProcess . env as any ) [ '=' + resolvedDevice ] || safeProcess . cwd ( ) ; if ( path === undefined || path . slice ( 0 , 3 ) . toLowerCase ( ) !== resolvedDevice . toLowerCase ( ) + '\\' ) { path = resolvedDevice + '\\' ; } } validateString ( path , 'path' ) ; if ( path . length === 0 ) { continue ; } let len = path . length ; let rootEnd = 0 ; let device = '' ; let isAbsolute = false ; const code = path . charCodeAt ( 0 ) ; if ( len > 1 ) { if ( isPathSeparator ( code ) ) { isAbsolute = true ; if ( isPathSeparator ( path . charCodeAt ( 1 ) ) ) { let j = 2 ; let last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { const firstPart = path . slice ( last , j ) ; last = j ; for ( ; j < len ; ++ j ) { if ( ! isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j === len ) { device = '\\\\' + firstPart + '\\' + path . slice ( last ) ; rootEnd = j ; } else if ( j !== last ) { device = '\\\\' + firstPart + '\\' + path . slice ( last , j ) ; rootEnd = j ; } } } } else { rootEnd = 1 ; } } else if ( isWindowsDeviceRoot ( code ) ) { if ( path . charCodeAt ( 1 ) === CHAR_COLON ) { device = path . slice ( 0 , 2 ) ; rootEnd = 2 ; if ( len > 2 ) { if ( isPathSeparator ( path . charCodeAt ( 2 ) ) ) { isAbsolute = true ; rootEnd = 3 ; } } } } } else if ( isPathSeparator ( code ) ) { rootEnd = 1 ; isAbsolute = true ; } if ( device . length > 0 && resolvedDevice . length > 0 && device . toLowerCase ( ) !== resolvedDevice . toLowerCase ( ) ) { continue ; } if ( resolvedDevice . length === 0 && device . length > 0 ) { resolvedDevice = device ; } if ( ! resolvedAbsolute ) { resolvedTail = path . slice ( rootEnd ) + '\\' + resolvedTail ; resolvedAbsolute = isAbsolute ; } if ( resolvedDevice . length > 0 && resolvedAbsolute ) { break ; } } resolvedTail = normalizeString ( resolvedTail , ! resolvedAbsolute , '\\' , isPathSeparator ) ; return resolvedDevice + ( resolvedAbsolute ? '\\' : '' ) + resolvedTail || '.' ; } , normalize ( path ) { validateString ( path , 'path' ) ; const len = path . length ; if ( len === 0 ) { return '.' ; } let rootEnd = 0 ; let device ; let isAbsolute = false ; const code = path . charCodeAt ( 0 ) ; if ( len > 1 ) { if ( isPathSeparator ( code ) ) { isAbsolute = true ; if ( isPathSeparator ( path . charCodeAt ( 1 ) ) ) { let j = 2 ; let last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { const firstPart = path . slice ( last , j ) ; last = j ; for ( ; j < len ; ++ j ) { if ( ! isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j === len ) { return '\\\\' + firstPart + '\\' + path . slice ( last ) + '\\' ; } else if ( j !== last ) { device = '\\\\' + firstPart + '\\' + path . slice ( last , j ) ; rootEnd = j ; } } } } else { rootEnd = 1 ; } } else if ( isWindowsDeviceRoot ( code ) ) { if ( path . charCodeAt ( 1 ) === CHAR_COLON ) { device = path . slice ( 0 , 2 ) ; rootEnd = 2 ; if ( len > 2 ) { if ( isPathSeparator ( path . charCodeAt ( 2 ) ) ) { isAbsolute = true ; rootEnd = 3 ; } } } } } else if ( isPathSeparator ( code ) ) { return '\\' ; } let tail ; if ( rootEnd < len ) { tail = normalizeString ( path . slice ( rootEnd ) , ! isAbsolute , '\\' , isPathSeparator ) ; } else { tail = '' ; } if ( tail . length === 0 && ! isAbsolute ) { tail = '.' ; } if ( tail . length > 0 && isPathSeparator ( path . charCodeAt ( len - 1 ) ) ) { tail += '\\' ; } if ( device === undefined ) { if ( isAbsolute ) { if ( tail . length > 0 ) { return '\\' + tail ; } else { return '\\' ; } } else if ( tail . length > 0 ) { return tail ; } else { return '' ; } } else if ( isAbsolute ) { if ( tail . length > 0 ) { return device + '\\' + tail ; } else { return device + '\\' ; } } else if ( tail . length > 0 ) { return device + tail ; } else { return device ; } } , isAbsolute ( path ) { validateString ( path , 'path' ) ; const len = path . length ; if ( len === 0 ) { return false ; } const code = path . charCodeAt ( 0 ) ; if ( isPathSeparator ( code ) ) { return true ; } else if ( isWindowsDeviceRoot ( code ) ) { if ( len > 2 && path . charCodeAt ( 1 ) === CHAR_COLON ) { if ( isPathSeparator ( path . charCodeAt ( 2 ) ) ) { return true ; } } } return false ; } , join ( ... paths ) { if ( paths . length === 0 ) { return '.' ; } let joined ; let firstPart ; for ( let i = 0 ; i < paths . length ; ++ i ) { let arg = paths [ i ] ; validateString ( arg , 'path' ) ; if ( arg . length > 0 ) { if ( joined === undefined ) { joined = firstPart = arg ; } else { joined += '\\' + arg ; } } } if ( joined === undefined ) { return '.' ; } let needsReplace = true ; let slashCount = 0 ; if ( isPathSeparator ( ( firstPart as string ) . charCodeAt ( 0 ) ) ) { ++ slashCount ; const firstLen = ( firstPart as string ) . length ; if ( firstLen > 1 ) { if ( isPathSeparator ( ( firstPart as string ) . charCodeAt ( 1 ) ) ) { ++ slashCount ; if ( firstLen > 2 ) { if ( isPathSeparator ( ( firstPart as string ) . charCodeAt ( 2 ) ) ) { ++ slashCount ; } else { needsReplace = false ; } } } } } if ( needsReplace ) { for ( ; slashCount < joined . length ; ++ slashCount ) { if ( ! isPathSeparator ( joined . charCodeAt ( slashCount ) ) ) { break ; } } if ( slashCount >= 2 ) { joined = '\\' + joined . slice ( slashCount ) ; } } return win32 . normalize ( joined ) ; } , relative ( from , to ) { validateString ( from , 'from' ) ; validateString ( to , 'to' ) ; if ( from === to ) { return '' ; } let fromOrig = win32 . resolve ( from ) ; let toOrig = win32 . resolve ( to ) ; if ( fromOrig === toOrig ) { return '' ; } from = fromOrig . toLowerCase ( ) ; to = toOrig . toLowerCase ( ) ; if ( from === to ) { return '' ; } let fromStart = 0 ; for ( ; fromStart < from . length ; ++ fromStart ) { if ( from . charCodeAt ( fromStart ) !== CHAR_BACKWARD_SLASH ) { break ; } } let fromEnd = from . length ; for ( ; fromEnd - 1 > fromStart ; -- fromEnd ) { if ( from . charCodeAt ( fromEnd - 1 ) !== CHAR_BACKWARD_SLASH ) { break ; } } let fromLen = fromEnd - fromStart ; let toStart = 0 ; for ( ; toStart < to . length ; ++ toStart ) { if ( to . charCodeAt ( toStart ) !== CHAR_BACKWARD_SLASH ) { break ; } } let toEnd = to . length ; for ( ; toEnd - 1 > toStart ; -- toEnd ) { if ( to . charCodeAt ( toEnd - 1 ) !== CHAR_BACKWARD_SLASH ) { break ; } } let toLen = toEnd - toStart ; let length = fromLen < toLen ? fromLen : toLen ; let lastCommonSep = - 1 ; let i = 0 ; for ( ; i <= length ; ++ i ) { if ( i === length ) { if ( toLen > length ) { if ( to . charCodeAt ( toStart + i ) === CHAR_BACKWARD_SLASH ) { return toOrig . slice ( toStart + i + 1 ) ; } else if ( i === 2 ) { return toOrig . slice ( toStart + i ) ; } } if ( fromLen > length ) { if ( from . charCodeAt ( fromStart + i ) === CHAR_BACKWARD_SLASH ) { lastCommonSep = i ; } else if ( i === 2 ) { lastCommonSep = 3 ; } } break ; } let fromCode = from . charCodeAt ( fromStart + i ) ; let toCode = to . charCodeAt ( toStart + i ) ; if ( fromCode !== toCode ) { break ; } else if ( fromCode === CHAR_BACKWARD_SLASH ) { lastCommonSep = i ; } } if ( i !== length && lastCommonSep === - 1 ) { return toOrig ; } let out = '' ; if ( lastCommonSep === - 1 ) { lastCommonSep = 0 ; } for ( i = fromStart + lastCommonSep + 1 ; i <= fromEnd ; ++ i ) { if ( i === fromEnd || from . charCodeAt ( i ) === CHAR_BACKWARD_SLASH ) { if ( out . length === 0 ) { out += '..' ; } else { out += '\\..' ; } } } if ( out . length > 0 ) { return out + toOrig . slice ( toStart + lastCommonSep , toEnd ) ; } else { toStart += lastCommonSep ; if ( toOrig . charCodeAt ( toStart ) === CHAR_BACKWARD_SLASH ) { ++ toStart ; } return toOrig . slice ( toStart , toEnd ) ; } } , toNamespacedPath ( path ) { if ( typeof path !== 'string' ) { return path ; } if ( path . length === 0 ) { return '' ; } const resolvedPath = win32 . resolve ( path ) ; if ( resolvedPath . length >= 3 ) { if ( resolvedPath . charCodeAt ( 0 ) === CHAR_BACKWARD_SLASH ) { if ( resolvedPath . charCodeAt ( 1 ) === CHAR_BACKWARD_SLASH ) { const code = resolvedPath . charCodeAt ( 2 ) ; if ( code !== CHAR_QUESTION_MARK && code !== CHAR_DOT ) { return '\\\\?\\UNC\\' + resolvedPath . slice ( 2 ) ; } } } else if ( isWindowsDeviceRoot ( resolvedPath . charCodeAt ( 0 ) ) ) { if ( resolvedPath . charCodeAt ( 1 ) === CHAR_COLON && resolvedPath . charCodeAt ( 2 ) === CHAR_BACKWARD_SLASH ) { return '\\\\?\\' + resolvedPath ; } } } return path ; } , dirname ( path ) { validateString ( path , 'path' ) ; const len = path . length ; if ( len === 0 ) { return '.' ; } let rootEnd = - 1 ; let end = - 1 ; let matchedSlash = true ; let offset = 0 ; const code = path . charCodeAt ( 0 ) ; if ( len > 1 ) { if ( isPathSeparator ( code ) ) { rootEnd = offset = 1 ; if ( isPathSeparator ( path . charCodeAt ( 1 ) ) ) { let j = 2 ; let last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { last = j ; for ( ; j < len ; ++ j ) { if ( ! isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j === len ) { return path ; } if ( j !== last ) { rootEnd = offset = j + 1 ; } } } } } else if ( isWindowsDeviceRoot ( code ) ) { if ( path . charCodeAt ( 1 ) === CHAR_COLON ) { rootEnd = offset = 2 ; if ( len > 2 ) { if ( isPathSeparator ( path . charCodeAt ( 2 ) ) ) { rootEnd = offset = 3 ; } } } } } else if ( isPathSeparator ( code ) ) { return path ; } for ( let i = len - 1 ; i >= offset ; -- i ) { if ( isPathSeparator ( path . charCodeAt ( i ) ) ) { if ( ! matchedSlash ) { end = i ; break ; } } else { matchedSlash = false ; } } if ( end === - 1 ) { if ( rootEnd === - 1 ) { return '.' ; } else { end = rootEnd ; } } return path . slice ( 0 , end ) ; } , basename ( path , ext ? ) { if ( ext !== undefined ) { validateString ( ext , 'ext' ) ; } validateString ( path , 'path' ) ; let start = 0 ; let end = - 1 ; let matchedSlash = true ; let i ; if ( path . length >= 2 ) { const drive = path . charCodeAt ( 0 ) ; if ( isWindowsDeviceRoot ( drive ) ) { if ( path . charCodeAt ( 1 ) === CHAR_COLON ) { start = 2 ; } } } if ( ext !== undefined && ext . length > 0 && ext . length <= path . length ) { if ( ext . length === path . length && ext === path ) { return '' ; } let extIdx = ext . length - 1 ; let firstNonSlashEnd = - 1 ; for ( i = path . length - 1 ; i >= start ; -- i ) { const code = path . charCodeAt ( i ) ; if ( isPathSeparator ( code ) ) { if ( ! matchedSlash ) { start = i + 1 ; break ; } } else { if ( firstNonSlashEnd === - 1 ) { matchedSlash = false ; firstNonSlashEnd = i + 1 ; } if ( extIdx >= 0 ) { if ( code === ext . 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 . slice ( start , end ) ; } else { for ( i = path . length - 1 ; i >= start ; -- i ) { if ( isPathSeparator ( path . charCodeAt ( i ) ) ) { if ( ! matchedSlash ) { start = i + 1 ; break ; } } else if ( end === - 1 ) { matchedSlash = false ; end = i + 1 ; } } if ( end === - 1 ) { return '' ; } return path . slice ( start , end ) ; } } , extname ( path ) { validateString ( path , 'path' ) ; let start = 0 ; let startDot = - 1 ; let startPart = 0 ; let end = - 1 ; let matchedSlash = true ; let preDotState = 0 ; if ( path . length >= 2 && path . charCodeAt ( 1 ) === CHAR_COLON && isWindowsDeviceRoot ( path . charCodeAt ( 0 ) ) ) { start = startPart = 2 ; } for ( let i = path . length - 1 ; i >= start ; -- i ) { const code = path . charCodeAt ( i ) ; if ( isPathSeparator ( code ) ) { 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 . slice ( startDot , end ) ; } , format ( pathObject ) { if ( pathObject === null || typeof pathObject !== 'object' ) { throw new ErrorInvalidArgType ( 'pathObject' , 'Object' , pathObject ) ; } return _format ( '\\' , pathObject ) ; } , parse ( path ) { validateString ( path , 'path' ) ; let ret = { root : '' , dir : '' , base : '' , ext : '' , name : '' } ; if ( path . length === 0 ) { return ret ; } let len = path . length ; let rootEnd = 0 ; let code = path . charCodeAt ( 0 ) ; if ( len > 1 ) { if ( isPathSeparator ( code ) ) { rootEnd = 1 ; if ( isPathSeparator ( path . charCodeAt ( 1 ) ) ) { let j = 2 ; let last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { last = j ; for ( ; j < len ; ++ j ) { if ( ! isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j < len && j !== last ) { last = j ; for ( ; j < len ; ++ j ) { if ( isPathSeparator ( path . charCodeAt ( j ) ) ) { break ; } } if ( j === len ) { rootEnd = j ; } else if ( j !== last ) { rootEnd = j + 1 ; } } } } } else if ( isWindowsDeviceRoot ( code ) ) { if ( path . charCodeAt ( 1 ) === CHAR_COLON ) { rootEnd = 2 ; if ( len > 2 ) { if ( isPathSeparator ( path . charCodeAt ( 2 ) ) ) { if ( len === 3 ) { ret . root = ret . dir = path ; return ret ; } rootEnd = 3 ; } } else { ret . root = ret . dir = path ; return ret ; } } } } else if ( isPathSeparator ( code ) ) { ret . root = ret . dir = path ; return ret ; } if ( rootEnd > 0 ) { ret . root = path . slice ( 0 , rootEnd ) ; } let startDot = - 1 ; let startPart = rootEnd ; let end = - 1 ; let matchedSlash = true ; let i = path . length - 1 ; let preDotState = 0 ; for ( ; i >= rootEnd ; -- i ) { code = path . charCodeAt ( i ) ; if ( isPathSeparator ( code ) ) { 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 ) ) { if ( end !== - 1 ) { ret . base = ret . name = path . slice ( startPart , end ) ; } } else { ret . name = path . slice ( startPart , startDot ) ; ret . base = path . slice ( startPart , end ) ; ret . ext = path . slice ( startDot , end ) ; } if ( startPart > 0 && startPart !== rootEnd ) { ret . dir = path . slice ( 0 , startPart - 1 ) ; } else { ret . dir = ret . root ; } return ret ; } , sep : '\\' , delimiter : ';' , win32 : null , posix : null , } ; const posix = { resolve ( ... pathSegments ) { let resolvedPath = '' ; let resolvedAbsolute = false ; for ( let i = pathSegments . length - 1 ; i >= - 1 && ! resolvedAbsolute ; i -- ) { let path ; if ( i >= 0 ) { path = pathSegments [ i ] ; } else { path = safeProcess . cwd ( ) ; } validateString ( path , 'path' ) ; if ( path . length === 0 ) { continue ; } resolvedPath = path + '/' + resolvedPath ; resolvedAbsolute = path . charCodeAt ( 0 ) === CHAR_FORWARD_SLASH ; } resolvedPath = normalizeString ( resolvedPath , ! resolvedAbsolute , '/' , isPosixPathSeparator ) ; if ( resolvedAbsolute ) { if ( resolvedPath . length > 0 ) { return '/' + resolvedPath ; } else { return '/' ; } } else if ( resolvedPath . length > 0 ) { return resolvedPath ; } else { return '.' ; } } , normalize ( path ) { validateString ( path , '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 && ! isAbsolute ) { path = '.' ; } if ( path . length > 0 && trailingSeparator ) { path += '/' ; } if ( isAbsolute ) { return '/' + path ; } return path ; } , isAbsolute ( path ) { validateString ( path , 'path' ) ; return path . length > 0 && path . charCodeAt ( 0 ) === CHAR_FORWARD_SLASH ; } , join ( ... paths ) { if ( paths . length === 0 ) { return '.' ; } let joined ; for ( let i = 0 ; i < paths . length ; ++ i ) { let arg = arguments [ i ] ; validateString ( arg , 'path' ) ; if ( arg . length > 0 ) { if ( joined === undefined ) { joined = arg ; } else { joined += '/' + arg ; } } } if ( joined === undefined ) { return '.' ; } return posix . normalize ( joined ) ; } , relative ( from , to ) { validateString ( from , 'from' ) ; validateString ( to , 'to' ) ; if ( from === to ) { return '' ; } from = posix . resolve ( from ) ; to = posix . resolve ( to ) ; if ( from === to ) { return '' ; } let fromStart = 1 ; for ( ; fromStart < from . length ; ++ fromStart ) { if ( from . charCodeAt ( fromStart ) !== CHAR_FORWARD_SLASH ) { break ; } } let fromEnd = from . length ; let fromLen = fromEnd - fromStart ; let toStart = 1 ; for ( ; toStart < to . length ; ++ toStart ) { if ( to . charCodeAt ( toStart ) !== CHAR_FORWARD_SLASH ) { break ; } } let toEnd = to . length ; let toLen = toEnd - toStart ; let length = fromLen < toLen ? fromLen : toLen ; let lastCommonSep = - 1 ; let i = 0 ; for ( ; i <= length ; ++ i ) { if ( i === length ) { if ( toLen > length ) { if ( to . charCodeAt ( toStart + i ) === CHAR_FORWARD_SLASH ) { return to . slice ( toStart + i + 1 ) ; } else if ( i === 0 ) { return to . slice ( toStart + i ) ; } } else if ( fromLen > length ) { if ( from . charCodeAt ( fromStart + i ) === CHAR_FORWARD_SLASH ) { lastCommonSep = i ; } else if ( i === 0 ) { lastCommonSep = 0 ; } } break ; } let fromCode = from . charCodeAt ( fromStart + i ) ; let toCode = to . charCodeAt ( toStart + i ) ; if ( fromCode !== toCode ) { break ; } else if ( fromCode === CHAR_FORWARD_SLASH ) { lastCommonSep = i ; } } let out = '' ; for ( i = fromStart + lastCommonSep + 1 ; i <= fromEnd ; ++ i ) { if ( i === fromEnd || from . charCodeAt ( i ) === CHAR_FORWARD_SLASH ) { if ( out . length === 0 ) { out += '..' ; } else { out += '/..' ; } } } if ( out . length > 0 ) { return out + to . slice ( toStart + lastCommonSep ) ; } else { toStart += lastCommonSep ; if ( to . charCodeAt ( toStart ) === CHAR_FORWARD_SLASH ) { ++ toStart ; } return to . slice ( toStart ) ; } } , toNamespacedPath ( path ) { return path ; } , dirname ( path ) { validateString ( path , '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 . slice ( 0 , end ) ; } , basename ( path , ext ? ) { if ( ext !== undefined ) { validateString ( ext , 'ext' ) ; } validateString ( path , 'path' ) ; let start = 0 ; let end = - 1 ; let matchedSlash = true ; let i ; if ( ext !== undefined && ext . length > 0 && ext . length <= path . length ) { if ( ext . length === path . length && ext === path ) { return '' ; } let extIdx = ext . length - 1 ; let firstNonSlashEnd = - 1 ; for ( 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 === ext . 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 . slice ( start , end ) ; } else { for ( 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 . slice ( start , end ) ; } } , extname ( path ) { validateString ( path , '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 . slice ( startDot , end ) ; } , format ( pathObject ) { if ( pathObject === null || typeof pathObject !== 'object' ) { throw new ErrorInvalidArgType ( 'pathObject' , 'Object' , pathObject ) ; } return _format ( '/' , pathObject ) ; } , parse ( path ) { validateString ( path , 'path' ) ; let ret = { root : '' , dir : '' , base : '' , ext : '' , name : '' } ; if ( path . length === 0 ) { return ret ; } let isAbsolute = path . charCodeAt ( 0 ) === CHAR_FORWARD_SLASH ; let start ; if ( isAbsolute ) { ret . root = '/' ; start = 1 ; } else { start = 0 ; } let startDot = - 1 ; let startPart = 0 ; let end = - 1 ; let matchedSlash = true ; let i = path . length - 1 ; let preDotState = 0 ; for ( ; i >= start ; -- 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 ) ) { if ( end !== - 1 ) { if ( startPart === 0 && isAbsolute ) { ret . base = ret . name = path . slice ( 1 , end ) ; } else { ret . base = ret . name = path . slice ( startPart , end ) ; } } } else { if ( startPart === 0 && isAbsolute ) { ret . name = path . slice ( 1 , startDot ) ; ret . base = path . slice ( 1 , end ) ; } else { ret . name = path . slice ( startPart , startDot ) ; ret . base = path . slice ( startPart , end ) ; } ret . ext = path . slice ( startDot , end ) ; } if ( startPart > 0 ) { ret . dir = path . slice ( 0 , startPart - 1 ) ; } else if ( isAbsolute ) { ret . dir = '/' ; } return ret ; } , sep : '/' , delimiter : ':' , win32 : null , posix : null , } ; posix . win32 = win32 . win32 = win32 ; posix . posix = win32 . posix = posix ; const impl = ( safeProcess . platform === 'win32' ? win32 : posix ) as IExportedPath ; export default impl ;