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

Style Engine: Include 6.1 CSS filter, ensure style engine can output CSS functions like clamp #43004

Merged
merged 4 commits into from
Aug 9, 2022

Conversation

andrewserong
Copy link
Contributor

@andrewserong andrewserong commented Aug 5, 2022

What?

Fixes #42948

A potential alternative to #42968, exploring @Mamaduka's idea from #42968 (comment)

The idea here is that to resolve the issue of the style engine stripping values that use clamp() we can roll out the proposed updated regex for filtering values from the Trac ticket: https://core.trac.wordpress.org/ticket/55966.

Why?

The idea behind this PR is that the style engine shouldn't have to be doing too much of its own work to determine whether or not a rule is valid. I've added an additional function just in case we need to add further special handling down the track (for display, perhaps?), but for now we're still deferring to safecss_filter_attr.

How?

Testing Instructions

  1. Follow the reproduction steps in 1.3.9: clamp() is no longer recognized in “contentSize” or “wideSize” in theme.json #42948 and check that this PR allows the expected clamp() values
  2. Double-check that the copied over regex from https://core.trac.wordpress.org/ticket/55966 looks acceptable and comparable to the core implementation. To review this section, it might be helpful to compare to the existing core implementation over in: https://github.com/WordPress/wordpress-develop/blob/HEAD/src/wp-includes/kses.php#L2469
  3. Since this filter applies for all CSS filtering in Gutenberg, rather than just the style engine, confidence check that the change looks acceptable

@andrewserong andrewserong self-assigned this Aug 5, 2022
@andrewserong andrewserong added [Package] Style Engine /packages/style-engine [Type] Bug An existing feature does not function as intended labels Aug 5, 2022
// Allow a controlled set of `display` values.
if (
'display' === $property &&
in_array( $value, array( 'block', 'inline', 'inline-block', 'flex', 'inline-flex', 'grid', 'inline-grid' ), true )
Copy link
Member

Choose a reason for hiding this comment

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

Any reason why we couldn't add a $attrs[] = 'display'; entry to gutenberg_safe_style_attrs_6_1() in lib/compat/wordpress-6.1/blocks.php?

If we're not confident that a core patch for display will be in before 6.1 maybe add another safe_style_css filter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Over in WordPress/wordpress-develop#2928 (comment) we discussed the issue with display: none, in that we still want that value to be excluded, but to allow the remaining display values.

Currently in the Layout output of the Theme JSON class we have special handling for display here: https://github.com/WordPress/gutenberg/blob/trunk/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php#L1370

For the purposes of this PR, we could always remove the display handling, since we're not yet using the style engine for global styles, and defer the issue to later.

I think the question comes down to — should WordPress in general allow display with a set number of values, or is it that the Layout / theme.json might need it for a particular use case, but it shouldn't otherwise be more broadly exposed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All that said, in principle, I really like the idea that the style engine could "just work" and outsource CSS validation / sanitization to core functions and filters 🤔

Copy link
Member

@ramonjd ramonjd Aug 5, 2022

Choose a reason for hiding this comment

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

we discussed the issue with display: none, in that we still want that value to be excluded

I've left a comment over in that discussion. It would be good to validate that claim.

For the purposes of this PR, we could always remove the display handling, since we're not yet using the style engine for global styles, and defer the issue to later.

I always say "if in doubt, chuck it out" 😄

If we're not using it, is there any benefit to having it right now or for 6.1?

Or could this be resolved in the core patch?

I think the question comes down to — should WordPress in general allow display with a set number of values, or is it that the Layout / theme.json might need it for a particular use case, but it shouldn't otherwise be more broadly exposed.

Yeah for sure. Do you think it'd be helpful to ask a wider audience before committing here?

Copy link
Contributor Author

@andrewserong andrewserong Aug 5, 2022

Choose a reason for hiding this comment

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

I always say "if in doubt, chuck it out" 😄

If we're not using it, is there any benefit to having it right now or for 6.1?

Great point. For the scope of this PR, we only need to resolve the issue reported in #42948, as display is still handled in the Theme JSON class. Let's avoid dealing with display in this PR until we need to refactor the centralised Layout output.

I've removed the display handling in: b7261d8

@ramonjd
Copy link
Member

ramonjd commented Aug 5, 2022

This is looking good to me.

I think having filters doing the temporary workarounds is a nice way to be explicit about things, and probably easier to remove/extract during migrations.

I just had a question as to whether we could move the checks for display to the gutenberg_safe_style_attrs_6_1 filter to make it even cleaner.

Also, using the code that'll be closer to what core will have.

I tested by running some of the target properties and values through:

max-width: clamp(36.00rem, calc(32.00rem + 10.00vw), 40.00rem);
max-width: min(calc(3 * 10.00vw));
max-width: max(calc(3 * 10.00vw));
max-width: minmax(20px, auto) 1fr 1fr);
.wp-testing-display-properties-block {
	display: block;
}
.wp-testing-display-properties-inline {
	display: inline;
}
.wp-testing-display-properties-inline-block {
	display: inline-block;
}
.wp-testing-display-properties-flex {
	display: flex;
}
.wp-testing-display-properties-inline-flex {
	display: inline-flex;
}
.wp-testing-display-properties-grid {
	display: grid;
}
.wp-testing-display-properties-inline-grid {
	display: inline-grid;
}

