const MIN_WH = 'minWH' ; const MIN_W = 'minW' ; const MIN_H = 'minH' ; const PRIORITY_STEP = 10000 ; /**
 * Used with qualifier matchers and module resolution
 */ export interface PlatformContext { width : number ; height : number ; os : string ; deviceType : string ; } interface QualifierSpec { isMatch ( path ) : boolean ; getMatchOccurences ( path ) : Array < string > ; getMatchValue ( value , context ) : number ; } const minWidthHeightQualifier = { isMatch : function ( path ) : boolean { return new RegExp ( `.${ MIN_WH }\\d+` ) . test ( path ) ; } , getMatchOccurences : function ( path ) : Array < string > { return path . match ( new RegExp ( `.${ MIN_WH }\\d+` , 'g' ) ) ; } , getMatchValue ( value , context ) { const numVal = parseInt ( value . substr ( MIN_WH . length + 1 ) ) ; if ( isNaN ( numVal ) ) { return - 1 ; } const actualLength = Math . min ( context . width , context . height ) ; if ( actualLength < numVal ) { return - 1 ; } return PRIORITY_STEP - ( actualLength - numVal ) ; } , } ; const minWidthQualifier = { isMatch : function ( path ) : boolean { return new RegExp ( `.${ MIN_W }\\d+` ) . test ( path ) && ! new RegExp ( `.${ MIN_WH }\\d+` ) . test ( path ) ; } , getMatchOccurences : function ( path ) : Array < string > { return path . match ( new RegExp ( `.${ MIN_W }\\d+` , 'g' ) ) ; } , getMatchValue ( value , context ) { const numVal = parseInt ( value . substr ( MIN_W . length + 1 ) ) ; if ( isNaN ( numVal ) ) { return - 1 ; } const actualWidth = context . width ; if ( actualWidth < numVal ) { return - 1 ; } return PRIORITY_STEP - ( actualWidth - numVal ) ; } , } ; const minHeightQualifier = { isMatch : function ( path ) : boolean { return new RegExp ( `.${ MIN_H }\\d+` ) . test ( path ) && ! new RegExp ( `.${ MIN_WH }\\d+` ) . test ( path ) ; } , getMatchOccurences : function ( path ) : Array < string > { return path . match ( new RegExp ( `.${ MIN_H }\\d+` , 'g' ) ) ; } , getMatchValue ( value , context ) { const numVal = parseInt ( value . substr ( MIN_H . length + 1 ) ) ; if ( isNaN ( numVal ) ) { return - 1 ; } const actualHeight = context . height ; if ( actualHeight < numVal ) { return - 1 ; } return PRIORITY_STEP - ( actualHeight - numVal ) ; } , } ; const platformQualifier = { isMatch : function ( path ) : boolean { return path . includes ( '.android' ) || path . includes ( '.ios' ) ; } , getMatchOccurences : function ( path ) : Array < string > { return path . match ( new RegExp ( '\\.android|\\.ios' , 'g' ) ) ; } , getMatchValue ( value , context ) { const val = value . substr ( 1 ) ; return val === context . os . toLowerCase ( ) ? 1 : - 1 ; } , } ; const orientationQualifier = { isMatch : function ( path ) : boolean { return path . includes ( '.land' ) || path . includes ( '.port' ) ; } , getMatchOccurences : function ( path ) : Array < string > { return path . match ( new RegExp ( '\\.land|\\.port' , 'g' ) ) ; } , getMatchValue ( value , context ) { const val = value . substr ( 1 ) ; const isLandscape = context . width > context . height ? 1 : - 1 ; return val === 'land' ? isLandscape : - isLandscape ; } , } ; const supportedQualifiers = [ minWidthHeightQualifier , minWidthQualifier , minHeightQualifier , orientationQualifier , platformQualifier ] ; function checkQualifiers ( path , context ) { let result = 0 ; for ( let i = 0 ; i < supportedQualifiers . length ; i ++ ) { const qualifier = supportedQualifiers [ i ] ; if ( qualifier . isMatch ( path ) ) { const occurences = qualifier . getMatchOccurences ( path ) ; result = qualifier . getMatchValue ( occurences [ occurences . length - 1 ] , context ) ; if ( result < 0 ) { return - 1 ; } result += ( supportedQualifiers . length - i ) * PRIORITY_STEP ; return result ; } } return result ; } export function stripQualifiers ( path ) { for ( let i = 0 ; i < supportedQualifiers . length ; i ++ ) { const qualifier = supportedQualifiers [ i ] ; if ( qualifier . isMatch ( path ) ) { const occurences = qualifier . getMatchOccurences ( path ) ; for ( let j = 0 ; j < occurences . length ; j ++ ) { path = path . replace ( occurences [ j ] , '' ) ; } } } return path ; } export function findMatch ( path , ext , candidates , context ) { const fullPath = ext ? path + ext : path ; let bestValue = - 1 ; let result = null ; for ( let i = 0 ; i < candidates . length ; i ++ ) { const filePath = candidates [ i ] ; const cleanFilePath = stripQualifiers ( filePath ) ; if ( cleanFilePath !== fullPath ) { continue ; } const value = checkQualifiers ( filePath , context ) ; if ( value >= 0 && value > bestValue ) { bestValue = value ; result = candidates [ i ] ; } } return result ; }