From 260fcbea3475459052c3ed3338c880a4d365ff5f Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Thu, 25 Jun 2026 19:43:05 +0000 Subject: [PATCH 1/8] Code Modernization: Use `array_any()` in `WP_REST_Comments_Controller`. This commit replaces a `foreach` loop in `::check_post_type_supports_notes()` that iterates the editor supports, returns `true` as soon as an element has non-empty notes, and otherwise falls through to `false`. That is exactly what PHP 8.4's `array_any()` expresses in a single, more readable call. WordPress core includes a polyfill for `array_any()` on PHP < 8.4 as of WordPress 6.8, so the change works on every supported PHP version without raising the minimum requirement. Follow-up to [59783], [62550], [62553]. Props Soean. See #65519. git-svn-id: https://develop.svn.wordpress.org/trunk@62564 602fd350-edb4-49c9-b593-d223f7449a82 --- .../endpoints/class-wp-rest-comments-controller.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php index f462928847c77..d14aefb1f6308 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php @@ -2049,17 +2049,15 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { */ private function check_post_type_supports_notes( $post_type ) { $supports = get_all_post_type_supports( $post_type ); + if ( ! isset( $supports['editor'] ) ) { return false; } + if ( ! is_array( $supports['editor'] ) ) { return false; } - foreach ( $supports['editor'] as $item ) { - if ( ! empty( $item['notes'] ) ) { - return true; - } - } - return false; + + return array_any( $supports['editor'], fn( $item ) => ! empty( $item['notes'] ) ); } } From 752d544e9ab7bb5bd9948203dc65a2f97bc43015 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Fri, 26 Jun 2026 22:49:12 +0000 Subject: [PATCH 2/8] Docs: Correct `$format` default in `get_next_post_link()` and `next_post_link()`. Follow-up to [37254]. Props ishihara-takashi, sabernhardt, khokansardar, mindctrl, SergeyBiryukov. Fixes #65541. git-svn-id: https://develop.svn.wordpress.org/trunk@62565 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/link-template.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php index cfff8b6525e10..223d6b5548fc6 100644 --- a/src/wp-includes/link-template.php +++ b/src/wp-includes/link-template.php @@ -2291,7 +2291,7 @@ function previous_post_link( $format = '« %link', $link = '%title', $in_sa * * @since 3.7.0 * - * @param string $format Optional. Link anchor format. Default '« %link'. + * @param string $format Optional. Link anchor format. Default '%link »'. * @param string $link Optional. Link permalink format. Default '%title'. * @param bool $in_same_term Optional. Whether link should be in the same taxonomy term. * Default false. @@ -2311,7 +2311,7 @@ function get_next_post_link( $format = '%link »', $link = '%title', $in_sa * * @see get_next_post_link() * - * @param string $format Optional. Link anchor format. Default '« %link'. + * @param string $format Optional. Link anchor format. Default '%link »'. * @param string $link Optional. Link permalink format. Default '%title'. * @param bool $in_same_term Optional. Whether link should be in the same taxonomy term. * Default false. From 2a5a37e54b1474f24e3f49a9345b22c49ff6e2e4 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Sat, 27 Jun 2026 22:17:32 +0000 Subject: [PATCH 3/8] Build/Test Tools: Correct `git pull` command for syncing with upstream. Follow-up to [61202]. Props mkrndmane, mukesh27, khokansardar, dhruvang21, SergeyBiryukov. Fixes #65540. git-svn-id: https://develop.svn.wordpress.org/trunk@62566 602fd350-edb4-49c9-b593-d223f7449a82 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5201a5180c1da..820b54759c907 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ You can get started using the local development environment with these steps: 1. Then clone the forked repository to your computer using `git clone https://github.com//wordpress-develop.git`. 1. Navigate into the directory for the cloned repository using `cd wordpress-develop`. 1. Add the origin repo as an `upstream` remote via `git remote add upstream https://github.com/WordPress/wordpress-develop.git`. -1. Then you can keep your branches up to date via `git pull --ff upstream/trunk`, for example. +1. Then you can keep your branches up to date via `git pull --ff upstream trunk`, for example. Alternatively, if you have the [GitHub CLI](https://cli.github.com/) installed, you can simply run `gh repo fork WordPress/wordpress-develop --clone --remote` ([docs](https://cli.github.com/manual/gh_repo_fork)). This command will: 1. Fork the repository to your account (use the `--org` flag to clone into an organization). From e0e6680d69097e330921898e1747030e7d204f48 Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 28 Jun 2026 20:38:14 +0000 Subject: [PATCH 4/8] Administration: Fix selected/active buttons in High Contrast Mode. Follow up to [62467]. Replaces original fix, which turned out to be insufficient. Replaces pseudo-elements with more standard outlines, shifted in scale for visibility. Props sabernhardt, wildworks, apermo, joedolson. Fixes #65153. git-svn-id: https://develop.svn.wordpress.org/trunk@62567 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/css/buttons.css | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/wp-includes/css/buttons.css b/src/wp-includes/css/buttons.css index 09457ce6a4dc5..967970a9ba461 100644 --- a/src/wp-includes/css/buttons.css +++ b/src/wp-includes/css/buttons.css @@ -194,7 +194,8 @@ TABLE OF CONTENTS: color: var(--wp-admin-theme-color-darker-20, #183ad6); border-color: var(--wp-admin-theme-color, #3858e9); box-shadow: inset 0 2px 6px -2px var(--wp-admin-theme-color-darker-20); - position: relative; + outline: 3px solid transparent; + outline-offset: -3px; } .wp-core-ui .button.active:focus { @@ -202,19 +203,7 @@ TABLE OF CONTENTS: color: var(--wp-admin-theme-color-darker-20, #183ad6); border-color: var(--wp-admin-theme-color-darker-20, #183ad6); box-shadow: inset 0 2px 6px -2px var(--wp-admin-theme-color-darker-20), 0 0 0 var(--wp-admin-border-width-focus, 1.5px) var(--wp-admin-theme-color, #3858e9); -} - -/* Only visible in Windows High Contrast mode */ -.wp-core-ui .button.active:before { - content: ""; - display: block; - position: absolute; - width: 100%; - height: 0; - border-top: 3px solid transparent; - bottom: 0; - left: 0; - box-sizing: border-box; + outline-width: 4px; } .wp-core-ui .button[disabled], From 8b36984e643a15ca94a9bffff3f9e92d29ac12e9 Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 28 Jun 2026 21:41:22 +0000 Subject: [PATCH 5/8] Administration: Fix cursor on first submenu list item in admin menu. The first submenu item in the collapsed view of the admin menu accepts a click event to navigate, but does not have `cursor: pointer` to indicate that it's interactive. These were removed in [51684], but this specific case (JS activate, menu collapsed, first list item) should remain. Props mazharulrobeen, sumitsingh, sabernhardt, swapnil1010, joedolson. Fixes #65250. git-svn-id: https://develop.svn.wordpress.org/trunk@62568 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/css/admin-menu.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wp-admin/css/admin-menu.css b/src/wp-admin/css/admin-menu.css index c4b32ac4b9e87..2b665f583484f 100644 --- a/src/wp-admin/css/admin-menu.css +++ b/src/wp-admin/css/admin-menu.css @@ -417,6 +417,10 @@ ul#adminmenu > li.current > a.current:after { border-color: transparent; } +.js #adminmenu .wp-submenu .wp-submenu-head { + cursor: pointer; +} + #adminmenu li.current, .folded #adminmenu li.wp-menu-open { border: 0 none; From cdf2433e06650ac5d007ccbffbe03c089bd7573a Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Sun, 28 Jun 2026 23:21:09 +0000 Subject: [PATCH 6/8] Build/Test Tools: Update GitHub CLI fork command in `README.md`. This resolves an error when running the documented command as of GitHub CLI 2.88.0: {{{ the `--remote` flag is unsupported when a repository argument is provided. }}} Reference: [https://github.com/cli/cli/pull/12375 GitHub CLI: fix: error when --remote flag used with repo argument]. Follow-up to [61202]. Props mkrndmane, khokansardar. Fixes #65542. git-svn-id: https://develop.svn.wordpress.org/trunk@62569 602fd350-edb4-49c9-b593-d223f7449a82 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 820b54759c907..bb6d06c034651 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ You can get started using the local development environment with these steps: 1. Add the origin repo as an `upstream` remote via `git remote add upstream https://github.com/WordPress/wordpress-develop.git`. 1. Then you can keep your branches up to date via `git pull --ff upstream trunk`, for example. -Alternatively, if you have the [GitHub CLI](https://cli.github.com/) installed, you can simply run `gh repo fork WordPress/wordpress-develop --clone --remote` ([docs](https://cli.github.com/manual/gh_repo_fork)). This command will: +Alternatively, if you have the [GitHub CLI](https://cli.github.com/) installed, you can simply run `gh repo fork WordPress/wordpress-develop --clone` ([docs](https://cli.github.com/manual/gh_repo_fork)). This command will: 1. Fork the repository to your account (use the `--org` flag to clone into an organization). 1. Clone the repository to your machine. 1. Add `WordPress/wordpress-develop` as `upstream` and set it to the default `remote` repository From f5523819aa419d97a9bade437a7bbe7d685e9505 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Mon, 29 Jun 2026 08:34:46 +0000 Subject: [PATCH 7/8] Build Tools: Replace deprecated browserslist --update-db command. Replaces the deprecated `--update-db` command in the `browserslist:update` Grunt task with `update-browserslist-db@latest`. Props ekla, sergeybiryukov, masteradhoc. Fixes #64900. git-svn-id: https://develop.svn.wordpress.org/trunk@62570 602fd350-edb4-49c9-b593-d223f7449a82 --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index dae8c3e972e4c..ab56358b8f60d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2370,7 +2370,7 @@ module.exports = function(grunt) { grunt.registerTask( 'browserslist:update', 'Update the local database of browser supports', function() { grunt.log.writeln( `Updating browsers list` ); - spawn( 'npx', [ 'browserslist@latest', '--update-db' ], { + spawn( 'npx', [ 'update-browserslist-db@latest' ], { cwd: __dirname, stdio: 'inherit', } ); From 2a95d7fa505845f06e576e31e2c22cee322c6209 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 29 Jun 2026 13:59:24 +0200 Subject: [PATCH 8/8] Docs: Clarify HTML Processor subtree traversal --- .../html-api/class-wp-html-processor.php | 91 ++++++++++++++++++- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 10f3ee3e2dd0f..481f230704d03 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -767,9 +767,52 @@ public function next_tag( $query = null ): bool { /** * Finds the next token in the HTML document. * - * This doesn't currently have a way to represent non-tags and doesn't process - * semantic rules for text nodes. For access to the raw tokens consider using - * WP_HTML_Tag_Processor instead. + * A token is a span of the document with its own meaning: a tag opener or + * closer, a text node, a comment, or a doctype declaration. Use this method + * instead of {@see WP_HTML_Processor::next_tag} when text or other non-tag + * content matters, while keeping the HTML Processor's structural awareness. + * + * Unlike the Tag Processor's lexical scan, the HTML Processor visits a + * closing token for every element it opens and can continue to process, + * including elements the HTML specification closes implicitly and elements + * left unclosed at the end of the input. + * + * A walk also visits elements the parser inserted into the document tree, + * because HTML defines implied structure. For example, `` is + * visited as TABLE > TBODY > TR, with the implied TBODY appearing in + * {@see WP_HTML_Processor::get_breadcrumbs} and adding to + * {@see WP_HTML_Processor::get_current_depth}. Anchor depth-bounded walks + * on the depth recorded at a matched element rather than on absolute depth + * numbers. + * + * `next_token()` does not stop when an element matched by an earlier + * `next_tag()` call closes. Bound subtree walks with depth or breadcrumbs. + * + * Example: + * + * // Collect the text content of the first LI element. + * $processor = WP_HTML_Processor::create_fragment( '
  • Buy milk today.
