Customize: Introduce extensible code editor Customizer control for CodeMirror.

* Adds `WP_Customize_Code_Editor_Control` and `wp.customize.CodeEditorControl()`.
* Control respects user preference for syntax highlighting, showing a textarea when user opts out.
* Code editor control takes the ad hoc code for Additional CSS and makes it reusable and extensible, for Additional CSS in core and plugins to use (such as Jetpack).
* Replace `settings` arg in `wp_enqueue_code_editor()` with separate args for `codemirror`, `csslint`, `jshint`, and `htmlhint`.
* Prefix `codemirror` script and style handles with `wp-` to prevent collisions, as also the object is exported as `wp.CodeMirror` in JS.
* Reduce indent size in Customizer code editor instances and Custom HTML widget to use tab size of 2 instead of 4 to save on space.

See #12423, #38707, #35395.
Fixes #41897.

Built from https://develop.svn.wordpress.org/trunk@41558


git-svn-id: http://core.svn.wordpress.org/trunk@41391 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Weston Ruter 2017-09-21 23:04:45 +00:00
parent 43eb51d4a6
commit f0b5c39bde
12 changed files with 423 additions and 245 deletions

View File

@ -1164,12 +1164,26 @@ p.customize-section-description {
}
/**
* Custom CSS Section
* Code Editor Control and Custom CSS Section
*
* Modifications to the Section Container to make the textarea full-width and
* full-height, if the control is the only control in the section.
*/
.customize-control-code_editor textarea {
width: 100%;
font-family: Consolas, Monaco, monospace;
font-size: 12px;
padding: 6px 8px;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
.customize-control-code_editor textarea,
.customize-control-code_editor .CodeMirror {
height: 14em;
}
#customize-controls .customize-section-description-container.section-meta.customize-info {
border-bottom: none;
}
@ -1180,13 +1194,7 @@ p.customize-section-description {
#customize-control-custom_css textarea {
display: block;
font-family: Consolas, Monaco, monospace;
font-size: 12px;
padding: 6px 8px;
height: 500px;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
}
.customize-section-description-container + #customize-control-custom_css:last-child textarea {

File diff suppressed because one or more lines are too long

View File

@ -1164,12 +1164,26 @@ p.customize-section-description {
}
/**
* Custom CSS Section
* Code Editor Control and Custom CSS Section
*
* Modifications to the Section Container to make the textarea full-width and
* full-height, if the control is the only control in the section.
*/
.customize-control-code_editor textarea {
width: 100%;
font-family: Consolas, Monaco, monospace;
font-size: 12px;
padding: 6px 8px;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
.customize-control-code_editor textarea,
.customize-control-code_editor .CodeMirror {
height: 14em;
}
#customize-controls .customize-section-description-container.section-meta.customize-info {
border-bottom: none;
}
@ -1180,13 +1194,7 @@ p.customize-section-description {
#customize-control-custom_css textarea {
display: block;
font-family: Consolas, Monaco, monospace;
font-size: 12px;
padding: 6px 8px;
height: 500px;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
}
.customize-section-description-container + #customize-control-custom_css:last-child textarea {

File diff suppressed because one or more lines are too long

View File

