import { isWindows } from './platform' ; import { startsWithIgnoreCase , equalsIgnoreCase } from './strings' ; import { CharCode } from './charCode' ; /**
 * The forward slash path separator.
 */ export const sep = '/' ; /**
 * The native path separator depending on the OS.
 */ export const nativeSep = isWindows ? '\\' : '/' ; param path param separator returns export function dirname ( path , separator = nativeSep ) { const idx = ~ path . lastIndexOf ( '/' ) || ~ path . lastIndexOf ( '\\' ) ; if ( idx === 0 ) { return '.' ; } else if ( ~ idx === 0 ) { return path [ 0 ] ; } else if ( ~ idx === path . length - 1 ) { return dirname ( path . substring ( 0 , path . length - 1 ) ) ; } else { let res = path . substring ( 0 , ~ idx ) ; if ( isWindows && res [ res . length - 1 ] === ':' ) { res += separator ; } return res ; } } returns export function basename ( path ) { const idx = ~ path . lastIndexOf ( '/' ) || ~ path . lastIndexOf ( '\\' ) ; if ( idx === 0 ) { return path ; } else if ( ~ idx === path . length - 1 ) { return basename ( path . substring ( 0 , path . length - 1 ) ) ; } else { return path . substr ( ~ idx + 1 ) ; } } returns export function extname ( path ) { path = basename ( path ) ; const idx = ~ path . lastIndexOf ( '.' ) ; return idx ? path . substring ( ~ idx ) : '' ; } const _posixBadPath = /(\/\.\.?\/)|(\/\.\.?)$|^(\.\.?\/)|(\/\/+)|(\\)/ ; const _winBadPath = /(\\\.\.?\\)|(\\\.\.?)$|^(\.\.?\\)|(\\\\+)|(\/)/ ; function _isNormal ( path , win ) { return win ? ! _winBadPath . test ( path ) : ! _posixBadPath . test ( path ) ; } export function normalize ( path , toOSPath ? ) { if ( path === null || path === void 0 ) { return path ; } const len = path . length ; if ( len === 0 ) { return '.' ; } const wantsBackslash = ! ! ( isWindows && toOSPath ) ; if ( _isNormal ( path , wantsBackslash ) ) { return path ; } const sep = wantsBackslash ? '\\' : '/' ; const root = getRoot ( path , sep ) ; let start = root . length ; let skip = false ; let res = '' ; for ( let end = root . length ; end <= len ; end ++ ) { if ( end === len || path . charCodeAt ( end ) === CharCode . Slash || path . charCodeAt ( end ) === CharCode . Backslash ) { if ( streql ( path , start , end , '..' ) ) { let prev_start = res . lastIndexOf ( sep ) ; let prev_part = res . slice ( prev_start + 1 ) ; if ( ( root || prev_part . length > 0 ) && prev_part !== '..' ) { res = prev_start === - 1 ? '' : res . slice ( 0 , prev_start ) ; skip = true ; } } else if ( streql ( path , start , end , '.' ) && ( root || res || end < len - 1 ) ) { skip = true ; } if ( ! skip ) { let part = path . slice ( start , end ) ; if ( res !== '' && res [ res . length - 1 ] !== sep ) { res += sep ; } res += part ; } start = end + 1 ; skip = false ; } } return root + res ; } function streql ( value , start , end , other ) { return start + other . length === end && value . indexOf ( other , start ) === start ; } /**
 * Computes the _root_ this path, like `getRoot('c:\files') === c:\`,
 * `getRoot('files:///files/path') === files:///`,
 * or `getRoot('\\server\shares\path') === \\server\shares\`
 */ export function getRoot ( path , sep = '/' ) { if ( ! path ) { return '' ; } let len = path . length ; let code = path . charCodeAt ( 0 ) ; if ( code === CharCode . Slash || code === CharCode . Backslash ) { code = path . charCodeAt ( 1 ) ; if ( code === CharCode . Slash || code === CharCode . Backslash ) { code = path . charCodeAt ( 2 ) ; if ( code !== CharCode . Slash && code !== CharCode . Backslash ) { let pos = 3 ; let start = pos ; for ( ; pos < len ; pos ++ ) { code = path . charCodeAt ( pos ) ; if ( code === CharCode . Slash || code === CharCode . Backslash ) { break ; } } code = path . charCodeAt ( pos + 1 ) ; if ( start !== pos && code !== CharCode . Slash && code !== CharCode . Backslash ) { pos += 1 ; for ( ; pos < len ; pos ++ ) { code = path . charCodeAt ( pos ) ; if ( code === CharCode . Slash || code === CharCode . Backslash ) { return path . slice ( 0 , pos + 1 ) . replace ( /[\\/]/g , sep ) ; } } } } } return sep ; } else if ( ( code >= CharCode . A && code <= CharCode . Z ) || ( code >= CharCode . a && code <= CharCode . z ) ) { if ( path . charCodeAt ( 1 ) === CharCode . Colon ) { code = path . charCodeAt ( 2 ) ; if ( code === CharCode . Slash || code === CharCode . Backslash ) { return path . slice ( 0 , 2 ) + sep ; } else { return path . slice ( 0 , 2 ) ; } } } let pos = path . indexOf ( '://' ) ; if ( pos !== - 1 ) { pos += 3 ; for ( ; pos < len ; pos ++ ) { code = path . charCodeAt ( pos ) ; if ( code === CharCode . Slash || code === CharCode . Backslash ) { return path . slice ( 0 , pos + 1 ) ; } } } return '' ; } export const join = function ( ) { let value = '' ; for ( let i = 0 ; i < arguments . length ; i ++ ) { let part = arguments [ i ] ; if ( i > 0 ) { let last = value . charCodeAt ( value . length - 1 ) ; if ( last !== CharCode . Slash && last !== CharCode . Backslash ) { let next = part . charCodeAt ( 0 ) ; if ( next !== CharCode . Slash && next !== CharCode . Backslash ) { value += sep ; } } } value += part ; } return normalize ( value ) ; } ; see https return export function isUNC ( path ) { if ( ! isWindows ) { return false ; } if ( ! path || path . length < 5 ) { return false ; } let code = path . charCodeAt ( 0 ) ; if ( code !== CharCode . Backslash ) { return false ; } code = path . charCodeAt ( 1 ) ; if ( code !== CharCode . Backslash ) { return false ; } let pos = 2 ; let start = pos ; for ( ; pos < path . length ; pos ++ ) { code = path . charCodeAt ( pos ) ; if ( code === CharCode . Backslash ) { break ; } } if ( start === pos ) { return false ; } code = path . charCodeAt ( pos + 1 ) ; if ( isNaN ( code ) || code === CharCode . Backslash ) { return false ; } return true ; } const INVALID_FILE_CHARS = isWindows ? /[\\/:\*\?"<>\|]/g : /[\\/]/g ; const WINDOWS_FORBIDDEN_NAMES = /^(con|prn|aux|clock\$|nul|lpt[0-9]|com[0-9])$/i ; export function isValidBasename ( name ) { if ( ! name || name . length === 0 || /^\s+$/ . test ( name ) ) { return false ; } INVALID_FILE_CHARS . lastIndex = 0 ; if ( INVALID_FILE_CHARS . test ( name ) ) { return false ; } if ( isWindows && WINDOWS_FORBIDDEN_NAMES . test ( name ) ) { return false ; } if ( name === '.' || name === '..' ) { return false ; } if ( isWindows && name [ name . length - 1 ] === '.' ) { return false ; } if ( isWindows && name . length !== name . trim ( ) . length ) { return false ; } return true ; } export function isEqual ( pathA , pathB , ignoreCase ? ) { const identityEquals = ( pathA === pathB ) ; if ( ! ignoreCase || identityEquals ) { return identityEquals ; } if ( ! pathA || ! pathB ) { return false ; } return equalsIgnoreCase ( pathA , pathB ) ; } export function isEqualOrParent ( path , candidate , ignoreCase ? , separator = nativeSep ) { if ( path === candidate ) { return true ; } if ( ! path || ! candidate ) { return false ; } if ( candidate . length > path . length ) { return false ; } if ( ignoreCase ) { const beginsWith = startsWithIgnoreCase ( path , candidate ) ; if ( ! beginsWith ) { return false ; } if ( candidate . length === path . length ) { return true ; } let sepOffset = candidate . length ; if ( candidate . charAt ( candidate . length - 1 ) === separator ) { sepOffset -- ; } return path . charAt ( sepOffset ) === separator ; } if ( candidate . charAt ( candidate . length - 1 ) !== separator ) { candidate += separator ; } return path . indexOf ( candidate ) === 0 ; } /**
 * Adapted from Node's path.isAbsolute functions
 */ export function isAbsolute ( path ) { return isWindows ? isAbsolute_win32 ( path ) : isAbsolute_posix ( path ) ; } export function isAbsolute_win32 ( path ) { if ( ! path ) { return false ; } const char0 = path . charCodeAt ( 0 ) ; if ( char0 === CharCode . Slash || char0 === CharCode . Backslash ) { return true ; } else if ( ( char0 >= CharCode . A && char0 <= CharCode . Z ) || ( char0 >= CharCode . a && char0 <= CharCode . z ) ) { if ( path . length > 2 && path . charCodeAt ( 1 ) === CharCode . Colon ) { const char2 = path . charCodeAt ( 2 ) ; if ( char2 === CharCode . Slash || char2 === CharCode . Backslash ) { return true ; } } } return false ; } export function isAbsolute_posix ( path ) { return ! ! ( path && path . charCodeAt ( 0 ) === CharCode . Slash ) ; }