' ); + * if ( $processor->next_tag( 'LI' ) ) { + * $li_depth = $processor->get_current_depth(); + * $text = ''; + * + * while ( $processor->next_token() && $processor->get_current_depth() >= $li_depth ) { + * if ( '#text' === $processor->get_token_type() ) { + * $text .= $processor->get_modifiable_text(); + * } + * } + * + * // $text is 'Buy milk today.' + * } + * + * The `>=` comparison is required. A nested child closer, such as + * `` above, reports the same depth as the LI opener did; a `>` + * comparison would stop early and drop the trailing text. + * + * For repeated regions, prefer one `next_token()` loop with explicit state + * over nested loops. Every call advances the same cursor, so an inner loop + * can consume the boundary token or next sibling that the outer loop expected + * to see. * * @since 6.5.0 Added for internal support; do not use. * @since 6.7.2 Refactored so subclasses may extend. @@ -1204,6 +1247,23 @@ public function get_breadcrumbs(): array { /** * Returns the nesting depth of the current location in the document. * + * The depth counts every node from the root down to and including the + * currently-matched token, so it matches the length of the array returned by + * {@see WP_HTML_Processor::get_breadcrumbs}. Non-element tokens count + * themselves: when matched on a text node directly inside BODY, the depth is + * 3: HTML > BODY > #text. + * + * When the processor is matched on a closing tag token, the closed element + * has already been removed from the stack of open elements. The reported + * depth is that of the remaining parent context: one less than the depth + * reported at the matching opening tag. + * + * This gives a reliable way to visit every token inside an element: record + * the depth when matched on its opening tag and continue while the depth + * remains at or above that value. Only the element's own closer reports a + * shallower depth; nested child closers still report a depth within the + * subtree. + * * Example: * * $processor = WP_HTML_Processor::create_fragment( '

' ); @@ -1218,10 +1278,33 @@ public function get_breadcrumbs(): array { * $processor->next_token(); * 4 === $processor->get_current_depth(); * - * // The P element is closed during `next_token()` so the depth is decreased to reflect that. + * // The processor is now matched on the

closing token. The P + * // element has already been removed from the stack of open elements, + * // so the depth reflects its parent context: one less than at

. * $processor->next_token(); * 3 === $processor->get_current_depth(); * + * // Likewise on the closing token, the depth has returned to + * // that of the BODY context. + * $processor->next_token(); + * 2 === $processor->get_current_depth(); + * + * Example: + * + * // Visit every token inside the first UL element. + * $processor = WP_HTML_Processor::create_fragment( $html ); + * if ( $processor->next_tag( 'UL' ) ) { + * $ul_depth = $processor->get_current_depth(); + * + * while ( $processor->next_token() && $processor->get_current_depth() >= $ul_depth ) { + * // Matched on each token inside the UL, including the openers + * // and closers of nested elements. + * } + * } + * + * In break-condition form, break when the depth drops below the depth + * recorded at the opener (`< $ul_depth`), never when it is equal. + * * @since 6.6.0 * * @return int Nesting-depth of current location in the document.