Copy link
Member

@ramonjd ramonjd left a comment

Choose a reason for hiding this comment

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

Can confirm that display is not longer supported.

Looks like a good approach to me. Keeps the style engine clean, and has a clear path to migration.

Thanks for the tests.

@@ -130,7 +146,7 @@ public function get_declarations_string( $should_prettify = false, $indent_count

foreach ( $declarations_array as $property => $value ) {
$spacer = $should_prettify ? ' ' : '';
$filtered_declaration = esc_html( safecss_filter_attr( "{$property}:{$spacer}{$value}" ) );
$filtered_declaration = esc_html( static::filter_declaration( $property, $value, $spacer ) );
Copy link
Member

Choose a reason for hiding this comment

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

For a follow up: could we abstract all sanitization and move the esc_html too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question — depending on the output context, I wasn't too sure if esc_html() is always desired so left it inline for the time being. Happy to play around with it in a follow-up if this PR looks viable (I'd like to better understand when and why we need to escape the html characters, too — I can imagine some circumstances, but I don't feel I fully get it yet 🙂).

Copy link
Member

Choose a reason for hiding this comment

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

I think this is worth investigating separately. The safecss_filter_attr is probably enough here.

Looking at other usages of safecss_filter_attr in the plugin, I don't see any of them wrapped in the esc_* method.

Copy link
Member

@aristath aristath Aug 5, 2022

Choose a reason for hiding this comment

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

could we abstract all sanitization and move the esc_html too?

esc_html causes issues with values that contain quotes - like for example URLs in background:url("example.com/image.jpg"). That's why over in #42968 I was introducing a sanitize_value method 😉

Copy link
Member

Choose a reason for hiding this comment

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

I did some tests, and now I'm 99% sure we don't need esc_html here.

Sorry for the ping, @peterwilsoncc. Can you confirm that values returned by safecss_filter_attr don't need escaping?

$value = safecss_filter_attr( $css );

// VS

$value = esc_html( safecss_filter_attr( $css ) );

Copy link
Member

Choose a reason for hiding this comment

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

I think we can just remove esc_html
It's not used anywhere in Core when printing CSS, and the safecss call takes care of most (all?) cases I can think of that could potentially cause issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the discussion, folks! I've updated this PR to remove the call to esc_html and updated the tests accordingly.

@ramonjd ramonjd requested a review from Mamaduka August 5, 2022 04:53
@Mamaduka
Copy link
Member

Mamaduka commented Aug 5, 2022

There're new flaky test reports 43007...43011. Let's double check code for 500 errors and close those.

@@ -149,14 +149,37 @@ public function test_generate_prettified_with_more_indents_css_declarations_stri
*/
public function test_remove_unsafe_properties_and_values() {
$input_declarations = array(
'color' => '<red/>',
'color' => 'url("https://wordpress.org")',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've changed this one to be a value that safecss_filter_attr strips, instead, since this PR now removes the call to esc_html so we no longer need to test whether or not HTML characters will be escaped.

@andrewserong
Copy link
Contributor Author

andrewserong commented Aug 8, 2022

There're new flaky test reports 43007...43011. Let's double check code for 500 errors and close those.

Thanks for the heads-up @Mamaduka, these 500 errors occurred while wordpress.org was down, so it was most likely caused by failures fetching from there. I'll close out those issues.

@andrewserong andrewserong force-pushed the try/allow-css-functions-and-var-fallback branch from 62444ec to 45f4c41 Compare August 8, 2022 02:09
@andrewserong
Copy link
Contributor Author

I think this one's ready now for a final review. @aristath, @Mamaduka and @ramonjd are there any objections to proceeding with this approach? I don't mind too much whether we go with this PR or another one, but it'd be great to try to get a fix merged before the 13.9 RC gets pushed tomorrow if we can.

@ramonjd
Copy link
Member

ramonjd commented Aug 9, 2022

LGTM 👍

Retested. The CSS functions are coming through as expected

<style id='block-supports-inline-css'>
.barnacle-bill {
	max-width: clamp(36.00rem, calc(32.00rem + 10.00vw), 40.00rem);
}
.barnacle-bob {
	font-size: min(calc(3 * 10.00vw));
}
.barnacle-barry {
	height: max(calc(3 * 10.00vw));
}
.barnacle-brad {
	padding: minmax(20px, auto) 1fr 1fr);
}
</style>

@aristath aristath merged commit 60adc79 into trunk Aug 9, 2022
@aristath aristath deleted the try/allow-css-functions-and-var-fallback branch August 9, 2022 08:01
@github-actions github-actions bot added this to the Gutenberg 13.9 milestone Aug 9, 2022
@Mamaduka
Copy link
Member

Mamaduka commented Aug 9, 2022

Thanks for landing this, folks!

@andrewserong, do you mind leaving a comment on https://core.trac.wordpress.org/ticket/55966, saying that we adopted regex from the patch? It might help move the ticket forward for committing.

@andrewserong
Copy link
Contributor Author

Good idea! I've added a comment in https://core.trac.wordpress.org/ticket/55966#comment:6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Style Engine /packages/style-engine [Type] Bug An existing feature does not function as intended
Projects
Status: 🏆 Done
Development

Successfully merging this pull request may close these issues.

1.3.9: clamp() is no longer recognized in “contentSize” or “wideSize” in theme.json
4 participants