Skip to content

Commit ab8cc9c

Browse files
Merge branch 'trunk' into feat/trac-64109-minify-classic-themes
2 parents 58c06a2 + 845f7ce commit ab8cc9c

28 files changed

Lines changed: 939 additions & 207 deletions
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
##
2+
# A reusable workflow that tests the Gutenberg plugin build process when run within a wordpress-develop checkout.
3+
##
4+
name: Test the Gutenberg plugin Build Process
5+
6+
on:
7+
workflow_call:
8+
inputs:
9+
os:
10+
description: 'Operating system to run tests on'
11+
required: false
12+
type: 'string'
13+
default: 'ubuntu-24.04'
14+
directory:
15+
description: 'Directory to run WordPress from. Valid values are `src` or `build`'
16+
required: false
17+
type: 'string'
18+
default: 'src'
19+
20+
env:
21+
GUTENBERG_DIRECTORY: ${{ inputs.directory == 'build' && 'build' || 'src' }}/wp-content/plugins/gutenberg
22+
PUPPETEER_SKIP_DOWNLOAD: ${{ true }}
23+
NODE_OPTIONS: '--max-old-space-size=8192'
24+
25+
# Disable permissions for all available scopes by default.
26+
# Any needed permissions should be configured at the job level.
27+
permissions: {}
28+
29+
jobs:
30+
# Verifies that installing npm dependencies and building the Gutenberg plugin works as expected.
31+
#
32+
# Performs the following steps:
33+
# - Checks out the repository.
34+
# - Checks out the Gutenberg plugin into the plugins directory.
35+
# - Sets up Node.js.
36+
# - Logs debug information about the GitHub Action runner.
37+
# - Installs Gutenberg npm dependencies.
38+
# - Runs the Gutenberg build process.
39+
# - Installs Core npm dependencies.
40+
# - Builds WordPress to run from the relevant location (src or build).
41+
# - Builds Gutenberg.
42+
# - Ensures version-controlled files are not modified or deleted.
43+
build-process-tests:
44+
name: ${{ contains( inputs.os, 'macos-' ) && 'MacOS' || contains( inputs.os, 'windows-' ) && 'Windows' || 'Linux' }}
45+
permissions:
46+
contents: read
47+
runs-on: ${{ inputs.os }}
48+
timeout-minutes: 30
49+
50+
steps:
51+
- name: Checkout repository
52+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
53+
with:
54+
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
55+
persist-credentials: false
56+
57+
- name: Checkout Gutenberg plugin
58+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
59+
with:
60+
repository: 'WordPress/gutenberg'
61+
path: ${{ env.GUTENBERG_DIRECTORY }}
62+
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
63+
persist-credentials: false
64+
65+
- name: Set up Node.js
66+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
67+
with:
68+
node-version-file: '.nvmrc'
69+
cache: npm
70+
cache-dependency-path: |
71+
package-lock.json
72+
${{ env.GUTENBERG_DIRECTORY }}/package-lock.json
73+
74+
- name: Log debug information
75+
run: |
76+
npm --version
77+
node --version
78+
curl --version
79+
git --version
80+
81+
- name: Install Gutenberg Dependencies
82+
run: npm ci
83+
working-directory: ${{ env.GUTENBERG_DIRECTORY }}
84+
85+
- name: Build Gutenberg
86+
run: npm run build
87+
working-directory: ${{ env.GUTENBERG_DIRECTORY }}
88+
89+
- name: Install Core Dependencies
90+
run: npm ci
91+
92+
- name: Build WordPress to run from ${{ inputs.directory }}
93+
run: npm run ${{ inputs.directory == 'src' && 'build:dev' || 'build' }}
94+
95+
- name: Run Gutenberg build script after building Core to run from ${{ inputs.directory }}
96+
run: npm run build
97+
working-directory: ${{ env.GUTENBERG_DIRECTORY }}
98+
99+
- name: Ensure version-controlled files are not modified or deleted during building
100+
run: git diff --exit-code

src/js/_enqueues/wp/code-editor.js

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* @output wp-admin/js/code-editor.js
33
*/
44

