Procedural cosmetic filters

gwarser edited this page Jan 13, 2019 · 39 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. As a reminder, use procedural cosmetic filters only for when plain CSS selectors won't solve a case.

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

Procedural means javascript code is used to find DOM elements which must be hidden. A procedural cosmetic filter makes use of cosmetic filter operator, which will tell uBO how to find/filter DOM elements in order to find which DOM elements to target.

Important: Procedural filters must always be specific, i.e. prefixed with the hostname of the site(s) on which they are meant to apply. 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 prefix automatically with the hostname to ensure created cosmetic filters are specific.

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.

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-item1,2
    • strdef.world##div[style]:has(> a[href="http://www.streamdefence.com/index.php"]) - > forces a to be direct descendant of div

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 and only if the text needle is found inside the element subject.
  • 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)

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

subject:if-not(arg)

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: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 ensure compatibility with the existing CSS :not(...) pseudo-class.

subject:watch-attrs(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.

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.

Example:

  • vivrehome.pl##.js-popup-register:has(.js-title-default.is-hidden:watch-attributes(class)) blocks the "Register" overlay when first visiting the site, but yet allow the "Register" overlay when clicking "rejestracja".
  • ameshkov.github.io###testdiv:watch-attrs(id):has(p) demo, detects id changes.

subject:xpath(arg)

  • Description: Create a new set of elements by evaluating a XPath 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 use 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
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.