-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fix: WP_Font_Face: Font names that contain single quotes are not wrapped in double quotes #8982
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: trunk
Are you sure you want to change the base?
Fix: WP_Font_Face: Font names that contain single quotes are not wrapped in double quotes #8982
Conversation
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN:
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Thanks for the PR! I'm thinking it might be better to expose the That way, it should be available in the form of |
To me, this seems better choice as well without duplication/repeatations. |
Thanks for the update! I think we can commit this PR once the PHP lint errors are fixed. |
It seems good to always process the provided font family name, however I wonder whether we should improve on I believe there are a number of edge cases that are unhandled here. Most of these are edge cases and not likely to appear in popular font names, however it seems ideal if the system behaves well under any conditions. For example, what happens if the string contains This section of the CSS standard is interesting and relevant, in particular the notes:
I'd like to consider always using the quoted form of the font family name. This way they are handeled as CSS strings, and handling a few characters should ensure that font names are correctly represented in the resulting CSS. A quoted form of the name seems ideal where some escaping inside the quoted CSS string would be necessary, namely:
I'm not familiar with the fonts API so this may be problematic in some ways I'm unaware of, but from the CSS perspective this should be more robust. |
My comment is not intended to block this PR which seems to be an incremental improvement. |
@sirreal Thanks for the feedback!
I think this is a nice suggestion. This method was previously private, it should be safe to change the method name.
This is true. There are also no unit tests and they will need to be added, but I think those can be addressed in a follow-up. |
Yes, there’s zero downside to being more defensive here.
I agree, this is a good suggestion. I've gone ahead and added some edge cases as mentioned above by @sirreal and renamed the method to normalize_quoted_font_family_name since it better reflects what the function is doing now. |
@iamsandeepdahiya Thanks for the update. If we change the logic of the method itself, I feel like we need unit testing to prevent regressions. This method is very hard to test manually. |
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.
Thanks for the additional changes @iamsandeepdahiya.
I'm concerned that making these additional changes is going to be much more involved. Ultimately, it seems good to do, but it may be a good idea to land a simple fix like you initially proposed in this PR. My recommendation would be to land the simpler fix and then create a new PR with the additional improvements.
Specifically, I agree with @t-hamano, this functionality absolutely needs testing and that's going to be a big addition to this PR. I've flagged several potential issues in this review that suggest some good test cases.
@@ -29,12 +29,15 @@ class WP_Font_Utils { | |||
* @param string $item A font family name. | |||
* @return string The font family name with surrounding quotes, if necessary. | |||
*/ | |||
private static function maybe_add_quotes( $item ) { | |||
public static function normalize_quoted_font_family_name( $item ) { |
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 know I suggested this name, but considering again I'd prefer not to include "quoted" here, that seems like an implementation detail of normalization and this function could choose not to use quotes.
This seems preferable, indicating that it's a font family name for CSS which has different encoding rules than other contexts:
public static function normalize_quoted_font_family_name( $item ) { | |
public static function normalize_css_font_family_name( $item ) { |
The description of this function is now incorrect and needs to be updated about its behavior.
// Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens). | ||
$regex = '/^(?!generic\([a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/'; | ||
$item = trim( $item ); | ||
if ( preg_match( $regex, $item ) ) { | ||
$item = trim( $item, "\"'" ); | ||
$item = str_replace( [ "\r\n", "\r", "\n" ], '\\A', $item ); |
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.
Good catch on normalizing the newlines and replacing them.
However the replacement may be problematic because it could be followed by hex digits which would then be interpreted as part of the escape sequence. The safest thing to do here is to include a trailing space character to terminate the escape sequence:
$item = str_replace( [ "\r\n", "\r", "\n" ], '\\A', $item ); | |
$item = str_replace( [ "\r\n", "\r", "\n" ], '\\A ', $item ); |
// Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens). | ||
$regex = '/^(?!generic\([a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/'; | ||
$item = trim( $item ); | ||
if ( preg_match( $regex, $item ) ) { | ||
$item = trim( $item, "\"'" ); | ||
$item = str_replace( [ "\r\n", "\r", "\n" ], '\\A', $item ); | ||
$item = str_replace( '\\', '\\\\', $item ); |
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.
The order of these replacements is very important. The \
replacement must happen first or we risk replacing the \
characters that have been inserted. We don't want to replace a newline character with \A
only to later replace that with \\A
.
// Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens). | ||
$regex = '/^(?!generic\([a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/'; | ||
$item = trim( $item ); | ||
if ( preg_match( $regex, $item ) ) { | ||
$item = trim( $item, "\"'" ); | ||
$item = str_replace( [ "\r\n", "\r", "\n" ], '\\A', $item ); | ||
$item = str_replace( '\\', '\\\\', $item ); | ||
$item = str_replace( '"', '\\"', $item ); |
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 decide to pick a quote character that avoids the need to escape by checking for '
and "
characters inside the string. That adds some slight complication here but is potentially nicer in the result.
I agree with this suggestion. I think it would be better to make only minimal changes here and address the logic changes and adding unit tests in a follow-up. The feedback left by @sirreal will be useful when creating a follow-up PR. Looking at the feedback, it seems that there are many edge cases that need to be tested carefully 😅 |
This reverts commit 9f29537.
I have reverted the last commit as discussed and the recent changes have been undone. The branch is now back to the previous state. Please let me know if any further adjustments are needed. ✅ |
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.
@iamsandeepdahiya Thanks for the update!
- Can you delete this white space?
- Personally, I think it's okay to include the method name change in this PR: from
maybe_add_quotes
tonormalize_css_font_family_name
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.
LGTM 👍
Please don't wait for additional review from me, I'm not familiar with the font system and am satisfied with @t-hamano's approval. |
I have created a patch for the following Trac ticket:
Trac ticket: https://core.trac.wordpress.org/ticket/63568
Details for the bug reproduction can be found here.
In this patch, the quotes are added by using the logic of
maybe_add_quotes
method in thebuild_font_face_css
function.The comparison of input and output before the patch and after the patch is:

Here is the before patch (bug reproduction video):-
https://github.com/user-attachments/assets/d93736c0-d410-46da-84fa-38900f843471
After patch (test report video):-
https://github.com/user-attachments/assets/4a610657-5c09-4de1-92a2-f161c9910812
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.