diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1a60b53e4d..e7c44d5340 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -32,3 +32,6 @@ # Plugin: Speculative Loading /plugins/speculation-rules @felixarntz + +# Plugin: View Transitions +/plugins/view-transitions @felixarntz diff --git a/.github/workflows/php-test-plugins.yml b/.github/workflows/php-test-plugins.yml index ec1aebda1b..761be7e7ad 100644 --- a/.github/workflows/php-test-plugins.yml +++ b/.github/workflows/php-test-plugins.yml @@ -95,6 +95,7 @@ jobs: npm run test-php:image-prioritizer -- -- -- --coverage-clover=./single-site-reports/coverage-image-prioritizer.xml npm run test-php:optimization-detective -- -- -- --coverage-clover=./single-site-reports/coverage-optimization-detective.xml npm run test-php:speculation-rules -- -- -- --coverage-clover=./single-site-reports/coverage-speculation-rules.xml + npm run test-php:view-transitions -- -- -- --coverage-clover=./single-site-reports/coverage-view-transitions.xml npm run test-php:web-worker-offloading -- -- -- --coverage-clover=./single-site-reports/coverage-web-worker-offloading.xml npm run test-php:webp-uploads -- -- -- --coverage-clover=./single-site-reports/coverage-webp-uploads.xml else @@ -110,6 +111,7 @@ jobs: npm run test-php-multisite:image-prioritizer -- -- -- --coverage-clover=./multisite-reports/coverage-multisite-image-prioritizer.xml npm run test-php-multisite:optimization-detective -- -- -- --coverage-clover=./multisite-reports/coverage-multisite-optimization-detective.xml npm run test-php-multisite:speculation-rules -- -- -- --coverage-clover=./multisite-reports/coverage-multisite-speculation-rules.xml + npm run test-php-multisite:view-transitions -- -- -- --coverage-clover=./multisite-reports/coverage-multisite-view-transitions.xml npm run test-php-multisite:web-worker-offloading -- -- -- --coverage-clover=./multisite-reports/coverage-multisite-web-worker-offloading.xml npm run test-php-multisite:webp-uploads -- -- -- --coverage-clover=./multisite-reports/coverage-multisite-webp-uploads.xml else diff --git a/.wp-env.json b/.wp-env.json index 3887c95a09..9a7daf67ab 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -8,6 +8,7 @@ "./plugins/image-prioritizer", "./plugins/performance-lab", "./plugins/speculation-rules", + "./plugins/view-transitions", "./plugins/web-worker-offloading", "./plugins/webp-uploads" ], diff --git a/composer.json b/composer.json index a0de99af67..8accd8b17a 100644 --- a/composer.json +++ b/composer.json @@ -55,6 +55,7 @@ "@format:optimization-detective", "@format:performance-lab", "@format:speculation-rules", + "@format:view-transitions", "@format:web-worker-offloading", "@format:webp-uploads" ], @@ -65,6 +66,7 @@ "format:optimization-detective": "@format -- ./plugins/optimization-detective --standard=./plugins/optimization-detective/phpcs.xml.dist", "format:performance-lab": "@format -- ./plugins/performance-lab --standard=./plugins/performance-lab/phpcs.xml.dist", "format:speculation-rules": "@format -- ./plugins/speculation-rules --standard=./plugins/speculation-rules/phpcs.xml.dist", + "format:view-transitions": "@format -- ./plugins/view-transitions --standard=./plugins/view-transitions/phpcs.xml.dist", "format:web-worker-offloading": "@format -- ./plugins/web-worker-offloading --standard=./plugins/web-worker-offloading/phpcs.xml.dist", "format:webp-uploads": "@format -- ./plugins/webp-uploads --standard=./plugins/webp-uploads/phpcs.xml.dist", "lint": "phpcs", @@ -77,6 +79,7 @@ "@lint:optimization-detective", "@lint:performance-lab", "@lint:speculation-rules", + "@lint:view-transitions", "@lint:web-worker-offloading", "@lint:webp-uploads" ], @@ -87,6 +90,7 @@ "lint:optimization-detective": "@lint -- ./plugins/optimization-detective --standard=./plugins/optimization-detective/phpcs.xml.dist", "lint:performance-lab": "@lint -- ./plugins/performance-lab --standard=./plugins/performance-lab/phpcs.xml.dist", "lint:speculation-rules": "@lint -- ./plugins/speculation-rules --standard=./plugins/speculation-rules/phpcs.xml.dist", + "lint:view-transitions": "@lint -- ./plugins/view-transitions --standard=./plugins/view-transitions/phpcs.xml.dist", "lint:web-worker-offloading": "@lint -- ./plugins/web-worker-offloading --standard=./plugins/web-worker-offloading/phpcs.xml.dist", "lint:webp-uploads": "@lint -- ./plugins/webp-uploads --standard=./plugins/webp-uploads/phpcs.xml.dist", "phpstan": "phpstan analyse --memory-limit=2048M", @@ -102,6 +106,7 @@ "@test-multisite:optimization-detective", "@test-multisite:performance-lab", "@test-multisite:speculation-rules", + "@test-multisite:view-transitions", "@test-multisite:web-worker-offloading", "@test-multisite:webp-uploads" ], @@ -112,6 +117,7 @@ "test-multisite:optimization-detective": "@test-multisite --verbose --testsuite optimization-detective", "test-multisite:performance-lab": "@test-multisite --verbose --testsuite performance-lab", "test-multisite:speculation-rules": "@test-multisite --verbose --testsuite speculation-rules", + "test-multisite:view-transitions": "@test-multisite --verbose --testsuite view-transitions", "test-multisite:web-worker-offloading": "@test-multisite --verbose --testsuite web-worker-offloading", "test-multisite:webp-uploads": "@test-multisite --verbose --testsuite webp-uploads", "test:plugins": [ @@ -122,6 +128,7 @@ "@test:optimization-detective", "@test:performance-lab", "@test:speculation-rules", + "@test:view-transitions", "@test:web-worker-offloading", "@test:webp-uploads" ], @@ -132,6 +139,7 @@ "test:optimization-detective": "@test --verbose --testsuite optimization-detective", "test:performance-lab": "@test --verbose --testsuite performance-lab", "test:speculation-rules": "@test --verbose --testsuite speculation-rules", + "test:view-transitions": "@test --verbose --testsuite view-transitions", "test:web-worker-offloading": "@test --verbose --testsuite web-worker-offloading", "test:webp-uploads": "@test --verbose --testsuite webp-uploads" } diff --git a/composer.lock b/composer.lock index cecba65f29..0fb65c4661 100644 --- a/composer.lock +++ b/composer.lock @@ -659,16 +659,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.11", + "version": "0.4.12", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "8b29105305d85fa440ae0bce1d4d83fcdf5b47ca" + "reference": "d8f8290313e4fd1b4840c553a8492eff31ad54eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/8b29105305d85fa440ae0bce1d4d83fcdf5b47ca", - "reference": "8b29105305d85fa440ae0bce1d4d83fcdf5b47ca", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/d8f8290313e4fd1b4840c553a8492eff31ad54eb", + "reference": "d8f8290313e4fd1b4840c553a8492eff31ad54eb", "shasum": "" }, "type": "library", @@ -685,9 +685,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.11" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.12" }, - "time": "2025-02-12T00:19:27+00:00" + "time": "2025-04-15T00:22:00+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -2471,16 +2471,16 @@ }, { "name": "wp-phpunit/wp-phpunit", - "version": "6.7.2", + "version": "6.8.1", "source": { "type": "git", "url": "https://github.com/wp-phpunit/wp-phpunit.git", - "reference": "e2bb06bacc92a8e9e405e83f56989e8ed9359db1" + "reference": "a33d328dab5a4a9ddf0c560bcadbabb58b5ee67f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/e2bb06bacc92a8e9e405e83f56989e8ed9359db1", - "reference": "e2bb06bacc92a8e9e405e83f56989e8ed9359db1", + "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/a33d328dab5a4a9ddf0c560bcadbabb58b5ee67f", + "reference": "a33d328dab5a4a9ddf0c560bcadbabb58b5ee67f", "shasum": "" }, "type": "library", @@ -2515,7 +2515,7 @@ "issues": "https://github.com/wp-phpunit/issues", "source": "https://github.com/wp-phpunit/wp-phpunit" }, - "time": "2025-02-12T01:22:52+00:00" + "time": "2025-04-16T01:40:54+00:00" }, { "name": "yoast/phpunit-polyfills", diff --git a/package.json b/package.json index f11025caa4..1c53880c57 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "build:plugin:image-prioritizer": "webpack --mode production --env plugin=image-prioritizer", "build:plugin:optimization-detective": "webpack --mode production --env plugin=optimization-detective", "build:plugin:speculation-rules": "webpack --mode production --env plugin=speculation-rules", + "build:plugin:view-transitions": "webpack --mode production --env plugin=view-transitions", "build:plugin:web-worker-offloading": "webpack --mode production --env plugin=web-worker-offloading", "build:plugin:webp-uploads": "webpack --mode production --env plugin=webp-uploads", "generate-pending-release-diffs": "bin/generate-pending-release-diffs.sh", @@ -62,6 +63,7 @@ "test-php:image-prioritizer": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:image-prioritizer", "test-php:optimization-detective": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:optimization-detective", "test-php:speculation-rules": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:speculation-rules", + "test-php:view-transitions": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:view-transitions", "test-php:web-worker-offloading": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:web-worker-offloading", "test-php:webp-uploads": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:webp-uploads", "test-php-multisite:performance-lab": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:performance-lab", @@ -71,6 +73,7 @@ "test-php-multisite:image-prioritizer": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:image-prioritizer", "test-php-multisite:optimization-detective": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:optimization-detective", "test-php-multisite:speculation-rules": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:speculation-rules", + "test-php-multisite:view-transitions": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:view-transitions", "test-php-multisite:web-worker-offloading": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:web-worker-offloading", "test-php-multisite:webp-uploads": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:webp-uploads", "wp-env": "wp-env", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index dabb920a24..58530fba96 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -29,6 +29,9 @@ plugins/speculation-rules/tests + + plugins/view-transitions/tests + plugins/web-worker-offloading/tests diff --git a/plugins/view-transitions/hooks.php b/plugins/view-transitions/hooks.php new file mode 100644 index 0000000000..df3903f708 --- /dev/null +++ b/plugins/view-transitions/hooks.php @@ -0,0 +1,32 @@ +' . "\n"; +} +add_action( 'wp_head', 'plvt_render_generator' ); + +/** + * Filters related to the View Transitions functionality. + */ +add_action( 'after_setup_theme', 'plvt_polyfill_theme_support', PHP_INT_MAX ); +add_action( 'wp_enqueue_scripts', 'plvt_load_view_transitions' ); diff --git a/plugins/view-transitions/includes/theme.php b/plugins/view-transitions/includes/theme.php new file mode 100644 index 0000000000..c2f691b679 --- /dev/null +++ b/plugins/view-transitions/includes/theme.php @@ -0,0 +1,45 @@ + + + WordPress Coding Standards for View Transitions Plugin + + + + + + . + diff --git a/plugins/view-transitions/readme.txt b/plugins/view-transitions/readme.txt new file mode 100644 index 0000000000..7fb27b817f --- /dev/null +++ b/plugins/view-transitions/readme.txt @@ -0,0 +1,56 @@ +=== View Transitions === + +Contributors: wordpressdotorg +Tested up to: 6.8 +Stable tag: 1.4.0 +License: GPLv2 or later +License URI: https://www.gnu.org/licenses/gpl-2.0.html +Tags: performance, view transitions, smooth transitions, animations + +Adds smooth transitions between navigations to your WordPress site. + +== Description == + +This plugin implements support for [cross-document view transitions](https://developer.chrome.com/docs/web-platform/view-transitions/cross-document) in WordPress. This effectively replaces the hard transitions when navigating from one URL to the other with a smooth animation, by default using a fade effect. + += Browser support = + +Cross-document view transitions are supported in a variety of browsers, including Chrome, Edge, and Safari. Users with browsers that currently do not support it should not see any adverse effects when the plugin is active. They will simply not benefit from the feature and continue to experience the traditional hard transitions between URLs. + +[Please refer to "Can I use..." for a comprehensive overview of browser support for the feature.](https://caniuse.com/mdn-css_at-rules_view-transition) + +== Installation == + += Installation from within WordPress = + +1. Visit **Plugins > Add New**. +2. Search for **View Transitions**. +3. Install and activate the **View Transitions** plugin. + += Manual installation = + +1. Upload the entire plugin folder to the `/wp-content/plugins/` directory. +2. Visit **Plugins**. +3. Activate the **View Transitions** plugin. + +== Frequently Asked Questions == + += Where can I submit my plugin feedback? = + +Feedback is encouraged and much appreciated, especially since this plugin may contain future WordPress core features. If you have suggestions or requests for new features, you can [submit them as an issue in the WordPress Performance Team's GitHub repository](https://github.com/WordPress/performance/issues/new/choose). If you need help with troubleshooting or have a question about the plugin, please [create a new topic on our support forum](https://wordpress.org/support/plugin/view-transitions/#new-topic-0). + += Where can I report security bugs? = + +The Performance team and WordPress community take security bugs seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +To report a security issue, please visit the [WordPress HackerOne](https://hackerone.com/wordpress) program. + += How can I contribute to the plugin? = + +Contributions are always welcome! Learn more about how to get involved in the [Core Performance Team Handbook](https://make.wordpress.org/performance/handbook/get-involved/). + +== Changelog == + += 1.0.0 = + +* Initial release. diff --git a/plugins/view-transitions/tests/test-hooks.php b/plugins/view-transitions/tests/test-hooks.php new file mode 100644 index 0000000000..505d4f3c77 --- /dev/null +++ b/plugins/view-transitions/tests/test-hooks.php @@ -0,0 +1,22 @@ +assertSame( 10, has_action( 'wp_head', 'plvt_render_generator' ) ); + $this->assertSame( PHP_INT_MAX, has_action( 'after_setup_theme', 'plvt_polyfill_theme_support' ) ); + $this->assertSame( 10, has_action( 'wp_enqueue_scripts', 'plvt_load_view_transitions' ) ); + } + + public function test_plvt_render_generator(): void { + $expected = '' . "\n"; + $output = get_echo( 'plvt_render_generator' ); + $this->assertSame( $expected, $output ); + } +} diff --git a/plugins/view-transitions/tests/test-theme.php b/plugins/view-transitions/tests/test-theme.php new file mode 100644 index 0000000000..5e43560cf1 --- /dev/null +++ b/plugins/view-transitions/tests/test-theme.php @@ -0,0 +1,43 @@ +assertTrue( current_theme_supports( 'view-transitions' ) ); + $this->assertTrue( get_theme_support( 'view-transitions' ) ); + + // Test polyfill does not override theme support arguments if already provided by the actual theme. + add_theme_support( 'view-transitions', array( 'custom_key' => 'custom_value' ) ); + plvt_polyfill_theme_support(); + $this->assertTrue( current_theme_supports( 'view-transitions' ) ); + $this->assertSame( array( array( 'custom_key' => 'custom_value' ) ), get_theme_support( 'view-transitions' ) ); + } + + public function test_plvt_load_view_transitions(): void { + // Clear up style if it is already registered. + if ( wp_style_is( 'wp-view-transitions', 'registered' ) ) { + unset( wp_styles()->registered['wp-view-transitions'] ); + } + + // Test that without theme support this does nothing. + remove_theme_support( 'view-transitions' ); + plvt_load_view_transitions(); + $this->assertFalse( wp_style_is( 'wp-view-transitions', 'registered' ) ); + $this->assertFalse( wp_style_is( 'wp-view-transitions', 'enqueued' ) ); + + // Test that with theme support it registers and enqueues the style. + add_theme_support( 'view-transitions' ); + plvt_load_view_transitions(); + $this->assertTrue( wp_style_is( 'wp-view-transitions', 'registered' ) ); + $this->assertTrue( wp_style_is( 'wp-view-transitions', 'enqueued' ) ); + } +} diff --git a/plugins/view-transitions/view-transitions.php b/plugins/view-transitions/view-transitions.php new file mode 100644 index 0000000000..0e508f30f5 --- /dev/null +++ b/plugins/view-transitions/view-transitions.php @@ -0,0 +1,32 @@ +