Commit 5db53df0a8 for wordpress.org
commit 5db53df0a8af6a06b594d4e83dff51bda93ce48d
Author: Weston Ruter <weston@xwp.co>
Date: Wed Feb 4 07:03:44 2026 +0000
Code Editor: Allow saving with Ctrl/Cmd+S in Theme/Plugin Editors.
* Keyboard shortcuts work when CodeMirror is not enabled (due to syntax highlighting not being enabled), and when the user is not focused inside the CodeMirror editor.
* The autocomplete trigger is switched from `keyup` to `inputRead` to improve reliability, support IME composition, and prevent conflicts with modifier keys (e.g., releasing `Ctrl`/`Cmd` before `s` after a save).
* A `updateErrorNotice` method is exposed on the code editor instance to ensure validation errors are displayed when a save via shortcut is attempted, preventing "silent" failures. Otherwise, the linting error notice is only shown when focus leaves the editor.
* The form submission is modernized by replacing the deprecated jQuery `.submit()` shorthand with `.trigger( 'submit' )`.
Developed in https://github.com/WordPress/wordpress-develop/pull/10851
Props westonruter, Junaidkbr, evansolomon, desrosj, mukesh27, jonsurrell, spiraltee, chexee, andrewryno, tusharaddweb, gauri87, huzaifaalmesbah, ocean90, karmatosed, johnbillion, scribu, jcnetsys.
Fixes #17133.
Built from https://develop.svn.wordpress.org/trunk@61588
git-svn-id: http://core.svn.wordpress.org/trunk@60899 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-admin/js/code-editor.js b/wp-admin/js/code-editor.js
index 4266f39292..bc57026385 100644
--- a/wp-admin/js/code-editor.js
+++ b/wp-admin/js/code-editor.js
@@ -46,7 +46,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
* @param {Function} settings.onChangeLintingErrors - Callback for when there are changes to linting errors.
* @param {Function} settings.onUpdateErrorNotice - Callback to update error notice.
*
- * @return {void}
+ * @return {Function} Update error notice function.
*/
function configureLinting( editor, settings ) { // eslint-disable-line complexity
var currentErrorAnnotations = [], previouslyShownErrorAnnotations = [];
@@ -82,7 +82,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
}
/*
- * Note that rules must be sent in the "deprecated" lint.options property
+ * Note that rules must be sent in the "deprecated" lint.options property
* to prevent linter from complaining about unrecognized options.
* See <https://github.com/codemirror/CodeMirror/pull/4944>.
*/
@@ -209,6 +209,8 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
updateErrorNotice();
}
});
+
+ return updateErrorNotice;
}
/**
@@ -261,6 +263,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
* @typedef {object} wp.codeEditor~CodeEditorInstance
* @property {object} settings - The code editor settings.
* @property {CodeMirror} codemirror - The CodeMirror instance.
+ * @property {Function} updateErrorNotice - Force update the error notice.
*/
/**
@@ -282,7 +285,7 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
* @return {CodeEditorInstance} Instance.
*/
wp.codeEditor.initialize = function initialize( textarea, settings ) {
- var $textarea, codemirror, instanceSettings, instance;
+ var $textarea, codemirror, instanceSettings, instance, updateErrorNotice;
if ( 'string' === typeof textarea ) {
$textarea = $( '#' + textarea );
} else {
@@ -294,16 +297,33 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
codemirror = wp.CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror );
- configureLinting( codemirror, instanceSettings );
+ updateErrorNotice = configureLinting( codemirror, instanceSettings );
instance = {
settings: instanceSettings,
- codemirror: codemirror
+ codemirror,
+ updateErrorNotice,
};
if ( codemirror.showHint ) {
- codemirror.on( 'keyup', function( editor, event ) { // eslint-disable-line complexity
- var shouldAutocomplete, isAlphaKey = /^[a-zA-Z]$/.test( event.key ), lineBeforeCursor, innerMode, token;
+ codemirror.on( 'inputRead', function( editor, change ) {
+ var shouldAutocomplete, isAlphaKey, lineBeforeCursor, innerMode, token, char;
+
+ // Only trigger autocompletion for typed input or IME composition.
+ if ( '+input' !== change.origin && ! change.origin.startsWith( '*compose' ) ) {
+ return;
+ }
+
+ // Only trigger autocompletion for single-character inputs.
+ // The text property is an array of strings, one for each line.
+ // We check that there is only one line and that line has only one character.
+ if ( 1 !== change.text.length || 1 !== change.text[0].length ) {
+ return;
+ }
+
+ char = change.text[0];
+ isAlphaKey = /^[a-zA-Z]$/.test( char );
+
if ( codemirror.state.completionActive && isAlphaKey ) {
return;
}
@@ -318,11 +338,11 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
lineBeforeCursor = codemirror.doc.getLine( codemirror.doc.getCursor().line ).substr( 0, codemirror.doc.getCursor().ch );
if ( 'html' === innerMode || 'xml' === innerMode ) {
shouldAutocomplete = (
- '<' === event.key ||
- ( '/' === event.key && 'tag' === token.type ) ||
+ '<' === char ||
+ ( '/' === char && 'tag' === token.type ) ||
( isAlphaKey && 'tag' === token.type ) ||
( isAlphaKey && 'attribute' === token.type ) ||
- ( '=' === event.key && (
+ ( '=' === char && (
token.state.htmlState?.tagName ||
token.state.curState?.htmlState?.tagName
) )
@@ -330,17 +350,17 @@ if ( 'undefined' === typeof window.wp.codeEditor ) {
} else if ( 'css' === innerMode ) {
shouldAutocomplete =
isAlphaKey ||
- ':' === event.key ||
- ( ' ' === event.key && /:\s+$/.test( lineBeforeCursor ) );
+ ':' === char ||
+ ( ' ' === char && /:\s+$/.test( lineBeforeCursor ) );
} else if ( 'javascript' === innerMode ) {
- shouldAutocomplete = isAlphaKey || '.' === event.key;
+ shouldAutocomplete = isAlphaKey || '.' === char;
} else if ( 'clike' === innerMode && 'php' === codemirror.options.mode ) {
shouldAutocomplete = isAlphaKey && ( 'keyword' === token.type || 'variable' === token.type );
}
if ( shouldAutocomplete ) {
codemirror.showHint( { completeSingle: false } );
}
- });
+ } );
}
// Facilitate tabbing out of the editor.
diff --git a/wp-admin/js/code-editor.min.js b/wp-admin/js/code-editor.min.js
index e16666ef3a..e89d6f9d3a 100644
--- a/wp-admin/js/code-editor.min.js
+++ b/wp-admin/js/code-editor.min.js
@@ -1,2 +1,2 @@
/*! This file is auto-generated */
-void 0===window.wp&&(window.wp={}),void 0===window.wp.codeEditor&&(window.wp.codeEditor={}),function(u,d){"use strict";function s(r,s){var a=[],d=[];function c(){s.onUpdateErrorNotice&&!_.isEqual(a,d)&&(s.onUpdateErrorNotice(a,r),d=a)}function i(){var i,t=r.getOption("lint");return!!t&&(!0===t?t={}:_.isObject(t)&&(t=u.extend({},t)),t.options||(t.options={}),"javascript"===s.codemirror.mode&&s.jshint&&u.extend(t.options,s.jshint),"css"===s.codemirror.mode&&s.csslint&&u.extend(t.options,s.csslint),"htmlmixed"===s.codemirror.mode&&s.htmlhint&&(t.options.rules=u.extend({},s.htmlhint),s.jshint&&(t.options.rules.jshint=s.jshint),s.csslint)&&(t.options.rules.csslint=s.csslint),t.onUpdateLinting=(i=t.onUpdateLinting,function(t,e,n){var o=_.filter(t,function(t){return"error"===t.severity});i&&i.apply(t,e,n),!_.isEqual(o,a)&&(a=o,s.onChangeLintingErrors&&s.onChangeLintingErrors(o,t,e,n),!r.state.focused||0===a.length||0<d.length)&&c()}),t)}r.setOption("lint",i()),r.on("optionChange",function(t,e){var n,o="CodeMirror-lint-markers";"lint"===e&&(e=r.getOption("gutters")||[],!0===(n=r.getOption("lint"))?(_.contains(e,o)||r.setOption("gutters",[o].concat(e)),r.setOption("lint",i())):n||r.setOption("gutters",_.without(e,o)),r.getOption("lint")?r.performLint():(a=[],c()))}),r.on("blur",c),r.on("startCompletion",function(){r.off("blur",c)}),r.on("endCompletion",function(){r.on("blur",c),_.delay(function(){r.state.focused||c()},500)}),u(document.body).on("mousedown",function(t){!r.state.focused||u.contains(r.display.wrapper,t.target)||u(t.target).hasClass("CodeMirror-hint")||c()})}d.codeEditor.defaultSettings={codemirror:{},csslint:{},htmlhint:{},jshint:{},onTabNext:function(){},onTabPrevious:function(){},onChangeLintingErrors:function(){},onUpdateErrorNotice:function(){}},d.codeEditor.initialize=function(t,e){var a,n,o,i,t=u("string"==typeof t?"#"+t:t),r=u.extend({},d.codeEditor.defaultSettings,e);return r.codemirror=u.extend({},r.codemirror),s(a=d.CodeMirror.fromTextArea(t[0],r.codemirror),r),t={settings:r,codemirror:a},a.showHint&&a.on("keyup",function(t,e){var n,o,i,r,s=/^[a-zA-Z]$/.test(e.key);a.state.completionActive&&s||"string"!==(r=a.getTokenAt(a.getCursor())).type&&"comment"!==r.type&&(i=d.CodeMirror.innerMode(a.getMode(),r.state).mode.name,o=a.doc.getLine(a.doc.getCursor().line).substr(0,a.doc.getCursor().ch),"html"===i||"xml"===i?n="<"===e.key||"/"===e.key&&"tag"===r.type||s&&"tag"===r.type||s&&"attribute"===r.type||"="===e.key&&(r.state.htmlState?.tagName||r.state.curState?.htmlState?.tagName):"css"===i?n=s||":"===e.key||" "===e.key&&/:\s+$/.test(o):"javascript"===i?n=s||"."===e.key:"clike"===i&&"php"===a.options.mode&&(n=s&&("keyword"===r.type||"variable"===r.type)),n)&&a.showHint({completeSingle:!1})}),o=e,i=u((n=a).getTextArea()),n.on("blur",function(){i.data("next-tab-blurs",!1)}),n.on("keydown",function(t,e){27===e.keyCode?i.data("next-tab-blurs",!0):9===e.keyCode&&i.data("next-tab-blurs")&&(e.shiftKey?o.onTabPrevious(n,e):o.onTabNext(n,e),i.data("next-tab-blurs",!1),e.preventDefault())}),t}}(window.jQuery,window.wp);
\ No newline at end of file
+void 0===window.wp&&(window.wp={}),void 0===window.wp.codeEditor&&(window.wp.codeEditor={}),function(u,d){"use strict";function s(r,s){var a=[],d=[];function c(){s.onUpdateErrorNotice&&!_.isEqual(a,d)&&(s.onUpdateErrorNotice(a,r),d=a)}function i(){var i,t=r.getOption("lint");return!!t&&(!0===t?t={}:_.isObject(t)&&(t=u.extend({},t)),t.options||(t.options={}),"javascript"===s.codemirror.mode&&s.jshint&&u.extend(t.options,s.jshint),"css"===s.codemirror.mode&&s.csslint&&u.extend(t.options,s.csslint),"htmlmixed"===s.codemirror.mode&&s.htmlhint&&(t.options.rules=u.extend({},s.htmlhint),s.jshint&&(t.options.rules.jshint=s.jshint),s.csslint)&&(t.options.rules.csslint=s.csslint),t.onUpdateLinting=(i=t.onUpdateLinting,function(t,n,e){var o=_.filter(t,function(t){return"error"===t.severity});i&&i.apply(t,n,e),!_.isEqual(o,a)&&(a=o,s.onChangeLintingErrors&&s.onChangeLintingErrors(o,t,n,e),!r.state.focused||0===a.length||0<d.length)&&c()}),t)}return r.setOption("lint",i()),r.on("optionChange",function(t,n){var e,o="CodeMirror-lint-markers";"lint"===n&&(n=r.getOption("gutters")||[],!0===(e=r.getOption("lint"))?(_.contains(n,o)||r.setOption("gutters",[o].concat(n)),r.setOption("lint",i())):e||r.setOption("gutters",_.without(n,o)),r.getOption("lint")?r.performLint():(a=[],c()))}),r.on("blur",c),r.on("startCompletion",function(){r.off("blur",c)}),r.on("endCompletion",function(){r.on("blur",c),_.delay(function(){r.state.focused||c()},500)}),u(document.body).on("mousedown",function(t){!r.state.focused||u.contains(r.display.wrapper,t.target)||u(t.target).hasClass("CodeMirror-hint")||c()}),c}d.codeEditor.defaultSettings={codemirror:{},csslint:{},htmlhint:{},jshint:{},onTabNext:function(){},onTabPrevious:function(){},onChangeLintingErrors:function(){},onUpdateErrorNotice:function(){}},d.codeEditor.initialize=function(t,n){var a,e,o,i,t=u("string"==typeof t?"#"+t:t),r=u.extend({},d.codeEditor.defaultSettings,n);return r.codemirror=u.extend({},r.codemirror),t=s(a=d.CodeMirror.fromTextArea(t[0],r.codemirror),r),r={settings:r,codemirror:a,updateErrorNotice:t},a.showHint&&a.on("inputRead",function(t,n){var e,o,i,r,s;"+input"!==n.origin&&!n.origin.startsWith("*compose")||1!==n.text.length||1!==n.text[0].length||(n=n.text[0],o=/^[a-zA-Z]$/.test(n),a.state.completionActive&&o)||"string"!==(s=a.getTokenAt(a.getCursor())).type&&"comment"!==s.type&&(r=d.CodeMirror.innerMode(a.getMode(),s.state).mode.name,i=a.doc.getLine(a.doc.getCursor().line).substr(0,a.doc.getCursor().ch),"html"===r||"xml"===r?e="<"===n||"/"===n&&"tag"===s.type||o&&"tag"===s.type||o&&"attribute"===s.type||"="===n&&(s.state.htmlState?.tagName||s.state.curState?.htmlState?.tagName):"css"===r?e=o||":"===n||" "===n&&/:\s+$/.test(i):"javascript"===r?e=o||"."===n:"clike"===r&&"php"===a.options.mode&&(e=o&&("keyword"===s.type||"variable"===s.type)),e)&&a.showHint({completeSingle:!1})}),o=n,i=u((e=a).getTextArea()),e.on("blur",function(){i.data("next-tab-blurs",!1)}),e.on("keydown",function(t,n){27===n.keyCode?i.data("next-tab-blurs",!0):9===n.keyCode&&i.data("next-tab-blurs")&&(n.shiftKey?o.onTabPrevious(e,n):o.onTabNext(e,n),i.data("next-tab-blurs",!1),n.preventDefault())}),r}}(window.jQuery,window.wp);
\ No newline at end of file
diff --git a/wp-admin/js/theme-plugin-editor.js b/wp-admin/js/theme-plugin-editor.js
index 1e3ac0d904..7bcff376e9 100644
--- a/wp-admin/js/theme-plugin-editor.js
+++ b/wp-admin/js/theme-plugin-editor.js
@@ -2,7 +2,9 @@
* @output wp-admin/js/theme-plugin-editor.js
*/
-/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1] }] */
+/* eslint-env es2020 */
+
+/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1, 9, 1000] }] */
if ( ! window.wp ) {
window.wp = {};
@@ -81,6 +83,18 @@ wp.themePluginEditor = (function( $ ) {
component.docsLookUpButton.prop( 'disabled', false );
}
} );
+
+ // Initiate saving the file when not focused in CodeMirror or when the user has syntax highlighting turned off.
+ $( window ).on( 'keydown', function( event ) {
+ if (
+ ( event.ctrlKey || event.metaKey ) &&
+ ( 's' === event.key.toLowerCase() ) &&
+ ( ! component.instance || ! component.instance.codemirror.hasFocus() )
+ ) {
+ event.preventDefault();
+ component.form.trigger( 'submit' );
+ }
+ } );
};
/**
@@ -191,6 +205,10 @@ wp.themePluginEditor = (function( $ ) {
return;
}
+ if ( component.instance && component.instance.updateErrorNotice ) {
+ component.instance.updateErrorNotice();
+ }
+
// Scroll to the line that has the error.
if ( component.lintErrors.length ) {
component.instance.codemirror.setCursor( component.lintErrors[0].from.line );
@@ -399,6 +417,16 @@ wp.themePluginEditor = (function( $ ) {
editor = wp.codeEditor.initialize( $( '#newcontent' ), codeEditorSettings );
editor.codemirror.on( 'change', component.onChange );
+ function onSaveShortcut() {
+ component.form.trigger( 'submit' );
+ }
+
+ editor.codemirror.setOption( 'extraKeys', {
+ ...( editor.codemirror.getOption( 'extraKeys' ) || {} ),
+ 'Ctrl-S': onSaveShortcut,
+ 'Cmd-S': onSaveShortcut,
+ } );
+
// Improve the editor accessibility.
$( editor.codemirror.display.lineDiv )
.attr({
diff --git a/wp-admin/js/theme-plugin-editor.min.js b/wp-admin/js/theme-plugin-editor.min.js
index 5d93871f2f..50c5693be8 100644
--- a/wp-admin/js/theme-plugin-editor.min.js
+++ b/wp-admin/js/theme-plugin-editor.min.js
@@ -1,2 +1,2 @@
/*! This file is auto-generated */
-window.wp||(window.wp={}),wp.themePluginEditor=function(i){"use strict";var t,o=wp.i18n.__,s=wp.i18n._n,r=wp.i18n.sprintf,n={codeEditor:{},instance:null,noticeElements:{},dirty:!1,lintErrors:[],init:function(e,t){n.form=e,t&&i.extend(n,t),n.noticeTemplate=wp.template("wp-file-editor-notice"),n.noticesContainer=n.form.find(".editor-notices"),n.submitButton=n.form.find(":input[name=submit]"),n.spinner=n.form.find(".submit .spinner"),n.form.on("submit",n.submit),n.textarea=n.form.find("#newcontent"),n.textarea.on("change",n.onChange),n.warning=i(".file-editor-warning"),n.docsLookUpButton=n.form.find("#docs-lookup"),n.docsLookUpList=n.form.find("#docs-list"),0<n.warning.length&&n.showWarning(),!1!==n.codeEditor&&_.defer(function(){n.initCodeEditor()}),i(n.initFileBrowser),i(window).on("beforeunload",function(){if(n.dirty)return o("The changes you made will be lost if you navigate away from this page.")}),n.docsLookUpList.on("change",function(){""===i(this).val()?n.docsLookUpButton.prop("disabled",!0):n.docsLookUpButton.prop("disabled",!1)})},showWarning:function(){var e=n.warning.find(".file-editor-warning-message").text();i("#wpwrap").attr("aria-hidden","true"),i(document.body).addClass("modal-open").append(n.warning.detach()),n.warning.removeClass("hidden").find(".file-editor-warning-go-back").trigger("focus"),n.warningTabbables=n.warning.find("a, button"),n.warningTabbables.on("keydown",n.constrainTabbing),n.warning.on("click",".file-editor-warning-dismiss",n.dismissWarning),setTimeout(function(){wp.a11y.speak(wp.sanitize.stripTags(e.replace(/\s+/g," ")),"assertive")},1e3)},constrainTabbing:function(e){var t,i;9===e.which&&(t=n.warningTabbables.first()[0],(i=n.warningTabbables.last()[0])!==e.target||e.shiftKey?t===e.target&&e.shiftKey&&(i.focus(),e.preventDefault()):(t.focus(),e.preventDefault()))},dismissWarning:function(){wp.ajax.post("dismiss-wp-pointer",{pointer:n.themeOrPlugin+"_editor_notice"}),n.warning.remove(),i("#wpwrap").removeAttr("aria-hidden"),i("body").removeClass("modal-open")},onChange:function(){n.dirty=!0,n.removeNotice("file_saved")},submit:function(e){var t={};e.preventDefault(),i.each(n.form.serializeArray(),function(){t[this.name]=this.value}),n.instance&&(t.newcontent=n.instance.codemirror.getValue()),n.isSaving||(n.lintErrors.length?n.instance.codemirror.setCursor(n.lintErrors[0].from.line):(n.isSaving=!0,n.textarea.prop("readonly",!0),n.instance&&n.instance.codemirror.setOption("readOnly",!0),n.spinner.addClass("is-active"),e=wp.ajax.post("edit-theme-plugin-file",t),n.lastSaveNoticeCode&&n.removeNotice(n.lastSaveNoticeCode),e.done(function(e){n.lastSaveNoticeCode="file_saved",n.addNotice({code:n.lastSaveNoticeCode,type:"success",message:e.message,dismissible:!0}),n.dirty=!1}),e.fail(function(e){e=i.extend({code:"save_error",message:o("An error occurred while saving your changes. Please try again. If the problem persists, you may need to manually update the file via FTP.")},e,{type:"error",dismissible:!0});n.lastSaveNoticeCode=e.code,n.addNotice(e)}),e.always(function(){n.spinner.removeClass("is-active"),n.isSaving=!1,n.textarea.prop("readonly",!1),n.instance&&n.instance.codemirror.setOption("readOnly",!1)})))},addNotice:function(e){var t;if(e.code)return n.removeNotice(e.code),(t=i(n.noticeTemplate(e))).hide(),t.find(".notice-dismiss").on("click",function(){n.removeNotice(e.code),e.onDismiss&&e.onDismiss(e)}),wp.a11y.speak(e.message),n.noticesContainer.append(t),t.slideDown("fast"),n.noticeElements[e.code]=t;throw new Error("Missing code.")},removeNotice:function(e){return!!n.noticeElements[e]&&(n.noticeElements[e].slideUp("fast",function(){i(this).remove()}),delete n.noticeElements[e],!0)},initCodeEditor:function(){var e,t=i.extend({},n.codeEditor);t.onTabPrevious=function(){i("#templateside").find(":tabbable").last().trigger("focus")},t.onTabNext=function(){i("#template").find(":tabbable:not(.CodeMirror-code)").first().trigger("focus")},t.onChangeLintingErrors=function(e){0===(n.lintErrors=e).length&&n.submitButton.toggleClass("disabled",!1)},t.onUpdateErrorNotice=function(e){n.submitButton.toggleClass("disabled",0<e.length),0!==e.length?n.addNotice({code:"lint_errors",type:"error",message:r(s("There is %s error which must be fixed before you can update this file.","There are %s errors which must be fixed before you can update this file.",e.length),String(e.length)),dismissible:!1}).find("input[type=checkbox]").on("click",function(){t.onChangeLintingErrors([]),n.removeNotice("lint_errors")}):n.removeNotice("lint_errors")},(e=wp.codeEditor.initialize(i("#newcontent"),t)).codemirror.on("change",n.onChange),i(e.codemirror.display.lineDiv).attr({role:"textbox","aria-multiline":"true","aria-labelledby":"theme-plugin-editor-label","aria-describedby":"editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"}),i("#theme-plugin-editor-label").on("click",function(){e.codemirror.focus()}),n.instance=e},initFileBrowser:function(){var e=i("#templateside");e.find('[role="group"]').parent().attr("aria-expanded",!1),e.find(".notice").parents("[aria-expanded]").attr("aria-expanded",!0),e.find('[role="tree"]').each(function(){new t(this).init()}),e.find(".current-file:first").each(function(){this.scrollIntoViewIfNeeded?this.scrollIntoViewIfNeeded():this.scrollIntoView(!1)})}},a=(e.prototype.init=function(){this.domNode.tabIndex=-1,this.domNode.getAttribute("role")||this.domNode.setAttribute("role","treeitem"),this.domNode.addEventListener("keydown",this.handleKeydown.bind(this)),this.domNode.addEventListener("click",this.handleClick.bind(this)),this.domNode.addEventListener("focus",this.handleFocus.bind(this)),this.domNode.addEventListener("blur",this.handleBlur.bind(this)),(this.isExpandable?(this.domNode.firstElementChild.addEventListener("mouseover",this.handleMouseOver.bind(this)),this.domNode.firstElementChild):(this.domNode.addEventListener("mouseover",this.handleMouseOver.bind(this)),this.domNode)).addEventListener("mouseout",this.handleMouseOut.bind(this))},e.prototype.isExpanded=function(){return!!this.isExpandable&&"true"===this.domNode.getAttribute("aria-expanded")},e.prototype.handleKeydown=function(e){e.currentTarget;var t=!1,i=e.key;function o(e){return 1===e.length&&e.match(/\S/)}function s(e){"*"==i?(e.tree.expandAllSiblingItems(e),t=!0):o(i)&&(e.tree.setFocusByFirstCharacter(e,i),t=!0)}if(this.stopDefaultClick=!1,!(e.altKey||e.ctrlKey||e.metaKey)){if(e.shift)e.keyCode==this.keyCode.SPACE||e.keyCode==this.keyCode.RETURN?(e.stopPropagation(),this.stopDefaultClick=!0):o(i)&&s(this);else switch(e.keyCode){case this.keyCode.SPACE:case this.keyCode.RETURN:this.isExpandable?(this.isExpanded()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),t=!0):(e.stopPropagation(),this.stopDefaultClick=!0);break;case this.keyCode.UP:this.tree.setFocusToPreviousItem(this),t=!0;break;case this.keyCode.DOWN:this.tree.setFocusToNextItem(this),t=!0;break;case this.keyCode.RIGHT:this.isExpandable&&(this.isExpanded()?this.tree.setFocusToNextItem(this):this.tree.expandTreeitem(this)),t=!0;break;case this.keyCode.LEFT:this.isExpandable&&this.isExpanded()?(this.tree.collapseTreeitem(this),t=!0):this.inGroup&&(this.tree.setFocusToParentItem(this),t=!0);break;case this.keyCode.HOME:this.tree.setFocusToFirstItem(),t=!0;break;case this.keyCode.END:this.tree.setFocusToLastItem(),t=!0;break;default:o(i)&&s(this)}t&&(e.stopPropagation(),e.preventDefault())}},e.prototype.handleClick=function(e){e.target!==this.domNode&&e.target!==this.domNode.firstElementChild||this.isExpandable&&(this.isExpanded()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),e.stopPropagation())},e.prototype.handleFocus=function(e){var t=this.domNode;(t=this.isExpandable?t.firstElementChild:t).classList.add("focus")},e.prototype.handleBlur=function(e){var t=this.domNode;(t=this.isExpandable?t.firstElementChild:t).classList.remove("focus")},e.prototype.handleMouseOver=function(e){e.currentTarget.classList.add("hover")},e.prototype.handleMouseOut=function(e){e.currentTarget.classList.remove("hover")},e);function e(e,t,i){if("object"==typeof e){e.tabIndex=-1,this.tree=t,this.groupTreeitem=i,this.domNode=e,this.label=e.textContent.trim(),this.stopDefaultClick=!1,e.getAttribute("aria-label")&&(this.label=e.getAttribute("aria-label").trim()),this.isExpandable=!1,this.isVisible=!1,this.inGroup=!1,i&&(this.inGroup=!0);for(var o=e.firstElementChild;o;){if("ul"==o.tagName.toLowerCase()){o.setAttribute("role","group"),this.isExpandable=!0;break}o=o.nextElementSibling}this.keyCode=Object.freeze({RETURN:13,SPACE:32,PAGEUP:33,PAGEDOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40})}}function d(e){"object"==typeof e&&(this.domNode=e,this.treeitems=[],this.firstChars=[],this.firstTreeitem=null,this.lastTreeitem=null)}return d.prototype.init=function(){this.domNode.getAttribute("role")||this.domNode.setAttribute("role","tree"),function e(t,i,o){for(var s=t.firstElementChild,r=o;s;)("li"===s.tagName.toLowerCase()&&"span"===s.firstElementChild.tagName.toLowerCase()||"a"===s.tagName.toLowerCase())&&((r=new a(s,i,o)).init(),i.treeitems.push(r),i.firstChars.push(r.label.substring(0,1).toLowerCase())),s.firstElementChild&&e(s,i,r),s=s.nextElementSibling}(this.domNode,this,!1),this.updateVisibleTreeitems(),this.firstTreeitem.domNode.tabIndex=0},d.prototype.setFocusToItem=function(e){for(var t=0;t<this.treeitems.length;t++){var i=this.treeitems[t];i===e?(i.domNode.tabIndex=0,i.domNode.focus()):i.domNode.tabIndex=-1}},d.prototype.setFocusToNextItem=function(e){for(var t=!1,i=this.treeitems.length-1;0<=i;i--){var o=this.treeitems[i];if(o===e)break;o.isVisible&&(t=o)}t&&this.setFocusToItem(t)},d.prototype.setFocusToPreviousItem=function(e){for(var t=!1,i=0;i<this.treeitems.length;i++){var o=this.treeitems[i];if(o===e)break;o.isVisible&&(t=o)}t&&this.setFocusToItem(t)},d.prototype.setFocusToParentItem=function(e){e.groupTreeitem&&this.setFocusToItem(e.groupTreeitem)},d.prototype.setFocusToFirstItem=function(){this.setFocusToItem(this.firstTreeitem)},d.prototype.setFocusToLastItem=function(){this.setFocusToItem(this.lastTreeitem)},d.prototype.expandTreeitem=function(e){e.isExpandable&&(e.domNode.setAttribute("aria-expanded",!0),this.updateVisibleTreeitems())},d.prototype.expandAllSiblingItems=function(e){for(var t=0;t<this.treeitems.length;t++){var i=this.treeitems[t];i.groupTreeitem===e.groupTreeitem&&i.isExpandable&&this.expandTreeitem(i)}},d.prototype.collapseTreeitem=function(e){var t=!1;(t=e.isExpanded()?e:e.groupTreeitem)&&(t.domNode.setAttribute("aria-expanded",!1),this.updateVisibleTreeitems(),this.setFocusToItem(t))},d.prototype.updateVisibleTreeitems=function(){this.firstTreeitem=this.treeitems[0];for(var e=0;e<this.treeitems.length;e++){var t=this.treeitems[e],i=t.domNode.parentNode;for(t.isVisible=!0;i&&i!==this.domNode;)"false"==i.getAttribute("aria-expanded")&&(t.isVisible=!1),i=i.parentNode;t.isVisible&&(this.lastTreeitem=t)}},d.prototype.setFocusByFirstCharacter=function(e,t){t=t.toLowerCase(),(e=this.treeitems.indexOf(e)+1)===this.treeitems.length&&(e=0),-1<(e=-1===(e=this.getIndexFirstChars(e,t))?this.getIndexFirstChars(0,t):e)&&this.setFocusToItem(this.treeitems[e])},d.prototype.getIndexFirstChars=function(e,t){for(var i=e;i<this.firstChars.length;i++)if(this.treeitems[i].isVisible&&t===this.firstChars[i])return i;return-1},t=d,n}(jQuery),wp.themePluginEditor.l10n=wp.themePluginEditor.l10n||{saveAlert:"",saveError:"",lintError:{alternative:"wp.i18n",func:function(){return{singular:"",plural:""}}}},wp.themePluginEditor.l10n=window.wp.deprecateL10nObject("wp.themePluginEditor.l10n",wp.themePluginEditor.l10n,"5.5.0");
\ No newline at end of file
+window.wp||(window.wp={}),wp.themePluginEditor=function(o){"use strict";var t,i=wp.i18n.__,s=wp.i18n._n,r=wp.i18n.sprintf,n={codeEditor:{},instance:null,noticeElements:{},dirty:!1,lintErrors:[],init:function(e,t){n.form=e,t&&o.extend(n,t),n.noticeTemplate=wp.template("wp-file-editor-notice"),n.noticesContainer=n.form.find(".editor-notices"),n.submitButton=n.form.find(":input[name=submit]"),n.spinner=n.form.find(".submit .spinner"),n.form.on("submit",n.submit),n.textarea=n.form.find("#newcontent"),n.textarea.on("change",n.onChange),n.warning=o(".file-editor-warning"),n.docsLookUpButton=n.form.find("#docs-lookup"),n.docsLookUpList=n.form.find("#docs-list"),0<n.warning.length&&n.showWarning(),!1!==n.codeEditor&&_.defer(function(){n.initCodeEditor()}),o(n.initFileBrowser),o(window).on("beforeunload",function(){if(n.dirty)return i("The changes you made will be lost if you navigate away from this page.")}),n.docsLookUpList.on("change",function(){""===o(this).val()?n.docsLookUpButton.prop("disabled",!0):n.docsLookUpButton.prop("disabled",!1)}),o(window).on("keydown",function(e){!e.ctrlKey&&!e.metaKey||"s"!==e.key.toLowerCase()||n.instance&&n.instance.codemirror.hasFocus()||(e.preventDefault(),n.form.trigger("submit"))})},showWarning:function(){var e=n.warning.find(".file-editor-warning-message").text();o("#wpwrap").attr("aria-hidden","true"),o(document.body).addClass("modal-open").append(n.warning.detach()),n.warning.removeClass("hidden").find(".file-editor-warning-go-back").trigger("focus"),n.warningTabbables=n.warning.find("a, button"),n.warningTabbables.on("keydown",n.constrainTabbing),n.warning.on("click",".file-editor-warning-dismiss",n.dismissWarning),setTimeout(function(){wp.a11y.speak(wp.sanitize.stripTags(e.replace(/\s+/g," ")),"assertive")},1e3)},constrainTabbing:function(e){var t,i;9===e.which&&(t=n.warningTabbables.first()[0],(i=n.warningTabbables.last()[0])!==e.target||e.shiftKey?t===e.target&&e.shiftKey&&(i.focus(),e.preventDefault()):(t.focus(),e.preventDefault()))},dismissWarning:function(){wp.ajax.post("dismiss-wp-pointer",{pointer:n.themeOrPlugin+"_editor_notice"}),n.warning.remove(),o("#wpwrap").removeAttr("aria-hidden"),o("body").removeClass("modal-open")},onChange:function(){n.dirty=!0,n.removeNotice("file_saved")},submit:function(e){var t={};e.preventDefault(),o.each(n.form.serializeArray(),function(){t[this.name]=this.value}),n.instance&&(t.newcontent=n.instance.codemirror.getValue()),n.isSaving||(n.instance&&n.instance.updateErrorNotice&&n.instance.updateErrorNotice(),n.lintErrors.length?n.instance.codemirror.setCursor(n.lintErrors[0].from.line):(n.isSaving=!0,n.textarea.prop("readonly",!0),n.instance&&n.instance.codemirror.setOption("readOnly",!0),n.spinner.addClass("is-active"),e=wp.ajax.post("edit-theme-plugin-file",t),n.lastSaveNoticeCode&&n.removeNotice(n.lastSaveNoticeCode),e.done(function(e){n.lastSaveNoticeCode="file_saved",n.addNotice({code:n.lastSaveNoticeCode,type:"success",message:e.message,dismissible:!0}),n.dirty=!1}),e.fail(function(e){e=o.extend({code:"save_error",message:i("An error occurred while saving your changes. Please try again. If the problem persists, you may need to manually update the file via FTP.")},e,{type:"error",dismissible:!0});n.lastSaveNoticeCode=e.code,n.addNotice(e)}),e.always(function(){n.spinner.removeClass("is-active"),n.isSaving=!1,n.textarea.prop("readonly",!1),n.instance&&n.instance.codemirror.setOption("readOnly",!1)})))},addNotice:function(e){var t;if(e.code)return n.removeNotice(e.code),(t=o(n.noticeTemplate(e))).hide(),t.find(".notice-dismiss").on("click",function(){n.removeNotice(e.code),e.onDismiss&&e.onDismiss(e)}),wp.a11y.speak(e.message),n.noticesContainer.append(t),t.slideDown("fast"),n.noticeElements[e.code]=t;throw new Error("Missing code.")},removeNotice:function(e){return!!n.noticeElements[e]&&(n.noticeElements[e].slideUp("fast",function(){o(this).remove()}),delete n.noticeElements[e],!0)},initCodeEditor:function(){var t,e;function i(){n.form.trigger("submit")}(t=o.extend({},n.codeEditor)).onTabPrevious=function(){o("#templateside").find(":tabbable").last().trigger("focus")},t.onTabNext=function(){o("#template").find(":tabbable:not(.CodeMirror-code)").first().trigger("focus")},t.onChangeLintingErrors=function(e){0===(n.lintErrors=e).length&&n.submitButton.toggleClass("disabled",!1)},t.onUpdateErrorNotice=function(e){n.submitButton.toggleClass("disabled",0<e.length),0!==e.length?n.addNotice({code:"lint_errors",type:"error",message:r(s("There is %s error which must be fixed before you can update this file.","There are %s errors which must be fixed before you can update this file.",e.length),String(e.length)),dismissible:!1}).find("input[type=checkbox]").on("click",function(){t.onChangeLintingErrors([]),n.removeNotice("lint_errors")}):n.removeNotice("lint_errors")},(e=wp.codeEditor.initialize(o("#newcontent"),t)).codemirror.on("change",n.onChange),e.codemirror.setOption("extraKeys",{...e.codemirror.getOption("extraKeys")||{},"Ctrl-S":i,"Cmd-S":i}),o(e.codemirror.display.lineDiv).attr({role:"textbox","aria-multiline":"true","aria-labelledby":"theme-plugin-editor-label","aria-describedby":"editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"}),o("#theme-plugin-editor-label").on("click",function(){e.codemirror.focus()}),n.instance=e},initFileBrowser:function(){var e=o("#templateside");e.find('[role="group"]').parent().attr("aria-expanded",!1),e.find(".notice").parents("[aria-expanded]").attr("aria-expanded",!0),e.find('[role="tree"]').each(function(){new t(this).init()}),e.find(".current-file:first").each(function(){this.scrollIntoViewIfNeeded?this.scrollIntoViewIfNeeded():this.scrollIntoView(!1)})}},a=(e.prototype.init=function(){this.domNode.tabIndex=-1,this.domNode.getAttribute("role")||this.domNode.setAttribute("role","treeitem"),this.domNode.addEventListener("keydown",this.handleKeydown.bind(this)),this.domNode.addEventListener("click",this.handleClick.bind(this)),this.domNode.addEventListener("focus",this.handleFocus.bind(this)),this.domNode.addEventListener("blur",this.handleBlur.bind(this)),(this.isExpandable?(this.domNode.firstElementChild.addEventListener("mouseover",this.handleMouseOver.bind(this)),this.domNode.firstElementChild):(this.domNode.addEventListener("mouseover",this.handleMouseOver.bind(this)),this.domNode)).addEventListener("mouseout",this.handleMouseOut.bind(this))},e.prototype.isExpanded=function(){return!!this.isExpandable&&"true"===this.domNode.getAttribute("aria-expanded")},e.prototype.handleKeydown=function(e){e.currentTarget;var t=!1,i=e.key;function o(e){return 1===e.length&&e.match(/\S/)}function s(e){"*"==i?(e.tree.expandAllSiblingItems(e),t=!0):o(i)&&(e.tree.setFocusByFirstCharacter(e,i),t=!0)}if(this.stopDefaultClick=!1,!(e.altKey||e.ctrlKey||e.metaKey)){if(e.shift)e.keyCode==this.keyCode.SPACE||e.keyCode==this.keyCode.RETURN?(e.stopPropagation(),this.stopDefaultClick=!0):o(i)&&s(this);else switch(e.keyCode){case this.keyCode.SPACE:case this.keyCode.RETURN:this.isExpandable?(this.isExpanded()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),t=!0):(e.stopPropagation(),this.stopDefaultClick=!0);break;case this.keyCode.UP:this.tree.setFocusToPreviousItem(this),t=!0;break;case this.keyCode.DOWN:this.tree.setFocusToNextItem(this),t=!0;break;case this.keyCode.RIGHT:this.isExpandable&&(this.isExpanded()?this.tree.setFocusToNextItem(this):this.tree.expandTreeitem(this)),t=!0;break;case this.keyCode.LEFT:this.isExpandable&&this.isExpanded()?(this.tree.collapseTreeitem(this),t=!0):this.inGroup&&(this.tree.setFocusToParentItem(this),t=!0);break;case this.keyCode.HOME:this.tree.setFocusToFirstItem(),t=!0;break;case this.keyCode.END:this.tree.setFocusToLastItem(),t=!0;break;default:o(i)&&s(this)}t&&(e.stopPropagation(),e.preventDefault())}},e.prototype.handleClick=function(e){e.target!==this.domNode&&e.target!==this.domNode.firstElementChild||this.isExpandable&&(this.isExpanded()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),e.stopPropagation())},e.prototype.handleFocus=function(e){var t=this.domNode;(t=this.isExpandable?t.firstElementChild:t).classList.add("focus")},e.prototype.handleBlur=function(e){var t=this.domNode;(t=this.isExpandable?t.firstElementChild:t).classList.remove("focus")},e.prototype.handleMouseOver=function(e){e.currentTarget.classList.add("hover")},e.prototype.handleMouseOut=function(e){e.currentTarget.classList.remove("hover")},e);function e(e,t,i){if("object"==typeof e){e.tabIndex=-1,this.tree=t,this.groupTreeitem=i,this.domNode=e,this.label=e.textContent.trim(),this.stopDefaultClick=!1,e.getAttribute("aria-label")&&(this.label=e.getAttribute("aria-label").trim()),this.isExpandable=!1,this.isVisible=!1,this.inGroup=!1,i&&(this.inGroup=!0);for(var o=e.firstElementChild;o;){if("ul"==o.tagName.toLowerCase()){o.setAttribute("role","group"),this.isExpandable=!0;break}o=o.nextElementSibling}this.keyCode=Object.freeze({RETURN:13,SPACE:32,PAGEUP:33,PAGEDOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40})}}function d(e){"object"==typeof e&&(this.domNode=e,this.treeitems=[],this.firstChars=[],this.firstTreeitem=null,this.lastTreeitem=null)}return d.prototype.init=function(){this.domNode.getAttribute("role")||this.domNode.setAttribute("role","tree"),function e(t,i,o){for(var s=t.firstElementChild,r=o;s;)("li"===s.tagName.toLowerCase()&&"span"===s.firstElementChild.tagName.toLowerCase()||"a"===s.tagName.toLowerCase())&&((r=new a(s,i,o)).init(),i.treeitems.push(r),i.firstChars.push(r.label.substring(0,1).toLowerCase())),s.firstElementChild&&e(s,i,r),s=s.nextElementSibling}(this.domNode,this,!1),this.updateVisibleTreeitems(),this.firstTreeitem.domNode.tabIndex=0},d.prototype.setFocusToItem=function(e){for(var t=0;t<this.treeitems.length;t++){var i=this.treeitems[t];i===e?(i.domNode.tabIndex=0,i.domNode.focus()):i.domNode.tabIndex=-1}},d.prototype.setFocusToNextItem=function(e){for(var t=!1,i=this.treeitems.length-1;0<=i;i--){var o=this.treeitems[i];if(o===e)break;o.isVisible&&(t=o)}t&&this.setFocusToItem(t)},d.prototype.setFocusToPreviousItem=function(e){for(var t=!1,i=0;i<this.treeitems.length;i++){var o=this.treeitems[i];if(o===e)break;o.isVisible&&(t=o)}t&&this.setFocusToItem(t)},d.prototype.setFocusToParentItem=function(e){e.groupTreeitem&&this.setFocusToItem(e.groupTreeitem)},d.prototype.setFocusToFirstItem=function(){this.setFocusToItem(this.firstTreeitem)},d.prototype.setFocusToLastItem=function(){this.setFocusToItem(this.lastTreeitem)},d.prototype.expandTreeitem=function(e){e.isExpandable&&(e.domNode.setAttribute("aria-expanded",!0),this.updateVisibleTreeitems())},d.prototype.expandAllSiblingItems=function(e){for(var t=0;t<this.treeitems.length;t++){var i=this.treeitems[t];i.groupTreeitem===e.groupTreeitem&&i.isExpandable&&this.expandTreeitem(i)}},d.prototype.collapseTreeitem=function(e){var t=!1;(t=e.isExpanded()?e:e.groupTreeitem)&&(t.domNode.setAttribute("aria-expanded",!1),this.updateVisibleTreeitems(),this.setFocusToItem(t))},d.prototype.updateVisibleTreeitems=function(){this.firstTreeitem=this.treeitems[0];for(var e=0;e<this.treeitems.length;e++){var t=this.treeitems[e],i=t.domNode.parentNode;for(t.isVisible=!0;i&&i!==this.domNode;)"false"==i.getAttribute("aria-expanded")&&(t.isVisible=!1),i=i.parentNode;t.isVisible&&(this.lastTreeitem=t)}},d.prototype.setFocusByFirstCharacter=function(e,t){t=t.toLowerCase(),(e=this.treeitems.indexOf(e)+1)===this.treeitems.length&&(e=0),-1<(e=-1===(e=this.getIndexFirstChars(e,t))?this.getIndexFirstChars(0,t):e)&&this.setFocusToItem(this.treeitems[e])},d.prototype.getIndexFirstChars=function(e,t){for(var i=e;i<this.firstChars.length;i++)if(this.treeitems[i].isVisible&&t===this.firstChars[i])return i;return-1},t=d,n}(jQuery),wp.themePluginEditor.l10n=wp.themePluginEditor.l10n||{saveAlert:"",saveError:"",lintError:{alternative:"wp.i18n",func:function(){return{singular:"",plural:""}}}},wp.themePluginEditor.l10n=window.wp.deprecateL10nObject("wp.themePluginEditor.l10n",wp.themePluginEditor.l10n,"5.5.0");
\ No newline at end of file
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 33befb47a0..1a50374451 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.0-alpha-61587';
+$wp_version = '7.0-alpha-61588';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.