Skip to content

Procedural cosmetic filters

peace2000 edited this page Apr 3, 2022 · 95 revisions

Back to "Static filter syntax"


The concept of procedural cosmetic filtering was introduced with uBlock Origin (uBO) version 1.8.0.

The initial implementation was revised to allow chained/recursive use of the procedural operators with version 1.11.0+. There is no limit on the number of operators chained, or the number of recursion level, aside common sense. Though, chaining to native CSS selector after procedural one was not supported before 1.17.5rc1.

Only use procedural cosmetic filters when plain CSS selectors won't work.

Regular cosmetic filters are declarative, i.e., they are used as a selector in a CSS rule and handled by browsers through style tag elements.

Procedural means JavaScript code will find DOM elements that it must hide. A procedural cosmetic filter uses a filter operator that will tell uBO how to find/filter DOM elements to find which DOM elements to target.

Important:

  1. Procedural filters must always be specific, i.e. prefixed with the hostname of the site(s) on which they are meant to apply[exception]. If a procedural cosmetic filter is generic, i.e. meant to apply everywhere, it will be discarded by uBO. Examples: Good, because specific: example.com##body > div:has-text(Sponsored). Bad, because generic: ##body > div:has-text(Sponsored). The element picker always prefixes the filter automatically with the hostname to ensure created cosmetic filters are specific.

  2. Efficient procedural cosmetic filters (or any cosmetic filters really) are the ones which result in the smallest set of nodes to visit. The element picker input field will display the number of elements matching the current filter. The element picker will only consider the entered text up to the first line break, while leaving the rest as is. You can use this feature to break up your filter to find out the size of the resultset of the first part(s) of your filter: the smallest resultset the most efficient is your cosmetic filter.

  3. Concatenating multiple procedural selectors in one filter is not supported. example.com##p:has(img),div:has-text(advert) will not work as expected (#453).

Cosmetic filter operators

subject:has(arg)

Semantic changed in uBO 1.15.0 to resemble :if(...)

  • Description: Select element subject if and only if evaluating arg in the context of subject returns one or more elements.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter.
  • arg: A valid plain CSS selector or procedural cosmetic filter, which is evaluated in the context of the subject element.
  • Examples:
    • mobile.twitter.com##main [role="region"] > [role="grid"] > [role="rowgroup"] [role="row"]:has(div:last-of-type span:has-text(/^Promoted by/))
    • strikeout.me##body > div:has(img[alt="AdBlock Alert"])
    • yandex.ru##.serp-item:has(:scope .organic > .organic__subtitle > .label_color_yellow) - :scope forces .organic to match inside .serp-item (why :scope is needed, general :scope doc)
    • strdef.world##div[style]:has(> a[href="https://www.streamdefence.com/index.php"]) - > forces a to be direct descendant of div[style]

The :has(arg) operator is actually a planned pseudo-class in CSS4, but as of writing no browser supports it. Instead of waiting for browser vendors to provide support, uBO provides support for :has(arg) as a procedural operator.


subject:has-text(needle)

  • Description: Select element subject if the text needle is found inside the element subject or its children.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter.
  • needle: The literal text which must be found, or a literal regular expression. If using a literal regular expression, you can optionally use the i and/or m flags (version 1.15).
  • Examples:
    • example.com##body > div:last-of-type span:has-text(/^Promoted by/): starts with "Promoted by"
    • example.com##body > div:last-of-type span:has-text(/^Promoted by/i): starts with "Promoted by", ignore case
    • example.com##body > div:last-of-type span:has-text(Promoted by): contains "Promoted by" at any position

subject:if(arg)

Do not use.

Deprecated in favor of :has(...) in uBO 1.15.0


subject:if-not(arg)

Do not use.

Deprecated in favor of :not(:has(arg)) operator.


subject:matches-css(arg)

  • Description: Select element subject if and only if the result of evaluating arg is one or more elements.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter.
  • arg: A declaration in the form name: value, where name is a valid CSS style property, and value is the expected value for that style property. value can be a literal text or literal regular expression:
    • Literal text: the value will be matched exactly against the property value as returned by the browser's getComputedStyle method.
    • Literal regular expression: you can optionally use the i and/or m flags (version 1.15).
  • Examples:
    • extratorrent.*##body > div[class]:matches-css(position: absolute)
    • facet.wp.pl##div[class^="_"]:matches-css(background-image: /^url\("data:image/png;base64,/)

subject:matches-css-before(arg)

Same as :matches-css(...), except that the style will be looked-up for the :before pseudo-class of the subject element.


subject:matches-css-after(arg)

Same as :matches-css(...) except that the style will be looked-up for :after pseudo-class of the subject element.


