From 858fcab59a39cccfdcde60275f28ea2c1f1fefd1 Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Wed, 10 Jun 2026 15:19:08 -0500 Subject: [PATCH 1/5] Revert "Force base ref to www.php.net, and set it only once" This reverts commit f88212520ebdc5e7012e87c119cd2e0a376f460f. --- include/header.inc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/header.inc b/include/header.inc index 8dc0076126..48722edafa 100644 --- a/include/header.inc +++ b/include/header.inc @@ -61,7 +61,9 @@ if (!isset($config["languages"])) { - + + "> + <?php echo $title ?> @@ -103,6 +105,10 @@ if (!isset($config["languages"])) { + + "> + + From ef7fc2456353990a8823cc720aa6d4d07370b5db Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Fri, 14 Nov 2025 16:49:42 -0600 Subject: [PATCH 2/5] Use PHP 8.5 styling for all release pages Enables dark mode, syntax highlighting of variables, and unified design for all release pages. Release pages prior to 8.5 still lack the Key Features section. Also fixed inconsistent i18n language spelling in the dropdowns on a few release pages, and corrected an English grammar typo on the PHP 8.1 page. No other content has been changed. --- releases/8.0/common.php | 38 +- releases/8.0/release.inc | 609 +++++++----------- releases/8.1/common.php | 36 +- releases/8.1/languages/en.php | 2 +- releases/8.1/release.inc | 977 +++++++++++------------------ releases/8.2/common.php | 40 +- releases/8.2/release.inc | 606 ++++++++---------- releases/8.3/common.php | 40 +- releases/8.3/release.inc | 836 ++++++++++--------------- releases/8.4/common.php | 40 +- releases/8.4/release.inc | 965 ++++++++++++---------------- releases/8.5/common.php | 2 +- releases/8.5/release.inc | 1004 +++++++++--------------------- src/Themes/FeatureComparison.php | 18 + src/Themes/ReleasePage.php | 394 ++++++++++++ styles/php8.css | 444 ------------- styles/php85.css | 85 ++- 17 files changed, 2407 insertions(+), 3729 deletions(-) create mode 100644 src/Themes/FeatureComparison.php create mode 100644 src/Themes/ReleasePage.php delete mode 100644 styles/php8.css diff --git a/releases/8.0/common.php b/releases/8.0/common.php index bd1b9a5d30..17b0c181ba 100644 --- a/releases/8.0/common.php +++ b/releases/8.0/common.php @@ -22,15 +22,22 @@ ]; function common_header(string $description): void { - global $MYSITE; + global $MYSITE, $lang; $meta_image_path = \htmlspecialchars( \filter_var($MYSITE . 'images/php8/php_8_released.png', \FILTER_VALIDATE_URL)); $meta_description = \htmlspecialchars($description); - \site_header("PHP 8.0.0 Release Announcement", [ - 'current' => 'php8', - 'css' => ['php8.css'], + $languages = []; + foreach (LANGUAGES as $code => $text) { + $languages[] = ['name' => $text, 'selected' => $lang === $code, 'url' => '/releases/8.0/' . $code . '.php']; + } + + \site_header("PHP 8.0 Release Announcement", [ + 'current' => 'php85', + 'css' => ['php85.css'], + 'language_switcher' => $languages, + 'theme_switcher' => true, 'meta_tags' => << @@ -49,28 +56,7 @@ function common_header(string $description): void { ]); } -function language_chooser(string $currentLang): void { - // Print out the form with all the options - echo ' -
-
- - -
-
-'; -} - -function message($code, $language = 'en') +function message($code, $language = 'en'): string { $original = require __DIR__ . '/languages/en.php'; if (($language !== 'en') && file_exists(__DIR__ . '/languages/' . $language . '.php')) { diff --git a/releases/8.0/release.inc b/releases/8.0/release.inc index 84e5115ac7..0b7ec671be 100644 --- a/releases/8.0/release.inc +++ b/releases/8.0/release.inc @@ -1,7 +1,8 @@ -
-
-
- -
-
-
- -
-
-
- -
-
-
+$comparisons = [ + new FeatureComparison( + id: 'named-arguments', + title: message('named_arguments_title', $lang), + description: '', + links: [ + 'RFC|https://wiki.php.net/rfc/named_params', + message('documentation', $lang) . "|/manual/$documentation/functions.arguments.php#functions.named-arguments", + ], + before: <<<'PHP' + htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); + PHP, + after: <<<'PHP' + htmlspecialchars($string, double_encode: false); + PHP, + ), + new FeatureComparison( + id: 'attributes', + title: message('attributes_title', $lang), + description: '

' . message('attributes_description', $lang) . '

', + links: [ + 'RFC|https://wiki.php.net/rfc/attributes_v2', + message('documentation', $lang) . "|/manual/$documentation/language.attributes.php", + ], + before: <<<'PHP' + class PostsController + { + /** + * @Route("/api/posts/{id}", methods={"GET"}) + */ + public function get($id) { /* ... */ } + } + PHP, + after: <<<'PHP' + class PostsController + { + #[Route("/api/posts/{id}", methods: ["GET"])] + public function get($id) { /* ... */ } + } + PHP, + ), + new FeatureComparison( + id: 'constructor-property-promotion', + title: message('constructor_promotion_title', $lang), + description: '

' . message('constructor_promotion_description', $lang) . '

', + links: [ + 'RFC|https://wiki.php.net/rfc/constructor_promotion', + message('documentation', $lang) . "|/manual/$documentation/language.oop5.decon.php#language.oop5.decon.constructor.promotion", + ], + before: <<<'PHP' + class Point { + public float $x; + public float $y; + public float $z; -
-
-

- - RFC - -

-
-
-
PHP 7
-
- -
-
-
-
-
PHP 8
-
- -
-
-
-
-
    - -
-
-
+ public function __construct( + float $x = 0.0, + float $y = 0.0, + float $z = 0.0 + ) { + $this->x = $x; + $this->y = $y; + $this->z = $z; + } + } + PHP, + after: <<<'PHP' + class Point { + public function __construct( + public float $x = 0.0, + public float $y = 0.0, + public float $z = 0.0, + ) {} + } + PHP, + ), + new FeatureComparison( + id: 'union-types', + title: message('union_types_title', $lang), + description: '

' . message('union_types_description', $lang) . '

', + links: [ + 'RFC|https://wiki.php.net/rfc/union_types_v2', + message('documentation', $lang) . "|/manual/$documentation/language.types.declarations.php#language.types.declarations.union", + ], + before: <<<'PHP' + class Number { + /** @var int|float */ + private $number; -
-

- - RFC - -

-
-
-
PHP 7
-
- -
-
-
-
-
PHP 8
-
- -
-
-
-
-

-
-
+ /** + * @param float|int $number + */ + public function __construct($number) { + $this->number = $number; + } + } -
-

- - RFC - -

-
-
-
PHP 7
-
- x = $x; - $this->y = $y; - $this->z = $z; - } - } - PHP - );?> -
-
-
-
-
PHP 8
-
- -
-
-
-
-

-
-
+ new Number('NaN'); // TypeError + PHP, + ), + new FeatureComparison( + id: 'match-expression', + title: message('match_expression_title', $lang), + description: message('match_expression_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/match_expression_v2', + message('documentation', $lang) . "|/manual/$documentation/control-structures.match.php", + ], + before: << {$ohNoText} + PHP, + after: << "{$ohNoText}", + 8.0 => "{$expectedText}", + }; + //> {$expectedText} + PHP, + ), + new FeatureComparison( + id: 'nullsafe-operator', + title: message('nullsafe_operator_title', $lang), + description: '

' . message('nullsafe_operator_description', $lang) . '

', + links: ['RFC|https://wiki.php.net/rfc/nullsafe_operator'], + before: <<<'PHP' + $country = null; -
-

- - RFC - -

-
-
-
PHP 7
-
- user; - /** - * @param float|int $number - */ - public function __construct($number) { - $this->number = $number; - } - } + if ($user !== null) { + $address = $user->getAddress(); - new Number('NaN'); // - PHP - . ' ' . message('ok', $lang), - );?> -
-
-
-
-
PHP 8
-
- country; + } + } + } + PHP, + after: <<<'PHP' + $country = $session?->user?->getAddress()?->country; + PHP, + ), + new FeatureComparison( + id: 'saner-string-to-number-comparisons', + title: message('saner_string_number_comparisons_title', $lang), + description: '

' . message('saner_string_number_comparisons_description', $lang) . '

', + links: ['RFC|https://wiki.php.net/rfc/string_to_number_comparison'], + before: <<<'PHP' + 0 == 'foobar' // true + PHP, + after: <<<'PHP' + 0 == 'foobar' // false + PHP, + ), + new FeatureComparison( + id: 'consistent-type-errors-for-internal-functions', + title: message('consistent_internal_function_type_errors_title', $lang), + description: '

' . message('consistent_internal_function_type_errors_description', $lang) . '

', + links: ['RFC|https://wiki.php.net/rfc/consistent_type_errors'], + before: <<<'PHP' + strlen([]); // Warning: strlen() expects parameter 1 to be string, array given - new Number('NaN'); // TypeError - PHP - );?> -
-
-
-
-

-
-
+ array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0 + PHP, + after: <<<'PHP' + strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given -
-

- - RFC - -

-
-
-
PHP 7
-
- {$ohNoText} - PHP - );?> -
-
-
-
-
PHP 8
-
- "{$ohNoText}", - 8.0 => "{$expectedText}", - }; - //> {$expectedText} - PHP - );?> -
-
-
-
- -
-
- -
-

- - RFC -

-
-
-
PHP 7
-
- user; + array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0 + PHP, + ), +]; - if ($user !== null) { - $address = $user->getAddress(); - - if ($address !== null) { - $country = $address->country; - } - } - } - PHP - );?> -
-
-
-
-
PHP 8
-
- user?->getAddress()?->country; - PHP - );?> -
-
-
-
-

-
-
- -
-

- - RFC -

-
-
-
PHP 7
-
- -
-
-
-
-
PHP 8
-
- -
-
-
-
-

-
-
+echo ReleasePage::getHeroSection( + title: message('main_title', $lang), + subtitle: message('main_subtitle', $lang), + logoSvg: << + SVG, + upgradeNow: message('upgrade_now', $lang), +); -
-

- - RFC -

-
-
-
PHP 7
-
- -
-
-
-
-
PHP 8
-
- - array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0 - PHP - );?> +
+
+
+
+

+

+

+
+ Just-In-Time compilation
-
-

-
-
-
-

-

-

-
- Just-In-Time compilation -
- -
-
-

-
+
+
+
+

  • @@ -443,12 +289,9 @@ $expectedText = message('this_is_expected', $lang);
-
- -
-

-
-
    +
    +

    +
    • @@ -471,11 +314,9 @@ $expectedText = message('this_is_expected', $lang); RFC
    -
    -

    -
    -
      +

      +
      • @@ -490,16 +331,12 @@ $expectedText = message('this_is_expected', $lang);
- - false]); diff --git a/releases/8.1/common.php b/releases/8.1/common.php index a0a7cffc99..48e86aacb2 100644 --- a/releases/8.1/common.php +++ b/releases/8.1/common.php @@ -18,15 +18,22 @@ ]; function common_header(string $description): void { - global $MYSITE; + global $MYSITE, $lang; $meta_image_path = \htmlspecialchars( \filter_var($MYSITE . 'images/php8/php_8_1_released.png', \FILTER_VALIDATE_URL)); $meta_description = \htmlspecialchars($description); + $languages = []; + foreach (LANGUAGES as $code => $text) { + $languages[] = ['name' => $text, 'selected' => $lang === $code, 'url' => '/releases/8.1/' . $code . '.php']; + } + \site_header("PHP 8.1.0 Release Announcement", [ - 'current' => 'php8', - 'css' => ['php8.css'], + 'current' => 'php85', + 'css' => ['php85.css'], + 'language_switcher' => $languages, + 'theme_switcher' => true, 'meta_tags' => << @@ -45,28 +52,7 @@ function common_header(string $description): void { ]); } -function language_chooser(string $currentLang): void { - // Print out the form with all the options - echo ' -
-
- - -
-
-'; -} - -function message($code, $language = 'en') +function message($code, $language = 'en'): string { $original = require __DIR__ . '/languages/en.php'; if (($language !== 'en') && file_exists(__DIR__ . '/languages/' . $language . '.php')) { diff --git a/releases/8.1/languages/en.php b/releases/8.1/languages/en.php index 9f62cbf49a..8e14dc4712 100644 --- a/releases/8.1/languages/en.php +++ b/releases/8.1/languages/en.php @@ -8,7 +8,7 @@ 'documentation' => 'Doc', 'enumerations_title' => 'Enumerations', - 'enumerations_content' => 'Use enum instead of a set of constants and get validation out of the box.', + 'enumerations_content' => 'Use an enum instead of a set of constants to get validation out of the box.', 'readonly_properties_title' => 'Readonly Properties', 'readonly_properties_content' => '

Readonly properties cannot be changed after initialization, i.e. after a value is assigned to them.
They are a great way to model value objects and data-transfer objects.

', diff --git a/releases/8.1/release.inc b/releases/8.1/release.inc index 2485d64995..cea74b2648 100644 --- a/releases/8.1/release.inc +++ b/releases/8.1/release.inc @@ -1,7 +1,8 @@ -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-

- - RFC - -

-
-
-
PHP < 8.1
-
- -
-
-
-
-
PHP 8.1
-
- -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- status = $status; - } - - public function getStatus(): Status - { - return $this->status; - } -} -PHP - - );?> -
-
-
-
-
PHP 8.1
-
- status = $status; - } -} -PHP - );?> -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- -
-
-
-
-
PHP 8.1
-
- foo(...); - -$fn = strlen(...); -PHP - );?> -
-
-
-
- -
-
- -
-

- - RFC -

-
-
-
PHP < 8.1
-
- logger = $logger ?? new NullLogger(); - } -} -PHP - );?> -
-
-
-
-
PHP 8.1
-
- logger = $logger; - } -} -PHP - );?> -
-
-
- -
- -
-
-
-
PHP < 8.1
-
- -
-
-
-
-
PHP 8.1
-
- -
-
-
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- status = $status; + } + + public function getStatus(): Status + { + return $this->status; + } + } + PHP, + after: <<<'PHP' + class BlogData + { + public readonly Status $status; + + public function __construct(Status $status) + { + $this->status = $status; + } + } + PHP, + ), + new FeatureComparison( + id: 'first_class_callable_syntax', + title: message('first_class_callable_syntax_title', $lang), + description: message('first_class_callable_syntax_content', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/first_class_callable_syntax', + message('documentation', $lang) . "|/manual/$documentation/functions.first_class_callable_syntax.php", + ], + before: <<<'PHP' + $foo = [$this, 'foo']; + + $fn = Closure::fromCallable('strlen'); + PHP, + after: <<<'PHP' + $foo = $this->foo(...); + + $fn = strlen(...); + PHP, + ), + new FeatureComparison( + id: 'new_in_initializers', + title: message('new_in_initializers_title', $lang), + description: message('new_in_initializers_content', $lang), + links: ['RFC|https://wiki.php.net/rfc/new_in_initializers'], + before: <<<'PHP' + class Service + { + private Logger $logger; + + public function __construct( + ?Logger $logger = null, + ) { + $this->logger = $logger ?? new NullLogger(); + } + } + PHP, + after: <<<'PHP' + class Service + { + private Logger $logger; + + public function __construct( + Logger $logger = new NullLogger(), + ) { + $this->logger = $logger; + } + } + PHP, + before2: <<<'PHP' + class User + { + /** + * @Assert\All({ + * @Assert\NotNull, + * @Assert\Length(min=5) + * }) + */ + public string $name = ''; + } + PHP, + after2: <<<'PHP' + class User + { + #[\Assert\All( + new \Assert\NotNull, + new \Assert\Length(min: 5)) + ] + public string $name = ''; + } + PHP, + ), + new FeatureComparison( + id: 'pure_intersection_types', + title: message('pure_intersection_types_title', $lang), + description: message('pure_intersection_types_content', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/pure-intersection-types', + message('documentation', $lang) . "|/manual/$documentation/language.types.declarations.php#language.types.declarations.composite.intersection", + ], + before: <<<'PHP' + function count_and_iterate(Iterator $value) { + if (!($value instanceof Countable)) { + throw new TypeError('value must be Countable'); + } + + foreach ($value as $val) { + echo $val; + } + + count($value); + } + PHP, + after: <<<'PHP' + function count_and_iterate(Iterator&Countable $value) { + foreach ($value as $val) { + echo $val; + } + + count($value); + } + PHP, + ), + new FeatureComparison( + id: 'never_return_type', + title: message('never_return_type_title', $lang), + description: message('never_return_type_content', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/noreturn_type', + message('documentation', $lang) . "|/manual/$documentation/language.types.declarations.php#language.types.declarations.never", + ], + before: <<<'PHP' + function redirect(string $uri) { + header('Location: ' . $uri); + exit(); + } + + function redirectToLoginPage() { + redirect('/login'); + echo 'Hello'; // <- dead code + } + PHP, + after: <<<'PHP' + function redirect(string $uri): never { + header('Location: ' . $uri); + exit(); + } + + function redirectToLoginPage(): never { + redirect('/login'); + echo 'Hello'; // <- dead code detected by static analysis + } + PHP, + ), + new FeatureComparison( + id: 'final_class_constants', + title: message('final_class_constants_title', $lang), + description: message('final_class_constants_content', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/final_class_const', + message('documentation', $lang) . "|/manual/$documentation/language.oop5.final.php#language.oop5.final.example.php81", + ], + before: <<<'PHP' + class Foo + { + public const XX = "foo"; + } + + class Bar extends Foo + { + public const XX = "bar"; // No error + } + PHP, + after: <<<'PHP' + class Foo + { + final public const XX = "foo"; + } + + class Bar extends Foo + { + public const XX = "bar"; // Fatal error + } + PHP, + ), + new FeatureComparison( + id: 'explicit_octal_numeral_notation', + title: message('octal_numeral_notation_title', $lang), + description: message('octal_numeral_notation_content', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/explicit_octal_notation', + message('documentation', $lang) . "|/manual/$documentation/migration81.new-features.php#migration81.new-features.core.octal-literal-prefix", + ], + before: <<<'PHP' + 016 === 16; // false because `016` is octal for `14` and it's confusing + 016 === 14; // true + PHP, + after: <<<'PHP' + 0o16 === 16; // false — not confusing with explicit notation + 0o16 === 14; // true + PHP, + ), + new FeatureComparison( + id: 'fibers', + title: message('fibers_title', $lang), + description: message('fibers_content', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/fibers', + message('documentation', $lang) . "|/manual/$documentation/language.fibers.php", + ], + before: <<<'PHP' + $httpClient->request('https://example.com/') + ->then(function (Response $response) { + return $response->getBody()->buffer(); + }) + ->then(function (string $responseBody) { + print json_decode($responseBody)['code']; + }); + PHP, + after: <<<'PHP' + $response = $httpClient->request('https://example.com/'); + print json_decode($response->getBody()->buffer())['code']; + PHP, + ), + new FeatureComparison( + id: 'array_unpacking_support_for_string_keyed_arrays', + title: message('array_unpacking_title', $lang), + description: message('array_unpacking_content', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/array_unpacking_string_keys', + message('documentation', $lang) . "|/manual/$documentation/language.types.array.php#language.types.array.unpacking", + ], + before: <<<'PHP' + $arrayA = ['a' => 1]; + $arrayB = ['b' => 2]; + + $result = array_merge(['a' => 0], $arrayA, $arrayB); + + // ['a' => 1, 'b' => 2] + PHP, + after: <<<'PHP' + $arrayA = ['a' => 1]; + $arrayB = ['b' => 2]; + + $result = ['a' => 0, ...$arrayA, ...$arrayB]; + + // ['a' => 1, 'b' => 2] + PHP, + ), +]; + +echo ReleasePage::getHeroSection( + title: message('main_title', $lang), + subtitle: message('main_subtitle', $lang), + logoSvg: << + SVG, + upgradeNow: message('upgrade_now', $lang), +); + +echo ReleasePage::getFeatureComparisons($comparisons, 'PHP 8.1', 'PHP < 8.1'); - );?> -
-
-
-
-
PHP 8.1
-
- -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- - );?> +
+
+
+
+

+
+ +
+ +
+
+

+
    +
  • +
  • +
+ +

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
-
-
-
-
PHP 8.1
-
- +
+

+
    +
  • +
  • +
  • +
  • +
+ +

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- -
-
-
-
-
PHP 8.1
-
- -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- -
-
-
-
-
PHP 8.1
-
- -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- request('https://example.com/') - ->then(function (Response $response) { - return $response->getBody()->buffer(); - }) - ->then(function (string $responseBody) { - print json_decode($responseBody)['code']; - }); -PHP - - );?> -
-
-
-
-
PHP 8.1
-
- request('https://example.com/'); -print json_decode($response->getBody()->buffer())['code']; -PHP - );?> -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.1
-
- 1]; -$arrayB = ['b' => 2]; - -$result = array_merge(['a' => 0], $arrayA, $arrayB); - -// ['a' => 1, 'b' => 2] -PHP - );?> -
-
-
-
-
PHP 8.1
-
- 1]; -$arrayB = ['b' => 2]; - -$result = ['a' => 0, ...$arrayA, ...$arrayB]; - -// ['a' => 1, 'b' => 2] -PHP - );?> -
-
-
-
- -
-
-
- -
-
-

