@duckduckgo/autoconsent 16.26.0 → 16.28.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.md +1 -1
- package/CHANGELOG.md +45 -0
- package/dist/addon-firefox/compact-rules.json +1 -1
- package/dist/addon-firefox/content.bundle.js +28 -3
- 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 +28 -3
- 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 +28 -3
- package/dist/autoconsent.esm.js +28 -3
- package/dist/autoconsent.playwright.js +28 -3
- package/dist/autoconsent.standalone.js +29 -4
- package/dist/types/cmps/base.d.ts +1 -0
- package/dist/types/dom-actions.d.ts +1 -0
- package/dist/types/rules.d.ts +6 -2
- package/dist/types/utils.d.ts +1 -0
- package/docs/rule-syntax.md +14 -0
- package/lib/cmps/base.ts +7 -0
- package/lib/dom-actions.ts +7 -1
- package/lib/heuristic-patterns.ts +2 -2
- package/lib/rules.ts +9 -2
- package/lib/utils.ts +16 -0
- package/package.json +1 -1
- package/rules/autoconsent/amazon-pay.json +13 -0
- package/rules/autoconsent/bbva.json +12 -0
- package/rules/autoconsent/complianz-opt-out.json +6 -0
- package/rules/autoconsent/deliveroo.json +15 -0
- package/rules/autoconsent/ebay.json +34 -0
- package/rules/autoconsent/gemini-google-com.json +9 -0
- package/rules/autoconsent/justwatch-com.json +1 -1
- package/rules/autoconsent/kingrecords-co-jp.json +21 -0
- package/rules/autoconsent/paypal-us.json +4 -3
- package/rules/autoconsent/pornpics-de.json +1 -1
- package/rules/autoconsent/rule34-xxx.json +12 -0
- package/rules/autoconsent/sex.com.json +45 -0
- package/rules/autoconsent/theguardian.com.json +13 -3
- package/rules/autoconsent/twitch.json +27 -12
- package/rules/autoconsent/wpconsent.json +30 -0
- package/rules/autoconsent/xhamster-eu.json +3 -1
- package/rules/compact-rules.json +1 -1
- package/rules/rule-index.json +1 -1
- package/rules/rules.json +1 -1
- package/tests/amazon-pay.spec.ts +3 -0
- package/tests/bbva.spec.ts +4 -0
- package/tests/complianz-opt-out.spec.ts +5 -0
- package/tests/deliveroo.spec.ts +3 -0
- package/tests/gemini-google-com.spec.ts +5 -0
- package/tests/justwatch-com.spec.ts +1 -1
- package/tests/kingrecords-co-jp.spec.ts +3 -0
- package/tests/paypal-us.spec.ts +4 -0
- package/tests/pornpics-de.spec.ts +1 -1
- package/tests/rule34-xxx.spec.ts +6 -0
- package/tests/sex.com.spec.ts +3 -0
- package/tests/wpconsent.spec.ts +5 -0
- package/tests-wtr/dom-actions/dom-actions.stylesheet.html +13 -0
- package/tests-wtr/dom-actions/dom-actions.stylesheet.ts +26 -0
- package/tests-wtr/heuristics/heuristics-utils.test.ts +6 -0
- package/tests-wtr/utils/append-stylesheet-rule.html +11 -0
- package/tests-wtr/utils/append-stylesheet-rule.test.ts +29 -0
|
@@ -32,6 +32,7 @@ export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
|
32
32
|
waitForThenClick(selector: ElementSelector, timeout?: number, all?: boolean): Promise<boolean>;
|
|
33
33
|
wait(ms: number): Promise<true>;
|
|
34
34
|
hide(selector: string, method?: HideMethod): boolean;
|
|
35
|
+
stylesheet(cssRule: string, stylesheetId?: string): boolean;
|
|
35
36
|
removeClass(selector: ElementSelector, className: string): boolean;
|
|
36
37
|
setStyle(selector: ElementSelector, css: string): boolean;
|
|
37
38
|
addStyle(selector: ElementSelector, css: string): boolean;
|
|
@@ -14,6 +14,7 @@ export declare class DomActions implements DomActionsProvider {
|
|
|
14
14
|
wait(ms: number): Promise<true>;
|
|
15
15
|
cookieContains(substring: string): boolean;
|
|
16
16
|
hide(selector: string, method?: HideMethod): boolean;
|
|
17
|
+
stylesheet(cssRule: string, stylesheetId?: string): boolean;
|
|
17
18
|
removeClass(selector: ElementSelector, className: string): boolean;
|
|
18
19
|
setStyle(selector: ElementSelector, css: string): boolean;
|
|
19
20
|
addStyle(selector: ElementSelector, css: string): boolean;
|
package/dist/types/rules.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { snippets } from './eval-snippets';
|
|
2
|
-
export declare const SUPPORTED_RULE_STEP_VERSION =
|
|
2
|
+
export declare const SUPPORTED_RULE_STEP_VERSION = 3;
|
|
3
3
|
export type AutoConsentCMPRule = {
|
|
4
4
|
readonly name: string;
|
|
5
5
|
/**
|
|
@@ -33,7 +33,7 @@ export type ElementSelector = string | string[];
|
|
|
33
33
|
export type AutoConsentRuleStep = {
|
|
34
34
|
optional?: boolean;
|
|
35
35
|
comment?: string;
|
|
36
|
-
} & Partial<ElementExistsRule> & Partial<ElementVisibleRule> & Partial<EvalRule> & Partial<WaitForRule> & Partial<WaitForVisibleRule> & Partial<ClickRule> & Partial<WaitForThenClickRule> & Partial<WaitRule> & Partial<HideRule> & Partial<IfRule> & Partial<AnyRule> & Partial<NegatedRule> & Partial<CookieContainsRule> & Partial<RemoveClassRule> & Partial<SetStyleRule> & Partial<AddStyleRule>;
|
|
36
|
+
} & Partial<ElementExistsRule> & Partial<ElementVisibleRule> & Partial<EvalRule> & Partial<WaitForRule> & Partial<WaitForVisibleRule> & Partial<ClickRule> & Partial<WaitForThenClickRule> & Partial<WaitRule> & Partial<HideRule> & Partial<IfRule> & Partial<AnyRule> & Partial<NegatedRule> & Partial<CookieContainsRule> & Partial<RemoveClassRule> & Partial<SetStyleRule> & Partial<AddStyleRule> & Partial<StylesheetRule>;
|
|
37
37
|
export type NegatedRule = {
|
|
38
38
|
negated: boolean;
|
|
39
39
|
};
|
|
@@ -97,3 +97,7 @@ export type AddStyleRule = {
|
|
|
97
97
|
addStyle: string;
|
|
98
98
|
selector: ElementSelector;
|
|
99
99
|
};
|
|
100
|
+
export type StylesheetRule = {
|
|
101
|
+
stylesheet: string;
|
|
102
|
+
stylesheetId?: string;
|
|
103
|
+
};
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Config } from './types';
|
|
|
3
3
|
export declare function getStyleElement(styleOverrideElementId?: string): HTMLStyleElement;
|
|
4
4
|
export declare function getHidingStyle(method: HideMethod): string;
|
|
5
5
|
export declare function hideElements(styleEl: HTMLStyleElement, selector: string, method?: HideMethod): boolean;
|
|
6
|
+
export declare function appendStylesheetRule(styleEl: HTMLStyleElement, cssRule: string, marker?: string): boolean;
|
|
6
7
|
export declare function waitFor(predicate: () => Promise<boolean> | boolean, maxTimes: number, interval: number): Promise<boolean>;
|
|
7
8
|
export declare function isElementVisible(elem: HTMLElement): boolean;
|
|
8
9
|
export declare function copyObject(data: any): any;
|
package/docs/rule-syntax.md
CHANGED
|
@@ -154,6 +154,18 @@ Set the inline style of the elements matched by the `selector`. `style-string` i
|
|
|
154
154
|
```
|
|
155
155
|
Append the inline style of the elements matched by the `selector`. `style-string` is a string of CSS properties and values. The style is appended to the existing inline style, separated by a semicolon.
|
|
156
156
|
|
|
157
|
+
## Stylesheet
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
{
|
|
161
|
+
"stylesheet": "css-rule-string",
|
|
162
|
+
"stylesheetId": "unique-marker"
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
Append a CSS rule (e.g. `".overlay { display: none !important; }"`) to the style element injected by autoconsent. Unlike `setStyle`/`addStyle`, which modify inline styles of currently matched elements, an appended stylesheet rule keeps applying to elements matched later — useful when the page re-adds classes or inline styles after the opt-out (e.g. scroll locks reapplied on back/forward navigation).
|
|
166
|
+
|
|
167
|
+
The optional `stylesheetId` is a marker used to prevent duplicate inserts when the rule runs multiple times; if omitted, the CSS rule text itself is used for deduplication.
|
|
168
|
+
|
|
157
169
|
## Cookie match
|
|
158
170
|
```javascript
|
|
159
171
|
{
|
|
@@ -241,11 +253,13 @@ The `minimumRuleStepVersion` field solves this: clients compare the rule's decla
|
|
|
241
253
|
|---------|-----------------|
|
|
242
254
|
| 1 | All original step types (`exists`, `visible`, `waitFor`, `waitForVisible`, `click`, `waitForThenClick`, `wait`, `hide`, `if`/`then`/`else`, `any`, `eval`, `cookieContains`, `negated`) |
|
|
243
255
|
| 2 | `removeClass`, `setStyle`, `addStyle` |
|
|
256
|
+
| 3 | `stylesheet` |
|
|
244
257
|
|
|
245
258
|
### When to set it
|
|
246
259
|
|
|
247
260
|
- If a rule only uses version-1 step types, omit the field (defaults to `1`).
|
|
248
261
|
- If a rule uses `removeClass`, `setStyle`, or `addStyle`, set `"minimumRuleStepVersion": 2`.
|
|
262
|
+
- If a rule uses `stylesheet`, set `"minimumRuleStepVersion": 3`.
|
|
249
263
|
- When a future version introduces new step types, any rule using them must set `minimumRuleStepVersion` to the corresponding version number.
|
|
250
264
|
|
|
251
265
|
### Adding new step types
|
package/lib/cmps/base.ts
CHANGED
|
@@ -196,6 +196,10 @@ export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
|
196
196
|
return this.autoconsent.domActions.hide(selector, method);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
stylesheet(cssRule: string, stylesheetId?: string) {
|
|
200
|
+
return this.autoconsent.domActions.stylesheet(cssRule, stylesheetId);
|
|
201
|
+
}
|
|
202
|
+
|
|
199
203
|
removeClass(selector: ElementSelector, className: string) {
|
|
200
204
|
return this.autoconsent.domActions.removeClass(selector, className);
|
|
201
205
|
}
|
|
@@ -340,6 +344,9 @@ export class AutoConsentCMP extends AutoConsentCMPBase {
|
|
|
340
344
|
if (rule.hide) {
|
|
341
345
|
results.push(this.hide(rule.hide, rule.method));
|
|
342
346
|
}
|
|
347
|
+
if (rule.stylesheet !== undefined) {
|
|
348
|
+
results.push(this.stylesheet(rule.stylesheet, rule.stylesheetId));
|
|
349
|
+
}
|
|
343
350
|
if (rule.removeClass !== undefined) {
|
|
344
351
|
results.push(rule.selector ? this.removeClass(rule.selector, rule.removeClass) : false);
|
|
345
352
|
}
|
package/lib/dom-actions.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ElementSelector, HideMethod, VisibilityCheck } from './rules';
|
|
2
2
|
import { DomActionsProvider } from './types';
|
|
3
|
-
import { getStyleElement, hideElements, isElementVisible, waitFor } from './utils';
|
|
3
|
+
import { getStyleElement, hideElements, appendStylesheetRule, isElementVisible, waitFor } from './utils';
|
|
4
4
|
import AutoConsent from './web';
|
|
5
5
|
|
|
6
6
|
export class DomActions implements DomActionsProvider {
|
|
@@ -91,6 +91,12 @@ export class DomActions implements DomActionsProvider {
|
|
|
91
91
|
return hideElements(styleEl, selector, method);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
stylesheet(cssRule: string, stylesheetId?: string): boolean {
|
|
95
|
+
this.autoconsentInstance.config.logs.rulesteps && console.log('[stylesheet]', cssRule, stylesheetId);
|
|
96
|
+
const styleEl = getStyleElement();
|
|
97
|
+
return appendStylesheetRule(styleEl, cssRule, stylesheetId);
|
|
98
|
+
}
|
|
99
|
+
|
|
94
100
|
removeClass(selector: ElementSelector, className: string): boolean {
|
|
95
101
|
const elements = this.elementSelector(selector);
|
|
96
102
|
this.autoconsentInstance.config.logs.rulesteps && console.log('[removeClass]', selector, className, elements);
|
|
@@ -163,8 +163,8 @@ const REJECT_PATTERNS_ENGLISH = [
|
|
|
163
163
|
// note that "reject and subscribe" and "reject and pay" are excluded via BUTTON_NEVER_MATCH_PATTERNS
|
|
164
164
|
/^\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,
|
|
165
165
|
|
|
166
|
-
// e.g. "i do not accept", "do not accept cookies"
|
|
167
|
-
/^\s*(i\s+)?do\s+not\s+accept\s*(cookies)?\s*$/is,
|
|
166
|
+
// e.g. "i do not accept", "do not accept cookies", "i do not accept the use of cookies"
|
|
167
|
+
/^\s*(no,?\s*)?(i\s+)?do\s+not\s+accept\s*(the\s+use\s+of\s+)?(any\s+)?(cookies)?\s*$/is,
|
|
168
168
|
|
|
169
169
|
// e.g. "continue without accepting", "continue without agreeing", "continue without agreeing →"
|
|
170
170
|
/^\s*(continue|proceed|continue\s+browsing)\s+without\s+(accepting|agreeing|consent|cookies|tracking)(\s*→)?\s*$/is,
|
package/lib/rules.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { snippets } from './eval-snippets';
|
|
|
2
2
|
|
|
3
3
|
// 1 - the first version of the rule step format
|
|
4
4
|
// 2 - added removeClass, setStyle, addStyle
|
|
5
|
-
|
|
5
|
+
// 3 - added stylesheet
|
|
6
|
+
export const SUPPORTED_RULE_STEP_VERSION = 3;
|
|
6
7
|
|
|
7
8
|
export type AutoConsentCMPRule = {
|
|
8
9
|
readonly name: string;
|
|
@@ -52,7 +53,8 @@ export type AutoConsentRuleStep = { optional?: boolean; comment?: string } & Par
|
|
|
52
53
|
Partial<CookieContainsRule> &
|
|
53
54
|
Partial<RemoveClassRule> &
|
|
54
55
|
Partial<SetStyleRule> &
|
|
55
|
-
Partial<AddStyleRule
|
|
56
|
+
Partial<AddStyleRule> &
|
|
57
|
+
Partial<StylesheetRule>;
|
|
56
58
|
|
|
57
59
|
export type NegatedRule = {
|
|
58
60
|
negated: boolean;
|
|
@@ -134,3 +136,8 @@ export type AddStyleRule = {
|
|
|
134
136
|
addStyle: string;
|
|
135
137
|
selector: ElementSelector;
|
|
136
138
|
};
|
|
139
|
+
|
|
140
|
+
export type StylesheetRule = {
|
|
141
|
+
stylesheet: string;
|
|
142
|
+
stylesheetId?: string;
|
|
143
|
+
};
|
package/lib/utils.ts
CHANGED
|
@@ -32,6 +32,22 @@ export function hideElements(styleEl: HTMLStyleElement, selector: string, method
|
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// append a stylesheet rule once; marker is used to avoid duplicate inserts on re-runs
|
|
36
|
+
export function appendStylesheetRule(styleEl: HTMLStyleElement, cssRule: string, marker?: string): boolean {
|
|
37
|
+
if (!(styleEl instanceof HTMLStyleElement) || cssRule.length === 0) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const markerComment = marker ? `/* autoconsent:${marker} */` : '';
|
|
41
|
+
if (markerComment && styleEl.innerText.includes(markerComment)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (!markerComment && styleEl.innerText.includes(cssRule.trim())) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
styleEl.innerText += `${markerComment}${markerComment ? ' ' : ''}${cssRule} `;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
35
51
|
export async function waitFor(predicate: () => Promise<boolean> | boolean, maxTimes: number, interval: number): Promise<boolean> {
|
|
36
52
|
const result = await predicate();
|
|
37
53
|
if (!result && maxTimes > 0) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "amazon-pay",
|
|
3
|
+
"vendorUrl": "https://pay.amazon.com/",
|
|
4
|
+
"runContext": {
|
|
5
|
+
"urlPattern": "^https?://pay\\.amazon\\."
|
|
6
|
+
},
|
|
7
|
+
"prehideSelectors": [".cookie-menu.js-cookie-banner"],
|
|
8
|
+
"detectCmp": [{ "exists": ".cookie-menu.js-cookie-banner .js-cookie-banner-close" }],
|
|
9
|
+
"detectPopup": [{ "visible": ".cookie-menu.js-cookie-banner" }],
|
|
10
|
+
"optIn": [{ "click": ".cookie-menu.js-cookie-banner .js-cookie-banner-close" }],
|
|
11
|
+
"optOut": [{ "click": ".cookie-menu.js-cookie-banner .js-cookie-banner-close" }],
|
|
12
|
+
"test": [{ "cookieContains": "apaycnst-mktg=true" }]
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bbva",
|
|
3
|
+
"prehideSelectors": [".cookiesgdpr__base:has(.cookiesgdpr__rejectbtn)"],
|
|
4
|
+
"detectCmp": [{ "exists": ".cookiesgdpr__base .cookiesgdpr__rejectbtn" }],
|
|
5
|
+
"detectPopup": [{ "visible": ".cookiesgdpr__base .cookiesgdpr__rejectbtn" }],
|
|
6
|
+
"optIn": [{ "waitForThenClick": ".cookiesgdpr__base .cookiesgdpr__acceptbtn" }],
|
|
7
|
+
"optOut": [
|
|
8
|
+
{ "waitForThenClick": ".cookiesgdpr__base .cookiesgdpr__rejectbtn" },
|
|
9
|
+
{ "waitForVisible": ".cookiesgdpr__base .cookiesgdpr__wrapper", "check": "none" }
|
|
10
|
+
],
|
|
11
|
+
"test": [{ "cookieContains": "\"analitica\":false" }]
|
|
12
|
+
}
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
}
|
|
27
27
|
],
|
|
28
28
|
"optOut": [
|
|
29
|
+
{
|
|
30
|
+
"comment": "the popup markup exists before the library opens it; clicking too early gets undone by the pending open",
|
|
31
|
+
"waitFor": "[aria-describedby=\"cookieconsent:desc\"].cc-type-opt-out:not(.cc-invisible)",
|
|
32
|
+
"timeout": 2000,
|
|
33
|
+
"optional": true
|
|
34
|
+
},
|
|
29
35
|
{
|
|
30
36
|
"if": {
|
|
31
37
|
"exists": ".cc-deny"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "deliveroo",
|
|
3
|
+
"runContext": {
|
|
4
|
+
"urlPattern": "^https?://(\\w+\\.)?deliveroo\\.(co\\.uk|\\w+)/"
|
|
5
|
+
},
|
|
6
|
+
"prehideSelectors": ["div[role=\"dialog\"][class*=\"CustomCookieBanner\"]"],
|
|
7
|
+
"detectCmp": [{ "exists": "div[role=\"dialog\"][class*=\"CustomCookieBanner\"]" }],
|
|
8
|
+
"detectPopup": [{ "visible": "div[role=\"dialog\"][class*=\"CustomCookieBanner\"]" }],
|
|
9
|
+
"optIn": [{ "waitForThenClick": "#onetrust-consent-sdk #accept-recommended-btn-handler" }],
|
|
10
|
+
"optOut": [
|
|
11
|
+
{ "waitForThenClick": "#onetrust-consent-sdk .ot-pc-refuse-all-handler" },
|
|
12
|
+
{ "waitForVisible": "div[role=\"dialog\"][class*=\"CustomCookieBanner\"]", "check": "none" }
|
|
13
|
+
],
|
|
14
|
+
"test": [{ "cookieContains": "OptanonAlertBoxClosed" }]
|
|
15
|
+
}
|
|
@@ -21,11 +21,45 @@
|
|
|
21
21
|
"optIn": [
|
|
22
22
|
{
|
|
23
23
|
"waitForThenClick": "#gdpr-banner-accept"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"waitForVisible": "#gdpr-banner",
|
|
27
|
+
"check": "none",
|
|
28
|
+
"timeout": 2000,
|
|
29
|
+
"optional": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"if": {
|
|
33
|
+
"visible": "#gdpr-banner"
|
|
34
|
+
},
|
|
35
|
+
"then": [
|
|
36
|
+
{
|
|
37
|
+
"waitForThenClick": "#gdpr-banner-accept",
|
|
38
|
+
"timeout": 2000
|
|
39
|
+
}
|
|
40
|
+
]
|
|
24
41
|
}
|
|
25
42
|
],
|
|
26
43
|
"optOut": [
|
|
27
44
|
{
|
|
28
45
|
"waitForThenClick": "#gdpr-banner-decline"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"waitForVisible": "#gdpr-banner",
|
|
49
|
+
"check": "none",
|
|
50
|
+
"timeout": 2000,
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"if": {
|
|
55
|
+
"visible": "#gdpr-banner"
|
|
56
|
+
},
|
|
57
|
+
"then": [
|
|
58
|
+
{
|
|
59
|
+
"waitForThenClick": "#gdpr-banner-decline",
|
|
60
|
+
"timeout": 2000
|
|
61
|
+
}
|
|
62
|
+
]
|
|
29
63
|
}
|
|
30
64
|
]
|
|
31
65
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gemini.google.com",
|
|
3
|
+
"prehideSelectors": ["[data-test-id=\"cookie-banner-body\"]"],
|
|
4
|
+
"detectCmp": [{ "exists": "cookie-banner [data-test-id=\"cookie-banner-body\"] [data-test-id=\"reject-button\"]" }],
|
|
5
|
+
"detectPopup": [{ "visible": "[data-test-id=\"cookie-banner-body\"]" }],
|
|
6
|
+
"optIn": [{ "waitForThenClick": "[data-test-id=\"cookie-banner-body\"] [data-test-id=\"accept-button\"]" }],
|
|
7
|
+
"optOut": [{ "waitForThenClick": "[data-test-id=\"cookie-banner-body\"] [data-test-id=\"reject-button\"]" }],
|
|
8
|
+
"test": []
|
|
9
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"optOut": [
|
|
8
8
|
{ "click": ".consent-banner__actions button.basic-button.secondary" },
|
|
9
9
|
{ "waitForThenClick": ".consent-modal__footer button.basic-button.secondary" },
|
|
10
|
-
{ "waitForThenClick": ".consent-modal
|
|
10
|
+
{ "waitForThenClick": ".consent-modal .base-modal__body a", "all": true },
|
|
11
11
|
{ "click": "label.consent-switch input[type=checkbox]:checked", "all": true, "optional": true },
|
|
12
12
|
{ "waitForVisible": ".consent-modal__footer button.basic-button.primary" },
|
|
13
13
|
{ "click": ".consent-modal__footer button.basic-button.primary" }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kingrecords-co-jp",
|
|
3
|
+
"vendorUrl": "https://www.kingrecords.co.jp/",
|
|
4
|
+
"runContext": {
|
|
5
|
+
"urlPattern": "^https?://(?:[^/]+\\.)?kingrecords\\.co\\.jp/"
|
|
6
|
+
},
|
|
7
|
+
"prehideSelectors": [".cookie:has(.cookie__inner .cookie__button)"],
|
|
8
|
+
"detectCmp": [{ "exists": ".cookie > .cookie__inner > .cookie__button > a" }],
|
|
9
|
+
"detectPopup": [{ "visible": ".cookie > .cookie__inner > .cookie__button > a" }],
|
|
10
|
+
"optIn": [
|
|
11
|
+
{ "waitFor": "#loader.is--show", "timeout": 10000, "optional": true },
|
|
12
|
+
{ "waitForThenClick": ".cookie > .cookie__inner > .cookie__button > a" }
|
|
13
|
+
],
|
|
14
|
+
"optOut": [
|
|
15
|
+
{ "waitFor": "#loader.is--show", "timeout": 10000, "optional": true },
|
|
16
|
+
{ "waitForThenClick": ".cookie > .cookie__inner > .cookie__button > a" },
|
|
17
|
+
{ "if": { "visible": ".cookie" }, "then": [{ "wait": 1000 }, { "click": ".cookie > .cookie__inner > .cookie__button > a" }] },
|
|
18
|
+
{ "waitForVisible": ".cookie", "check": "none", "timeout": 5000 }
|
|
19
|
+
],
|
|
20
|
+
"test": [{ "cookieContains": "cookiesubmit=1" }]
|
|
21
|
+
}
|
|
@@ -27,16 +27,17 @@
|
|
|
27
27
|
"else": [
|
|
28
28
|
{ "waitForVisible": ".privacy-sheet-content #formContent" },
|
|
29
29
|
{
|
|
30
|
-
"click": "#formContent
|
|
30
|
+
"click": "#formContent input[type='checkbox']:checked",
|
|
31
31
|
"all": true,
|
|
32
32
|
"optional": true
|
|
33
33
|
},
|
|
34
|
-
{ "click": ".cookieAction
|
|
34
|
+
{ "click": ".cookieAction #submitCookiesBtn" }
|
|
35
35
|
]
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
38
|
}
|
|
39
39
|
]
|
|
40
40
|
}
|
|
41
|
-
]
|
|
41
|
+
],
|
|
42
|
+
"test": [{ "wait": 1000 }, { "cookieContains": "type%3Dexplicit" }]
|
|
42
43
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rule34-xxx",
|
|
3
|
+
"runContext": {
|
|
4
|
+
"urlPattern": "^https?://(www\\.)?rule34\\.xxx/"
|
|
5
|
+
},
|
|
6
|
+
"prehideSelectors": ["#gdprconsent.gdprcontainer"],
|
|
7
|
+
"detectCmp": [{ "exists": "#gdprconsent.gdprcontainer" }],
|
|
8
|
+
"detectPopup": [{ "visible": "#gdprconsent.gdprcontainer" }],
|
|
9
|
+
"optIn": [{ "waitForThenClick": "#gdprconsent .gdprbutton button" }],
|
|
10
|
+
"optOut": [{ "waitForThenClick": "#gdprconsent .gdprbutton a" }],
|
|
11
|
+
"test": [{ "cookieContains": "gdpr-consent=0" }]
|
|
12
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sex.com",
|
|
3
|
+
"runContext": {
|
|
4
|
+
"urlPattern": "^https?://(\\w+\\.)?sex\\.com/"
|
|
5
|
+
},
|
|
6
|
+
"prehideSelectors": ["[class*=\"cookie-consent-required\"]"],
|
|
7
|
+
"detectCmp": [
|
|
8
|
+
{
|
|
9
|
+
"comment": "the flag is cleared once consent is stored, so it prevents re-detecting the leftover markup",
|
|
10
|
+
"exists": "html[data-cookie-consent-required] [data-testid=\"accept-all-cookie-button\"]"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"detectPopup": [
|
|
14
|
+
{
|
|
15
|
+
"visible": "[data-testid=\"accept-all-cookie-button\"]"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"optIn": [
|
|
19
|
+
{
|
|
20
|
+
"comment": "the modal is server-rendered, buttons only respond once the dialog is hydrated and locks scrolling",
|
|
21
|
+
"waitFor": "body[data-scroll-locked]"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"waitForThenClick": "[data-testid=\"accept-all-cookie-button\"]"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"optOut": [
|
|
28
|
+
{
|
|
29
|
+
"comment": "the modal is server-rendered, buttons only respond once the dialog is hydrated and locks scrolling",
|
|
30
|
+
"waitFor": "body[data-scroll-locked]"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"comment": "optional categories default to off, so confirming the defaults rejects them",
|
|
34
|
+
"waitForThenClick": "[data-testid=\"customize-cookie-button\"]"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"waitForThenClick": "[data-testid=\"confirm-settings-cookie-button\"]"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"test": [
|
|
41
|
+
{
|
|
42
|
+
"cookieContains": "%22analytics%22%3Afalse"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"vendorUrl": "https://www.theguardian.com/",
|
|
4
4
|
"comment": "Sourcepoint 'consent or pay' wall shown in the EU/EEA (message 1482251) and UK (message 1482252), where the only reject option requires a paid subscription. The container id embeds the Sourcepoint message id, so we target the pay-wall variants specifically to avoid clashing with the free-reject Sourcepoint popup used in other regions (handled by Sourcepoint-frame). Brittle: message ids may change if the campaign is reconfigured.",
|
|
5
5
|
"cosmetic": true,
|
|
6
|
-
"minimumRuleStepVersion":
|
|
6
|
+
"minimumRuleStepVersion": 3,
|
|
7
7
|
"runContext": {
|
|
8
8
|
"urlPattern": "^https?://(\\w+\\.)?theguardian\\.com/",
|
|
9
9
|
"main": true,
|
|
@@ -11,11 +11,21 @@
|
|
|
11
11
|
},
|
|
12
12
|
"prehideSelectors": ["div[id='sp_message_container_1482251'],div[id='sp_message_container_1482252']"],
|
|
13
13
|
"detectCmp": [{ "exists": "div[id='sp_message_container_1482251'],div[id='sp_message_container_1482252']" }],
|
|
14
|
-
"detectPopup": [
|
|
14
|
+
"detectPopup": [
|
|
15
|
+
{
|
|
16
|
+
"any": [
|
|
17
|
+
{ "visible": "div[id='sp_message_container_1482251'],div[id='sp_message_container_1482252']" },
|
|
18
|
+
{ "exists": "html.sp-message-open" }
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
],
|
|
15
22
|
"optIn": [],
|
|
16
23
|
"optOut": [
|
|
17
24
|
{ "hide": "div[id='sp_message_container_1482251'],div[id='sp_message_container_1482252']" },
|
|
18
|
-
{
|
|
25
|
+
{
|
|
26
|
+
"stylesheet": "html.sp-message-open body { position: static !important; top: auto !important; width: auto !important; overflow: auto !important; }",
|
|
27
|
+
"stylesheetId": "theguardian-scroll-unlock"
|
|
28
|
+
}
|
|
19
29
|
],
|
|
20
30
|
"test": [{ "visible": "div[id='sp_message_container_1482251'],div[id='sp_message_container_1482252']", "check": "none" }]
|
|
21
31
|
}
|
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "twitch.tv",
|
|
3
3
|
"runContext": {
|
|
4
|
-
"urlPattern": "^https?://([\\w-]+\\.)?twitch\\.tv"
|
|
4
|
+
"urlPattern": "^https?://([\\w-]+\\.)?twitch\\.tv/"
|
|
5
5
|
},
|
|
6
|
-
"prehideSelectors": [
|
|
7
|
-
|
|
6
|
+
"prehideSelectors": ["[data-a-target=\"consent-banner\"],.ReactModalPortal:has([data-a-target=consent-modal-save])"],
|
|
7
|
+
"detectCmp": [{ "exists": "[data-a-target=\"consent-banner\"]" }],
|
|
8
|
+
"detectPopup": [{ "visible": "[data-a-target=\"consent-banner\"]" }],
|
|
9
|
+
"optIn": [
|
|
10
|
+
{
|
|
11
|
+
"if": { "exists": "[data-a-target=\"consent-banner-accept\"]" },
|
|
12
|
+
"then": [{ "click": "button[data-a-target=\"consent-banner-accept\"]" }],
|
|
13
|
+
"else": [{ "click": "[data-a-target=\"consent-banner\"] button:not([data-a-target])" }]
|
|
14
|
+
}
|
|
8
15
|
],
|
|
9
|
-
"detectCmp": [{ "exists": ".consent-banner .consent-banner__content--gdpr-v2" }],
|
|
10
|
-
"detectPopup": [{ "visible": ".consent-banner .consent-banner__content--gdpr-v2" }],
|
|
11
|
-
"optIn": [{ "click": "button[data-a-target=\"consent-banner-accept\"]" }],
|
|
12
16
|
"optOut": [
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
{
|
|
18
|
+
"if": { "exists": "[data-a-target=\"consent-banner-accept\"]" },
|
|
19
|
+
"then": [
|
|
20
|
+
{ "click": "[data-a-target=\"consent-banner\"] button:not([data-a-target])" },
|
|
21
|
+
{ "waitForVisible": "[data-a-target=\"consent-banner\"]", "check": "none" }
|
|
22
|
+
],
|
|
23
|
+
"else": [
|
|
24
|
+
{ "click": "button[data-a-target=\"consent-banner-manage-preferences\"]" },
|
|
25
|
+
{ "waitFor": "input[type=checkbox][data-a-target=tw-checkbox]" },
|
|
26
|
+
{
|
|
27
|
+
"click": "input[type=checkbox][data-a-target=tw-checkbox]:not(:checked):not([disabled])",
|
|
28
|
+
"optional": true
|
|
29
|
+
},
|
|
30
|
+
{ "waitForThenClick": "[data-a-target=consent-modal-save]" },
|
|
31
|
+
{ "waitForVisible": ".ReactModalPortal:has([data-a-target=consent-modal-save])", "check": "none" }
|
|
32
|
+
]
|
|
33
|
+
}
|
|
19
34
|
]
|
|
20
35
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "WPConsent",
|
|
3
|
+
"vendorUrl": "https://wordpress.org/plugins/wpconsent-cookies-banner-privacy-suite/",
|
|
4
|
+
"prehideSelectors": ["#wpconsent-root"],
|
|
5
|
+
"detectCmp": [
|
|
6
|
+
{
|
|
7
|
+
"exists": "#wpconsent-container"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"detectPopup": [
|
|
11
|
+
{
|
|
12
|
+
"visible": ["#wpconsent-container", "#wpconsent-banner-holder.wpconsent-banner-visible"]
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"optIn": [
|
|
16
|
+
{
|
|
17
|
+
"waitForThenClick": ["#wpconsent-container", "#wpconsent-accept-all"]
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"optOut": [
|
|
21
|
+
{
|
|
22
|
+
"waitForThenClick": ["#wpconsent-container", "#wpconsent-cancel-all"]
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"test": [
|
|
26
|
+
{
|
|
27
|
+
"cookieContains": "wpconsent_preferences="
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
"detectPopup": [{ "visible": "[data-role=\"cookies-modal\"] [data-opt-hydration=\"cookies-dialog-eu\"]" }],
|
|
9
9
|
"optIn": [{ "waitForThenClick": "[data-role=\"cookies-modal\"] [class*=experimentalButtons] button:nth-of-type(1)" }],
|
|
10
10
|
"optOut": [
|
|
11
|
-
{ "
|
|
11
|
+
{ "waitForVisible": "[data-role=\"cookies-modal\"] [class*=experimentalButtons] button:nth-of-type(2)" },
|
|
12
|
+
{ "wait": 500 },
|
|
13
|
+
{ "click": "[data-role=\"cookies-modal\"] [class*=experimentalButtons] button:nth-of-type(2)" },
|
|
12
14
|
{ "hide": "[data-role=\"cookies-modal\"] [class*=container]", "optional": true }
|
|
13
15
|
]
|
|
14
16
|
}
|