-
Notifications
You must be signed in to change notification settings - Fork 147
[BUGFIX] Do not escape characters that do not need escaping in CSS string #1444
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
base: main
Are you sure you want to change the base?
Conversation
JakeQZ
left a comment
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 it could be significantly slower looping through the string rather than using the built-in function (particularly as some strings may be base64-encoded images). Also this is reimplementing some of what addslashes() does.
Wouldn't it be simpler (and more efficient) to use addslashes() as before, then do a str_replace() to replace \' with ' or \" with " depending on the string quoting type?
PS. I agree with adding a separate method to do this. |
|
Updated according to your feedback. |
|
@8ctopus Thanks! Could you please rebase? |
2a66812 to
47970ab
Compare
|
done |
|
Thanks! GitHub is still showing merge conflicts. Could you please have a look? |
47970ab to
676dd8c
Compare
|
now should be good. |
|
Thanks! Now GitHub was able to run the CI jobs. The PHP-CS-Fixer job suggests some improvements. Could you please apply those to get the build green? Thanks! |
|
This time all tests are green, I also added a test to check that we do not escape when not necessary. |
|
Thanks! |
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 looks generally good now.
However, looking at the tests, there don't seem to be any covering that double-quotes within a single-quoted string are no longer escaped, e.g. if string quoting type is ', the quotes in "Hello World" don't need escaping and the result should be '"Hello World"'. Could you add a test for that?
I've suggested a couple of improvements, and a further correction to a comment that was previously wrong.
I'm not sure whether we have a project preference for string concatenation vs interpolation, so am asking @oliverklee for comment...
tests/fixtures/unicode.css
Outdated
| .test-7 { content: '\a' } /* Same as "\A" (Newline) */ | ||
| .test-8 { content: "\"\22" } /* Same as "\"\"" */ | ||
| .test-9 { content: "\"\27" } /* Same as ""\"\'"" */ | ||
| .test-9 { content: "\"\27" } /* Same as ""\"'"" */ |
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.
There seems to be an extra double-quote around the string in the comment, which was previously incorrect.
As we're changing this, we should probably fix that too:
| .test-9 { content: "\"\27" } /* Same as ""\"'"" */ | |
| .test-9 { content: "\"\27" } /* Same as "\"'" */ |
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
| $input = "data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none'" . | ||
| " xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd'" . | ||
| " d='M14.3145 2 3V11.9987H17.5687L18 8.20761H14.3145L14.32 6.31012C14.32 5.32134 14.4207" . | ||
| ' 4.79153 15.9426 4.79153H17.977V1H14.7223C10.8129 1 9.43687 2.83909 9.43687 ' . | ||
| " 5.93187V8.20804H7V11.9991H9.43687V23H14.3145Z' fill='black'/%3E%3C/svg%3E%0A"; |
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.
Autoformatting may apply some indentation, but I suggest leaving it as is for now. @oliverklee can run the autoformatter he uses as a post-PR (I think it's part of PHPStorm, which I don't have, and even if you have it, you may not have the same configuration set-up).
|
|
||
| $outputFormat = OutputFormat::createPretty(); | ||
|
|
||
| self::assertSame("\"{$input}\"", (new CSSString($input))->render($outputFormat)); |
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 are generally favouring using string contactenation rather than string interpolation, but I'm not sure of the rationale. All I can gather from some threads on StackOverflow is that it is a matter of personal preference. @oliverklee, are you able to expand on this?
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.
If you regex the project with /\{\$.*\}/ you will see that interpolation is used 19 times, 4 times being my newly added code.
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.
Yes, for new code, please use string concatenation instead of interpolation.
|
|
||
| $expected = str_replace("'", "\\'", $input); | ||
|
|
||
| self::assertSame("'{$expected}'", (new CSSString($input))->render($outputFormat)); |
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.
Ditto.
src/Value/CSSString.php
Outdated
| ]; | ||
| } | ||
|
|
||
| private function escape(string $str, string $quote): string |
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 would prefer a full word ($string) as the parameter name rather than an abbreviation ($str).
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
tests/Unit/Value/CSSStringTest.php
Outdated
| /** | ||
| * @test | ||
| */ | ||
| public function doNotEscapeCharactersThatDoNotNeedToBeEscaped(): void |
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 we have the test name in the present rather than imperative tense?
| public function doNotEscapeCharactersThatDoNotNeedToBeEscaped(): void | |
| public function doesNotEscapeCharactersThatDoNotNeedToBeEscaped(): void |
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
done |
For new/updated code, we prefer string concatenation over interpolation (without having a hard-and-fast rule, though). |
|
|
||
| private function escape(string $string, string $quote): string | ||
| { | ||
| $string = \addslashes($string); |
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.
Instead of first escaping unnecessarily and then undoing part of the work, I'd prefer to only escape what we need to escape in the first place, i.e., directly use str_replace and avoid addslashes.
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 suggested the current approach in my original review - see #1444 (review)
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.
Hm … couldn't we use just the str_replace and skip the addslashes (without using a 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.
… or use addcslashes and provide the characters to escape?
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.
We could probably use addcslashes to escape the backslash and quote.
The only other character that addslashes escapes is the null character (U+0000), which I don't think we need to worry about (there are no tests for this, it is highly unlikely to be used in the real world, and it was probably just an inconsequential side-effect of addslashes that that would be the behaviour - other control characters aren't handled, apart from newline which is currently str_replaced separately by the calling method).
Perhaps we could move the str_replace for newline to the new method as part of this change.
|
|
||
| $outputFormat = OutputFormat::createPretty(); | ||
|
|
||
| self::assertSame("\"{$input}\"", (new CSSString($input))->render($outputFormat)); |
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.
Yes, for new code, please use string concatenation instead of interpolation.
Add draft to attempt to resolve #1443
There are no specific tests yet, and there are improvements that can be made, I just want to get your approval before I polish things up.