@duckduckgo/autoconsent 10.8.0 → 10.9.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.
@@ -544,6 +544,7 @@
544
544
  EVAL_EU_COOKIE_LAW_0: () => !document.cookie.includes("euCookie"),
545
545
  EVAL_EZOIC_0: () => ezCMP.handleAcceptAllClick(),
546
546
  EVAL_EZOIC_1: () => !!document.cookie.match(/ez-consent-tcf/),
547
+ EVAL_FIDES_DETECT_POPUP: () => window.Fides?.initialized,
547
548
  EVAL_GOOGLE_0: () => !!document.cookie.match(/SOCS=CAE/),
548
549
  EVAL_HEMA_TEST_0: () => document.cookie.includes("cookies_rejected=1"),
549
550
  EVAL_IUBENDA_0: () => document.querySelectorAll(".purposes-item input[type=checkbox]:not([disabled])").forEach((x) => {
@@ -553,6 +554,7 @@
553
554
  EVAL_IUBENDA_1: () => !!document.cookie.match(/_iub_cs-\d+=/),
554
555
  EVAL_IWINK_TEST: () => document.cookie.includes("cookie_permission_granted=no"),
555
556
  EVAL_JQUERY_COOKIEBAR_0: () => !document.cookie.includes("cookies-state=accepted"),
557
+ EVAL_KETCH_TEST: () => document.cookie.includes("_ketch_consent_v1_"),
556
558
  EVAL_MEDIAVINE_0: () => document.querySelectorAll('[data-name="mediavine-gdpr-cmp"] input[type=checkbox]').forEach((x) => x.checked && x.click()) || true,
557
559
  EVAL_MICROSOFT_0: () => Array.from(document.querySelectorAll("div > button")).filter((el) => el.innerText.match("Reject|Ablehnen"))[0].click() || true,
558
560
  EVAL_MICROSOFT_1: () => Array.from(document.querySelectorAll("div > button")).filter((el) => el.innerText.match("Accept|Annehmen"))[0].click() || true,
@@ -567,6 +569,7 @@
567
569
  EVAL_PRIMEBOX_0: () => !document.cookie.includes("cb-enabled=accepted"),
568
570
  EVAL_PUBTECH_0: () => document.cookie.includes("euconsent-v2") && (document.cookie.match(/.YAAAAAAAAAAA/) || document.cookie.match(/.aAAAAAAAAAAA/) || document.cookie.match(/.YAAACFgAAAAA/)),
569
571
  EVAL_REDDIT_0: () => document.cookie.includes("eu_cookie={%22opted%22:true%2C%22nonessential%22:false}"),
572
+ EVAL_ROBLOX_TEST: () => document.cookie.includes("RBXcb"),
570
573
  EVAL_SIRDATA_UNBLOCK_SCROLL: () => {
571
574
  document.documentElement.classList.forEach((cls) => {
572
575
  if (cls.startsWith("sd-cmp-"))
@@ -1439,10 +1442,11 @@
1439
1442
  if (this.click("#_evidon-decline-button")) {
1440
1443
  return true;
1441
1444
  }
1442
- hideElements(getStyleElement(), "#evidon-prefdiag-overlay,#evidon-prefdiag-background");
1443
- this.click("#_evidon-option-button");
1445
+ hideElements(getStyleElement(), "#evidon-prefdiag-overlay,#evidon-prefdiag-background,#_evidon-background");
1446
+ await this.waitForThenClick("#_evidon-option-button");
1444
1447
  await this.waitForElement("#evidon-prefdiag-overlay", 5e3);
1445
- this.click("#evidon-prefdiag-decline");
1448
+ await this.wait(500);
1449
+ await this.waitForThenClick("#evidon-prefdiag-decline");
1446
1450
  return true;
1447
1451
  }
1448
1452
  async optIn() {
@@ -2763,7 +2767,6 @@
2763
2767
  },
2764
2768
  {
2765
2769
  name: "aquasana.com",
2766
- cosmetic: true,
2767
2770
  prehideSelectors: [
2768
2771
  "#consent-tracking"
2769
2772
  ],
@@ -2779,12 +2782,24 @@
2779
2782
  ],
2780
2783
  optIn: [
2781
2784
  {
2782
- click: "#accept_consent"
2785
+ waitForThenClick: "#consent-tracking .affirm.btn"
2783
2786
  }
2784
2787
  ],
2785
2788
  optOut: [
2786
2789
  {
2787
- hide: "#consent-tracking"
2790
+ if: {
2791
+ exists: "#consent-tracking .decline.btn"
2792
+ },
2793
+ then: [
2794
+ {
2795
+ click: "#consent-tracking .decline.btn"
2796
+ }
2797
+ ],
2798
+ else: [
2799
+ {
2800
+ hide: "#consent-tracking"
2801
+ }
2802
+ ]
2788
2803
  }
2789
2804
  ]
2790
2805
  },
@@ -3960,7 +3975,20 @@
3960
3975
  ],
3961
3976
  else: [
3962
3977
  {
3963
- hide: '[aria-describedby="cookieconsent:desc"]'
3978
+ if: {
3979
+ exists: ".cmp-pref-link"
3980
+ },
3981
+ then: [
3982
+ {
3983
+ click: ".cmp-pref-link"
3984
+ },
3985
+ {
3986
+ waitForThenClick: ".cmp-body [id*=rejectAll]"
3987
+ },
3988
+ {
3989
+ waitForThenClick: ".cmp-body .cmp-save-btn"
3990
+ }
3991
+ ]
3964
3992
  }
3965
3993
  ]
3966
3994
  }
@@ -4354,6 +4382,51 @@
4354
4382
  }
