Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some issues with Adblock Procedural Filters / Feedback #42873

Open
1 of 6 tasks
ghost opened this issue Dec 12, 2024 · 12 comments
Open
1 of 6 tasks

Some issues with Adblock Procedural Filters / Feedback #42873

ghost opened this issue Dec 12, 2024 · 12 comments
Assignees
Labels
OS/Android Fixes related to Android browser functionality OS/Desktop

Comments

@ghost
Copy link

ghost commented Dec 12, 2024

Description

I have been testing the Procedural Filters in Brave for a while, while I stick to native CSS selectors unless has-text or upward is the only way to accomplish what I want to hide, I have notice some issues with them compared to uBlock in terms of being applied to some specific cases with heavy dynamic JS in place.

First issue

For example, in some extreme case like Twitch chat, the structure of the html tree will look like this:

<div class="Layout-sc-1xcs6mc-0 capulb chat-scrollable-area__message-container"
    data-test-selector="chat-scrollable-area__message-container">
    <div class="Layout-sc-1xcs6mc-0">
        <div class=" chat-line__message tw-relative" data-room-id="00000000" data-room="game"
            data-user-id="000000000" data-user="username">
            <div class="chat-line__message-highlight tw-absolute tw-border-radius-medium tw-top-0 tw-bottom-0 tw-right-0 tw-left-0"
                data-test-selector="chat-message-highlight"></div>
            <div class="chat-line__message-container tw-relative"><span class="chat-line__message--badges"><span
                        data-provider="twitch" data-badge="predictions" data-version="pink-2"
                        class="ffz-tooltip ffz-badge" data-tooltip-type="badge" data-badge-idx="0"></span><span
                        data-provider="twitch" data-badge="twitch-recap-2024" data-version="1"
                        class="ffz-tooltip ffz-badge" data-tooltip-type="badge" data-badge-idx="1"></span></span><span
                    class="chat-line__username notranslate " role="button" style="color: rgb(11, 149, 11);"><span
                        class="chat-author__display-name">USERNAME</span></span><span aria-hidden="true">: </span><span
                    class="message  "><span class="text-fragment" data-a-target="chat-message-text">FIRST</span></span></div>
            <div class="ffz--hover-actions ffz-action-data tw-mg-r-05" data-source="line">
                <div class="ffz-hover-action"><button class="ffz-tooltip ffz-mod-icon tw-c-text-alt-2"
                        data-tooltip-type="action" data-action="reply" data-options="{}">
                        <figure class="ffz-i-reply"></figure>
                    </button></div>
            </div>
        </div>
    </div>
    <div class="Layout-sc-1xcs6mc-0">
        <div class=" chat-line__message tw-relative" data-room-id="00000000" data-room="game"
            data-user-id="000000000" data-user="username">
            <div class="chat-line__message-highlight tw-absolute tw-border-radius-medium tw-top-0 tw-bottom-0 tw-right-0 tw-left-0"
                data-test-selector="chat-message-highlight"></div>
            <div class="chat-line__message-container tw-relative"><span class="chat-line__message--badges"><span
                        data-provider="twitch" data-badge="predictions" data-version="pink-2"
                        class="ffz-tooltip ffz-badge" data-tooltip-type="badge" data-badge-idx="0"></span><span
                        data-provider="twitch" data-badge="twitch-recap-2024" data-version="1"
                        class="ffz-tooltip ffz-badge" data-tooltip-type="badge" data-badge-idx="1"></span></span><span
                    class="chat-line__username notranslate " role="button" style="color: rgb(11, 149, 11);"><span
                        class="chat-author__display-name">USERNAME</span></span><span aria-hidden="true">: </span><span
                    class="message  "><span class="text-fragment" data-a-target="chat-message-text">SECOND MESSAGE</span></span></div>
            <div class="ffz--hover-actions ffz-action-data tw-mg-r-05" data-source="line">
                <div class="ffz-hover-action"><button class="ffz-tooltip ffz-mod-icon tw-c-text-alt-2"
                        data-tooltip-type="action" data-action="reply" data-options="{}">
                        <figure class="ffz-i-reply"></figure>
                    </button></div>
            </div>
        </div>
    </div>

