import { promises as fs } from 'fs' ; import { join } from 'path' ; import { fullLists , CosmeticFilter , detectFilterType , NetworkFilter , FilterType , } from '../adblocker' ; class Counter < K > { private counter : Map < K , number > ; constructor ( ) { this . counter = new Map < K , number > ( ) ; } public incr ( key ) { this . counter . set ( key , ( this . counter . get ( key ) || 0 ) + 1 ) ; } public get ( key ) { return this . counter . get ( key ) || 0 ; } public set ( key , value ) { this . counter . set ( key , value ) ; } public entries ( ) { return Array . from ( this . counter . entries ( ) ) ; } } const PREFIX = 'https://raw.githubusercontent.com/cliqz-oss/adblocker/master/packages/adblocker/assets' ; async function loadAllLists ( ) { return ( await Promise . all ( fullLists . map ( ( path ) => join ( __dirname , '..' , 'assets' , path . slice ( PREFIX . length ) ) ) . map ( ( path ) => fs . readFile ( path , 'utf-8' ) ) ) ) . join ( '\n' ) ; } ( async ( ) => { let numberOfFiltersSupported = 0 ; let numberOfFiltersUnsupported = 0 ; const unsupported = new Counter ( ) ; for ( const line of ( await loadAllLists ( ) ) . split ( /\s*[\r\n]+\s*/g ) ) { switch ( detectFilterType ( line ) ) { case FilterType . NETWORK : { if ( NetworkFilter . parse ( line ) === null ) { numberOfFiltersUnsupported += 1 ; const optionStart = line . lastIndexOf ( '$' ) ; if ( optionStart === - 1 ) { unsupported . incr ( line ) ; continue ; } if ( NetworkFilter . parse ( line . slice ( 0 , optionStart ) ) === null ) { unsupported . incr ( line ) ; continue ; } let found = false ; const options = line . slice ( optionStart + 1 ) . split ( ',' ) ; for ( const option of options ) { if ( NetworkFilter . parse ( `${ line . slice ( 0 , optionStart ) }$${ option }` ) === null ) { found = true ; unsupported . incr ( option ) ; } } if ( found === false ) { unsupported . incr ( line ) ; } } else { numberOfFiltersSupported += 1 ; } break ; } case FilterType . COSMETIC : { if ( CosmeticFilter . parse ( line ) === null ) { numberOfFiltersUnsupported += 1 ; let indexOfColon = line . indexOf ( ':' ) ; let strippedFilter = line ; let found = false ; while ( indexOfColon !== - 1 ) { const indexOfParenthesis = strippedFilter . indexOf ( '(' , indexOfColon ) ; if ( indexOfParenthesis !== - 1 ) { const operator = strippedFilter . slice ( indexOfColon , indexOfParenthesis ) ; if ( /^:[a-z-]+$/ . test ( operator ) ) { const filterWithoutOperator = `${ strippedFilter . slice ( 0 , indexOfColon ) }${ strippedFilter . slice ( indexOfParenthesis ) }` ; unsupported . incr ( operator ) ; if ( CosmeticFilter . parse ( filterWithoutOperator ) !== null ) { found = true ; break ; } strippedFilter = filterWithoutOperator ; } } indexOfColon = strippedFilter . indexOf ( ':' , indexOfColon + 1 ) ; } if ( found === false ) { unsupported . incr ( line ) ; } } else { numberOfFiltersSupported += 1 ; } break ; } default : { if ( line . length !== 0 && line . startsWith ( '!' ) === false && line . startsWith ( '[Adblock' ) === false ) { numberOfFiltersUnsupported += 1 ; const indexOfSharp = line . indexOf ( '#' ) ; if ( indexOfSharp !== - 1 && line . startsWith ( '#?#' , indexOfSharp ) ) { unsupported . incr ( '#?#' ) ; } else { unsupported . incr ( line ) ; } } break ; } } } for ( const [ name , count ] of unsupported . entries ( ) . sort ( ( [ _1 , c1 ] , [ _2 , c2 ] ) => c2 - c1 ) ) { console . log ( `+ ${ name } = ${ count }` ) ; } console . log ( { numberOfFiltersSupported , numberOfFiltersUnsupported , percentage : 100 - 100.0 * ( numberOfFiltersUnsupported / numberOfFiltersSupported ) , } ) ; } ) ( ) ;