@ -3677,6 +3677,250 @@
}
});
/**
* Class wp.customize.CodeEditorControl
*
* @since 4.9.0
*
* @constructor
* @augments wp.customize.Control
* @augments wp.customize.Class
*/
api.CodeEditorControl = api.Control.extend({
/**
* Initialize the editor when the containing section is ready and expanded.
*
* @since 4.9.0
* @returns {void}
*/
ready: function() {
var control = this;
if ( ! control.section() ) {
control.initEditor();
return;
}
// Wait to initialize editor until section is embedded and expanded.
api.section( control.section(), function( section ) {
section.deferred.embedded.done( function() {
var onceExpanded;
if ( section.expanded() ) {
control.initEditor();
} else {
onceExpanded = function( isExpanded ) {
if ( isExpanded ) {
control.initEditor();
section.expanded.unbind( onceExpanded );
}
};
section.expanded.bind( onceExpanded );
}
} );
} );
},
/**
* Initialize editor.
*
* @since 4.9.0
* @returns {void}
*/
initEditor: function() {
var control = this, element;
element = new api.Element( control.container.find( 'textarea' ) );
control.elements.push( element );
element.sync( control.setting );
element.set( control.setting() );
if ( control.params.editor_settings ) {
control.initSyntaxHighlightingEditor( control.params.editor_settings );
} else {
control.initPlainTextareaEditor();
}
},
/**
* Make sure editor gets focused when control is focused.
*
* @since 4.9.0
* @param {Object} [params] - Focus params.
* @param {Function} [params.completeCallback] - Function to call when expansion is complete.
* @returns {void}
*/
focus: function( params ) {
var control = this, extendedParams = _.extend( {}, params ), originalCompleteCallback;
originalCompleteCallback = extendedParams.completeCallback;
extendedParams.completeCallback = function() {
if ( originalCompleteCallback ) {
originalCompleteCallback();
}
if ( control.editor ) {
control.editor.codemirror.focus();
}
};
api.Control.prototype.focus.call( control, extendedParams );
},
/**
* Initialize syntax-highlighting editor.
*
* @since 4.9.0
* @param {object} codeEditorSettings - Code editor settings.
* @returns {void}
*/
initSyntaxHighlightingEditor: function( codeEditorSettings ) {
var control = this, $textarea = control.container.find( 'textarea' ), settings, suspendEditorUpdate = false;
settings = _.extend( {}, codeEditorSettings, {
onTabNext: _.bind( control.onTabNext, control ),
onTabPrevious: _.bind( control.onTabPrevious, control ),
onUpdateErrorNotice: _.bind( control.onUpdateErrorNotice, control )
});
control.editor = wp.codeEditor.initialize( $textarea, settings );
// Refresh when receiving focus.
control.editor.codemirror.on( 'focus', function( codemirror ) {
codemirror.refresh();
});
/*
* When the CodeMirror instance changes, mirror to the textarea,
* where we have our "true" change event handler bound.
*/
control.editor.codemirror.on( 'change', function( codemirror ) {
suspendEditorUpdate = true;
$textarea.val( codemirror.getValue() ).trigger( 'change' );
suspendEditorUpdate = false;
});
// Update CodeMirror when the setting is changed by another plugin.
control.setting.bind( function( value ) {
if ( ! suspendEditorUpdate ) {
control.editor.codemirror.setValue( value );
}
});
// Prevent collapsing section when hitting Esc to tab out of editor.
control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
var escKeyCode = 27;
if ( escKeyCode === event.keyCode ) {
event.stopPropagation();
}
});
},
/**
* Handle tabbing to the field after the editor.
*
* @since 4.9.0
* @returns {void}
*/
onTabNext: function onTabNext() {
var control = this, controls, controlIndex, section;
section = api.section( control.section() );
controls = section.controls();
controlIndex = controls.indexOf( control );
if ( controls.length === controlIndex + 1 ) {
$( '#customize-footer-actions .collapse-sidebar' ).focus();
} else {
controls[ controlIndex + 1 ].container.find( ':focusable:first' ).focus();
}
},
/**
* Handle tabbing to the field before the editor.
*
* @since 4.9.0
* @returns {void}
*/
onTabPrevious: function onTabPrevious() {
var control = this, controls, controlIndex, section;
section = api.section( control.section() );
controls = section.controls();
controlIndex = controls.indexOf( control );
if ( 0 === controlIndex ) {
section.contentContainer.find( '.customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close' ).last().focus();
} else {
controls[ controlIndex - 1 ].contentContainer.find( ':focusable:first' ).focus();
}
},
/**
* Update error notice.
*
* @since 4.9.0
* @param {Array} errorAnnotations - Error annotations.
* @returns {void}
*/
onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
var control = this, message;
control.setting.notifications.remove( 'csslint_error' );
if ( 0 !== errorAnnotations.length ) {
if ( 1 === errorAnnotations.length ) {
message = api.l10n.customCssError.singular.replace( '%d', '1' );
} else {
message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) );
}
control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', {
message: message,
type: 'error'
} ) );
}
},
/**
* Initialize plain-textarea editor when syntax highlighting is disabled.
*
* @since 4.9.0
* @returns {void}
*/
initPlainTextareaEditor: function() {
var control = this, $textarea = control.container.find( 'textarea' ), textarea = $textarea[0];
$textarea.on( 'blur', function onBlur() {
$textarea.data( 'next-tab-blurs', false );
} );
$textarea.on( 'keydown', function onKeydown( event ) {
var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27;
if ( escKeyCode === event.keyCode ) {
if ( ! $textarea.data( 'next-tab-blurs' ) ) {
$textarea.data( 'next-tab-blurs', true );
event.stopPropagation(); // Prevent collapsing the section.
}
return;
}
// Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed.
if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) {
return;
}
// Prevent capturing Tab characters if Esc was pressed.
if ( $textarea.data( 'next-tab-blurs' ) ) {
return;
}
selectionStart = textarea.selectionStart;
selectionEnd = textarea.selectionEnd;
value = textarea.value;
if ( selectionStart >= 0 ) {
textarea.value = value.substring( 0, selectionStart ).concat( '\t', value.substring( selectionEnd ) );
$textarea.selectionStart = textarea.selectionEnd = selectionStart + 1;
}
event.stopPropagation();
event.preventDefault();
});
}
});
// Change objects contained within the main customize object to Settings.
api.defaultConstructor = api.Setting;
@ -4372,7 +4616,8 @@
header: api.HeaderControl,
background: api.BackgroundControl,
background_position: api.BackgroundPositionControl,
theme: api.ThemeControl
theme: api.ThemeControl,
code_editor: api.CodeEditorControl
};
api.panelConstructor = {};
api.sectionConstructor = {
@ -5712,7 +5957,7 @@
// Add code editor for Custom CSS.
(function() {
var ready, sectionReady = $.Deferred(), controlReady = $.Deferred();
var sectionReady = $.Deferred();
api.section( 'custom_css', function( section ) {
section.deferred.embedded.done( function() {
@ -5727,16 +5972,10 @@
}
});
});
api.control( 'custom_css', function( control ) {
control.deferred.embedded.done( function() {
controlReady.resolve( control );
});
});
ready = $.when( sectionReady, controlReady );
// Set up the section desription behaviors.
ready.done( function setupSectionDescription( section, control ) {
sectionReady.done( function setupSectionDescription( section ) {
var control = api.control( 'custom_css' );
// Close the section description when clicking the close button.
section.container.find( '.section-description-buttons .section-description-close' ).on( 'click', function() {
@ -5747,174 +5986,13 @@
});
// Reveal help text if setting is empty.
if ( ! control.setting.get() ) {
if ( control && ! control.setting.get() ) {
section.container.find( '.section-meta .customize-section-description:first' )
.addClass( 'open' )
.show()
.attr( 'aria-expanded', 'true' );
}
});
// Set up the code editor itself.
if ( api.settings.customCss && api.settings.customCss.codeEditor ) {
// Set up the syntax highlighting editor.
ready.done( function setupSyntaxHighlightingEditor( section, control ) {
var $textarea = control.container.find( 'textarea' ), settings, suspendEditorUpdate = false;
// Make sure editor gets focused when control is focused.
control.focus = (function( originalFocus ) { // eslint-disable-line max-nested-callbacks
return function( params ) { // eslint-disable-line max-nested-callbacks
var extendedParams = _.extend( {}, params ), originalCompleteCallback;
originalCompleteCallback = extendedParams.completeCallback;
extendedParams.completeCallback = function() {
if ( originalCompleteCallback ) {
originalCompleteCallback();
}
if ( control.editor ) {
control.editor.codemirror.focus();
}
};
originalFocus.call( this, extendedParams );
};
})( control.focus );
settings = _.extend( {}, api.settings.customCss.codeEditor, {
/**
* Handle tabbing to the field after the editor.
*
* @returns {void}
*/
onTabNext: function onTabNext() {
var controls, controlIndex;
controls = section.controls();
controlIndex = controls.indexOf( control );
if ( controls.length === controlIndex + 1 ) {
$( '#customize-footer-actions .collapse-sidebar' ).focus();
} else {
controls[ controlIndex + 1 ].container.find( ':focusable:first' ).focus();
}
},
/**
* Handle tabbing to the field before the editor.
*
* @returns {void}
*/
onTabPrevious: function onTabPrevious() {
var controls, controlIndex;
controls = section.controls();
controlIndex = controls.indexOf( control );
if ( 0 === controlIndex ) {
section.contentContainer.find( '.customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close' ).last().focus();
} else {
controls[ controlIndex - 1 ].contentContainer.find( ':focusable:first' ).focus();
}
},
/**
* Update error notice.
*
* @param {Array} errorAnnotations - Error annotations.
* @returns {void}
*/
onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
var message;
control.setting.notifications.remove( 'csslint_error' );
if ( 0 !== errorAnnotations.length ) {
if ( 1 === errorAnnotations.length ) {
message = api.l10n.customCssError.singular.replace( '%d', '1' );
} else {
message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) );
}
control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', {
message: message,
type: 'error'
} ) );
}
}
});
control.editor = wp.codeEditor.initialize( $textarea, settings );
// Refresh when receiving focus.
control.editor.codemirror.on( 'focus', function( codemirror ) {
codemirror.refresh();
});
/*
* When the CodeMirror instance changes, mirror to the textarea,
* where we have our "true" change event handler bound.
*/
control.editor.codemirror.on( 'change', function( codemirror ) {
suspendEditorUpdate = true;
$textarea.val( codemirror.getValue() ).trigger( 'change' );
suspendEditorUpdate = false;
});
// Update CodeMirror when the setting is changed by another plugin.
control.setting.bind( function( value ) {
if ( ! suspendEditorUpdate ) {
control.editor.codemirror.setValue( value );
}
});
// Prevent collapsing section when hitting Esc to tab out of editor.
control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
var escKeyCode = 27;
if ( escKeyCode === event.keyCode ) {
event.stopPropagation();
}
});
});
} else {
// Allow tabs to be entered in Custom CSS textarea.
ready.done( function allowTabs( section, control ) {
var $textarea = control.container.find( 'textarea' ), textarea = $textarea[0];
$textarea.on( 'blur', function onBlur() {
$textarea.data( 'next-tab-blurs', false );
} );
$textarea.on( 'keydown', function onKeydown( event ) {
var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27;
if ( escKeyCode === event.keyCode ) {
if ( ! $textarea.data( 'next-tab-blurs' ) ) {
$textarea.data( 'next-tab-blurs', true );
event.stopPropagation(); // Prevent collapsing the section.
}
return;
}
// Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed.
if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) {
return;
}
// Prevent capturing Tab characters if Esc was pressed.
if ( $textarea.data( 'next-tab-blurs' ) ) {
return;
}
selectionStart = textarea.selectionStart;
selectionEnd = textarea.selectionEnd;
value = textarea.value;
if ( selectionStart >= 0 ) {
textarea.value = value.substring( 0, selectionStart ).concat( '\t', value.substring( selectionEnd ) );
$textarea.selectionStart = textarea.selectionEnd = selectionStart + 1;
}
event.stopPropagation();
event.preventDefault();
});
});
}
})();
// Toggle visibility of Header Video notice when active state change.

