Skip to content

Commit 2479484

Browse files
committed
[mv3] Add old-school filter editor for filter list authors
The filter editor is in the "Custom filters" pane in the dashboard, and is available only when "Developer mode" is enabled. The filter editor is also only available in browsers which WebExtensions framework supports the `userScripts` and `offscreen` APIs (so only Chromium-based browsers currently). The filter editor's main purpose is as a tool for filter list authors, it's not meant to be a replacement for importing filter lists due to the maxium number of dynamic DNR rules allowed. This is a first version with a list of TODOs, and some filter syntaxes are currently not supported: - not possible to `badfilter` a filter - cosmetic exception filters do not apply to stock lists - generic cosmetic filters are currently discarded - `popup` filters are discarded - `doc` filters can't trigger the strict-block page
1 parent 2eebc75 commit 2479484

35 files changed

Lines changed: 1378 additions & 645 deletions

platform/mv3/extension/_locales/en/messages.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@
263263
"message": "When active, matching filters will automatically close unwanted browser tabs created by websites.",
264264
"description": "Short description for a checkbox in the options page"
265265
},
266+
"sandboxEditorLabel": {
267+
"message": "Filter-creation sandbox",
268+
"description": "Header for filter-creation section in the dashboard"
269+
},
266270
"developerModeLabel": {
267271
"message": "Developer mode",
268272
"description": "Label for a checkbox in the options page"
@@ -303,11 +307,11 @@
303307
"message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}",
304308
"description": "Text warning about an incoming redirect"
305309
},
306-
"strictblockNoParamsPrompt": {
310+
"strictblockNoParamsPrompt": {
307311
"message": "without parameters",
308312
"description": "Label to be used for the parameter-less URL"
309313
},
310-
"strictblockBack": {
314+
"strictblockBack": {
311315
"message": "Go back",
312316
"description": "A button to go back to the previous web page"
313317
},

platform/mv3/extension/css/develop.css

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,57 +19,58 @@ section[data-pane="develop"] > div > * {
1919
margin-top: 1em;
2020
}
2121

22-
#cm-container {
22+
.cm-container {
2323
flex-grow: 1;
2424
font-size: var(--monospace-size);
25-
overflow: hidden;
25+
max-height: stretch;
26+
padding-bottom: 2em;
2627
}
2728

2829
/* https://discuss.codemirror.net/t/how-to-set-max-height-of-the-editor/2882/2 */
29-
#cm-container .cm-editor {
30+
.cm-container .cm-editor {
3031
background-color: var(--surface-0);
3132
height: 100%;
3233
}
3334

34-
#cm-container .cm-editor .cm-line:has(.ubol-boundary) {
35+
.cm-container .cm-editor .cm-line:has(.ubol-boundary) {
3536
background-image: url('line-hor-dashed.png'), url('line-hor-dashed.png');
3637
background-position: left 3px, left calc(100% - 3px);
3738
background-repeat: repeat-x;
3839
}
39-
#cm-container .cm-editor {
40+
.cm-container .cm-editor {
4041
color: var(--ink-1);
4142
}
42-
:root.dark #cm-container .cm-editor {
43+
:root.dark .cm-container .cm-editor {
4344
color: var(--ink-2);
4445
}
45-
#cm-container .cm-editor .cm-line .ubol-comment {
46+
.cm-container .cm-editor .cm-line .ubol-comment {
4647
color: #ba5300;
4748
}
48-
:root.dark #cm-container .cm-editor .cm-line .ubol-comment {
49+
:root.dark .cm-container .cm-editor .cm-line .ubol-comment {
4950
color: #fa7000;
5051
}
51-
#cm-container .cm-editor .cm-line .ubol-keyword {
52+
.cm-container .cm-editor .cm-line .ubol-keyword {
5253
color: #ae42be;
5354
}
54-
:root.dark #cm-container .cm-editor .cm-line .ubol-keyword {
55+
:root.dark .cm-container .cm-editor .cm-line .ubol-keyword {
5556
color: #ea59ff;
5657
}
57-
#cm-container .cm-editor .cm-line .ubol-literal {
58+
.cm-container .cm-editor .cm-line .ubol-literal {
5859
color: #168156;
5960
}
60-
:root.dark #cm-container .cm-editor .cm-line .ubol-literal {
61+
:root.dark .cm-container .cm-editor .cm-line .ubol-literal {
6162
color: #1dae74;
6263
}
63-
#cm-container .cm-editor .cm-line.badline {
64+
.cm-container .cm-editor .cm-line.badline {
6465
background-color: color-mix(in srgb, var(--info3-ink) 15%, transparent 85%);
6566
}
6667

67-
#cm-container .cm-editor .cm-line .badmark {
68+
.cm-container .cm-editor .cm-line .badmark {
6869
text-decoration: underline var(--cm-negative) wavy;
6970
text-decoration-skip-ink: none;
7071
}
7172

72-
#cm-container .cm-editor .cm-panel.cm-search {
73+
.cm-container .cm-editor .cm-panel.cm-search {
7374
display: flex;
7475
flex-wrap: wrap;
7576
font-family: sans-serif;
@@ -78,25 +79,25 @@ section[data-pane="develop"] > div > * {
7879
padding: 0.5em 1.5em 0.5em 0.5em;
7980
}
8081

81-
#cm-container .cm-editor .cm-panel.cm-search > * {
82+
.cm-container .cm-editor .cm-panel.cm-search > * {
8283
margin: 0;
8384
}
8485

85-
#cm-container .cm-editor .cm-panel.cm-search .cm-textfield,
86-
#cm-container .cm-editor .cm-panel.cm-search .cm-button,
87-
#cm-container .cm-editor .cm-panel.cm-search label {
86+
.cm-container .cm-editor .cm-panel.cm-search .cm-textfield,
87+
.cm-container .cm-editor .cm-panel.cm-search .cm-button,
88+
.cm-container .cm-editor .cm-panel.cm-search label {
8889
background-image: inherit;
8990
border: inherit;
9091
flex-grow: 0;
9192
font-size: var(--button-font-size);
9293
min-height: calc(var(--button-font-size) * 1.8);
9394
}
9495

95-
#cm-container .cm-editor .cm-panel .warning {
96+
.cm-container .cm-editor .cm-panel .warning {
9697
color: var(--info3-ink);
9798
}
9899

99-
#cm-container .cm-editor .cm-panel.io-panel {
100+
.cm-container .cm-editor .cm-panel.io-panel {
100101
background-color: var(--surface-1);
101102
box-sizing: border-box;
102103
display: inline-flex;
@@ -105,64 +106,64 @@ section[data-pane="develop"] > div > * {
105106
padding-inline-start: 0;
106107
width: 100%;
107108
}
108-
#cm-container .cm-editor .cm-panel.io-panel button {
109+
.cm-container .cm-editor .cm-panel.io-panel button {
109110
min-height: 30px;
110111
}
111-
#cm-container .cm-editor .cm-panel.io-panel button#revert {
112+
.cm-container .cm-editor .cm-panel.io-panel button#revert {
112113
margin-inline-end: 1em;
113114
}
114-
#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="apply"]) button#apply {
115+
.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="apply"]) button#apply {
115116
display: none;
116117
}
117-
#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="revert"]) button#revert {
118+
.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="revert"]) button#revert {
118119
display: none;
119120
}
120-
#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="import"]) button#import {
121+
.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="import"]) button#import {
121122
display: none;
122123
}
123-
#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="export"]) button#export {
124+
.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="export"]) button#export {
124125
display: none;
125126
}
126127

