import { h } from "tsx-dom" ; import { RuleTableRow } from "./ruleTableRow" ; import { getDomain } from "tldjs" ; import { settings } from "../../lib/settings" ; import { removeAllChildren , translateChildren , on } from "../../lib/htmlUtils" ; import { messageUtil } from "../../lib/messageUtil" ; import { wetLayer } from "wet-layer" ; import { RuleDefinition } from "../../lib/settingsSignature" ; import "./style.scss" ; interface RuleTableProps { headerI18n : string ; forDomain ? : string ; filterInput ? : HTMLInputElement ; } function sortByRule ( a , b ) { if ( a . rule < b . rule ) return - 1 ; else if ( a . rule > b . rule ) return 1 ; return 0 ; } function rebuildRows ( tbody , forDomain ? , filterInput ? ) { removeAllChildren ( tbody ) ; let rules ; let chosenRulesForDomain ; if ( forDomain ) { chosenRulesForDomain = settings . getChosenRulesForDomain ( forDomain ) ; const domainFP = getDomain ( forDomain ) || forDomain ; const expressions = [ "*." + domainFP ] ; if ( domainFP !== forDomain ) expressions . push ( "*." + forDomain ) ; expressions . forEach ( ( expression ) => { const chosenRule = chosenRulesForDomain . find ( ( r ) => r . rule === expression ) ; const temporary = ( chosenRule && chosenRule . temporary ) || false ; tbody . appendChild ( < RuleTableRow expression = { expression } isChosen = { ! ! chosenRule } type = { settings . getExactCleanupType ( expression ) } temporary = { temporary } / > ) ; } ) ; rules = settings . getRulesForDomain ( forDomain ) . filter ( ( rule ) => expressions . indexOf ( rule . rule ) === - 1 ) ; } else { chosenRulesForDomain = [ ] ; rules = settings . get ( "rules" ) . slice ( ) ; } for ( const rule of rules ) rule . rule = rule . rule . toLowerCase ( ) ; rules . sort ( sortByRule ) ; rules . forEach ( ( rule ) => { const isChosen = chosenRulesForDomain . some ( ( r ) => r . rule === rule . rule ) ; tbody . appendChild ( < RuleTableRow expression = { rule . rule } isChosen = { isChosen } type = { rule . type } temporary = { rule . temporary } / > ) ; } ) ; translateChildren ( tbody ) ; applyFilter ( tbody , filterInput ) ; } function applyFilter ( tbody , filterInput ? ) { if ( filterInput ) { const value = filterInput . value . trim ( ) . toLowerCase ( ) ; for ( const tr of tbody . querySelectorAll ( "tr" ) ) { const visible = ! value || tr . textContent && tr . textContent . indexOf ( value ) !== - 1 ; tr . classList . toggle ( "is-filtered" , ! visible ) ; } } updateIsNotEmpty ( tbody ) ; } function updateIsNotEmpty ( tbody ) { tbody . className = tbody . querySelector ( "tr:not(.is-filtered)" ) ? "is-not-empty" : "" ; } export function RuleTable ( { headerI18n , forDomain , filterInput } ) { const tbody = < tbody aria - live = "polite" / > ; messageUtil . receive ( "settingsChanged" , ( changedKeys ) => { if ( changedKeys . indexOf ( "rules" ) !== - 1 ) rebuildRows ( tbody , forDomain , filterInput ) ; } ) ; wetLayer . addListener ( ( ) => rebuildRows ( tbody , forDomain , filterInput ) ) ; rebuildRows ( tbody , forDomain , filterInput ) ; if ( filterInput ) on ( filterInput , "input" , ( ) => applyFilter ( tbody , filterInput ) ) ; const className = "rules_table" + ( forDomain ? " rules_table_for_domain" : "" ) ; return < table class = { className } > < thead > < tr > < th data - i18n = { headerI18n } /> < th data - i18n = "rules_column_type" class = "rules_column_type" / > < th /> < /tr> < /thead> { tbody } < tbody class = "no_entries_label" > < tr > < td colSpan = { 3 } data - i18n = "rules_no_entries" > < /td></tr > < /tbody> < /table>; }