-
-
- -
- -
-
-

-
    -
  • -
  • -
-

-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
- -
-

-
-
    -
  • -
  • -
  • -
  • -
-
-

-
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
-
- - +
false]); diff --git a/releases/8.2/common.php b/releases/8.2/common.php index c3b50d6706..ae23977e97 100644 --- a/releases/8.2/common.php +++ b/releases/8.2/common.php @@ -12,21 +12,28 @@ 'de' => 'Deutsch', 'fr' => 'Français', 'pt_BR' => 'Brazilian Portuguese', - 'ru' => 'Russian', + 'ru' => 'Русский', 'ja' => '日本語', 'zh' => '简体中文', ]; function common_header(string $description): void { - global $MYSITE; + global $MYSITE, $lang; $meta_image_path = \htmlspecialchars( \filter_var($MYSITE . 'images/php8/php_8_2_released.png', \FILTER_VALIDATE_URL)); $meta_description = \htmlspecialchars($description); - \site_header("PHP 8.2.0 Release Announcement", [ - 'current' => 'php8', - 'css' => ['php8.css'], + $languages = []; + foreach (LANGUAGES as $code => $text) { + $languages[] = ['name' => $text, 'selected' => $lang === $code, 'url' => '/releases/8.2/' . $code . '.php']; + } + + \site_header("PHP 8.2 Release Announcement", [ + 'current' => 'php85', + 'css' => ['php85.css'], + 'language_switcher' => $languages, + 'theme_switcher' => true, 'meta_tags' => << @@ -45,28 +52,7 @@ function common_header(string $description): void { ]); } -function language_chooser(string $currentLang): void { - // Print out the form with all the options - echo ' -
-
- - -
-
-'; -} - -function message($code, $language = 'en') +function message($code, $language = 'en'): string { $original = require __DIR__ . '/languages/en.php'; if (($language !== 'en') && file_exists(__DIR__ . '/languages/' . $language . '.php')) { diff --git a/releases/8.2/release.inc b/releases/8.2/release.inc index 7fbacf9a4b..bcd7a56b2d 100644 --- a/releases/8.2/release.inc +++ b/releases/8.2/release.inc @@ -1,7 +1,8 @@ -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-

- - RFC - -

-
-
-
PHP < 8.2
-
- title = $title; - $this->status = $status; - } -} -PHP - - ); ?> -
-
-
-
-
PHP 8.2
-
- title = $title; - $this->status = $status; - } -} -PHP - ); ?> -
-
-
-
- -
-

- - RFC - -

-
-
-
PHP < 8.2
-
- -
-
-
-
-
PHP 8.2
-
- -
-
-
-
-
- -
- -
-

- - RFC - RFC -

-
-
-
PHP < 8.2
-
- -
-
-
-
-
PHP 8.2
-
- -
-
-
-
- -
-

- - RFC - RFC - -

-
-
-
PHP 8.2
-
- title = $title; + $this->status = $status; + } + } + PHP, + after: <<<'PHP' + readonly class BlogData + { + public string $title; + + public Status $status; + + public function __construct(string $title, Status $status) + { + $this->title = $title; + $this->status = $status; + } + } + PHP, + ), + new FeatureComparison( + id: 'dnf_types', + title: message('dnf_types_title', $lang), + description: message('dnf_types_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/dnf_types', + message('documentation', $lang) . "|/manual/$lang/migration82.new-features.php#migration82.new-features.core.type-system", + ], + before: <<<'PHP' + class Foo { + public function bar(mixed $entity) { + if ((($entity instanceof A) && ($entity instanceof B)) || ($entity === null)) { + return $entity; + } + + throw new Exception('Invalid entity'); + } + } + PHP, + after: <<<'PHP' + class Foo { + public function bar((A&B)|null $entity) { + return $entity; + } + } + PHP, + ), + new FeatureComparison( + id: 'null_false_true_types', + title: message('null_false_true_types_title', $lang), + description: '', + links: [ + 'RFC|https://wiki.php.net/rfc/null-false-standalone-types', + 'RFC|https://wiki.php.net/rfc/true-type', + ], + before: <<<'PHP' + class Falsy + { + public function almostFalse(): bool { /* ... */ *} + + public function almostTrue(): bool { /* ... */ *} + + public function almostNull(): string|null { /* ... */ *} + } + PHP, + after: <<<'PHP' + class Falsy + { + public function alwaysFalse(): false { /* ... */ *} + + public function alwaysTrue(): true { /* ... */ *} + + public function alwaysNull(): null { /* ... */ *} + } + PHP, + ), + new FeatureComparison( + id: 'random_extension', + title: message('random_title', $lang), + description: message('random_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/rng_extension', + 'RFC|https://wiki.php.net/rfc/random_extension_improvement', + message('documentation', $lang) . "|/manual/$lang/book.random.php", + ], + before: '', + after: <<<'PHP' + use Random\Engine\Xoshiro256StarStar; + use Random\Randomizer; + + $blueprintRng = new Xoshiro256StarStar( + hash('sha256', "Example seed that is converted to a 256 Bit string via SHA-256", true) + ); + + $fibers = []; + for ($i = 0; $i < 8; $i++) { + $fiberRng = clone $blueprintRng; + // Xoshiro256**'s 'jump()' method moves the blueprint ahead 2**128 steps, as if calling + // 'generate()' 2**128 times, giving the Fiber 2**128 unique values without needing to reseed. + $blueprintRng->jump(); + + $fibers[] = new Fiber(function () use ($fiberRng, $i): void { + $randomizer = new Randomizer($fiberRng); + + echo "{$i}: " . $randomizer->getInt(0, 100), PHP_EOL; + }); + } + + // The randomizer will use a CSPRNG by default. + $randomizer = new Randomizer(); + + // Even though the fibers execute in a random order, they will print the same value + // each time, because each has its own unique instance of the RNG. + $fibers = $randomizer->shuffleArray($fibers); + foreach ($fibers as $fiber) { + $fiber->start(); + } + PHP, + ), + new FeatureComparison( + id: 'constants_in_traits', + title: message('constants_in_traits_title', $lang), + description: message('constants_in_traits_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/constants_in_traits', + message('documentation', $lang) . "|/manual/$lang/migration82.new-features.php#migration82.new-features.core.constant-in-traits", + ], + before: '', + after: <<<'PHP' + trait Foo + { + public const CONSTANT = 1; + } + + class Bar + { + use Foo; + } + + var_dump(Bar::CONSTANT); // 1 + var_dump(Foo::CONSTANT); // Error + PHP, + ), + new FeatureComparison( + id: 'deprecate_dynamic_properties', + title: message('deprecate_dynamic_properties_title', $lang), + description: message('deprecate_dynamic_properties_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/deprecate_dynamic_properties', + message('documentation', $lang) . "|/manual/$lang/migration82.deprecated.php#migration82.deprecated.core.dynamic-properties", + ], + before: <<<'PHP' + class User + { + public $name; + } + + $user = new User(); + $user->last_name = 'Doe'; + + $user = new stdClass(); + $user->last_name = 'Doe'; + PHP, + after: <<<'PHP' + class User + { + public $name; + } + + $user = new User(); + $user->last_name = 'Doe'; // Deprecated notice + + $user = new stdClass(); + $user->last_name = 'Doe'; // Still allowed + PHP, + ), +]; + +echo ReleasePage::getHeroSection( + title: message('main_title', $lang), + subtitle: message('main_subtitle', $lang), + logoSvg: << + SVG, + upgradeNow: message('upgrade_now', $lang), ); -$fibers = []; -for ($i = 0; $i < 8; $i++) { - $fiberRng = clone $blueprintRng; - // Xoshiro256**'s 'jump()' method moves the blueprint ahead 2**128 steps, as if calling - // 'generate()' 2**128 times, giving the Fiber 2**128 unique values without needing to reseed. - $blueprintRng->jump(); - - $fibers[] = new Fiber(function () use ($fiberRng, $i): void { - $randomizer = new Randomizer($fiberRng); - - echo "{$i}: " . $randomizer->getInt(0, 100), PHP_EOL; - }); -} - -// The randomizer will use a CSPRNG by default. -$randomizer = new Randomizer(); +echo ReleasePage::getFeatureComparisons($comparisons, 'PHP 8.2', 'PHP < 8.2'); -// Even though the fibers execute in a random order, they will print the same value -// each time, because each has its own unique instance of the RNG. -$fibers = $randomizer->shuffleArray($fibers); -foreach ($fibers as $fiber) { - $fiber->start(); -} -PHP - ); ?> -
-
-
-
-
- -
- -
-

- - RFC - -

-
-
-
PHP 8.2
-
- -var_dump(Bar::CONSTANT); // 1 -var_dump(Foo::CONSTANT); // Error -PHP - ); ?> -
+
+
+
+
+

+
    +
  • +
  • +
  • +
  • +
  • +
-
-
-
- -
- -
-

- - RFC - -

-
-
-
PHP < 8.2
-
- last_name = 'Doe'; - -$user = new stdClass(); -$user->last_name = 'Doe'; -PHP - - ); ?> -
+
+

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
-
-
-
PHP 8.2
-
- last_name = 'Doe'; // Deprecated notice - -$user = new stdClass(); -$user->last_name = 'Doe'; // Still allowed -PHP - ); ?> -
-
-
-
-
- -
- -
- -
-
-

-
-
    -
  • -
  • -
  • -
  • -
  • -
-
-
- -
-

-
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
- - false]); diff --git a/releases/8.3/common.php b/releases/8.3/common.php index 8c3ff3bae9..81b7605d78 100644 --- a/releases/8.3/common.php +++ b/releases/8.3/common.php @@ -10,7 +10,7 @@ 'en' => 'English', 'es' => 'Español', 'de' => 'Deutsch', - 'ru' => 'Russian', + 'ru' => 'Русский', 'zh' => '简体中文', 'pt_BR' => 'Brazilian Portuguese', 'ja' => '日本語', @@ -18,15 +18,22 @@ ]; function common_header(string $description): void { - global $MYSITE; + global $MYSITE, $lang; $meta_image_path = \htmlspecialchars( \filter_var($MYSITE . 'images/php8/php_8_3_released.png', \FILTER_VALIDATE_URL)); $meta_description = \htmlspecialchars($description); - \site_header("PHP 8.3.0 Release Announcement", [ - 'current' => 'php8', - 'css' => ['php8.css'], + $languages = []; + foreach (LANGUAGES as $code => $text) { + $languages[] = ['name' => $text, 'selected' => $lang === $code, 'url' => '/releases/8.3/' . $code . '.php']; + } + + \site_header("PHP 8.3 Release Announcement", [ + 'current' => 'php85', + 'css' => ['php85.css'], + 'language_switcher' => $languages, + 'theme_switcher' => true, 'meta_tags' => << @@ -45,28 +52,7 @@ function common_header(string $description): void { ]); } -function language_chooser(string $currentLang): void { - // Print out the form with all the options - echo ' -
-
- - -
-
-'; -} - -function message($code, $language = 'en') +function message($code, $language = 'en'): string { $original = require __DIR__ . '/languages/en.php'; if (($language !== 'en') && file_exists(__DIR__ . '/languages/' . $language . '.php')) { diff --git a/releases/8.3/release.inc b/releases/8.3/release.inc index 0277ce66d6..25caa7f1dd 100644 --- a/releases/8.3/release.inc +++ b/releases/8.3/release.inc @@ -1,7 +1,8 @@ -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-

- - RFC -

-
-
-
PHP < 8.3
-
- -
-
-
-
-
PHP 8.3
-
- -
-
-
-
- -
-

- - RFC -

-
-
-
PHP < 8.3
-
- -
-
-
-
-
PHP 8.3
-
- -
-
-
-
- -
-

- - RFC -

-
-
-
PHP < 8.3
-
- logFile = fopen('/tmp/logfile', 'w'); - } - - protected function taerDown(): void { - fclose($this->logFile); - unlink('/tmp/logfile'); - } -} - -// The log file will never be removed, because the -// method name was mistyped (taerDown vs tearDown). -PHP - - ); ?> -
-
-
-
-
PHP 8.3
-
- logFile = fopen('/tmp/logfile', 'w'); - } - - #[\Override] - protected function taerDown(): void { - fclose($this->logFile); - unlink('/tmp/logfile'); - } -} - -// Fatal error: MyTest::taerDown() has #[\Override] attribute, -// but no matching parent method exists -PHP - ); ?> -
-
-
- -
- -
-
- -
-

- - RFC -

-
-
-
PHP < 8.3
-
- php = clone $this->php; - } -} - -$instance = new Foo(new PHP()); -$cloned = clone $instance; - -// Fatal error: Cannot modify readonly property Foo::$php -PHP - - ); ?> -
-
-
-
-
PHP 8.3
-
- php = clone $this->php; - } -} - -$instance = new Foo(new PHP()); -$cloned = clone $instance; - -$cloned->php->version = '8.3'; -PHP - ); ?> -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.3
-
- -
-
-
-
-
PHP 8.3
-
- -
-
-
-
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.3
-
- -
-
-
-
-
PHP 8.3
-
- getBytesFromString( - 'abcdefghijklmnopqrstuvwxyz0123456789', - 16, + new FeatureComparison( + id: 'dynamic_class_constant_fetch', + title: message('dynamic_class_constant_fetch_title', $lang), + description: '', + links: ['RFC|https://wiki.php.net/rfc/dynamic_class_constant_fetch'], + before: <<<'PHP' + class Foo { + const PHP = 'PHP 8.2'; + } + + $searchableConstant = 'PHP'; + + var_dump(constant(Foo::class . "::{$searchableConstant}")); + PHP, + after: <<<'PHP' + class Foo { + const PHP = 'PHP 8.3'; + } + + $searchableConstant = 'PHP'; + + var_dump(Foo::{$searchableConstant}); + PHP, ), + new FeatureComparison( + id: 'override_attribute', + title: message('override_title', $lang), + description: message('override_description', $lang), + links: ['RFC|https://wiki.php.net/rfc/marking_overriden_methods'], + before: <<<'PHP' + use PHPUnit\Framework\TestCase; + + final class MyTest extends TestCase { + protected $logFile; + + protected function setUp(): void { + $this->logFile = fopen('/tmp/logfile', 'w'); + } + + protected function taerDown(): void { + fclose($this->logFile); + unlink('/tmp/logfile'); + } + } + + // The log file will never be removed, because the + // method name was mistyped (taerDown vs tearDown). + PHP, + after: <<<'PHP' + use PHPUnit\Framework\TestCase; + + final class MyTest extends TestCase { + protected $logFile; + + protected function setUp(): void { + $this->logFile = fopen('/tmp/logfile', 'w'); + } + + #[\Override] + protected function taerDown(): void { + fclose($this->logFile); + unlink('/tmp/logfile'); + } + } + + // Fatal error: MyTest::taerDown() has #[\Override] attribute, + // but no matching parent method exists + PHP, + ), + new FeatureComparison( + id: 'readonly_classes', + title: message('readonly_title', $lang), + description: message('readonly_description', $lang), + links: ['RFC|https://wiki.php.net/rfc/readonly_amendments'], + before: <<<'PHP' + class PHP { + public string $version = '8.2'; + } + + readonly class Foo { + public function __construct( + public PHP $php + ) {} + + public function __clone(): void { + $this->php = clone $this->php; + } + } + + $instance = new Foo(new PHP()); + $cloned = clone $instance; + + // Fatal error: Cannot modify readonly property Foo::$php + PHP, + after: <<<'PHP' + class PHP { + public string $version = '8.2'; + } + + readonly class Foo { + public function __construct( + public PHP $php + ) {} + + public function __clone(): void { + $this->php = clone $this->php; + } + } + + $instance = new Foo(new PHP()); + $cloned = clone $instance; + + $cloned->php->version = '8.3'; + PHP, + ), + new FeatureComparison( + id: 'json_validate', + title: message('json_validate_title', $lang), + description: message('json_validate_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/json_validate', + message('documentation', $lang) . "|/manual/$lang/function.json-validate.php", + ], + before: <<<'PHP' + function json_validate(string $string): bool { + json_decode($string); + + return json_last_error() === JSON_ERROR_NONE; + } + + var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true + PHP, + after: <<<'PHP' + var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true + PHP, + ), + new FeatureComparison( + id: 'randomizer_get_bytes_from_string', + title: message('randomizer_getbytesfromstring_title', $lang), + description: message('randomizer_getbytesfromstring_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/randomizer_additions#getbytesfromstring', + message('documentation', $lang) . "|/manual/$lang/random-randomizer.getbytesfromstring.php", + ], + before: <<<'PHP' + // This function needs to be manually implemented. + function getBytesFromString(string $string, int $length) { + $stringLength = strlen($string); + + $result = ''; + for ($i = 0; $i < $length; $i++) { + // random_int is not seedable for testing, but secure. + $result .= $string[random_int(0, $stringLength - 1)]; + } + + return $result; + } + + $randomDomain = sprintf( + "%s.example.com", + getBytesFromString( + 'abcdefghijklmnopqrstuvwxyz0123456789', + 16, + ), + ); + + echo $randomDomain; + PHP, + after: <<<'PHP' + // A \Random\Engine may be passed for seeding, + // the default is the secure engine. + $randomizer = new \Random\Randomizer(); + + $randomDomain = sprintf( + "%s.example.com", + $randomizer->getBytesFromString( + 'abcdefghijklmnopqrstuvwxyz0123456789', + 16, + ), + ); + + echo $randomDomain; + PHP, + ), + new FeatureComparison( + id: 'randomizer_get_float', + title: message('randomizer_getfloat_nextfloat_title', $lang), + description: message('randomizer_getfloat_nextfloat_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/randomizer_additions#getfloat', + message('documentation', $lang) . "|/manual/$lang/random-randomizer.getfloat.php", + ], + before: <<<'PHP' + // Returns a random float between $min and $max, both including. + function getFloat(float $min, float $max) { + // This algorithm is biased for specific inputs and may + // return values outside the given range. This is impossible + // to work around in userland. + $offset = random_int(0, PHP_INT_MAX) / PHP_INT_MAX; + + return $offset * ($max - $min) + $min; + } + + $temperature = getFloat(-89.2, 56.7); + + $chanceForTrue = 0.1; + // getFloat(0, 1) might return the upper bound, i.e. 1, + // introducing a small bias. + $myBoolean = getFloat(0, 1) < $chanceForTrue; + PHP, + after: <<<'PHP' + $randomizer = new \Random\Randomizer(); + + $temperature = $randomizer->getFloat( + -89.2, + 56.7, + \Random\IntervalBoundary::ClosedClosed, + ); + + $chanceForTrue = 0.1; + // Randomizer::nextFloat() is equivalent to + // Randomizer::getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen). + // The upper bound, i.e. 1, will not be returned. + $myBoolean = $randomizer->nextFloat() < $chanceForTrue; + PHP, + ), + new FeatureComparison( + id: 'command_line_linter', + title: message('command_line_linter_title', $lang), + description: message('command_line_linter_description', $lang), + links: [ + 'PR|https://github.com/php/php-src/issues/10024', + message('documentation', $lang) . "|/manual/$lang/features.commandline.options.php", + ], + before: <<<'CODE' + php -l foo.php bar.php + No syntax errors detected in foo.php + CODE, + after: <<<'CODE' + php -l foo.php bar.php + No syntax errors detected in foo.php + No syntax errors detected in bar.php + CODE, + highlightCode: false, + ), +]; + +echo ReleasePage::getHeroSection( + title: message('main_title', $lang), + subtitle: message('main_subtitle', $lang), + logoSvg: << + SVG, + upgradeNow: message('upgrade_now', $lang), ); -echo $randomDomain; -PHP - ); ?> -
-
-
- -
- -
-
- -
-

- - RFC - -

-
-
-
PHP < 8.3
-
- -
-
-
-
-
PHP 8.3
-
- getFloat( - -89.2, - 56.7, - \Random\IntervalBoundary::ClosedClosed, -); - -$chanceForTrue = 0.1; -// Randomizer::nextFloat() is equivalent to -// Randomizer::getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen). -// The upper bound, i.e. 1, will not be returned. -$myBoolean = $randomizer->nextFloat() < $chanceForTrue; -PHP - ); ?> -
-
-
-
+echo ReleasePage::getFeatureComparisons($comparisons, 'PHP 8.3', 'PHP < 8.3'); -
- -
+?> -
-

- - PR - -

-
-
-
PHP < 8.3
-
- -php -l foo.php bar.php -No syntax errors detected in foo.php - -
+
+
+
+
+

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
-
-
-
PHP 8.3
-
- -php -l foo.php bar.php -No syntax errors detected in foo.php -No syntax errors detected in bar.php - -
+
+

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
- -
- -
- - -
- -
-
-

-
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
- -
-

-
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
-
- - false]); diff --git a/releases/8.4/common.php b/releases/8.4/common.php index 2bcea2a397..72e3e908db 100644 --- a/releases/8.4/common.php +++ b/releases/8.4/common.php @@ -8,11 +8,11 @@ const LANGUAGES = [ 'en' => 'English', + 'es' => 'Español', 'fr' => 'Français', - 'ru' => 'Russian', + 'ru' => 'Русский', 'pt_BR' => 'Brazilian Portuguese', 'nl' => 'Nederlands', - 'es' => 'Spanish', 'tr' => 'Türkçe', 'uk' => 'Українська', 'zh' => '简体中文', @@ -20,15 +20,22 @@ ]; function common_header(string $description): void { - global $MYSITE; + global $MYSITE, $lang; $meta_image_path = \htmlspecialchars( \filter_var($MYSITE . 'images/php8/php_8_4_released.png', \FILTER_VALIDATE_URL)); $meta_description = \htmlspecialchars($description); + $languages = []; + foreach (LANGUAGES as $code => $text) { + $languages[] = ['name' => $text, 'selected' => $lang === $code, 'url' => '/releases/8.4/' . $code . '.php']; + } + \site_header("PHP 8.4 Release Announcement", [ - 'current' => 'php8', - 'css' => ['php8.css'], + 'current' => 'php85', + 'css' => ['php85.css'], + 'language_switcher' => $languages, + 'theme_switcher' => true, 'meta_tags' => << @@ -47,28 +54,7 @@ function common_header(string $description): void { ]); } -function language_chooser(string $currentLang): void { - // Print out the form with all the options - echo ' -
-
- - -
-
-'; -} - -function message($code, $language = 'en') +function message($code, $language = 'en'): string { $original = require __DIR__ . '/languages/en.php'; if (($language !== 'en') && file_exists(__DIR__ . '/languages/' . $language . '.php')) { diff --git a/releases/8.4/release.inc b/releases/8.4/release.inc index d83664812c..192cdd43a5 100644 --- a/releases/8.4/release.inc +++ b/releases/8.4/release.inc @@ -1,6 +1,9 @@ -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-

- - RFC - -

-
-
-
PHP < 8.4
-
- setLanguageCode($languageCode); - $this->setCountryCode($countryCode); - } - - public function getLanguageCode(): string - { - return $this->languageCode; - } - - public function setLanguageCode(string $languageCode): void - { - $this->languageCode = $languageCode; - } - - public function getCountryCode(): string - { - return $this->countryCode; - } - - public function setCountryCode(string $countryCode): void - { - $this->countryCode = strtoupper($countryCode); - } - - public function setCombinedCode(string $combinedCode): void - { - [$languageCode, $countryCode] = explode('_', $combinedCode, 2); - - $this->setLanguageCode($languageCode); - $this->setCountryCode($countryCode); - } - - public function getCombinedCode(): string - { - return \sprintf("%s_%s", $this->languageCode, $this->countryCode); - } -} - -$brazilianPortuguese = new Locale('pt', 'br'); -var_dump($brazilianPortuguese->getCountryCode()); // BR -var_dump($brazilianPortuguese->getCombinedCode()); // pt_BR -PHP - - ); ?> -
-
-
-
-
PHP 8.4
-
- countryCode = strtoupper($countryCode); - } - } - - public string $combinedCode - { - get => \sprintf("%s_%s", $this->languageCode, $this->countryCode); - set (string $value) { - [$this->languageCode, $this->countryCode] = explode('_', $value, 2); - } - } - - public function __construct(string $languageCode, string $countryCode) - { - $this->languageCode = $languageCode; - $this->countryCode = $countryCode; - } -} - -$brazilianPortuguese = new Locale('pt', 'br'); -var_dump($brazilianPortuguese->countryCode); // BR -var_dump($brazilianPortuguese->combinedCode); // pt_BR -PHP - ); ?> -
-
-
-
- -
-
-
-

