@@ -249,6 +249,54 @@ const isGood = rule =>
249
249
250
250
/******************************************************************************/
251
251
252
+ // Two distinct hostnames:
253
+ // www.example.com
254
+ // example.com
255
+ // Can be reduced to a single one:
256
+ // example.com
257
+ // Since if example.com matches, then www.example.com (or any other subdomain
258
+ // of example.com) will always match.
259
+
260
+ function pruneHostnameArray ( hostnames ) {
261
+ const rootMap = new Map ( ) ;
262
+ for ( const hostname of hostnames ) {
263
+ const labels = hostname . split ( '.' ) ;
264
+ let currentMap = rootMap ;
265
+ let i = labels . length ;
266
+ while ( i -- ) {
267
+ const label = labels [ i ] ;
268
+ let nextMap = currentMap . get ( label ) ;
269
+ if ( nextMap === null ) { break ; }
270
+ if ( nextMap === undefined ) {
271
+ if ( i === 0 ) {
272
+ currentMap . set ( label , ( nextMap = null ) ) ;
273
+ } else {
274
+ currentMap . set ( label , ( nextMap = new Map ( ) ) ) ;
275
+ }
276
+ } else if ( i === 0 ) {
277
+ currentMap . set ( label , null ) ;
278
+ }
279
+ currentMap = nextMap ;
280
+ }
281
+ }
282
+ const assemble = ( currentMap , currentHostname , out ) => {
283
+ for ( const [ label , nextMap ] of currentMap ) {
284
+ const nextHostname = currentHostname === ''
285
+ ? label
286
+ : `${ label } .${ currentHostname } ` ;
287
+ if ( nextMap === null ) {
288
+ out . push ( nextHostname ) ;
289
+ } else {
290
+ assemble ( nextMap , nextHostname , out ) ;
291
+ }
292
+ }
293
+ return out ;
294
+ } ;
295
+ return assemble ( rootMap , '' , [ ] ) ;
296
+ }
297
+
298
+ /******************************************************************************/
299
+
252
300
async function processNetworkFilters ( assetDetails , network ) {
253
301
const replacer = ( k , v ) => {
254
302
if ( k . startsWith ( '_' ) ) { return ; }
@@ -271,6 +319,37 @@ async function processNetworkFilters(assetDetails, network) {
271
319
log ( `\tRejected filter count: ${ network . rejectedFilterCount } ` ) ;
272
320
log ( `Output rule count: ${ rules . length } ` ) ;
273
321
322
+ // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/RuleCondition#browser_compatibility
323
+ // isUrlFilterCaseSensitive is false by default in Firefox. It will be
324
+ // false by default in Chromium 118+.
325
+ if ( platform === 'firefox' ) {
326
+ for ( const rule of rules ) {
327
+ if ( rule . condition === undefined ) { continue ; }
328
+ if ( rule . condition . urlFilter === undefined ) {
329
+ if ( rule . condition . regexFilter === undefined ) { continue ; }
330
+ }
331
+ if ( rule . condition . isUrlFilterCaseSensitive === undefined ) {
332
+ rule . condition . isUrlFilterCaseSensitive = true ;
333
+ } else if ( rule . condition . isUrlFilterCaseSensitive === false ) {
334
+ rule . condition . isUrlFilterCaseSensitive = undefined ;
335
+ }
336
+ }
337
+ }
338
+
339
+ // Minimize requestDomains arrays
340
+ for ( const rule of rules ) {
341
+ const condition = rule . condition ;
342
+ if ( condition === undefined ) { continue ; }
343
+ const requestDomains = condition . requestDomains ;
344
+ if ( requestDomains === undefined ) { continue ; }
345
+ const beforeCount = requestDomains . length ;
346
+ condition . requestDomains = pruneHostnameArray ( requestDomains ) ;
347
+ const afterCount = condition . requestDomains . length ;
348
+ if ( afterCount !== beforeCount ) {
349
+ log ( `\tPruning requestDomains: from ${ beforeCount } to ${ afterCount } ` ) ;
350
+ }
351
+ }
352
+
274
353
const plainGood = rules . filter ( rule => isGood ( rule ) && isRegex ( rule ) === false ) ;
275
354
log ( `\tPlain good: ${ plainGood . length } ` ) ;
276
355
log ( plainGood
@@ -314,9 +393,11 @@ async function processNetworkFilters(assetDetails, network) {
314
393
log ( `\tUnsupported: ${ bad . length } ` ) ;
315
394
log ( bad . map ( rule => rule . _error . map ( v => `\t\t${ v } ` ) ) . join ( '\n' ) , true ) ;
316
395
396
+ const jsonIndent = platform !== 'firefox' ? 1 : undefined ;
397
+
317
398
writeFile (
318
399
`${ rulesetDir } /main/${ assetDetails . id } .json` ,
319
- `${ JSON . stringify ( plainGood , replacer , 1 ) } \n`
400
+ `${ JSON . stringify ( plainGood , replacer , jsonIndent ) } \n`
320
401
) ;
321
402
322
403
if ( regexes . length !== 0 ) {
0 commit comments