4355
4383
  ]
4356
4384
  },
4385
+ {
4386
+ name: "cookiecuttr",
4387
+ vendorUrl: "https://github.com/cdwharton/cookieCuttr",
4388
+ cosmetic: false,
4389
+ runContext: {
4390
+ main: true,
4391
+ frame: false,
4392
+ urlPattern: ""
4393
+ },
4394
+ prehideSelectors: [
4395
+ ".cc-cookies"
4396
+ ],
4397
+ detectCmp: [
4398
+ {
4399
+ exists: ".cc-cookies .cc-cookie-accept"
4400
+ }
4401
+ ],
4402
+ detectPopup: [
4403
+ {
4404
+ visible: ".cc-cookies .cc-cookie-accept"
4405
+ }
4406
+ ],
4407
+ optIn: [
4408
+ {
4409
+ waitForThenClick: ".cc-cookies .cc-cookie-accept"
4410
+ }
4411
+ ],
4412
+ optOut: [
4413
+ {
4414
+ if: {
4415
+ exists: ".cc-cookies .cc-cookie-decline"
4416
+ },
4417
+ then: [
4418
+ {
4419
+ click: ".cc-cookies .cc-cookie-decline"
4420
+ }
4421
+ ],
4422
+ else: [
4423
+ {
4424
+ hide: ".cc-cookies"
4425
+ }
4426
+ ]
4427
+ }
4428
+ ]
4429
+ },
4357
4430
  {
4358
4431
  name: "cookiefirst.com",
4359
4432
  prehideSelectors: [
@@ -5273,16 +5346,19 @@
5273
5346
  detectPopup: [
5274
5347
  {
5275
5348
  visible: "#fides-overlay #fides-banner"
5349
+ },
5350
+ {
5351
+ eval: "EVAL_FIDES_DETECT_POPUP"
5276
5352
  }
5277
5353
  ],
5278
5354
  optIn: [
5279
5355
  {
5280
- waitForThenClick: '#fides-banner [data-testid="Accept all-btn"]'
5356
+ waitForThenClick: "#fides-banner .fides-accept-all-button"
5281
5357
  }
5282
5358
  ],
5283
5359
  optOut: [
5284
5360
  {
5285
- waitForThenClick: '#fides-banner [data-testid="Reject all-btn"]'
5361
+ waitForThenClick: "#fides-banner .fides-reject-all-button"
5286
5362
  }
5287
5363
  ]
5288
5364
  },
@@ -6127,29 +6203,34 @@
6127
6203
  },