Each message will be the <div class="Layout-sc-1xcs6mc-0">.

If I use a filter like this it will work fine:

twitch.tv##.chat-scrollable-area__message-container > div:has-text(/(FIRST|SECOND)/)

But if I use this one it will not work

twitch.tv##.chat-line__message:has-text(/(FIRST|SECOND)/)

My theory is that the procedural filtering will be applied because the <div class="Layout-sc-1xcs6mc-0"> element is being created, and makes it easier for the engine to work, and not using like something inside that element.

using .Layout-sc-1xcs6mc-0:has-text(/(FIRST|SECOND)/) is not possible for Twitch because many elements have that class, which means it will hide the whole thing.

And using works fine too.

twitch.tv##.Layout-sc-1xcs6mc-0:has(>.chat-line__message):has-text(/(FIRST|SECOND)/)

but using anything below .Layout-sc-1xcs6mc-0 in the will not work, only using that element will work great.

With uBlock you can use any element and it will work. like using .chat-line__message:has(.text-fragment):has-text(/(FIRST|SECOND)/)

As you can imagine uBlock doesn't have these issues.

Second issue:

This might be connected to the first one and how the DOM is read when elements are created with JS and all that.

But I noticed a similar issue by using :upward() which probably would have worked better depending on the 'final' selected element to hide, but it was to hide Channels based on their tags, I just use normal :has() for that, I just wanted to try it, but I remember the :upward worked in the main Top Channels directory, but then it didn't work for when I went to an individual game to see the live channels.

So using this will not work

twitch.tv##.tw-tower > div:has(.tw-tag):has-text(English)

But also the issue would be present if you use this:

twitch.tv##.tw-tag[data-a-target="English"]:upward(.tw-tower > div)

My theory in this case is that it has to do with the channels and how they get updated with the JS, so if you go to a game that doesn't have many channels, the tags will not get hidden because the DOM will not get updated with new channels, like it only starts kicking in when the DOM gets updated and fetching other channels when you scroll down or when enough channels get hidden that the channels page just fetch more channels by itself.

So Top Channels having thousands of channels will work fine, but not a game with only 12 live channels or less it will not hide the tags, unless there were more channels and then the DOM gets updated after a while. (hope it makes sense)

I mean, it is pretty situational but as you can imagine, there is no issues like this in uBlock, it always hide things without any issue on any selected node, the problem is while I am using the extreme case of a heavy JS website like twitch, many websites should have similar issues if their DOM has many things around.

Steps to reproduce

  1. Use twitch.tv##.chat-line__message:has-text(ANY WORD)

  2. Go to any Twitch channel, better a big one with tons of spam to have a lot to test from.

  3. No text gets hidden

  4. use twitch.tv##.tw-tower > div:has(.tw-tag):has-text(English) or twitch.tv##.tw-tag[data-a-target="English"]:upward(.tw-tower > div)

  5. Go to https://www.twitch.tv/directory/all

  6. it works

  7. go to any game with few live channels and nothing will get hidden

Actual result

Procedural Filtering is failing in some circumstances

Expected result

Elements should hide like uBlock does.

Reproduces how often

Easily reproduced

