@adguard/agtree 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/agtree.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * AGTree v2.0.0 (build date: Thu, 15 Aug 2024 15:06:58 GMT)
2
+ * AGTree v2.0.1 (build date: Fri, 06 Sep 2024 12:11:38 GMT)
3
3
  * (c) 2024 Adguard Software Ltd.
4
4
  * Released under the MIT license
5
5
  * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
@@ -212,6 +212,7 @@ const NUMBERS = new Set([NUMBER_0, NUMBER_1, NUMBER_2, NUMBER_3, NUMBER_4, NUMBE
212
212
  const REGEX_MARKER = '/';
213
213
  const ADG_SCRIPTLET_MASK = '//scriptlet';
214
214
  const UBO_SCRIPTLET_MASK = '+js';
215
+ const UBO_SCRIPTLET_MASK_LEGACY = 'script:inject';
215
216
  const UBO_HTML_MASK = '^';
216
217
  // Modifiers are separated by ",". For example: "script,domain=example.com"
217
218
  const MODIFIERS_SEPARATOR = ',';
@@ -1148,6 +1149,15 @@ const isUndefined = value => {
1148
1149
  const isNull = value => {
1149
1150
  return value === null;
1150
1151
  };
1152
+ /**
1153
+ * Checks whether the given value is a string.
1154
+ *
1155
+ * @param value Value to check.
1156
+ * @returns `true` if the value is a string, `false` otherwise.
1157
+ */
1158
+ const isString = value => {
1159
+ return typeof value === 'string';
1160
+ };
1151
1161
  /**
1152
1162
  * Checks whether the given value is an array of Uint8Arrays.
1153
1163
  *
@@ -6338,11 +6348,17 @@ class UboScriptletInjectionBodyParser extends ParserBase {
6338
6348
  let offset = 0;
6339
6349
  // Skip leading spaces
6340
6350
  offset = StringUtils.skipWS(raw, offset);
6351
+ let scriptletMaskLength = 0;
6352
+ if (raw.startsWith(UBO_SCRIPTLET_MASK, offset)) {
6353
+ scriptletMaskLength = UBO_SCRIPTLET_MASK.length;
6354
+ } else if (raw.startsWith(UBO_SCRIPTLET_MASK_LEGACY, offset)) {
6355
+ scriptletMaskLength = UBO_SCRIPTLET_MASK_LEGACY.length;
6356
+ }
6341
6357
  // Scriptlet call should start with "+js"
6342
- if (!raw.startsWith(UBO_SCRIPTLET_MASK, offset)) {
6358
+ if (!scriptletMaskLength) {
6343
6359
  throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_SCRIPTLET_MASK, baseOffset + offset, baseOffset + raw.length);
6344
6360
  }
6345
- offset += UBO_SCRIPTLET_MASK.length;
6361
+ offset += scriptletMaskLength;
6346
6362
  // Whitespace is not allowed after the mask
6347
6363
  if (raw[offset] === SPACE) {
6348
6364
  throw new AdblockSyntaxError(this.ERROR_MESSAGES.WHITESPACE_AFTER_MASK, baseOffset + offset, baseOffset + raw.length);
@@ -6387,6 +6403,7 @@ class UboScriptletInjectionBodyParser extends ParserBase {
6387
6403
  if (node.children.length > 1) {
6388
6404
  throw new Error(this.ERROR_MESSAGES.NO_MULTIPLE_SCRIPTLET_CALLS);
6389
6405
  }
6406
+ // During generation, we only support the modern scriptlet mask
6390
6407
  result.push(UBO_SCRIPTLET_MASK);
6391
6408
  result.push(OPEN_PARENTHESIS);
6392
6409
  if (node.children.length > 0) {
@@ -6924,7 +6941,7 @@ class CosmeticRuleParser extends ParserBase {
6924
6941
  };
6925
6942
  };
6926
6943
  const parseUboScriptletInjection = () => {
6927
- if (!rawBody.startsWith(UBO_SCRIPTLET_MASK)) {
6944
+ if (!rawBody.startsWith(UBO_SCRIPTLET_MASK) && !rawBody.startsWith(UBO_SCRIPTLET_MASK_LEGACY)) {
6928
6945
  return null;
6929
6946
  }
6930
6947
  if (!options.parseUboSpecificRules) {
@@ -13879,7 +13896,8 @@ const redirectsCompatibilityTableData = {
13879
13896
  deprecationMessage: null,
13880
13897
  removed: false,
13881
13898
  removalMessage: null,
13882
- isBlocking: false
13899
+ isBlocking: false,
13900
+ resourceTypes: []
13883
13901
  }, {
13884
13902
  name: "1x1.gif",
13885
13903
  aliases: null,
@@ -13891,7 +13909,8 @@ const redirectsCompatibilityTableData = {
13891
13909
  deprecationMessage: null,
13892
13910
  removed: false,
13893
13911
  removalMessage: null,
13894
- isBlocking: false
13912
+ isBlocking: false,
13913
+ resourceTypes: ["image"]
13895
13914
  }, {
13896
13915
  name: "1x1-transparent-gif",
13897
13916
  aliases: null,
@@ -13903,7 +13922,8 @@ const redirectsCompatibilityTableData = {
13903
13922
  deprecationMessage: null,
13904
13923
  removed: false,
13905
13924
  removalMessage: null,
13906
- isBlocking: false
13925
+ isBlocking: false,
13926
+ resourceTypes: []
13907
13927
  }],
13908
13928
  map: {
13909
13929
  "1": 0,
@@ -13934,7 +13954,8 @@ const redirectsCompatibilityTableData = {
13934
13954
  deprecationMessage: null,
13935
13955
  removed: false,
13936
13956
  removalMessage: null,
13937
- isBlocking: false
13957
+ isBlocking: false,
13958
+ resourceTypes: []
13938
13959
  }, {
13939
13960
  name: "2x2.png",
13940
13961
  aliases: null,
@@ -13946,7 +13967,8 @@ const redirectsCompatibilityTableData = {
13946
13967
  deprecationMessage: null,
13947
13968
  removed: false,
13948
13969
  removalMessage: null,
13949
- isBlocking: false
13970
+ isBlocking: false,
13971
+ resourceTypes: ["image"]
13950
13972
  }, {
13951
13973
  name: "2x2-transparent-png",
13952
13974
  aliases: null,
@@ -13958,7 +13980,8 @@ const redirectsCompatibilityTableData = {
13958
13980
  deprecationMessage: null,
13959
13981
  removed: false,
13960
13982
  removalMessage: null,
13961
- isBlocking: false
13983
+ isBlocking: false,
13984
+ resourceTypes: []
13962
13985
  }],
13963
13986
  map: {
13964
13987
  "1": 0,
@@ -13989,7 +14012,8 @@ const redirectsCompatibilityTableData = {
13989
14012
  deprecationMessage: null,
13990
14013
  removed: false,
13991
14014
  removalMessage: null,
13992
- isBlocking: false
14015
+ isBlocking: false,
14016
+ resourceTypes: []
13993
14017
  }, {
13994
14018
  name: "32x32.png",
13995
14019
  aliases: null,
@@ -14001,7 +14025,8 @@ const redirectsCompatibilityTableData = {
14001
14025
  deprecationMessage: null,
14002
14026
  removed: false,
14003
14027
  removalMessage: null,
14004
- isBlocking: false
14028
+ isBlocking: false,
14029
+ resourceTypes: ["image"]
14005
14030
  }, {
14006
14031
  name: "32x32-transparent-png",
14007
14032
  aliases: null,
@@ -14013,7 +14038,8 @@ const redirectsCompatibilityTableData = {
14013
14038
  deprecationMessage: null,
14014
14039
  removed: false,
14015
14040
  removalMessage: null,
14016
- isBlocking: false
14041
+ isBlocking: false,
14042
+ resourceTypes: []
14017
14043
  }],
14018
14044
  map: {
14019
14045
  "1": 0,
@@ -14044,7 +14070,8 @@ const redirectsCompatibilityTableData = {
14044
14070
  deprecationMessage: null,
14045
14071
  removed: false,
14046
14072
  removalMessage: null,
14047
- isBlocking: false
14073
+ isBlocking: false,
14074
+ resourceTypes: []
14048
14075
  }, {
14049
14076
  name: "3x2.png",
14050
14077
  aliases: null,
@@ -14056,7 +14083,8 @@ const redirectsCompatibilityTableData = {
14056
14083
  deprecationMessage: null,
14057
14084
  removed: false,
14058
14085
  removalMessage: null,
14059
- isBlocking: false
14086
+ isBlocking: false,
14087
+ resourceTypes: ["image"]
14060
14088
  }, {
14061
14089
  name: "3x2-transparent-png",
14062
14090
  aliases: null,
@@ -14068,7 +14096,8 @@ const redirectsCompatibilityTableData = {
14068
14096
  deprecationMessage: null,
14069
14097
  removed: false,
14070
14098
  removalMessage: null,
14071
- isBlocking: false
14099
+ isBlocking: false,
14100
+ resourceTypes: []
14072
14101
  }],
14073
14102
  map: {
14074
14103
  "1": 0,
@@ -14099,7 +14128,8 @@ const redirectsCompatibilityTableData = {
14099
14128
  deprecationMessage: null,
14100
14129
  removed: false,
14101
14130
  removalMessage: null,
14102
- isBlocking: false
14131
+ isBlocking: false,
14132
+ resourceTypes: []
14103
14133
  }, {
14104
14134
  name: "amazon_apstag.js",
14105
14135
  aliases: null,
@@ -14111,7 +14141,8 @@ const redirectsCompatibilityTableData = {
14111
14141
  deprecationMessage: null,
14112
14142
  removed: false,
14113
14143
  removalMessage: null,
14114
- isBlocking: false
14144
+ isBlocking: false,
14145
+ resourceTypes: ["script"]
14115
14146
  }],
14116
14147
  map: {
14117
14148
  "1": 0,
@@ -14138,7 +14169,8 @@ const redirectsCompatibilityTableData = {
14138
14169
  deprecationMessage: null,
14139
14170
  removed: false,
14140
14171
  removalMessage: null,
14141
- isBlocking: false
14172
+ isBlocking: false,
14173
+ resourceTypes: ["script"]
14142
14174
  }],
14143
14175
  map: {
14144
14176
  "1024": 0,
@@ -14158,7 +14190,8 @@ const redirectsCompatibilityTableData = {
14158
14190
  deprecationMessage: null,
14159
14191
  removed: false,
14160
14192
  removalMessage: null,
14161
- isBlocking: false
14193
+ isBlocking: false,
14194
+ resourceTypes: ["script"]
14162
14195
  }],
14163
14196
  map: {
14164
14197
  "1024": 0,
@@ -14178,7 +14211,8 @@ const redirectsCompatibilityTableData = {
14178
14211
  deprecationMessage: null,
14179
14212
  removed: false,
14180
14213
  removalMessage: null,
14181
- isBlocking: false
14214
+ isBlocking: false,
14215
+ resourceTypes: []
14182
14216
  }],
14183
14217
  map: {
14184
14218
  "1": 0,
@@ -14201,7 +14235,8 @@ const redirectsCompatibilityTableData = {
14201
14235
  deprecationMessage: null,
14202
14236
  removed: false,
14203
14237
  removalMessage: null,
14204
- isBlocking: false
14238
+ isBlocking: false,
14239
+ resourceTypes: ["script"]
14205
14240
  }],
14206
14241
  map: {
14207
14242
  "1024": 0,
@@ -14221,7 +14256,8 @@ const redirectsCompatibilityTableData = {
14221
14256
  deprecationMessage: null,
14222
14257
  removed: false,
14223
14258
  removalMessage: null,
14224
- isBlocking: true
14259
+ isBlocking: true,
14260
+ resourceTypes: []
14225
14261
  }, {
14226
14262
  name: "click2load.html",
14227
14263
  aliases: null,
@@ -14233,7 +14269,8 @@ const redirectsCompatibilityTableData = {
14233
14269
  deprecationMessage: null,
14234
14270
  removed: false,
14235
14271
  removalMessage: null,
14236
- isBlocking: true
14272
+ isBlocking: true,
14273
+ resourceTypes: []
14237
14274
  }],
14238
14275
  map: {
14239
14276
  "1": 0,
@@ -14260,7 +14297,8 @@ const redirectsCompatibilityTableData = {
14260
14297
  deprecationMessage: null,
14261
14298
  removed: false,
14262
14299
  removalMessage: null,
14263
- isBlocking: false
14300
+ isBlocking: false,
14301
+ resourceTypes: []
14264
14302
  }],
14265
14303
  map: {
14266
14304
  "1": 0,
@@ -14283,7 +14321,8 @@ const redirectsCompatibilityTableData = {
14283
14321
  deprecationMessage: null,
14284
14322
  removed: false,
14285
14323
  removalMessage: null,
14286
- isBlocking: false
14324
+ isBlocking: false,
14325
+ resourceTypes: []
14287
14326
  }, {
14288
14327
  name: "empty",
14289
14328
  aliases: null,
@@ -14295,7 +14334,8 @@ const redirectsCompatibilityTableData = {
14295
14334
  deprecationMessage: null,
14296
14335
  removed: false,
14297
14336
  removalMessage: null,
14298
- isBlocking: false
14337
+ isBlocking: false,
14338
+ resourceTypes: []
14299
14339
  }],
14300
14340
  map: {
14301
14341
  "1": 0,
@@ -14322,7 +14362,8 @@ const redirectsCompatibilityTableData = {
14322
14362
  deprecationMessage: null,
14323
14363
  removed: false,
14324
14364
  removalMessage: null,
14325
- isBlocking: false
14365
+ isBlocking: false,
14366
+ resourceTypes: []
14326
14367
  }, {
14327
14368
  name: "fingerprint2.js",
14328
14369
  aliases: null,
@@ -14334,7 +14375,8 @@ const redirectsCompatibilityTableData = {
14334
14375
  deprecationMessage: null,
14335
14376
  removed: false,
14336
14377
  removalMessage: null,
14337
- isBlocking: false
14378
+ isBlocking: false,
14379
+ resourceTypes: ["script"]
14338
14380
  }],
14339
14381
  map: {
14340
14382
  "1": 0,
@@ -14361,7 +14403,8 @@ const redirectsCompatibilityTableData = {
14361
14403
  deprecationMessage: null,
14362
14404
  removed: false,
14363
14405
  removalMessage: null,
14364
- isBlocking: false
14406
+ isBlocking: false,
14407
+ resourceTypes: []
14365
14408
  }, {
14366
14409
  name: "fingerprint3.js",
14367
14410
  aliases: null,
@@ -14373,7 +14416,8 @@ const redirectsCompatibilityTableData = {
14373
14416
  deprecationMessage: null,
14374
14417
  removed: false,
14375
14418
  removalMessage: null,
14376
- isBlocking: false
14419
+ isBlocking: false,
14420
+ resourceTypes: ["script"]
14377
14421
  }],
14378
14422
  map: {
14379
14423
  "1": 0,
@@ -14400,7 +14444,8 @@ const redirectsCompatibilityTableData = {
14400
14444
  deprecationMessage: null,
14401
14445
  removed: false,
14402
14446
  removalMessage: null,
14403
- isBlocking: false
14447
+ isBlocking: false,
14448
+ resourceTypes: []
14404
14449
  }],
14405
14450
  map: {
14406
14451
  "1": 0,
@@ -14423,7 +14468,8 @@ const redirectsCompatibilityTableData = {
14423
14468
  deprecationMessage: null,
14424
14469
  removed: false,
14425
14470
  removalMessage: null,
14426
- isBlocking: false
14471
+ isBlocking: false,
14472
+ resourceTypes: []
14427
14473
  }, {
14428
14474
  name: "google-analytics_ga.js",
14429
14475
  aliases: null,
@@ -14435,7 +14481,8 @@ const redirectsCompatibilityTableData = {
14435
14481
  deprecationMessage: null,
14436
14482
  removed: false,
14437
14483
  removalMessage: null,
14438
- isBlocking: false
14484
+ isBlocking: false,
14485
+ resourceTypes: ["script"]
14439
14486
  }],
14440
14487
  map: {
14441
14488
  "1": 0,
@@ -14462,7 +14509,8 @@ const redirectsCompatibilityTableData = {
14462
14509
  deprecationMessage: null,
14463
14510
  removed: false,
14464
14511
  removalMessage: null,
14465
- isBlocking: false
14512
+ isBlocking: false,
14513
+ resourceTypes: []
14466
14514
  }, {
14467
14515
  name: "google-analytics_analytics.js",
14468
14516
  aliases: null,
@@ -14474,7 +14522,8 @@ const redirectsCompatibilityTableData = {
14474
14522
  deprecationMessage: null,
14475
14523
  removed: false,
14476
14524
  removalMessage: null,
14477
- isBlocking: false
14525
+ isBlocking: false,
14526
+ resourceTypes: ["script"]
14478
14527
  }],
14479
14528
  map: {
14480
14529
  "1": 0,
@@ -14501,7 +14550,8 @@ const redirectsCompatibilityTableData = {
14501
14550
  deprecationMessage: null,
14502
14551
  removed: false,
14503
14552
  removalMessage: null,
14504
- isBlocking: false
14553
+ isBlocking: false,
14554
+ resourceTypes: ["script"]
14505
14555
  }],
14506
14556
  map: {
14507
14557
  "1024": 0,
@@ -14521,7 +14571,8 @@ const redirectsCompatibilityTableData = {
14521
14571
  deprecationMessage: null,
14522
14572
  removed: false,
14523
14573
  removalMessage: null,
14524
- isBlocking: false
14574
+ isBlocking: false,
14575
+ resourceTypes: ["script"]
14525
14576
  }],
14526
14577
  map: {
14527
14578
  "1024": 0,
@@ -14541,7 +14592,8 @@ const redirectsCompatibilityTableData = {
14541
14592
  deprecationMessage: null,
14542
14593
  removed: false,
14543
14594
  removalMessage: null,
14544
- isBlocking: false
14595
+ isBlocking: false,
14596
+ resourceTypes: []
14545
14597
  }, {
14546
14598
  name: "google-ima.js",
14547
14599
  aliases: null,
@@ -14553,7 +14605,8 @@ const redirectsCompatibilityTableData = {
14553
14605
  deprecationMessage: null,
14554
14606
  removed: false,
14555
14607
  removalMessage: null,
14556
- isBlocking: false
14608
+ isBlocking: false,
14609
+ resourceTypes: ["script"]
14557
14610
  }],
14558
14611
  map: {
14559
14612
  "1": 0,
@@ -14571,7 +14624,7 @@ const redirectsCompatibilityTableData = {
14571
14624
  }, {
14572
14625
  shared: [{
14573
14626
  name: "googlesyndication-adsbygoogle",
14574
- aliases: ["ubo-googlesyndication_adsbygoogle.js", "googlesyndication_adsbygoogle.js"],
14627
+ aliases: ["ubo-googlesyndication_adsbygoogle.js", "ubo-googlesyndication.com/adsbygoogle.js", "googlesyndication_adsbygoogle.js"],
14575
14628
  description: "Mocks Google AdSense API.",
14576
14629
  docs: null,
14577
14630
  versionAdded: null,
@@ -14580,10 +14633,11 @@ const redirectsCompatibilityTableData = {
14580
14633
  deprecationMessage: null,
14581
14634
  removed: false,
14582
14635
  removalMessage: null,
14583
- isBlocking: false
14636
+ isBlocking: false,
14637
+ resourceTypes: []
14584
14638
  }, {
14585
14639
  name: "googlesyndication_adsbygoogle.js",
14586
- aliases: null,
14640
+ aliases: ["googlesyndication.com/adsbygoogle.js"],
14587
14641
  description: "Mocks Google AdSense API.",
14588
14642
  docs: null,
14589
14643
  versionAdded: null,
@@ -14592,7 +14646,8 @@ const redirectsCompatibilityTableData = {
14592
14646
  deprecationMessage: null,
14593
14647
  removed: false,
14594
14648
  removalMessage: null,
14595
- isBlocking: false
14649
+ isBlocking: false,
14650
+ resourceTypes: ["script"]
14596
14651
  }],
14597
14652
  map: {
14598
14653
  "1": 0,
@@ -14619,7 +14674,8 @@ const redirectsCompatibilityTableData = {
14619
14674
  deprecationMessage: null,
14620
14675
  removed: false,
14621
14676
  removalMessage: null,
14622
- isBlocking: false
14677
+ isBlocking: false,
14678
+ resourceTypes: []
14623
14679
  }, {
14624
14680
  name: "googletagservices_gpt.js",
14625
14681
  aliases: null,
@@ -14631,7 +14687,8 @@ const redirectsCompatibilityTableData = {
14631
14687
  deprecationMessage: null,
14632
14688
  removed: false,
14633
14689
  removalMessage: null,
14634
- isBlocking: false
14690
+ isBlocking: false,
14691
+ resourceTypes: ["script"]
14635
14692
  }],
14636
14693
  map: {
14637
14694
  "1": 0,
@@ -14658,7 +14715,8 @@ const redirectsCompatibilityTableData = {
14658
14715
  deprecationMessage: null,
14659
14716
  removed: false,
14660
14717
  removalMessage: null,
14661
- isBlocking: false
14718
+ isBlocking: false,
14719
+ resourceTypes: ["script"]
14662
14720
  }],
14663
14721
  map: {
14664
14722
  "1024": 0,
@@ -14678,7 +14736,8 @@ const redirectsCompatibilityTableData = {
14678
14736
  deprecationMessage: null,
14679
14737
  removed: false,
14680
14738
  removalMessage: null,
14681
- isBlocking: false
14739
+ isBlocking: false,
14740
+ resourceTypes: []
14682
14741
  }],
14683
14742
  map: {
14684
14743
  "1": 0,
@@ -14701,7 +14760,8 @@ const redirectsCompatibilityTableData = {
14701
14760
  deprecationMessage: null,
14702
14761
  removed: false,
14703
14762
  removalMessage: null,
14704
- isBlocking: false
14763
+ isBlocking: false,
14764
+ resourceTypes: []
14705
14765
  }],
14706
14766
  map: {
14707
14767
  "1": 0,
@@ -14724,7 +14784,8 @@ const redirectsCompatibilityTableData = {
14724
14784
  deprecationMessage: null,
14725
14785
  removed: false,
14726
14786
  removalMessage: null,
14727
- isBlocking: false
14787
+ isBlocking: false,
14788
+ resourceTypes: []
14728
14789
  }],
14729
14790
  map: {
14730
14791
  "1": 0,
@@ -14747,7 +14808,8 @@ const redirectsCompatibilityTableData = {
14747
14808
  deprecationMessage: null,
14748
14809
  removed: false,
14749
14810
  removalMessage: null,
14750
- isBlocking: false
14811
+ isBlocking: false,
14812
+ resourceTypes: []
14751
14813
  }],
14752
14814
  map: {
14753
14815
  "1": 0,
@@ -14770,7 +14832,8 @@ const redirectsCompatibilityTableData = {
14770
14832
  deprecationMessage: null,
14771
14833
  removed: false,
14772
14834
  removalMessage: null,
14773
- isBlocking: false
14835
+ isBlocking: false,
14836
+ resourceTypes: []
14774
14837
  }],
14775
14838
  map: {
14776
14839
  "1": 0,
@@ -14793,7 +14856,8 @@ const redirectsCompatibilityTableData = {
14793
14856
  deprecationMessage: null,
14794
14857
  removed: false,
14795
14858
  removalMessage: null,
14796
- isBlocking: false
14859
+ isBlocking: false,
14860
+ resourceTypes: []
14797
14861
  }],
14798
14862
  map: {
14799
14863
  "1": 0,
@@ -14816,7 +14880,8 @@ const redirectsCompatibilityTableData = {
14816
14880
  deprecationMessage: null,
14817
14881
  removed: false,
14818
14882
  removalMessage: null,
14819
- isBlocking: false
14883
+ isBlocking: false,
14884
+ resourceTypes: []
14820
14885
  }, {
14821
14886
  name: "noeval.js",
14822
14887
  aliases: null,
@@ -14828,7 +14893,8 @@ const redirectsCompatibilityTableData = {
14828
14893
  deprecationMessage: null,
14829
14894
  removed: false,
14830
14895
  removalMessage: null,
14831
- isBlocking: false
14896
+ isBlocking: false,
14897
+ resourceTypes: ["script"]
14832
14898
  }],
14833
14899
  map: {
14834
14900
  "1": 0,
@@ -14855,7 +14921,8 @@ const redirectsCompatibilityTableData = {
14855
14921
  deprecationMessage: null,
14856
14922
  removed: false,
14857
14923
  removalMessage: null,
14858
- isBlocking: false
14924
+ isBlocking: false,
14925
+ resourceTypes: ["media"]
14859
14926
  }],
14860
14927
  map: {
14861
14928
  "1024": 0,
@@ -14875,7 +14942,8 @@ const redirectsCompatibilityTableData = {
14875
14942
  deprecationMessage: null,
14876
14943
  removed: false,
14877
14944
  removalMessage: null,
14878
- isBlocking: false
14945
+ isBlocking: false,
14946
+ resourceTypes: []
14879
14947
  }, {
14880
14948
  name: "noop.css",
14881
14949
  aliases: null,
@@ -14887,7 +14955,8 @@ const redirectsCompatibilityTableData = {
14887
14955
  deprecationMessage: null,
14888
14956
  removed: false,
14889
14957
  removalMessage: null,
14890
- isBlocking: false
14958
+ isBlocking: false,
14959
+ resourceTypes: ["stylesheet"]
14891
14960
  }, {
14892
14961
  name: "blank-css",
14893
14962
  aliases: null,
@@ -14899,7 +14968,8 @@ const redirectsCompatibilityTableData = {
14899
14968
  deprecationMessage: null,
14900
14969
  removed: false,
14901
14970
  removalMessage: null,
14902
- isBlocking: false
14971
+ isBlocking: false,
14972
+ resourceTypes: []
14903
14973
  }],
14904
14974
  map: {
14905
14975
  "1": 0,
@@ -14930,7 +15000,8 @@ const redirectsCompatibilityTableData = {
14930
15000
  deprecationMessage: null,
14931
15001
  removed: false,
14932
15002
  removalMessage: null,
14933
- isBlocking: false
15003
+ isBlocking: false,
15004
+ resourceTypes: []
14934
15005
  }, {
14935
15006
  name: "noop.html",
14936
15007
  aliases: null,
@@ -14942,7 +15013,8 @@ const redirectsCompatibilityTableData = {
14942
15013
  deprecationMessage: null,
14943
15014
  removed: false,
14944
15015
  removalMessage: null,
14945
- isBlocking: false
15016
+ isBlocking: false,
15017
+ resourceTypes: ["sub_frame"]
14946
15018
  }, {
14947
15019
  name: "blank-html",
14948
15020
  aliases: null,
@@ -14954,7 +15026,8 @@ const redirectsCompatibilityTableData = {
14954
15026
  deprecationMessage: null,
14955
15027
  removed: false,
14956
15028
  removalMessage: null,
14957
- isBlocking: false
15029
+ isBlocking: false,
15030
+ resourceTypes: []
14958
15031
  }],
14959
15032
  map: {
14960
15033
  "1": 0,
@@ -14985,7 +15058,8 @@ const redirectsCompatibilityTableData = {
14985
15058
  deprecationMessage: null,
14986
15059
  removed: false,
14987
15060
  removalMessage: null,
14988
- isBlocking: false
15061
+ isBlocking: false,
15062
+ resourceTypes: []
14989
15063
  }, {
14990
15064
  name: "noop.js",
14991
15065
  aliases: null,
@@ -14997,7 +15071,8 @@ const redirectsCompatibilityTableData = {
14997
15071
  deprecationMessage: null,
14998
15072
  removed: false,
14999
15073
  removalMessage: null,
15000
- isBlocking: false
15074
+ isBlocking: false,
15075
+ resourceTypes: ["script"]
15001
15076
  }, {
15002
15077
  name: "blank-js",
15003
15078
  aliases: null,
@@ -15009,7 +15084,8 @@ const redirectsCompatibilityTableData = {
15009
15084
  deprecationMessage: null,
15010
15085
  removed: false,
15011
15086
  removalMessage: null,
15012
- isBlocking: false
15087
+ isBlocking: false,
15088
+ resourceTypes: []
15013
15089
  }],
15014
15090
  map: {
15015
15091
  "1": 0,
@@ -15040,7 +15116,8 @@ const redirectsCompatibilityTableData = {
15040
15116
  deprecationMessage: null,
15041
15117
  removed: false,
15042
15118
  removalMessage: null,
15043
- isBlocking: false
15119
+ isBlocking: false,
15120
+ resourceTypes: []
15044
15121
  }, {
15045
15122
  name: "noop.json",
15046
15123
  aliases: null,
@@ -15052,7 +15129,8 @@ const redirectsCompatibilityTableData = {
15052
15129
  deprecationMessage: null,
15053
15130
  removed: false,
15054
15131
  removalMessage: null,
15055
- isBlocking: false
15132
+ isBlocking: false,
15133
+ resourceTypes: []
15056
15134
  }],
15057
15135
  map: {
15058
15136
  "1": 0,
@@ -15079,7 +15157,8 @@ const redirectsCompatibilityTableData = {
15079
15157
  deprecationMessage: null,
15080
15158
  removed: false,
15081
15159
  removalMessage: null,
15082
- isBlocking: false
15160
+ isBlocking: false,
15161
+ resourceTypes: []
15083
15162
  }, {
15084
15163
  name: "noop-0.1s.mp3",
15085
15164
  aliases: null,
@@ -15091,7 +15170,8 @@ const redirectsCompatibilityTableData = {
15091
15170
  deprecationMessage: null,
15092
15171
  removed: false,
15093
15172
  removalMessage: null,
15094
- isBlocking: false
15173
+ isBlocking: false,
15174
+ resourceTypes: ["media"]
15095
15175
  }, {
15096
15176
  name: "blank-mp3",
15097
15177
  aliases: null,
@@ -15103,7 +15183,8 @@ const redirectsCompatibilityTableData = {
15103
15183
  deprecationMessage: null,
15104
15184
  removed: false,
15105
15185
  removalMessage: null,
15106
- isBlocking: false
15186
+ isBlocking: false,
15187
+ resourceTypes: []
15107
15188
  }],
15108
15189
  map: {
15109
15190
  "1": 0,
@@ -15134,7 +15215,8 @@ const redirectsCompatibilityTableData = {
15134
15215
  deprecationMessage: null,
15135
15216
  removed: false,
15136
15217
  removalMessage: null,
15137
- isBlocking: false
15218
+ isBlocking: false,
15219
+ resourceTypes: []
15138
15220
  }, {
15139
15221
  name: "noop-1s.mp4",
15140
15222
  aliases: null,
@@ -15146,7 +15228,8 @@ const redirectsCompatibilityTableData = {
15146
15228
  deprecationMessage: null,
15147
15229
  removed: false,
15148
15230
  removalMessage: null,
15149
- isBlocking: false
15231
+ isBlocking: false,
15232
+ resourceTypes: ["media"]
15150
15233
  }, {
15151
15234
  name: "blank-mp4",
15152
15235
  aliases: null,
@@ -15158,7 +15241,8 @@ const redirectsCompatibilityTableData = {
15158
15241
  deprecationMessage: null,
15159
15242
  removed: false,
15160
15243
  removalMessage: null,
15161
- isBlocking: false
15244
+ isBlocking: false,
15245
+ resourceTypes: []
15162
15246
  }],
15163
15247
  map: {
15164
15248
  "1": 0,
@@ -15189,7 +15273,8 @@ const redirectsCompatibilityTableData = {
15189
15273
  deprecationMessage: null,
15190
15274
  removed: false,
15191
15275
  removalMessage: null,
15192
- isBlocking: false
15276
+ isBlocking: false,
15277
+ resourceTypes: []
15193
15278
  }, {
15194
15279
  name: "noop.txt",
15195
15280
  aliases: null,
@@ -15201,7 +15286,8 @@ const redirectsCompatibilityTableData = {
15201
15286
  deprecationMessage: null,
15202
15287
  removed: false,
15203
15288
  removalMessage: null,
15204
- isBlocking: false
15289
+ isBlocking: false,
15290
+ resourceTypes: ["image", "media", "sub_frame", "stylesheet", "script", "xmlhttprequest", "other"]
15205
15291
  }, {
15206
15292
  name: "blank-text",
15207
15293
  aliases: null,
@@ -15213,7 +15299,8 @@ const redirectsCompatibilityTableData = {
15213
15299
  deprecationMessage: null,
15214
15300
  removed: false,
15215
15301
  removalMessage: null,
15216
- isBlocking: false
15302
+ isBlocking: false,
15303
+ resourceTypes: []
15217
15304
  }],
15218
15305
  map: {
15219
15306
  "1": 0,
@@ -15244,7 +15331,8 @@ const redirectsCompatibilityTableData = {
15244
15331
  deprecationMessage: null,
15245
15332
  removed: false,
15246
15333
  removalMessage: null,
15247
- isBlocking: false
15334
+ isBlocking: false,
15335
+ resourceTypes: []
15248
15336
  }],
15249
15337
  map: {
15250
15338
  "1": 0,
@@ -15267,7 +15355,8 @@ const redirectsCompatibilityTableData = {
15267
15355
  deprecationMessage: null,
15268
15356
  removed: false,
15269
15357
  removalMessage: null,
15270
- isBlocking: false
15358
+ isBlocking: false,
15359
+ resourceTypes: []
15271
15360
  }],
15272
15361
  map: {
15273
15362
  "1": 0,
@@ -15290,7 +15379,8 @@ const redirectsCompatibilityTableData = {
15290
15379
  deprecationMessage: null,
15291
15380
  removed: false,
15292
15381
  removalMessage: null,
15293
- isBlocking: false
15382
+ isBlocking: false,
15383
+ resourceTypes: []
15294
15384
  }],
15295
15385
  map: {
15296
15386
  "1": 0,
@@ -15313,7 +15403,8 @@ const redirectsCompatibilityTableData = {
15313
15403
  deprecationMessage: null,
15314
15404
  removed: false,
15315
15405
  removalMessage: null,
15316
- isBlocking: false
15406
+ isBlocking: false,
15407
+ resourceTypes: []
15317
15408
  }, {
15318
15409
  name: "noop-vmap1.0.xml",
15319
15410
  aliases: null,
@@ -15325,7 +15416,8 @@ const redirectsCompatibilityTableData = {
15325
15416
  deprecationMessage: null,
15326
15417
  removed: false,
15327
15418
  removalMessage: null,
15328
- isBlocking: false
15419
+ isBlocking: false,
15420
+ resourceTypes: ["media"]
15329
15421
  }],
15330
15422
  map: {
15331
15423
  "1": 0,
@@ -15352,7 +15444,8 @@ const redirectsCompatibilityTableData = {
15352
15444
  deprecationMessage: null,
15353
15445
  removed: false,
15354
15446
  removalMessage: null,
15355
- isBlocking: false
15447
+ isBlocking: false,
15448
+ resourceTypes: []
15356
15449
  }, {
15357
15450
  name: "nowebrtc.js",
15358
15451
  aliases: null,
@@ -15364,7 +15457,8 @@ const redirectsCompatibilityTableData = {
15364
15457
  deprecationMessage: null,
15365
15458
  removed: false,
15366
15459
  removalMessage: null,
15367
- isBlocking: false
15460
+ isBlocking: false,
15461
+ resourceTypes: ["other"]
15368
15462
  }],
15369
15463
  map: {
15370
15464
  "1": 0,
@@ -15391,7 +15485,8 @@ const redirectsCompatibilityTableData = {
15391
15485
  deprecationMessage: null,
15392
15486
  removed: false,
15393
15487
  removalMessage: null,
15394
- isBlocking: false
15488
+ isBlocking: false,
15489
+ resourceTypes: ["script"]
15395
15490
  }],
15396
15491
  map: {
15397
15492
  "1024": 0,
@@ -15411,7 +15506,8 @@ const redirectsCompatibilityTableData = {
15411
15506
  deprecationMessage: null,
15412
15507
  removed: false,
15413
15508
  removalMessage: null,
15414
- isBlocking: false
15509
+ isBlocking: false,
15510
+ resourceTypes: []
15415
15511
  }],
15416
15512
  map: {
15417
15513
  "1": 0,
@@ -15434,7 +15530,8 @@ const redirectsCompatibilityTableData = {
15434
15530
  deprecationMessage: null,
15435
15531
  removed: false,
15436
15532
  removalMessage: null,
15437
- isBlocking: false
15533
+ isBlocking: false,
15534
+ resourceTypes: []
15438
15535
  }, {
15439
15536
  name: "prebid-ads.js",
15440
15537
  aliases: null,
@@ -15446,7 +15543,8 @@ const redirectsCompatibilityTableData = {
15446
15543
  deprecationMessage: null,
15447
15544
  removed: false,
15448
15545
  removalMessage: null,
15449
- isBlocking: false
15546
+ isBlocking: false,
15547
+ resourceTypes: ["script"]
15450
15548
  }],
15451
15549
  map: {
15452
15550
  "1": 0,
@@ -15473,7 +15571,8 @@ const redirectsCompatibilityTableData = {
15473
15571
  deprecationMessage: null,
15474
15572
  removed: false,
15475
15573
  removalMessage: null,
15476
- isBlocking: false
15574
+ isBlocking: false,
15575
+ resourceTypes: []
15477
15576
  }],
15478
15577
  map: {
15479
15578
  "1": 0,
@@ -15496,7 +15595,8 @@ const redirectsCompatibilityTableData = {
15496
15595
  deprecationMessage: null,
15497
15596
  removed: false,
15498
15597
  removalMessage: null,
15499
- isBlocking: false
15598
+ isBlocking: false,
15599
+ resourceTypes: []
15500
15600
  }, {
15501
15601
  name: "nobab.js",
15502
15602
  aliases: null,
@@ -15508,7 +15608,8 @@ const redirectsCompatibilityTableData = {
15508
15608
  deprecationMessage: null,
15509
15609
  removed: false,
15510
15610
  removalMessage: null,
15511
- isBlocking: false
15611
+ isBlocking: false,
15612
+ resourceTypes: ["script"]
15512
15613
  }],
15513
15614
  map: {
15514
15615
  "1": 0,
@@ -15535,7 +15636,8 @@ const redirectsCompatibilityTableData = {
15535
15636
  deprecationMessage: null,
15536
15637
  removed: false,
15537
15638
  removalMessage: null,
15538
- isBlocking: false
15639
+ isBlocking: false,
15640
+ resourceTypes: []
15539
15641
  }, {
15540
15642
  name: "nobab2.js",
15541
15643
  aliases: null,
@@ -15547,7 +15649,8 @@ const redirectsCompatibilityTableData = {
15547
15649
  deprecationMessage: null,
15548
15650
  removed: false,
15549
15651
  removalMessage: null,
15550
- isBlocking: false
15652
+ isBlocking: false,
15653
+ resourceTypes: ["script"]
15551
15654
  }],
15552
15655
  map: {
15553
15656
  "1": 0,
@@ -15574,10 +15677,11 @@ const redirectsCompatibilityTableData = {
15574
15677
  deprecationMessage: null,
15575
15678
  removed: false,
15576
15679
  removalMessage: null,
15577
- isBlocking: false
15680
+ isBlocking: false,
15681
+ resourceTypes: []
15578
15682
  }, {
15579
15683
  name: "nofab.js",
15580
- aliases: null,
15684
+ aliases: ["fuckadblock.js-3.2.0", "fuckadblock.js-3.2.0.js"],
15581
15685
  description: "Mocks FAB script v3.2.0.",
15582
15686
  docs: null,
15583
15687
  versionAdded: null,
@@ -15586,7 +15690,8 @@ const redirectsCompatibilityTableData = {
15586
15690
  deprecationMessage: null,
15587
15691
  removed: false,
15588
15692
  removalMessage: null,
15589
- isBlocking: false
15693
+ isBlocking: false,
15694
+ resourceTypes: ["script"]
15590
15695
  }],
15591
15696
  map: {
15592
15697
  "1": 0,
@@ -15613,7 +15718,8 @@ const redirectsCompatibilityTableData = {
15613
15718
  deprecationMessage: null,
15614
15719
  removed: false,
15615
15720
  removalMessage: null,
15616
- isBlocking: false
15721
+ isBlocking: false,
15722
+ resourceTypes: []
15617
15723
  }, {
15618
15724
  name: "popads.js",
15619
15725
  aliases: null,
@@ -15625,7 +15731,8 @@ const redirectsCompatibilityTableData = {
15625
15731
  deprecationMessage: null,
15626
15732
  removed: false,
15627
15733
  removalMessage: null,
15628
- isBlocking: false
15734
+ isBlocking: false,
15735
+ resourceTypes: ["script"]
15629
15736
  }],
15630
15737
  map: {
15631
15738
  "1": 0,
@@ -15652,7 +15759,8 @@ const redirectsCompatibilityTableData = {
15652
15759
  deprecationMessage: null,
15653
15760
  removed: false,
15654
15761
  removalMessage: null,
15655
- isBlocking: false
15762
+ isBlocking: false,
15763
+ resourceTypes: []
15656
15764
  }, {
15657
15765
  name: "scorecardresearch_beacon.js",
15658
15766
  aliases: null,
@@ -15664,7 +15772,8 @@ const redirectsCompatibilityTableData = {
15664
15772
  deprecationMessage: null,
15665
15773
  removed: false,
15666
15774
  removalMessage: null,
15667
- isBlocking: false
15775
+ isBlocking: false,
15776
+ resourceTypes: ["script"]
15668
15777
  }],
15669
15778
  map: {
15670
15779
  "1": 0,
@@ -15691,7 +15800,8 @@ const redirectsCompatibilityTableData = {
15691
15800
  deprecationMessage: null,
15692
15801
  removed: false,
15693
15802
  removalMessage: null,
15694
- isBlocking: false
15803
+ isBlocking: false,
15804
+ resourceTypes: []
15695
15805
  }, {
15696
15806
  name: "popads-dummy.js",
15697
15807
  aliases: null,
@@ -15703,7 +15813,8 @@ const redirectsCompatibilityTableData = {
15703
15813
  deprecationMessage: null,
15704
15814
  removed: false,
15705
15815
  removalMessage: null,
15706
- isBlocking: false
15816
+ isBlocking: false,
15817
+ resourceTypes: ["script"]
15707
15818
  }],
15708
15819
  map: {
15709
15820
  "1": 0,
@@ -15764,7 +15875,9 @@ const redirectsCompatibilityTableData = {
15764
15875
  "google-ima.js": 19,
15765
15876
  "googlesyndication-adsbygoogle": 20,
15766
15877
  "ubo-googlesyndication_adsbygoogle.js": 20,
15878
+ "ubo-googlesyndication.com/adsbygoogle.js": 20,
15767
15879
  "googlesyndication_adsbygoogle.js": 20,
15880
+ "googlesyndication.com/adsbygoogle.js": 20,
15768
15881
  "googletagservices-gpt": 21,
15769
15882
  "ubo-googletagservices_gpt.js": 21,
15770
15883
  "googletagservices_gpt.js": 21,
@@ -15823,6 +15936,8 @@ const redirectsCompatibilityTableData = {
15823
15936
  "nobab2.js": 48,
15824
15937
  "prevent-fab-3.2.0": 49,
15825
15938
  "nofab.js": 49,
15939
+ "fuckadblock.js-3.2.0": 49,
15940
+ "fuckadblock.js-3.2.0.js": 49,
15826
15941
  "prevent-popads-net": 50,
15827
15942
  "popads.js": 50,
15828
15943
  "scorecardresearch-beacon": 51,
@@ -18530,7 +18645,7 @@ const scriptletsCompatibilityTableData = {
18530
18645
  }]
18531
18646
  }, {
18532
18647
  name: "remove-attr.js",
18533
- aliases: ["ra.js"],
18648
+ aliases: ["ra.js", "ra", "remove-attr"],
18534
18649
  description: null,
18535
18650
  docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-attrjs-",
18536
18651
  versionAdded: null,
@@ -18611,7 +18726,7 @@ const scriptletsCompatibilityTableData = {
18611
18726
  }]
18612
18727
  }, {
18613
18728
  name: "remove-class.js",
18614
- aliases: ["rc.js"],
18729
+ aliases: ["rc.js", "rc", "remove-class"],
18615
18730
  description: null,
18616
18731
  docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-classjs-",
18617
18732
  versionAdded: null,
@@ -20468,6 +20583,7 @@ const scriptletsCompatibilityTableData = {
20468
20583
  "ubo-ra.js": 59,
20469
20584
  "ubo-remove-attr": 59,
20470
20585
  "ubo-ra": 59,
20586
+ ra: 59,
20471
20587
  "remove-class": 60,
20472
20588
  "remove-class.js": 60,
20473
20589
  "ubo-remove-class.js": 60,
@@ -20475,6 +20591,7 @@ const scriptletsCompatibilityTableData = {
20475
20591
  "ubo-rc.js": 60,
20476
20592
  "ubo-remove-class": 60,
20477
20593
  "ubo-rc": 60,
20594
+ rc: 60,
20478
20595
  "remove-cookie": 61,
20479
20596
  "cookie-remover.js": 61,
20480
20597
  "ubo-cookie-remover.js": 61,
@@ -21541,8 +21658,22 @@ function getScriptletName(scriptletNode) {
21541
21658
  */
21542
21659
  function transformNthScriptletArgument(scriptletNode, index, transform) {
21543
21660
  const child = scriptletNode.children[index];
21544
- if (!isUndefined(child) && !isNull(child)) {
21545
- child.value = transform(child.value);
21661
+ if (!isUndefined(child)) {
21662
+ const transformed = transform(child?.value ?? null);
21663
+ if (isNull(transformed)) {
21664
+ // eslint-disable-next-line no-param-reassign
21665
+ scriptletNode.children[index] = null;
21666
+ return;
21667
+ }
21668
+ if (isNull(child)) {
21669
+ // eslint-disable-next-line no-param-reassign
21670
+ scriptletNode.children[index] = {
21671
+ type: 'Value',
21672
+ value: transformed
21673
+ };
21674
+ return;
21675
+ }
21676
+ child.value = transformed;
21546
21677
  }
21547
21678
  }
21548
21679
  /**
@@ -21573,9 +21704,89 @@ function setScriptletName(scriptletNode, name) {
21573
21704
  * @param quoteType Preferred quote type
21574
21705
  */
21575
21706
  function setScriptletQuoteType(scriptletNode, quoteType) {
21576
- transformAllScriptletArguments(scriptletNode, value => QuoteUtils.setStringQuoteType(value, quoteType));
21707
+ // null is a special value that means "no value", but we can't change its quote type,
21708
+ // so we need to convert it to empty string
21709
+ transformAllScriptletArguments(scriptletNode, value => QuoteUtils.setStringQuoteType(value ?? EMPTY, quoteType));
21577
21710
  }
21578
21711
 
21712
+ /**
21713
+ * @file Resource type schema.
21714
+ */
21715
+ /**
21716
+ * Resource type.
21717
+ *
21718
+ * @see {@link https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-ResourceType}
21719
+ */
21720
+ exports.ResourceType = void 0;
21721
+ (function (ResourceType) {
21722
+ ResourceType["MainFrame"] = "main_frame";
21723
+ ResourceType["SubFrame"] = "sub_frame";
21724
+ ResourceType["Stylesheet"] = "stylesheet";
21725
+ ResourceType["Script"] = "script";
21726
+ ResourceType["Image"] = "image";
21727
+ ResourceType["Font"] = "font";
21728
+ ResourceType["Object"] = "object";
21729
+ ResourceType["XmlHttpRequest"] = "xmlhttprequest";
21730
+ ResourceType["Ping"] = "ping";
21731
+ ResourceType["Media"] = "media";
21732
+ ResourceType["WebSocket"] = "websocket";
21733
+ ResourceType["Other"] = "other";
21734
+ })(exports.ResourceType || (exports.ResourceType = {}));
21735
+ /**
21736
+ * Resource type schema.
21737
+ */
21738
+ const resourceTypeSchema = zod.nativeEnum(exports.ResourceType);
21739
+
21740
+ /**
21741
+ * Map of resource types to their corresponding adblock modifier names.
21742
+ *
21743
+ * @note Record type is used to ensure that all resource types are present in the map.
21744
+ */
21745
+ const RESOURCE_TYPE_MODIFIER_MAP = Object.freeze({
21746
+ [exports.ResourceType.MainFrame]: 'document',
21747
+ [exports.ResourceType.SubFrame]: 'subdocument',
21748
+ [exports.ResourceType.Stylesheet]: 'stylesheet',
21749
+ [exports.ResourceType.Script]: 'script',
21750
+ [exports.ResourceType.Image]: 'image',
21751
+ [exports.ResourceType.Font]: 'font',
21752
+ [exports.ResourceType.Object]: 'object',
21753
+ [exports.ResourceType.XmlHttpRequest]: 'xmlhttprequest',
21754
+ [exports.ResourceType.Ping]: 'ping',
21755
+ [exports.ResourceType.Media]: 'media',
21756
+ [exports.ResourceType.WebSocket]: 'websocket',
21757
+ [exports.ResourceType.Other]: 'other'
21758
+ });
21759
+ /**
21760
+ * Gets the adblock modifier name for the given resource type.
21761
+ *
21762
+ * @param resourceType Resource type to get the modifier name for.
21763
+ * @param platform Platform to get the modifier for.
21764
+ *
21765
+ * @returns A string containing the adblock modifier name for the given resource type
21766
+ * or `null` if the modifier could not be found.
21767
+ */
21768
+ const getResourceTypeModifier = (resourceType, platform) => {
21769
+ const modifierName = RESOURCE_TYPE_MODIFIER_MAP[resourceType];
21770
+ if (!modifierName) {
21771
+ return null;
21772
+ }
21773
+ const modifierData = modifiersCompatibilityTable.getFirst(modifierName, platform);
21774
+ if (isNull(modifierData)) {
21775
+ return null;
21776
+ }
21777
+ return modifierData.name;
21778
+ };
21779
+ /**
21780
+ * Checks if the given resource type is valid.
21781
+ *
21782
+ * @param resourceType Resource type to check.
21783
+ *
21784
+ * @returns `true` if the resource type is valid, `false` otherwise.
21785
+ */
21786
+ const isValidResourceType = resourceType => {
21787
+ return Object.values(exports.ResourceType).includes(resourceType);
21788
+ };
21789
+
21579
21790
  /**
21580
21791
  * @file Compatibility tables for redirects.
21581
21792
  */
@@ -21585,19 +21796,29 @@ function setScriptletQuoteType(scriptletNode, quoteType) {
21585
21796
  const ABP_RESOURCE_PREFIX = 'abp-resource:';
21586
21797
  const ABP_RESOURCE_PREFIX_LENGTH = ABP_RESOURCE_PREFIX.length;
21587
21798
  /**
21588
- * Transforms the name of an ABP redirect to a normalized form.
21799
+ * Normalizes the redirect name.
21589
21800
  *
21590
21801
  * @param name Redirect name to normalize.
21591
21802
  *
21592
21803
  * @returns Normalized redirect name.
21593
21804
  *
21594
21805
  * @example
21595
- * abpRedirectNameNormalizer('abp-resource:my-resource') // => 'my-resource'
21806
+ * redirectNameNormalizer('abp-resource:my-resource') // => 'my-resource'
21807
+ * redirectNameNormalizer('noop.js:99') // => 'noop.js'
21596
21808
  */
21597
- const abpRedirectNameNormalizer = name => {
21809
+ const redirectNameNormalizer = name => {
21810
+ // Remove ABP resource prefix, if present
21598
21811
  if (name.startsWith(ABP_RESOURCE_PREFIX)) {
21599
21812
  return name.slice(ABP_RESOURCE_PREFIX_LENGTH);
21600
21813
  }
21814
+ // Remove :[integer] priority suffix from the name, if present
21815
+ // See:
21816
+ // - https://github.com/AdguardTeam/tsurlfilter/issues/59
21817
+ // - https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect
21818
+ const colonIndex = name.lastIndexOf(COLON);
21819
+ if (colonIndex !== -1 && /^\d+$/.test(name.slice(colonIndex + 1))) {
21820
+ return name.slice(0, colonIndex);
21821
+ }
21601
21822
  return name;
21602
21823
  };
21603
21824
  /**
@@ -21610,7 +21831,36 @@ class RedirectsCompatibilityTable extends CompatibilityTableBase {
21610
21831
  * @param data Compatibility table data.
21611
21832
  */
21612
21833
  constructor(data) {
21613
- super(data, abpRedirectNameNormalizer);
21834
+ super(data, redirectNameNormalizer);
21835
+ }
21836
+ /**
21837
+ * Gets the resource type adblock modifiers for the redirect for the given platform
21838
+ * based on the `resourceTypes` field.
21839
+ *
21840
+ * @param redirect Redirect name or redirect data.
21841
+ * @param platform Platform to get the modifiers for.
21842
+ *
21843
+ * @returns Set of resource type modifiers or an empty set if the redirect is not found or has no resource types.
21844
+ */
21845
+ getResourceTypeModifiers(redirect, platform) {
21846
+ let redirectData = null;
21847
+ if (isString(redirect)) {
21848
+ redirectData = this.getFirst(redirect, platform);
21849
+ } else {
21850
+ redirectData = redirect;
21851
+ }
21852
+ const modifierNames = new Set();
21853
+ if (isNull(redirectData) || isUndefined(redirectData.resourceTypes)) {
21854
+ return modifierNames;
21855
+ }
21856
+ for (const resourceType of redirectData.resourceTypes) {
21857
+ const modifierName = getResourceTypeModifier(resourceType, platform);
21858
+ if (isNull(modifierName)) {
21859
+ continue;
21860
+ }
21861
+ modifierNames.add(modifierName);
21862
+ }
21863
+ return modifierNames;
21614
21864
  }
21615
21865
  }
21616
21866
  /**
@@ -22245,7 +22495,13 @@ zodToCamelCase(baseCompatibilityDataSchema.extend({
22245
22495
  /**
22246
22496
  * Whether the redirect is blocking.
22247
22497
  */
22248
- is_blocking: booleanSchema.default(false)
22498
+ is_blocking: booleanSchema.default(false),
22499
+ /**
22500
+ * Resource type(s) belonging to the redirect.
22501
+ *
22502
+ * @see {@link https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-ResourceType}
22503
+ */
22504
+ resource_types: zod.array(resourceTypeSchema).default([])
22249
22505
  }).superRefine(baseRefineLogic));
22250
22506
 
22251
22507
  /**
@@ -22338,11 +22594,14 @@ const ADG_PREVENT_FETCH_NAME = 'prevent-fetch';
22338
22594
  const ADG_PREVENT_FETCH_EMPTY_STRING = '';
22339
22595
  const ADG_PREVENT_FETCH_WILDCARD = '*';
22340
22596
  const UBO_NO_FETCH_IF_WILDCARD = '/^/';
22597
+ const UBO_REMOVE_CLASS_NAME = 'remove-class.js';
22598
+ const UBO_REMOVE_ATTR_NAME = 'remove-attr.js';
22341
22599
  const setConstantAdgToUboMap = {
22342
22600
  [ADG_SET_CONSTANT_EMPTY_STRING]: UBO_SET_CONSTANT_EMPTY_STRING,
22343
22601
  [ADG_SET_CONSTANT_EMPTY_ARRAY]: UBO_SET_CONSTANT_EMPTY_ARRAY,
22344
22602
  [ADG_SET_CONSTANT_EMPTY_OBJECT]: UBO_SET_CONSTANT_EMPTY_OBJECT
22345
22603
  };
22604
+ const REMOVE_ATTR_CLASS_APPLYING = new Set(['asap', 'stay', 'complete']);
22346
22605
  /**
22347
22606
  * Scriptlet injection rule converter class
22348
22607
  *
@@ -22378,12 +22637,18 @@ class ScriptletRuleConverter extends RuleConverterBase {
22378
22637
  const scriptletName = QuoteUtils.setStringQuoteType(getScriptletName(scriptletClone), exports.QuoteType.None);
22379
22638
  // Add prefix if it's not already there
22380
22639
  let prefix;
22640
+ // In uBO / ABP syntax, if a parameter contains the separator character, it should be escaped,
22641
+ // but during the conversion, we need to unescape them, because AdGuard syntax uses quotes to
22642
+ // distinguish between parameters.
22643
+ let charToUnescape;
22381
22644
  switch (rule.syntax) {
22382
22645
  case exports.AdblockSyntax.Abp:
22383
22646
  prefix = ABP_SCRIPTLET_PREFIX;
22647
+ charToUnescape = SPACE;
22384
22648
  break;
22385
22649
  case exports.AdblockSyntax.Ubo:
22386
22650
  prefix = UBO_SCRIPTLET_PREFIX;
22651
+ charToUnescape = COMMA_SEPARATOR;
22387
22652
  break;
22388
22653
  default:
22389
22654
  prefix = EMPTY;
@@ -22391,6 +22656,59 @@ class ScriptletRuleConverter extends RuleConverterBase {
22391
22656
  if (!scriptletName.startsWith(prefix)) {
22392
22657
  setScriptletName(scriptletClone, `${prefix}${scriptletName}`);
22393
22658
  }
22659
+ if (!isUndefined(charToUnescape)) {
22660
+ transformAllScriptletArguments(scriptletClone, value => {
22661
+ if (!isNull(value)) {
22662
+ return QuoteUtils.unescapeSingleEscapedOccurrences(value, charToUnescape);
22663
+ }
22664
+ return value;
22665
+ });
22666
+ }
22667
+ if (rule.syntax === exports.AdblockSyntax.Ubo) {
22668
+ const scriptletData = scriptletsCompatibilityTable.getFirst(scriptletName, exports.GenericPlatform.UboAny);
22669
+ // Some scriptlets have special values that need to be converted
22670
+ if (scriptletData && (scriptletData.name === UBO_REMOVE_CLASS_NAME || scriptletData.name === UBO_REMOVE_ATTR_NAME) && scriptletClone.children.length > 2) {
22671
+ const selectors = [];
22672
+ let applying = null;
22673
+ let lastArg = scriptletClone.children.pop();
22674
+ // The very last argument might be the 'applying' parameter
22675
+ if (lastArg) {
22676
+ if (REMOVE_ATTR_CLASS_APPLYING.has(lastArg.value)) {
22677
+ applying = lastArg.value;
22678
+ } else {
22679
+ selectors.push(lastArg.value);
22680
+ }
22681
+ }
22682
+ while (scriptletClone.children.length > 2) {
22683
+ lastArg = scriptletClone.children.pop();
22684
+ if (lastArg) {
22685
+ selectors.push(lastArg.value.trim());
22686
+ }
22687
+ }
22688
+ // Set last arg to be the combined selectors (in reverse order, because we popped them)
22689
+ if (selectors.length > 0) {
22690
+ scriptletClone.children.push({
22691
+ type: 'Value',
22692
+ value: selectors.reverse().join(', ')
22693
+ });
22694
+ }
22695
+ // Push back the 'applying' parameter if it was found previously
22696
+ if (!isNull(applying)) {
22697
+ // If we don't have any selectors,
22698
+ // we need to add an empty parameter before the 'applying' one
22699
+ if (selectors.length === 0) {
22700
+ scriptletClone.children.push({
22701
+ type: 'Value',
22702
+ value: EMPTY
22703
+ });
22704
+ }
22705
+ scriptletClone.children.push({
22706
+ type: 'Value',
22707
+ value: applying
22708
+ });
22709
+ }
22710
+ }
22711
+ }
22394
22712
  // ADG scriptlet parameters should be quoted, and single quoted are preferred
22395
22713
  setScriptletQuoteType(scriptletClone, exports.QuoteType.Single);
22396
22714
  convertedScriptlets.push(scriptletClone);
@@ -22475,13 +22793,28 @@ class ScriptletRuleConverter extends RuleConverterBase {
22475
22793
  // and we need to escape the comma in the second argument to prevent it from being treated
22476
22794
  // as two separate arguments.
22477
22795
  transformAllScriptletArguments(scriptletClone, value => {
22478
- return QuoteUtils.escapeUnescapedOccurrences(value, COMMA_SEPARATOR);
22796
+ if (!isNull(value)) {
22797
+ return QuoteUtils.escapeUnescapedOccurrences(value, COMMA_SEPARATOR);
22798
+ }
22799
+ return value;
22479
22800
  });
22801
+ // Unescape spaces in parameters, because uBlock Origin doesn't treat them as separators.
22802
+ if (rule.syntax === exports.AdblockSyntax.Abp) {
22803
+ transformAllScriptletArguments(scriptletClone, value => {
22804
+ if (!isNull(value)) {
22805
+ return QuoteUtils.unescapeSingleEscapedOccurrences(value, SPACE);
22806
+ }
22807
+ return value;
22808
+ });
22809
+ }
22480
22810
  // Some scriptlets have special values that need to be converted
22481
22811
  switch (scriptletName) {
22482
22812
  case ADG_SET_CONSTANT_NAME:
22483
22813
  transformNthScriptletArgument(scriptletClone, 2, value => {
22484
- return setConstantAdgToUboMap[value] ?? value;
22814
+ if (!isNull(value)) {
22815
+ return setConstantAdgToUboMap[value] ?? value;
22816
+ }
22817
+ return value;
22485
22818
  });
22486
22819
  break;
22487
22820
  case ADG_PREVENT_FETCH_NAME:
@@ -23152,6 +23485,10 @@ const REDIRECT_MODIFIER = 'redirect';
23152
23485
  * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#redirect-rule-modifier}
23153
23486
  */
23154
23487
  const REDIRECT_RULE_MODIFIER = 'redirect-rule';
23488
+ /**
23489
+ * @see {@link https://github.com/gorhill/uBlock/wiki/Resources-Library#empty-redirect-resources}
23490
+ */
23491
+ const UBO_NOOP_TEXT_RESOURCE = 'noop.txt';
23155
23492
  /**
23156
23493
  * Redirect-related modifiers.
23157
23494
  */
@@ -23301,6 +23638,112 @@ class NetworkRuleModifierListConverter extends ConverterBase {
23301
23638
  }
23302
23639
  return createConversionResult(modifierList, false);
23303
23640
  }
23641
+ /**
23642
+ * Converts a network rule modifier list to uBlock format, if possible.
23643
+ *
23644
+ * @param modifierList Network rule modifier list node to convert
23645
+ * @param isException If `true`, the rule is an exception rule
23646
+ * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
23647
+ * the converted node, and its `isConverted` flag indicates whether the original node was converted.
23648
+ * If the node was not converted, the result will contain the original node with the same object reference
23649
+ * @throws If the conversion is not possible
23650
+ */
23651
+ // TODO: Optimize
23652
+ static convertToUbo(modifierList, isException = false) {
23653
+ const conversionMap = new MultiValueMap();
23654
+ const resourceTypeModifiersToAdd = new Set();
23655
+ modifierList.children.forEach((modifierNode, index) => {
23656
+ const originalModifierName = modifierNode.name.value;
23657
+ const modifierData = modifiersCompatibilityTable.getFirst(originalModifierName, exports.GenericPlatform.UboAny);
23658
+ // Handle special case: resource redirection modifiers
23659
+ if (REDIRECT_MODIFIERS.has(originalModifierName)) {
23660
+ // Redirect modifiers cannot be negated
23661
+ if (modifierNode.exception === true) {
23662
+ throw new RuleConversionError(`Modifier '${modifierNode.name.value}' cannot be negated`);
23663
+ }
23664
+ // Convert the redirect resource name to uBO format
23665
+ const redirectResourceName = modifierNode.value?.value;
23666
+ // Special case: for exception rules, $redirect without value is allowed,
23667
+ // and in this case it means an exception for all redirects
23668
+ if (!redirectResourceName && !isException) {
23669
+ throw new RuleConversionError(`No redirect resource specified for '${modifierNode.name.value}' modifier`);
23670
+ }
23671
+ if (!redirectResourceName) {
23672
+ // Jump to the next modifier if the redirect resource is not specified
23673
+ return;
23674
+ }
23675
+ // Leave $redirect and $redirect-rule modifiers as is, but convert $rewrite to $redirect
23676
+ const modifierName = modifierNode.name.value === ABP_REWRITE_MODIFIER ? REDIRECT_MODIFIER : modifierNode.name.value;
23677
+ const convertedRedirectResourceData = redirectsCompatibilityTable.getFirst(redirectResourceName, exports.GenericPlatform.UboAny);
23678
+ const convertedRedirectResourceName = convertedRedirectResourceData?.name ?? redirectResourceName;
23679
+ // uBlock requires the $redirect modifier to have a resource type
23680
+ // https://github.com/AdguardTeam/Scriptlets/issues/101
23681
+ if (convertedRedirectResourceData?.resourceTypes?.length) {
23682
+ // Convert the resource types to uBO modifiers
23683
+ const uboResourceTypeModifiers = redirectsCompatibilityTable.getResourceTypeModifiers(convertedRedirectResourceData, exports.GenericPlatform.UboAny);
23684
+ // Special case: noop text resource
23685
+ // If any of resource type is already present, we don't need to add other resource types,
23686
+ // otherwise, add all resource types
23687
+ // TODO: Optimize this logic
23688
+ // Check if the current resource is the noop text resource
23689
+ const isNoopTextResource = convertedRedirectResourceName === UBO_NOOP_TEXT_RESOURCE;
23690
+ // Determine if there are any valid resource types already present
23691
+ const hasValidResourceType = modifierList.children.some(modifier => {
23692
+ const name = modifier.name.value;
23693
+ if (!isValidResourceType(name)) {
23694
+ return false;
23695
+ }
23696
+ const convertedModifierData = modifiersCompatibilityTable.getFirst(name, exports.GenericPlatform.UboAny);
23697
+ return uboResourceTypeModifiers.has(convertedModifierData?.name ?? name);
23698
+ });
23699
+ // If it's not the noop text resource or if no valid resource types are present
23700
+ if (!isNoopTextResource || !hasValidResourceType) {
23701
+ uboResourceTypeModifiers.forEach(resourceType => {
23702
+ resourceTypeModifiersToAdd.add(resourceType);
23703
+ });
23704
+ }
23705
+ }
23706
+ // Check if the modifier name or the redirect resource name is different from the original modifier.
23707
+ // If so, add the converted modifier to the list
23708
+ if (modifierName !== originalModifierName || !isUndefined(convertedRedirectResourceName) && convertedRedirectResourceName !== redirectResourceName) {
23709
+ conversionMap.add(index, createModifierNode(modifierName,
23710
+ // If the redirect resource name is unknown, fall back to the original one
23711
+ // Later, the validator will throw an error if the resource name is invalid
23712
+ convertedRedirectResourceName || redirectResourceName, modifierNode.exception));
23713
+ }
23714
+ return;
23715
+ }
23716
+ // Generic modifier conversion
23717
+ if (modifierData && modifierData.name !== originalModifierName) {
23718
+ conversionMap.add(index, createModifierNode(modifierData.name, modifierNode.value?.value, modifierNode.exception));
23719
+ }
23720
+ });
23721
+ // Prepare the result if there are any converted modifiers or $csp modifiers
23722
+ if (conversionMap.size || resourceTypeModifiersToAdd.size) {
23723
+ const modifierListClone = cloneModifierListNode(modifierList);
23724
+ // Replace the original modifiers with the converted ones
23725
+ // One modifier may be replaced with multiple modifiers, so we need to flatten the array
23726
+ modifierListClone.children = modifierListClone.children.map((modifierNode, index) => {
23727
+ const conversionRecord = conversionMap.get(index);
23728
+ if (conversionRecord) {
23729
+ return conversionRecord;
23730
+ }
23731
+ return modifierNode;
23732
+ }).flat();
23733
+ // Before returning the result, remove duplicated modifiers
23734
+ modifierListClone.children = modifierListClone.children.filter((modifierNode, index, self) => self.findIndex(m => m.name.value === modifierNode.name.value && m.exception === modifierNode.exception && m.value?.value === modifierNode.value?.value) === index);
23735
+ if (resourceTypeModifiersToAdd.size) {
23736
+ const modifierNameSet = new Set(modifierList.children.map(m => m.name.value));
23737
+ resourceTypeModifiersToAdd.forEach(resourceType => {
23738
+ if (!modifierNameSet.has(resourceType)) {
23739
+ modifierListClone.children.push(createModifierNode(resourceType));
23740
+ }
23741
+ });
23742
+ }
23743
+ return createConversionResult(modifierListClone, true);
23744
+ }
23745
+ return createConversionResult(modifierList, false);
23746
+ }
23304
23747
  }