6128
6204
  then: [
6129
6205
  {
6130
- waitForThenClick: "#lanyard_root div[class*=buttons] > button[class*=secondaryButton]",
6206
+ waitForThenClick: "#lanyard_root div[class*=buttons] > button[class*=secondaryButton], #lanyard_root button[class*=buttons-secondary]",
6131
6207
  comment: "can be either settings or reject button"
6132
6208
  }
6133
6209
  ]
6134
6210
  },
6135
6211
  {
6136
- waitFor: "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description]",
6212
+ waitFor: "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences",
6137
6213
  timeout: 1e3,
6138
6214
  optional: true
6139
6215
  },
6140
6216
  {
6141
6217
  if: {
6142
- exists: "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description]"
6218
+ exists: "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences"
6143
6219
  },
6144
6220
  then: [
6145
6221
  {
6146
- waitForThenClick: "#lanyard_root button[class*=rejectButton]"
6222
+ waitForThenClick: "#lanyard_root button[class*=rejectButton], #lanyard_root button[class*=rejectAllButton]"
6147
6223
  },
6148
6224
  {
6149
- click: "#lanyard_root button[class*=confirmButton],#lanyard_root div[class*=actions_] > button:nth-child(1)"
6225
+ click: "#lanyard_root button[class*=confirmButton],#lanyard_root div[class*=actions_] > button:nth-child(1), #lanyard_root button[class*=actionButton]"
6150
6226
  }
6151
6227
  ]
6152
6228
  }
6229
+ ],
6230
+ test: [
6231
+ {
6232
+ eval: "EVAL_KETCH_TEST"
6233
+ }
6153
6234
  ]
6154
6235
  },
6155
6236
  {
@@ -7551,6 +7632,42 @@
7551
7632
  }
7552
7633
  ]
7553
7634
  },
7635
+ {
7636
+ name: "roblox",
7637
+ vendorUrl: "https://roblox.com",
7638
+ cosmetic: false,
7639
+ runContext: {
7640
+ main: true,
7641
+ frame: false,
7642
+ urlPattern: "^https://(www\\.)?roblox\\.com/"
7643
+ },
7644
+ prehideSelectors: [],
7645
+ detectCmp: [
7646
+ {
7647
+ exists: ".cookie-banner-wrapper"
7648
+ }
7649
+ ],
7650
+ detectPopup: [
7651
+ {
7652
+ visible: ".cookie-banner-wrapper .cookie-banner"
7653
+ }
7654
+ ],
7655
+ optIn: [
7656
+ {
7657
+ waitForThenClick: ".cookie-banner-wrapper button.btn-cta-lg"
7658
+ }
7659
+ ],
7660
+ optOut: [
7661
+ {
7662
+ waitForThenClick: ".cookie-banner-wrapper button.btn-secondary-lg"
7663
+ }
7664
+ ],
7665
+ test: [
7666
+ {
7667
+ eval: "EVAL_ROBLOX_TEST"
7668
+ }
7669
+ ]
7670
+ },
7554
7671
  {
7555
7672
  name: "rog-forum.asus.com",
7556
7673
  runContext: {
@@ -8972,27 +9089,32 @@
8972
9089
  },
8973
9090
  {
8974
9091
  name: "uswitch.com",
9092
+ runContext: {
9093
+ main: true,
9094
+ frame: false,
9095
+ urlPattern: "^https://(www\\.)?uswitch\\.com/"
9096
+ },
8975
9097
  prehideSelectors: [
8976
- "#cookie-banner-wrapper"
9098
+ ".ucb"
8977
9099
  ],
8978
9100
  detectCmp: [
8979
9101
  {
8980
- exists: "#cookie-banner-wrapper"
9102
+ exists: ".ucb-banner"
8981
9103
  }
8982
9104
  ],
8983
9105
  detectPopup: [
8984
9106
  {
8985
- visible: "#cookie-banner-wrapper"
9107
+ visible: ".ucb-banner"
8986
9108
  }
8987
9109
  ],
8988
9110
  optIn: [
8989
9111
  {
8990
- click: "#cookie_banner_accept_mobile"
9112
+ waitForThenClick: ".ucb-banner .ucb-btn-accept"
8991
9113
  }
8992
9114
  ],
8993
9115
  optOut: [
8994
9116
  {
8995
- click: "#cookie_banner_save"
9117
+ waitForThenClick: ".ucb-banner .ucb-btn-save"
8996
9118
  }
8997
9119
  ]
8998
9120
  },
@@ -29,12 +29,13 @@ export default class Evidon extends AutoConsentCMPBase {
29
29
  return true;
30
30
  }
31
31
 
32
- hideElements(getStyleElement(), "#evidon-prefdiag-overlay,#evidon-prefdiag-background");
33
- this.click("#_evidon-option-button");
32
+ hideElements(getStyleElement(), "#evidon-prefdiag-overlay,#evidon-prefdiag-background,#_evidon-background");
33
+ await this.waitForThenClick("#_evidon-option-button");
34
34
 
35
35
  await this.waitForElement("#evidon-prefdiag-overlay", 5000);
36
36
 
37
- this.click("#evidon-prefdiag-decline");
37
+ await this.wait(500);
38
+ await this.waitForThenClick("#evidon-prefdiag-decline");
38
39
  return true;
39
40
  }