Desktop Brave version (brave://version info)

1.75.93 Chromium: 132.0.6834.46 (Official Build) nightly (64-bit)
Windows 11 Version 24H2 (Build 26100.2605)

Android device

  • Brand/model: Samsung
  • Android version: Android 14

Channel information

  • release (stable)
  • beta
  • nightly

Reproducibility

  • with Brave Shields disabled
  • with Brave Rewards disabled
  • in the latest version of Chrome

Miscellaneous information

No response

@ghost ghost added OS/Android Fixes related to Android browser functionality OS/Desktop labels Dec 12, 2024
@ghost
Copy link
Author

ghost commented Dec 13, 2024

Also, another feedback is that, there has to be a Procedural :has() and :not().

For example if you go to cgpress.org and use this filter

cgpress.org##.gdl-blog-medium:has(.category-abovetitle:has-text(Software):has(~.blog-content:has-text(/Autodesk|Maxon/)))

it will not work in Brave Adblocker becasue the 'invalid' selectors will not work with the native :has().

A :has(:has()) will not work, that's why the filters I gave have the :has():has-text() instead of adding them to the :has(), of course it makes more sense to write the filters with the native :has(), but for compatibility reasons the :has() and :not() as a Procedural is necessary.

What uBlock does is that it uses the native pseudo :has() when it is a simple :has() with no invalid selectors inside, and it will use the Procedural one when it reads it has other Procedurals.

Of course that rule in cgpress is not necessary, but it is to show what you can find in uBlock ruleset, like I quickly opened the uBlock lists and found this one:

facebook.com,facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion###watch_feed div:not([class]) > div:not([class]) div[class] span[class] > a span[aria-labelledby]:has(> span[style="display: flex;"] > span[class]:has-text(/^S$/)):has(> span[style="display: flex;"] > span[class]:has-text(/^p$/)):has(> span[style="display: flex;"] > span[class]:has-text(/^d$/)):upward(div:not([class]) > div:not([class])):style(height: 0 !important; overflow: hidden !important;)

as you can see the has-text() is inside the :has() twice in the rule making it incompatible. So, I guess it should be done as a compatibility thing, because I know 'we' can't ask uBlock to rewrite their filters to be compatible with Brave because they won't care.

with :not() should also be the same issue.

I didn't find many rules with procedural :not() like that only this one:

indiatimes.com,samayam.com##[onclick] p:matches-css-before(content:/Ad /):xpath(../..):not(p:has-text(/MAHA/i)):not(p:has-text(/Times/i))

But it has more than just a simple :not() with a :has-text inside.

But overall the feedback is how different in terms of blocking somethin is to say :has(:has(:has-text)) vs :has():has():has-text() or something like that.

@ghost
Copy link
Author

ghost commented Dec 13, 2024

Another feedback is since the introduction of Procedural Filters, Quora is impossible to browse, it loads and then becomes too slow to even scrolldown.

It has to do with the xpath rules, even if they are not in use, scrolling down became impossible and then the page will freeze, and if you disable most xpath, the page will work better but eventually it will freeze, so disabling all xpath rules https://github.com/uBlockOrigin/uAssets/blob/4a1d7a78fcb109c6c0525d0a72494af5422314f9/filters/filters.txt#L700-L702 and https://github.com/uBlockOrigin/uAssets/blob/4a1d7a78fcb109c6c0525d0a72494af5422314f9/filters/filters.txt#L705-L706 fix the issue and quora is responsive again without any issues.

Easy to test, go to and try to scroll down.
https://www.quora.com/What-are-your-thoughts-on-the-Brave-web-browser

So it is an issue when the page seems to load things even if rules will not match anything.

@ghost ghost changed the title Issues with some Procedural Filters / Feedback Some issues with Adblock Procedural Filters / Feedback Dec 13, 2024
@ghost
Copy link
Author

ghost commented Dec 21, 2024

I also compared the Procedural filters that are supported in Brave against the ones in uBlock to see if something is not compatible and noticed regex support is missing from:

  • :matches-css()

    cgpersia.com##.menu-item > a:matches-css(background-color: /rgb\(161/)`
    
  • :matches-css-before()

    cgpersia.com##.post:matches-css-before(display: /blo/)
    
  • :matches-css-after()

    cgpersia.com##.post:matches-css-after(clear: /bot/)
    

@ghost
Copy link
Author

ghost commented Dec 21, 2024

Also, I was testing :has-text(), I found an inconsistency in the way Brave does the :has-text() vs uBlock.

if you add

cgpersia.com##.menu-item:has-text(BLOG)

It will work in Brave, but not in uBlock

In uBlock it needs to be cgpersia.com##.menu-item:has-text(Blog)

Blog, is the way that the DOM shows the text, but it in the page it shows as BLOG because the element has the CSS property text-transform: uppercase;, and it seems Brave is using that for the :has-text(), and not the node's text. I don't think this is wrong, but be aware that there is a difference in the way Brave reads the text compared to uBlock to apply the procedural.

While it seems Brave is doing the correct thing by seeing any transformation, and taking into account because it is what the user would see, instead of opening the devtools and see 'why the text doesn't work', it seems like uBlock, ABP and Adguard do the same, they just see the text's node case and not the final rendered one in the page, so the consortium is that Brave is 'wrong'

I guess the difference by using the rendered text vs the one in the node is that and example like this:

https://codepen.io/kitasenjudesign/pen/zYgZgRm

with a rule like this, will not work as expected like uBlock does.

cdpn.io##.aa:has-text(HELLO)

in Codepen, you can do any code and just Reload Frame to test the adblocker, so if you Reload Frame, you will see Hello then if you quickly hover the word it will transform to HELLO and hide.
This will only work for like a second, because after that, the text will not hide if you hover on it, and the word is HELLO.

In uBlock that wouldn't happen because it will always be :has-text(Hello) doesn't matter how many transformations it has.

Or for example this: https://codepen.io/FritzAPI/pen/aJvaWq

cdpn.io##:is(p, b):has-text(THIS IS)

or

cdpn.io##:is(p, b):has-text(This is)

Look how different Brave and uBlock does it, uBlock will almost hide everything (This is) but that's good, because elements might have different CSSproperties affecting it, but it is easy to see why Brave way of doing things makes more sense, because it is only hiding what truly matches what the user can see, although when you select and copy the text might be This is or THIS IS, Brave is visually hiding the correct thing, because not everyone has access to Devtools, especially on mobile and since other Adblockers already said the text in the node is what matters before any CSS then, I don't know, compatibility is what should matter, although I think Brave is fine in this regard for the most part.


Also, I noticed Brave supports :contains(), but it only works in Brave if the rule has #?#, but uBlock allows the rules to have either #?# or ##

So for example, this doesn't work in Brave.

cgpersia.com##.menu-item:contains(BLOG)

Of course, I only few like 5 facebook rules with it https://github.com/uBlockOrigin/uAssets/blob/9b0ec459aa526e2a0db120af5a6a082b973e0ae3/filters/filters-mobile.txt#L47-L51 which have the #?# at the beginning, but I also searched them in the list.txt Brave uses/downloads and they are not even in the list, which means they got excluded from being imported to Brave users so I guess this part doesn't matter but I still noticed the small and unimportant difference.

@ghost
Copy link
Author

ghost commented Dec 22, 2024

seems like :matches-path is not being applied as uBlock would, first, as I found, you can only use it at the end of the rule.

But also, there are some issues, especially in heavy dynamic JS websites, where you have to refresh the page for thing to display correctly.

Example 1

sooplive.co.kr##body:matches-path(/directory) 

or

sooplive.co.kr##.side-conts:matches-path(/osu!) 

This will not work correctly because if you go from sooplive.co.kr to --> directory (탐색) or to Osu! and then press the back button to go back to sooplive.co.kr the content will stay hidden, it will only appear if you refresh the page.

twitch.tv##.tw-title:matches-path(pubg-battlegrounds)

This one in Twitch displays the issue even better. Go to https://www.twitch.tv/directory then go to Pubg, you will see Title of the game hides but also the top element in the .top-nav, if you get out of PUBG, the elements stay hidden.
If you go to another game, the title will show correctly. So it's like the Procedural filtering in Brave are only working if the elements in the DOM get updated, but it doesn't take into account elements that are arleady hidden, to unhide if the path doesn't match anymore.

For instance:

cgchannel.com##.site-logo-desktop:matches-path(/features)

This one in Cgchannel works correctly correctly. You go to cgchannel's main page, then to Featured and then go back, it will hide and unhide the Logo as expected, which is the normal behavior in uBlock in all pages, but in Brave is gambling to see if it works or not, requiring to refresh a page.

Example 2

Also the filter is not working fine, like... it will work depending on the page and the selector it has or how deep the element is in the DOM? I guess depends on complexity where Brave has trouble doing what uBlock does.

For example, this will not work:

  sooplive.co.kr##img:matches-path(/osu!)
  sooplive.co.kr##.thumb:matches-path(/category)

But this will work:

sooplive.co.kr##.side-conts:matches-path(/category)
cgchannel.com##img:matches-path(/features) 

Example 3

The rule is invalid if you use Korean:

sooplive.co.kr##.side-conts:matches-path(/PUBG%3A%20배틀그라운드)

It works fine if you use one of the few non-korean games:

sooplive.co.kr##.side-conts:matches-path(/osu!) 

Saying this, uBlock has no issues about this, also it seems using matches-path will hang the page and cause more issues.

Procedural Filtering needs proper testing in many websites, not just simple ones, while they work for the most part, seems like they are not working correctly unless the page is refreshed.

While they seem okay for the most part, I am the ones who test them in various websites from heavy to light and compare it to uBlock and it Procedural Filtering needs to be good in Brave like it is in uBlock, where it feels like it doesn't add anything to the page and just works.

@ghost
Copy link
Author

ghost commented Dec 23, 2024

Ok, seems like :matches-path() works, but if you place it at the end of the rule, not the beginning which is exactly what uBlock recommends, and how they write their rules, so Brave is actually not compatible with any :matches-path rule from uBlock lists, since they are all placing them at the beginning.

Of course, it should work either way, because you are allowed, just to avoid issues the beginning is better.
https://github.com/gorhill/ublock/wiki/Procedural-cosmetic-filters#subjectmatches-patharg

Typically this procedural operator is used as first operator in a procedural cosmetic filter, so as to ensure that no further matching work is performed should there be no match against the current path of the current document location

So this works:

cgchannel.com##img:matches-path(/features)

And this doesn't work

cgchannel.com##:matches-path(/features) img

I guess now it makes sense why it would hide the whole page and everything, if it is pretty much doing it on the html tag! my mistake I guess 👍

@antonok-edm antonok-edm self-assigned this Dec 23, 2024
@ghost
Copy link
Author

ghost commented Dec 24, 2024

Another issue I found testing the :has-text()

is that in the example: https://codepen.io/FritzAPI/pen/aJvaWq

cdpn.io##p, b:has-text(/.+/)

doesn't work in Brave, but works fine in uBlock. This is the reason I had to use :is(p, b):has-text()

This works fine:

cdpn.io##p, b:style(color: green)

because action operators or procedural filters are not like normal CSS selectors and there can only be one affecting comma list selector, so something like cdpn.io##p:has-text(/.+/), b:has-text(/.+/) in uBlock is invalid, although it is not marking the rule invalid in the editor

Of course in Brave the whole rule is rendered useless and not even using the b:has-text(/.+/), like if it was taken as a normal list selector, so it is like making the whole thing invalid even if it should by the :style() action operator logic.

guess is another thing to be tested.

I just tested the same scenario and yes.

  • This works fine in action operators

    cdpn.io##p, b:remove()
    cdpn.io##p, b:remove-class(uppercase)
    cdpn.io##p, b:remove-attr(class)
    
  • Fails as Procedural Filtering

    cdpn.io##p, b:matches-css(text-transform: capitalize):style(color: green)
    cdpn.io##p, b:matches-attr(class=/^/):style(color: green)
    cdpn.io##p, b:min-text-length(1):style(color: green)
    cdpn.io##p, b:upward(1):style(color: green)
    

So another missbehavior.

@ghost
Copy link
Author

ghost commented Dec 24, 2024

Opps, I forgot to mention this about :matches-attr() which I found out because of the test.

This is allowed in uBlock:

cdpn.io##:is(p, b):matches-attr(class):style(color: green)

But in Brave you have to specify the class, reason why I used regex (class=/^/) to do the same you would with uBlock with just (class).


Also, Brave Adblocker doesn't work in https://cdpn.io/FritzAPI/fullpage/aJvaWq which loads the content in the about:srcdoc, this is not about Procedurals only, no rule gets applied, but uBlock works fine, because I was trying to test cosmetics and test the performance with (devtools -> Performance) there and nothing happened.

so not even using cdpn.io##*:style(color: green !important;) works.

I tried to make it work, but it seems the only way to make it work is to opening devtools, Edit as HTML the srcdoc attribute with something, like adding a space and once you click out, the cosmetic or procedural will get applied, but it seems to be a probelm with brave with srcdoc attribute, because I also tested https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_iframe_srcdoc, and same issue, oh well, it's pretty rare.


To test the performance, I had to modify codepen example a little change, like adding a dot to the HTML and then View frame source will give a link like https://cdpn.io/cpe/boomboom/index.html?key=index.html-00000000-0000-0000 and then it will load as a normal page and not the iframed srcdoc.

Testing cdpn.io##:is(p, b):matches-attr(class=/^/):style(color: green) and then using the Performance tab with the screenshots as 'indidication' when the :matches-attr with the style took place I got this on every refresh:

Brave 795ms - 321ms - 314ms - 395ms - 312ms

uBlock 373ms - after any subsequent reload the Procedural filter is already applied, like if it got cached, while on Brave it always gets applied on every reload by the few milliseconds, sometimes hardly seen by the eye.

So there is a difference in there too but I guess nothing interestesting, in more complex pages the difference get more minimal since you can see the procedural being applied and in some cases faster in Brave.

@ghost
Copy link
Author

ghost commented Dec 24, 2024

Seems like I will have to stop testing Procedurals, because everytime I test something, I find some little tiny missbehavior.

It has to do with :matches-attr() https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters#subjectmatches-attrarg

Besides the value not being optional in Brave where it is optional in both uBlock and Adguard, as I described in one of my comments.

Now the issue is that the value as a string doesn't match the exact value, it will match it and anything beyond around or not around quotes.

So a rule liks this:

cgchannel.com##div:matches-attr(class="header")

is matching header but also header-top, header-menu and anything header...+... etc. when it should just match the class=header as per uBlock behavior.

The only way to workaround this is to use regex, as cgchannel.com##div:matches-attr(class=/^header$/) to make it exact.

This same thing happens with the attr though (less of an issue though), in the case of that rule, it will also match anything class+, for example: class, classiti, classitini etc, when it should be just class.

So regex should be use it to match non-exact values and attributes, not the other way around, which is wrong compared to what uBlock and Adguard does. Although Adguard even supports wildcard in the attr and value as shown by their documentation https://adguard.com/kb/general/ad-filtering/create-own-filters/#extended-css-matches-attr, something not even uBlock does, which should achive the same Brave is doing without regex, but since uBlock doesn't support it, I guess no uBlock rule has it, but still something Brave might consider to support because Adguard does it, and uBlock says "The supported syntax is exactly as per AdGuard's documentation", so they might do it someday in the future as well.

@ghost
Copy link
Author

ghost commented Jan 6, 2025

Another test where Brave fails to do what Procedural Filtering, what uBlock does without any issue.

instagram.com###loginForm:upward(19)
  1. go to https://www.instagram.com/bravebrowser/ in private mode or unlogged
  2. scrolldown
  3. you will eventually get the message to login and nothing will change in the page, because Procedural doesn't get applied anywhere.

@TEMP-ad
Copy link

TEMP-ad commented Jan 13, 2025

I was making some tests for brave/adblock-rust#415 (comment) I found couple issues, with regex now parsing \s \d and stuff like that correctly, :has-text()not working inside native :not().

But the biggest issue is that adding too many rules will break the rules, they are not parsed anymore in some cases or it becomes random when they are going to parse or not.

I got a nice test where I added these rules and went to https://abptestpages.org/en/filters/remove where all rules are compatible or https://abptestpages.org/en/filters/remove-extended where most are compatible, it would just be be random if the rules would be applied or not on refresh.

If you use a small set of rules they will work, but it seems Procedural Filtering and Action Operators just break like that when too many rules are applied to a page.

! <------------------- Remove ------------------->

!   https://abptestpages.org/en/filters/remove
abptestpages.org###remove-id:remove()
abptestpages.org##div[id='{{remove-id}}']:remove()
abptestpages.org##.remove-class:remove()
abptestpages.org##.testcase-area > .remove-descendant:remove()
abptestpages.org##.testcase-examplecontent + .remove-sibling:remove()
abptestpages.org##div[height="40"][width="40"]:remove()
abptestpages.org##div[href="http://testcase-attribute-remove.com/"]:remove()
abptestpages.org##div[style="width: 42px;"]:remove()
abptestpages.org##div[href^="http://testcase-startswith-remove.com/"]:remove()
abptestpages.org##div[style^="width: 43px;"]:remove()
abptestpages.org##div[style$="width: 44px;"]:remove()
abptestpages.org##div[style*="width: 45px;"]:remove()

! https://abptestpages.org/en/filters/remove-extended
abptestpages.org#?#div:matches-css(width: 46px):remove()
abptestpages.org#?#div:matches-css(width: 46px):remove()
abptestpages.org#?#div:-abp-has(>div>span.remove-abp-has):remove()
abptestpages.org#?#div:has(>div>span.remove-has):remove()
abptestpages.org#?#span:-abp-contains(remove-contains-target):remove()
abptestpages.org#?#span:has-text(remove-has-text):remove()
abptestpages.org#?#div:-abp-has(> div:matches-css(width: 47px)):remove()
abptestpages.org#?#div:matches-css(WiDtH: 48px):remove()
abptestpages.org#?#.remove-wildcard:matches-css(cursor:*):remove()
abptestpages.org#?#div:matches-css(/width: 13[1-5]px;/):remove()
abptestpages.org#?#div > div:-abp-contains(/remove-containsregex/):remove()
Recording.mp4

@TEMP-ad
Copy link

TEMP-ad commented Feb 7, 2025

https://gorhill.github.io/uBlock/tests/procedural-cosmetic-filters.html

gorhill.github.io#?##pcf #a7 .fail:has-text(needle)
gorhill.github.io#?##pcf #a8 .fail:has-text(/NEEDLE/i)

Don't work for whatever reason, even in simple pages, the Procedurals fail to work.

Probably
gorhill.github.io#?##pcf #a15 .fail:min-text-length(300) also affected by this, because they all seem to work if you apply it above the .pass / remove the .fail from the rule, and the min-text-length in the #pcf

So this does something:

gorhill.github.io#?##pcf #a7:has-text(needle)
gorhill.github.io#?##pcf #a8:has-text(/NEEDLE/i)
gorhill.github.io#?##pcf:min-text-length(300)

the gorhill.github.io#?##pcf #a9 .fail:not(:has-text(haystack)) doesn't work because :not() is not accepting the filter because it thinks it is invalid and it is dropping it, it probably needs a procedural :not() to work with Procedurals. Same with other filters that don't work, that's because they need their own Procedural :has() to work when some procedural is inside of it or another :has().

The others :nth-ancestor() and :watch-attr() I know are not available.

So a simpler example, where Procedurals like :has-text() don't get applied for whatever reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OS/Android Fixes related to Android browser functionality OS/Desktop
Projects
None yet
Development

No branches or pull requests

2 participants