5+
/* eslint-env es2020 */
6+
57
if ( 'undefined' === typeof window.wp ) {
68
/**
79
* @namespace wp
@@ -44,7 +46,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
4446
* @param {Function} settings.onChangeLintingErrors - Callback for when there are changes to linting errors.
4547
* @param {Function} settings.onUpdateErrorNotice - Callback to update error notice.
4648
*
47-
* @return {void}
49+
* @return {Function} Update error notice function.
4850
*/
4951
function configureLinting( editor, settings ) { // eslint-disable-line complexity
5052
var currentErrorAnnotations = [], previouslyShownErrorAnnotations = [];
@@ -80,7 +82,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
8082
}
8183

8284
/*
83-
* Note that rules must be sent in the "deprecated" lint.options property
85+
* Note that rules must be sent in the "deprecated" lint.options property
8486
* to prevent linter from complaining about unrecognized options.
8587
* See <https://github.com/codemirror/CodeMirror/pull/4944>.
8688
*/
@@ -207,6 +209,8 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
207209
updateErrorNotice();
208210
}
209211
});
212+
213+
return updateErrorNotice;
210214
}
211215

212216
/**
@@ -259,6 +263,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
259263
* @typedef {object} wp.codeEditor~CodeEditorInstance
260264
* @property {object} settings - The code editor settings.
261265
* @property {CodeMirror} codemirror - The CodeMirror instance.
266+
* @property {Function} updateErrorNotice - Force update the error notice.
262267
*/
263268

264269
/**
@@ -280,7 +285,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
280285
* @return {CodeEditorInstance} Instance.
281286
*/
282287
wp.codeEditor.initialize = function initialize( textarea, settings ) {
283-
var $textarea, codemirror, instanceSettings, instance;
288+
var $textarea, codemirror, instanceSettings, instance, updateErrorNotice;
284289
if ( 'string' === typeof textarea ) {
285290
$textarea = $( '#' + textarea );
286291
} else {
@@ -292,16 +297,33 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
292297

293298
codemirror = wp.CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror );
294299

295-
configureLinting( codemirror, instanceSettings );
300+
updateErrorNotice = configureLinting( codemirror, instanceSettings );
296301

297302
instance = {
298303
settings: instanceSettings,
299-
codemirror: codemirror
304+
codemirror,
305+
updateErrorNotice,
300306
};
301307

302308
if ( codemirror.showHint ) {
303-
codemirror.on( 'keyup', function( editor, event ) { // eslint-disable-line complexity
304-
var shouldAutocomplete, isAlphaKey = /^[a-zA-Z]$/.test( event.key ), lineBeforeCursor, innerMode, token;
309+
codemirror.on( 'inputRead', function( editor, change ) {
310+
var shouldAutocomplete, isAlphaKey, lineBeforeCursor, innerMode, token, char;
311+
312+
// Only trigger autocompletion for typed input or IME composition.
313+
if ( '+input' !== change.origin && ! change.origin.startsWith( '*compose' ) ) {
314+
return;
315+
}
316+
317+
// Only trigger autocompletion for single-character inputs.
318+
// The text property is an array of strings, one for each line.
319+
// We check that there is only one line and that line has only one character.
320+
if ( 1 !== change.text.length || 1 !== change.text[0].length ) {
321+
return;
322+
}
323+
324+
char = change.text[0];
325+
isAlphaKey = /^[a-zA-Z]$/.test( char );
326+
305327
if ( codemirror.state.completionActive && isAlphaKey ) {
306328
return;
307329
}
@@ -315,26 +337,30 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
315337
innerMode = wp.CodeMirror.innerMode( codemirror.getMode(), token.state ).mode.name;
316338
lineBeforeCursor = codemirror.doc.getLine( codemirror.doc.getCursor().line ).substr( 0, codemirror.doc.getCursor().ch );
317339
if ( 'html' === innerMode || 'xml' === innerMode ) {
318-
shouldAutocomplete =
319-
'<' === event.key ||
320-
'/' === event.key && 'tag' === token.type ||
321-
isAlphaKey && 'tag' === token.type ||
322-
isAlphaKey && 'attribute' === token.type ||
323-
'=' === token.string && token.state.htmlState && token.state.htmlState.tagName;
340+
shouldAutocomplete = (
341+
'<' === char ||
342+
( '/' === char && 'tag' === token.type ) ||
343+
( isAlphaKey && 'tag' === token.type ) ||
344+
( isAlphaKey && 'attribute' === token.type ) ||
345+
( '=' === char && (
346+
token.state.htmlState?.tagName ||
347+
token.state.curState?.htmlState?.tagName
348+
) )
349+
);
324350
} else if ( 'css' === innerMode ) {
325351
shouldAutocomplete =
326352
isAlphaKey ||
327-
':' === event.key ||
328-
' ' === event.key && /:\s+$/.test( lineBeforeCursor );
353+
':' === char ||
354+
( ' ' === char && /:\s+$/.test( lineBeforeCursor ) );
329355
} else if ( 'javascript' === innerMode ) {
330-
shouldAutocomplete = isAlphaKey || '.' === event.key;
356+
shouldAutocomplete = isAlphaKey || '.' === char;
331357
} else if ( 'clike' === innerMode && 'php' === codemirror.options.mode ) {
332-
shouldAutocomplete = 'keyword' === token.type || 'variable' === token.type;
358+
shouldAutocomplete = isAlphaKey && ( 'keyword' === token.type || 'variable' === token.type );
333359
}
334360
if ( shouldAutocomplete ) {
335361
codemirror.showHint( { completeSingle: false } );
336362
}
337-
});
363+
} );
338364
}
339365

340366
// Facilitate tabbing out of the editor.

src/js/_enqueues/wp/sanitize.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
* @return {string} Stripped text.
2424
*/
2525
stripTags: function( text ) {
26+
if ( ! text ) {
27+
return '';
28+
}
29+
2630
const domParser = new DOMParser();
2731
const htmlDocument = domParser.parseFromString(
2832
text,

src/js/_enqueues/wp/theme-plugin-editor.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
* @output wp-admin/js/theme-plugin-editor.js
33
*/
44

5-
/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1] }] */
5+
/* eslint-env es2020 */
6+
7+
/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1, 9, 1000] }] */
68