23305
23748
 
23306
23749
  /**
@@ -23350,6 +23793,44 @@ class NetworkRuleConverter extends RuleConverterBase {
23350
23793
  // If the modifiers were not converted, return the original rule
23351
23794
  return createNodeConversionResult([rule], false);
23352
23795
  }
23796
+ /**
23797
+ * Converts a network rule to uBlock format, if possible.
23798
+ *
23799
+ * @param rule Rule node to convert
23800
+ * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
23801
+ * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
23802
+ * If the rule was not converted, the result array will contain the original node with the same object reference
23803
+ * @throws If the rule is invalid or cannot be converted
23804
+ */
23805
+ static convertToUbo(rule) {
23806
+ // TODO: add support for host rules
23807
+ if (rule.type !== exports.NetworkRuleType.NetworkRule) {
23808
+ throw new Error(`Invalid rule type: ${rule.type}`);
23809
+ }
23810
+ if (rule.modifiers) {
23811
+ const modifiers = NetworkRuleModifierListConverter.convertToUbo(rule.modifiers, rule.exception);
23812
+ // If the object reference is different, it means that the modifiers were converted
23813
+ // In this case, we should clone the entire rule and replace the modifiers with the converted ones
23814
+ if (modifiers.isConverted) {
23815
+ return {
23816
+ result: [{
23817
+ category: exports.RuleCategory.Network,
23818
+ type: exports.NetworkRuleType.NetworkRule,
23819
+ syntax: rule.syntax,
23820
+ exception: rule.exception,
23821
+ pattern: {
23822
+ type: 'Value',
23823
+ value: rule.pattern.value
23824
+ },
23825
+ modifiers: modifiers.result
23826
+ }],
23827
+ isConverted: true
23828
+ };
23829
+ }
23830
+ }
23831
+ // If the modifiers were not converted, return the original rule
23832
+ return createNodeConversionResult([rule], false);
23833
+ }
23353
23834
  }
