diff --git a/src/wp-includes/kses.php b/src/wp-includes/kses.php index d1e3552f4e91b..bc6a98df6c564 100644 --- a/src/wp-includes/kses.php +++ b/src/wp-includes/kses.php @@ -2553,6 +2553,8 @@ function kses_init() { * @since 6.5.0 Added support for `background-repeat`. * @since 6.6.0 Added support for `grid-column`, `grid-row`, and `container-type`. * @since 6.9.0 Added support for `white-space`. + * @since 7.1.0 Added support for CSS anchor positioning properties and the + * `anchor()` and `anchor-size()` functions. * * @param string $css A string of CSS rules, decoded from an HTML `style` attribute. * @param string $deprecated Not used. @@ -2734,6 +2736,16 @@ function safecss_filter_attr( $css, $deprecated = '' ) { 'aspect-ratio', 'container-type', + // CSS anchor positioning. + 'anchor-name', + 'anchor-scope', + 'position-anchor', + 'position-area', + 'position-try', + 'position-try-fallbacks', + 'position-try-order', + 'position-visibility', + 'fill', 'fill-opacity', 'fill-rule', @@ -2913,7 +2925,7 @@ function safecss_filter_attr( $css, $deprecated = '' ) { * Nested functions and parentheses are also removed, so long as the parentheses are balanced. */ $css_test_string = preg_replace( - '/\b(?:var|calc|min|max|minmax|clamp|repeat)(\((?:[^()]|(?1))*\))/', + '/\b(?:var|calc|min|max|minmax|clamp|repeat|anchor-size|anchor)(\((?:[^()]|(?1))*\))/', '', $css_test_string ); diff --git a/tests/phpunit/tests/kses.php b/tests/phpunit/tests/kses.php index 9ed3a45b2d90e..d3487fddbb7fd 100644 --- a/tests/phpunit/tests/kses.php +++ b/tests/phpunit/tests/kses.php @@ -1001,6 +1001,7 @@ public function test_wp_kses_attr_no_attributes_allowed_with_false() { * @ticket 60132 * @ticket 64414 * @ticket 65457 + * @ticket 64972 * * @dataProvider data_safecss_filter_attr * @@ -1511,6 +1512,31 @@ public function data_safecss_filter_attr() { 'css' => 'text-anchor: middle', 'expected' => 'text-anchor: middle', ), + // CSS anchor positioning properties are allowed. + array( + 'css' => 'anchor-name: --tooltip;anchor-scope: all;position-anchor: --tooltip;position-area: top;position-try: flip-block;position-try-fallbacks: --fallback;position-try-order: most-height;position-visibility: anchors-visible', + 'expected' => 'anchor-name: --tooltip;anchor-scope: all;position-anchor: --tooltip;position-area: top;position-try: flip-block;position-try-fallbacks: --fallback;position-try-order: most-height;position-visibility: anchors-visible', + ), + // The `anchor()` function is allowed in inset properties. + array( + 'css' => 'top: anchor(--tooltip bottom)', + 'expected' => 'top: anchor(--tooltip bottom)', + ), + // The `anchor-size()` function is allowed in sizing properties. + array( + 'css' => 'width: anchor-size(--tooltip width)', + 'expected' => 'width: anchor-size(--tooltip width)', + ), + // The `anchor-size()` function is allowed when nested in another function. + array( + 'css' => 'margin-left: calc(anchor-size(width) / 2)', + 'expected' => 'margin-left: calc(anchor-size(width) / 2)', + ), + // Allowing `anchor()` must not allow other, unknown functions. + array( + 'css' => 'width: expression(alert(1))', + 'expected' => '', + ), ); }