79
if ( ! window.wp ) {
810
window.wp = {};
@@ -81,6 +83,18 @@ wp.themePluginEditor = (function( $ ) {
8183
component.docsLookUpButton.prop( 'disabled', false );
8284
}
8385
} );
86+
87+
// Initiate saving the file when not focused in CodeMirror or when the user has syntax highlighting turned off.
88+
$( window ).on( 'keydown', function( event ) {
89+
if (
90+
( event.ctrlKey || event.metaKey ) &&
91+
( 's' === event.key.toLowerCase() ) &&
92+
( ! component.instance || ! component.instance.codemirror.hasFocus() )
93+
) {
94+
event.preventDefault();
95+
component.form.trigger( 'submit' );
96+
}
97+
} );
8498
};
8599

86100
/**
@@ -191,6 +205,10 @@ wp.themePluginEditor = (function( $ ) {
191205
return;
192206
}
193207

208+
if ( component.instance && component.instance.updateErrorNotice ) {
209+
component.instance.updateErrorNotice();
210+
}
211+
194212
// Scroll to the line that has the error.
195213
if ( component.lintErrors.length ) {
196214
component.instance.codemirror.setCursor( component.lintErrors[0].from.line );
@@ -399,6 +417,16 @@ wp.themePluginEditor = (function( $ ) {
399417
editor = wp.codeEditor.initialize( $( '#newcontent' ), codeEditorSettings );
400418
editor.codemirror.on( 'change', component.onChange );
401419

420+
function onSaveShortcut() {
421+
component.form.trigger( 'submit' );
422+
}
423+
424+
editor.codemirror.setOption( 'extraKeys', {
425+
...( editor.codemirror.getOption( 'extraKeys' ) || {} ),
426+
'Ctrl-S': onSaveShortcut,
427+
'Cmd-S': onSaveShortcut,
428+
} );
429+
402430
// Improve the editor accessibility.
403431
$( editor.codemirror.display.lineDiv )
404432
.attr({

src/wp-admin/edit-form-blocks.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static function ( $classes ) {
105105
),
106106
$paths[] = add_query_arg(
107107
'slug',
108-
// @see https://github.com/WordPress/gutenberg/blob/e093fefd041eb6cc4a4e7f67b92ab54fd75c8858/packages/core-data/src/private-selectors.ts#L244-L254
108+
// @link https://github.com/WordPress/gutenberg/blob/e093fefd041eb6cc4a4e7f67b92ab54fd75c8858/packages/core-data/src/private-selectors.ts#L244-L254
109109
$template_lookup_slug,
110110
'/wp/v2/templates/lookup'
111111
),

src/wp-admin/includes/class-wp-debug-data.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,12 @@ private static function get_wp_server(): array {
505505
}
506506

507507
// Check if a robots.txt file exists.
508-
if ( is_file( ABSPATH . 'robots.txt' ) ) {
508+
if ( is_file( get_home_path() . 'robots.txt' ) ) {
509509
// If the file exists, turn debug info to true.
510510
$robotstxt_debug = true;
511511

512512
/* translators: %s: robots.txt */
513-
$robotstxt_string = sprintf( __( 'There is a static %s file in your installation folder. WordPress cannot dynamically serve one.' ), 'robots.txt' );
513+
$robotstxt_string = sprintf( __( 'Your site is using a static %s file. WordPress cannot dynamically serve one.' ), 'robots.txt' );
514514
} elseif ( got_url_rewrite() ) {
515515
// No robots.txt file available and rewrite rules in place, turn debug info to false.
516516
$robotstxt_debug = false;
@@ -522,7 +522,7 @@ private static function get_wp_server(): array {
522522
$robotstxt_debug = true;
523523

524524
/* translators: %s: robots.txt */
525-
$robotstxt_string = sprintf( __( 'WordPress cannot dynamically serve a %s file due to a lack of rewrite rule support' ), 'robots.txt' );
525+
$robotstxt_string = sprintf( __( 'WordPress cannot dynamically serve a %s file due to a lack of rewrite rule support.' ), 'robots.txt' );
526526

527527
}
528528

src/wp-admin/media-new.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
}
4141