40
41
 
@@ -94,12 +94,14 @@ export const snippets = {
94
94
  EVAL_EU_COOKIE_LAW_0: () => !document.cookie.includes('euCookie'),
95
95
  EVAL_EZOIC_0: () => ezCMP.handleAcceptAllClick(),
96
96
  EVAL_EZOIC_1: () => !!document.cookie.match(/ez-consent-tcf/),
97
+ EVAL_FIDES_DETECT_POPUP: () => window.Fides?.initialized,
97
98
  EVAL_GOOGLE_0: () => !!document.cookie.match(/SOCS=CAE/),
98
99
  EVAL_HEMA_TEST_0: () => document.cookie.includes('cookies_rejected=1'),
99
100
  EVAL_IUBENDA_0: () => document.querySelectorAll('.purposes-item input[type=checkbox]:not([disabled])').forEach(x => {if(x.checked) x.click()}) || true,
100
101
  EVAL_IUBENDA_1: () => !!document.cookie.match(/_iub_cs-\d+=/),
101
102
  EVAL_IWINK_TEST: () => document.cookie.includes('cookie_permission_granted=no'),
102
103
  EVAL_JQUERY_COOKIEBAR_0: () => !document.cookie.includes('cookies-state=accepted'),
104
+ EVAL_KETCH_TEST: () => document.cookie.includes('_ketch_consent_v1_'),
103
105
  EVAL_MEDIAVINE_0: () => document.querySelectorAll("[data-name=\"mediavine-gdpr-cmp\"] input[type=checkbox]").forEach(x => x.checked && x.click()) || true,
104
106
  EVAL_MICROSOFT_0: () => Array.from(document.querySelectorAll('div > button')).filter(el => el.innerText.match('Reject|Ablehnen'))[0].click() || true,
105
107
  EVAL_MICROSOFT_1: () => Array.from(document.querySelectorAll('div > button')).filter(el => el.innerText.match('Accept|Annehmen'))[0].click() || true,
@@ -111,6 +113,7 @@ export const snippets = {
111
113
  EVAL_PRIMEBOX_0: () => !document.cookie.includes('cb-enabled=accepted'),
112
114
  EVAL_PUBTECH_0: () => document.cookie.includes('euconsent-v2') && (document.cookie.match(/.YAAAAAAAAAAA/) || document.cookie.match(/.aAAAAAAAAAAA/) || document.cookie.match(/.YAAACFgAAAAA/)) ,
113
115
  EVAL_REDDIT_0: () => document.cookie.includes('eu_cookie={%22opted%22:true%2C%22nonessential%22:false}'),
116
+ EVAL_ROBLOX_TEST: () => document.cookie.includes('RBXcb'),
114
117
  EVAL_SIRDATA_UNBLOCK_SCROLL: () => {
115
118
  document.documentElement.classList.forEach(cls => {
116
119
  if (cls.startsWith('sd-cmp-')) document.documentElement.classList.remove(cls)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckduckgo/autoconsent",
3
- "version": "10.8.0",
3
+ "version": "10.9.0",
4
4
  "description": "",
5
5
  "main": "dist/autoconsent.cjs.js",
6
6
  "module": "dist/autoconsent.esm.js",
package/readme.md CHANGED
@@ -12,10 +12,8 @@ The web extension can be built with the following steps:
12
12
  ```bash
13
13
  # Download dependencies
14
14
  npm ci
15
- # Build consent ruleset
16
- npm run build-rules
17
- # Build JS bundles (rules must be built first)
18
- npm run bundle
15
+ # Build the extension
16
+ npm run prepublish
19
17
  ```
20
18
 
21
19
  The extension-specific code can be found in the `addon` directory. There are two versions of the
@@ -1,9 +1,18 @@
1
1
  {
2
2
  "name": "aquasana.com",
3
- "cosmetic": true,
4
3
  "prehideSelectors": ["#consent-tracking"],
5
4
  "detectCmp": [{ "exists": "#consent-tracking" }],
6
5
  "detectPopup": [{ "exists": "#consent-tracking" }],
7
- "optIn": [{ "click": "#accept_consent" }],
8
- "optOut": [{ "hide": "#consent-tracking" }]
6
+ "optIn": [
7
+ {
8
+ "waitForThenClick": "#consent-tracking .affirm.btn"
9
+ }
10
+ ],
11
+ "optOut": [
12
+ {
13
+ "if": { "exists": "#consent-tracking .decline.btn" },
14
+ "then": [{ "click": "#consent-tracking .decline.btn" }],
15
+ "else": [{ "hide": "#consent-tracking" }]
16
+ }
17
+ ]
9
18
  }
@@ -39,7 +39,18 @@
39
39
  ],
40
40
  "else": [
41
41
  {
42
- "hide": "[aria-describedby=\"cookieconsent:desc\"]"
42
+ "if": { "exists": ".cmp-pref-link" },
43
+ "then": [
44
+ {
45
+ "click": ".cmp-pref-link"
46
+ },
47
+ {
48
+ "waitForThenClick": ".cmp-body [id*=rejectAll]"
49
+ },
50
+ {
51
+ "waitForThenClick": ".cmp-body .cmp-save-btn"
52
+ }
53
+ ]
43
54
  }
44
55
  ]
45
56
  }
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "cookiecuttr",
3
+ "vendorUrl": "https://github.com/cdwharton/cookieCuttr",
4
+ "cosmetic": false,
5
+ "runContext": {
6
+ "main": true,
7
+ "frame": false,
8
+ "urlPattern": ""
9
+ },
10
+ "prehideSelectors": [".cc-cookies"],
11
+ "detectCmp": [
12
+ {
13
+ "exists": ".cc-cookies .cc-cookie-accept"
14
+ }
15
+ ],
16
+ "detectPopup": [
17
+ {
18
+ "visible": ".cc-cookies .cc-cookie-accept"
19
+ }
20
+ ],
21
+ "optIn": [
22
+ {
23
+ "waitForThenClick": ".cc-cookies .cc-cookie-accept"
24
+ }
25
+ ],
26
+ "optOut": [
27
+ {
28
+ "if": { "exists": ".cc-cookies .cc-cookie-decline" },
29
+ "then": [{
30
+ "click": ".cc-cookies .cc-cookie-decline"
31
+ }],
32
+ "else": [{
33
+ "hide": ".cc-cookies"
34
+ }]
35
+ }
36
+ ]
37
+ }
@@ -10,16 +10,19 @@
10
10
  "detectPopup": [
11
11
  {
12
12
  "visible": "#fides-overlay #fides-banner"
13
+ },
14
+ {
15
+ "eval": "EVAL_FIDES_DETECT_POPUP"
13
16
  }
14
17
  ],
15
18
  "optIn": [
16
19
  {
17
- "waitForThenClick": "#fides-banner [data-testid=\"Accept all-btn\"]"
20
+ "waitForThenClick": "#fides-banner .fides-accept-all-button"
18
21
  }
19
22
  ],
20
23
  "optOut": [
21
24
  {
22
- "waitForThenClick": "#fides-banner [data-testid=\"Reject all-btn\"]"
25
+ "waitForThenClick": "#fides-banner .fides-reject-all-button"
23
26
  }
24
27
  ]
25
28
  }
@@ -40,24 +40,27 @@
40
40
  },