127-
#cm-container .cm-editor .cm-panel.info-panel {
128+
.cm-container .cm-editor .cm-panel.info-panel {
128129
display: flex;
129130
flex-wrap: nowrap;
130131
font-size: var(--font-size);
131132
padding: var(--default-gap-xxsmall) var(--default-gap-xsmall);
132133
}
133-
#cm-container .cm-editor .cm-panel.info-panel .info {
134+
.cm-container .cm-editor .cm-panel.info-panel .info {
134135
flex-grow: 1;
135136
overflow: auto;
136137
}
137-
#cm-container .cm-editor .cm-panel.info-panel .close {
138+
.cm-container .cm-editor .cm-panel.info-panel .close {
138139
cursor: default;
139140
flex-shrink: 0;
140141
padding-inline-start: 1em;
141142
}
142-
#cm-container .cm-editor .cm-panel.info-panel .close::after {
143+
.cm-container .cm-editor .cm-panel.info-panel .close::after {
143144
content: '\2715';
144145
}
145146

146-
#cm-container .cm-editor .cm-panel.summary-panel {
147+
.cm-container .cm-editor .cm-panel.summary-panel {
147148
background-color: color-mix(in srgb, var(--info1-ink) 15%, transparent 85%);
148149
gap: 1em;
149150
}
150-
#cm-container .cm-editor .cm-panel.summary-panel .info {
151+
.cm-container .cm-editor .cm-panel.summary-panel .info {
151152
flex-shrink: 0;
152153
}
153154

