-
Notifications
You must be signed in to change notification settings - Fork 154
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
[CLEANUP] Refactor parseCssRules
: parse all CSS
#528
Conversation
Refactored `parseCssRules` so that it can now parse an entire CSS string, including @media rules. It now returns two arrays, in an array with the following keys: - "inlineable" => The inlineable rules that would have been previously returned; - "uninlineable" => The uninlineable rules, currently those from within @media rules. The original line number information from the CSS is available in both arrays, so the original ordering of all the rules (that will be required for MyIntervals#280) can be determined. A temporary method `combineCssMediaRules` has been added to recombine the @media rules back into a string of CSS as expected by `copyCssWithMediaToStyleNode`, pending refactoring of that method to instead accept a parsed rule array as its parameter. This does mean that, for now, the rules within each @media rule are parsed again.
As you'll see, the code in |
src/Emogrifier.php
Outdated
|
||
$cssRules = [ | ||
'inlineable' => [], | ||
'uninlineable' => [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a trailing comma also after the last element of a multiline array. This makes appending elements possible without having to modify the existing line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/Emogrifier.php
Outdated
]; | ||
$selectors = explode(',', $cssRule[1]); | ||
foreach ($selectors as $selector) { | ||
// don't process pseudo-elements and behavioral (dynamic) pseudo-classes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have this part (within the foreach loop of $selector, or most of it) in a separate private method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved the outer loop and regex matching into a separate method, so the loops are now very similar to how they were prior to this PR.
src/Emogrifier.php
Outdated
'uninlineable' => [] | ||
]; | ||
// keep track of where each rule appears in the file, since order is important | ||
$key = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we have this as the key in the corresponding loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently it needs to increment with the inner loop and carry on incrementing with each iteration of the outer loop. However, it should be possible to have one double-loop doing the regex matching and array_merge
-ing the results, then a second single loop processing the matches...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed as per comment above.
* | ||
* @return string | ||
*/ | ||
private function combineCssMediaRules(array $cssRules) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also please split up this method? It's far too long. This would also allow to get rid of the comments (if the methods are well-named).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is why I'd like to add a CssConcatenator
class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now using CssConcatenator
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, I propose you do this kind of changes to one file first, and then do it to the other file once the changes to one file are final.
As for the |
Oops, wrong button. Sorry, Reopening. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also please rebase to resolve the merge conflicts?
Would something like
not be possible within the Emogrifier class? I understand the need to support those not using autoload, but is it also a requirement to support grabbing just the |
No, that would be okay for me. |
I've added a |
These will be merged as a separate PR once the equivalent changes to Emogrifier.php have been agreed.
- Moved the regex matching part of `parseCssRules` (along with outer loop) into a separate private method; - Added trailing comma in multiline array definition; - Use `CssConcatenator` in `combineCssMediaRules`.
Now made the changes suggested in review. Also rebased and reverted changes to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good. Just needs the finishing polish!
src/Emogrifier.php
Outdated
|
||
$this->caches[static::CACHE_KEY_CSS][$cssKey] = $cssRules; | ||
} | ||
|
||
return $this->caches[static::CACHE_KEY_CSS][$cssKey]; | ||
} | ||
|
||
/** | ||
* Parse a string of CSS into the media query, selectors and declarations for each ruleset in order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Third person, please ("Parses") and a period at the end of sentence.
src/Emogrifier.php
Outdated
if ($cssRule['media'] === '') { | ||
$cssRules['inlineable'][] = $parsedCssRule; | ||
} else { | ||
$cssRules['uninlineable'][] = $parsedCssRule; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can shorten this to something like this:
$ruleType = ($cssRule['media'] === '') ? 'inlineable' : 'uninlineable';
$cssRules[$ruleType] = $parsedCssRule;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just done the last two polishing tasks myself. Thanks for this refactoring, @JakeQZ! ❤️
Refactored
parseCssRules
so that it can now parse an entire CSS string,including @media rules. It now returns two arrays, in an array with the
following keys:
rules.
The original line number information from the CSS is available in both arrays,
so the original ordering of all the rules (that will be required for #280) can
be determined.
A temporary method
combineCssMediaRules
has been added to recombine the @mediarules back into a string of CSS as expected by
copyCssWithMediaToStyleNode
,pending refactoring of that method to instead accept a parsed rule array as its
parameter. This does mean that, for now, the rules within each @media rule are
parsed again.