Skip to content

Commit

Permalink
Adds support for the "body" element selector. Resolves #68
Browse files Browse the repository at this point in the history
  • Loading branch information
mmikkel committed Jun 10, 2024
1 parent 87f893e commit 5eebb34
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased
### Added
- Adds support for the body element selector (i.e. `'body'`), which can be used in conjunction with the child combinator to only select top-level nodes (e.g. `'body > p'`). [#68](https://github.com/mmikkel/Retcon-Craft/issues/68)

## 3.0.0 - 2024-03-28
### Added
- Added Craft 5.0 compatibility
Expand Down
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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 (e.g. `'img'`, `'div.foobar'`, `'p:first-child'` etc)
* 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)
Expand Down Expand Up @@ -107,14 +107,41 @@ public function init() {

### Selectors

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

In Retcon 2+, _almost all CSS selectors_ will work – see the [CssSelector](https://symfony.com/doc/3.3/components/css_selector.html) docs for further details on selectors.
_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 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

*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:

```twig
{# Make all top level <p> tags red #}
{% apply retconAttr('body > p', { style: 'color: red;' }) %}
<p>I wanna be red</p>
<div>
<p>I wanna be left alone</p>
</div>
{% endapply %}
```

Result:

```html
<p style="color: red;">I wanna be red</p>
<div>
<p>I wanna be left alone</p>
</div>
```

_The body element selector is supported for all filters._

### Methods

**[transform](https://github.com/mmikkel/Retcon-Craft/wiki/Transform)**
Expand Down
18 changes: 16 additions & 2 deletions src/library/RetconDom.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,23 @@ public function __construct($html)
*/
public function filter($selector, bool $asArray = true)
{
if (\is_array($selector)) {
$selector = \implode(',', $selector);
if (!is_array($selector)) {
$selector = explode(',', $selector);
}
$selector = array_reduce($selector, static function (array $carry, string $selector) {
$selector = trim($selector);
if (empty($selector)) {
return $carry;
}
if (str_starts_with($selector, 'body')) {
$selector = substr_replace($selector, 'html > retcon', 0, 4);
}
return [
...$carry,
$selector
];
}, []);
$selector = implode(',', $selector);
$nodes = $this->crawler->filter($selector);
if (!$asArray) {
return $nodes;
Expand Down

0 comments on commit 5eebb34

Please sign in to comment.