File diff suppressed because one or more lines are too long

View File

@ -212,21 +212,6 @@ final class WP_Customize_Manager {
*/
private $_changeset_data;
/**
* Code Editor Settings for Custom CSS.
*
* This variable contains the settings returned by `wp_enqueue_code_editor()` which are then later output
* to the client in `WP_Customize_Manager::customize_pane_settings()`. A value of false means that the
* Custom CSS section or control was removed, or that the Syntax Highlighting user pref was turned off.
*
* @see wp_enqueue_code_editor()
* @see WP_Customize_Manager::enqueue_control_scripts()
* @see WP_Customize_Manager::customize_pane_settings()
* @since 4.9.0
* @var array|false
*/
private $_custom_css_code_editor_settings = false;
/**
* Constructor.
*
@ -291,6 +276,7 @@ final class WP_Customize_Manager {
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-site-icon-control.php' );
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-header-image-control.php' );
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-theme-control.php' );
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-code-editor-control.php' );
require_once( ABSPATH . WPINC . '/customize/class-wp-widget-area-customize-control.php' );
require_once( ABSPATH . WPINC . '/customize/class-wp-widget-form-customize-control.php' );
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-control.php' );
@ -3337,12 +3323,6 @@ final class WP_Customize_Manager {
foreach ( $this->controls as $control ) {
$control->enqueue();
}
if ( $this->get_section( 'custom_css' ) && $this->get_control( 'custom_css' ) ) {
$this->_custom_css_code_editor_settings = wp_enqueue_code_editor( array(
'type' => 'text/css',
) );
}
}
/**
@ -3600,9 +3580,6 @@ final class WP_Customize_Manager {
'stylesheet' => $this->get_stylesheet(),
'active' => $this->is_theme_active(),
),
'customCss' => array(
'codeEditor' => $this->_custom_css_code_editor_settings,
),
'url' => array(
'preview' => esc_url_raw( $this->get_preview_url() ),
'parent' => esc_url_raw( admin_url() ),
@ -3736,6 +3713,7 @@ final class WP_Customize_Manager {
$this->register_control_type( 'WP_Customize_Cropped_Image_Control' );
$this->register_control_type( 'WP_Customize_Site_Icon_Control' );
$this->register_control_type( 'WP_Customize_Theme_Control' );
$this->register_control_type( 'WP_Customize_Code_Editor_Control' );
/* Themes */
@ -4239,14 +4217,11 @@ final class WP_Customize_Manager {
) );
$this->add_setting( $custom_css_setting );
$this->add_control( 'custom_css', array(
'type' => 'textarea',
$this->add_control( new WP_Customize_Code_Editor_Control( $this, 'custom_css', array(
'section' => 'custom_css',
'settings' => array( 'default' => $custom_css_setting->id ),
'input_attrs' => array(
'class' => 'code', // Ensures contents displayed as LTR instead of RTL.
),
) );
'code_type' => 'text/css',
) ) );
}
/**

View File

@ -0,0 +1,104 @@
<?php
/**
* Customize API: WP_Customize_Code_Editor_Control class
*
* @package WordPress
* @subpackage Customize
* @since 4.9.0
*/
/**
* Customize Code Editor Control class.
*
* @since 4.9.0
*
* @see WP_Customize_Control
*/
class WP_Customize_Code_Editor_Control extends WP_Customize_Control {
/**
* Customize control type.
*
* @since 4.9.0
* @var string
*/
public $type = 'code_editor';
/**
* Type of code that is being edited.
*
* @since 4.9.0
* @var string
*/
public $code_type = '';
/**
* Code editor settings.
*
* @see wp_enqueue_code_editor()
* @since 4.9.0
* @var array|false
*/
public $editor_settings = array();
/**
* Enqueue control related scripts/styles.
*
* @since 4.9.0
*/
public function enqueue() {
$this->editor_settings = wp_enqueue_code_editor( array_merge(
array(
'type' => $this->code_type,
'codemirror' => array(
'indentUnit' => 2,
'tabSize' => 2,
),
),
$this->editor_settings
) );
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @since 4.9.0
* @see WP_Customize_Control::json()
*
* @return array Array of parameters passed to the JavaScript.
*/
public function json() {
$json = parent::json();
$json['code_type'] = $this->code_type;
$json['editor_settings'] = $this->editor_settings;
return $json;
}
/**
* Don't render the control content from PHP, as it's rendered via JS on load.
*
* @since 4.9.0
*/
public function render_content() {}
/**
* Render a JS template for control display.
*
* @since 4.9.0
*/
public function content_template() {
?>
<# var elementIdPrefix = 'el' + String( Math.random() ); #>
<# if ( data.label ) { #>
<label for="{{ elementIdPrefix }}_editor">
<span class="customize-control-title">{{ data.label }}</span>
</label>
<# } #>
<# if ( data.description ) { #>
<span class="description customize-control-description">{{{ data.description }}}</span>
<# } #>
<div class="customize-control-notifications-container"></div>
<textarea id="{{ elementIdPrefix }}_editor" class="code"></textarea>
<?php
}
}

View File

@ -3125,11 +3125,14 @@ function wp_enqueue_editor() {
* @param array $args {
* Args.
*
* @type string $type The MIME type of the file to be edited.
* @type string $file Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param.
* @type array $settings Settings to merge on top of defaults which derive from `$type` or `$file` args.
* @type WP_Theme $theme Theme being edited when on theme editor.
* @type string $plugin Plugin being edited when on plugin editor.
* @type string $type The MIME type of the file to be edited.
* @type string $file Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param.
* @type WP_Theme $theme Theme being edited when on theme editor.
* @type string $plugin Plugin being edited when on plugin editor.
* @type array $codemirror Additional CodeMirror setting overrides.
* @type array $csslint CSSLint rule overrides.
* @type array $jshint JSHint rule overrides.
* @type array $htmlhint JSHint rule overrides.
* }
* @returns array|false Settings for the enqueued code editor, or false if the editor was not enqueued .
*/
@ -3408,13 +3411,11 @@ function wp_enqueue_code_editor( $args ) {
}
// Let settings supplied via args override any defaults.
if ( isset( $args['settings'] ) ) {
foreach ( $args['settings'] as $key => $value ) {
$settings[ $key ] = array_merge(
$settings[ $key ],
$value
);
}
foreach ( wp_array_slice_assoc( $args, array( 'codemirror', 'csslint', 'jshint', 'htmlhint' ) ) as $key => $value ) {
$settings[ $key ] = array_merge(
$settings[ $key ],
$value
);
}
/**
@ -3428,11 +3429,14 @@ function wp_enqueue_code_editor( $args ) {
* @param array $args {
* Args passed when calling `wp_enqueue_code_editor()`.
*
* @type string $type The MIME type of the file to be edited.
* @type string $file Filename being edited.
* @type array $settings Settings to merge on top of defaults which derive from `$type` or `$file` args.
* @type WP_Theme $theme Theme being edited when on theme editor.
* @type string $plugin Plugin being edited when on plugin editor.
* @type string $type The MIME type of the file to be edited.
* @type string $file Filename being edited.
* @type WP_Theme $theme Theme being edited when on theme editor.
* @type string $plugin Plugin being edited when on plugin editor.
* @type array $codemirror Additional CodeMirror setting overrides.
* @type array $csslint CSSLint rule overrides.
* @type array $jshint JSHint rule overrides.
* @type array $htmlhint JSHint rule overrides.
* }
*/
$settings = apply_filters( 'wp_code_editor_settings', $settings, $args );
@ -3444,9 +3448,6 @@ function wp_enqueue_code_editor( $args ) {
wp_enqueue_script( 'code-editor' );
wp_enqueue_style( 'code-editor' );
wp_enqueue_script( 'codemirror' );
wp_enqueue_style( 'codemirror' );
if ( isset( $settings['codemirror']['mode'] ) ) {
$mode = $settings['codemirror']['mode'];
if ( is_string( $mode ) ) {

View File

@ -463,13 +463,13 @@ function wp_default_scripts( &$scripts ) {
apply_filters( 'mejs_settings', $mejs_settings )
);
$scripts->add( 'codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.29.1-alpha-ee20357' );
$scripts->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.29.1-alpha-ee20357' );
$scripts->add( 'csslint', '/wp-includes/js/codemirror/csslint.js', array(), '1.0.5' );
$scripts->add( 'jshint', '/wp-includes/js/codemirror/jshint.js', array(), '2.9.5' );
$scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.2' );
$scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' );
$scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) );
$scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'codemirror' ) );
$scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'wp-codemirror' ) );
$scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'code-editor', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ) );
did_action( 'init' ) && $scripts->add_inline_script( 'wp-theme-plugin-editor', sprintf( 'wp.themePluginEditor.l10n = %s;', wp_json_encode( wp_array_slice_assoc(
/* translators: placeholder is error count */
@ -952,7 +952,7 @@ function wp_default_styles( &$styles ) {
$styles->add( 'widgets', "/wp-admin/css/widgets$suffix.css", array( 'wp-pointer' ) );
$styles->add( 'site-icon', "/wp-admin/css/site-icon$suffix.css" );
$styles->add( 'l10n', "/wp-admin/css/l10n$suffix.css" );
$styles->add( 'code-editor', "/wp-admin/css/code-editor$suffix.css", array( 'codemirror' ) );
$styles->add( 'code-editor', "/wp-admin/css/code-editor$suffix.css", array( 'wp-codemirror' ) );
$styles->add( 'wp-admin', false, array( 'dashicons', 'common', 'forms', 'admin-menu', 'dashboard', 'list-tables', 'edit', 'revisions', 'media', 'themes', 'about', 'nav-menus', 'widgets', 'site-icon', 'l10n' ) );
@ -987,7 +987,7 @@ function wp_default_styles( &$styles ) {
$styles->add( 'mediaelement', "/wp-includes/js/mediaelement/mediaelementplayer-legacy.min.css", array(), '4.2.5-74e01a40' );
$styles->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement$suffix.css", array( 'mediaelement' ) );
$styles->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.css', array( 'dashicons' ) );
$styles->add( 'codemirror', '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' );
$styles->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' );
// Deprecated CSS
$styles->add( 'deprecated-media', "/wp-admin/css/deprecated-media$suffix.css" );

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.9-alpha-41557';
$wp_version = '4.9-alpha-41558';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.

View File

@ -160,6 +160,10 @@ class WP_Widget_Custom_HTML extends WP_Widget {
public function enqueue_admin_scripts() {
$settings = wp_enqueue_code_editor( array(
'type' => 'text/html',
'codemirror' => array(
'indentUnit' => 2,
'tabSize' => 2,
),
) );
wp_enqueue_script( 'custom-html-widgets' );