41
41
  "then": [
42
42
  {
43
- "waitForThenClick":"#lanyard_root div[class*=buttons] > button[class*=secondaryButton]",
43
+ "waitForThenClick": "#lanyard_root div[class*=buttons] > button[class*=secondaryButton], #lanyard_root button[class*=buttons-secondary]",
44
44
  "comment": "can be either settings or reject button"
45
45
  }
46
46
  ]
47
47
  },
48
48
  {
49
- "waitFor": "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description]",
49
+ "waitFor": "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences",
50
50
  "timeout": 1000,
51
51
  "optional": true
52
52
  },
53
53
  {
54
54
  "if": {
55
- "exists": "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description]"
55
+ "exists": "#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences"
56
56
  },
57
57
  "then": [
58
- { "waitForThenClick": "#lanyard_root button[class*=rejectButton]" },
59
- { "click": "#lanyard_root button[class*=confirmButton],#lanyard_root div[class*=actions_] > button:nth-child(1)" }
58
+ { "waitForThenClick": "#lanyard_root button[class*=rejectButton], #lanyard_root button[class*=rejectAllButton]" },
59
+ { "click": "#lanyard_root button[class*=confirmButton],#lanyard_root div[class*=actions_] > button:nth-child(1), #lanyard_root button[class*=actionButton]" }
60
60
  ]
61
61
  }
