mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 15:22:17 +02:00
N°8834 - Add compatibility with PHP 8.4 (#819)
* N°8834 - Add compatibility with PHP 8.4 * Rollback of scssphp/scssphp version upgrade due to compilation error
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# Emogrifier
|
||||
|
||||
[](https://github.com/MyIntervals/emogrifier/actions/)
|
||||
[](https://github.com/MyIntervals/emogrifier/actions/)
|
||||
[](https://packagist.org/packages/pelago/emogrifier)
|
||||
[](https://packagist.org/packages/pelago/emogrifier)
|
||||
[](https://packagist.org/packages/pelago/emogrifier)
|
||||
[](https://coveralls.io/github/MyIntervals/emogrifier?branch=main)
|
||||
|
||||
_n. e•mog•ri•fi•er [\ē-'mä-grƏ-,fī-Ər\] - a utility for changing completely the
|
||||
nature or appearance of HTML email, esp. in a particularly fantastic or bizarre
|
||||
@@ -31,6 +32,7 @@ into inline style attributes in your HTML code.
|
||||
- [Usage](#usage)
|
||||
- [Supported CSS selectors](#supported-css-selectors)
|
||||
- [Caveats](#caveats)
|
||||
- [Contributing](#contributing)
|
||||
- [Steps to release a new version](#steps-to-release-a-new-version)
|
||||
- [Maintainers](#maintainers)
|
||||
|
||||
@@ -157,6 +159,58 @@ $visualHtml = CssToAttributeConverter::fromDomDocument($domDocument)
|
||||
->convertCssToVisualAttributes()->render();
|
||||
```
|
||||
|
||||
### Evaluating CSS custom properties (variables)
|
||||
|
||||
The `CssVariableEvaluator` class can be used to apply the values of CSS
|
||||
variables defined in inline style attributes to inline style properties which
|
||||
use them.
|
||||
|
||||
For example, the following CSS defines and uses a custom property:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--text-color: green;
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--text-color);
|
||||
}
|
||||
```
|
||||
|
||||
After `CssInliner` has inlined that CSS on the (contrived) HTML
|
||||
`<html><body><p></p></body></html>`, it will look like this:
|
||||
|
||||
```html
|
||||
|
||||
<html style="--text-color: green;">
|
||||
<body>
|
||||
<p style="color: var(--text-color);">
|
||||
<p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The `CssVariableEvaluator` method `evaluateVariables` will apply the value of
|
||||
`--text-color` so that the paragraph `style` attribute becomes `color: green;`.
|
||||
|
||||
It can be used like this:
|
||||
|
||||
```php
|
||||
use Pelago\Emogrifier\HtmlProcessor\CssVariableEvaluator;
|
||||
|
||||
…
|
||||
|
||||
$evaluatedHtml = CssVariableEvaluator::fromHtml($html)
|
||||
->evaluateVariables()->render();
|
||||
```
|
||||
|
||||
You can also have the ` CssVariableEvaluator ` work on a `DOMDocument`:
|
||||
|
||||
```php
|
||||
$evaluatedHtml = CssVariableEvaluator::fromDomDocument($domDocument)
|
||||
->evaluateVariables()->render();
|
||||
```
|
||||
|
||||
### Removing redundant content and attributes from the HTML
|
||||
|
||||
The `HtmlPruner` class can reduce the size of the HTML by removing elements with
|
||||
@@ -174,11 +228,11 @@ $prunedHtml = HtmlPruner::fromHtml($html)->removeElementsWithDisplayNone()
|
||||
->removeRedundantClasses($classesToKeep)->render();
|
||||
```
|
||||
|
||||
The `removeRedundantClasses` method accepts a whitelist of names of classes that
|
||||
should be retained. If this is a post-processing step after inlining CSS, you
|
||||
can alternatively use `removeRedundantClassesAfterCssInlined`, passing it the
|
||||
`CssInliner` instance that has inlined the CSS (and having the `HtmlPruner` work
|
||||
on the `DOMDocument`). This will use information from the `CssInliner` to
|
||||
The `removeRedundantClasses` method accepts an allowlist of names of classes
|
||||
that should be retained. If this is a post-processing step after inlining CSS,
|
||||
you can alternatively use `removeRedundantClassesAfterCssInlined`, passing it
|
||||
the `CssInliner` instance that has inlined the CSS (and having the `HtmlPruner`
|
||||
work on the `DOMDocument`). This will use information from the `CssInliner` to
|
||||
determine which classes are still required (namely, those used in uninlinable
|
||||
rules that have been copied to a `<style>` element):
|
||||
|
||||
@@ -189,16 +243,16 @@ $prunedHtml = HtmlPruner::fromDomDocument($cssInliner->getDomDocument())
|
||||
```
|
||||
|
||||
The `removeElementsWithDisplayNone` method will not remove any elements which
|
||||
have the class `-emogrifier-keep`. So if, for example, there are elements which
|
||||
have the class `-emogrifier-keep`. So if, for example, there are elements which
|
||||
by default have `display: none` but are revealed by an `@media` rule, or which
|
||||
are intended as a preheader, you can add that class to those elements. The
|
||||
are intended as a preheader, you can add that class to those elements. The
|
||||
paragraph in this HTML snippet will not be removed even though it has
|
||||
`display: none` (which has presumably been applied by `CssInliner::inlineCss()`
|
||||
from a CSS rule `.preheader { display: none; }`):
|
||||
|
||||
```html
|
||||
<p class="preheader -emogrifier-keep" style="display: none;">
|
||||
Hello World!
|
||||
Hello World!
|
||||
</p>
|
||||
```
|
||||
|
||||
@@ -229,15 +283,32 @@ calling the `inlineCss` method:
|
||||
* `->removeAllowedMediaType(string $mediaName)` - You can use this
|
||||
method to remove media types that Emogrifier keeps.
|
||||
* `->addExcludedSelector(string $selector)` - Keeps elements from
|
||||
being affected by CSS inlining. Note that only elements matching the supplied
|
||||
being affected by CSS inlining. Note that only elements matching the supplied
|
||||
selector(s) will be excluded from CSS inlining, not necessarily their
|
||||
descendants. If you wish to exclude an entire subtree, you should provide
|
||||
descendants. If you wish to exclude an entire subtree, you should provide
|
||||
selector(s) which will match all elements in the subtree, for example by using
|
||||
the universal selector:
|
||||
```php
|
||||
$cssInliner->addExcludedSelector('.message-preview');
|
||||
$cssInliner->addExcludedSelector('.message-preview *');
|
||||
```
|
||||
* `->addExcludedCssSelector(string $selector)` - Contrary to
|
||||
`addExcludedSelector`, which excludes HTML nodes, this method excludes CSS
|
||||
selectors from being inlined. This is for example useful if you don't want
|
||||
your CSS reset rules to be inlined on each HTML node (e.g.
|
||||
`* { margin: 0; padding: 0; font-size: 100% }`).
|
||||
Note that these selectors must precisely match the selectors you wish to
|
||||
exclude.
|
||||
Meaning that excluding `.example` will not exclude `p .example`.
|
||||
```php
|
||||
$cssInliner->addExcludedCssSelector('*');
|
||||
$cssInliner->addExcludedCssSelector('form');
|
||||
```
|
||||
* `->removeExcludedCssSelector(string $selector)` - Removes previously added
|
||||
excluded selectors, if any.
|
||||
```php
|
||||
$cssInliner->removeExcludedCssSelector('form');
|
||||
```
|
||||
|
||||
### Migrating from the dropped `Emogrifier` class to the `CssInliner` class
|
||||
|
||||
@@ -286,11 +357,11 @@ $html = CssToAttributeConverter::fromDomDocument($domDocument)
|
||||
Emogrifier currently supports the following
|
||||
[CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors):
|
||||
|
||||
* [type](https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors)
|
||||
* [class](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors)
|
||||
* [ID](https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors)
|
||||
* [universal](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors)
|
||||
* [attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors):
|
||||
* [type](https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors)
|
||||
* [class](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors)
|
||||
* [ID](https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors)
|
||||
* [universal](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors)
|
||||
* [attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors):
|
||||
* presence
|
||||
* exact value match
|
||||
* value with `~` (one word within a whitespace-separated list of words)
|
||||
@@ -298,68 +369,71 @@ Emogrifier currently supports the following
|
||||
* value with `^` (prefix match)
|
||||
* value with `$` (suffix match)
|
||||
* value with `*` (substring match)
|
||||
* [adjacent](https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors)
|
||||
* [general sibling](https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator)
|
||||
* [child](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors)
|
||||
* [descendant](https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors)
|
||||
* [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes):
|
||||
* [empty](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty)
|
||||
* [first-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child)
|
||||
* [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type)
|
||||
(with a type, e.g. `p:first-of-type` but not `*:first-of-type`)
|
||||
* [last-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child)
|
||||
* [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type)
|
||||
(with a type)
|
||||
* [not()](https://developer.mozilla.org/en-US/docs/Web/CSS/:not)
|
||||
* [nth-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child)
|
||||
* [nth-last-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-child)
|
||||
* [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type)
|
||||
(with a type)
|
||||
* [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type)
|
||||
(with a type)
|
||||
* [only-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-child)
|
||||
* [only-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type)
|
||||
(with a type)
|
||||
* [adjacent](https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors)
|
||||
* [general sibling](https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator)
|
||||
* [child](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors)
|
||||
* [descendant](https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors)
|
||||
* [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes):
|
||||
* [empty](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty)
|
||||
* [first-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child)
|
||||
* [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type)
|
||||
(with a type, e.g. `p:first-of-type` but not `*:first-of-type`)
|
||||
* [last-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child)
|
||||
* [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type)
|
||||
(with a type)
|
||||
* [not()](https://developer.mozilla.org/en-US/docs/Web/CSS/:not)
|
||||
* [nth-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child)
|
||||
* [nth-last-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-child)
|
||||
* [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type)
|
||||
(with a type)
|
||||
* [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type)
|
||||
(with a type)
|
||||
* [only-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-child)
|
||||
* [only-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type)
|
||||
(with a type)
|
||||
* [root](https://developer.mozilla.org/en-US/docs/Web/CSS/:root)
|
||||
|
||||
The following selectors are not implemented yet:
|
||||
|
||||
* [case-insensitive attribute value](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors#case-insensitive)
|
||||
* static [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)
|
||||
not listed above as supported – rules involving them will nonetheless be
|
||||
preserved and copied to a `<style>` element in the HTML – including (but not
|
||||
necessarily limited to) the following:
|
||||
* [any-link](https://developer.mozilla.org/en-US/docs/Web/CSS/:any-link)
|
||||
* [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type)
|
||||
without a type
|
||||
* [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type)
|
||||
without a type
|
||||
* [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type)
|
||||
without a type
|
||||
* [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type)
|
||||
without a type
|
||||
* [only-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type)
|
||||
without a type
|
||||
* [optional](https://developer.mozilla.org/en-US/docs/Web/CSS/:optional)
|
||||
* [required](https://developer.mozilla.org/en-US/docs/Web/CSS/:required)
|
||||
* [case-insensitive attribute value](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors#case-insensitive)
|
||||
* static
|
||||
[pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)
|
||||
not listed above as supported – rules involving them will nonetheless be
|
||||
preserved and copied to a `<style>` element in the HTML – including (but not
|
||||
necessarily limited to) the following:
|
||||
* [any-link](https://developer.mozilla.org/en-US/docs/Web/CSS/:any-link)
|
||||
* [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type)
|
||||
without a type
|
||||
* [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type)
|
||||
without a type
|
||||
* [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type)
|
||||
without a type
|
||||
* [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type)
|
||||
without a type
|
||||
* [only-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type)
|
||||
without a type
|
||||
* [optional](https://developer.mozilla.org/en-US/docs/Web/CSS/:optional)
|
||||
* [required](https://developer.mozilla.org/en-US/docs/Web/CSS/:required)
|
||||
|
||||
Rules involving the following selectors cannot be applied as inline styles.
|
||||
They will, however, be preserved and copied to a `<style>` element in the HTML:
|
||||
|
||||
* dynamic [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)
|
||||
(such as `:hover`)
|
||||
* [pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)
|
||||
(such as `::after`)
|
||||
* dynamic
|
||||
[pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)
|
||||
(such as `:hover`)
|
||||
* [pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)
|
||||
(such as `::after`)
|
||||
|
||||
## Caveats
|
||||
|
||||
* Emogrifier requires the HTML and the CSS to be UTF-8. Encodings like
|
||||
ISO8859-1 or ISO8859-15 are not supported.
|
||||
* Emogrifier preserves all valuable `@media` rules. Media queries can be very
|
||||
useful in responsive email design. See
|
||||
* Emogrifier preserves all applicable `@media` rules. Media queries can be very
|
||||
useful in responsive email design. See
|
||||
[media query support](https://litmus.com/help/email-clients/media-query-support/).
|
||||
However, in order for them to be effective, you may need to add `!important`
|
||||
to some of the declarations within them so that they will override CSS styles
|
||||
that have been inlined. For example, with the following CSS, the `font-size`
|
||||
that have been inlined. For example, with the following CSS, the `font-size`
|
||||
declaration in the `@media` rule would not override the font size for `p`
|
||||
elements from the preceding rule after that has been inlined as
|
||||
`<p style="font-size: 16px;">` in the HTML, without the `!important` directive
|
||||
@@ -374,11 +448,15 @@ They will, however, be preserved and copied to a `<style>` element in the HTML:
|
||||
}
|
||||
}
|
||||
```
|
||||
Any CSS custom properties (variables) defined in `@media` rules cannot be
|
||||
applied to CSS property values that have been inlined and evaluated. However,
|
||||
`@media` rules using custom properties (with `var()`) would still be able to
|
||||
obtain their values (from the inlined definitions or `@media` rules) in email
|
||||
clients that support custom properties.
|
||||
* Emogrifier cannot inline CSS rules involving selectors with pseudo-elements
|
||||
(such as `::after`) or dynamic pseudo-classes (such as `:hover`) – it is
|
||||
impossible. However, such rules will be preserved and copied to a `<style>`
|
||||
element, as for `@media` rules. The same caveat about the possible need for
|
||||
the `!important` directive also applies with pseudo-classes.
|
||||
impossible. However, such rules will be preserved and copied to a `<style>`
|
||||
element, as for `@media` rules, with the same caveats applying.
|
||||
* Emogrifier will grab existing inline style attributes _and_ will
|
||||
grab `<style>` blocks from your HTML, but it will not grab CSS files
|
||||
referenced in `<link>` elements or `@import` rules (though it will leave them
|
||||
@@ -402,20 +480,32 @@ They will, however, be preserved and copied to a `<style>` element in the HTML:
|
||||
self-closing tags will lose their slash. To keep your HTML valid, it is
|
||||
recommended to use HTML5 instead of one of the XHTML variants.
|
||||
|
||||
## API and deprecation policy
|
||||
|
||||
Please have a look at our
|
||||
[API and deprecation policy](docs/API-and-deprecation-policy.md).
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions in the form of bug reports, feature requests, or pull requests are
|
||||
more than welcome. :pray: Please have a look at our
|
||||
[contribution guidelines](CONTRIBUTING.md) to learn more about how to
|
||||
contribute to Emogrifier.
|
||||
|
||||
## Steps to release a new version
|
||||
|
||||
1. In the [composer.json](composer.json), update the `branch-alias` entry to
|
||||
point to the release _after_ the upcoming release.
|
||||
2. In the [CHANGELOG.md](CHANGELOG.md), create a new section with subheadings
|
||||
1. In the [CHANGELOG.md](CHANGELOG.md), create a new section with subheadings
|
||||
for changes _after_ the upcoming release, set the version number for the
|
||||
upcoming release, and remove any empty sections.
|
||||
3. Create a pull request "Prepare release of version x.y.z" with those
|
||||
changes.
|
||||
4. Have the pull request reviewed and merged.
|
||||
5. Tag the new release.
|
||||
6. In the [Releases tab](https://github.com/MyIntervals/emogrifier/releases),
|
||||
1. Update the target milestone in the Dependabot configuration.
|
||||
1. Create a pull request "Prepare release of version x.y.z" with those changes.
|
||||
1. Have the pull request reviewed and merged.
|
||||
1. Tag the new release.
|
||||
1. In the [Releases tab](https://github.com/MyIntervals/emogrifier/releases),
|
||||
create a new release and copy the change log entries to the new release.
|
||||
7. Post about the new release on social media.
|
||||
1. Post about the new release on social media.
|
||||
|
||||
## Maintainers
|
||||
|
||||
|
||||
Reference in New Issue
Block a user