PHPackages                             mmikkel/retcon - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. mmikkel/retcon

ActiveCraft-plugin[Templating &amp; Views](/categories/templating)

mmikkel/retcon
==============

Powerful Twig filters for mutating and querying HTML

3.2.2(5mo ago)79183.1k—4.5%9[2 issues](https://github.com/mmikkel/Retcon-Craft/issues)9MITPHPPHP ^8.2

Since Mar 5Pushed 5mo ago3 watchersCompare

[ Source](https://github.com/mmikkel/Retcon-Craft)[ Packagist](https://packagist.org/packages/mmikkel/retcon)[ RSS](/packages/mmikkel-retcon/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (5)Versions (51)Used By (9)

Retcon plugin for Craft CMS
===========================

[](#retcon-plugin-for-craft-cms)

Retcon is a tiny Craft CMS plugin adding a series of powerful Twig filters for modifying HTML content. **Here are some of the things Retcon can do:**

- Add attributes (e.g. `class="foobar"`, `style="color:red;"` or `data-foo`) using [CSS selectors](#selectors) (e.g. `'img'`, `'div.foobar'`, `'p:first-child'` etc)
- Append values to existing attributes
- Remove attributes completely (e.g. removing all inline `style` attributes)
- Transform inline images (it even uses [Imager](https://github.com/aelvan/Imager-Craft), if installed)
- Add srcset or lazyloading to inline images (again, using Imager if installed)
- Remove or unwrap DOM nodes
- Wrap DOM nodes (e.g. wrap all `` tags in a ``)
- Extract DOM nodes (e.g. remove everything except `` tags)
- Inject strings or HTML content
- Change tag names (e.g. change all occurrences of `` to ``, or change `div.foobar` to `p.foobar`)

...and much more!

Requirements
------------

[](#requirements)

This plugin requires Craft CMS 5.0+

How does it work?
-----------------

[](#how-does-it-work)

Retcon uses PHP's native [DOMDocument](http://php.net/manual/en/class.domdocument.php) class to parse and modify HTML. Additionally, [Masterminds' HTML5 library](https://github.com/Masterminds/html5-php) is used for HTML5 support, and Symfony's [DomCrawler](https://symfony.com/doc/3.3/components/dom_crawler.html) and [CssSelector](https://symfony.com/doc/3.3/components/css_selector.html) components are used to enable the powerful jQuery-like selector syntax.

Basic usage
-----------

[](#basic-usage)

Retcon exposes a series of different [methods](#methods) for modifying HTML. Most methods take a `selector` parameter (i.e. the selector(s) for the elements you want to modify, e.g. `'img'`, `'p'` or `'div.foobar'`), and some take additional parameters for further configuration.

Note that it doesn't matter if your HTML is from a WYSIWYG field (Redactor or CK Editor) or just a regular ol' string. If it's HTML, Retcon will eat it.

### Twig filters

[](#twig-filters)

All of Retcon's methods are exposed as Twig filters, which is how Retcon is primarily designed to be used. For example, if you wanted to add a classname `'image'` to all images in a Redactor field called `body`, here's how that'd look:

```
{{ entry.body | retconAttr('img', { class: 'image' }) }}
```

Note that for the Twig filters, the prefix `retcon` is added to the method name – i.e. the `attr` method becomes the `retconAttr` filter, the `transform` method becomes the `retconTransform` filter, etc.

#### Filter tag pair

[](#filter-tag-pair)

For use cases where your HTML is not in a field or variable, the *apply tag pair* syntax works nicely – the following example adds `rel="noopener noreferrer"` to all `` tags with `target="_blank"`:

```
{% apply retconAttr('a[target="_blank"]:not([rel])', { rel: 'noopener noreferrer' }) %}
    {# A whole bunch of HTML in here #}
    ....
{% endapply %}
```

#### Catch-all filter

[](#catch-all-filter)

Being Twig filters, *chaining* multiple Retcon methods will of course work:

```
{{ entry.body | retconChange('h1,h2,h4,h5,h6', 'h3') | retconAttr('h3', { class: 'heading') }}
```

Another option is to use the "catch-all" filter `retcon`, which takes a single array containing the names of the methods you want to run in sequence, and their parameters:

```
{{ entry.body | retcon([
    ['change', 'h1,h2,h4,h5,h6', 'h3'],
    ['attr', 'h3', { class: 'heading' }]
]) }}
```

### PHP

[](#php)

If you want to use Retcon in a Craft plugin or module, all methods are also available through the `mmikkel/retcon/Retcon::getInstance()->retcon` service (note that unlike the Twig filters, the `retcon` prefix is missing from the service method names – in other words, `retconAttr` is just `attr()`):

```
use mmikkel\retcon\Retcon;
echo Retcon::getInstance()->retcon->attr($entry->body, ['class' => 'image']);
```

For an actual use case example; here's how the `rel="noopener noreferrer"` example could look in a module (basically, the below code would add `rel="noopener noreferrer"` automatically to *all* `` tags in your templates (unless they've already got a `rel` attribute set, of course):

```
use mmikkel\retcon;

public function init() {

    Event::on(
        View::class,
        View::EVENT_AFTER_RENDER_TEMPLATE,
        function (TemplateEvent $event) {
            if (!Craft::$app->getRequest()->getIsSiteRequest()) {
                return;
            }

            if ($event->output && Craft::$app->getPlugins()->getPlugin('retcon')) {
                $event->output =
                    Retcon::getInstance()->retcon->attr(
                        $event->output,
                        'a[target="_blank"]:not([rel])', [
                            'rel' => 'noopener noreferrer',
                        ]);
            }

        }
    );
}
```

### Selectors

[](#selectors)

A "selector" in Retcon is the same thing as a selector in CSS; i.e. something like `'img'`, `'.foo'` or `h3 + p`.

*Retcon's selector support is close to full parity with CSS*, but not every selector will work. See the [CssSelector](https://symfony.com/doc/7.0/components/css_selector.html#limitations-of-the-cssselector-component) docs for further details.

#### Multiple selectors

[](#multiple-selectors)

Multiple selectors can be defined as a comma-separated string (i.e. `'p, span'`) or as an array (i.e. `['p', 'span']`).

#### Selecting top level nodes only

[](#selecting-top-level-nodes-only)

*New (Retcon 3.1.0+ only)*:

If you need to limit your selection to top-level nodes only, the `'body'` element selector can be used in conjunction with the child combinator (`'>'`). As an example:

```
{# Make all top level  tags red #}
{% apply retconAttr('body > p', { style: 'color: red;' }) %}
    I wanna be red

        I wanna be left alone

{% endapply %}
```

Result:

```
I wanna be red

    I wanna be left alone

```

*The body element selector is supported for all filters.*

### Methods

[](#methods)

**[transform](https://github.com/mmikkel/Retcon-Craft/wiki/Transform)**Apply a named or inline image transform to all images. **If installed, Retcon uses [Imager](https://github.com/aelvan/Imager-Craft) to apply the transform.****New:** Retcon also supports Imager's successor, [Imager X](https://github.com/spacecatninja/craft-imager-x).

**[srcset](https://github.com/mmikkel/Retcon-Craft/wiki/srcset)**Apply an array of named or inline image transform to all images, for simple srcset support. **If installed, Retcon uses [Imager](https://github.com/aelvan/Imager-Craft) to apply the transforms.**

**[lazy](https://github.com/mmikkel/Retcon-Craft/wiki/Lazy)**Replaces the *src* attribute of image tags with a transparent, base64 encoded SVG (retaining the original image's aspect ratio); putting the original src URL in a data-attribute

**[dimensions](https://github.com/mmikkel/Retcon-Craft/wiki/Dimensions)**Adds `width` and `height` attributes to image nodes, if they are missing (and the image referenced in the image nodes' `src` attribute is a local image file). **NEW**

**[autoAlt](https://github.com/mmikkel/Retcon-Craft/wiki/AutoAlt)**Adds Asset title or filename as alternative text for images missing `alt` tags

**[attr](https://github.com/mmikkel/Retcon-Craft/wiki/Attr)**Adds, replaces, appends to or removes a set of attributes and attribute values – e.g. `class`. **Can be used to remove inline styles.**

**[renameAttr](https://github.com/mmikkel/Retcon-Craft/wiki/renameAttr)**Renames existing attributes for matching selectors, retaining the attribute values

**[wrap](https://github.com/mmikkel/Retcon-Craft/wiki/Wrap)**Wraps stuff in other stuff (e.g. put all `` tags in `` tags)

**[unwrap](https://github.com/mmikkel/Retcon-Craft/wiki/Unwrap)**Removes parent node for matching elements; retaining their content

**[remove](https://github.com/mmikkel/Retcon-Craft/wiki/Remove)**Removes all elements matching the given selector(s)

**[removeEmpty](https://github.com/mmikkel/Retcon-Craft/wiki/RemoveEmpty)**Removes all empty elements. **NEW**

**[only](https://github.com/mmikkel/Retcon-Craft/wiki/Only)**Removes everything except the elements matching the given selector(s)

**[change](https://github.com/mmikkel/Retcon-Craft/wiki/Change)**Changes tag type for all elements matching the given selector(s). Can also be used to remove tags completely, but retaining their content.

**[inject](https://github.com/mmikkel/Retcon-Craft/wiki/Inject)**Inject strings or HTML

### Disclaimer &amp; support

[](#disclaimer--support)

Retcon is provided free of charge. The author is not responsible for data loss or any other problems resulting from the use of this plugin. Please see [the Wiki page](https://github.com/mmikkel/Retcon-Craft/wiki) for documentation and examples. and report any bugs, feature requests or other issues [here](https://github.com/mmikkel/Retcon-Craft). As Retcon is a hobby project, no promises are made regarding response time, feature implementations or bug amendments.

###  Health Score

62

—

FairBetter than 99% of packages

Maintenance71

Regular maintenance activity

Popularity46

Moderate usage in the ecosystem

Community23

Small or concentrated contributor base

Maturity89

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 98.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~60 days

Recently: every ~131 days

Total

48

Last Release

160d ago

Major Versions

1.0.1 → 2.0.02018-07-10

2.7.5 → 3.0.0-beta.12024-02-14

2.8.0 → 3.2.02024-06-28

2.8.2 → 3.2.12024-10-21

PHP version history (2 changes)2.4.0PHP ^7.2.5|^8.0

3.0.0-beta.1PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/298510?v=4)[M. Mikkel Rummelhoff](/maintainers/mmikkel)[@mmikkel](https://github.com/mmikkel)

---

Top Contributors

[![mmikkel](https://avatars.githubusercontent.com/u/298510?v=4)](https://github.com/mmikkel "mmikkel (153 commits)")[![aelvan](https://avatars.githubusercontent.com/u/2675644?v=4)](https://github.com/aelvan "aelvan (3 commits)")

---

Tags

cmsCraftcraftcmscraft-pluginretcon

### Embed Badge

![Health badge](/badges/mmikkel-retcon/health.svg)

```
[![Health](https://phpackages.com/badges/mmikkel-retcon/health.svg)](https://phpackages.com/packages/mmikkel-retcon)
```

###  Alternatives

[lewisjenkins/craft-dynamic-fields

Populate Craft fields with dynamic data using the power of Twig.

14667.0k](/packages/lewisjenkins-craft-dynamic-fields)[nystudio107/craft-minify

A simple plugin that allows you to minify blocks of HTML, CSS, and JS inline in Craft CMS templates.

37461.2k29](/packages/nystudio107-craft-minify)[jalendport/craft-preparse

A fieldtype that parses Twig when an element is saved and saves the result as plain text.

1086.4k](/packages/jalendport-craft-preparse)[craftpulse/craft-colour-swatches

Let clients choose from a predefined set of colours and utilise associated colour codes and class names in your templates.

3530.8k2](/packages/craftpulse-craft-colour-swatches)[verbb/footnotes

Adds a footnotes feature to CKEditor fields and Twig templates.

213.3k](/packages/verbb-footnotes)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
