Remove Admiral adblock walls
This commit is contained in:
@@ -64,6 +64,27 @@ const COMMON_ANNOYANCE_ROOT_CLASSES = [
|
|||||||
"iubenda-cs-visible"
|
"iubenda-cs-visible"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const COMMON_ANNOYANCE_TRIGGER_SELECTORS = [
|
||||||
|
"a[href*=\"getadmiral.com\" i]",
|
||||||
|
"a[href*=\"%67e%74%61%64mi%72%61l.com\" i]",
|
||||||
|
"a[href*=\"admiraladblock\" i]",
|
||||||
|
"button",
|
||||||
|
"[role=\"dialog\"]",
|
||||||
|
"[aria-modal=\"true\"]"
|
||||||
|
];
|
||||||
|
|
||||||
|
const COMMON_ANNOYANCE_TEXT_PATTERNS = [
|
||||||
|
"ad blocker detected",
|
||||||
|
"allow ads",
|
||||||
|
"allowlist",
|
||||||
|
"continue using your ad blocker",
|
||||||
|
"disable your ad blocker",
|
||||||
|
"support us by disabling",
|
||||||
|
"support the verge by allowing ads",
|
||||||
|
"turn off your ad blocker",
|
||||||
|
"you are using an ad blocker"
|
||||||
|
];
|
||||||
|
|
||||||
const COMMON_ANNOYANCE_CSS = `
|
const COMMON_ANNOYANCE_CSS = `
|
||||||
${COMMON_ANNOYANCE_SELECTORS.join(",\n")} {
|
${COMMON_ANNOYANCE_SELECTORS.join(",\n")} {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
@@ -1253,7 +1274,57 @@ async function injectCosmeticFilters(page, hostname) {
|
|||||||
|
|
||||||
async function removeCommonAnnoyances(page) {
|
async function removeCommonAnnoyances(page) {
|
||||||
try {
|
try {
|
||||||
await page.evaluate(({ selectors, rootClasses }) => {
|
await page.evaluate(({ selectors, rootClasses, triggerSelectors, textPatterns }) => {
|
||||||
|
const annoyanceText = textPatterns.map((pattern) => pattern.toLowerCase());
|
||||||
|
const textFor = (element) => (element.innerText || element.textContent || "")
|
||||||
|
.replace(/\s+/g, " ")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
|
const isTextTrigger = (element) => {
|
||||||
|
const text = textFor(element);
|
||||||
|
if (!text) return false;
|
||||||
|
if (annoyanceText.some((pattern) => text.includes(pattern))) return true;
|
||||||
|
return text.includes("ad blocker") && /allow|disable|turn off|subscribe|support/.test(text);
|
||||||
|
};
|
||||||
|
const isLinkTrigger = (element) => {
|
||||||
|
const href = `${element.getAttribute("href") || ""} ${element.href || ""}`.toLowerCase();
|
||||||
|
return href.includes("getadmiral.com") ||
|
||||||
|
href.includes("%67e%74%61%64mi%72%61l.com") ||
|
||||||
|
href.includes("admiraladblock");
|
||||||
|
};
|
||||||
|
const findModalRoot = (element) => {
|
||||||
|
let node = element;
|
||||||
|
let best = null;
|
||||||
|
while (node && node !== document.body && node !== document.documentElement) {
|
||||||
|
const style = window.getComputedStyle(node);
|
||||||
|
const rect = node.getBoundingClientRect();
|
||||||
|
const zIndex = Number.parseInt(style.zIndex, 10);
|
||||||
|
const positioned = /fixed|absolute|sticky/i.test(style.position);
|
||||||
|
const wide = rect.width >= window.innerWidth * 0.5;
|
||||||
|
const tall = rect.height >= window.innerHeight * 0.4;
|
||||||
|
const fullScreen = rect.width >= window.innerWidth * 0.9 && rect.height >= window.innerHeight * 0.9;
|
||||||
|
if ((positioned && (wide || tall || zIndex >= 1000)) || fullScreen) {
|
||||||
|
best = node;
|
||||||
|
}
|
||||||
|
node = node.parentElement;
|
||||||
|
}
|
||||||
|
return best || element.closest("[role=\"dialog\"], [aria-modal=\"true\"]") || element;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const selector of triggerSelectors) {
|
||||||
|
try {
|
||||||
|
document.querySelectorAll(selector).forEach((element) => {
|
||||||
|
if (!isLinkTrigger(element) && !isTextTrigger(element)) return;
|
||||||
|
const root = findModalRoot(element);
|
||||||
|
if (root && root !== document.body && root !== document.documentElement) {
|
||||||
|
root.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// Ignore selectors unsupported by the current browser.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const selector of selectors) {
|
for (const selector of selectors) {
|
||||||
try {
|
try {
|
||||||
document.querySelectorAll(selector).forEach((element) => element.remove());
|
document.querySelectorAll(selector).forEach((element) => element.remove());
|
||||||
@@ -1280,7 +1351,9 @@ async function removeCommonAnnoyances(page) {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
selectors: COMMON_ANNOYANCE_SELECTORS,
|
selectors: COMMON_ANNOYANCE_SELECTORS,
|
||||||
rootClasses: COMMON_ANNOYANCE_ROOT_CLASSES
|
rootClasses: COMMON_ANNOYANCE_ROOT_CLASSES,
|
||||||
|
triggerSelectors: COMMON_ANNOYANCE_TRIGGER_SELECTORS,
|
||||||
|
textPatterns: COMMON_ANNOYANCE_TEXT_PATTERNS
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
// Ignore cleanup failures; the archive is still useful.
|
// Ignore cleanup failures; the archive is still useful.
|
||||||
|
|||||||
@@ -100,6 +100,34 @@ test("renderPage removes common cookie consent overlays before snapshot", async
|
|||||||
assert.doesNotMatch(rendered, /<body[^>]*class="[^"]*didomi-popup-open/i);
|
assert.doesNotMatch(rendered, /<body[^>]*class="[^"]*didomi-popup-open/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("renderPage removes Admiral adblock walls before snapshot", async () => {
|
||||||
|
const html = `<!doctype html>
|
||||||
|
<html style="overflow: hidden;">
|
||||||
|
<body style="overflow: hidden;">
|
||||||
|
<main>Article text</main>
|
||||||
|
<div style="position: fixed; inset: 0; z-index: 2147483647; overflow: auto;">
|
||||||
|
<section>
|
||||||
|
<h2>Support The Verge by allowing ads</h2>
|
||||||
|
<p>Or <a href="https://www.theverge.com/subscribe?itm_campaign=admiraladblock&itm_source=popup">subscribe</a> to continue using your ad blocker uninterrupted.</p>
|
||||||
|
<button>ALLOW ADS</button>
|
||||||
|
<a href="https://%67e%74%61%64mi%72%61l.com/pb/">Powered By</a>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
|
||||||
|
const rendered = await renderPage(`data:text/html,${encodeURIComponent(html)}`, {
|
||||||
|
userscriptDelay: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.match(rendered, /Article text/);
|
||||||
|
assert.doesNotMatch(rendered, /Support The Verge by allowing ads/);
|
||||||
|
assert.doesNotMatch(rendered, /ALLOW ADS/);
|
||||||
|
assert.doesNotMatch(rendered, /getadmiral|%67e%74%61%64mi%72%61l/i);
|
||||||
|
assert.doesNotMatch(rendered, /<html[^>]*style="[^"]*overflow:\s*hidden/i);
|
||||||
|
assert.doesNotMatch(rendered, /<body[^>]*style="[^"]*overflow:\s*hidden/i);
|
||||||
|
});
|
||||||
|
|
||||||
test("renderPage serializes CSSOM-inserted style rules", async () => {
|
test("renderPage serializes CSSOM-inserted style rules", async () => {
|
||||||
const html = `<!doctype html>
|
const html = `<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
|
|||||||
Reference in New Issue
Block a user