154-
#cm-container .cm-editor .cm-panel.feedback-panel {
155+
.cm-container .cm-editor .cm-panel.feedback-panel {
155156
background-color: color-mix(in srgb, var(--info3-ink) 15%, transparent 85%);
156157
white-space: pre;
157158
max-height: 10cqh;
158159
}
159160

160-
#cm-container .cm-editor .cm-gutterElement {
161+
.cm-container .cm-editor .cm-gutterElement {
161162
cursor: default;
162163
user-select: none;
163164
}
164165

165-
#cm-container .cm-editor .cm-tooltip .badmark-tooltip {
166+
.cm-container .cm-editor .cm-tooltip .badmark-tooltip {
166167
background-color: color-mix(in srgb, var(--info3-ink) 15%, transparent 85%);
167168
padding: var(--default-gap-xxsmall) var(--default-gap-xsmall);
168169
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
.sfp_comment {
2+
color: var(--sf-comment-ink);
3+
}
4+
.sfp_def {
5+
color: var(--sf-def-ink);
6+
}
7+
.sfp_directive {
8+
color: var(--sf-directive-ink);
9+
font-weight: bold;
10+
}
11+
.sfp_error {
12+
color: inherit;
13+
}
14+
.sfp-ext-dom {
15+
}
16+
.sfp-ext-html {
17+
}
18+
.sfp-ext-js {
19+
}
20+
.sfp_keyword {
21+
color: var(--sf-keyword-ink);
22+
}
23+
.sfp_link {
24+
text-decoration: none;
25+
}
26+
.sfp-net {
27+
}
28+
.sfp_notice {
29+
text-decoration-color: var(--sf-notice-ink);
30+
text-decoration-style: solid;
31+
text-decoration-line: underline;
32+
}
33+
.sfp_strong {
34+
font-weight: bold;
35+
}
36+
.sfp_tag {
37+
color: var(--sf-tag-ink);
38+
}
39+
.sfp_unicode {
40+
text-decoration-color: var(--sf-unicode-ink);
41+
text-decoration-style: dashed;
42+
text-decoration-line: underline;
43+
}
44+
.sfp_value {
45+
color: var(--sf-value-ink);
46+
}
47+
.sfp_variable {
48+
color: var(--sf-variable-ink);
49+
}

platform/mv3/extension/css/settings.css

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,8 @@ html.desktop section[data-pane="filters"] li > div:hover {
320320
html.desktop section[data-pane="filters"] li > div span.fa-icon:hover {
321321
transform: scale(1.3);
322322
}
323-
section[data-pane="filters"] aside {
324-
padding: 1em 0.5em;
325-
}
326323
section[data-pane="filters"] aside details {
327-
padding: 0;
324+
padding: 1em 0;
328325
}
329326
section[data-pane="filters"] aside summary {
330327
cursor: default;
@@ -333,15 +330,15 @@ section[data-pane="filters"] aside summary {
333330
section[data-pane="filters"] aside .importFromText {
334331
color: var(--ink-2);
335332
}
336-
section[data-pane="filters"] aside .importFromText textarea {
333+
section[data-pane="filters"] aside textarea {
337334
background-color: var(--surface-1);
338335
border: 1px solid var(--border-1);
339336
box-sizing: border-box;
340337
min-height: 6em;
341338
resize: vertical;
342339
width: 100%;
343340
}
344-
section[data-pane="filters"] aside .importFromText textarea:focus {
341+
section[data-pane="filters"] aside textarea:focus {
345342
background-color: var(--surface-0);
346343
}
347344
section[data-pane="filters"] aside .importFromText:has(textarea:placeholder-shown) button:has([data-i18n="addButton"]) {
@@ -359,6 +356,15 @@ section[data-pane="filters"] aside p {
359356
section[data-pane="filters"] li.error[data-pretty] > div span[contenteditable] {
360357
color: var(--info3-ink);
361358
}
359+
body:not([data-supports~="user-scripts"]) section[data-pane="filters"] aside#sandboxEditor {
360+
display: none;
361+
}
362+
section[data-pane="filters"] aside#sandboxEditor .cm-scroller {
363+
max-height: 480px;
364+
}
365+
body:not([data-develop="true"]) section[data-pane="filters"] aside#sandboxEditor {
366+
display: none;
367+
}
362368

363369
@media (max-width: 480px) {
364370
#defaultFilteringMode {

platform/mv3/extension/dashboard.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<link rel="stylesheet" href="css/dashboard-common.css">
1414
<link rel="stylesheet" href="css/filtering-mode.css">
1515
<link rel="stylesheet" href="css/settings.css">
16+
<link rel="stylesheet" href="css/filter-editor.css">
1617
<link rel="stylesheet" href="css/develop.css">
1718

1819
<link rel="icon" type="image/png" href="img/icon_64.png"/>
@@ -129,6 +130,10 @@ <h3 data-i18n="settingsBackupRestoreLabel">_</h3>
129130
</p>
130131
</details>
131132
</aside>
133+
<aside id="sandboxEditor">
134+
<h3 data-i18n="sandboxEditorLabel">_</h3>
135+
<div class="cm-container"></div>
136+
</aside>
132137
</section>
133138

134139
<!-- -------- -->
@@ -145,7 +150,7 @@ <h3 data-i18n="settingsBackupRestoreLabel">_</h3>
145150
</optgroup>
146151
</select>&nbsp;
147152
</p>
148-
<div id="cm-container"></div>
153+
<div class="cm-container"></div>
149154
</div>
150155
</section>
151156

platform/mv3/extension/js/admin.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import {
4343

4444
import { broadcastMessage } from './utils.js';
4545
import { dnr } from './ext-compat.js';
46-
import { registerInjectables } from './scripting-manager.js';
46+
import { registerContentScripts } from './scripting-manager.js';
4747
import { ubolLog } from './debug.js';
4848

4949
/******************************************************************************/
@@ -114,7 +114,7 @@ const adminSettings = {
114114
if ( this.keys.has('rulesets') ) {
115115
ubolLog('admin setting "rulesets" changed');
116116
await enableRulesets(rulesetConfig.enabledRulesets);
117-
await registerInjectables();
117+
await registerContentScripts();
118118
const results = await Promise.all([
119119
getAdminRulesets(),
120120
dnr.getEnabledRulesets(),
@@ -125,14 +125,14 @@ const adminSettings = {
125125
if ( this.keys.has('defaultFiltering') ) {
126126
ubolLog('admin setting "defaultFiltering" changed');
127127
await readFilteringModeDetails(true);
128-
await registerInjectables();
128+
await registerContentScripts();
129129
const defaultFilteringMode = await getDefaultFilteringMode();
130130
broadcastMessage({ defaultFilteringMode });
131131
}
132132
if ( this.keys.has('noFiltering') ) {
133133
ubolLog('admin setting "noFiltering" changed');
134134
const filteringModeDetails = await readFilteringModeDetails(true);
135-
await registerInjectables();
135+
await registerContentScripts();
136136
broadcastMessage({ filteringModeDetails });
137137
}
138138
if ( this.keys.has('showBlockedCount') ) {

0 commit comments

Comments
 (0)