subject:matches-path(arg)

  • Description: Allows to further narrow the specificity according to the path and query of the current document location.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter. Preferably should be used as first operator in a procedural cosmetic filter.
  • arg: Plain text to be found at any position in the path + query, or a literal regex against which the path + query is tested.
  • Examples:
    • example.com##:matches-path(/shop) p: Will hide all p elements when visiting https://example.com/shop/stuff, but not when visiting https://example.com/ or any other page on example.com which has no instance of /shop in the path part of the URL. To only match the main page but not any of the subpages, use: example.com##:matches-path(//$/) p

Introduced in uBO 1.37.3b13, feature request #1690.

This is a all-or-nothing passthrough operator, which on/off behavior is dictated by whether the argument match the path of the current location. The argument can be either plain text to be found at any position in the path, or a literal Regular Expression against which the path is tested.

Whereas cosmetic filters can be made specific to whole domain, the new :matches-path() operator allows to further narrow the specificity according to the path of the current document location.

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.


subject:min-text-length(n)

  • Description: DOM elements whose text length is greater than or equal to n will be selected.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter.
  • n: positive number, minimal text length of the subject DOM element.
  • Examples:
    • Regular expression based filter: quoka.de##^script:has-text(/[\w\W]{35000}/) can be rewritten as: quoka.de##^script:min-text-length(35000).

Introduced in uBO 1.20.1b2 As a result of internal discussion[1] with filter list maintainers. The original rationale for such procedural cosmetic operator is to be able to remove inline script elements according to a minimum text length using HTML filtering.

[1] https://github.com/orgs/uBlockOrigin/teams/ublock-filters-volunteers/discussions/194?from_comment=65


subject:not(arg)

  • Description: Select element subject if and only if the result of evaluating arg is exactly zero elements.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter.
  • arg: A procedural cosmetic filter, which is evaluated in the context of the subject element.

Introduced in uBO 1.17.5b9 to increase compatibility with AdGuard filter syntax.

Use to negate other procedural selectors. For example :not(:has(.foo)) will match if there are no descendant matching .foo.

Note that if arg is valid CSS selector, uBO will not consider the :not operator to be a procedural one, it will rather consider the operator as being part of a CSS selector. Thus this ensures compatibility with the existing CSS :not(...) pseudo-class.


subject:nth-ancestor(n)

Do not use.

Deprecated in favor of subject:upward(arg) in 1.25.3b0


subject:upward(arg)

  • Description: lookup the ancestor relative to the currently selected node.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter.
  • arg:
    • Positive number >= 1 and < 256, distance from the currently selected node.
    • A valid plain CSS selector.
  • Examples:
    • Existing filter: fastbay.org##.detLink:has-text(VPN):xpath(../../..) can be rewritten as fastbay.org##.detLink:has-text(VPN):upward(3)
    • gorhill.github.io###pcf #a19 b:upward(2)
    • gorhill.github.io###pcf #a20 b:upward(.fail)

Introduced in uBO 1.25.3b0. Evolution of :nth-ancestor(n) selector.


subject:watch-attrs(arg)

Do not use.

Deprecated in favor of subject:watch-attr(arg) in 1.20.1b3


subject:watch-attr(arg)

Experimental.

  • Description: Pass-through filter used to modify behavior of the procedural cosmetic filter engine by forcing re-evaluation when one or more attribute changes on the matching elements.
  • Chainable: Yes.
  • subject: Can be a plain CSS selector, or a procedural cosmetic filter.
  • arg: comma-separate list of attribute names. No argument means watch changes of any one attribute.

Example:

  • Test case to detect id changes using filter ameshkov.github.io###testdiv:watch-attr(id):has(p)

Introduced in uBO 1.17.5rc3

Solves uBlockOrigin/uBlock-issues#341 (comment) (overlay dialog used for two purposes, differ only by class name in child node).

By default hiding by procedural filters is reevaluated only when nodes in sub-tree are added or removed - uBO does not watch for attribute changes for performance reasons. This filter instructs uBO procedural filtering engine to watch for changes in specific attributes.


subject:xpath(arg)

  • Description: Create a new set of elements by evaluating an XPath expression using subject as the context node (optional) and arg as the expression.
  • Chainable: Yes.
  • subject: Optional. Can be a plain CSS selector, or a procedural cosmetic filter.
  • arg: A valid XPath expression.
  • Examples:
    • facebook.com##:xpath(//div[@id="stream_pagelet"]//div[starts-with(@id,"hyperfeed_story_id_")][.//h6//span/text()="People You May Know"])

The :xpath(...) operator is different than other operators. Whereas all other operators are used to filter down a resultset of elements, the :xpath(...) operator can be used both to create a new resultset or filter down an existing one. For this reason, subject is optional. For example, an :xpath(...) operator could be used to create a new resultset consisting of all ancestors elements of a subject element, something not otherwise possible with either plain CSS selectors or other procedural operators.

Clone this wiki locally