4242
// Used in the HTML title tag.
43-
$title = __( 'Upload New Media' );
43+
$title = __( 'Upload Media' );
4444
$parent_file = 'upload.php';
4545

4646
get_current_screen()->add_help_tab(

src/wp-admin/site-editor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ static function ( $classes ) {
238238
if ( 'page' === $block_editor_context->post->post_type ) {
239239
$preload_paths[] = add_query_arg(
240240
'slug',
241-
// @see https://github.com/WordPress/gutenberg/blob/e093fefd041eb6cc4a4e7f67b92ab54fd75c8858/packages/core-data/src/private-selectors.ts#L244-L254
241+
// @link https://github.com/WordPress/gutenberg/blob/e093fefd041eb6cc4a4e7f67b92ab54fd75c8858/packages/core-data/src/private-selectors.ts#L244-L254
242242
empty( $block_editor_context->post->post_name ) ? 'page' : 'page-' . $block_editor_context->post->post_name,
243243
'/wp/v2/templates/lookup'
244244
);

src/wp-includes/class-wp-http-requests-response.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public function set_data( $data ) {
155155
*
156156
* @since 4.6.0
157157
*
158-
* @return WP_HTTP_Cookie[] List of cookie objects.
158+
* @return WP_Http_Cookie[] List of cookie objects.
159159
*/
160160
public function get_cookies() {
161161
$cookies = array();

src/wp-includes/class-wp-http.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class WP_Http {
161161
* @type int|false $code HTTP response status code.
162162
* @type string|false $message HTTP response message.
163163
* }
164-
* @type WP_HTTP_Cookie[] $cookies Array of cookies set by the server.
164+
* @type WP_Http_Cookie[] $cookies Array of cookies set by the server.
165165
* @type string|null $filename Optional. Filename of the response.
166166
* @type WP_HTTP_Requests_Response|null $http_response Response object.
167167
* }
@@ -804,7 +804,7 @@ public static function processHeaders( $headers, $url = '' ) { // phpcs:ignore W
804804
*/
805805
public static function buildCookieHeader( &$r ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
806806
if ( ! empty( $r['cookies'] ) ) {
807-
// Upgrade any name => value cookie pairs to WP_HTTP_Cookie instances.
807+
// Upgrade any name => value cookie pairs to WP_Http_Cookie instances.
808808
foreach ( $r['cookies'] as $name => $value ) {
809809
if ( ! is_object( $value ) ) {
810810
$r['cookies'][ $name ] = new WP_Http_Cookie(

0 commit comments

Comments
 (0)