23354
23835
 
23355
23836
  /**
@@ -23411,6 +23892,9 @@ class RuleConverter extends RuleConverterBase {
23411
23892
  if (rule.category === exports.RuleCategory.Cosmetic) {
23412
23893
  return CosmeticRuleConverter.convertToUbo(rule);
23413
23894
  }
23895
+ if (rule.category === exports.RuleCategory.Network) {
23896
+ return NetworkRuleConverter.convertToUbo(rule);
23897
+ }
23414
23898
  return createConversionResult([rule], false);
23415
23899
  }
23416
23900
  }
@@ -24460,7 +24944,7 @@ class RuleCategorizer {
24460
24944
  }
24461
24945
  }
24462
24946
  }
24463
- const version = "2.0.0";
24947
+ const version = "2.0.1";
24464
24948
 
24465
24949
  /**
24466
24950
  * @file AGTree version
@@ -24541,8 +25025,10 @@ exports.decodeTextPolyfill = decodeTextPolyfill;
24541
25025
  exports.defaultParserOptions = defaultParserOptions;
24542
25026
  exports.encodeIntoPolyfill = encodeIntoPolyfill;
24543
25027
  exports.getPlatformId = getPlatformId;
25028
+ exports.getResourceTypeModifier = getResourceTypeModifier;
24544
25029
  exports.getSpecificPlatformName = getSpecificPlatformName;
24545
25030
  exports.isGenericPlatform = isGenericPlatform;
25031
+ exports.isValidResourceType = isValidResourceType;
24546
25032
  exports.modifierValidator = modifierValidator;
24547
25033
  exports.modifiersCompatibilityTable = modifiersCompatibilityTable;
24548
25034
  exports.parseRawPlatforms = parseRawPlatforms;