import { memoize } from '../../esl-utils/decorators/memoize' ; import { ExportNs } from '../../esl-utils/environment/export-ns' ; import { ESLScreenDPR } from './common/screen-dpr' ; import { ESLScreenBreakpoints } from './common/screen-breakpoint' ; import { ESLEnvShortcuts } from './common/env-shortcuts' ; import { ALL , NOT_ALL } from './conditions/media-query-base' ; import { MediaQueryCondition } from './conditions/media-query-condition' ; import { MediaQueryConjunction , MediaQueryDisjunction } from './conditions/media-query-containers' ; import type { IMediaQueryCondition } from './conditions/media-query-base' ; export interface IMediaQueryPreprocessor { process : ( match : string ) => string | boolean | undefined ; } author @ ExportNs ( 'MediaQuery' ) export abstract class ESLMediaQuery implements IMediaQueryCondition { /** Always true condition */ public static readonly ALL : IMediaQueryCondition = ALL ; /** Always false condition */ public static readonly NOT_ALL : IMediaQueryCondition = NOT_ALL ; protected static readonly SHORTCUT_PATTERN = /@([a-z0-9.+-]+)/i ; protected static readonly _preprocessors : IMediaQueryPreprocessor [ ] = [ ] ; /** Add  IMediaQueryPreprocessor instance for query preprocessing step  public static use ( preprocessor ) { this . _preprocessors . unshift ( preprocessor ) ; return this ; } /** Cached method to create  ESLMediaQuery condition instance from query string  @ memoize ( ) public static for ( query ) { return ESLMediaQuery . from ( query ) ; } /** Creates  ESLMediaQuery condition instance from query string  public static from ( query ) { const conjunctions = query . split ( /\sor\s|,/ ) . map ( ( term ) => { const conditions = term . split ( /\sand\s/ ) . map ( ESLMediaQuery . parseSimpleQuery ) ; return new MediaQueryConjunction ( conditions ) ; } ) ; return new MediaQueryDisjunction ( conjunctions ) . optimize ( ) ; } /** Preprocess simple query term by applying replacers and shortcuts rules */ protected static preprocess ( term ) { if ( ! this . SHORTCUT_PATTERN . test ( term ) ) return term ; const shortcut = term . trim ( ) . substring ( 1 ) . toLowerCase ( ) ; for ( const replacer of this . _preprocessors ) { const result = replacer . process ( shortcut ) ; if ( typeof result === 'string' ) return result ; if ( typeof result === 'boolean' ) return result ? 'all' : 'not all' ; } return term ; } /** Creates simple  ESLMediaQuery condition  protected static parseSimpleQuery ( term ) { const query = term . replace ( /^\s*not\s+/ , '' ) ; const queryInverted = query !== term ; const processedQuery = ESLMediaQuery . preprocess ( query ) ; const sanitizedQuery = processedQuery . replace ( /^\s*not\s+/ , '' ) ; const resultInverted = processedQuery !== sanitizedQuery ; const invert = queryInverted !== resultInverted ; if ( ALL . eq ( sanitizedQuery ) ) return invert ? NOT_ALL : ALL ; if ( NOT_ALL . eq ( sanitizedQuery ) ) return invert ? ALL : NOT_ALL ; return new MediaQueryCondition ( sanitizedQuery , invert ) ; } public abstract matches : boolean ; public abstract optimize ( ) ; public abstract addListener ( cb ) ; public abstract removeListener ( cb ) ; public abstract toString ( ) ; } ESLMediaQuery . use ( ESLScreenDPR ) ; ESLMediaQuery . use ( ESLScreenBreakpoints ) ; ESLMediaQuery . use ( ESLEnvShortcuts ) ; declare global { export interface ESLLibrary { MediaQuery : typeof ESLMediaQuery ; } }