Skip to content

Commit 6bf0d4a

Browse files
committed
Merge branch 'trunk' into block_styles_on_demand_in_classic_themes
2 parents 65a9250 + 4f3c923 commit 6bf0d4a

28 files changed

+1059
-91
lines changed

.github/workflows/reusable-test-gutenberg-build-process.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ jobs:
3434
# - Checks out the Gutenberg plugin into the plugins directory.
3535
# - Sets up Node.js.
3636
# - Logs debug information about the GitHub Action runner.
37-
# - Installs Core npm dependencies.
3837
# - Installs Gutenberg npm dependencies.
3938
# - Runs the Gutenberg build process.
39+
# - Installs Core npm dependencies.
4040
# - Builds WordPress to run from the relevant location (src or build).
4141
# - Builds Gutenberg.
4242
# - Ensures version-controlled files are not modified or deleted.
@@ -78,9 +78,6 @@ jobs:
7878
curl --version
7979
git --version
8080
81-
- name: Install Core Dependencies
82-
run: npm ci
83-
8481
- name: Install Gutenberg Dependencies
8582
run: npm ci
8683
working-directory: ${{ env.GUTENBERG_DIRECTORY }}
@@ -89,6 +86,9 @@ jobs:
8986
run: npm run build
9087
working-directory: ${{ env.GUTENBERG_DIRECTORY }}
9188

89+
- name: Install Core Dependencies
90+
run: npm ci
91+
9292
- name: Build WordPress to run from ${{ inputs.directory }}
9393
run: npm run ${{ inputs.directory == 'src' && 'build:dev' || 'build' }}
9494

src/js/_enqueues/admin/user-profile.js

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
$form,
2121
originalFormContent,
2222
$passwordWrapper,
23-
successTimeout;
23+
successTimeout,
24+
isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false,
25+
ua = navigator.userAgent.toLowerCase(),
26+
isSafari = window.safari !== 'undefined' && typeof window.safari === 'object',
27+
isFirefox = ua.indexOf( 'firefox' ) !== -1;
2428

2529
function generatePassword() {
2630
if ( typeof zxcvbn !== 'function' ) {
@@ -80,6 +84,8 @@
8084
$pass1.removeClass( 'short bad good strong' );
8185
showOrHideWeakPasswordCheckbox();
8286
} );
87+
88+
bindCapsLockWarning( $pass1 );
8389
}
8490

8591
function resetToggle( show ) {
@@ -213,6 +219,8 @@
213219
} else {
214220
// Password field for the login form.
215221
$pass1 = $( '#user_pass' );
222+
223+
bindCapsLockWarning( $pass1 );
216224
}
217225

