@duckduckgo/autoconsent 16.12.0 → 16.14.0
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/.node-version +1 -0
- package/CHANGELOG.md +35 -0
- package/Jenkinsfile +11 -6
- package/dist/addon-firefox/compact-rules.json +1 -1
- package/dist/addon-firefox/content.bundle.js +32 -8
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/rule-index.json +1 -1
- package/dist/addon-firefox/rules.json +1 -1
- package/dist/addon-mv3/compact-rules.json +1 -1
- package/dist/addon-mv3/content.bundle.js +32 -8
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/rule-index.json +1 -1
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.cjs.js +32 -8
- package/dist/autoconsent.esm.js +32 -8
- package/dist/autoconsent.playwright.js +32 -8
- package/dist/autoconsent.standalone.js +33 -9
- package/dist/types/heuristic-patterns.d.ts +2 -1
- package/dist/types/heuristics.d.ts +1 -0
- package/lib/heuristic-patterns.ts +21 -4
- package/lib/heuristics.ts +17 -5
- package/package.json +1 -1
- package/rules/autoconsent/interia.json +15 -0
- package/rules/autoconsent/unive-nl.json +40 -0
- package/rules/autoconsent/xhamster-eu.json +8 -5
- package/rules/autoconsent/xnxx-com.json +24 -4
- package/rules/compact-rules.json +1 -1
- package/rules/rule-index.json +1 -1
- package/rules/rules.json +1 -1
- package/tests/interia.spec.ts +3 -0
- package/tests/unive-nl.spec.ts +3 -0
- package/tests/xhamster-eu.spec.ts +3 -1
- package/tests-wtr/heuristics/get-actionable-popups.html +10 -0
- package/tests-wtr/heuristics/get-actionable-popups.ts +8 -0
- package/tests-wtr/heuristics/heuristics-utils.test.ts +38 -0
package/dist/autoconsent.cjs.js
CHANGED
|
@@ -564,7 +564,7 @@ var DETECT_PATTERNS = [
|
|
|
564
564
|
var REJECT_PATTERNS_ENGLISH = [
|
|
565
565
|
// e.g. "reject", "reject all", "reject all cookies", "deny all", "refuse cookies", "decline",
|
|
566
566
|
// "reject non-essential cookies", "reject unnecessary cookies", "reject all but necessary", "reject all and close"
|
|
567
|
-
// note that "reject and subscribe" and "reject and pay" are excluded via
|
|
567
|
+
// note that "reject and subscribe" and "reject and pay" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
568
568
|
/^\s*(no,?\s*)?(i\s+)?(reject|deny|refuse|decline|disable)\s*(all)?\s*(but|except)?\s*(non[- ]?essential|un(necessary|required)|optional|additional|targeting|analytics|marketing|non[- ]?necessary|extra|tracking|advertising|necessary|essential)?\s*(cookies)?\s*(and\s+close)?\s*$/is,
|
|
569
569
|
// e.g. "i do not accept", "do not accept cookies"
|
|
570
570
|
/^\s*(i\s+)?do\s+not\s+accept\s*(cookies)?\s*$/is,
|
|
@@ -612,7 +612,7 @@ var REJECT_PATTERNS_DUTCH = [
|
|
|
612
612
|
];
|
|
613
613
|
var REJECT_PATTERNS_FRENCH = [
|
|
614
614
|
// refuser / rejeter / interdire / décliner (reject verbs, any position)
|
|
615
|
-
// "refuser et s'abonner" / "refuser et payer" are excluded via
|
|
615
|
+
// "refuser et s'abonner" / "refuser et payer" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
616
616
|
/(^|\s)(refus|rejet|rejeter|interdire|interdis|déclin|declin)/is,
|
|
617
617
|
// only necessary / essential / technical / functional
|
|
618
618
|
/(uniquement|seulement|indispensable|strictement nécessaire|que les cookies\s+(nécessaires|techniques|essentiels|indispensables|fonctionnels))/is,
|
|
@@ -667,7 +667,7 @@ var REJECT_PATTERNS_BRAZILIAN_PORTUGUESE = [
|
|
|
667
667
|
];
|
|
668
668
|
var REJECT_PATTERNS_SPANISH = [
|
|
669
669
|
// rechazar / denegar / declinar / negar (reject verbs, any position)
|
|
670
|
-
// "rechazar y pagar" / "rechazar y suscribirse" are excluded via
|
|
670
|
+
// "rechazar y pagar" / "rechazar y suscribirse" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
671
671
|
/(^|\s)(rechaz|recház|deneg|negar|declin)/is,
|
|
672
672
|
// accept/allow/use (only) necessary / essential / technical / functional / own
|
|
673
673
|
/^\s*(aceptar?|acepta|permitir|permite|usar|utilizar)?\s*(solo|sólo|només|únicamente)?\s*(las?\s+|los\s+)?(cookies?\s+)?(estrictamente\s+)?(necesari\w*|esencial\w*|técnic\w*|obligatori\w*|funcional\w*|propias)\s*$/is,
|
|
@@ -735,7 +735,7 @@ var REJECT_PATTERNS = [
|
|
|
735
735
|
...REJECT_PATTERNS_TURKISH,
|
|
736
736
|
...REJECT_PATTERNS_INDONESIAN
|
|
737
737
|
];
|
|
738
|
-
var
|
|
738
|
+
var BUTTON_NEVER_MATCH_PATTERNS = [
|
|
739
739
|
/pay|subscribe/is,
|
|
740
740
|
/abonneer/is,
|
|
741
741
|
/abonnier/is,
|
|
@@ -756,6 +756,20 @@ var NEVER_MATCH_PATTERNS = [
|
|
|
756
756
|
// Polish (PL)
|
|
757
757
|
/subskrybuj/
|
|
758
758
|
];
|
|
759
|
+
var DETECT_NEVER_MATCH_PATTERNS = [
|
|
760
|
+
// e.g. "age verification", "age confirmation", "age check", "age gate", "age restriction"
|
|
761
|
+
/age\s+(?:verification|confirmation|check|gate|restriction)/i,
|
|
762
|
+
// e.g. "over 18 years", "at least 21 years", "older than 21", "18+"
|
|
763
|
+
/(?:over|above|at\s*least|minimum|older\s+than)\s*(?:18|21)\s*(?:years|yo|y\.?o\.?|\+)?/i,
|
|
764
|
+
// e.g. "18 years of age", "18+ years old", "21 years or older"
|
|
765
|
+
/(?:18|21)\s*(?:\+|years?)\s*(?:of\s*age|or\s*older|or\s*above)/i,
|
|
766
|
+
// e.g. "I am 18+", "I am over 18", "I'm 21 or older"
|
|
767
|
+
/(?:i'?m|i\s*am)\s*(?:over|above|at\s*least)?\s*(?:18|21)(?:\+|\s*(?:or\s*older|years))?/i,
|
|
768
|
+
// e.g. "you must be 18", "users must be at least 21", "visitors must be over 18"
|
|
769
|
+
/(?:you|users?|visitors?)\s+must\s+be\s+(?:over|above|at\s*least)?\s*(?:18|21)/i,
|
|
770
|
+
// e.g. "adult oriented material", "adult content", "adult-only website"
|
|
771
|
+
/adult[\s-]+(?:oriented|only|content|material|websites?)/i
|
|
772
|
+
];
|
|
759
773
|
var SETTINGS_PATTERNS = [
|
|
760
774
|
// Multilingual "open customization" patterns: a customization verb next to a
|
|
761
775
|
// cookie/preference/settings/options/details/purposes noun (both word orders).
|
|
@@ -1129,6 +1143,9 @@ function getActionablePopups(mode = "reject", timeout = POPUP_SEARCH_MAX_TIME) {
|
|
|
1129
1143
|
const result = popups.reduce((acc, popup) => {
|
|
1130
1144
|
const popupText = popup.text?.trim();
|
|
1131
1145
|
if (popupText) {
|
|
1146
|
+
if (isExcludedPopup(popupText)) {
|
|
1147
|
+
return acc;
|
|
1148
|
+
}
|
|
1132
1149
|
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1133
1150
|
if (patterns.length > 0) {
|
|
1134
1151
|
classifyButtons(popup.buttons);
|
|
@@ -1147,6 +1164,13 @@ function classifyButtons(buttons) {
|
|
|
1147
1164
|
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
1148
1165
|
}
|
|
1149
1166
|
}
|
|
1167
|
+
function isExcludedPopup(popupText, excludePatterns = DETECT_NEVER_MATCH_PATTERNS) {
|
|
1168
|
+
if (!popupText) {
|
|
1169
|
+
return false;
|
|
1170
|
+
}
|
|
1171
|
+
const truncated = popupText.slice(0, TEXT_LIMIT);
|
|
1172
|
+
return excludePatterns.some((p) => p.test(truncated));
|
|
1173
|
+
}
|
|
1150
1174
|
function classifyPopup(buttons) {
|
|
1151
1175
|
const { reject, settings, accept, acknowledge } = buttons.reduce(
|
|
1152
1176
|
(acc, button) => {
|
|
@@ -1191,16 +1215,16 @@ function cleanButtonText(buttonText) {
|
|
|
1191
1215
|
return result;
|
|
1192
1216
|
}
|
|
1193
1217
|
function classifyButtonTextRegex(buttonText) {
|
|
1194
|
-
if (testButtonMatches(buttonText, REJECT_PATTERNS,
|
|
1218
|
+
if (testButtonMatches(buttonText, REJECT_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1195
1219
|
return "reject";
|
|
1196
1220
|
}
|
|
1197
|
-
if (testButtonMatches(buttonText, SETTINGS_PATTERNS,
|
|
1221
|
+
if (testButtonMatches(buttonText, SETTINGS_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1198
1222
|
return "settings";
|
|
1199
1223
|
}
|
|
1200
|
-
if (testButtonMatches(buttonText, ACCEPT_PATTERNS,
|
|
1224
|
+
if (testButtonMatches(buttonText, ACCEPT_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1201
1225
|
return "accept";
|
|
1202
1226
|
}
|
|
1203
|
-
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS,
|
|
1227
|
+
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1204
1228
|
return "acknowledge";
|
|
1205
1229
|
}
|
|
1206
1230
|
return "other";
|
package/dist/autoconsent.esm.js
CHANGED
|
@@ -534,7 +534,7 @@ var DETECT_PATTERNS = [
|
|
|
534
534
|
var REJECT_PATTERNS_ENGLISH = [
|
|
535
535
|
// e.g. "reject", "reject all", "reject all cookies", "deny all", "refuse cookies", "decline",
|
|
536
536
|
// "reject non-essential cookies", "reject unnecessary cookies", "reject all but necessary", "reject all and close"
|
|
537
|
-
// note that "reject and subscribe" and "reject and pay" are excluded via
|
|
537
|
+
// note that "reject and subscribe" and "reject and pay" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
538
538
|
/^\s*(no,?\s*)?(i\s+)?(reject|deny|refuse|decline|disable)\s*(all)?\s*(but|except)?\s*(non[- ]?essential|un(necessary|required)|optional|additional|targeting|analytics|marketing|non[- ]?necessary|extra|tracking|advertising|necessary|essential)?\s*(cookies)?\s*(and\s+close)?\s*$/is,
|
|
539
539
|
// e.g. "i do not accept", "do not accept cookies"
|
|
540
540
|
/^\s*(i\s+)?do\s+not\s+accept\s*(cookies)?\s*$/is,
|
|
@@ -582,7 +582,7 @@ var REJECT_PATTERNS_DUTCH = [
|
|
|
582
582
|
];
|
|
583
583
|
var REJECT_PATTERNS_FRENCH = [
|
|
584
584
|
// refuser / rejeter / interdire / décliner (reject verbs, any position)
|
|
585
|
-
// "refuser et s'abonner" / "refuser et payer" are excluded via
|
|
585
|
+
// "refuser et s'abonner" / "refuser et payer" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
586
586
|
/(^|\s)(refus|rejet|rejeter|interdire|interdis|déclin|declin)/is,
|
|
587
587
|
// only necessary / essential / technical / functional
|
|
588
588
|
/(uniquement|seulement|indispensable|strictement nécessaire|que les cookies\s+(nécessaires|techniques|essentiels|indispensables|fonctionnels))/is,
|
|
@@ -637,7 +637,7 @@ var REJECT_PATTERNS_BRAZILIAN_PORTUGUESE = [
|
|
|
637
637
|
];
|
|
638
638
|
var REJECT_PATTERNS_SPANISH = [
|
|
639
639
|
// rechazar / denegar / declinar / negar (reject verbs, any position)
|
|
640
|
-
// "rechazar y pagar" / "rechazar y suscribirse" are excluded via
|
|
640
|
+
// "rechazar y pagar" / "rechazar y suscribirse" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
641
641
|
/(^|\s)(rechaz|recház|deneg|negar|declin)/is,
|
|
642
642
|
// accept/allow/use (only) necessary / essential / technical / functional / own
|
|
643
643
|
/^\s*(aceptar?|acepta|permitir|permite|usar|utilizar)?\s*(solo|sólo|només|únicamente)?\s*(las?\s+|los\s+)?(cookies?\s+)?(estrictamente\s+)?(necesari\w*|esencial\w*|técnic\w*|obligatori\w*|funcional\w*|propias)\s*$/is,
|
|
@@ -705,7 +705,7 @@ var REJECT_PATTERNS = [
|
|
|
705
705
|
...REJECT_PATTERNS_TURKISH,
|
|
706
706
|
...REJECT_PATTERNS_INDONESIAN
|
|
707
707
|
];
|
|
708
|
-
var
|
|
708
|
+
var BUTTON_NEVER_MATCH_PATTERNS = [
|
|
709
709
|
/pay|subscribe/is,
|
|
710
710
|
/abonneer/is,
|
|
711
711
|
/abonnier/is,
|
|
@@ -726,6 +726,20 @@ var NEVER_MATCH_PATTERNS = [
|
|
|
726
726
|
// Polish (PL)
|
|
727
727
|
/subskrybuj/
|
|
728
728
|
];
|
|
729
|
+
var DETECT_NEVER_MATCH_PATTERNS = [
|
|
730
|
+
// e.g. "age verification", "age confirmation", "age check", "age gate", "age restriction"
|
|
731
|
+
/age\s+(?:verification|confirmation|check|gate|restriction)/i,
|
|
732
|
+
// e.g. "over 18 years", "at least 21 years", "older than 21", "18+"
|
|
733
|
+
/(?:over|above|at\s*least|minimum|older\s+than)\s*(?:18|21)\s*(?:years|yo|y\.?o\.?|\+)?/i,
|
|
734
|
+
// e.g. "18 years of age", "18+ years old", "21 years or older"
|
|
735
|
+
/(?:18|21)\s*(?:\+|years?)\s*(?:of\s*age|or\s*older|or\s*above)/i,
|
|
736
|
+
// e.g. "I am 18+", "I am over 18", "I'm 21 or older"
|
|
737
|
+
/(?:i'?m|i\s*am)\s*(?:over|above|at\s*least)?\s*(?:18|21)(?:\+|\s*(?:or\s*older|years))?/i,
|
|
738
|
+
// e.g. "you must be 18", "users must be at least 21", "visitors must be over 18"
|
|
739
|
+
/(?:you|users?|visitors?)\s+must\s+be\s+(?:over|above|at\s*least)?\s*(?:18|21)/i,
|
|
740
|
+
// e.g. "adult oriented material", "adult content", "adult-only website"
|
|
741
|
+
/adult[\s-]+(?:oriented|only|content|material|websites?)/i
|
|
742
|
+
];
|
|
729
743
|
var SETTINGS_PATTERNS = [
|
|
730
744
|
// Multilingual "open customization" patterns: a customization verb next to a
|
|
731
745
|
// cookie/preference/settings/options/details/purposes noun (both word orders).
|
|
@@ -1099,6 +1113,9 @@ function getActionablePopups(mode = "reject", timeout = POPUP_SEARCH_MAX_TIME) {
|
|
|
1099
1113
|
const result = popups.reduce((acc, popup) => {
|
|
1100
1114
|
const popupText = popup.text?.trim();
|
|
1101
1115
|
if (popupText) {
|
|
1116
|
+
if (isExcludedPopup(popupText)) {
|
|
1117
|
+
return acc;
|
|
1118
|
+
}
|
|
1102
1119
|
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1103
1120
|
if (patterns.length > 0) {
|
|
1104
1121
|
classifyButtons(popup.buttons);
|
|
@@ -1117,6 +1134,13 @@ function classifyButtons(buttons) {
|
|
|
1117
1134
|
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
1118
1135
|
}
|
|
1119
1136
|
}
|
|
1137
|
+
function isExcludedPopup(popupText, excludePatterns = DETECT_NEVER_MATCH_PATTERNS) {
|
|
1138
|
+
if (!popupText) {
|
|
1139
|
+
return false;
|
|
1140
|
+
}
|
|
1141
|
+
const truncated = popupText.slice(0, TEXT_LIMIT);
|
|
1142
|
+
return excludePatterns.some((p) => p.test(truncated));
|
|
1143
|
+
}
|
|
1120
1144
|
function classifyPopup(buttons) {
|
|
1121
1145
|
const { reject, settings, accept, acknowledge } = buttons.reduce(
|
|
1122
1146
|
(acc, button) => {
|
|
@@ -1161,16 +1185,16 @@ function cleanButtonText(buttonText) {
|
|
|
1161
1185
|
return result;
|
|
1162
1186
|
}
|
|
1163
1187
|
function classifyButtonTextRegex(buttonText) {
|
|
1164
|
-
if (testButtonMatches(buttonText, REJECT_PATTERNS,
|
|
1188
|
+
if (testButtonMatches(buttonText, REJECT_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1165
1189
|
return "reject";
|
|
1166
1190
|
}
|
|
1167
|
-
if (testButtonMatches(buttonText, SETTINGS_PATTERNS,
|
|
1191
|
+
if (testButtonMatches(buttonText, SETTINGS_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1168
1192
|
return "settings";
|
|
1169
1193
|
}
|
|
1170
|
-
if (testButtonMatches(buttonText, ACCEPT_PATTERNS,
|
|
1194
|
+
if (testButtonMatches(buttonText, ACCEPT_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1171
1195
|
return "accept";
|
|
1172
1196
|
}
|
|
1173
|
-
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS,
|
|
1197
|
+
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1174
1198
|
return "acknowledge";
|
|
1175
1199
|
}
|
|
1176
1200
|
return "other";
|
|
@@ -536,7 +536,7 @@
|
|
|
536
536
|
var REJECT_PATTERNS_ENGLISH = [
|
|
537
537
|
// e.g. "reject", "reject all", "reject all cookies", "deny all", "refuse cookies", "decline",
|
|
538
538
|
// "reject non-essential cookies", "reject unnecessary cookies", "reject all but necessary", "reject all and close"
|
|
539
|
-
// note that "reject and subscribe" and "reject and pay" are excluded via
|
|
539
|
+
// note that "reject and subscribe" and "reject and pay" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
540
540
|
/^\s*(no,?\s*)?(i\s+)?(reject|deny|refuse|decline|disable)\s*(all)?\s*(but|except)?\s*(non[- ]?essential|un(necessary|required)|optional|additional|targeting|analytics|marketing|non[- ]?necessary|extra|tracking|advertising|necessary|essential)?\s*(cookies)?\s*(and\s+close)?\s*$/is,
|
|
541
541
|
// e.g. "i do not accept", "do not accept cookies"
|
|
542
542
|
/^\s*(i\s+)?do\s+not\s+accept\s*(cookies)?\s*$/is,
|
|
@@ -584,7 +584,7 @@
|
|
|
584
584
|
];
|
|
585
585
|
var REJECT_PATTERNS_FRENCH = [
|
|
586
586
|
// refuser / rejeter / interdire / décliner (reject verbs, any position)
|
|
587
|
-
// "refuser et s'abonner" / "refuser et payer" are excluded via
|
|
587
|
+
// "refuser et s'abonner" / "refuser et payer" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
588
588
|
/(^|\s)(refus|rejet|rejeter|interdire|interdis|déclin|declin)/is,
|
|
589
589
|
// only necessary / essential / technical / functional
|
|
590
590
|
/(uniquement|seulement|indispensable|strictement nécessaire|que les cookies\s+(nécessaires|techniques|essentiels|indispensables|fonctionnels))/is,
|
|
@@ -639,7 +639,7 @@
|
|
|
639
639
|
];
|
|
640
640
|
var REJECT_PATTERNS_SPANISH = [
|
|
641
641
|
// rechazar / denegar / declinar / negar (reject verbs, any position)
|
|
642
|
-
// "rechazar y pagar" / "rechazar y suscribirse" are excluded via
|
|
642
|
+
// "rechazar y pagar" / "rechazar y suscribirse" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
643
643
|
/(^|\s)(rechaz|recház|deneg|negar|declin)/is,
|
|
644
644
|
// accept/allow/use (only) necessary / essential / technical / functional / own
|
|
645
645
|
/^\s*(aceptar?|acepta|permitir|permite|usar|utilizar)?\s*(solo|sólo|només|únicamente)?\s*(las?\s+|los\s+)?(cookies?\s+)?(estrictamente\s+)?(necesari\w*|esencial\w*|técnic\w*|obligatori\w*|funcional\w*|propias)\s*$/is,
|
|
@@ -707,7 +707,7 @@
|
|
|
707
707
|
...REJECT_PATTERNS_TURKISH,
|
|
708
708
|
...REJECT_PATTERNS_INDONESIAN
|
|
709
709
|
];
|
|
710
|
-
var
|
|
710
|
+
var BUTTON_NEVER_MATCH_PATTERNS = [
|
|
711
711
|
/pay|subscribe/is,
|
|
712
712
|
/abonneer/is,
|
|
713
713
|
/abonnier/is,
|
|
@@ -728,6 +728,20 @@
|
|
|
728
728
|
// Polish (PL)
|
|
729
729
|
/subskrybuj/
|
|
730
730
|
];
|
|
731
|
+
var DETECT_NEVER_MATCH_PATTERNS = [
|
|
732
|
+
// e.g. "age verification", "age confirmation", "age check", "age gate", "age restriction"
|
|
733
|
+
/age\s+(?:verification|confirmation|check|gate|restriction)/i,
|
|
734
|
+
// e.g. "over 18 years", "at least 21 years", "older than 21", "18+"
|
|
735
|
+
/(?:over|above|at\s*least|minimum|older\s+than)\s*(?:18|21)\s*(?:years|yo|y\.?o\.?|\+)?/i,
|
|
736
|
+
// e.g. "18 years of age", "18+ years old", "21 years or older"
|
|
737
|
+
/(?:18|21)\s*(?:\+|years?)\s*(?:of\s*age|or\s*older|or\s*above)/i,
|
|
738
|
+
// e.g. "I am 18+", "I am over 18", "I'm 21 or older"
|
|
739
|
+
/(?:i'?m|i\s*am)\s*(?:over|above|at\s*least)?\s*(?:18|21)(?:\+|\s*(?:or\s*older|years))?/i,
|
|
740
|
+
// e.g. "you must be 18", "users must be at least 21", "visitors must be over 18"
|
|
741
|
+
/(?:you|users?|visitors?)\s+must\s+be\s+(?:over|above|at\s*least)?\s*(?:18|21)/i,
|
|
742
|
+
// e.g. "adult oriented material", "adult content", "adult-only website"
|
|
743
|
+
/adult[\s-]+(?:oriented|only|content|material|websites?)/i
|
|
744
|
+
];
|
|
731
745
|
var SETTINGS_PATTERNS = [
|
|
732
746
|
// Multilingual "open customization" patterns: a customization verb next to a
|
|
733
747
|
// cookie/preference/settings/options/details/purposes noun (both word orders).
|
|
@@ -1101,6 +1115,9 @@
|
|
|
1101
1115
|
const result = popups.reduce((acc, popup) => {
|
|
1102
1116
|
const popupText = popup.text?.trim();
|
|
1103
1117
|
if (popupText) {
|
|
1118
|
+
if (isExcludedPopup(popupText)) {
|
|
1119
|
+
return acc;
|
|
1120
|
+
}
|
|
1104
1121
|
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1105
1122
|
if (patterns.length > 0) {
|
|
1106
1123
|
classifyButtons(popup.buttons);
|
|
@@ -1119,6 +1136,13 @@
|
|
|
1119
1136
|
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
1120
1137
|
}
|
|
1121
1138
|
}
|
|
1139
|
+
function isExcludedPopup(popupText, excludePatterns = DETECT_NEVER_MATCH_PATTERNS) {
|
|
1140
|
+
if (!popupText) {
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1143
|
+
const truncated = popupText.slice(0, TEXT_LIMIT);
|
|
1144
|
+
return excludePatterns.some((p) => p.test(truncated));
|
|
1145
|
+
}
|
|
1122
1146
|
function classifyPopup(buttons) {
|
|
1123
1147
|
const { reject, settings, accept, acknowledge } = buttons.reduce(
|
|
1124
1148
|
(acc, button) => {
|
|
@@ -1163,16 +1187,16 @@
|
|
|
1163
1187
|
return result;
|
|
1164
1188
|
}
|
|
1165
1189
|
function classifyButtonTextRegex(buttonText) {
|
|
1166
|
-
if (testButtonMatches(buttonText, REJECT_PATTERNS,
|
|
1190
|
+
if (testButtonMatches(buttonText, REJECT_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1167
1191
|
return "reject";
|
|
1168
1192
|
}
|
|
1169
|
-
if (testButtonMatches(buttonText, SETTINGS_PATTERNS,
|
|
1193
|
+
if (testButtonMatches(buttonText, SETTINGS_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1170
1194
|
return "settings";
|
|
1171
1195
|
}
|
|
1172
|
-
if (testButtonMatches(buttonText, ACCEPT_PATTERNS,
|
|
1196
|
+
if (testButtonMatches(buttonText, ACCEPT_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1173
1197
|
return "accept";
|
|
1174
1198
|
}
|
|
1175
|
-
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS,
|
|
1199
|
+
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS, BUTTON_NEVER_MATCH_PATTERNS)) {
|
|
1176
1200
|
return "acknowledge";
|
|
1177
1201
|
}
|
|
1178
1202
|
return "other";
|