diff --git a/projects/plugins/jetpack/changelog/add-custom-css-variable-support b/projects/plugins/jetpack/changelog/add-custom-css-variable-support new file mode 100644 index 0000000000000..5ae8aa78d0aae --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-custom-css-variable-support @@ -0,0 +1,4 @@ +Significance: patch +Type: compat + +Modified csstidy to allow css variable properties diff --git a/projects/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php b/projects/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php index 106a770b8bb74..2411526f83ac9 100644 --- a/projects/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php +++ b/projects/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php @@ -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 @@ -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 ) ) ); } + /** + * 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 ); + } /** * 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: diff --git a/projects/plugins/jetpack/modules/custom-css/custom-css.php b/projects/plugins/jetpack/modules/custom-css/custom-css.php index a62e2fe703f8e..4d6e28ea3285b 100644 --- a/projects/plugins/jetpack/modules/custom-css/custom-css.php +++ b/projects/plugins/jetpack/modules/custom-css/custom-css.php @@ -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']; diff --git a/projects/plugins/jetpack/tests/php/modules/csstidy/test-class.jetpack-csstidy.php b/projects/plugins/jetpack/tests/php/modules/csstidy/test-class.jetpack-csstidy.php index a30b3bcc4d528..d8cc9c90fd531 100644 --- a/projects/plugins/jetpack/tests/php/modules/csstidy/test-class.jetpack-csstidy.php +++ b/projects/plugins/jetpack/tests/php/modules/csstidy/test-class.jetpack-csstidy.php @@ -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;}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() + ); + } }