218226
/*
@@ -332,6 +340,79 @@
332340
}
333341
}
334342

343+
/**
344+
* Bind Caps Lock detection to a password input field.
345+
*
346+
* @param {jQuery} $input The password input field.
347+
*/
348+
function bindCapsLockWarning( $input ) {
349+
var $capsWarning,
350+
$capsIcon,
351+
$capsText,
352+
capsLockOn = false;
353+
354+
// Skip warning on macOS Safari + Firefox (they show native indicators).
355+
if ( isMac && ( isSafari || isFirefox ) ) {
356+
return;
357+
}
358+
359+
$capsWarning = $( '<div id="caps-warning" class="caps-warning"></div>' );
360+
$capsIcon = $( '<span class="caps-icon" aria-hidden="true"><svg viewBox="0 0 24 26" xmlns="http://www.w3.org/2000/svg" fill="#3c434a" stroke="#3c434a" stroke-width="0.5"><path d="M12 5L19 15H16V19H8V15H5L12 5Z"/><rect x="8" y="21" width="8" height="1.5" rx="0.75"/></svg></span>' );
361+
$capsText = $( '<span>', { 'class': 'caps-warning-text', text: __( 'Caps lock is on.' ) } );
362+
$capsWarning.append( $capsIcon, $capsText );
363+
364+
$input.parent( 'div' ).append( $capsWarning );
365+
366+
$input.on( 'keydown', function( jqEvent ) {
367+
var event = jqEvent.originalEvent;
368+
369+
// Skip if key is not a printable character.
370+
// Key length > 1 usually means non-printable (e.g., "Enter", "Tab").
371+
if ( event.ctrlKey || event.metaKey || event.altKey || ! event.key || event.key.length !== 1 ) {
372+
return;
373+
}
374+
375+
var state = isCapsLockOn( event );
376+
377+
// React when the state changes or if caps lock is on when the user starts typing.
378+
if ( state !== capsLockOn ) {
379+
capsLockOn = state;
380+
381+
if ( capsLockOn ) {
382+
$capsWarning.show();
383+
// Don't duplicate existing screen reader Caps lock notifications.
384+
if ( event.key !== 'CapsLock' ) {
385+
wp.a11y.speak( __( 'Caps lock is on.' ), 'assertive' );
386+
}
387+
} else {
388+
$capsWarning.hide();
389+
}
390+
}
391+
} );
392+
393+
$input.on( 'blur', function() {
394+
if ( ! document.hasFocus() ) {
395+
return;
396+
}
397+
capsLockOn = false;
398+
$capsWarning.hide();
399+
} );
400+
}
401+
402+
/**
403+
* Determines if Caps Lock is currently enabled.
404+
*
405+
* On macOS Safari and Firefox, the native warning is preferred,
406+
* so this function returns false to suppress custom warnings.
407+
*
408+
* @param {KeyboardEvent} e The keydown event object.
409+
*
410+
* @return {boolean} True if Caps Lock is on, false otherwise.
411+
*/
412+
function isCapsLockOn( event ) {
413+
return event.getModifierState( 'CapsLock' );
414+
}
415+
335416
function showOrHideWeakPasswordCheckbox() {
336417
var passStrengthResult = $('#pass-strength-result');
337418

src/js/_enqueues/lib/nav-menu.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,14 +1406,25 @@
14061406

14071407
updateQuickSearchResults : function(input) {
14081408
var panel, params,
1409-
minSearchLength = 2,
1410-
q = input.val();
1409+
minSearchLength = 1,
1410+
q = input.val(),
1411+
pageSearchChecklist = $( '#page-search-checklist' );
14111412

14121413
/*
1413-
* Minimum characters for a search. Also avoid a new Ajax search when
1414-
* the pressed key (e.g. arrows) doesn't change the searched term.
1414+
* Avoid a new Ajax search when the pressed key (e.g. arrows)
1415+
* doesn't change the searched term.
14151416
*/
1416-
if ( q.length < minSearchLength || api.lastSearch == q ) {
1417+
if ( api.lastSearch == q ) {
1418+
return;
1419+
}
1420+
1421+
/*
1422+
* Reset results when search is less than or equal to
1423+
* minimum characters for searched term.
1424+
*/
1425+
if ( q.length <= minSearchLength ) {
1426+
pageSearchChecklist.empty();
1427+
wp.a11y.speak( wp.i18n.__( 'Search results cleared' ) );
14171428
return;
14181429
}
14191430

@@ -1770,12 +1781,14 @@
17701781
$item;
17711782

17721783
if( ! $items.length ) {
1784+
let noResults = wp.i18n.__( 'No results found.' );
17731785
const li = $( '<li>' );
1774-
const p = $( '<p>', { text: wp.i18n.__( 'No results found.' ) } );
1786+
const p = $( '<p>', { text: noResults } );
17751787
li.append( p );
17761788
$('.categorychecklist', panel).empty().append( li );
17771789
$( '.spinner', panel ).removeClass( 'is-active' );
17781790
wrapper.addClass( 'has-no-menu-item' );
1791+
wp.a11y.speak( noResults, 'assertive' );
17791792
return;
17801793
}
17811794

@@ -1802,6 +1815,7 @@
18021815
});
18031816

18041817
$('.categorychecklist', panel).html( $items );
1818+
wp.a11y.speak( wp.i18n.sprintf( wp.i18n.__( '%d Search Results Found' ), $items.length ), 'assertive' );
18051819
$( '.spinner', panel ).removeClass( 'is-active' );
18061820
wrapper.removeClass( 'has-no-menu-item' );
18071821

src/wp-admin/css/forms.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,37 @@ fieldset label,
713713
display: inline-block;
714714
}
715715

