import normalizePath from 'normalize-path' ; import Qs from 'querystring' ; class ParsedPath { constructor ( public readonly root , public readonly dirs , public readonly query ? , public readonly filename ? ) { } private indexOfDir ( match , fromIndex = 0 ) { for ( let i = fromIndex ; i < this . dirs . length ; i ++ ) { if ( this . matchDir ( i , match ) ) { return i ; } } return - 1 ; } private matchDir ( i , match ) { return typeof match === 'string' ? this . dirs [ i ] === match : match . test ( this . dirs [ i ] ) ; } matchDirs ( ... segments ) { const [ first , ... rest ] = segments ; let fromIndex = 0 ; while ( true ) { const startIndex = this . indexOfDir ( first , fromIndex ) ; if ( startIndex === - 1 ) { return ; } if ( ! rest . length || rest . every ( ( seg , i ) => this . matchDir ( startIndex + 1 + i , seg ) ) ) { return { startIndex , endIndex : startIndex + rest . length } ; } fromIndex = startIndex + 1 ; } } } /**
 * Parse an absolute path, supporting normalized paths from webpack,
 * into a list of directories and root
 */ export function parseDirPath ( path ) { const filePath = parseFilePath ( path ) ; return new ParsedPath ( filePath . root , [ ... filePath . dirs , ... ( filePath . filename ? [ filePath . filename ] : [ ] ) ] , filePath . query , undefined ) ; } export function parseFilePath ( path ) { let normalized = normalizePath ( path ) ; let query ; const queryIndex = normalized . indexOf ( '?' ) ; if ( queryIndex !== - 1 ) { query = Qs . parse ( normalized . slice ( queryIndex + 1 ) ) ; normalized = normalized . slice ( 0 , queryIndex ) ; } const [ root , ... others ] = normalized . split ( '/' ) ; return new ParsedPath ( root === '' ? '/' : root , others . slice ( 0 , - 1 ) , query , others [ others . length - 1 ] || undefined ) ; }