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

CSSTidy: add support for css variable definition #19935

Closed
wants to merge 12 commits into from
5 changes: 5 additions & 0 deletions projects/plugins/jetpack/changelog/add-css-vars-to-csstidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: compat
Comment: Modified csstidy to allow css variable properties


Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ function __construct() {
$this->settings['preserve_css'] = false;
$this->settings['timestamp'] = false;
$this->settings['template'] = ''; // say that propertie exist
$this->settings['preserve_css_variables'] = false;
$this->set_cfg('template','default'); // call load_template
$this->optimise = new csstidy_optimise($this);

Expand Down Expand Up @@ -1178,7 +1179,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 ) ) );
}

/**
* 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.0
*/
public function property_is_css_variable( $property ) {
return preg_match( '/^--([a-zA-Z0-9]+[\-_]?)+(?<![\-_])$/', $property );
}

/**
Expand Down
3 changes: 2 additions & 1 deletion projects/plugins/jetpack/modules/custom-css/custom-css.php
Original file line number Diff line number Diff line change
Expand Up @@ -1623,9 +1623,10 @@ static function filter_attr( $css, $element = 'div' ) {
$csstidy->set_cfg( 'remove_last_;', false );
$csstidy->set_cfg( 'css_level', 'CSS3.0' );

// Turn off css shorthands when in block editor context as it breaks block validation.
// Turn off css shorthands, and allow css variables, when in block editor context otherwise block validation is broken.
if ( true === isset( $_REQUEST['_gutenberg_nonce'] ) && wp_verify_nonce( $_REQUEST['_gutenberg_nonce'], 'gutenberg_request' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
$csstidy->set_cfg( 'optimise_shorthands', 0 );
$csstidy->set_cfg( 'preserve_css_variables', true );
}

$css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $css );
Expand Down
3 changes: 3 additions & 0 deletions projects/plugins/jetpack/phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@
<testsuite name="seo-tools">
<directory prefix="test" suffix=".php">tests/php/modules/seo-tools</directory>
</testsuite>
<testsuite name="csstidy">
<directory prefix="test" suffix=".php">tests/php/modules/csstidy</directory>
</testsuite>
</testsuites>
<groups>
<exclude>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for adding some tests! ❤️

/**
* Class WP_Test_Jetpack_CSSTidy.
*
* @package automattic/jetpack
*/

require_jetpack_file( 'modules/custom-css/csstidy/class.csstidy.php' );

/**
* Class WP_Test_Jetpack_CSSTidy
*/
class WP_Test_Jetpack_CSSTidy extends WP_UnitTestCase {

/**
* The tested instance.
*
* @var csstidy
*/
public $instance;

/**
* Sets up each test.
*
* @inheritDoc
*/
public function setUp() {
parent::setUp();
$this->instance = new csstidy();
$this->instance->set_cfg( 'optimise_shorthands', 0 );
$this->instance->set_cfg( 'discard_invalid_properties', true );
}

/** 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 {\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( 'preserve_css_variables', $preserve_css_variables );
$this->instance->parse( $input );
$this->assertEquals(
$expected_output,
$this->instance->print->plain()
);
}
}