@duckduckgo/autoconsent 15.0.0 → 15.1.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/CHANGELOG.md +12 -0
- package/build.sh +3 -0
- package/dist/addon-firefox/content.bundle.js +15 -7
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/popup.bundle.js +180 -13
- package/dist/addon-firefox/popup.html +93 -8
- package/dist/addon-firefox/rule-index.json +1 -0
- package/dist/addon-mv3/content.bundle.js +15 -7
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/popup.bundle.js +180 -13
- package/dist/addon-mv3/popup.html +93 -8
- package/dist/addon-mv3/rule-index.json +1 -0
- package/dist/autoconsent.cjs.js +15 -7
- package/dist/autoconsent.esm.js +15 -7
- package/dist/autoconsent.extra.cjs.js +15 -7
- package/dist/autoconsent.extra.esm.js +15 -7
- package/dist/autoconsent.playwright.js +15 -7
- package/dist/autoconsent.standalone.js +4138 -0
- package/dist/types/cmps/trustarc-top.d.ts +1 -1
- package/dist/types/eval-handler.d.ts +3 -3
- package/lib/cmps/conversant.ts +7 -4
- package/lib/cmps/trustarc-top.ts +1 -1
- package/lib/cmps/uniconsent.ts +4 -4
- package/lib/eval-handler.ts +6 -3
- package/lib/utils.ts +11 -5
- package/package.json +1 -1
- package/rules/build.ts +4 -0
- package/rules/rule-index-builder.ts +63 -0
- package/rules/rule-index.json +1 -0
- package/standalone/content.ts +103 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# v15.1.0 (Tue Jun 23 2026)
|
|
2
|
+
|
|
3
|
+
#### 🚀 Enhancement
|
|
4
|
+
|
|
5
|
+
- Test extension improvements [#1372](https://github.com/duckduckgo/autoconsent/pull/1372) ([@muodov](https://github.com/muodov))
|
|
6
|
+
|
|
7
|
+
#### Authors: 1
|
|
8
|
+
|
|
9
|
+
- Maxim Tsoy ([@muodov](https://github.com/muodov))
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
1
13
|
# v15.0.0 (Sat Jun 20 2026)
|
|
2
14
|
|
|
3
15
|
#### 💥 Breaking Change
|
package/build.sh
CHANGED
|
@@ -4,6 +4,7 @@ set -ex
|
|
|
4
4
|
ESBUILD="node_modules/.bin/esbuild --bundle"
|
|
5
5
|
|
|
6
6
|
$ESBUILD --format=iife --target=es2021 playwright/content.ts --outfile=dist/autoconsent.playwright.js
|
|
7
|
+
$ESBUILD --format=iife --target=es2021 standalone/content.ts --outfile=dist/autoconsent.standalone.js
|
|
7
8
|
$ESBUILD --format=esm --target=es2021 lib/web-extra.ts --outfile=dist/autoconsent.extra.esm.js
|
|
8
9
|
$ESBUILD --format=cjs --target=es2021 --platform=node lib/web-extra.ts --outfile=dist/autoconsent.extra.cjs.js
|
|
9
10
|
$ESBUILD --format=esm --target=es2021 lib/web.ts --outfile=dist/autoconsent.esm.js
|
|
@@ -25,8 +26,10 @@ cp -r addon/icons dist/addon-mv3/
|
|
|
25
26
|
cp -r addon/icons dist/addon-firefox/
|
|
26
27
|
cp rules/rules.json dist/addon-mv3/
|
|
27
28
|
cp rules/compact-rules.json dist/addon-mv3/
|
|
29
|
+
cp rules/rule-index.json dist/addon-mv3/
|
|
28
30
|
cp rules/rules.json dist/addon-firefox/
|
|
29
31
|
cp rules/compact-rules.json dist/addon-firefox/
|
|
32
|
+
cp rules/rule-index.json dist/addon-firefox/
|
|
30
33
|
cp addon/popup.html dist/addon-mv3/
|
|
31
34
|
cp addon/popup.html dist/addon-firefox/
|
|
32
35
|
cp -r addon/devtools dist/addon-mv3/
|
|
@@ -434,6 +434,9 @@
|
|
|
434
434
|
sendContentMessage: null
|
|
435
435
|
};
|
|
436
436
|
function requestEval(code, snippetId) {
|
|
437
|
+
if (!evalState.sendContentMessage) {
|
|
438
|
+
return Promise.reject(new Error("AutoConsent is not initialized yet"));
|
|
439
|
+
}
|
|
437
440
|
const id = getRandomID();
|
|
438
441
|
evalState.sendContentMessage({
|
|
439
442
|
type: "eval",
|
|
@@ -736,12 +739,13 @@
|
|
|
736
739
|
}
|
|
737
740
|
}
|
|
738
741
|
function highlightNode(node) {
|
|
742
|
+
const highlightedNode = node;
|
|
739
743
|
if (!node.style) return;
|
|
740
|
-
if (
|
|
744
|
+
if (highlightedNode.__oldStyles !== void 0) {
|
|
741
745
|
return;
|
|
742
746
|
}
|
|
743
747
|
if (node.hasAttribute("style")) {
|
|
744
|
-
|
|
748
|
+
highlightedNode.__oldStyles = node.style.cssText;
|
|
745
749
|
}
|
|
746
750
|
node.style.animation = "pulsate .5s infinite";
|
|
747
751
|
node.style.outline = "solid red";
|
|
@@ -769,10 +773,11 @@
|
|
|
769
773
|
document.head.appendChild(styleTag);
|
|
770
774
|
}
|
|
771
775
|
function unhighlightNode(node) {
|
|
776
|
+
const highlightedNode = node;
|
|
772
777
|
if (!node.style || !node.hasAttribute("style")) return;
|
|
773
|
-
if (
|
|
774
|
-
node.style.cssText =
|
|
775
|
-
delete
|
|
778
|
+
if (highlightedNode.__oldStyles !== void 0) {
|
|
779
|
+
node.style.cssText = highlightedNode.__oldStyles;
|
|
780
|
+
delete highlightedNode.__oldStyles;
|
|
776
781
|
} else {
|
|
777
782
|
node.removeAttribute("style");
|
|
778
783
|
}
|
|
@@ -2818,7 +2823,7 @@
|
|
|
2818
2823
|
async optOut() {
|
|
2819
2824
|
await this.waitForElement(".unic button", 1e3);
|
|
2820
2825
|
document.querySelectorAll(".unic button").forEach((button) => {
|
|
2821
|
-
const text = button.textContent;
|
|
2826
|
+
const text = button.textContent || "";
|
|
2822
2827
|
if (text.includes("Manage Options") || text.includes("Optionen verwalten")) {
|
|
2823
2828
|
button.click();
|
|
2824
2829
|
}
|
|
@@ -2831,7 +2836,7 @@
|
|
|
2831
2836
|
}
|
|
2832
2837
|
});
|
|
2833
2838
|
for (const b of document.querySelectorAll(".unic button")) {
|
|
2834
|
-
const text = b.textContent;
|
|
2839
|
+
const text = b.textContent || "";
|
|
2835
2840
|
for (const pattern of ["Confirm Choices", "Save Choices", "Auswahl speichern"]) {
|
|
2836
2841
|
if (text.includes(pattern)) {
|
|
2837
2842
|
b.click();
|
|
@@ -2888,6 +2893,9 @@
|
|
|
2888
2893
|
item.querySelector(".cmp-accordion-item-title").click();
|
|
2889
2894
|
await waitFor(() => !!item.querySelector(".cmp-accordion-item-content.cmp-active"), 10, 50);
|
|
2890
2895
|
const content = item.querySelector(".cmp-accordion-item-content.cmp-active");
|
|
2896
|
+
if (!content) {
|
|
2897
|
+
return false;
|
|
2898
|
+
}
|
|
2891
2899
|
content.querySelectorAll(".cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)").forEach((e) => e.click());
|
|
2892
2900
|
content.querySelectorAll(".cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)").forEach((e) => e.click());
|
|
2893
2901
|
}
|
|
@@ -913,6 +913,7 @@
|
|
|
913
913
|
}
|
|
914
914
|
|
|
915
915
|
// addon/popup.ts
|
|
916
|
+
var maxRenderedRules = 100;
|
|
916
917
|
async function init() {
|
|
917
918
|
const autoconsentConfig = await storageGet("config");
|
|
918
919
|
const enabledCheckbox = document.querySelector("input#enabled");
|
|
@@ -926,8 +927,7 @@
|
|
|
926
927
|
const cosmeticOffRadio = document.querySelector("input#cosmetic-off");
|
|
927
928
|
const generatedOnRadio = document.querySelector("input#generated-on");
|
|
928
929
|
const generatedOffRadio = document.querySelector("input#generated-off");
|
|
929
|
-
const
|
|
930
|
-
const heuristicActionOffRadio = document.querySelector("input#heuristic-action-off");
|
|
930
|
+
const heuristicActionCheckbox = document.querySelector("input#heuristic-action");
|
|
931
931
|
const visualTestOnRadio = document.querySelector("input#visual-test-on");
|
|
932
932
|
const visualTestOffRadio = document.querySelector("input#visual-test-off");
|
|
933
933
|
const popupMutationOnRadio = document.querySelector("input#popup-mutation-on");
|
|
@@ -942,6 +942,47 @@
|
|
|
942
942
|
const logsMessagesCheckbox = document.querySelector("input#logs-messages");
|
|
943
943
|
const ruleReloadButton = document.querySelector("#reload");
|
|
944
944
|
const resetButton = document.querySelector("#reset");
|
|
945
|
+
const ruleSectionControls = {
|
|
946
|
+
generated: {
|
|
947
|
+
details: document.querySelector("#generated-rules-section"),
|
|
948
|
+
count: document.querySelector("#generated-rules-count"),
|
|
949
|
+
search: document.querySelector("#generated-rules-search"),
|
|
950
|
+
enableAll: document.querySelector("#generated-rules-enable-all"),
|
|
951
|
+
disableAll: document.querySelector("#generated-rules-disable-all"),
|
|
952
|
+
status: document.querySelector("#generated-rules-status"),
|
|
953
|
+
list: document.querySelector("#generated-rules-list")
|
|
954
|
+
},
|
|
955
|
+
generic: {
|
|
956
|
+
details: document.querySelector("#generic-rules-section"),
|
|
957
|
+
count: document.querySelector("#generic-rules-count"),
|
|
958
|
+
search: document.querySelector("#generic-rules-search"),
|
|
959
|
+
enableAll: document.querySelector("#generic-rules-enable-all"),
|
|
960
|
+
disableAll: document.querySelector("#generic-rules-disable-all"),
|
|
961
|
+
status: document.querySelector("#generic-rules-status"),
|
|
962
|
+
list: document.querySelector("#generic-rules-list")
|
|
963
|
+
},
|
|
964
|
+
code: {
|
|
965
|
+
details: document.querySelector("#code-rules-section"),
|
|
966
|
+
count: document.querySelector("#code-rules-count"),
|
|
967
|
+
search: document.querySelector("#code-rules-search"),
|
|
968
|
+
enableAll: document.querySelector("#code-rules-enable-all"),
|
|
969
|
+
disableAll: document.querySelector("#code-rules-disable-all"),
|
|
970
|
+
status: document.querySelector("#code-rules-status"),
|
|
971
|
+
list: document.querySelector("#code-rules-list")
|
|
972
|
+
},
|
|
973
|
+
consentomatic: {
|
|
974
|
+
details: document.querySelector("#consentomatic-rules-section"),
|
|
975
|
+
count: document.querySelector("#consentomatic-rules-count"),
|
|
976
|
+
search: document.querySelector("#consentomatic-rules-search"),
|
|
977
|
+
enableAll: document.querySelector("#consentomatic-rules-enable-all"),
|
|
978
|
+
disableAll: document.querySelector("#consentomatic-rules-disable-all"),
|
|
979
|
+
status: document.querySelector("#consentomatic-rules-status"),
|
|
980
|
+
list: document.querySelector("#consentomatic-rules-list")
|
|
981
|
+
}
|
|
982
|
+
};
|
|
983
|
+
let ruleIndexPromise = null;
|
|
984
|
+
let ruleIndex = null;
|
|
985
|
+
autoconsentConfig.disabledCmps = autoconsentConfig.disabledCmps || [];
|
|
945
986
|
const [currentTab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
|
|
946
987
|
if (!currentTab.url || !currentTab.id) {
|
|
947
988
|
console.error("Current tab is not valid");
|
|
@@ -1007,11 +1048,7 @@
|
|
|
1007
1048
|
} else {
|
|
1008
1049
|
generatedOffRadio.checked = true;
|
|
1009
1050
|
}
|
|
1010
|
-
|
|
1011
|
-
heuristicActionOnRadio.checked = true;
|
|
1012
|
-
} else {
|
|
1013
|
-
heuristicActionOffRadio.checked = true;
|
|
1014
|
-
}
|
|
1051
|
+
heuristicActionCheckbox.checked = autoconsentConfig.enableHeuristicAction;
|
|
1015
1052
|
if (autoconsentConfig.visualTest) {
|
|
1016
1053
|
visualTestOnRadio.checked = true;
|
|
1017
1054
|
} else {
|
|
@@ -1061,11 +1098,10 @@
|
|
|
1061
1098
|
generatedOnRadio.addEventListener("change", generatedChange);
|
|
1062
1099
|
generatedOffRadio.addEventListener("change", generatedChange);
|
|
1063
1100
|
function heuristicActionChange() {
|
|
1064
|
-
autoconsentConfig.enableHeuristicAction =
|
|
1101
|
+
autoconsentConfig.enableHeuristicAction = heuristicActionCheckbox.checked;
|
|
1065
1102
|
storageSet({ config: autoconsentConfig });
|
|
1066
1103
|
}
|
|
1067
|
-
|
|
1068
|
-
heuristicActionOffRadio.addEventListener("change", heuristicActionChange);
|
|
1104
|
+
heuristicActionCheckbox.addEventListener("change", heuristicActionChange);
|
|
1069
1105
|
function visualTestChange() {
|
|
1070
1106
|
autoconsentConfig.visualTest = visualTestOnRadio.checked;
|
|
1071
1107
|
storageSet({ config: autoconsentConfig });
|
|
@@ -1111,10 +1147,141 @@
|
|
|
1111
1147
|
logsMessagesCheckbox.addEventListener("change", () => {
|
|
1112
1148
|
updateLogsConfig();
|
|
1113
1149
|
});
|
|
1150
|
+
async function loadRuleIndex() {
|
|
1151
|
+
if (!ruleIndexPromise) {
|
|
1152
|
+
ruleIndexPromise = fetch("./rule-index.json").then(async (res) => await res.json());
|
|
1153
|
+
}
|
|
1154
|
+
ruleIndex = await ruleIndexPromise;
|
|
1155
|
+
updateRuleCounts();
|
|
1156
|
+
return ruleIndex;
|
|
1157
|
+
}
|
|
1158
|
+
function updateRuleCounts() {
|
|
1159
|
+
if (!ruleIndex) {
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
const disabledCmps = autoconsentConfig.disabledCmps || [];
|
|
1163
|
+
Object.keys(ruleSectionControls).forEach((section) => {
|
|
1164
|
+
const sectionRules = ruleIndex?.filter((rule) => rule.section === section) || [];
|
|
1165
|
+
const disabledInSection = sectionRules.filter((rule) => disabledCmps.includes(rule.name)).length;
|
|
1166
|
+
const count = ruleSectionControls[section].count;
|
|
1167
|
+
count.textContent = `(${disabledInSection}/${sectionRules.length} disabled)`;
|
|
1168
|
+
count.classList.toggle("rule-count-disabled", disabledInSection > 0);
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
function setRuleEnabled(ruleName, enabled) {
|
|
1172
|
+
const disabledCmps = new Set(autoconsentConfig.disabledCmps || []);
|
|
1173
|
+
if (enabled) {
|
|
1174
|
+
disabledCmps.delete(ruleName);
|
|
1175
|
+
} else {
|
|
1176
|
+
disabledCmps.add(ruleName);
|
|
1177
|
+
}
|
|
1178
|
+
autoconsentConfig.disabledCmps = Array.from(disabledCmps).sort();
|
|
1179
|
+
storageSet({ config: autoconsentConfig });
|
|
1180
|
+
updateRuleCounts();
|
|
1181
|
+
}
|
|
1182
|
+
function renderOpenRuleSections() {
|
|
1183
|
+
Object.keys(ruleSectionControls).forEach((section) => {
|
|
1184
|
+
if (ruleSectionControls[section].details.open) {
|
|
1185
|
+
renderRuleSection(section);
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
function setRuleSectionEnabled(section, enabled) {
|
|
1190
|
+
if (!ruleIndex) {
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
const disabledCmps = new Set(autoconsentConfig.disabledCmps || []);
|
|
1194
|
+
ruleIndex.filter((rule) => rule.section === section).forEach((rule) => {
|
|
1195
|
+
if (enabled) {
|
|
1196
|
+
disabledCmps.delete(rule.name);
|
|
1197
|
+
} else {
|
|
1198
|
+
disabledCmps.add(rule.name);
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
autoconsentConfig.disabledCmps = Array.from(disabledCmps).sort();
|
|
1202
|
+
storageSet({ config: autoconsentConfig });
|
|
1203
|
+
updateRuleCounts();
|
|
1204
|
+
renderOpenRuleSections();
|
|
1205
|
+
}
|
|
1206
|
+
function renderRuleSection(section) {
|
|
1207
|
+
const controls = ruleSectionControls[section];
|
|
1208
|
+
if (!ruleIndex) {
|
|
1209
|
+
controls.status.textContent = "Rules are not loaded yet.";
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
const disabledCmps = autoconsentConfig.disabledCmps || [];
|
|
1213
|
+
const searchQuery = controls.search.value.trim().toLowerCase();
|
|
1214
|
+
const sectionRules = ruleIndex.filter((rule) => rule.section === section);
|
|
1215
|
+
const matchingRules = sectionRules.filter((rule) => {
|
|
1216
|
+
if (!searchQuery) {
|
|
1217
|
+
return disabledCmps.includes(rule.name);
|
|
1218
|
+
}
|
|
1219
|
+
return rule.name.toLowerCase().includes(searchQuery) || !!rule.urlPattern?.toLowerCase().includes(searchQuery);
|
|
1220
|
+
});
|
|
1221
|
+
const renderedRules = matchingRules.slice(0, maxRenderedRules);
|
|
1222
|
+
const disabledInSection = sectionRules.filter((rule) => disabledCmps.includes(rule.name)).length;
|
|
1223
|
+
controls.status.textContent = searchQuery ? `Showing ${renderedRules.length} of ${matchingRules.length} matches. ${disabledInSection} disabled.` : `Showing ${renderedRules.length} of ${disabledInSection} disabled rules. Search to find enabled rules.`;
|
|
1224
|
+
controls.list.replaceChildren(
|
|
1225
|
+
...renderedRules.map((rule) => {
|
|
1226
|
+
const checkbox = document.createElement("input");
|
|
1227
|
+
checkbox.type = "checkbox";
|
|
1228
|
+
checkbox.checked = !disabledCmps.includes(rule.name);
|
|
1229
|
+
checkbox.addEventListener("change", () => {
|
|
1230
|
+
setRuleEnabled(rule.name, checkbox.checked);
|
|
1231
|
+
renderRuleSection(section);
|
|
1232
|
+
});
|
|
1233
|
+
const label = document.createElement("label");
|
|
1234
|
+
label.className = "rule-row";
|
|
1235
|
+
label.title = rule.urlPattern ? `${rule.name}
|
|
1236
|
+
${rule.urlPattern}` : rule.name;
|
|
1237
|
+
label.append(checkbox, document.createTextNode(` ${rule.name}${rule.cosmetic ? " (cosmetic)" : ""}`));
|
|
1238
|
+
return label;
|
|
1239
|
+
})
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
async function loadAndRenderRuleSection(section) {
|
|
1243
|
+
ruleSectionControls[section].status.textContent = "Loading rules...";
|
|
1244
|
+
try {
|
|
1245
|
+
await loadRuleIndex();
|
|
1246
|
+
renderRuleSection(section);
|
|
1247
|
+
} catch (e) {
|
|
1248
|
+
console.error("Failed to load rule index", e);
|
|
1249
|
+
ruleSectionControls[section].status.textContent = "Failed to load rules.";
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
Object.keys(ruleSectionControls).forEach((section) => {
|
|
1253
|
+
const controls = ruleSectionControls[section];
|
|
1254
|
+
controls.details.addEventListener("toggle", () => {
|
|
1255
|
+
if (controls.details.open) {
|
|
1256
|
+
loadAndRenderRuleSection(section);
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
controls.search.addEventListener("input", () => renderRuleSection(section));
|
|
1260
|
+
controls.enableAll.addEventListener("click", async () => {
|
|
1261
|
+
await loadRuleIndex();
|
|
1262
|
+
setRuleSectionEnabled(section, true);
|
|
1263
|
+
});
|
|
1264
|
+
controls.disableAll.addEventListener("click", async () => {
|
|
1265
|
+
await loadRuleIndex();
|
|
1266
|
+
setRuleSectionEnabled(section, false);
|
|
1267
|
+
});
|
|
1268
|
+
});
|
|
1269
|
+
loadRuleIndex().catch((e) => {
|
|
1270
|
+
console.error("Failed to load rule index", e);
|
|
1271
|
+
});
|
|
1114
1272
|
ruleReloadButton.addEventListener("click", async () => {
|
|
1115
|
-
const
|
|
1116
|
-
|
|
1117
|
-
|
|
1273
|
+
const [compactRulesRes, fullRulesRes] = await Promise.all([fetch("./compact-rules.json"), fetch("./rules.json")]);
|
|
1274
|
+
const fullRules = await fullRulesRes.json();
|
|
1275
|
+
await storageSet({
|
|
1276
|
+
rules: await compactRulesRes.json(),
|
|
1277
|
+
fullRules: fullRules.autoconsent
|
|
1278
|
+
});
|
|
1279
|
+
ruleIndexPromise = null;
|
|
1280
|
+
ruleIndex = null;
|
|
1281
|
+
Object.keys(ruleSectionControls).forEach((section) => {
|
|
1282
|
+
if (ruleSectionControls[section].details.open) {
|
|
1283
|
+
loadAndRenderRuleSection(section);
|
|
1284
|
+
}
|
|
1118
1285
|
});
|
|
1119
1286
|
});
|
|
1120
1287
|
resetButton.addEventListener("click", async () => {
|
|
@@ -23,6 +23,52 @@
|
|
|
23
23
|
cursor: pointer;
|
|
24
24
|
border-radius: 2px;
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
.rule-section {
|
|
28
|
+
margin: 0.5em 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.rule-search {
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
margin: 0.5em 0;
|
|
34
|
+
width: 100%;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.rule-actions {
|
|
38
|
+
display: flex;
|
|
39
|
+
gap: 0.5em;
|
|
40
|
+
margin: 0.5em 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.rule-actions button {
|
|
44
|
+
flex: 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.rule-list {
|
|
48
|
+
border: 1px solid #ddd;
|
|
49
|
+
max-height: 12em;
|
|
50
|
+
overflow-y: auto;
|
|
51
|
+
padding: 0.25em;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.rule-row {
|
|
55
|
+
display: block;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
padding: 0.15em 0;
|
|
58
|
+
text-overflow: ellipsis;
|
|
59
|
+
white-space: nowrap;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.rule-list-status {
|
|
63
|
+
color: #666;
|
|
64
|
+
font-size: 0.9em;
|
|
65
|
+
margin: 0.25em 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.rule-count-disabled {
|
|
69
|
+
color: #b00020;
|
|
70
|
+
font-weight: bold;
|
|
71
|
+
}
|
|
26
72
|
</style>
|
|
27
73
|
</head>
|
|
28
74
|
|
|
@@ -96,16 +142,55 @@
|
|
|
96
142
|
</fieldset>
|
|
97
143
|
|
|
98
144
|
<fieldset>
|
|
99
|
-
<legend>
|
|
145
|
+
<legend>Rules</legend>
|
|
100
146
|
|
|
101
|
-
<
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
|
|
147
|
+
<details class="rule-section" id="generated-rules-section">
|
|
148
|
+
<summary>Generated rules <span id="generated-rules-count"></span></summary>
|
|
149
|
+
<input class="rule-search" type="search" id="generated-rules-search" placeholder="Search generated rules" />
|
|
150
|
+
<div class="rule-actions">
|
|
151
|
+
<button id="generated-rules-enable-all">Enable all</button>
|
|
152
|
+
<button id="generated-rules-disable-all">Disable all</button>
|
|
153
|
+
</div>
|
|
154
|
+
<div class="rule-list-status" id="generated-rules-status"></div>
|
|
155
|
+
<div class="rule-list" id="generated-rules-list"></div>
|
|
156
|
+
</details>
|
|
105
157
|
|
|
106
|
-
<
|
|
107
|
-
<
|
|
108
|
-
<
|
|
158
|
+
<details class="rule-section" id="generic-rules-section">
|
|
159
|
+
<summary>Generic rules <span id="generic-rules-count"></span></summary>
|
|
160
|
+
<input class="rule-search" type="search" id="generic-rules-search" placeholder="Search generic rules" />
|
|
161
|
+
<div class="rule-actions">
|
|
162
|
+
<button id="generic-rules-enable-all">Enable all</button>
|
|
163
|
+
<button id="generic-rules-disable-all">Disable all</button>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="rule-list-status" id="generic-rules-status"></div>
|
|
166
|
+
<div class="rule-list" id="generic-rules-list"></div>
|
|
167
|
+
</details>
|
|
168
|
+
|
|
169
|
+
<details class="rule-section" id="code-rules-section">
|
|
170
|
+
<summary>Code-based rules <span id="code-rules-count"></span></summary>
|
|
171
|
+
<input class="rule-search" type="search" id="code-rules-search" placeholder="Search code-based rules" />
|
|
172
|
+
<div class="rule-actions">
|
|
173
|
+
<button id="code-rules-enable-all">Enable all</button>
|
|
174
|
+
<button id="code-rules-disable-all">Disable all</button>
|
|
175
|
+
</div>
|
|
176
|
+
<div class="rule-list-status" id="code-rules-status"></div>
|
|
177
|
+
<div class="rule-list" id="code-rules-list"></div>
|
|
178
|
+
</details>
|
|
179
|
+
|
|
180
|
+
<details class="rule-section" id="consentomatic-rules-section">
|
|
181
|
+
<summary>Consent-O-Matic rules <span id="consentomatic-rules-count"></span></summary>
|
|
182
|
+
<input class="rule-search" type="search" id="consentomatic-rules-search" placeholder="Search Consent-O-Matic rules" />
|
|
183
|
+
<div class="rule-actions">
|
|
184
|
+
<button id="consentomatic-rules-enable-all">Enable all</button>
|
|
185
|
+
<button id="consentomatic-rules-disable-all">Disable all</button>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="rule-list-status" id="consentomatic-rules-status"></div>
|
|
188
|
+
<div class="rule-list" id="consentomatic-rules-list"></div>
|
|
189
|
+
</details>
|
|
190
|
+
|
|
191
|
+
<div class="rule-section">
|
|
192
|
+
<input type="checkbox" id="heuristic-action" name="heuristic-action" />
|
|
193
|
+
<label for="heuristic-action">Handle unknown popups (heuristic rule)</label>
|
|
109
194
|
</div>
|
|
110
195
|
</fieldset>
|
|
111
196
|
|