ublock-origin/docs/tests/procedural-cosmetic-filters...

231 lines
6.3 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Procedural cosmetic filters</title>
<style>
.filters {
font-family: monospace;
white-space: pre;
}
.tests {
align-items: flex-start;
display: flex;
flex-wrap: wrap;
}
.tile {
display: inline-flex;
flex-direction: column;
margin: 0 20px 10px 0;
min-width: 200px;
}
.tile div {
align-items: center;
color: white;
display: flex;
justify-content: center;
}
.tile > div {
height: 50px;
position: relative;
}
.tile > div > div {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.tile > code {
align-self: center;
}
.pass {
background-color: green;
}
.pass::before {
content: 'pass';
}
.fail {
background-color: red;
}
.fail::before {
content: 'fail';
}
.tests a, .tests b {
display: none;
}
.tests a::before {
opacity: 0;
}
.tests b::after {
opacity: 0;
}
</style>
</head>
<body>
<h1>Procedural cosmetic filters</h1>
<p><a href="./.">Back</a>
<br><br></p>
<h3>Filters</h3>
<div class="filters"><noscript>Enable JavaScript to see needed filters</noscript></div>
<h3>Tests</h3>
<div id="pcf" class="tests">
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail:has(b)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail:has(> a > b)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"></div><a><b></b></a></div>
<code> .fail:has(+ a > b)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"></div><a><b></b></a></div>
<code> .fail:has(:scope + a > b)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail:has(:is(.pass a > b))</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail:not(:has(c))</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b>I am a needle!!!</b></a></div></div>
<code> .fail:has-text(needle)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b>I am a needle!!!</b></a></div></div>
<code> .fail:has-text(/NEEDLE/i)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b>I am a needle!!!</b></a></div></div>
<code> .fail:not(:has-text(haystack))</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail:matches-css(position: absolute)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail:has(a:matches-css-before(opacity: 0))</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail:has(b:matches-css-after(opacity: 0))</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> .fail > a > b:nth-ancestor(2)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code>:xpath(.//b/../..)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna<b>aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</b>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</a></div></div>
<code> .fail:min-text-length(300)</code>
</div>
<div class="tile">
<div class="pass"><a><b></b></a><div class="fail"></div></div>
<code> .pass > a:has(b) + .fail</code>
</div>
<div class="tile">
<div class="pass"><a><b></b></a><div class="fail"><a><b></b></a></div></div>
<code> .pass > a:has(b) + .fail:has(b)</code>
</div>
<div class="tile watchattr1">
<div class="pass"><div class="pass"><a><b class="ok"></b></a></div></div>
<code> .pass:watch-attr(class) > .fail:has(b.notok)</code>
<script>
self.setTimeout(( ) =>
{
document.querySelector('.watchattr1 .pass > .pass').className = 'fail';
document.querySelector('.watchattr1 .pass > .fail b.ok').className = 'notok';
},
500
);
</script>
</div>
<div class="tile">
<div class="pass"><div class="fail"></div><a></a><b></b></div>
<code> .fail:has(+ a)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"></div><a><b></b></a></div>
<code> .fail:has(~ a:has(b))</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"></div><a><b></b></a></div>
<code> .fail:remove()</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> b:upward(2)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> b:upward(.fail)</code>
</div>
<div class="tile">
<div class="pass"><div class="fail"><a><b></b></a></div></div>
<code> b:upward(.fail):style(visibility: hidden !important)</code>
</div>
</div>
<script>
const hostname = self.location.hostname;
const filters = [];
const fragment = document.createDocumentFragment();
let i = 1;
for ( const tile of document.querySelectorAll('.tile') ) {
const id = `a${i}`;
tile.id = id;
const code = tile.querySelector('code');
const filter = `#pcf #${id}${code.textContent}`;
code.textContent = filter;
const div = document.createElement('div');
div.textContent = `${hostname}#?#${filter}`;
fragment.appendChild(div);
i += 1;
}
const parent = document.querySelector('.filters');
while ( parent.lastElementChild !== null ) {
parent.removeChild(parent.lastElementChild);
}
parent.appendChild(fragment);
</script>
</body>
</html>