62
+ ],
63
+ "test": [
64
+ { "eval": "EVAL_KETCH_TEST" }
62
65
  ]
63
66
  }
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "roblox",
3
+ "vendorUrl": "https://roblox.com",
4
+ "cosmetic": false,
5
+ "runContext": {
6
+ "main": true,
7
+ "frame": false,
8
+ "urlPattern": "^https://(www\\.)?roblox\\.com/"
9
+ },
10
+ "prehideSelectors": [],
11
+ "detectCmp": [
12
+ {
13
+ "exists": ".cookie-banner-wrapper"
14
+ }
15
+ ],
16
+ "detectPopup": [
17
+ {
18
+ "visible": ".cookie-banner-wrapper .cookie-banner"
19
+ }
20
+ ],
21
+ "optIn": [
22
+ {
23
+ "waitForThenClick": ".cookie-banner-wrapper button.btn-cta-lg"
24
+ }
25
+ ],
26
+ "optOut": [
27
+ {
28
+ "waitForThenClick": ".cookie-banner-wrapper button.btn-secondary-lg"
29
+ }
30
+ ],
31
+ "test": [
32
+ {
33
+ "eval": "EVAL_ROBLOX_TEST"
34
+ }
35
+ ]
36
+ }
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "uswitch.com",
3
- "prehideSelectors": ["#cookie-banner-wrapper"],
4
- "detectCmp": [{ "exists": "#cookie-banner-wrapper"}],
5
- "detectPopup": [{ "visible": "#cookie-banner-wrapper" }],
6
- "optIn": [{ "click": "#cookie_banner_accept_mobile" }],
7
- "optOut": [{ "click": "#cookie_banner_save"}]
3
+ "runContext": {
4
+ "main": true,
5
+ "frame": false,
6
+ "urlPattern": "^https://(www\\.)?uswitch\\.com/"
7
+ },
8
+ "prehideSelectors": [".ucb"],
9
+ "detectCmp": [{ "exists": ".ucb-banner"}],
10
+ "detectPopup": [{ "visible": ".ucb-banner" }],
11
+ "optIn": [{ "waitForThenClick": ".ucb-banner .ucb-btn-accept" }],
12
+ "optOut": [{ "waitForThenClick": ".ucb-banner .ucb-btn-save" }]
8
13
  }