Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Add the ability to excluded CSS selectors from being inlined #1202

Closed

Conversation

nlemoine
Copy link
Contributor

@nlemoine nlemoine commented Jan 5, 2023

Exclude CSS selectors from the stylesheets being inlined. This might for example prevent global CSS rules with universal selector (*) to be inlined on each node.

@oliverklee oliverklee added this to the 8.0.0 milestone Jan 6, 2023
Copy link
Contributor

@oliverklee oliverklee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this contribution!

I've added some review comments.

And could you also please add a changelog entry (newest on top, and with a reference to the PR ID)? Thanks!

tests/Unit/CssInlinerTest.php Outdated Show resolved Hide resolved
src/CssInliner.php Outdated Show resolved Hide resolved
Copy link
Contributor

@JakeQZ JakeQZ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the neatness of this being an almost one-line change.

Some usage documentation for the feature should also be added to the README.md file.

Comment on lines 621 to 623
if (\count(\array_intersect($cssRule->getSelectors(), \array_keys($this->excludedCssSelectors)))) {
continue;
}
Copy link
Contributor

@JakeQZ JakeQZ Jan 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming the excluded selector list matches a full selector from a possibly comma-separated list, so .example will not exclude p.example or p .example. It would be good to confirm though that p .example would also exclude selectors written with varying whitespace (e.g. newline or multiple spaces), perhaps using a dataProvider for the currently-named addExcludedCssSelector test, so it can be run with a few different excluded selectors vs target selectors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I didn't normalized excluded CSS selectors, I assume developers are able to fill this with the right characters.

Copy link
Contributor

@JakeQZ JakeQZ Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume developers are able to fill this with the right characters.

My point was just to add a couple of extra tests to help define and isolate the precise behaviour of the new functionality. Thanks for continued engagement and persuing this. Your idea is good.

I'll look into your latest changes in the next few days, and expect @oliverklee will too.

Thanks again <3

Copy link
Contributor Author

@nlemoine nlemoine Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point was just to add a couple of extra tests to help define and isolate the precise behaviour of the new functionality

And it was totally legit, I wasn't sure it was meant to be handled on the user input (addExcludedCssSelector('.example p')), or on the selectors found in the provided CSS. I went for the provided CSS only since weird spaces/lines breaks or very unlikely passed in addExcludedCssSelector method. Let me know if you feel like it normalization should be applied on both.

Copy link
Contributor

@JakeQZ JakeQZ Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure it was meant to be handled on the user input (addExcludedCssSelector('.example p')), or on the selectors found in the provided CSS.

Not quite sure what you mean by this. Aren't they both user input? In context, the most usery of input will be the CSS. The parameter to the function, whilst also user input, will likely be more carefully chosen ;)

Edit: OK, got it. We are on the same wavelength. The user input is the CSS. The parameter to the function, whilst techically also user input, I think should be considered more as programmer input.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter to the function, whilst also user input, will likely be more carefully chosen ;)

I think w're both on the same side here :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if you feel like it normalization should be applied on both.

Sorry, I've only just fully read and understood your comment. Though that doesn't change anything, other than that my inrigue is now piqued as to whether a programmer error in the whitespacing department is covered too (it may well be).

@nlemoine
Copy link
Contributor Author

Thank you both for your reviews and comments. I pushed some changes that will address those issues.

@nlemoine nlemoine force-pushed the feature/excluded-css-selectors branch from c60ce2f to a4abcb2 Compare January 16, 2023 08:04
@JakeQZ
Copy link
Contributor

JakeQZ commented Sep 8, 2023

Sorry, we both seem to have overlooked this. Maybe GitHub never sent us the notification email (it is notoriously flaky).

I'll try and take a look in the next few days, and remember what it was about.

Copy link
Contributor

@JakeQZ JakeQZ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it's taken so long to get back to you.

We've been busy and somehow missed your post-review changes for months.

Hope you're still around and able to complete this change. It would be useful functionality.

You can use \s++ to efficiently match a sequence of one or more whitespace characters in a regular expression. Doing so would greatly simplify this change and avoid the need for an ALL_SPACES constant.

Comment on lines 639 to 640
$selector = \str_replace(["\r", "\n", "\t"], ' ', $selector);
$selector = \preg_replace('@[ ' . self::ALL_SPACES . ']+@mu', ' ', $selector);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely you can just use \s++ in the regular expression to match all whitespace sequences (without having to reinvent the wheel, so to speak) - ?

(Also, you don't need the m modifier as you are not matching . (any character) at all.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, regex are not my strong suit, I changed it. Let me know if you see any other issues.

@nlemoine nlemoine force-pushed the feature/excluded-css-selectors branch from a4abcb2 to ae1142f Compare September 8, 2023 08:23
@nlemoine
Copy link
Contributor Author

nlemoine commented Sep 8, 2023

Sorry it's taken so long to get back to you.

It's open source, no deadline or expectations ;)

@JakeQZ I just made the requested changes, let me know if it works for you.

Copy link
Contributor

@JakeQZ JakeQZ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a few minor issues that need to be addressed, but otherwise looks good.

Oh, and it will need to be rebased.

README.md Outdated
Comment on lines 242 to 251
* `->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');
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removeExcludedCssSelector should also be (briefly) documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 59 to 67
/**
* regular expression component to match all kinds of whitespace
*
* @see https://github.com/jolicode/JoliTypo/blob/8799bae6cda2280b319750d2fe764bfd8e8f6ba2/src/JoliTypo/Fixer.php#L37
*
* @var string
*/
private const ALL_SPACES = '\\xE2\\x80\\xAF|\\xC2\\xAD|\\xC2\\xA0|\\s';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't needed now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 639 to 640
$selector = \preg_replace('@\s++@u', ' ', $selector);
return $selector;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer not to modify the parameter, as this can cause confusion when debugging. Either a different local variable can be assigned and returned, or the result of preg_replace can simply be returned.

Also the \ should be escaped (as \\).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@oliverklee
Copy link
Contributor

@nlemoine Could you please rebase, resolve the merge conflicts and repush? Thanks!

@nlemoine nlemoine force-pushed the feature/excluded-css-selectors branch from 8274ffd to d59a873 Compare September 19, 2023 20:16
@nlemoine nlemoine closed this Sep 19, 2023
@nlemoine nlemoine force-pushed the feature/excluded-css-selectors branch from 007cb28 to 06785d1 Compare September 19, 2023 20:28
@nlemoine
Copy link
Contributor Author

@JakeQZ @oliverklee Sorry, I accidentally screwed up my rebase and this ended in my original PR to be closed. Please see #1236 for requested changes.

@JakeQZ
Copy link
Contributor

JakeQZ commented Sep 19, 2023

@JakeQZ @oliverklee Sorry, I accidentally screwed up my rebase and this ended in my original PR to be closed. Please see #1236 for requested changes.

No worries. Thanks for sorting it out. I guess you fell foul at step 7 of https://github.com/MyIntervals/emogrifier/blob/main/.github/CONTRIBUTING.md#rebasing, when git incorrectly suggests you do a pull (which does totally screw up the branch).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants