@duckduckgo/autoconsent 16.59.0 → 16.60.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/.agents/lib/regional-testing/harness.mjs +4 -172
- package/.agents/skills/oxylabs-testing/SKILL.md +4 -4
- package/.agents/skills/oxylabs-testing/scripts/oxylabs.mjs +17 -164
- package/.agents/skills/oxylabs-testing/scripts/oxylabs.test.mjs +6 -3
- package/.agents/skills/verify-pr/SKILL.md +1 -1
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +83 -0
- package/Jenkinsfile +36 -1
- package/dist/addon-firefox/background.bundle.js +21 -0
- package/dist/addon-firefox/compact-rules.json +1 -1
- package/dist/addon-firefox/content.bundle.js +253 -93
- 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/background.bundle.js +21 -0
- package/dist/addon-mv3/compact-rules.json +1 -1
- package/dist/addon-mv3/content.bundle.js +253 -93
- 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 +253 -93
- package/dist/autoconsent.esm.js +253 -93
- package/dist/autoconsent.playwright.js +253 -93
- package/dist/autoconsent.standalone.js +254 -94
- package/dist/heuristics.cjs.js +29 -3
- package/dist/heuristics.mjs +28 -3
- package/dist/types/cmps/onetrust.d.ts +1 -0
- package/dist/types/eval-snippets.d.ts +3 -0
- package/dist/types/heuristic-classify.d.ts +1 -0
- package/dist/types/heuristics.d.ts +10 -1
- package/lib/cmps/onetrust.ts +15 -0
- package/lib/eval-snippets.ts +21 -0
- package/lib/heuristic-classify.ts +6 -0
- package/lib/heuristic-patterns.ts +26 -1
- package/lib/heuristics.ts +256 -104
- package/package.json +1 -1
- package/playwright/isolated-world.mjs +217 -0
- package/playwright/oxylabs.mjs +196 -0
- package/playwright/runner.ts +183 -39
- package/playwright.config.ts +4 -1
- package/rules/autoconsent/aeolservice.json +39 -0
- package/rules/autoconsent/amazon-music.json +13 -0
- package/rules/autoconsent/annunci69.json +19 -0
- package/rules/autoconsent/arbeidsplassen-nav-no.json +33 -0
- package/rules/autoconsent/att.json +36 -0
- package/rules/autoconsent/auctionet.json +39 -0
- package/rules/autoconsent/autodoc.json +18 -0
- package/rules/autoconsent/bbc.com-orb-cosmetic.json +34 -0
- package/rules/autoconsent/bbc.com.json +8 -5
- package/rules/autoconsent/bokadirekt.se.json +50 -0
- package/rules/autoconsent/bouvet-cookiepanel.json +29 -0
- package/rules/autoconsent/consent-studio.json +25 -13
- package/rules/autoconsent/cookielegit.json +21 -0
- package/rules/autoconsent/cookieprompter.json +21 -0
- package/rules/autoconsent/cookiereports.json +10 -0
- package/rules/autoconsent/cookietractor.json +37 -0
- package/rules/autoconsent/de-volksbank.json +14 -0
- package/rules/autoconsent/dpgmedia-nl.json +20 -8
- package/rules/autoconsent/eon.pl.json +18 -0
- package/rules/autoconsent/eroticiracconti-it.json +13 -0
- package/rules/autoconsent/ersatzteile-24.json +49 -0
- package/rules/autoconsent/gravito.json +23 -16
- package/rules/autoconsent/hacon-next-gen.json +41 -0
- package/rules/autoconsent/ing-de.json +31 -0
- package/rules/autoconsent/interia.json +1 -4
- package/rules/autoconsent/intesasanpaolo.json +37 -0
- package/rules/autoconsent/jobindex.json +40 -0
- package/rules/autoconsent/kaspersky-cookies-notification.json +9 -0
- package/rules/autoconsent/lantmateriet.json +13 -0
- package/rules/autoconsent/mainichi.json +39 -0
- package/rules/autoconsent/mango.json +56 -0
- package/rules/autoconsent/nederlandseloterij.json +35 -0
- package/rules/autoconsent/nordea.json +21 -0
- package/rules/autoconsent/nordnet.json +33 -0
- package/rules/autoconsent/ok.json +4 -12
- package/rules/autoconsent/onlineradiobox.json +35 -0
- package/rules/autoconsent/pe-cookies.json +30 -0
- package/rules/autoconsent/pensionsmyndigheten.json +13 -0
- package/rules/autoconsent/pro-euclp-cookies-box.json +31 -0
- package/rules/autoconsent/pubfactory.json +45 -0
- package/rules/autoconsent/puesc-gov-pl.json +37 -0
- package/rules/autoconsent/rambler.json +30 -0
- package/rules/autoconsent/rejestr-io.json +36 -0
- package/rules/autoconsent/schumacher.com.json +53 -0
- package/rules/autoconsent/sitevision.json +18 -1
- package/rules/autoconsent/skatteverket-se.json +33 -0
- package/rules/autoconsent/smile-insurances.json +13 -0
- package/rules/autoconsent/svt.se.json +7 -7
- package/rules/autoconsent/temu.json +12 -16
- package/rules/autoconsent/thecode.json +21 -0
- package/rules/autoconsent/uk-parliament.json +19 -0
- package/rules/autoconsent/wirtualna-polska.json +13 -10
- package/rules/autoconsent/xenforo-cookie-consent.json +62 -0
- package/rules/autoconsent/zorginstituut-cookiewarning.json +33 -0
- package/rules/compact-rules.json +1 -1
- package/rules/rule-index.json +1 -1
- package/rules/rules.json +1 -1
- package/tests/aeolservice.spec.ts +5 -0
- package/tests/amazon-music.spec.ts +9 -0
- package/tests/annunci69.spec.ts +5 -0
- package/tests/arbeidsplassen-nav-no.spec.ts +3 -0
- package/tests/att.spec.ts +3 -0
- package/tests/auctionet.spec.ts +3 -0
- package/tests/autodoc.spec.ts +8 -0
- package/tests/bbc.com-orb-cosmetic.spec.ts +8 -0
- package/tests/bbc.com.spec.ts +11 -9
- package/tests/bokadirekt.se.spec.ts +3 -0
- package/tests/bouvet-cookiepanel.spec.ts +9 -0
- package/tests/consent-studio.spec.ts +5 -0
- package/tests/cookiebot.spec.ts +1 -0
- package/tests/cookielegit.spec.ts +3 -0
- package/tests/cookieprompter.spec.ts +9 -0
- package/tests/cookiereports.spec.ts +13 -0
- package/tests/cookietractor.spec.ts +12 -0
- package/tests/de-volksbank.spec.ts +5 -0
- package/tests/dpgmedia-nl.spec.ts +15 -1
- package/tests/eon.pl.spec.ts +3 -0
- package/tests/eroticiracconti-it.spec.ts +3 -0
- package/tests/ersatzteile-24.spec.ts +6 -0
- package/tests/gravito.spec.ts +7 -1
- package/tests/hacon-next-gen.spec.ts +6 -0
- package/tests/ing-de.spec.ts +3 -0
- package/tests/interia.spec.ts +1 -1
- package/tests/intesasanpaolo.spec.ts +3 -0
- package/tests/jobindex.spec.ts +3 -0
- package/tests/kaspersky-cookies-notification.spec.ts +8 -0
- package/tests/lantmateriet.spec.ts +3 -0
- package/tests/mainichi.spec.ts +10 -0
- package/tests/mango.spec.ts +3 -0
- package/tests/nederlandseloterij.spec.ts +9 -0
- package/tests/nordea.spec.ts +6 -0
- package/tests/nordnet.spec.ts +8 -0
- package/tests/onlineradiobox.spec.ts +5 -0
- package/tests/pe-cookies.spec.ts +6 -0
- package/tests/pensionsmyndigheten.spec.ts +3 -0
- package/tests/pro-euclp-cookies-box.spec.ts +8 -0
- package/tests/pubfactory.spec.ts +10 -0
- package/tests/puesc-gov-pl.spec.ts +3 -0
- package/tests/rambler.spec.ts +3 -0
- package/tests/rejestr-io.spec.ts +3 -0
- package/tests/schumacher.com.spec.ts +6 -0
- package/tests/sitevision-cookie-consent.spec.ts +1 -0
- package/tests/sitevision.spec.ts +7 -0
- package/tests/skatteverket-se.spec.ts +3 -0
- package/tests/smile-insurances.spec.ts +6 -0
- package/tests/svt.se.spec.ts +1 -3
- package/tests/temu.spec.ts +3 -1
- package/tests/thecode.spec.ts +3 -0
- package/tests/uk-parliament.spec.ts +8 -0
- package/tests/wirtualna-polska.spec.ts +6 -1
- package/tests/xenforo-cookie-consent.spec.ts +6 -0
- package/tests/zorginstituut-cookiewarning.spec.ts +10 -0
- package/tests-wtr/heuristics/get-potential-popups.test.ts +330 -9
- package/tests-wtr/heuristics/heuristics-utils.test.ts +98 -0
- package/rules/autoconsent/twitter.json +0 -34
- package/rules/generated/auto_CH_autodoc.de_krd.json +0 -40
- package/rules/generated/auto_CH_svtplay.se_d39.json +0 -40
- package/rules/generated/auto_GB_parliamentlive.tv_r3v.json +0 -28
- package/rules/generated/auto_NL_asnbank.nl_e28.json +0 -40
- package/rules/generated/auto_NL_eurojackpot.nederlandseloterij.nl_7hr.json +0 -40
- package/rules/generated/auto_NL_lotto.nederlandseloterij.nl_7c8.json +0 -40
- package/rules/generated/auto_NL_nederlandseloterij.nl_b60.json +0 -40
- package/rules/generated/auto_NL_staatsloterij.nederlandseloterij.nl_197.json +0 -40
- package/rules/generated/auto_NO_arronet.se_vo5.json +0 -40
- package/rules/generated/auto_NO_liseberg.se_qy4.json +0 -40
- package/rules/generated/auto_NO_nordnet.se_2en.json +0 -40
- package/rules/generated/auto_NO_regeringen.se_uhv.json +0 -40
- package/rules/generated/auto_NO_svtplay.se_ujn.json +0 -40
- package/rules/generated/auto_NO_uu.se_eea.json +0 -40
- package/tests/generated/auto_CH_autodoc.de_krd.spec.ts +0 -2
- package/tests/generated/auto_CH_svtplay.se_d39.spec.ts +0 -2
- package/tests/generated/auto_GB_parliamentlive.tv_r3v.spec.ts +0 -6
- package/tests/generated/auto_NL_asnbank.nl_e28.spec.ts +0 -6
- package/tests/generated/auto_NL_eurojackpot.nederlandseloterij.nl_7hr.spec.ts +0 -6
- package/tests/generated/auto_NL_lotto.nederlandseloterij.nl_7c8.spec.ts +0 -6
- package/tests/generated/auto_NL_nederlandseloterij.nl_b60.spec.ts +0 -6
- package/tests/generated/auto_NL_staatsloterij.nederlandseloterij.nl_197.spec.ts +0 -6
- package/tests/generated/auto_NO_arronet.se_vo5.spec.ts +0 -2
- package/tests/generated/auto_NO_liseberg.se_qy4.spec.ts +0 -2
- package/tests/generated/auto_NO_nordnet.se_2en.spec.ts +0 -2
- package/tests/generated/auto_NO_regeringen.se_uhv.spec.ts +0 -6
- package/tests/generated/auto_NO_svtplay.se_ujn.spec.ts +0 -2
- package/tests/generated/auto_NO_uu.se_eea.spec.ts +0 -2
- package/tests/twitter.spec.ts +0 -10
package/dist/autoconsent.cjs.js
CHANGED
|
@@ -372,6 +372,27 @@ var snippets = {
|
|
|
372
372
|
EVAL_COOKIEFIRST_1: () => document.querySelectorAll("button[data-cookiefirst-accent-color=true][role=checkbox]:not([disabled])").forEach((i) => i.getAttribute("aria-checked") === "true" && i.click()) || true,
|
|
373
373
|
EVAL_COOKIEINFORMATION_0: () => CookieInformation.declineAllCategories() || true,
|
|
374
374
|
EVAL_COOKIEINFORMATION_1: () => CookieInformation.submitAllCategories() || true,
|
|
375
|
+
// banner button order and meaning are configurable per site, so set the consent levels through the public API
|
|
376
|
+
EVAL_COOKIEREPORTS_OPT_OUT: () => {
|
|
377
|
+
const cr = window._cookiereports;
|
|
378
|
+
if (typeof cr?.saveConsent !== "function") return false;
|
|
379
|
+
cr.saveConsent({ 1: true, 2: false, 3: false, 4: false, 5: false });
|
|
380
|
+
cr.processConsent("banner", { trigger: "ok" });
|
|
381
|
+
cr.hideBanner();
|
|
382
|
+
return true;
|
|
383
|
+
},
|
|
384
|
+
EVAL_COOKIEREPORTS_OPT_IN: () => {
|
|
385
|
+
const cr = window._cookiereports;
|
|
386
|
+
if (typeof cr?.saveConsent !== "function") return false;
|
|
387
|
+
cr.saveConsent({ 1: true, 2: true, 3: true, 4: true, 5: true });
|
|
388
|
+
cr.processConsent("banner", { trigger: "ok" });
|
|
389
|
+
cr.hideBanner();
|
|
390
|
+
return true;
|
|
391
|
+
},
|
|
392
|
+
EVAL_COOKIEREPORTS_TEST: () => {
|
|
393
|
+
const levels = window._cookiereports?.loadConsent?.();
|
|
394
|
+
return !!levels && Object.keys(levels).length > 0 && Object.values(levels).every((v) => !v);
|
|
395
|
+
},
|
|
375
396
|
// turn the single-button form into a decline submission, same fields as the CMP's own decline form
|
|
376
397
|
EVAL_EE_CONSENT_DECLINE_0: () => document.querySelectorAll('#cookieConsentFormAccept input[name^="ee:cookies_"]').forEach((i) => i.value = "n") || true,
|
|
377
398
|
EVAL_ETSY_0: () => document.querySelectorAll(".gdpr-overlay-body input").forEach((toggle) => {
|
|
@@ -622,10 +643,20 @@ var DETECT_PATTERNS = [
|
|
|
622
643
|
// "файлы cookie" / "cookie-файлы" / "куки-файлы" in any phrasing
|
|
623
644
|
/(?:файл[а-яё]*[\s-]+(?:cookie|куки)|(?:cookie|куки)[\s-]+файл[а-яё]*)/gi,
|
|
624
645
|
// Italian (IT)
|
|
625
|
-
|
|
646
|
+
// e.g. "usiamo i cookie", "utilizziamo cookie tecnici", "questo sito utilizza i cookie", "noi e i nostri partner utilizziamo i cookie"
|
|
647
|
+
/(?:usiamo|utilizziamo).{0,20}cookie/gi,
|
|
648
|
+
/sito.{0,50}(?:usa|utilizza).{0,20}cookie/gi,
|
|
649
|
+
/noi e i nostri.{0,20}partner.{0,100}cookie/gi,
|
|
650
|
+
/(?:archiviare|memorizzare) e\/o accedere a informazioni su un dispositivo/gi,
|
|
651
|
+
// Swedish (SV)
|
|
652
|
+
// e.g. "vi använder cookies", "vi använder spårningstekniker såsom cookies", "webbplatsen använder kakor"
|
|
653
|
+
/(?:vi|webbplatsen|webbplats|sajten|sidan)\s+använder.{0,60}(?:cookies|kakor)/gi,
|
|
626
654
|
// Japanese (JA)
|
|
627
655
|
// e.g. "当サイトはCookieを使用しています", "クッキー(Cookie)を利用しています"
|
|
628
|
-
/(?:cookie|クッキー).{0,10}を(?:使用|利用)/gi
|
|
656
|
+
/(?:cookie|クッキー).{0,10}を(?:使用|利用)/gi,
|
|
657
|
+
// Danish (DA)
|
|
658
|
+
// e.g. "vi bruger cookies", "hjemmesiden bruger cookies til at ..."
|
|
659
|
+
/bruger cookies/gi
|
|
629
660
|
];
|
|
630
661
|
var REJECT_PATTERNS_ENGLISH = [
|
|
631
662
|
// e.g. "reject", "reject all", "reject all cookies", "deny all", "refuse cookies", "decline",
|
|
@@ -759,6 +790,14 @@ var REJECT_PATTERNS_SWEDISH = [
|
|
|
759
790
|
"till\xE5t inte cookies",
|
|
760
791
|
"jag accepterar endast grundl\xE4ggande kakor"
|
|
761
792
|
];
|
|
793
|
+
var REJECT_PATTERNS_DANISH = [
|
|
794
|
+
// afvis / afvis alle / afvis alle cookies (reject verbs)
|
|
795
|
+
/(^|\s)afvis/is,
|
|
796
|
+
// (accept/allow) only necessary cookies
|
|
797
|
+
/^(accepter\s+|tillad\s+)?(kun|udelukkende)\s+(strengt\s+)?nødvendige( cookies)?$/is,
|
|
798
|
+
// "nej tak" (no thanks)
|
|
799
|
+
/^nej(,?\s+tak)?$/is
|
|
800
|
+
];
|
|
762
801
|
var REJECT_PATTERNS_CATALAN = [/(^|\s)rebutj/is, "no accepto", "no, gr\xE0cies"];
|
|
763
802
|
var REJECT_PATTERNS_GALICIAN = [/(^|\s)rexeitar/is];
|
|
764
803
|
var REJECT_PATTERNS_BASQUE = [/(^|\s)(baztertu|ukatu)/is];
|
|
@@ -805,6 +844,7 @@ var REJECT_PATTERNS = [
|
|
|
805
844
|
...REJECT_PATTERNS_BRAZILIAN_PORTUGUESE,
|
|
806
845
|
...REJECT_PATTERNS_SPANISH,
|
|
807
846
|
...REJECT_PATTERNS_SWEDISH,
|
|
847
|
+
...REJECT_PATTERNS_DANISH,
|
|
808
848
|
...REJECT_PATTERNS_CATALAN,
|
|
809
849
|
...REJECT_PATTERNS_GALICIAN,
|
|
810
850
|
...REJECT_PATTERNS_BASQUE,
|
|
@@ -1154,7 +1194,8 @@ var ACCEPT_PATTERNS = [
|
|
|
1154
1194
|
"kabul et",
|
|
1155
1195
|
// Italian (IT)
|
|
1156
1196
|
"accetta",
|
|
1157
|
-
"accetta tutti i cookie"
|
|
1197
|
+
"accetta tutti i cookie",
|
|
1198
|
+
"accetto tutti i cookie"
|
|
1158
1199
|
];
|
|
1159
1200
|
var ACKNOWLEDGE_PATTERNS = [
|
|
1160
1201
|
// close / dismiss the banner/dialog/message (multilingual). The negative lookahead avoids
|
|
@@ -1230,6 +1271,10 @@ function checkHeuristicPatterns(allText, detectPatterns = DETECT_PATTERNS) {
|
|
|
1230
1271
|
}
|
|
1231
1272
|
return { patterns, snippets: snippets2 };
|
|
1232
1273
|
}
|
|
1274
|
+
function hasHeuristicPatterns(allText, detectPatterns = DETECT_PATTERNS) {
|
|
1275
|
+
const text = allText.slice(0, TEXT_LIMIT);
|
|
1276
|
+
return detectPatterns.some((p) => text.search(p) !== -1);
|
|
1277
|
+
}
|
|
1233
1278
|
function classifyButtons(buttons) {
|
|
1234
1279
|
for (const button of buttons) {
|
|
1235
1280
|
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
@@ -1306,57 +1351,135 @@ var BUTTON_LIKE_ELEMENT_SELECTOR = 'button, input[type="button"], input[type="su
|
|
|
1306
1351
|
var POPUP_SEARCH_MAX_TIME = 100;
|
|
1307
1352
|
function getActionablePopups(mode = "reject", timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1308
1353
|
const acceptedLevels = mode === "tier2" ? ["reject", "tier1", "tier2"] : mode === "tier1" ? ["reject", "tier1"] : ["reject"];
|
|
1309
|
-
|
|
1310
|
-
return [];
|
|
1311
|
-
}
|
|
1312
|
-
const popups = getPotentialPopups(timeout);
|
|
1313
|
-
const result = popups.reduce((acc, popup) => {
|
|
1354
|
+
const popups = getPotentialPopups(timeout).filter((popup) => {
|
|
1314
1355
|
const popupText = popup.text?.trim();
|
|
1315
|
-
if (popupText) {
|
|
1316
|
-
|
|
1317
|
-
return acc;
|
|
1318
|
-
}
|
|
1319
|
-
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1320
|
-
if (patterns.length > 0) {
|
|
1321
|
-
classifyButtons(popup.buttons);
|
|
1322
|
-
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1323
|
-
acc.push({
|
|
1324
|
-
...popup
|
|
1325
|
-
});
|
|
1326
|
-
}
|
|
1356
|
+
if (!popupText || isExcludedPopup(popupText) || !hasHeuristicPatterns(popupText)) {
|
|
1357
|
+
return false;
|
|
1327
1358
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1359
|
+
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1360
|
+
return popup.regexClassification !== void 0 && acceptedLevels.includes(popup.regexClassification);
|
|
1361
|
+
});
|
|
1362
|
+
return popups.sort((a, b) => (a.regexClassification ?? "") > (b.regexClassification ?? "") ? 1 : -1);
|
|
1331
1363
|
}
|
|
1332
1364
|
function getPotentialPopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
}
|
|
1337
|
-
return collectPotentialPopups(isFramed, timeout);
|
|
1338
|
-
}
|
|
1339
|
-
function collectPotentialPopups(isFramed, timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1340
|
-
let elements = [];
|
|
1341
|
-
if (!isFramed) {
|
|
1342
|
-
elements = getPopupLikeElements(timeout);
|
|
1343
|
-
} else {
|
|
1344
|
-
const doc = document.body || document.documentElement;
|
|
1345
|
-
if (doc && isElementVisible(doc) && doc.innerText) {
|
|
1346
|
-
elements.push(doc);
|
|
1365
|
+
if (!isTopFrame()) {
|
|
1366
|
+
if (window.parent && window.parent !== window.top) {
|
|
1367
|
+
return [];
|
|
1347
1368
|
}
|
|
1369
|
+
const frameElement = getFramePopupElement(document);
|
|
1370
|
+
const popup = frameElement && toPopupData(frameElement);
|
|
1371
|
+
return popup ? [popup] : [];
|
|
1348
1372
|
}
|
|
1373
|
+
const deadline = performance.now() + timeout;
|
|
1374
|
+
const { elements, shadowHosts } = getPopupLikeElements(deadline);
|
|
1349
1375
|
const potentialPopups = [];
|
|
1376
|
+
const expanded = [];
|
|
1350
1377
|
for (const el of elements) {
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1378
|
+
const popup = toPopupData(el, shadowHosts);
|
|
1379
|
+
if (!popup) {
|
|
1380
|
+
continue;
|
|
1381
|
+
}
|
|
1382
|
+
const root = performance.now() > deadline ? popup : expandPopupFragment(popup, shadowHosts);
|
|
1383
|
+
if (potentialPopups.some((p) => p.element === root.element)) {
|
|
1384
|
+
continue;
|
|
1385
|
+
}
|
|
1386
|
+
if (root !== popup) {
|
|
1387
|
+
expanded.push(root.element);
|
|
1388
|
+
}
|
|
1389
|
+
potentialPopups.push(root);
|
|
1390
|
+
}
|
|
1391
|
+
return potentialPopups.filter((p) => !expanded.some((root) => root !== p.element && composedContains(root, p.element)));
|
|
1392
|
+
}
|
|
1393
|
+
function toPopupData(el, shadowHosts, text = getElementText(el)) {
|
|
1394
|
+
if (!text) {
|
|
1395
|
+
return null;
|
|
1396
|
+
}
|
|
1397
|
+
const buttons = getButtonData(el, shadowHosts);
|
|
1398
|
+
classifyButtons(buttons);
|
|
1399
|
+
return { text, element: el, buttons };
|
|
1400
|
+
}
|
|
1401
|
+
function hasPopupButtons(text, buttons) {
|
|
1402
|
+
return !isOnlyButtonText(text, buttons) && buttons.some((b) => b.regexClassification !== "other");
|
|
1403
|
+
}
|
|
1404
|
+
function isOnlyButtonText(text, buttons) {
|
|
1405
|
+
let rest = text;
|
|
1406
|
+
for (const button of buttons) {
|
|
1407
|
+
rest = rest.replace(button.text, "");
|
|
1408
|
+
}
|
|
1409
|
+
return rest.replace(/\s+/g, "").length < 10;
|
|
1410
|
+
}
|
|
1411
|
+
var MAX_FRAGMENT_EXPANSION_DEPTH = 6;
|
|
1412
|
+
function expandPopupFragment(popup, shadowHosts) {
|
|
1413
|
+
if (hasHeuristicPatterns(popup.text) && hasPopupButtons(popup.text, popup.buttons)) {
|
|
1414
|
+
return popup;
|
|
1415
|
+
}
|
|
1416
|
+
let el = getComposedParent(popup.element);
|
|
1417
|
+
for (let depth = 0; el && depth < MAX_FRAGMENT_EXPANSION_DEPTH; depth++, el = getComposedParent(el)) {
|
|
1418
|
+
if (el === document.body || el === document.documentElement || el.getBoundingClientRect().height > window.innerHeight) {
|
|
1419
|
+
break;
|
|
1420
|
+
}
|
|
1421
|
+
const text = getElementText(el);
|
|
1422
|
+
if (!text || !hasHeuristicPatterns(text)) {
|
|
1423
|
+
continue;
|
|
1424
|
+
}
|
|
1425
|
+
const root = toPopupData(el, shadowHosts, text);
|
|
1426
|
+
if (root && hasPopupButtons(text, root.buttons)) {
|
|
1427
|
+
return root;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
return popup;
|
|
1431
|
+
}
|
|
1432
|
+
function getComposedParent(el) {
|
|
1433
|
+
if (el.parentElement) {
|
|
1434
|
+
return el.parentElement;
|
|
1435
|
+
}
|
|
1436
|
+
const parent = el.parentNode;
|
|
1437
|
+
return parent instanceof ShadowRoot && parent.host instanceof HTMLElement ? parent.host : null;
|
|
1438
|
+
}
|
|
1439
|
+
function getFramePopupElement(doc) {
|
|
1440
|
+
const el = doc.body || doc.documentElement;
|
|
1441
|
+
const win = doc.defaultView;
|
|
1442
|
+
if (!el || !win || win.innerWidth === 0 || win.innerHeight === 0 || !isStyleVisible(el)) {
|
|
1443
|
+
return null;
|
|
1444
|
+
}
|
|
1445
|
+
return getElementText(el).trim() ? el : null;
|
|
1446
|
+
}
|
|
1447
|
+
function isStyleVisible(el) {
|
|
1448
|
+
return typeof el.checkVisibility !== "function" || el.checkVisibility({ checkVisibilityCSS: true });
|
|
1449
|
+
}
|
|
1450
|
+
function getElementText(el) {
|
|
1451
|
+
const text = el.innerText || "";
|
|
1452
|
+
if (!el.shadowRoot) {
|
|
1453
|
+
return text;
|
|
1454
|
+
}
|
|
1455
|
+
const shadowTexts = Array.from(el.shadowRoot.children, (child) => isRenderedTextElement(child) ? getElementText(child) : "");
|
|
1456
|
+
return [text, ...shadowTexts].filter((t) => t.trim()).join("\n");
|
|
1457
|
+
}
|
|
1458
|
+
function isRenderedTextElement(el) {
|
|
1459
|
+
return el instanceof HTMLElement && !["STYLE", "SCRIPT", "TEMPLATE", "NOSCRIPT", "LINK", "SLOT"].includes(el.tagName) && window.getComputedStyle(el).display !== "none";
|
|
1460
|
+
}
|
|
1461
|
+
function composedContains(container, node) {
|
|
1462
|
+
if (container.contains(node)) {
|
|
1463
|
+
return true;
|
|
1464
|
+
}
|
|
1465
|
+
let root = node.getRootNode();
|
|
1466
|
+
while (root instanceof ShadowRoot) {
|
|
1467
|
+
if (container.contains(root.host)) {
|
|
1468
|
+
return true;
|
|
1357
1469
|
}
|
|
1470
|
+
root = root.host.getRootNode();
|
|
1471
|
+
}
|
|
1472
|
+
return false;
|
|
1473
|
+
}
|
|
1474
|
+
function isPopupCandidateVisible(el) {
|
|
1475
|
+
return isElementVisible(el) && isStyleVisible(el) && isOnScreen(el);
|
|
1476
|
+
}
|
|
1477
|
+
function isOnScreen(el) {
|
|
1478
|
+
const rect = el.getBoundingClientRect();
|
|
1479
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
1480
|
+
return window.getComputedStyle(el).overflow === "visible" && Array.from(el.children).some((child) => isOnScreen(child));
|
|
1358
1481
|
}
|
|
1359
|
-
return
|
|
1482
|
+
return rect.bottom > 0 && rect.right > 0 && rect.top < window.innerHeight && rect.left < window.innerWidth;
|
|
1360
1483
|
}
|
|
1361
1484
|
function isDialogLikeElement(node) {
|
|
1362
1485
|
if (node.tagName === "DIALOG" && node.hasAttribute("open")) {
|
|
@@ -1367,72 +1490,95 @@ function isDialogLikeElement(node) {
|
|
|
1367
1490
|
}
|
|
1368
1491
|
return false;
|
|
1369
1492
|
}
|
|
1370
|
-
function getPopupLikeElements(
|
|
1371
|
-
const
|
|
1372
|
-
const
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1493
|
+
function getPopupLikeElements(deadline) {
|
|
1494
|
+
const found = [];
|
|
1495
|
+
const shadowHosts = [];
|
|
1496
|
+
const roots = [document.documentElement];
|
|
1497
|
+
for (let i = 0; i < roots.length; i++) {
|
|
1498
|
+
if (i > 0 && performance.now() > deadline) {
|
|
1499
|
+
break;
|
|
1500
|
+
}
|
|
1501
|
+
const walker = document.createTreeWalker(
|
|
1502
|
+
roots[i],
|
|
1503
|
+
NodeFilter.SHOW_ELEMENT,
|
|
1504
|
+
// visit only element nodes
|
|
1505
|
+
{
|
|
1506
|
+
acceptNode(node) {
|
|
1507
|
+
if (node.shadowRoot) {
|
|
1508
|
+
shadowHosts.push(node);
|
|
1509
|
+
roots.push(node.shadowRoot);
|
|
1510
|
+
}
|
|
1511
|
+
if (node.tagName === "BODY") {
|
|
1512
|
+
return NodeFilter.FILTER_SKIP;
|
|
1385
1513
|
}
|
|
1386
|
-
|
|
1514
|
+
const style = window.getComputedStyle(node);
|
|
1515
|
+
if (style.display === "none") {
|
|
1516
|
+
return NodeFilter.FILTER_REJECT;
|
|
1517
|
+
}
|
|
1518
|
+
const cssPosition = style.position;
|
|
1519
|
+
if ((cssPosition === "fixed" || cssPosition === "sticky" || isDialogLikeElement(node)) && isPopupCandidateVisible(node)) {
|
|
1387
1520
|
return NodeFilter.FILTER_ACCEPT;
|
|
1388
1521
|
}
|
|
1522
|
+
if (performance.now() > deadline) {
|
|
1523
|
+
return NodeFilter.FILTER_REJECT;
|
|
1524
|
+
}
|
|
1525
|
+
return NodeFilter.FILTER_SKIP;
|
|
1389
1526
|
}
|
|
1390
|
-
if (performance.now() - startTime > timeout) {
|
|
1391
|
-
return NodeFilter.FILTER_REJECT;
|
|
1392
|
-
}
|
|
1393
|
-
return NodeFilter.FILTER_SKIP;
|
|
1394
1527
|
}
|
|
1528
|
+
);
|
|
1529
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
1530
|
+
found.push(node);
|
|
1395
1531
|
}
|
|
1396
|
-
);
|
|
1397
|
-
const found = [];
|
|
1398
|
-
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
1399
|
-
found.push(node);
|
|
1400
1532
|
}
|
|
1401
|
-
return excludeContainers(found.filter((element) => element.
|
|
1533
|
+
return { elements: excludeContainers(found.filter((element) => getElementText(element).trim())), shadowHosts };
|
|
1402
1534
|
}
|
|
1403
|
-
function getButtonData(el) {
|
|
1404
|
-
const
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
text
|
|
1410
|
-
|
|
1411
|
-
|
|
1535
|
+
function getButtonData(el, shadowHosts) {
|
|
1536
|
+
const buttons = [];
|
|
1537
|
+
for (const b of excludeContainers(getButtonLikeElements(el, shadowHosts))) {
|
|
1538
|
+
if (!isElementVisible(b) || isDisabled(b)) {
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
const text = getElementText(b).trim() || // <input> values do not appear in innerText
|
|
1542
|
+
(b instanceof HTMLInputElement && ["submit", "button"].includes(b.type) ? b.value?.trim() : "");
|
|
1543
|
+
if (text) {
|
|
1544
|
+
buttons.push({ text, element: b });
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
return buttons;
|
|
1412
1548
|
}
|
|
1413
|
-
function getButtonLikeElements(el) {
|
|
1414
|
-
|
|
1549
|
+
function getButtonLikeElements(el, shadowHosts = findShadowHosts(el)) {
|
|
1550
|
+
const buttons = Array.from(el.querySelectorAll(BUTTON_LIKE_ELEMENT_SELECTOR));
|
|
1551
|
+
for (const host of shadowHosts) {
|
|
1552
|
+
if (composedContains(el, host)) {
|
|
1553
|
+
buttons.push(...host.shadowRoot.querySelectorAll(BUTTON_LIKE_ELEMENT_SELECTOR));
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
return buttons;
|
|
1557
|
+
}
|
|
1558
|
+
function findShadowHosts(root) {
|
|
1559
|
+
const hosts = [];
|
|
1560
|
+
const candidates = root instanceof HTMLElement ? [root, ...root.querySelectorAll("*")] : root.querySelectorAll("*");
|
|
1561
|
+
for (const el of candidates) {
|
|
1562
|
+
if (el.shadowRoot) {
|
|
1563
|
+
hosts.push(el, ...findShadowHosts(el.shadowRoot));
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return hosts;
|
|
1415
1567
|
}
|
|
1416
1568
|
function isDisabled(el) {
|
|
1417
1569
|
return "disabled" in el && Boolean(el.disabled) || el.hasAttribute("disabled");
|
|
1418
1570
|
}
|
|
1419
1571
|
function excludeContainers(elements) {
|
|
1420
|
-
const
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
container = true;
|
|
1427
|
-
break;
|
|
1428
|
-
}
|
|
1429
|
-
}
|
|
1430
|
-
if (!container) {
|
|
1431
|
-
results.push(elements[i]);
|
|
1572
|
+
const candidates = new Set(elements);
|
|
1573
|
+
const containers = /* @__PURE__ */ new Set();
|
|
1574
|
+
for (const el of elements) {
|
|
1575
|
+
for (let node = el.parentNode; node; node = node.parentNode || (node instanceof ShadowRoot ? node.host : null)) {
|
|
1576
|
+
if (candidates.has(node)) {
|
|
1577
|
+
containers.add(node);
|
|
1432
1578
|
}
|
|
1433
1579
|
}
|
|
1434
1580
|
}
|
|
1435
|
-
return
|
|
1581
|
+
return elements.filter((el) => !containers.has(el)).reverse();
|
|
1436
1582
|
}
|
|
1437
1583
|
|
|
1438
1584
|
// lib/cmps/base.ts
|
|
@@ -2226,6 +2372,18 @@ var Onetrust = class extends AutoConsentCMPBase {
|
|
|
2226
2372
|
get isCosmetic() {
|
|
2227
2373
|
return false;
|
|
2228
2374
|
}
|
|
2375
|
+
// Some sites pre-render the banner before the SDK loads, and clicks before then may be lost.
|
|
2376
|
+
// Sites that copy the markup without the SDK never get #onetrust-style, so only wait when the page loads the SDK.
|
|
2377
|
+
async waitForSdk() {
|
|
2378
|
+
if (this.elementExists("#onetrust-style")) {
|
|
2379
|
+
return;
|
|
2380
|
+
}
|
|
2381
|
+
const sdkRef = /cookielaw\.org|otSDKStub|otBannerSdk/;
|
|
2382
|
+
const sdkExpected = Array.from(document.scripts).some((s) => sdkRef.test(s.src) || !s.src && sdkRef.test(s.textContent || ""));
|
|
2383
|
+
if (sdkExpected) {
|
|
2384
|
+
await this.waitForElement("#onetrust-style", 1e4);
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2229
2387
|
async detectCmp() {
|
|
2230
2388
|
return this.elementExists("#onetrust-banner-sdk") || this.elementVisible("#onetrust-pc-sdk", "any");
|
|
2231
2389
|
}
|
|
@@ -2234,6 +2392,7 @@ var Onetrust = class extends AutoConsentCMPBase {
|
|
|
2234
2392
|
}
|
|
2235
2393
|
async optOut() {
|
|
2236
2394
|
await this.wait(500);
|
|
2395
|
+
await this.waitForSdk();
|
|
2237
2396
|
if (this.elementVisible("#onetrust-reject-all-handler", "any")) {
|
|
2238
2397
|
return await this.click("#onetrust-reject-all-handler");
|
|
2239
2398
|
}
|
|
@@ -2273,6 +2432,7 @@ var Onetrust = class extends AutoConsentCMPBase {
|
|
|
2273
2432
|
return true;
|
|
2274
2433
|
}
|
|
2275
2434
|
async optIn() {
|
|
2435
|
+
await this.waitForSdk();
|
|
2276
2436
|
return await this.click("#onetrust-accept-btn-handler,#accept-recommended-btn-handler,.js-accept-cookies");
|
|
2277
2437
|
}
|
|
2278
2438
|
async test() {
|