- - RFC - -

-
-
-
PHP < 8.4
-
- version; - } - - public function increment(): void - { - [$major, $minor] = explode('.', $this->version); - $minor++; - $this->version = "{$major}.{$minor}"; - } -} -PHP - - ); ?> -
-
-
-
-
PHP 8.4
-
- version); - $minor++; - $this->version = "{$major}.{$minor}"; - } -} -PHP - ); ?> -
-
-
-
- -
-
-
-

- - RFC - -

-
-
-
PHP < 8.4
-
- getVersion(); - } - - public function getVersion(): string - { - return '8.3'; - } -} - -$phpVersion = new PhpVersion(); -// No indication that the method is deprecated. -echo $phpVersion->getPhpVersion(); -PHP - - ); ?> -
-
-
-
-
PHP 8.4
-
- getVersion(); - } - - public function getVersion(): string - { - return '8.4'; - } -} - -$phpVersion = new PhpVersion(); -// Deprecated: Method PhpVersion::getPhpVersion() is deprecated since 8.4, use PhpVersion::getVersion() instead -echo $phpVersion->getPhpVersion(); -PHP - ); ?> -
-
-
-
- -
-
-
-

- - RFC - RFC - -

-
-
-
PHP < 8.4
-
- loadHTML( - <<<'HTML' -
-
PHP 8.4 is a feature-rich release!
- -
- HTML, - LIBXML_NOERROR, -); - -$xpath = new DOMXPath($dom); -$node = $xpath->query(".//main/article[not(following-sibling::*)]")[0]; -$classes = explode(" ", $node->className); // Simplified -var_dump(in_array("featured", $classes)); // bool(true) -PHP - - ); ?> -
-
-
-
-
PHP 8.4
-
- -
PHP 8.4 is a feature-rich release!
- - - HTML, - LIBXML_NOERROR, -); - -$node = $dom->querySelector('main > article:last-child'); -var_dump($node->classList->contains("featured")); // bool(true) -PHP - ); ?> -
-
-
-
- -
-
-
-

- - RFC -

-
-
-
PHP < 8.4
-
- 0); // false -PHP - - ); ?> -
-
-
-
-
PHP 8.4
-
- $num2); // false -PHP - ); ?> -
-
-
-
- -
-
-
-

- - RFC -

-
-
-
PHP < 8.4
-
- -
-
-
-
-
PHP 8.4
-
- str_starts_with($value, 'c'), -); - -var_dump($animal); // string(3) "cat" -PHP - ); ?> -
-
-
-
- -
-
-
-

- - RFC -

-
-
-
PHP < 8.4
-
- sqliteCreateFunction( - 'prepend_php', - static fn($string) => "PHP {$string}", +$comparisons = [ + new FeatureComparison( + id: 'property_hooks', + title: message('property_hooks_title', $lang), + description: message('property_hooks_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/property-hooks', + message('documentation', $lang) . "|/manual/$documentation/migration84.new-features.php#migration84.new-features.core.property-hooks", + ], + before: <<<'PHP' + class Locale + { + private string $languageCode; + private string $countryCode; + + public function __construct(string $languageCode, string $countryCode) + { + $this->setLanguageCode($languageCode); + $this->setCountryCode($countryCode); + } + + public function getLanguageCode(): string + { + return $this->languageCode; + } + + public function setLanguageCode(string $languageCode): void + { + $this->languageCode = $languageCode; + } + + public function getCountryCode(): string + { + return $this->countryCode; + } + + public function setCountryCode(string $countryCode): void + { + $this->countryCode = strtoupper($countryCode); + } + + public function setCombinedCode(string $combinedCode): void + { + [$languageCode, $countryCode] = explode('_', $combinedCode, 2); + + $this->setLanguageCode($languageCode); + $this->setCountryCode($countryCode); + } + + public function getCombinedCode(): string + { + return \sprintf("%s_%s", $this->languageCode, $this->countryCode); + } + } + + $brazilianPortuguese = new Locale('pt', 'br'); + var_dump($brazilianPortuguese->getCountryCode()); // BR + var_dump($brazilianPortuguese->getCombinedCode()); // pt_BR + PHP, + after: <<<'PHP' + class Locale + { + public string $languageCode; + + public string $countryCode + { + set (string $countryCode) { + $this->countryCode = strtoupper($countryCode); + } + } + + public string $combinedCode + { + get => \sprintf("%s_%s", $this->languageCode, $this->countryCode); + set (string $value) { + [$this->languageCode, $this->countryCode] = explode('_', $value, 2); + } + } + + public function __construct(string $languageCode, string $countryCode) + { + $this->languageCode = $languageCode; + $this->countryCode = $countryCode; + } + } + + $brazilianPortuguese = new Locale('pt', 'br'); + var_dump($brazilianPortuguese->countryCode); // BR + var_dump($brazilianPortuguese->combinedCode); // pt_BR + PHP, + ), + new FeatureComparison( + id: 'asymmetric_visibility', + title: message('asymmetric_visibility_title', $lang), + description: message('asymmetric_visibility_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/asymmetric-visibility-v2', + message('documentation', $lang) . "|/manual/$documentation/language.oop5.visibility.php#language.oop5.visibility-members-aviz", + ], + before: <<<'PHP' + class PhpVersion + { + private string $version = '8.3'; + + public function getVersion(): string + { + return $this->version; + } + + public function increment(): void + { + [$major, $minor] = explode('.', $this->version); + $minor++; + $this->version = "{$major}.{$minor}"; + } + } + PHP, + after: <<<'PHP' + class PhpVersion + { + public private(set) string $version = '8.4'; + + public function increment(): void + { + [$major, $minor] = explode('.', $this->version); + $minor++; + $this->version = "{$major}.{$minor}"; + } + } + PHP, + ), + new FeatureComparison( + id: 'deprecated_attribute', + title: message('deprecated_attribute_title', $lang), + description: message('deprecated_attribute_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/deprecated_attribute', + message('documentation', $lang) . "|/manual/$documentation/class.deprecated.php", + ], + before: <<<'PHP' + class PhpVersion + { + /** + * @deprecated 8.3 use PhpVersion::getVersion() instead + */ + public function getPhpVersion(): string + { + return $this->getVersion(); + } + + public function getVersion(): string + { + return '8.3'; + } + } + + $phpVersion = new PhpVersion(); + // No indication that the method is deprecated. + echo $phpVersion->getPhpVersion(); + PHP, + after: <<<'PHP' + class PhpVersion + { + #[\Deprecated( + message: "use PhpVersion::getVersion() instead", + since: "8.4", + )] + public function getPhpVersion(): string + { + return $this->getVersion(); + } + + public function getVersion(): string + { + return '8.4'; + } + } + + $phpVersion = new PhpVersion(); + // Deprecated: Method PhpVersion::getPhpVersion() is deprecated since 8.4, use PhpVersion::getVersion() instead + echo $phpVersion->getPhpVersion(); + PHP, + ), + new FeatureComparison( + id: 'dom_additions_html5', + title: message('dom_additions_html5_title', $lang), + description: message('dom_additions_html5_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/dom_additions_84', + 'RFC|https://wiki.php.net/rfc/domdocument_html5_parser', + message('documentation', $lang) . "|/manual/$documentation/migration84.new-features.php#migration84.new-features.dom", + ], + before: <<<'PHP' + $dom = new DOMDocument(); + $dom->loadHTML( + <<<'HTML' +
+
PHP 8.4 is a feature-rich release!
+ +
+ HTML, + LIBXML_NOERROR, + ); + + $xpath = new DOMXPath($dom); + $node = $xpath->query(".//main/article[not(following-sibling::*)]")[0]; + $classes = explode(" ", $node->className); // Simplified + var_dump(in_array("featured", $classes)); // bool(true) + PHP, + after: <<<'PHP' + $dom = Dom\HTMLDocument::createFromString( + <<<'HTML' +
+
PHP 8.4 is a feature-rich release!
+ +
+ HTML, + LIBXML_NOERROR, + ); + + $node = $dom->querySelector('main > article:last-child'); + var_dump($node->classList->contains("featured")); // bool(true) + PHP, + ), + new FeatureComparison( + id: 'bcmath', + title: message('bcmath_title', $lang), + description: message('bcmath_description', $lang), + links: ['RFC|https://wiki.php.net/rfc/support_object_type_in_bcmath'], + before: <<<'PHP' + $num1 = '0.12345'; + $num2 = '2'; + $result = bcadd($num1, $num2, 5); + + echo $result; // '2.12345' + var_dump(bccomp($num1, $num2) > 0); // false + PHP, + after: <<<'PHP' + use BcMath\Number; + + $num1 = new Number('0.12345'); + $num2 = new Number('2'); + $result = $num1 + $num2; + + echo $result; // '2.12345' + var_dump($num1 > $num2); // false + PHP, + ), + new FeatureComparison( + id: 'new_array_find', + title: message('new_array_find_title', $lang), + description: message('new_array_find_description', $lang), + links: ['RFC|https://wiki.php.net/rfc/array_find'], + before: <<<'PHP' + $animal = null; + foreach (['dog', 'cat', 'cow', 'duck', 'goose'] as $value) { + if (str_starts_with($value, 'c')) { + $animal = $value; + break; + } + } + + var_dump($animal); // string(3) "cat" + PHP, + after: <<<'PHP' + $animal = array_find( + ['dog', 'cat', 'cow', 'duck', 'goose'], + static fn(string $value): bool => str_starts_with($value, 'c'), + ); + + var_dump($animal); // string(3) "cat" + PHP, + ), + new FeatureComparison( + id: 'pdo_driver_specific_subclasses', + title: message('pdo_driver_specific_subclasses_title', $lang), + description: message('pdo_driver_specific_subclasses_description', $lang), + links: ['RFC|https://wiki.php.net/rfc/pdo_driver_specific_subclasses'], + before: <<<'PHP' + $connection = new PDO( + 'sqlite:foo.db', + $username, + $password, + ); // object(PDO) + + $connection->sqliteCreateFunction( + 'prepend_php', + static fn($string) => "PHP {$string}", + ); + + $connection->query('SELECT prepend_php(version) FROM php'); + PHP, + after: <<<'PHP' + $connection = PDO::connect( + 'sqlite:foo.db', + $username, + $password, + ); // object(Pdo\Sqlite) + + $connection->createFunction( + 'prepend_php', + static fn($string) => "PHP {$string}", + ); // Does not exist on a mismatching driver. + + $connection->query('SELECT prepend_php(version) FROM php'); + PHP, + ), + new FeatureComparison( + id: 'new_without_parentheses', + title: message('new_without_parentheses_title', $lang), + description: message('new_without_parentheses_description', $lang), + links: [ + 'RFC|https://wiki.php.net/rfc/new_without_parentheses', + message('documentation', $lang) . "|/manual/$documentation/migration84.new-features.php#migration84.new-features.core.new-chaining", + ], + before: <<<'PHP' + class PhpVersion + { + public function getVersion(): string + { + return 'PHP 8.3'; + } + } + + var_dump((new PhpVersion())->getVersion()); + PHP, + after: <<<'PHP' + class PhpVersion + { + public function getVersion(): string + { + return 'PHP 8.4'; + } + } + + var_dump(new PhpVersion()->getVersion()); + PHP, + ), +]; + +echo ReleasePage::getHeroSection( + title: message('main_title', $lang), + subtitle: message('main_subtitle', $lang), + logoSvg: << + SVG, + upgradeNow: message('upgrade_now', $lang), ); -$connection->query('SELECT prepend_php(version) FROM php'); -PHP - ); ?> -
-
-
-
-
PHP 8.4
-
- createFunction( - 'prepend_php', - static fn($string) => "PHP {$string}", -); // Does not exist on a mismatching driver. - -$connection->query('SELECT prepend_php(version) FROM php'); -PHP - ); ?> -
-
-
-
- -
-
-
-

- - RFC - -

-
-
-
PHP < 8.4
-
- getVersion()); -PHP +?> - ); ?> -
+
+
+
+
+

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
-
-
-
PHP 8.4
-
- getVersion()); -PHP - ); ?> -
+
+

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
-
- -
-
- -
- -
-
-

-
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
- -
-

-
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
-
- - false]); diff --git a/releases/8.5/common.php b/releases/8.5/common.php index 2162fde427..c2dc3c3f45 100644 --- a/releases/8.5/common.php +++ b/releases/8.5/common.php @@ -54,7 +54,7 @@ function common_header(string $description): void { ]); } -function message($code, $language = 'en', array $interpolations = []) +function message($code, $language = 'en', array $interpolations = []): string { $original = require __DIR__ . '/languages/en.php'; if (($language !== 'en') && file_exists(__DIR__ . '/languages/' . $language . '.php')) { diff --git a/releases/8.5/release.inc b/releases/8.5/release.inc index 05447e3385..8ed4647e54 100644 --- a/releases/8.5/release.inc +++ b/releases/8.5/release.inc @@ -1,5 +1,7 @@ - -
- - - - - - - - - - - -
-
- - - - -
- - -

- - -
- - -
-
-
- + SVG, + upgradeNow: message('upgrade_now', $lang), + whatsNew: message('whats_new', $lang), + released: message('released', $lang), +); +?>
- -
-
-

- -
- -
-
-
-
-
- -
- -
- -
- -
-
-
- PHP 8.5 - - RFC -
- -
- getHost()); -// string(7) "php.net" -PHP - ); ?> -
-
-
-
- - -
-
-

- -
- -
-
-
-
-
- -
- -
- -
- -
-
-
- PHP 8.5 - - RFC -
- -
- trim(...) - |> (fn($str) => str_replace(' ', '-', $str)) - |> (fn($str) => str_replace('.', '', $str)) - |> strtolower(...); - -var_dump($slug); -// string(15) "php-85-released" -PHP - ); ?> -
-
-
-
- - -
-
-

- -
- -
-
-
-
-
- -
- -
- withAlpha(128); -PHP - ); ?> -
- -
-
-
- PHP 8.5 - - RFC -
- -
- $alpha, - ]); - } -} - -$blue = new Color(79, 91, 147); -$transparentBlue = $blue->withAlpha(128); -PHP - ); ?> -
-
-
-
- - -
-
-

- -
- -
-
-
-
-
- -
- -
- -
- -
-
-
- PHP 8.5 - - RFC - -
- -
- -
-
-
-
- - -
-
-

