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

Customizer > Custom CSS: Add support for CSS variables #20129

Open
wants to merge 6 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: compat

Modified csstidy to allow css variable properties
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ function __construct() {
$this->settings['discard_invalid_properties'] = false;
$this->settings['css_level'] = 'CSS2.1';
$this->settings['preserve_css'] = false;
$this->settings['preserve_css_variables'] = false;
$this->settings['timestamp'] = false;
$this->settings['template'] = ''; // say that propertie exist
$this->set_cfg('template','default'); // call load_template
Expand Down Expand Up @@ -1180,9 +1181,21 @@ function property_is_valid($property) {
$property = strtolower($property);
if (in_array(trim($property), $GLOBALS['csstidy']['multiple_properties'])) $property = trim($property);
$all_properties = & $GLOBALS['csstidy']['all_properties'];
return (isset($all_properties[$property]) && strpos($all_properties[$property], strtoupper($this->get_cfg('css_level'))) !== false );
return ( ( isset( $all_properties[ $property ] ) && strpos( $all_properties[ $property ], strtoupper( $this->get_cfg( 'css_level' ) ) ) !== false ) || ( $this->get_cfg( 'preserve_css_variables' ) && $this->property_is_css_variable( $property ) ) );
Copy link
Member

Choose a reason for hiding this comment

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

This line is really hard to grok, could we extract it to a function?

}

/**
* Checks if a property is a css variable
* Valid patterns must start with `--` and use alphanumeric characters optionally separated by `-`, `--`, or `_`. They must not end with a `-`, `--`, or `_`.
*
* @param string $property The property name to be checked.
* @return bool;
* @access public
* @version 1.5
*/
public function property_is_css_variable( $property ) {
return preg_match( '/^(--[a-zA-Z0-9]+)(([-]{1,2}|[_]?)[a-zA-Z0-9]+)*$/', $property );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FYI - I have modified the original regex: https://github.com/Automattic/jetpack/pull/19935/files#diff-09336221a25ca5f791ce459fbe1f11846ebd8ace76220d89eec08dca03591b70R1196 to allow for "nested" variables like, for example: --wp--custom--color--foreground

}
/**
* Accepts a list of strings (e.g., the argument to format() in a @font-face src property)
* and returns a list of the strings. Converts things like:
Expand Down
1 change: 1 addition & 0 deletions projects/plugins/jetpack/modules/custom-css/custom-css.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ public static function save( $args = array() ) {
$csstidy->set_cfg( 'discard_invalid_properties', true );
$csstidy->set_cfg( 'css_level', 'CSS3.0' );
$csstidy->set_cfg( 'preserve_css', true );
$csstidy->set_cfg( 'preserve_css_variables', true );
$csstidy->set_cfg( 'template', dirname( __FILE__ ) . '/csstidy/wordpress-standard.tpl' );

$css = $orig = $args['css'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,39 @@ public function test_preserve_leading_zeros( $input, $expected_output, $preserve
$this->instance->print->plain()
);
}

/** Provides values for CSS custom property patterns */
public function custom_property_matches_provider() {
// phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- false positive
// 'test case description' => [ 'input', 'expected output', 'preserve_css_variables' ].
return array(
'test_removes_css_var_properties_by_default' => array( 'div {--base-color:red;color:var(--base-color)}', "div {\ncolor:var(--base-color)\n}", false ),
'test_css_var_properties_preserved' => array( 'div {--base-color_for_1st-child:red;color:var(--base-color)}', "div {\n--base-color_for_1st-child:red;\ncolor:var(--base-color)\n}", true ),
'test_css_var_properties_with_no_alphanum_chars_removed' => array( 'div {--_:red;color:var(--base-color)}', "div {\ncolor:var(--base-color)\n}", true ),
'test_css_var_properties_ending_in_hyphen_removed' => array( 'div {--base-color-:red;color:var(--base-color)}', "div {\ncolor:var(--base-color)\n}", true ),
'test_css_var_properties_ending_in_underscore_removed' => array( 'div {--base-color_:red;color:var(--base-color)}', "div {\ncolor:var(--base-color)\n}", true ),
'test_unknown_properties_removed' => array( 'div {clowns-nose:red;color:var(--base-color)}', "div {\ncolor:var(--base-color)\n}", true ),
'test_invalid_css_properties_removed' => array( 'div {--$//2343--3423:red;color:var(--$//2343--3423)}', "div {\n--2343--3423:red;\ncolor:var(--$//2343--3423)\n}", true ),
'test_broken_or_dangerous_css_removed' => array( 'div {xss-trap-be-careful:red;}</style><script>alert(\'Gotcha!\')</script>color:var(--base-color)}', '', true ),
);
}

/**
* Test that css variable properties are valid/invalid.
*
* @dataProvider custom_property_matches_provider
*
* @param string $input potential CSS custom property.
* @param string $expected_output what we expect css tidy to output.
* @param bool $preserve_css_variables the value of preserve_css_variables in csstidy's config.
*/
public function test_custom_property_patterns( $input, $expected_output, $preserve_css_variables ) {
$this->instance->set_cfg( 'discard_invalid_properties', true );
$this->instance->set_cfg( 'preserve_css_variables', $preserve_css_variables );
$this->instance->parse( $input );
$this->assertEquals(
$expected_output,
$this->instance->print->plain()
);
}
}