716+
/* Caps lock warning */
717+
.wp-pwd .caps-warning {
718+
display: none;
719+
position: relative;
720+
background: #fcf9e8;
721+
border: 1px solid #f0c33c;
722+
color: #1d2327;
723+
padding: 6px 10px;
724+
top: -8px;
725+
}
726+
727+
.profile-php .wp-pwd .caps-warning {
728+
padding: 3px 5px;
729+
top: -4px;
730+
border-radius: 4px;
731+
}
732+
733+
.wp-pwd .caps-icon {
734+
display: inline-flex;
735+
justify-content: center;
736+
width: 20px;
737+
height: 20px;
738+
margin-right: 5px;
739+
vertical-align: middle;
740+
}
741+
742+
.wp-pwd .caps-warning-text {
743+
vertical-align: middle;
744+
}
745+
/* Caps lock warning */
746+
716747
p.search-box {
717748
display: flex;
718749
flex-wrap: wrap;
@@ -1640,6 +1671,10 @@ table.form-table td .updated p {
16401671
padding: 8px;
16411672
}
16421673

1674+
.profile-php .wp-pwd .caps-warning {
1675+
padding: 8px;
1676+
}
1677+
16431678
.password-input-wrapper {
16441679
display: block;
16451680
}

src/wp-admin/includes/admin-filters.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,6 @@
172172
// Font management.
173173
add_action( 'admin_print_styles', 'wp_print_font_faces', 50 );
174174
add_action( 'admin_print_styles', 'wp_print_font_faces_from_style_variations', 50 );
175+
176+
// Load Press This.
177+
add_action( 'press_this_init', 'wp_load_press_this' );

src/wp-admin/includes/class-wp-comments-list-table.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ public function prepare_items() {
151151
'order' => $order,
152152
'post_type' => $post_type,
153153
'update_comment_post_cache' => true,
154+
'type__not_in' => array( 'note' ),
154155
);
155156

156157
/**

src/wp-admin/includes/comment.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ function get_pending_comments_num( $post_id ) {
157157
$post_id_array = array_map( 'intval', $post_id_array );
158158
$post_id_in = "'" . implode( "', '", $post_id_array ) . "'";
159159

160-
$pending = $wpdb->get_results( "SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM $wpdb->comments WHERE comment_post_ID IN ( $post_id_in ) AND comment_approved = '0' GROUP BY comment_post_ID", ARRAY_A );
160+
$pending = $wpdb->get_results( "SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM $wpdb->comments WHERE comment_post_ID IN ( $post_id_in ) AND comment_approved = '0' AND comment_type != 'note' GROUP BY comment_post_ID", ARRAY_A );
161161

162162
if ( $single ) {
163163
if ( empty( $pending ) ) {

src/wp-admin/includes/nav-menu.php

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,34 @@ function _wp_ajax_menu_quick_search( $request = array() ) {
8383
} elseif ( preg_match( '/quick-search-(posttype|taxonomy)-([a-zA-Z0-9_-]*\b)/', $type, $matches ) ) {
8484
if ( 'posttype' === $matches[1] && get_post_type_object( $matches[2] ) ) {
8585
$post_type_obj = _wp_nav_menu_meta_box_object( get_post_type_object( $matches[2] ) );
86-
$args = array_merge(
87-
$args,
88-
array(
89-
'no_found_rows' => true,
90-
'update_post_meta_cache' => false,
91-
'update_post_term_cache' => false,
92-
'posts_per_page' => 10,
93-
'post_type' => $matches[2],
94-
's' => $query,
95-
)
86+
$query_args = array(
87+
'no_found_rows' => true,
88+
'update_post_meta_cache' => false,
89+
'update_post_term_cache' => false,
90+
'posts_per_page' => 10,
91+
'post_type' => $matches[2],
92+
's' => $query,
93+
'search_columns' => array( 'post_title' ),
9694
);
95+
/**
96+
* Filter the menu quick search arguments.
97+
*
98+
* @since 6.9.0
99+
*
100+
* @param array $args {
101+
* Menu quick search arguments.
102+
*
103+
* @type boolean $no_found_rows Whether to return found rows data. Default true.
104+
* @type boolean $update_post_meta_cache Whether to update post meta cache. Default false.
105+
* @type boolean $update_post_term_cache Whether to update post term cache. Default false.
106+
* @type int $posts_per_page Number of posts to return. Default 10.
107+
* @type string $post_type Type of post to return.
108+
* @type string $s Search query.
109+
* @type array $search_columns Which post table columns to query.
110+
* }
111+
*/
112+
$query_args = apply_filters( 'wp_ajax_menu_quick_search_args', $query_args );
113+
$args = array_merge( $args, $query_args );
97114

98115
if ( isset( $post_type_obj->_default_query ) ) {
99116
$args = array_merge( $args, (array) $post_type_obj->_default_query );

src/wp-admin/includes/template.php

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,30 +2246,43 @@ function iframe_footer() {
22462246
* @return string Post states string.
22472247
*/
22482248
function _post_states( $post, $display = true ) {
2249-
$post_states = get_post_states( $post );
2250-
$post_states_string = '';
2249+
$post_states = get_post_states( $post );
2250+
$post_states_html = '';
22512251

22522252
if ( ! empty( $post_states ) ) {
22532253
$state_count = count( $post_states );
22542254

22552255
$i = 0;
22562256

2257-
$post_states_string .= ' &mdash; ';
2257+
$post_states_html .= ' &mdash; ';
22582258

22592259
foreach ( $post_states as $state ) {
22602260
++$i;
22612261

22622262
$separator = ( $i < $state_count ) ? ', ' : '';
22632263

2264-
$post_states_string .= "<span class='post-state'>{$state}{$separator}</span>";
2264+
$post_states_html .= "<span class='post-state'>{$state}{$separator}</span>";
22652265
}
22662266
}
22672267

2268+
/**
2269+
* Filters the HTML string of post states.
2270+
*
2271+
* @since 6.9.0
2272+
*
2273+
* @param string $post_states_html All relevant post states combined into an HTML string for display.
2274+
* E.g. `&mdash; <span class='post-state'>Draft, </span><span class='post-state'>Sticky</span>`.
2275+
* @param string<string, string> $post_states A mapping of post state slugs to translated post state labels.
2276+
* E.g. `array( 'draft' => __( 'Draft' ), 'sticky' => __( 'Sticky' ), ... )`.
2277+
* @param WP_Post $post The current post object.
2278+
*/
2279+
$post_states_html = apply_filters( 'post_states_html', $post_states_html, $post_states, $post );
2280+
22682281
if ( $display ) {
2269-
echo $post_states_string;
2282+
echo $post_states_html;
22702283
}
22712284

2272-
return $post_states_string;
2285+
return $post_states_html;
22732286
}
22742287

22752288
/**
@@ -2342,8 +2355,9 @@ function get_post_states( $post ) {
23422355
* are used within the filter, their existence should be checked
23432356
* with `function_exists()` before being used.
23442357
*
2345-
* @param string[] $post_states An array of post display states.
2346-
* @param WP_Post $post The current post object.
2358+
* @param string<string, string> $post_states A mapping of post state slugs to translated post state labels.
2359+
* E.g. `array( 'draft' => __( 'Draft' ), 'sticky' => __( 'Sticky' ), ... )`.
2360+
* @param WP_Post $post The current post object.
23472361
*/
23482362
return apply_filters( 'display_post_states', $post_states, $post );
23492363
}

src/wp-admin/press-this.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,12 @@ function wp_load_press_this() {
8484
}
8585
}
8686

87-
wp_load_press_this();
87+
/**
88+
* Loads the Press This plugin.
89+
*
90+
* Via admin-filters.php, the wp_load_press_this() function is hooked into this action.
91+
* Plugins can remove_action and add their own function to load their own Press This functionality.
92+
*
93+
* @since 6.9.0
94+
*/
95+
do_action( 'press_this_init' );

0 commit comments

Comments
 (0)