- -
- -
-
-
-
-
- -
- -
- -
- -
-
-
- PHP 8.5 - - RFC - RFC -
- -
- user === $post->getAuthor(); - })] - public function update( - Request $request, - Post $post, - ): Response { - // ... - } -} -PHP - ); ?> -
-
-
-
+ - -
-
-

- -
- -
-
-
-
-
- -
- -
- -
- -
-
-
- PHP 8.5 - - RFC - RFC - -
- -
- -
-
-
-
- - -
-
-

- -
- -
-
-
-
-
- -
- -
- -
- -
-
-
- PHP 8.5 - - RFC -
- -
- -
-
-
-
- -
@@ -696,17 +393,17 @@ PHP
  • setcookie()', - 'setrawcookie()', - ]) ?>
  • + 'setcookie()', + 'setrawcookie()', + ]) ?>
  • get_error_handler()', - 'get_exception_handler()', - ]) ?>
  • + 'get_error_handler()', + 'get_exception_handler()', + ]) ?>
  • Dom\Element::getElementsByClassName()', - 'Dom\Element::insertAdjacentHTML()', - ]) ?>
  • + 'Dom\Element::getElementsByClassName()', + 'Dom\Element::insertAdjacentHTML()', + ]) ?>
  • grapheme_levenshtein()']) ?>
  • #[\DelayedTargetValidation]']) ?>
  • @@ -715,23 +412,23 @@ PHP

    - - - - - - - - - - - - - - - - - - Created as part of + + The PHP Foundation Design Contest. +

    + HTML, +); + site_footer(['footer' => false]); diff --git a/src/Themes/FeatureComparison.php b/src/Themes/FeatureComparison.php new file mode 100644 index 0000000000..f5a7095099 --- /dev/null +++ b/src/Themes/FeatureComparison.php @@ -0,0 +1,18 @@ + + + + + $released +
    + HTML; + } + + $featuresLink = ''; + if ($whatsNew !== '') { + $featuresLink = '' . $whatsNew . ''; + } + + if (!str_starts_with($subtitle, '

    ')) { + $subtitle = '

    ' . $subtitle . '

    '; + } + + return << + + + + + + + + + + + + + + +
    + $releasedBadge + $logoSvg + +

    $title

    + $subtitle + +
    + $featuresLink + $upgradeNow +
    +
    +
    + HTML; + } + + public static function getPrefooter(string $title, string $upgradeNow, string $description, string $extraCredit = ''): string + { + $currentYear = date('Y'); + + return << + + + +
    + + + + + + + + + + + + + + + + HTML; + } + + /** + * @param FeatureComparison[] $comparisons + */ + public static function getFeatureComparisons(array $comparisons, string $version, string $previousVersion, string $newText = ''): string + { + $html = ''; + $lastKey = array_key_last($comparisons); + + foreach ($comparisons as $key => $feature) { + $html .= self::getFeatureComparison( + feat: $feature, + version: $version, + previousVersion: $previousVersion, + isLast: $key === $lastKey, + newText: $newText, + ) . "\n"; + } + + return $html; + } + + private static function getFeatureComparison( + FeatureComparison $feat, + string $version, + string $previousVersion, + bool $isLast, + string $newText = '', + ): string { + $codeBlock = self::getCodeBlock($feat->before, $feat->after, $version, $previousVersion, $feat->highlightCode, $newText, $feat->links); + $code2Block = ''; + + if ($feat->after2 !== '') { + $code2Block = self::getCodeBlock($feat->before2, $feat->after2, $version, $previousVersion, $feat->highlightCode); + } + + $last = $isLast ? ' last' : ''; + + $description = $feat->description; + if (!str_starts_with($description, '

    ')) { + $description = '

    ' . $description . '

    '; + } + + return << +
    +

    {$feat->title}

    + $description +
    + $codeBlock + $code2Block +
    + HTML; + } + + private static function getCodeBlock( + string $beforeCode, + string $afterCode, + string $version, + string $previousVersion, + bool $highlightCode, + string $newText = '', + array $links = [], + ): string { + $links = array_map(self::getRfcLink(...), $links); + $linksHtml = implode("\n", $links); + + $newBadge = ''; + if ($newText !== '') { + $newBadge = '' . htmlspecialchars($newText) . ''; + } + + $noBeforeCode = $beforeCode === ''; + + if ($highlightCode) { + $beforeCode = highlight_php_trimmed($beforeCode, true); + $afterCode = highlight_php_trimmed($afterCode, true); + } else { + $beforeCode = "
    $beforeCode
    "; + $afterCode = "
    $afterCode
    "; + } + + $version = htmlspecialchars($version); + $previousVersion = htmlspecialchars($previousVersion); + $copyCodeButton = self::getCopyCodeButton(); + + if ($noBeforeCode) { + $codeMarkup = << +
    +
    + $version + $newBadge + $linksHtml +
    + $copyCodeButton +
    + $afterCode + + HTML; + } else { + $codeMarkup = << +
    +
    + $previousVersion +
    + $copyCodeButton +
    + $beforeCode + + +
    +
    +
    + $version + $newBadge + $linksHtml +
    + $copyCodeButton +
    + $afterCode +
    + HTML; + } + + $singleClass = $noBeforeCode ? ' single' : ''; + return << +
    + $codeMarkup +
    + + HTML; + } + + private static function getRfcLink(string $namedLink): string + { + // Use 'title|link' string since multiple links may have the same title + preg_match('!^((.+)\|)?(.+)$!', $namedLink, $matches); + $link = $matches[3]; + $title = $matches[2] ?: 'Link'; + + return '' . $title . ' '; + } + + private static function getCopyCodeButton(): string + { + return <<<'HTML' + + HTML; + } +} diff --git a/styles/php8.css b/styles/php8.css deleted file mode 100644 index 6baf25b9d4..0000000000 --- a/styles/php8.css +++ /dev/null @@ -1,444 +0,0 @@ -#layout-content:only-child { - width: 100% !important; -} - -.php8-section { - padding: 96px 1.5rem; - margin: 0 -1.5rem; -} - -.php8-section_dark { - background-color: var(--dark-blue-color); - /* Trick for darkening the background color, there is no gradient. - * Can be refactored once color-mix becomes widely supported. - * See https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix */ - background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)); - color: #fff; -} - -.php8-section__content { - width: 820px; - max-width: 100%; - margin: 0 auto; -} - -.php8-section_header .php8-section__content { - width: 1050px; -} - -.php8-section_dark * { - color: #fff; -} - -.php8-section_light { - background-color: #fff; -} - -.php8-section_header { - position: relative; - padding-top: 64px; - margin-top: -1.5rem; - font-family: Helvetica, Arial, sans-serif; -} - -.php8-section_footer { - margin-bottom: -1.5rem; - font-family: Helvetica, Arial, sans-serif; -} - -.php8-section img { - max-width: 100%; -} - -.php8-logo { - vertical-align: middle; -} - -.php8-logo img { - max-width: 90%; -} - -.php8-title { - margin-top: 16px; - font-size: 60px; - font-weight: 900; - font-stretch: normal; - font-style: normal; - line-height: 1.07; - letter-spacing: -1.5px; -} - -@media (max-width: 480px) { - .php8-title { - font-size: 50px; - } -} - -.php8-subtitle { - margin-top: 48px; - font-size: 28px; - font-weight: 300; - font-stretch: normal; - font-style: normal; - line-height: 1.43; - letter-spacing: normal; - text-align: center; -} - -@media (max-width: 480px) { - .php8-subtitle { - font-size: 24px; - } -} - -.php8-h2 { - display: inline-block; - font-size: 31px; - font-weight: bold; - font-stretch: normal; - font-style: normal; - line-height: 1.29; - letter-spacing: -0.5px; - overflow: visible; -} - -.php8-h2::after, -.php8-h3::after { - display: none; -} - -.php8-h2_margin-top { - margin-top: 48px; -} - -.php8-section_dark .php8-h2 { - display: block; - color: #fff; -} - -.php8-button-wrapper { - margin-top: 48px; -} - -.php8-button { - display: inline-block; - padding: 16px 46px; - border-radius: 30px; - border: none; - background-color: var(--dark-blue-color); - color: #fff !important; - text-decoration: none !important; - font-size: 20px; - font-weight: bold; - font-stretch: normal; - font-style: normal; - line-height: 1.4; - letter-spacing: normal; - text-align: center; -} - -@media (max-width: 640px) { - .php8-button { - padding: 16px 36px; - } -} - -.php8-button_light { - background-color: #fff !important; - color: #27282c !important; -} - -.php8-footer__content { - margin-top: 64px; - text-align: left; - font-size: 15px; - font-weight: normal; - font-stretch: normal; - font-style: normal; - line-height: 1.6; - letter-spacing: normal; -} - -#layout-content .php8-section_dark a:link, -#layout-content .php8-section_dark a:visited { - color: #fff; - transition: opacity 0.2s; -} - -#layout-content .php8-section_dark a:hover, -#layout-content .php8-section_dark a:focus { - color: #fff; - border-color: #fff; - opacity: 0.85; -} - -.php8-section p:last-child { - margin-bottom: 0; -} - -.display-block-lg { - display: block; -} -.display-none-lg { - display: none; -} - -@media (max-width: 1000px) { - .display-block-md { - display: block; - } - .display-none-md { - display: none; - } -} - -@media (max-width: 640px) { - .display-block-sm { - display: block; - } - .display-none-sm { - display: none; - } -} - -.php8-rfc { - font-size: 15px; - font-weight: normal; - line-height: 1.6; - vertical-align: middle; - color: var(--dark-blue-color); - border-bottom-color: currentColor; -} - -.php8-compare ~ .php8-compare { - margin-top: 58px; -} - -.php8-compare__main { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; -} - -@media (max-width: 810px) { - .php8-compare__main { - display: block; - } -} - -.php8-compare__block { - position: relative; - -ms-flex-preferred-size: calc((100% - 68px)/2); - flex-basis: calc((100% - 68px)/2); - text-align: left; -} - -.php8-compare__label { - position: absolute; - top: 12px; - left: 12px; - padding: 6px 16px 4px; - border-radius: 4px; - font-size: 12px; - font-weight: normal; - font-stretch: normal; - font-style: normal; - line-height: 1.33; - letter-spacing: normal; - text-align: center; - color: var(--background-color); - background-color: var(--foreground-color); -} - -.php8-compare__label_new { - background-color: var(--dark-blue-color); - color: #fff; -} - -.php8-compare__content { - display: inline-block; - max-width: 820px; - margin-top: 24px; - text-align: left; -} - -.php8-compare__content--spaced { - margin-bottom: 24px; -} - -.php8-compare__content--block { - display: block; -} - -@media (max-width: 810px) { - .php8-compare__content { - display: block; - } -} - -.php8-h2 code, -.php8-compare__content code { - color: rgba(39, 40, 44, 0.7); - background-color: rgba(39, 40, 44, 0.05); - padding: .2em .4em; - font-size: 85%; - border-radius: 6px; -} - -.php8-code { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - width: 100%; - height: 100%; - padding: 50px 40px 38px !important; - box-sizing: border-box; - margin: 0 !important; -} - -.align-start { - align-items: start; -} - -@media (max-width: 768px) { - .php8-code { - padding-left: 12px !important; - padding-right: 12px !important; - } -} - -.php8-compare__arrow { - height: 36px; - width: 20px; - margin: auto; - background: url("/images/php8/icon_arrow.svg") scroll no-repeat center center / contain transparent; -} - -@media (max-width: 810px) { - .php8-compare__arrow { - margin-top: 10px; - margin-bottom: 10px; - transform: rotate(90deg); - } -} - -.php8-section li ~ li { - margin-top: 24px; -} - -.php8-columns { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; -} - -@media (max-width: 768px) { - .php8-columns { - display: block; - } -} - -.php8-column { - -ms-flex-preferred-size: calc((100% - 68px)/2); - flex-basis: calc((100% - 68px)/2); -} - -@media (max-width: 768px) { - .php8-column { - width: 100%; - } -} - -.php8-h2 .genanchor { - display: none; - float: left; - height: 30px; - width: 30px; - margin-top: 4px; - margin-left: -30px; - background: url("/images/php8/anchor.svg") scroll no-repeat left center / 21px 16px transparent; - text-decoration: none; - border-bottom: none; - font-size: 0; -} - -.php8-h2:hover .genanchor { - display: block; -} - -.php8-chart__table { - margin: 16px 0; -} - -.page-tools { - position: absolute; - top: 28px; - right: 28px; -} - -@media (max-width: 1000px) { - .page-tools { - top: 16px; - right: 16px; - } -} - -@media (max-width: 480px) { - .page-tools { - top: 0; - } -} - -.change-language { - font-size: 15px; - color: #fff; - line-height: 1.6; -} - -.change-language label { - display: inline-block; - margin-left: 16px; - vertical-align: middle; -} - -@media (max-width: 480px) { - .change-language label { - margin-top: 8px; - } -} - -.change-language select { - min-width: 178px; - margin-left: 16px; - vertical-align: middle; -} - -@media (max-width: 480px) { - .change-language select { - margin-top: 8px; - } -} - -.change-language select, -.change-language option { - padding: 4px 5px; - color: rgba(39, 40, 44, 0.7); - line-height: 1.33; -} - -.example-contents-full { - width: 100%; - position: relative; -} diff --git a/styles/php85.css b/styles/php85.css index 1422c8f75c..caf32f635d 100644 --- a/styles/php85.css +++ b/styles/php85.css @@ -1828,6 +1828,10 @@ header nav { padding: calc(var(--spacing) * 5); grid-template-columns:repeat(2, minmax(0, 1fr)) } + + .before-and-after-code.single { + grid-template-columns: minmax(0, 1fr) + } } .before-and-after-code:where(.dark,.dark *) { @@ -1886,7 +1890,8 @@ header nav { } } -.before-and-after-title-and-description p { +.before-and-after-title-and-description p, +.before-and-after-title-and-description ul { color: var(--color-gray-600); text-align: left; } @@ -1898,12 +1903,14 @@ header nav { } } -.before-and-after-title-and-description p:where(.dark,.dark *) { +.before-and-after-title-and-description p:where(.dark,.dark *), +.before-and-after-title-and-description ul:where(.dark,.dark *) { color: #fffc } @supports (color:color-mix(in lab, red, red)) { - .before-and-after-title-and-description p:where(.dark,.dark *) { + .before-and-after-title-and-description p:where(.dark,.dark *), + .before-and-after-title-and-description ul:where(.dark,.dark *) { color: color-mix(in oklab, var(--color-white) 80%, transparent) } } @@ -1925,6 +1932,13 @@ header nav { font-size: var(--text-sm); line-height: var(--tw-leading, var(--text-sm--line-height)) } +.features-col a code { + font-size: inherit; + line-height: inherit +} +.before-and-after-title-and-description h2 > code { + font-size: 87%; +} .before-and-after-title-and-description code:where(.dark,.dark *) { background-color: #0003 @@ -2173,30 +2187,38 @@ header nav { } } -.release-notes ul { +.release-notes ul, +.before-and-after-title-and-description ul { margin-left: calc(var(--spacing) * 4); list-style-type: disc } -:where(.release-notes ul>:not(:last-child)) { +:where(.release-notes ul>:not(:last-child)), +:where(.before-and-after-title-and-description ul>:not(:last-child)) { --tw-space-y-reverse: 0; margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse)); margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse))) } -.release-notes ul { +.release-notes ul, +.before-and-after-title-and-description ul { font-size: var(--text-sm); line-height: var(--tw-leading, var(--text-sm--line-height)); overflow-wrap: break-word } @media (min-width: 64rem) { - .release-notes ul { + .release-notes ul, + .before-and-after-title-and-description ul { font-size: var(--text-base); line-height: var(--tw-leading, var(--text-base--line-height)) } } +.release-notes-grid div > ul:not(:last-of-type) { + margin-bottom: calc(var(--spacing) * 8); +} + .release-notes code { border-radius: var(--radius-md); background-color: #e4e4e780 @@ -2255,6 +2277,10 @@ header nav { color: var(--color-red-400) } +.release-notes h3 { + margin-bottom: calc(var(--spacing) * 2); +} + .release-notes-grid-container { margin-inline: auto; margin-top: calc(var(--spacing) * -2); @@ -2262,6 +2288,10 @@ header nav { padding-inline: calc(var(--spacing) * 4) } +.release-notes-grid-container + .release-notes-grid-container { + margin-top: calc(var(--spacing) * 8) +} + @media (min-width: 64rem) { .release-notes-grid-container { padding-inline: calc(var(--spacing) * 8) @@ -2276,17 +2306,16 @@ header nav { .release-notes-grid div { border-radius: var(--radius-3xl); - background-color: #00000008 + background-color: #00000008; + padding: calc(var(--spacing) * 6); } -@supports (color:color-mix(in lab, red, red)) { - .release-notes-grid div { - background-color: color-mix(in oklab, var(--color-black) 3%, transparent) - } +.release-notes-grid div.chart-table:where(.dark,.dark *) { + background-color: #ffffff59; } -.release-notes-grid div { - padding: calc(var(--spacing) * 6) +.release-notes-grid div:where(.dark,.dark *) { + background-color: #ffffff08 } @media (min-width: 48rem) { @@ -2295,20 +2324,42 @@ header nav { } } -.release-notes-grid div:where(.dark,.dark *) { - background-color: #ffffff08 +.release-notes-grid div.chart-table { + margin: calc(var(--spacing) * 4) 0; + padding: calc(var(--spacing) * 4); + border-radius: var(--radius-xl); } @supports (color:color-mix(in lab, red, red)) { + .release-notes-grid div { + background-color: color-mix(in oklab, var(--color-black) 3%, transparent); + } .release-notes-grid div:where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-white) 3%, transparent) + background-color: color-mix(in oklab, var(--color-white) 3%, transparent); } + .release-notes-grid div.chart-table:where(.dark,.dark *) { + background-color: color-mix(in oklab, var(--color-white) 80%, transparent); + } +} + +.release-notes-grid div.center { + background-color: transparent; + border-radius: 0; + padding: 0; +} + +.release-notes-grid div.center:where(.dark,.dark *) { + background-color: transparent; } @media (min-width: 64rem) { .release-notes-grid div:first-of-type { grid-column: span 6/span 6 } + + .release-notes-grid div:only-child { + grid-column: span 12/span 12 + } } .release-notes-grid div:nth-of-type(2) { From b6e189891020ba632d00d546351774391e5b132d Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Wed, 10 Jun 2026 09:14:59 -0500 Subject: [PATCH 3/5] Clean up dead and duplicate styles --- styles/php85.css | 1381 ++-------------------------------------------- 1 file changed, 41 insertions(+), 1340 deletions(-) diff --git a/styles/php85.css b/styles/php85.css index caf32f635d..a9339c08b4 100644 --- a/styles/php85.css +++ b/styles/php85.css @@ -113,60 +113,20 @@ code[class*=language-], pre[class*=language-] { @layer properties { @supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) { *, :before, :after, ::backdrop { - --tw-blur: initial; - --tw-brightness: initial; - --tw-contrast: initial; - --tw-grayscale: initial; - --tw-hue-rotate: initial; - --tw-invert: initial; - --tw-opacity: initial; - --tw-saturate: initial; - --tw-sepia: initial; - --tw-drop-shadow: initial; - --tw-drop-shadow-color: initial; - --tw-drop-shadow-alpha: 100%; - --tw-drop-shadow-size: initial; --tw-shadow: 0 0 #0000; - --tw-shadow-color: initial; - --tw-shadow-alpha: 100%; --tw-inset-shadow: 0 0 #0000; - --tw-inset-shadow-color: initial; - --tw-inset-shadow-alpha: 100%; --tw-ring-color: initial; --tw-ring-shadow: 0 0 #0000; - --tw-inset-ring-color: initial; --tw-inset-ring-shadow: 0 0 #0000; --tw-ring-inset: initial; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 #0000; - --tw-backdrop-blur: initial; - --tw-backdrop-brightness: initial; - --tw-backdrop-contrast: initial; - --tw-backdrop-grayscale: initial; - --tw-backdrop-hue-rotate: initial; - --tw-backdrop-invert: initial; - --tw-backdrop-opacity: initial; - --tw-backdrop-saturate: initial; - --tw-backdrop-sepia: initial; --tw-border-style: solid; --tw-outline-style: solid; - --tw-gradient-position: initial; - --tw-gradient-from: #0000; - --tw-gradient-via: #0000; - --tw-gradient-to: #0000; - --tw-gradient-stops: initial; - --tw-gradient-via-stops: initial; - --tw-gradient-from-position: 0%; - --tw-gradient-via-position: 50%; - --tw-gradient-to-position: 100%; - --tw-duration: initial; - --tw-ease: initial; - --tw-font-weight: initial; --tw-leading: initial; --tw-space-y-reverse: 0; --tw-space-x-reverse: 0; - --tw-tracking: initial } } } @@ -234,22 +194,13 @@ code[class*=language-], pre[class*=language-] { --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; - --tracking-tight: -.025em; --leading-relaxed: 1.625; - --leading-loose: 2; --radius-md: .375rem; --radius-lg: .5rem; --radius-xl: .75rem; --radius-2xl: 1rem; --radius-3xl: 1.5rem; --radius-4xl: 2rem; - --ease-in-out: cubic-bezier(.4, 0, .2, 1); - --blur-xs: 4px; - --blur-md: 12px; - --default-transition-duration: .15s; - --default-transition-timing-function: cubic-bezier(.4, 0, .2, 1); - --default-font-family: var(--font-sans); - --default-mono-font-family: var(--font-mono) } } @@ -272,9 +223,7 @@ code[class*=language-], pre[class*=language-] { -webkit-text-size-adjust: 100%; tab-size: 4; line-height: 1.5; - font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); - font-feature-settings: var(--default-font-feature-settings, normal); - font-variation-settings: var(--default-font-variation-settings, normal); + font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); -webkit-tap-highlight-color: transparent } @@ -285,7 +234,6 @@ code[class*=language-], pre[class*=language-] { } abbr:where([title]) { - -webkit-text-decoration: underline dotted; text-decoration: underline dotted } @@ -296,9 +244,6 @@ code[class*=language-], pre[class*=language-] { a { color: inherit; - -webkit-text-decoration: inherit; - -webkit-text-decoration: inherit; - -webkit-text-decoration: inherit; text-decoration: inherit } @@ -307,9 +252,7 @@ code[class*=language-], pre[class*=language-] { } code, kbd, samp, pre { - font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); - font-feature-settings: var(--default-mono-font-feature-settings, normal); - font-variation-settings: var(--default-mono-font-variation-settings, normal); + font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); font-size: 1em } @@ -398,84 +341,6 @@ code[class*=language-], pre[class*=language-] { margin-inline-end: 4px } - ::placeholder { - opacity: 1 - } - - @supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px) { - ::placeholder { - color: currentColor - } - - @supports (color:color-mix(in lab, red, red)) { - ::placeholder { - color: color-mix(in oklab, currentcolor 50%, transparent) - } - } - }textarea { - resize: vertical - } - - ::-webkit-search-decoration { - -webkit-appearance: none - } - - ::-webkit-date-and-time-value { - min-height: 1lh; - text-align: inherit - } - - ::-webkit-datetime-edit { - display: inline-flex - } - - ::-webkit-datetime-edit-fields-wrapper { - padding: 0 - } - - ::-webkit-datetime-edit { - padding-block: 0 - } - - ::-webkit-datetime-edit-year-field { - padding-block: 0 - } - - ::-webkit-datetime-edit-month-field { - padding-block: 0 - } - - ::-webkit-datetime-edit-day-field { - padding-block: 0 - } - - ::-webkit-datetime-edit-hour-field { - padding-block: 0 - } - - ::-webkit-datetime-edit-minute-field { - padding-block: 0 - } - - ::-webkit-datetime-edit-second-field { - padding-block: 0 - } - - ::-webkit-datetime-edit-millisecond-field { - padding-block: 0 - } - - ::-webkit-datetime-edit-meridiem-field { - padding-block: 0 - } - - ::-webkit-calendar-picker-indicator { - line-height: 1 - } - - :-moz-ui-invalid { - box-shadow: none - } button, input:where([type=button],[type=reset],[type=submit]) { appearance: button @@ -485,26 +350,13 @@ code[class*=language-], pre[class*=language-] { appearance: button } - ::-webkit-inner-spin-button { - height: auto - } - - ::-webkit-outer-spin-button { - height: auto - } [hidden]:where(:not([hidden=until-found])) { display: none !important } } -@layer components; - @layer utilities { - .visible { - visibility: visible - } - .sr-only { clip-path: inset(50%); white-space: nowrap; @@ -516,38 +368,6 @@ code[class*=language-], pre[class*=language-] { position: absolute; overflow: hidden } - - .static { - position: static - } - - .block { - display: block - } - - .hidden { - display: none - } - - .resize { - resize: both - } - - .opacity-0 { - opacity: 0 - } - - .opacity-25 { - opacity: .25 - } - - .opacity-40 { - opacity: .4 - } - - .filter { - filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,) - } } body { @@ -575,47 +395,6 @@ a { } } -header { - top: calc(var(--spacing) * 0); - z-index: 50; - background-color: #fffc; - width: 100%; - position: sticky -} - -@supports (color:color-mix(in lab, red, red)) { - header { - background-color: color-mix(in oklab, var(--color-white) 80%, transparent) - } -} - -header { - padding-block: calc(var(--spacing) * 3); - --tw-shadow: 0 1px var(--tw-shadow-color, #0000000d); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - --tw-backdrop-blur: blur(var(--blur-md)); - -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,) -} - -header:where(.dark,.dark *) { - background-color: oklab(24.2643% .00402537 -.0554365/.5) -} - -header nav { - width: 100%; - max-width: var(--container-7xl); - padding-inline: calc(var(--spacing) * 6); - margin-inline: auto; - display: flex; - position: relative -} - -@media (min-width: 64rem) { - header nav { - padding-inline: calc(var(--spacing) * 8) - } -} .header-logo { margin-right: calc(var(--spacing) * 6) @@ -743,10 +522,8 @@ header nav { line-height: var(--tw-leading, var(--text-base--line-height)); white-space: nowrap; color: var(--color-gray-500); - outline-style: var(--tw-outline-style); outline-offset: calc(1px * -1); - outline-width: 1px; - outline-color: var(--color-gray-300) + outline: var(--color-gray-300) var(--tw-outline-style) 1px; } .header-button-search:focus { @@ -908,10 +685,8 @@ header nav { .header-light-dark-mode-button { padding-inline: calc(var(--spacing) * 2.5); color: var(--color-gray-500); - outline-style: var(--tw-outline-style); outline-offset: calc(1px * -1); - outline-width: 1px; - outline-color: var(--color-gray-300) + outline: var(--color-gray-300) var(--tw-outline-style) 1px; } .header-light-dark-mode-button:focus { @@ -1020,9 +795,7 @@ header nav { } #mobile-menu-button:focus-visible { - outline-style: var(--tw-outline-style); - outline-width: 2px; - outline-color: var(--color-white) + outline: var(--color-white) var(--tw-outline-style) 2px; } #mobile-menu-button:where(.dark,.dark *) { @@ -1064,7 +837,6 @@ header nav { top: calc(var(--spacing) * .5); z-index: calc(10 * -1); width: 100%; - height: 100%; height: calc(var(--spacing) * 150); stroke: #18181b1a; position: absolute; @@ -1090,12 +862,7 @@ header nav { .hero-content { max-width: var(--container-4xl); - --tw-gradient-position: at 50% 50%; - background-image: radial-gradient(var(--tw-gradient-stops, at 50% 50%)); - --tw-gradient-from: var(--color-white); - --tw-gradient-to: transparent; - --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); - --tw-gradient-to-position: 65%; + background-image: radial-gradient(at 50% 50%, var(--color-white), transparent 65%); padding-inline: calc(var(--spacing) * 4); text-align: center; margin-inline: auto @@ -1114,8 +881,7 @@ header nav { } .hero-content:where(.dark,.dark *) { - --tw-gradient-from: #181d3a; - --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)) + background-image: radial-gradient(at 50% 50%, #181d3a, transparent 65%) } .hero .hero-bg { @@ -1127,12 +893,8 @@ header nav { height: 100%; transition-property: opacity; opacity: .35; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - --tw-duration: .5s; - --tw-ease: var(--ease-in-out); transition-duration: .5s; - transition-timing-function: var(--ease-in-out); + transition-timing-function: cubic-bezier(.4, 0, .2, 1); -webkit-user-select: none; user-select: none; position: absolute @@ -1169,16 +931,6 @@ header nav { } } -.hero-badge:where(.dark,.dark *) { - background-color: #0003 -} - -@supports (color:color-mix(in lab, red, red)) { - .hero-badge:where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-black) 20%, transparent) - } -} - .hero-badge:where(.dark,.dark *) { color: var(--color-gray-200); --tw-ring-color: #ffffff1a @@ -1223,7 +975,6 @@ header nav { margin-bottom: calc(var(--spacing) * 5); font-size: var(--text-4xl); line-height: var(--tw-leading, var(--text-4xl--line-height)); - --tw-font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold); text-wrap: balance } @@ -1286,128 +1037,6 @@ header nav { } } -.hero-logos { - margin-inline: auto; - margin-top: calc(var(--spacing) * 10); - max-width: var(--container-7xl); - padding-inline: calc(var(--spacing) * 6) -} - -@media (min-width: 64rem) { - .hero-logos { - margin-top: calc(var(--spacing) * 24); - padding-inline: calc(var(--spacing) * 8) - } -} - -.hero-logos h2 { - text-align: center; - text-wrap: balance; - color: var(--color-gray-600) -} - -.hero-logos h2:where(.dark,.dark *) { - color: #fffc -} - -@supports (color:color-mix(in lab, red, red)) { - .hero-logos h2:where(.dark,.dark *) { - color: color-mix(in oklab, var(--color-white) 80%, transparent) - } -} - -.hero-logos-container { - margin-top: calc(var(--spacing) * 8); - justify-content: center; - align-items: center; - column-gap: calc(var(--spacing) * 4); - row-gap: calc(var(--spacing) * 8); - color: var(--color-gray-800); - grid-template-columns:repeat(3, minmax(0, 1fr)); - display: grid -} - -@media (min-width: 64rem) { - .hero-logos-container { - gap: calc(var(--spacing) * 14); - display: flex - } -} - -.hero-logos-container:where(.dark,.dark *) { - color: #ffffffe6 -} - -@supports (color:color-mix(in lab, red, red)) { - .hero-logos-container:where(.dark,.dark *) { - color: color-mix(in oklab, var(--color-white) 90%, transparent) - } -} - -.hero-logos-container svg { - flex-shrink: 0; - margin-inline: auto -} - -.hero-logos-container svg:first-of-type { - height: calc(var(--spacing) * 5) -} - -@media (min-width: 64rem) { - .hero-logos-container svg:first-of-type { - height: calc(var(--spacing) * 7) - } -} - -.hero-logos-container svg:nth-of-type(2) { - height: calc(var(--spacing) * 4) -} - -@media (min-width: 64rem) { - .hero-logos-container svg:nth-of-type(2) { - height: calc(var(--spacing) * 4.5) - } -} - -.hero-logos-container svg:nth-of-type(3) { - height: calc(var(--spacing) * 5) -} - -@media (min-width: 64rem) { - .hero-logos-container svg:nth-of-type(3) { - height: calc(var(--spacing) * 6.5) - } -} - -.hero-logos-container svg:nth-of-type(4) { - height: calc(var(--spacing) * 5) -} - -@media (min-width: 64rem) { - .hero-logos-container svg:nth-of-type(4) { - height: calc(var(--spacing) * 6) - } -} - -.hero-logos-container svg:nth-of-type(5) { - height: calc(var(--spacing) * 5) -} - -@media (min-width: 64rem) { - .hero-logos-container svg:nth-of-type(5) { - height: calc(var(--spacing) * 6.5) - } -} - -.hero-logos-container svg:nth-of-type(6) { - height: calc(var(--spacing) * 5) -} - -@media (min-width: 64rem) { - .hero-logos-container svg:nth-of-type(6) { - height: calc(var(--spacing) * 7) - } -} .features { isolation: isolate; @@ -1498,7 +1127,6 @@ header nav { .features-title h2 { font-size: var(--text-2xl); line-height: var(--tw-leading, var(--text-2xl--line-height)); - --tw-font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold) } @@ -1531,7 +1159,6 @@ header nav { } .features-title strong { - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); color: var(--color-gray-900) } @@ -1584,11 +1211,9 @@ header nav { } .features-col { - --tw-shadow: 0 1px var(--tw-shadow-color, #0000000d); + --tw-shadow: 0 1px var(#0000000d); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - outline-style: var(--tw-outline-style); - outline-width: 1px; - outline-color: #0000000d + outline: #0000000d var(--tw-outline-style) 1px; } @supports (color:color-mix(in lab, red, red)) { @@ -1598,9 +1223,7 @@ header nav { } .features-col { - --tw-backdrop-blur: blur(var(--blur-xs)); - -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,) + backdrop-filter: blur(4px); } @media (hover: hover) { @@ -1638,10 +1261,7 @@ header nav { } .features-first-col { - border-top-left-radius: var(--radius-4xl); - border-top-right-radius: var(--radius-4xl); - border-bottom-right-radius: var(--radius-xl); - border-bottom-left-radius: var(--radius-xl) + border-radius: var(--radius-4xl) var(--radius-4xl) var(--radius-xl) var(--radius-xl); } @media (min-width: 64rem) { @@ -1660,10 +1280,7 @@ header nav { } .features-sixth-col { - border-top-left-radius: var(--radius-xl); - border-top-right-radius: var(--radius-xl); - border-bottom-right-radius: var(--radius-4xl); - border-bottom-left-radius: var(--radius-4xl) + border-radius: var(--radius-xl) var(--radius-xl) var(--radius-4xl) var(--radius-4xl); } @media (min-width: 64rem) { @@ -1704,7 +1321,6 @@ header nav { .features-col a { font-size: var(--text-lg); line-height: var(--tw-leading, var(--text-lg--line-height)); - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); color: var(--color-gray-950); text-decoration-line: none !important @@ -1736,34 +1352,6 @@ header nav { } } -.features-col code { - border-radius: var(--radius-md); - background-color: #e4e4e780 -} - -@supports (color:color-mix(in lab, red, red)) { - .features-col code { - background-color: color-mix(in oklab, var(--color-gray-200) 50%, transparent) - } -} - -.features-col code { - padding-inline: calc(var(--spacing) * 1); - padding-block: calc(var(--spacing) * .5); - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)) -} - -.features-col code:where(.dark,.dark *) { - background-color: #0003 -} - -@supports (color:color-mix(in lab, red, red)) { - .features-col code:where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-black) 20%, transparent) - } -} - .before-and-after-container { z-index: 10; padding-top: calc(var(--spacing) * 18); @@ -1816,9 +1404,7 @@ header nav { padding: calc(var(--spacing) * 2); font-size: var(--text-sm); line-height: var(--tw-leading, var(--text-sm--line-height)); - outline-style: var(--tw-outline-style); - outline-width: 1px; - outline-color: var(--color-gray-200); + outline: var(--color-gray-200) var(--tw-outline-style) 1px; display: grid } @@ -1879,7 +1465,6 @@ header nav { .before-and-after-title-and-description h2 { font-size: var(--text-2xl); line-height: var(--tw-leading, var(--text-2xl--line-height)); - --tw-font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold) } @@ -1915,17 +1500,7 @@ header nav { } } -.before-and-after-title-and-description code { - border-radius: var(--radius-md); - background-color: #e4e4e780 -} - -@supports (color:color-mix(in lab, red, red)) { - .before-and-after-title-and-description code { - background-color: color-mix(in oklab, var(--color-gray-200) 50%, transparent) - } -} - +.features-col code, .before-and-after-title-and-description code { padding-inline: calc(var(--spacing) * 1); padding-block: calc(var(--spacing) * .5); @@ -1940,16 +1515,6 @@ header nav { font-size: 87%; } -.before-and-after-title-and-description code:where(.dark,.dark *) { - background-color: #0003 -} - -@supports (color:color-mix(in lab, red, red)) { - .before-and-after-title-and-description code:where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-black) 20%, transparent) - } -} - .code-container { border-radius: var(--radius-2xl); border-style: var(--tw-border-style); @@ -2002,7 +1567,6 @@ header nav { padding-block: calc(var(--spacing) * 2); font-size: var(--text-sm); line-height: var(--tw-leading, var(--text-sm--line-height)); - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold) } @@ -2080,7 +1644,7 @@ header nav { .code-container pre { flex: 1; font-size: var(--text-xs); - line-height: var(--leading-loose); + line-height: 2; white-space: pre; display: flex } @@ -2143,10 +1707,8 @@ header nav { .release-notes h2 { font-size: var(--text-xl); line-height: var(--tw-leading, var(--text-xl--line-height)); - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); - --tw-tracking: var(--tracking-tight); - letter-spacing: var(--tracking-tight); + letter-spacing: -.025em; text-wrap: pretty; color: var(--color-gray-900) } @@ -2219,28 +1781,36 @@ header nav { margin-bottom: calc(var(--spacing) * 8); } -.release-notes code { - border-radius: var(--radius-md); - background-color: #e4e4e780 -} - -@supports (color:color-mix(in lab, red, red)) { - .release-notes code { - background-color: color-mix(in oklab, var(--color-gray-200) 50%, transparent) - } -} - .release-notes code { padding-inline: calc(var(--spacing) * 1); padding-block: calc(var(--spacing) * .5) } -.release-notes code:where(.dark,.dark *) { +.features-col code, +.release-notes code, +.before-and-after-title-and-description code { + border-radius: var(--radius-md); + background-color: #e4e4e780 +} + +.hero-badge:where(.dark,.dark *), +.features-col code:where(.dark,.dark *), +.release-notes code:where(.dark,.dark *), +.before-and-after-title-and-description code:where(.dark,.dark *) { background-color: #0003 } @supports (color:color-mix(in lab, red, red)) { - .release-notes code:where(.dark,.dark *) { + .features-col code, + .release-notes code, + .before-and-after-title-and-description code { + background-color: color-mix(in oklab, var(--color-gray-200) 50%, transparent) + } + + .hero-badge:where(.dark,.dark *), + .features-col code:where(.dark,.dark *), + .release-notes code:where(.dark,.dark *), + .before-and-after-title-and-description code:where(.dark,.dark *) { background-color: color-mix(in oklab, var(--color-black) 20%, transparent) } } @@ -2447,7 +2017,6 @@ header nav { font-family: var(--font-sans); font-size: var(--text-2xl); line-height: var(--tw-leading, var(--text-2xl--line-height)); - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); text-wrap: balance; color: var(--color-gray-900) @@ -2505,630 +2074,6 @@ header nav { margin-bottom: calc(var(--spacing) * 6) } -.docs-bg:where(.dark,.dark *) { - background-color: oklab(39.0688% .00431919 -.103547/.3) -} - -.docs-container { - z-index: 10; - max-width: var(--container-7xl); - margin-inline: auto; - position: relative -} - -.docs-container nav a { - text-decoration-line: none -} - -.docs-sidebar a[aria-current=page] { - --tw-font-weight: var(--font-weight-medium); - font-weight: var(--font-weight-medium); - color: var(--color-gray-950) -} - -.docs-sidebar a:where(.dark,.dark *)[aria-current=page] { - color: var(--color-white) -} - -.docs-grid { - gap: calc(var(--spacing) * 4); - padding-inline: calc(var(--spacing) * 6); - padding-top: calc(var(--spacing) * 10); - grid-template-columns:repeat(12, minmax(0, 1fr)); - display: grid -} - -@media (min-width: 64rem) { - .docs-grid { - gap: calc(var(--spacing) * 6); - padding-inline: calc(var(--spacing) * 0) - } -} - -@media (min-width: 80rem) { - .docs-grid { - column-gap: calc(var(--spacing) * 10) - } -} - -.docs-left-sidebar-container { - border-right-style: var(--tw-border-style); - border-color: #09090b1a; - border-right-width: 1px; - grid-column: span 3/span 3; - position: relative -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-left-sidebar-container { - border-color: color-mix(in oklab, var(--color-gray-950) 10%, transparent) - } -} - -@media (min-width: 64rem) { - .docs-left-sidebar-container { - padding-bottom: calc(var(--spacing) * 6) - } -} - -.docs-left-sidebar-container:where(.dark,.dark *) { - border-color: #ffffff1a -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-left-sidebar-container:where(.dark,.dark *) { - border-color: color-mix(in oklab, var(--color-white) 10%, transparent) - } -} - -.docs-left-sidebar-sub-container { - top: calc(var(--spacing) * 22); - bottom: calc(var(--spacing) * 0); - left: calc(var(--spacing) * 0); - z-index: 20; - display: none; - position: sticky -} - -@media (min-width: 64rem) { - .docs-left-sidebar-sub-container { - display: block - } -} - -.docs-left-sidebar { - overflow-y: auto -} - -.docs-left-sidebar:is(:where(.group)[data-sidebar-collapsed] *) { - display: none -} - -@media not all and (min-width: 80rem) { - .docs-left-sidebar { - display: none - } -} - -.docs-left-sidebar nav { - padding-inline: calc(var(--spacing) * 6) -} - -@media (min-width: 64rem) { - .docs-left-sidebar nav { - padding-inline: calc(var(--spacing) * 8) - } -} - -:where(.docs-left-sidebar-spacing>:not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse))) -} - -@media not all and (min-width: 80rem) { - .docs-left-sidebar-spacing { - display: none - } -} - -.docs-left-sidebar h2 { - font-size: var(--text-base); - line-height: calc(var(--spacing) * 7); - --tw-font-weight: var(--font-weight-semibold); - font-weight: var(--font-weight-semibold); - text-wrap: pretty; - color: var(--color-gray-950) -} - -@media (min-width: 40rem) { - .docs-left-sidebar h2 { - font-size: var(--text-sm); - line-height: calc(var(--spacing) * 6) - } -} - -.docs-left-sidebar h2:where(.dark,.dark *) { - color: var(--color-white) -} - -.docs-left-sidebar ul { - margin-top: calc(var(--spacing) * 4); - gap: calc(var(--spacing) * 4); - border-left-style: var(--tw-border-style); - border-color: #09090b1a; - border-left-width: 1px; - flex-direction: column; - display: flex -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-left-sidebar ul { - border-color: color-mix(in oklab, var(--color-gray-950) 10%, transparent) - } -} - -.docs-left-sidebar ul { - font-size: var(--text-base); - line-height: calc(var(--spacing) * 7); - color: var(--color-gray-700) -} - -@media (min-width: 40rem) { - .docs-left-sidebar ul { - margin-top: calc(var(--spacing) * 3); - gap: calc(var(--spacing) * 3); - font-size: var(--text-sm); - line-height: calc(var(--spacing) * 6) - } -} - -.docs-left-sidebar ul:where(.dark,.dark *) { - border-color: #ffffff1a -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-left-sidebar ul:where(.dark,.dark *) { - border-color: color-mix(in oklab, var(--color-white) 10%, transparent) - } -} - -.docs-left-sidebar ul:where(.dark,.dark *) { - color: #ffffffb3 -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-left-sidebar ul:where(.dark,.dark *) { - color: color-mix(in oklab, var(--color-white) 70%, transparent) - } -} - -.docs-left-sidebar li { - border-left-style: var(--tw-border-style); - padding-left: calc(var(--spacing) * 4); - border-color: #0000; - border-left-width: 1px; - margin-left: -1px; - display: flex -} - -@media (hover: hover) { - .docs-left-sidebar li:hover { - color: var(--color-gray-950) - } - - .docs-left-sidebar li:hover:not(:has([aria-current=page])) { - border-color: var(--color-gray-400) - } -} - -.docs-left-sidebar li:has([aria-current=page]) { - border-left-style: var(--tw-border-style); - border-color: #6b58ff; - border-left-width: 2px -} - -@media (hover: hover) { - .docs-left-sidebar li:where(.dark,.dark *):hover { - color: var(--color-white) - } -} - -.docs-right-sidebar-container { - border-left-style: var(--tw-border-style); - border-color: #09090b1a; - border-left-width: 1px; - grid-column: span 12/span 12; - display: none; - position: relative -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-right-sidebar-container { - border-color: color-mix(in oklab, var(--color-gray-950) 10%, transparent) - } -} - -.docs-right-sidebar-container:is(:where(.group)[data-sidebar-collapsed] *) { - display: none -} - -@media not all and (min-width: 80rem) { - .docs-right-sidebar-container { - display: none - } -} - -@media (min-width: 64rem) { - .docs-right-sidebar-container { - padding-bottom: calc(var(--spacing) * 10); - grid-column: 4/span 9 - } -} - -@media (min-width: 80rem) { - .docs-right-sidebar-container { - grid-column: auto/span 3; - display: block - } -} - -.docs-right-sidebar-container:where(.dark,.dark *) { - border-color: #ffffff1a -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-right-sidebar-container:where(.dark,.dark *) { - border-color: color-mix(in oklab, var(--color-white) 10%, transparent) - } -} - -.docs-right-sidebar-sub-container { - padding-left: calc(var(--spacing) * 10); - position: relative -} - -@media (min-width: 64rem) { - .docs-right-sidebar-sub-container { - top: calc(var(--spacing) * 28); - position: sticky - } -} - -.docs-right-sidebar-container nav { - width: calc(var(--spacing) * 56) -} - -.docs-right-sidebar-container h2 { - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)); - --tw-font-weight: var(--font-weight-semibold); - font-weight: var(--font-weight-semibold); - color: var(--color-gray-900) -} - -.docs-right-sidebar-container h2:where(.dark,.dark *) { - color: var(--color-white) -} - -.docs-right-sidebar-container ol { - margin-top: calc(var(--spacing) * 4) -} - -:where(.docs-right-sidebar-container ol>:not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse))) -} - -.docs-right-sidebar-container ol { - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)) -} - -.docs-right-sidebar-container ol ol { - margin-top: calc(var(--spacing) * 2); - margin-bottom: calc(var(--spacing) * 4) -} - -:where(.docs-right-sidebar-container ol ol>:not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse))) -} - -.docs-right-sidebar-container ol ol { - padding-left: calc(var(--spacing) * 5); - color: var(--color-gray-500) -} - -.docs-right-sidebar-container ol ol:where(.dark,.dark *) { - color: #ffffffb3 -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-right-sidebar-container ol ol:where(.dark,.dark *) { - color: color-mix(in oklab, var(--color-white) 70%, transparent) - } -} - -.docs-right-sidebar-container a { - --tw-font-weight: var(--font-weight-normal); - font-weight: var(--font-weight-normal); - color: var(--color-gray-500) -} - -@media (hover: hover) { - .docs-right-sidebar-container a:hover { - color: var(--color-gray-700) - } -} - -.docs-right-sidebar-container a[aria-current=page] { - --tw-font-weight: var(--font-weight-medium); - font-weight: var(--font-weight-medium); - color: #6b58ff -} - -.docs-right-sidebar-container a:where(.dark,.dark *) { - color: #ffffffb3 -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-right-sidebar-container a:where(.dark,.dark *) { - color: color-mix(in oklab, var(--color-white) 70%, transparent) - } -} - -@media (hover: hover) { - .docs-right-sidebar-container a:where(.dark,.dark *):hover { - color: #ffffffe6 - } - - @supports (color:color-mix(in lab, red, red)) { - .docs-right-sidebar-container a:where(.dark,.dark *):hover { - color: color-mix(in oklab, var(--color-white) 90%, transparent) - } - } -} - -.docs-right-sidebar-container a:where(.dark,.dark *)[aria-current=page] { - color: #7b75ff -} - -.docs-content { - grid-column: span 12/span 12 -} - -@media (min-width: 64rem) { - .docs-content { - grid-column: span 9/span 9 - } -} - -@media (min-width: 80rem) { - .docs-content { - grid-column: span 6/span 6 - } -} - -.docs-content .code-container { - margin-bottom: calc(var(--spacing) * 6) -} - -.docs-content .code-container:where(.dark,.dark *) { - border-color: #ffffff0d -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-content .code-container:where(.dark,.dark *) { - border-color: color-mix(in oklab, var(--color-white) 5%, transparent) - } -} - -.docs-content .code-container:where(.dark,.dark *) { - background-color: #ffffff14 -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-content .code-container:where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-white) 8%, transparent) - } -} - -.docs-content .code-container .header { - top: calc(var(--spacing) * 0); - right: calc(var(--spacing) * 0); - border-style: var(--tw-border-style); - border-width: 0; - justify-content: flex-end; - position: absolute -} - -.docs-content h1 { - margin-top: 0; - margin-bottom: 1.5rem; - padding-bottom: .75rem; - font-size: 2rem; - font-weight: 700; - line-height: 1.2 -} - -.docs-content h2 { - margin-top: 2.5rem; - margin-bottom: 1.25rem; - padding-bottom: .5rem; - font-size: 1.75rem; - font-weight: 600; - line-height: 1.3 -} - -.docs-content h3 { - margin-top: 2rem; - margin-bottom: 1rem; - font-size: 1.5rem; - font-weight: 600; - line-height: 1.4 -} - -.docs-content h4 { - margin-top: 1.5rem; - margin-bottom: .75rem; - font-size: 1.25rem; - font-weight: 600; - line-height: 1.4 -} - -.docs-content h5 { - margin-top: 1.25rem; - margin-bottom: .5rem; - font-size: 1.1rem; - font-weight: 600; - line-height: 1.4 -} - -.docs-content h6 { - margin-top: 1rem; - margin-bottom: .5rem; - font-size: 1rem; - font-weight: 600; - line-height: 1.4 -} - -.docs-content p { - margin-bottom: 1.25rem; - font-size: 1rem; - line-height: 1.75 -} - -.docs-content a { - color: #6b58ff; - text-decoration-line: none -} - -.docs-content a:where(.dark,.dark *) { - color: #7b75ff -} - -.docs-content a:hover { - text-decoration: underline -} - -.docs-content ol, .docs-content ul { - color: #4a5568; - margin-bottom: 1.25rem; - padding-left: 2rem -} - -.docs-content li { - margin-bottom: .5rem; - line-height: 1.75 -} - -.docs-content ul li { - list-style-type: disc -} - -.docs-content ol li { - list-style-type: decimal -} - -.docs-content p code, .docs-content blockquote code { - border-radius: var(--radius-md); - background-color: #e4e4e780 -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-content p code, .docs-content blockquote code { - background-color: color-mix(in oklab, var(--color-gray-200) 50%, transparent) - } -} - -.docs-content p code, .docs-content blockquote code { - padding-inline: calc(var(--spacing) * 1); - padding-block: calc(var(--spacing) * .5); - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)) -} - -:is(.docs-content p code,.docs-content blockquote code):where(.dark,.dark *) { - background-color: #ffffff1a -} - -@supports (color:color-mix(in lab, red, red)) { - :is(.docs-content p code,.docs-content blockquote code):where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-white) 10%, transparent) - } -} - -.docs-content table { - border-collapse: collapse; - border: 1px solid #6b58ff; - border-radius: 8px; - width: 100%; - margin-bottom: 1.5rem; - overflow: hidden -} - -.docs-content thead { - background-color: #f7fafc -} - -.docs-content th { - text-align: left; - border-bottom: 2px solid #6b58ff; - padding: 1rem; - font-weight: 600 -} - -.docs-content td { - border-bottom: 1px solid #6b58ff; - padding: 1rem -} - -.docs-content tbody tr:last-child td { - border-bottom: none -} - -.docs-content tbody tr:hover { - background-color: #f7fafc -} - -.docs-content blockquote { - margin-bottom: calc(var(--spacing) * 6); - border-radius: var(--radius-2xl); - border-style: var(--tw-border-style); - background-color: var(--color-white); - padding-inline: calc(var(--spacing) * 4); - padding-block: calc(var(--spacing) * 3); - border-width: 2px; - border-color: #6b58ff -} - -.docs-content blockquote:where(.dark,.dark *) { - background-color: #ffffff1a -} - -@supports (color:color-mix(in lab, red, red)) { - .docs-content blockquote:where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-white) 10%, transparent) - } -} - -.docs-content blockquote p { - margin-bottom: calc(var(--spacing) * 2) -} - -.docs-content em { - font-style: italic -} - -.docs-content hr { - border: none; - border-top: 1px solid #6b58ff; - margin: 2rem 0 -} - footer { isolation: isolate; z-index: 10; @@ -3286,7 +2231,6 @@ footer p:where(.dark,.dark *) { .footer-links-grid h3 { font-size: var(--text-sm); line-height: calc(var(--spacing) * 6); - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); color: var(--color-gray-900) } @@ -3418,7 +2362,6 @@ footer p:where(.dark,.dark *) { padding-block: calc(var(--spacing) * .5); font-size: var(--text-xs); line-height: var(--tw-leading, var(--text-xs--line-height)); - --tw-font-weight: var(--font-weight-medium); font-weight: var(--font-weight-medium); color: var(--color-green-900); align-items: center; @@ -3439,33 +2382,6 @@ footer p:where(.dark,.dark *) { color: var(--color-green-400) } -.badge-red { - border-radius: var(--radius-md); - background-color: var(--color-red-200); - padding-inline: calc(var(--spacing) * 1.5); - padding-block: calc(var(--spacing) * .5); - font-size: var(--text-xs); - line-height: var(--tw-leading, var(--text-xs--line-height)); - --tw-font-weight: var(--font-weight-medium); - font-weight: var(--font-weight-medium); - color: var(--color-red-900); - align-items: center; - display: inline-flex -} - -.badge-red:where(.dark,.dark *) { - background-color: #ff65681a -} - -@supports (color:color-mix(in lab, red, red)) { - .badge-red:where(.dark,.dark *) { - background-color: color-mix(in oklab, var(--color-red-400) 10%, transparent) - } -} - -.badge-red:where(.dark,.dark *) { - color: var(--color-red-400) -} .select { grid-template-columns:repeat(1, minmax(0, 1fr)); @@ -3494,10 +2410,8 @@ footer p:where(.dark,.dark *) { font-size: var(--text-base); line-height: var(--tw-leading, var(--text-base--line-height)); color: var(--color-gray-900); - outline-style: var(--tw-outline-style); outline-offset: calc(1px * -1); - outline-width: 1px; - outline-color: var(--color-gray-300) + outline: var(--color-gray-300) var(--tw-outline-style) 1px; } .select select:focus { @@ -3677,7 +2591,6 @@ footer p:where(.dark,.dark *) { padding-inline: calc(var(--spacing) * 5); font-size: var(--text-sm); line-height: var(--tw-leading, var(--text-sm--line-height)); - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); color: var(--color-white); background-color: #6b58ff; @@ -3697,10 +2610,8 @@ footer p:where(.dark,.dark *) { } .php85 #layout-content a.button-primary:focus-visible { - outline-style: var(--tw-outline-style); outline-offset: 2px; - outline-width: 2px; - outline-color: var(--color-gray-800) + outline: var(--color-gray-800) var(--tw-outline-style) 2px; } .php85 #layout-content a.button-primary:disabled { @@ -3722,10 +2633,9 @@ footer p:where(.dark,.dark *) { padding-inline: calc(var(--spacing) * 5); font-size: var(--text-sm); line-height: var(--tw-leading, var(--text-sm--line-height)); - --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); color: var(--color-gray-900); - --tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, #0000000d); + --tw-shadow: 0 1px 2px 0 var(#0000000d); --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); --tw-ring-color: color-mix(in oklab, var(--color-gray-200) 50%, transparent); @@ -3773,106 +2683,18 @@ footer p:where(.dark,.dark *) { box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow) } -@property --tw-blur { - syntax: "*"; - inherits: false -} - -@property --tw-brightness { - syntax: "*"; - inherits: false -} - -@property --tw-contrast { - syntax: "*"; - inherits: false -} - -@property --tw-grayscale { - syntax: "*"; - inherits: false -} - -@property --tw-hue-rotate { - syntax: "*"; - inherits: false -} - -@property --tw-invert { - syntax: "*"; - inherits: false -} - -@property --tw-opacity { - syntax: "*"; - inherits: false -} - -@property --tw-saturate { - syntax: "*"; - inherits: false -} - -@property --tw-sepia { - syntax: "*"; - inherits: false -} - -@property --tw-drop-shadow { - syntax: "*"; - inherits: false -} - -@property --tw-drop-shadow-color { - syntax: "*"; - inherits: false -} - -@property --tw-drop-shadow-alpha { - syntax: ""; - inherits: false; - initial-value: 100% -} - -@property --tw-drop-shadow-size { - syntax: "*"; - inherits: false -} - @property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000 } -@property --tw-shadow-color { - syntax: "*"; - inherits: false -} - -@property --tw-shadow-alpha { - syntax: ""; - inherits: false; - initial-value: 100% -} - @property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000 } -@property --tw-inset-shadow-color { - syntax: "*"; - inherits: false -} - -@property --tw-inset-shadow-alpha { - syntax: ""; - inherits: false; - initial-value: 100% -} - @property --tw-ring-color { syntax: "*"; inherits: false @@ -3884,11 +2706,6 @@ footer p:where(.dark,.dark *) { initial-value: 0 0 #0000 } -@property --tw-inset-ring-color { - syntax: "*"; - inherits: false -} - @property --tw-inset-ring-shadow { syntax: "*"; inherits: false; @@ -3918,51 +2735,6 @@ footer p:where(.dark,.dark *) { initial-value: 0 0 #0000 } -@property --tw-backdrop-blur { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-brightness { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-contrast { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-grayscale { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-hue-rotate { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-invert { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-opacity { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-saturate { - syntax: "*"; - inherits: false -} - -@property --tw-backdrop-sepia { - syntax: "*"; - inherits: false -} - @property --tw-border-style { syntax: "*"; inherits: false; @@ -3975,72 +2747,6 @@ footer p:where(.dark,.dark *) { initial-value: solid } -@property --tw-gradient-position { - syntax: "*"; - inherits: false -} - -@property --tw-gradient-from { - syntax: ""; - inherits: false; - initial-value: #0000 -} - -@property --tw-gradient-via { - syntax: ""; - inherits: false; - initial-value: #0000 -} - -@property --tw-gradient-to { - syntax: ""; - inherits: false; - initial-value: #0000 -} - -@property --tw-gradient-stops { - syntax: "*"; - inherits: false -} - -@property --tw-gradient-via-stops { - syntax: "*"; - inherits: false -} - -@property --tw-gradient-from-position { - syntax: ""; - inherits: false; - initial-value: 0% -} - -@property --tw-gradient-via-position { - syntax: ""; - inherits: false; - initial-value: 50% -} - -@property --tw-gradient-to-position { - syntax: ""; - inherits: false; - initial-value: 100% -} - -@property --tw-duration { - syntax: "*"; - inherits: false -} - -@property --tw-ease { - syntax: "*"; - inherits: false -} - -@property --tw-font-weight { - syntax: "*"; - inherits: false -} - @property --tw-leading { syntax: "*"; inherits: false @@ -4057,8 +2763,3 @@ footer p:where(.dark,.dark *) { inherits: false; initial-value: 0 } - -@property --tw-tracking { - syntax: "*"; - inherits: false -} From 1b25551dec6f99f6e285c10023434c72d6399b52 Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Wed, 10 Jun 2026 09:58:53 -0500 Subject: [PATCH 4/5] Correctly style code in PHP 8.5 headings Also removed duplicate feature title translation strings. --- releases/8.5/languages/en.php | 10 ++-------- releases/8.5/languages/es.php | 12 +++--------- releases/8.5/languages/fr.php | 12 +++--------- releases/8.5/languages/ja.php | 10 ++-------- releases/8.5/languages/pt_BR.php | 10 ++-------- releases/8.5/languages/ru.php | 10 ++-------- releases/8.5/languages/tr.php | 10 ++-------- releases/8.5/languages/uk.php | 10 ++-------- releases/8.5/languages/vi.php | 10 ++-------- releases/8.5/languages/zh.php | 10 ++-------- releases/8.5/release.inc | 12 ++++++------ 11 files changed, 28 insertions(+), 88 deletions(-) diff --git a/releases/8.5/languages/en.php b/releases/8.5/languages/en.php index 191878a2a7..30cf4f2c14 100644 --- a/releases/8.5/languages/en.php +++ b/releases/8.5/languages/en.php @@ -14,23 +14,17 @@ 'key_features' => 'Key Features in PHP 8.5', 'key_features_description' => '

    Faster, cleaner, and built for developers.

    ', - 'features_pipe_operator_title' => 'Pipe Operator', 'features_pipe_operator_description' => '

    The |> operator enables chaining callables left-to-right, passing values smoothly through multiple functions without intermediary variables.

    ', - 'features_persistent_curl_share_handles_title' => 'Persistent cURL Share Handles', 'features_persistent_curl_share_handles_description' => '

    Handles can now be persisted across multiple PHP requests, avoiding the cost of repeated connection initialization to the same hosts.

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    Clone objects and update properties with the new clone() syntax, making the "with-er" pattern simple for readonly classes.

    ', - 'features_uri_extension_title' => 'URI Extension', 'features_uri_extension_description' => '

    PHP 8.5 adds a built-in URI extension to parse, normalize, and handle URLs following RFC 3986 and WHATWG URL standards.

    ', - 'features_no_discard_title' => '#[\NoDiscard] Attribute', 'features_no_discard_description' => '

    The #[\NoDiscard] attribute warns when a return value isn’t used, helping prevent mistakes and improving overall API safety.

    ', - 'features_fcc_in_const_expr_title' => 'Closures and First-Class Callables in Constant Expressions', 'features_fcc_in_const_expr_description' => '

    Static closures and first-class callables can now be used in constant expressions, such as attribute parameters.

    ', 'pipe_operator_title' => 'Pipe Operator', 'pipe_operator_description' => '

    The pipe operator allows chaining function calls together without dealing with intermediary variables. This enables replacing many "nested calls" with a chain that can be read forwards, rather than inside-out.

    Learn more about the backstory of this feature in The PHP Foundation’s blog.

    ', - 'array_first_last_title' => 'array_first() and array_last() functions', + 'array_first_last_title' => 'array_first() and array_last() functions', 'array_first_last_description' => '

    The array_first() and array_last() functions return the first or last value of an array, respectively. If the array is empty, null is returned (making it easy to compose with the ?? operator).

    ', 'clone_with_title' => 'Clone With', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'URI Extension', 'uri_extension_description' => '

    The new always-available URI extension provides APIs to securely parse and modify URIs and URLs according to the RFC 3986 and the WHATWG URL standards.

    Powered by the uriparser (RFC 3986) and Lexbor (WHATWG URL) libraries.

    Learn more about the backstory of this feature in The PHP Foundation’s blog.

    ', - 'no_discard_title' => '#[\NoDiscard] Attribute', + 'no_discard_title' => '#[\NoDiscard] Attribute', 'no_discard_description' => '

    By adding the #[\NoDiscard] attribute to a function, PHP will check whether the returned value is consumed and emit a warning if it is not. This allows improving the safety of APIs where the returned value is important, but it\'s easy to forget using the return value by accident.

    The associated (void) cast can be used to indicate that a value is intentionally unused.

    ', 'persistent_curl_share_handles_title' => 'Persistent cURL Share Handles', diff --git a/releases/8.5/languages/es.php b/releases/8.5/languages/es.php index c68abd01ac..f5a0ab9f22 100644 --- a/releases/8.5/languages/es.php +++ b/releases/8.5/languages/es.php @@ -14,23 +14,17 @@ 'key_features' => 'Características clave en PHP 8.5', 'key_features_description' => '

    Más rápido, limpio y construido para desarrolladores.

    ', - 'features_pipe_operator_title' => 'Operador Pipe', 'features_pipe_operator_description' => '

    El operador |> permite encadenar callables de izquierda a derecha, pasando valores suavemente a través de múltiples funciones sin variables intermedias.

    ', - 'features_persistent_curl_share_handles_title' => 'Handles cURL Persistentes Compartidos', 'features_persistent_curl_share_handles_description' => '

    Los handles ahora pueden persistir a través de múltiples peticiones PHP, evitando el costo de inicialización repetida de conexiones a los mismos hosts.

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    Clona objetos y actualiza propiedades con la nueva sintaxis clone(), simplificando el patrón en clases readonly.

    ', - 'features_uri_extension_title' => 'Extensión URI', 'features_uri_extension_description' => '

    PHP 8.5 añade una extensión URI integrada para analizar, normalizar y manejar URLs siguiendo los estándares RFC 3986 y WHATWG URL.

    ', - 'features_no_discard_title' => 'Atributo #[\NoDiscard]', 'features_no_discard_description' => '

    El atributo #[\NoDiscard] advierte cuando un valor de retorno no se usa, ayudando a prevenir errores y mejorando la seguridad.

    ', - 'features_fcc_in_const_expr_title' => 'Closures y Callables de Primera Clase en Expresiones Constantes', 'features_fcc_in_const_expr_description' => '

    Los closures estáticos y callables de primera clase ahora pueden usarse en expresiones constantes, como parámetros de atributos.

    ', 'pipe_operator_title' => 'Operador Pipe', 'pipe_operator_description' => '

    El operador pipe permite encadenar llamadas a funciones sin tener que lidiar con variables intermedias. Esto permite reemplazar muchas "llamadas anidadas" con una cadena que se puede leer hacia adelante, en lugar de hacerlo de adentro hacia afuera.

    Aprende más sobre esta característica en el artículo de The PHP Foundation.

    ', - 'array_first_last_title' => 'Funciones array_first() y array_last()', + 'array_first_last_title' => 'Funciones array_first() y array_last()', 'array_first_last_description' => '

    Las funciones array_first() y array_last() devuelven el primer o último valor de un array, respectivamente. Si el array está vacío, se devuelve null (facilitando su usabilidad con el operador ??).

    ', 'clone_with_title' => 'Clone With', @@ -39,10 +33,10 @@ 'uri_extension_title' => 'Extensión URI', 'uri_extension_description' => '

    La nueva extensión URI proporciona APIs para analizar y modificar de forma segura URIs y URLs de acuerdo con los estándares RFC 3986 y WHATWG URL.

    Desarrollado por las librerías uriparser (RFC 3986) y Lexbor (WHATWG URL).

    Aprende más sobre esta característica en el artículo de The PHP Foundation.

    ', - 'no_discard_title' => 'Atributo #[\NoDiscard]', + 'no_discard_title' => 'Atributo #[\NoDiscard]', 'no_discard_description' => '

    Al agregar el atributo #[\NoDiscard] a una función, PHP verificará si el valor devuelto se consume y emitirá una advertencia si no lo es. Esto permite mejorar la seguridad de APIs donde el valor devuelto es importante, pero se podría olvidar usar el valor de retorno por accidente.

    El cast (void) puede usarse para indicar que un valor no se usa intencionalmente.

    ', - 'persistent_curl_share_handles_title' => 'Handles cURL persistentes compartidos', + 'persistent_curl_share_handles_title' => 'Handles cURL Persistentes Compartidos', 'persistent_curl_share_handles_description' => '

    A diferencia de curl_share_init(), los handles creados por curl_share_init_persistent() no serán destruidos al final de la petición PHP. Si se encuentra un handle persistente compartido con el mismo conjunto de opciones compartidas, será reutilizado, evitando el costo de inicializar handles cURL de nuevo.

    ', 'fcc_in_const_expr_title' => 'Closures y Callables de Primera Clase en Expresiones Constantes', diff --git a/releases/8.5/languages/fr.php b/releases/8.5/languages/fr.php index f93c241dea..9bb108811b 100644 --- a/releases/8.5/languages/fr.php +++ b/releases/8.5/languages/fr.php @@ -14,23 +14,17 @@ 'key_features' => 'Fonctionnalités clés de PHP 8.5', 'key_features_description' => '

    Plus rapide, plus propre et conçu pour les développeurs.

    ', - 'features_pipe_operator_title' => 'Opérateur Pipe', 'features_pipe_operator_description' => '

    L\'opérateur |> permet d\'enchaîner des callables de gauche à droite, en transmettant les valeurs fluidement à travers plusieurs fonctions sans variables intermédiaires.

    ', - 'features_persistent_curl_share_handles_title' => 'Handles cURL partagés persistants', 'features_persistent_curl_share_handles_description' => '

    Les handles peuvent désormais être conservés entre plusieurs requêtes PHP, évitant le coût de l\'initialisation répétée des connexions vers les mêmes hôtes.

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    Clonez des objets et mettez à jour leurs propriétés grâce à la nouvelle syntaxe clone(), simplifiant le pattern « with-er » pour les classes readonly.

    ', - 'features_uri_extension_title' => 'Extension URI', 'features_uri_extension_description' => '

    PHP 8.5 ajoute une extension URI native pour analyser, normaliser et gérer les URL conformément aux standards RFC 3986 et WHATWG URL.

    ', - 'features_no_discard_title' => 'Attribut #[\NoDiscard]', 'features_no_discard_description' => '

    L\'attribut #[\NoDiscard] émet un avertissement lorsqu\'une valeur de retour n\'est pas utilisée, aidant à prévenir les erreurs et à améliorer la sécurité globale des API.

    ', - 'features_fcc_in_const_expr_title' => 'Closures et callables de première classe dans les expressions constantes', 'features_fcc_in_const_expr_description' => '

    Les closures statiques et les callables de première classe peuvent désormais être utilisés dans les expressions constantes, comme les paramètres d\'attributs.

    ', 'pipe_operator_title' => 'Opérateur Pipe', 'pipe_operator_description' => '

    L\'opérateur pipe permet d\'enchaîner des appels de fonctions sans avoir recours à des variables intermédiaires. Il permet de remplacer de nombreux « appels imbriqués » par une chaîne qui se lit de gauche à droite, plutôt que de l\'intérieur vers l\'extérieur.

    Pour en savoir plus sur l\'histoire de cette fonctionnalité, consultez le blog de la PHP Foundation.

    ', - 'array_first_last_title' => 'Fonctions array_first() et array_last()', + 'array_first_last_title' => 'Fonctions array_first() et array_last()', 'array_first_last_description' => '

    Les fonctions array_first() et array_last() retournent respectivement la première ou la dernière valeur d\'un tableau. Si le tableau est vide, null est retourné (ce qui facilite la composition avec l\'opérateur ??).

    ', 'clone_with_title' => 'Clone With', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'Extension URI', 'uri_extension_description' => '

    La nouvelle extension URI, toujours disponible, fournit des API pour analyser et modifier de manière sécurisée les URI et URL selon les standards RFC 3986 et WHATWG URL.

    Propulsée par les bibliothèques uriparser (RFC 3986) et Lexbor (WHATWG URL).

    Pour en savoir plus sur l\'histoire de cette fonctionnalité, consultez le blog de la PHP Foundation.

    ', - 'no_discard_title' => 'Attribut #[\NoDiscard]', + 'no_discard_title' => 'Attribut #[\NoDiscard]', 'no_discard_description' => '

    En ajoutant l\'attribut #[\NoDiscard] à une fonction, PHP vérifie si la valeur retournée est consommée et émet un avertissement dans le cas contraire. Cela permet d\'améliorer la sécurité des API pour lesquelles la valeur de retour est importante, mais peut facilement être oubliée par inadvertance.

    Le cast associé (void) peut être utilisé pour indiquer qu\'une valeur est intentionnellement ignorée.

    ', 'persistent_curl_share_handles_title' => 'Handles cURL partagés persistants', @@ -76,4 +70,4 @@ 'footer_title' => 'Une syntaxe améliorée, de meilleures performances et une sécurité de typage renforcée.', 'footer_description' => '

    La liste complète des modifications est consignée dans le journal des modifications.

    Veuillez consulter le guide de migration pour une liste détaillée des nouvelles fonctionnalités et des changements incompatibles avec les versions précédentes.

    ', -]; \ No newline at end of file +]; diff --git a/releases/8.5/languages/ja.php b/releases/8.5/languages/ja.php index 4729484e8d..00fb9a6c07 100644 --- a/releases/8.5/languages/ja.php +++ b/releases/8.5/languages/ja.php @@ -14,23 +14,17 @@ 'key_features' => 'PHP 8.5 の主な機能', 'key_features_description' => '

    より速くよりクリーンに。そして開発者のために

    ', - 'features_pipe_operator_title' => 'パイプ演算子', 'features_pipe_operator_description' => '

    |> 演算子を使うと callable を左から右にチェインさせ、中間変数を使わずに値を複数の関数にスムーズに受け渡せます。

    ', - 'features_persistent_curl_share_handles_title' => '持続的な cURL 共有ハンドル', 'features_persistent_curl_share_handles_description' => '

    ハンドルを複数の PHP リクエストにまたがって持続させられるようになります。同じホストへの接続初期化を繰り返すコストを避けることができます。

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    新しい clone() 構文でオブジェクトを clone してプロパティを更新します。readonly クラスの "with-er" パターンが簡潔になります。

    ', - 'features_uri_extension_title' => 'URI 拡張モジュール', 'features_uri_extension_description' => '

    URL のパース、正規化、処理を行う新しい組み込みの URI 拡張モジュールが PHP 8.5 で追加されました。

    ', - 'features_no_discard_title' => '#[\NoDiscard] アトリビュート', 'features_no_discard_description' => '

    #[\NoDiscard] アトリビュートを使うと、戻り値が利用されていない場合に警告を出します。ミスを防ぎ全体の API 安全性を向上するのに役立ちます。

    ', - 'features_fcc_in_const_expr_title' => '定数式でのクロージャと第一級 callable', 'features_fcc_in_const_expr_description' => '

    static なクロージャと第一級 callable が、アトリビュートの引数などの定数式で使えるようになります。

    ', 'pipe_operator_title' => 'パイプ演算子', 'pipe_operator_description' => '

    パイプ演算子を使うと、中間変数を扱うことなく複数の関数呼び出しを繋げることができます。これによってたくさんの「入れ子呼び出し」を置き換え、中から外ではなく先に向かって読むことができるようになります。

    この機能の背景について詳しくは PHP Foundation のブログをお読みください。

    ', - 'array_first_last_title' => 'array_first() ・ array_last() 関数', + 'array_first_last_title' => 'array_first()array_last() 関数', 'array_first_last_description' => '

    array_first()array_last() 関数は、それぞれ配列の最初と最後の値を返します。空配列の場合は null を返します(そのため ?? 演算子と組み合わせやすいです)。

    ', 'clone_with_title' => 'Clone With', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'URI 拡張モジュール', 'uri_extension_description' => '

    常に有効な新しい URI 拡張モジュールは、RFC 3986 と WHATWG URL 標準にしたがって URI や URL を安全にパース・編集できる API を提供します。

    uriparser (RFC 3986) と Lexbor (WHATWG URL) ライブラリを利用しています。

    この機能の背景は PHP Foundation のブログをお読みください。

    ', - 'no_discard_title' => '#[\NoDiscard] アトリビュート', + 'no_discard_title' => '#[\NoDiscard] アトリビュート', 'no_discard_description' => '

    #[\NoDiscard] アトリビュートを関数に追加すると、戻り値が利用されたかを PHP がチェックし、されていなければ警告を出します。これにより、戻り値が重要なのにそれを利用することをうっかり忘れやすい API の安全性を高めることができます。

    関連する (void) キャストを使うと、戻り値を使っていないのが意図的であることを明示できます。

    ', 'persistent_curl_share_handles_title' => '持続的な cURL 共有ハンドル', diff --git a/releases/8.5/languages/pt_BR.php b/releases/8.5/languages/pt_BR.php index 4c0a0ddd11..eddef93304 100644 --- a/releases/8.5/languages/pt_BR.php +++ b/releases/8.5/languages/pt_BR.php @@ -14,23 +14,17 @@ 'key_features' => 'Principais recursos do PHP 8.5', 'key_features_description' => '

    Mais rápido, mais limpo e feito para desenvolvedores.

    ', - 'features_pipe_operator_title' => 'Operador Pipe', 'features_pipe_operator_description' => '

    O operador |> permite encadear funções da esquerda para a direita, passando valores entre múltiplas chamadas sem variáveis intermediárias.

    ', - 'features_persistent_curl_share_handles_title' => 'cURL Share Handles Persistentes', 'features_persistent_curl_share_handles_description' => '

    Agora é possível manter handles compartilhados entre várias requisições PHP, evitando o custo de inicializar conexões repetidas para os mesmos hosts.

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    Clone objetos e atualize propriedades usando a nova sintaxe clone(), facilitando o padrão “with-er” para classes readonly.

    ', - 'features_uri_extension_title' => 'Extensão URI', 'features_uri_extension_description' => '

    O PHP 8.5 adiciona uma extensão nativa para analisar, normalizar e manipular URLs seguindo os padrões RFC 3986 e WHATWG URL.

    ', - 'features_no_discard_title' => 'Atributo #[\NoDiscard]', 'features_no_discard_description' => '

    O atributo #[\NoDiscard] emite um aviso quando o valor de retorno não é usado, ajudando a evitar erros e aumentando a segurança de APIs.

    ', - 'features_fcc_in_const_expr_title' => 'Closures e First-Class Callables em Expressões Constantes', 'features_fcc_in_const_expr_description' => '

    Closures estáticas e first-class callables agora podem ser usadas em expressões constantes, como parâmetros de atributos.

    ', 'pipe_operator_title' => 'Operador Pipe', 'pipe_operator_description' => '

    O operador pipe permite encadear chamadas de função sem lidar com variáveis intermediárias. Isso substitui chamadas aninhadas por um fluxo mais legível de cima para baixo.

    Saiba mais sobre os bastidores desse recurso no blog da The PHP Foundation.

    ', - 'array_first_last_title' => 'Funções array_first() e array_last()', + 'array_first_last_title' => 'Funções array_first() e array_last()', 'array_first_last_description' => '

    As funções array_first() e array_last() retornam, respectivamente, o primeiro ou o último valor de um array. Se o array estiver vazio, retornam null, o que facilita o uso com o operador ??.

    ', 'clone_with_title' => 'Clone With', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'Extensão URI', 'uri_extension_description' => '

    A nova extensão URI, sempre disponível, fornece APIs para analisar e modificar URIs e URLs seguindo os padrões RFC 3986 e WHATWG URL.

    Baseada nas bibliotecas uriparser (RFC 3986) e Lexbor (WHATWG URL).

    Saiba mais sobre esse recurso no blog da The PHP Foundation.

    ', - 'no_discard_title' => 'Atributo #[\NoDiscard]', + 'no_discard_title' => 'Atributo #[\NoDiscard]', 'no_discard_description' => '

    Ao marcar uma função com #[\NoDiscard], o PHP verificará se o valor retornado foi usado e emitirá um aviso caso não seja. Isso aumenta a segurança de APIs em que o retorno é importante, mas pode ser facilmente ignorado.

    O cast (void) pode ser usado para indicar que o valor está sendo descartado intencionalmente.

    ', 'persistent_curl_share_handles_title' => 'cURL Share Handles Persistentes', diff --git a/releases/8.5/languages/ru.php b/releases/8.5/languages/ru.php index 695ea9b579..8fa163b91a 100644 --- a/releases/8.5/languages/ru.php +++ b/releases/8.5/languages/ru.php @@ -14,23 +14,17 @@ 'key_features' => 'Основные функции PHP 8.5', 'key_features_description' => '

    Быстрее, лучше, доступнее для разработчиков.

    ', - 'features_pipe_operator_title' => 'Оператор Pipe', 'features_pipe_operator_description' => '

    Оператор |> позволяет связывать вызываемые объекты слева направо, передавая значения через несколько функций без промежуточных переменных.

    ', - 'features_persistent_curl_share_handles_title' => 'Постоянные дескрипторы cURL Share', 'features_persistent_curl_share_handles_description' => '

    Теперь дескрипторы могут сохраняться между несколькими запросами PHP, что позволяет избежать затрат на повторную инициализацию соединения с одними и теми же хостами.

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    Клонируйте объекты и обновляйте свойства с помощью нового синтаксиса clone(), который упрощает использование шаблона «with-er» для классов readonly.

    ', - 'features_uri_extension_title' => 'Модуль URI', 'features_uri_extension_description' => '

    В PHP 8.5 добавлен модуль URI для анализа, нормализации и обработки URL-адресов в соответствии со стандартами RFC 3986 и WHATWG URL.

    ', - 'features_no_discard_title' => 'Атрибут #[\NoDiscard]', 'features_no_discard_description' => '

    Атрибут #[\NoDiscard] выдаёт предупреждение, если возвращаемое значение не используется, что помогает предотвратить ошибки и повысить общую безопасность API.

    ', - 'features_fcc_in_const_expr_title' => 'Замыкания и вызовы первого класса в константных выражениях', 'features_fcc_in_const_expr_description' => '

    Статические замыкания и вызываемые объекты первого класса теперь могут использоваться в константных выражениях, таких как параметры атрибутов.

    ', 'pipe_operator_title' => 'Оператор Pipe', 'pipe_operator_description' => '

    Оператор Pipe позволяет связывать вызовы функций в цепочку без использования промежуточных переменных. Позволяет заменить множество «вложенных вызовов» цепочкой.

    Узнайте больше об этой функции в блоге PHP Foundation.

    ', - 'array_first_last_title' => 'Функции array_first() и array_last()', + 'array_first_last_title' => 'Функции array_first() и array_last()', 'array_first_last_description' => '

    Функции array_first() и array_last() возвращают первое или последнее значение массива, соответственно. Если массив пустой, возвращается null (что упрощает работу с оператором ??).

    ', 'clone_with_title' => 'Clone With', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'Модуль URI', 'uri_extension_description' => '

    Встроенный модуль URI предоставляет API для безопасного анализа и изменения URI и URL в соответствии со стандартами RFC 3986 и WHATWG URL.

    Работает на базе библиотек uriparser (RFC 3986) и Lexbor (WHATWG URL).

    Узнайте больше об этой функции в блоге PHP Foundation.

    ', - 'no_discard_title' => 'Атрибут #[\NoDiscard]', + 'no_discard_title' => 'Атрибут #[\NoDiscard]', 'no_discard_description' => '

    Добавив атрибут #[\NoDiscard] к функции, PHP будет проверять, используется ли возвращаемое значение, и выдавать предупреждение, если это не так. Позволяет повысить безопасность API, где возвращаемое значение важно, но про него можно легко забыть.

    Связанное приведение типов (void) может использоваться для указания, что значение намеренно не используется.

    ', 'persistent_curl_share_handles_title' => 'Постоянные дескрипторы cURL Share', diff --git a/releases/8.5/languages/tr.php b/releases/8.5/languages/tr.php index 7df1c908c9..1f0a6ca766 100644 --- a/releases/8.5/languages/tr.php +++ b/releases/8.5/languages/tr.php @@ -14,23 +14,17 @@ 'key_features' => 'PHP 8.5’in Temel Özellikleri', 'key_features_description' => '

    Daha hızlı, daha temiz ve geliştiriciler için tasarlanmış.

    ', - 'features_pipe_operator_title' => 'Pipe Operatörü', 'features_pipe_operator_description' => '

    |> operatörü, fonksiyonları soldan sağa zincirlemenizi sağlar ve değerleri ara değişken kullanmadan sorunsuz şekilde birden fazla fonksiyona geçirir.

    ', - 'features_persistent_curl_share_handles_title' => 'Kalıcı cURL Share Handle’lar', 'features_persistent_curl_share_handles_description' => '

    Handle’lar artık birden fazla PHP isteği boyunca kalıcı olabilir, aynı hostlara tekrar bağlantı başlatma maliyetini ortadan kaldırır.

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    Nesneleri klonlarken özellikleri yeni clone() sözdizimi ile güncellemek mümkündür, bu da readonly sınıflar için "with-er" desenini basitleştirir.

    ', - 'features_uri_extension_title' => 'URI Uzantısı', 'features_uri_extension_description' => '

    PHP 8.5, RFC 3986 ve WHATWG URL standartlarına uygun URL’leri ayrıştırmak, normalize etmek ve yönetmek için yerleşik bir URI uzantısı ekler.

    ', - 'features_no_discard_title' => '#[\NoDiscard] Özelliği', 'features_no_discard_description' => '

    #[\NoDiscard] özelliği, döndürülen değer kullanılmadığında uyarı verir, böylece hataları önler ve API güvenliğini artırır.

    ', - 'features_fcc_in_const_expr_title' => 'Sabit İfadelerde Closure’lar ve Birinci Sınıf Callable’lar', 'features_fcc_in_const_expr_description' => '

    Artık statik closure’lar ve birinci sınıf callable’lar sabit ifadelerde kullanılabilir, örneğin attribute parametrelerinde.

    ', 'pipe_operator_title' => 'Pipe Operatörü', 'pipe_operator_description' => '

    Pipe operatörü, fonksiyon çağrılarını ara değişkenlerle uğraşmadan zincirlemenizi sağlar. Bu, iç içe geçmiş birçok çağrıyı ileri doğru okunabilecek bir zincir ile değiştirmenize olanak tanır.

    Bu özelliğin arka planını öğrenmek için PHP Foundation blogu’na bakabilirsiniz.

    ', - 'array_first_last_title' => 'array_first() ve array_last() fonksiyonları', + 'array_first_last_title' => 'array_first() ve array_last() fonksiyonları', 'array_first_last_description' => '

    array_first() ve array_last() fonksiyonları sırasıyla bir dizinin ilk veya son değerini döndürür. Eğer dizi boşsa null döner (bu, ?? operatörü ile kullanımı kolaylaştırır).

    ', 'clone_with_title' => 'Clone With', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'URI Uzantısı', 'uri_extension_description' => '

    Yeni her zaman kullanılabilir URI uzantısı, URI ve URL’leri güvenli bir şekilde ayrıştırmak ve düzenlemek için API sağlar. RFC 3986 ve WHATWG URL standartlarına uygundur.

    uriparser (RFC 3986) ve Lexbor (WHATWG URL) kütüphaneleri tarafından desteklenmektedir.

    Bu özelliğin arka planını öğrenmek için PHP Foundation blogu’na bakabilirsiniz.

    ', - 'no_discard_title' => '#[\NoDiscard] Özelliği', + 'no_discard_title' => '#[\NoDiscard] Özelliği', 'no_discard_description' => '

    Bir fonksiyona #[\NoDiscard] ekleyerek PHP, döndürülen değerin kullanılıp kullanılmadığını kontrol eder ve kullanılmadığında uyarı verir. Bu, döndürülen değerin önemli olduğu API’lerde hataları önler.

    ', 'persistent_curl_share_handles_title' => 'Kalıcı cURL Paylaşılan Handle’lar', diff --git a/releases/8.5/languages/uk.php b/releases/8.5/languages/uk.php index 9553251c70..8cc6d13257 100644 --- a/releases/8.5/languages/uk.php +++ b/releases/8.5/languages/uk.php @@ -14,23 +14,17 @@ 'key_features' => 'Ключові можливості PHP 8.5', 'key_features_description' => '

    Швидший, зрозуміліший, створений для розробників.

    ', - 'features_pipe_operator_title' => 'Оператор Pipe', 'features_pipe_operator_description' => '

    Оператор |> дозволяє об\'єднувати виклики у ланцюжок зліва направо, плавно передаючи значення через кілька функцій без проміжних змінних.

    ', - 'features_persistent_curl_share_handles_title' => 'Постійні cURL-дескриптори', 'features_persistent_curl_share_handles_description' => '

    Дескриптори тепер можуть зберігатися між декількома PHP-запитами, що дозволяє уникнути витрат на повторну ініціалізацію з\'єднання з тими самими хостами.

    ', - 'features_clone_with_title' => 'Конструкція Clone With', 'features_clone_with_description' => '

    Клонуйте об\'єкти та оновлюйте властивості за допомогою нової синтаксичної конструкції clone(), яка спрощує використання шаблону «with-er» для readonly класів.

    ', - 'features_uri_extension_title' => 'Розширення URI', 'features_uri_extension_description' => '

    У PHP 8.5 додано розширення URI для аналізу, нормалізації та обробки URL-адрес відповідно до стандартів RFC 3986 і WHATWG URL.

    ', - 'features_no_discard_title' => 'Атрибут #[\NoDiscard]', 'features_no_discard_description' => '

    Атрибут #[\NoDiscard] попереджає, коли повернене значення не використовується, допомагаючи запобігти помилкам і підвищити загальну безпеку API.

    ', - 'features_fcc_in_const_expr_title' => 'Замикання та callable-вирази першого класу в константних виразах', 'features_fcc_in_const_expr_description' => '

    Статичні замикання та callable-вирази першого класу тепер можна використовувати в константних виразах, таких як параметри атрибутів.

    ', 'pipe_operator_title' => 'Оператор Pipe', 'pipe_operator_description' => '

    Оператор Pipe дозволяє об\'єднувати виклики функцій у ланцюжок без використання проміжних змінних. Це дозволяє замінити багато «вкладених викликів» ланцюжком, який можна читати вперед, а не зсередини назовні.

    Дізнайтеся більше про історію створення цієї функції у блозі PHP Foundation.

    ', - 'array_first_last_title' => 'Функції array_first() і array_last()', + 'array_first_last_title' => 'Функції array_first() і array_last()', 'array_first_last_description' => '

    Функції array_first() і array_last() повертають перше або останнє значення масиву відповідно. Якщо масив порожній, повертається null (що полегшує компонування з оператором ??).

    ', 'clone_with_title' => 'Конструкція Clone With', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'Розширення URI', 'uri_extension_description' => '

    Нове вбудоване розширення URI надає API для безпечного аналізу та зміни URI та URL згідно зі стандартами RFC 3986 і WHATWG URL.

    Працює на основі бібліотек uriparser (RFC 3986) і Lexbor (WHATWG URL).

    Дізнайтеся більше про історію створення цієї функції у блозі PHP Foundation.

    ', - 'no_discard_title' => 'Атрибут #[\NoDiscard]', + 'no_discard_title' => 'Атрибут #[\NoDiscard]', 'no_discard_description' => '

    Після додавання атрибуту #[\NoDiscard] до функції PHP перевірятиме, чи використовується повернене значення, і викликатиме попередження, якщо ні. Це дозволяє підвищити безпеку API, де повернене значення є важливим, але його можна випадково проігнорувати.

    Відповідне приведення типу (void) може використовуватися як вказівка, що значення не використовується навмисно.

    ', 'persistent_curl_share_handles_title' => 'Постійні cURL-дескриптори', diff --git a/releases/8.5/languages/vi.php b/releases/8.5/languages/vi.php index 2901def619..a9bedcdfc3 100644 --- a/releases/8.5/languages/vi.php +++ b/releases/8.5/languages/vi.php @@ -14,23 +14,17 @@ 'key_features' => 'Các tính năng chính trong PHP 8.5', 'key_features_description' => '

    Nhanh hơn, sạch hơn, và được tối ưu cho lập trình viên.

    ', - 'features_pipe_operator_title' => 'Toán tử Pipe', 'features_pipe_operator_description' => '

    Toán tử |> cho phép chuỗi hóa các lệnh gọi từ trái sang phải, truyền giá trị mượt mà qua nhiều hàm mà không cần biến trung gian.

    ', - 'features_persistent_curl_share_handles_title' => 'Persistent cURL Share Handles', 'features_persistent_curl_share_handles_description' => '

    Các Handle hiện có thể duy trì qua nhiều request PHP, giúp tránh chi phí khởi tạo kết nối lặp lại tới cùng một host.

    ', - 'features_clone_with_title' => 'Clone With (Sao chép kèm sửa đổi)', 'features_clone_with_description' => '

    Sao chép đối tượng và cập nhật thuộc tính với cú pháp clone() mới, giúp triển khai mô hình "with-er" đơn giản hơn cho các lớp readonly.

    ', - 'features_uri_extension_title' => 'URI Extension', 'features_uri_extension_description' => '

    PHP 8.5 bổ sung một extension URI tích hợp để phân tích, chuẩn hóa và xử lý URL theo các tiêu chuẩn RFC 3986WHATWG URL.

    ', - 'features_no_discard_title' => 'Attribute #[\NoDiscard]', 'features_no_discard_description' => '

    Attribute #[\NoDiscard] sẽ đưa ra cảnh báo khi giá trị trả về không được sử dụng, giúp ngăn ngừa sai sót và cải thiện tính an toàn của API.

    ', - 'features_fcc_in_const_expr_title' => 'Closures và First-Class Callables trong biểu thức hằng số', 'features_fcc_in_const_expr_description' => '

    Các Static closure và first-class callable hiện có thể được dùng trong các biểu thức hằng số, chẳng hạn như tham số của attribute.

    ', 'pipe_operator_title' => 'Toán tử Pipe', 'pipe_operator_description' => '

    Toán tử pipe cho phép kết nối các lệnh gọi hàm với nhau mà không cần xử lý biến trung gian. Điều này giúp thay thế các "lệnh gọi lồng nhau" bằng một chuỗi có thể đọc từ trước ra sau, thay vì từ trong ra ngoài.

    Tìm hiểu thêm về lịch sử tính năng này tại Blog của PHP Foundation.

    ', - 'array_first_last_title' => 'Hàm array_first() và array_last()', + 'array_first_last_title' => 'Hàm array_first()array_last()', 'array_first_last_description' => '

    Các hàm array_first()array_last() trả về giá trị đầu tiên hoặc cuối cùng của một mảng. Nếu mảng trống, giá trị null sẽ được trả về (giúp dễ dàng kết hợp với toán tử ??).

    ', 'clone_with_title' => 'Clone With (Sao chép kèm sửa đổi)', @@ -39,7 +33,7 @@ 'uri_extension_title' => 'URI Extension', 'uri_extension_description' => '

    Extension URI mới (luôn sẵn có) cung cấp các API để phân tích và chỉnh sửa URI/URL một cách an toàn theo tiêu chuẩn RFC 3986 và WHATWG URL.

    Được vận hành bởi các thư viện uriparser (RFC 3986) và Lexbor (WHATWG URL).

    ', - 'no_discard_title' => 'Attribute #[\NoDiscard]', + 'no_discard_title' => 'Attribute #[\NoDiscard]', 'no_discard_description' => '

    Bằng cách thêm attribute #[\NoDiscard] vào một hàm, PHP sẽ kiểm tra xem giá trị trả về có được tiêu thụ hay không và phát cảnh báo nếu không. Điều này giúp tăng độ an toàn cho API khi giá trị trả về là quan trọng nhưng dễ bị bỏ quên.

    Ép kiểu (void) có thể được dùng để chỉ thị rằng giá trị đó cố tình không được sử dụng.

    ', 'persistent_curl_share_handles_title' => 'Persistent cURL Share Handles', diff --git a/releases/8.5/languages/zh.php b/releases/8.5/languages/zh.php index f37569e031..be10f394fa 100644 --- a/releases/8.5/languages/zh.php +++ b/releases/8.5/languages/zh.php @@ -18,23 +18,17 @@ 'key_features' => 'PHP 8.5 的主要特性', 'key_features_description' => '

    更快更简洁为开发者而生

    ', - 'features_pipe_operator_title' => '管道操作符', 'features_pipe_operator_description' => '

    |> 操作符允许从左到右连接可调用项,让数值在多个函数间顺畅传递,无需中间变量。

    ', - 'features_persistent_curl_share_handles_title' => '持久化 cURL Share 句柄', 'features_persistent_curl_share_handles_description' => '

    句柄现在可以在多个 PHP 请求之间保持,不再需要重复初始化到同一主机的连接。

    ', - 'features_clone_with_title' => 'Clone With', 'features_clone_with_description' => '

    使用新的 clone() 语法可以克隆对象并更新属性,让 readonly 类的 "with-er" 模式变得简单。

    ', - 'features_uri_extension_title' => 'URI 扩展', 'features_uri_extension_description' => '

    PHP 8.5 增加了内置的 URI 扩展,用于按照 RFC 3986WHATWG URL 标准解析、规范化和处理 URL。

    ', - 'features_no_discard_title' => '#[\NoDiscard] 属性', 'features_no_discard_description' => '

    #[\NoDiscard] 属性会在返回值未被使用时发出警告,有助于避免错误,提高 API 安全性。

    ', - 'features_fcc_in_const_expr_title' => '常量表达式中的闭包和 First-class 可调用', 'features_fcc_in_const_expr_description' => '

    静态闭包和 First-class 可调用现在可以用于常量表达式,例如属性参数。

    ', 'pipe_operator_title' => '管道操作符', 'pipe_operator_description' => '

    管道操作符允许将多个函数调用串联起来,而无需处理中间变量。它可以将许多“嵌套调用”替换成从左到右可读的链式结构。

    The PHP Foundation 的博客中了解该特性的更多背景。

    ', - 'array_first_last_title' => 'array_first() 与 array_last() 函数', + 'array_first_last_title' => 'array_first()array_last() 函数', 'array_first_last_description' => '

    array_first()array_last() 分别返回数组的第一个或最后一个值。若数组为空,则返回 null(方便与 ?? 操作符组合)。

    ', 'clone_with_title' => 'Clone With', @@ -43,7 +37,7 @@ 'uri_extension_title' => 'URI 扩展', 'uri_extension_description' => '

    全新的、始终可用的 URI 扩展提供了一组 API,可根据 RFC 3986 和 WHATWG URL 标准安全地解析和修改 URI 与 URL。

    uriparser(RFC 3986)和 Lexbor(WHATWG URL)库驱动。

    The PHP Foundation 的博客中了解更多背景。

    ', - 'no_discard_title' => '#[\NoDiscard] 属性', + 'no_discard_title' => '#[\NoDiscard] 属性', 'no_discard_description' => '

    为函数添加 #[\NoDiscard] 属性后,PHP 会检查返回值是否被使用,若未使用则发出警告。这样可以提高 API 的安全性,避免关键返回值被忽略。

    可以使用 (void) 来显式表示“我就是不使用这个结果”。

    ', 'persistent_curl_share_handles_title' => '持久化 cURL Share 句柄', diff --git a/releases/8.5/release.inc b/releases/8.5/release.inc index 8ed4647e54..d59c100981 100644 --- a/releases/8.5/release.inc +++ b/releases/8.5/release.inc @@ -288,7 +288,7 @@ echo ReleasePage::getHeroSection( d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418"/> - + @@ -304,7 +304,7 @@ echo ReleasePage::getHeroSection( d="M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 0 0-3.7-3.7 48.678 48.678 0 0 0-7.324 0 4.006 4.006 0 0 0-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 0 0 3.7 3.7 48.656 48.656 0 0 0 7.324 0 4.006 4.006 0 0 0 3.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3-3 3"/> - + @@ -320,7 +320,7 @@ echo ReleasePage::getHeroSection( d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"/> - + @@ -335,7 +335,7 @@ echo ReleasePage::getHeroSection( d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"/> - + @@ -351,7 +351,7 @@ echo ReleasePage::getHeroSection( d="M6 13.5V3.75m0 9.75a1.5 1.5 0 0 1 0 3m0-3a1.5 1.5 0 0 0 0 3m0 3.75V16.5m12-3V3.75m0 9.75a1.5 1.5 0 0 1 0 3m0-3a1.5 1.5 0 0 0 0 3m0 3.75V16.5m-6-9V3.75m0 3.75a1.5 1.5 0 0 1 0 3m0-3a1.5 1.5 0 0 0 0 3m0 9.75V10.5"/> - + @@ -367,7 +367,7 @@ echo ReleasePage::getHeroSection( d="M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25A2.25 2.25 0 0 1 13.5 18v-2.25Z"/> - + From fe872d4352ae2137e446e21fd138d4c5e7aa4280 Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Wed, 10 Jun 2026 10:35:41 -0500 Subject: [PATCH 5/5] Switch to CSS animations for hero background This allows Playwright to automatically disable the animations for stable screenshot testing. --- playwright.config.ts | 5 +++++ src/Themes/ReleasePage.php | 14 +++++++------- styles/php85.css | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index 20e28bf564..0675282122 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -14,6 +14,11 @@ export default defineConfig({ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: 'html', + expect: { + toHaveScreenshot: { + animations: 'disabled', + }, + }, /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ diff --git a/src/Themes/ReleasePage.php b/src/Themes/ReleasePage.php index ac4fee6fa5..7419d43752 100644 --- a/src/Themes/ReleasePage.php +++ b/src/Themes/ReleasePage.php @@ -36,15 +36,15 @@ public static function getHeroSection( return << - + diff --git a/styles/php85.css b/styles/php85.css index a9339c08b4..71f7399726 100644 --- a/styles/php85.css +++ b/styles/php85.css @@ -900,6 +900,40 @@ a { position: absolute } +.hero-orb-1-x, +.hero-orb-1-y, +.hero-orb-1-r, +.hero-orb-2-x, +.hero-orb-2-y, +.hero-orb-2-r, +.hero-orb-3-x, +.hero-orb-3-y, +.hero-orb-3-r { + transform-box: view-box; + transform-origin: 50% 50% +} + +.hero-orb-1-x { animation: hero-orb1-x 10s linear infinite alternate } +.hero-orb-1-y { animation: hero-orb1-y 10.5s linear infinite alternate } +.hero-orb-1-r { animation: hero-orb-rotate-fwd 7s linear infinite } + +.hero-orb-2-x { animation: hero-orb2-x 11.5s linear infinite alternate } +.hero-orb-2-y { animation: hero-orb2-y 12s linear infinite alternate } +.hero-orb-2-r { animation: hero-orb-rotate-fwd 12s linear infinite } + +.hero-orb-3-x { animation: hero-orb3-x 12.5s linear infinite alternate } +.hero-orb-3-y { animation: hero-orb3-y 6s linear infinite alternate } +.hero-orb-3-r { animation: hero-orb-rotate-rev 9s linear infinite } + +@keyframes hero-orb1-x { from { transform: translateX(25%) } to { transform: translateX(0%) } } +@keyframes hero-orb1-y { from { transform: translateY(0%) } to { transform: translateY(25%) } } +@keyframes hero-orb2-x { from { transform: translateX(-25%) } to { transform: translateX(0%) } } +@keyframes hero-orb2-y { from { transform: translateY(0%) } to { transform: translateY(50%) } } +@keyframes hero-orb3-x { from { transform: translateX(0%) } to { transform: translateX(25%) } } +@keyframes hero-orb3-y { from { transform: translateY(0%) } to { transform: translateY(25%) } } +@keyframes hero-orb-rotate-fwd { from { transform: rotate(0deg) } to { transform: rotate(360deg) } } +@keyframes hero-orb-rotate-rev { from { transform: rotate(360deg) } to { transform: rotate(0deg) } } + .hero-badge { margin-bottom: calc(var(--spacing) * 6); background-color: #ffffffa6;