Change record status: 
Introduced in branch: 


We needed to change the Filter API to accommodate three things:

  1. The ability to #attach assets. This is seen commonly, in many filters in Drupal 5/6/7 contrib. Until today, you had no choice but to load CSS associated with a text filter on all pages.
  2. The ability to associate #cache contexts. This is a new need in Drupal 8. This allows you to do language-specific filtering, you'd just specify that the filtering varies by the 'language' cache context. Another example: currency-specific filtering using a 'currency' cache context.
  3. The ability to associate #cache tags. This is a new need in Drupal 8. When a text filter uses information that's stored in a "product" entity, for example, then the cached result must be invalidated whenever the product entity changes. This is easily achieved using cache tags, but filters didn't allow cache tags to be associated, until today.
  4. The ability to associate placeholders (#lazy_builder callbacks). Previously, filters were allowed to declare themselves uncacheable. Which meant that the filtering had to occur on every single page load, i.e. it broke all caching. Now that Drupal 8 is caching as many things as possible, that's no longer acceptable (because it effectively breaks render caching of entities also!). Plus, it was a huge performance problem in Drupal 7. For those parts that truly are uncacheable, one should use placeholders with accompanying #lazy_builder callbacks.


  1. A new FilterProcessResult class has been added, which allows attachments (assets + placeholders) and cacheability metadata (cache contexts, tags and max-age) to be associated.
  2. A new '#type' = 'processed_text' element type has been added. This uses the #text, #format and #langcode properties, for the text to be processed, the text format to apply and the langcode to processed it in, respectively.
  3. check_markup() is refactored to use '#type' = 'processed_text'. You should only use it in scenarios where you're not rendering HTML (e.g. a plain-text e-mail whose contents are processed text).
  4. All caching is removed from check_markup(), FilterInterface::preprocess() and FilterInterface::process(). (Because we have entity render caching now.)
  5. Removed a filter's ability to declare itself uncacheable. (Because we need to add placeholder support anyway, which allows you to be as granular as you like with uncacheable things, instead of preventing the entire processed text from being cached, and by extension containing entity and even the page.) Hence also removed filter_format_allowcache(), which had no more use.
  6. filter_caption now attaches its asset instead of loading it on all pages.
  7. Images added when using a text editor (e.g. CKEditor) have a data-editor-file-uuid attribute is set on the <img /> tag. This is how the Text Editor module is capable of correctly tracking in which nodes a file is used without that file being referenced via a file field, but being referenced through a processed text field instead.
    However, the cache tags of those image files were not yet being associated, so if something changed about these images, then that wouldn't be reflected anywhere immediately. A new EditorFileReference filter was added (with test coverage) to fix that.
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other updates done