WordPress.org

Make WordPress Core

Changeset 41558


Ignore:
Timestamp:
09/21/2017 11:03:06 PM (9 months ago)
Author:
westonruter
Message:

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.

Location:
trunk
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/customize-controls.css

    r41390 r41558  
    11651165
    11661166/**
    1167  * Custom CSS Section
     1167 * Code Editor Control and Custom CSS Section
    11681168 *
    11691169 * Modifications to the Section Container to make the textarea full-width and
     
    11711171 */
    11721172
    1173 #customize-controls .customize-section-description-container.section-meta.customize-info {
    1174     border-bottom: none;
    1175 }
    1176 
    1177 #sub-accordion-section-custom_css .customize-control-notifications-container {
    1178     margin-bottom: 15px;
    1179 }
    1180 
    1181 #customize-control-custom_css textarea {
    1182     display: block;
     1173.customize-control-code_editor textarea {
     1174    width: 100%;
    11831175    font-family: Consolas, Monaco, monospace;
    11841176    font-size: 12px;
    11851177    padding: 6px 8px;
     1178    -moz-tab-size: 2;
     1179    -o-tab-size: 2;
     1180    tab-size: 2;
     1181}
     1182.customize-control-code_editor textarea,
     1183.customize-control-code_editor .CodeMirror {
     1184    height: 14em;
     1185}
     1186
     1187#customize-controls .customize-section-description-container.section-meta.customize-info {
     1188    border-bottom: none;
     1189}
     1190
     1191#sub-accordion-section-custom_css .customize-control-notifications-container {
     1192    margin-bottom: 15px;
     1193}
     1194
     1195#customize-control-custom_css textarea {
     1196    display: block;
    11861197    height: 500px;
    1187     -moz-tab-size: 4;
    1188     -o-tab-size: 4;
    1189     tab-size: 4;
    11901198}
    11911199
  • trunk/src/wp-admin/js/customize-controls.js

    r41390 r41558  
    36783678    });
    36793679
     3680    /**
     3681     * Class wp.customize.CodeEditorControl
     3682     *
     3683     * @since 4.9.0
     3684     *
     3685     * @constructor
     3686     * @augments wp.customize.Control
     3687     * @augments wp.customize.Class
     3688     */
     3689    api.CodeEditorControl = api.Control.extend({
     3690
     3691        /**
     3692         * Initialize the editor when the containing section is ready and expanded.
     3693         *
     3694         * @since 4.9.0
     3695         * @returns {void}
     3696         */
     3697        ready: function() {
     3698            var control = this;
     3699            if ( ! control.section() ) {
     3700                control.initEditor();
     3701                return;
     3702            }
     3703
     3704            // Wait to initialize editor until section is embedded and expanded.
     3705            api.section( control.section(), function( section ) {
     3706                section.deferred.embedded.done( function() {
     3707                    var onceExpanded;
     3708                    if ( section.expanded() ) {
     3709                        control.initEditor();
     3710                    } else {
     3711                        onceExpanded = function( isExpanded ) {
     3712                            if ( isExpanded ) {
     3713                                control.initEditor();
     3714                                section.expanded.unbind( onceExpanded );
     3715                            }
     3716                        };
     3717                        section.expanded.bind( onceExpanded );
     3718                    }
     3719                } );
     3720            } );
     3721        },
     3722
     3723        /**
     3724         * Initialize editor.
     3725         *
     3726         * @since 4.9.0
     3727         * @returns {void}
     3728         */
     3729        initEditor: function() {
     3730            var control = this, element;
     3731
     3732            element = new api.Element( control.container.find( 'textarea' ) );
     3733            control.elements.push( element );
     3734            element.sync( control.setting );
     3735            element.set( control.setting() );
     3736
     3737            if ( control.params.editor_settings ) {
     3738                control.initSyntaxHighlightingEditor( control.params.editor_settings );
     3739            } else {
     3740                control.initPlainTextareaEditor();
     3741            }
     3742        },
     3743
     3744        /**
     3745         * Make sure editor gets focused when control is focused.
     3746         *
     3747         * @since 4.9.0
     3748         * @param {Object}   [params] - Focus params.
     3749         * @param {Function} [params.completeCallback] - Function to call when expansion is complete.
     3750         * @returns {void}
     3751         */
     3752        focus: function( params ) {
     3753            var control = this, extendedParams = _.extend( {}, params ), originalCompleteCallback;
     3754            originalCompleteCallback = extendedParams.completeCallback;
     3755            extendedParams.completeCallback = function() {
     3756                if ( originalCompleteCallback ) {
     3757                    originalCompleteCallback();
     3758                }
     3759                if ( control.editor ) {
     3760                    control.editor.codemirror.focus();
     3761                }
     3762            };
     3763            api.Control.prototype.focus.call( control, extendedParams );
     3764        },
     3765
     3766        /**
     3767         * Initialize syntax-highlighting editor.
     3768         *
     3769         * @since 4.9.0
     3770         * @param {object} codeEditorSettings - Code editor settings.
     3771         * @returns {void}
     3772         */
     3773        initSyntaxHighlightingEditor: function( codeEditorSettings ) {
     3774            var control = this, $textarea = control.container.find( 'textarea' ), settings, suspendEditorUpdate = false;
     3775
     3776            settings = _.extend( {}, codeEditorSettings, {
     3777                onTabNext: _.bind( control.onTabNext, control ),
     3778                onTabPrevious: _.bind( control.onTabPrevious, control ),
     3779                onUpdateErrorNotice: _.bind( control.onUpdateErrorNotice, control )
     3780            });
     3781
     3782            control.editor = wp.codeEditor.initialize( $textarea, settings );
     3783
     3784            // Refresh when receiving focus.
     3785            control.editor.codemirror.on( 'focus', function( codemirror ) {
     3786                codemirror.refresh();
     3787            });
     3788
     3789            /*
     3790             * When the CodeMirror instance changes, mirror to the textarea,
     3791             * where we have our "true" change event handler bound.
     3792             */
     3793            control.editor.codemirror.on( 'change', function( codemirror ) {
     3794                suspendEditorUpdate = true;
     3795                $textarea.val( codemirror.getValue() ).trigger( 'change' );
     3796                suspendEditorUpdate = false;
     3797            });
     3798
     3799            // Update CodeMirror when the setting is changed by another plugin.
     3800            control.setting.bind( function( value ) {
     3801                if ( ! suspendEditorUpdate ) {
     3802                    control.editor.codemirror.setValue( value );
     3803                }
     3804            });
     3805
     3806            // Prevent collapsing section when hitting Esc to tab out of editor.
     3807            control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
     3808                var escKeyCode = 27;
     3809                if ( escKeyCode === event.keyCode ) {
     3810                    event.stopPropagation();
     3811                }
     3812            });
     3813        },
     3814
     3815        /**
     3816         * Handle tabbing to the field after the editor.
     3817         *
     3818         * @since 4.9.0
     3819         * @returns {void}
     3820         */
     3821        onTabNext: function onTabNext() {
     3822            var control = this, controls, controlIndex, section;
     3823            section = api.section( control.section() );
     3824            controls = section.controls();
     3825            controlIndex = controls.indexOf( control );
     3826            if ( controls.length === controlIndex + 1 ) {
     3827                $( '#customize-footer-actions .collapse-sidebar' ).focus();
     3828            } else {
     3829                controls[ controlIndex + 1 ].container.find( ':focusable:first' ).focus();
     3830            }
     3831        },
     3832
     3833        /**
     3834         * Handle tabbing to the field before the editor.
     3835         *
     3836         * @since 4.9.0
     3837         * @returns {void}
     3838         */
     3839        onTabPrevious: function onTabPrevious() {
     3840            var control = this, controls, controlIndex, section;
     3841            section = api.section( control.section() );
     3842            controls = section.controls();
     3843            controlIndex = controls.indexOf( control );
     3844            if ( 0 === controlIndex ) {
     3845                section.contentContainer.find( '.customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close' ).last().focus();
     3846            } else {
     3847                controls[ controlIndex - 1 ].contentContainer.find( ':focusable:first' ).focus();
     3848            }
     3849        },
     3850
     3851        /**
     3852         * Update error notice.
     3853         *
     3854         * @since 4.9.0
     3855         * @param {Array} errorAnnotations - Error annotations.
     3856         * @returns {void}
     3857         */
     3858        onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
     3859            var control = this, message;
     3860            control.setting.notifications.remove( 'csslint_error' );
     3861
     3862            if ( 0 !== errorAnnotations.length ) {
     3863                if ( 1 === errorAnnotations.length ) {
     3864                    message = api.l10n.customCssError.singular.replace( '%d', '1' );
     3865                } else {
     3866                    message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) );
     3867                }
     3868                control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', {
     3869                    message: message,
     3870                    type: 'error'
     3871                } ) );
     3872            }
     3873        },
     3874
     3875        /**
     3876         * Initialize plain-textarea editor when syntax highlighting is disabled.
     3877         *
     3878         * @since 4.9.0
     3879         * @returns {void}
     3880         */
     3881        initPlainTextareaEditor: function() {
     3882            var control = this, $textarea = control.container.find( 'textarea' ), textarea = $textarea[0];
     3883
     3884            $textarea.on( 'blur', function onBlur() {
     3885                $textarea.data( 'next-tab-blurs', false );
     3886            } );
     3887
     3888            $textarea.on( 'keydown', function onKeydown( event ) {
     3889                var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27;
     3890
     3891                if ( escKeyCode === event.keyCode ) {
     3892                    if ( ! $textarea.data( 'next-tab-blurs' ) ) {
     3893                        $textarea.data( 'next-tab-blurs', true );
     3894                        event.stopPropagation(); // Prevent collapsing the section.
     3895                    }
     3896                    return;
     3897                }
     3898
     3899                // Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed.
     3900                if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) {
     3901                    return;
     3902                }
     3903
     3904                // Prevent capturing Tab characters if Esc was pressed.
     3905                if ( $textarea.data( 'next-tab-blurs' ) ) {
     3906                    return;
     3907                }
     3908
     3909                selectionStart = textarea.selectionStart;
     3910                selectionEnd = textarea.selectionEnd;
     3911                value = textarea.value;
     3912
     3913                if ( selectionStart >= 0 ) {
     3914                    textarea.value = value.substring( 0, selectionStart ).concat( '\t', value.substring( selectionEnd ) );
     3915                    $textarea.selectionStart = textarea.selectionEnd = selectionStart + 1;
     3916                }
     3917
     3918                event.stopPropagation();
     3919                event.preventDefault();
     3920            });
     3921        }
     3922    });
     3923
    36803924    // Change objects contained within the main customize object to Settings.
    36813925    api.defaultConstructor = api.Setting;
     
    43734617        background:          api.BackgroundControl,
    43744618        background_position: api.BackgroundPositionControl,
    4375         theme:               api.ThemeControl
     4619        theme:               api.ThemeControl,
     4620        code_editor:         api.CodeEditorControl
    43764621    };
    43774622    api.panelConstructor = {};
     
    57135958        // Add code editor for Custom CSS.
    57145959        (function() {
    5715             var ready, sectionReady = $.Deferred(), controlReady = $.Deferred();
     5960            var sectionReady = $.Deferred();
    57165961
    57175962            api.section( 'custom_css', function( section ) {
     
    57285973                });
    57295974            });
    5730             api.control( 'custom_css', function( control ) {
    5731                 control.deferred.embedded.done( function() {
    5732                     controlReady.resolve( control );
    5733                 });
    5734             });
    5735 
    5736             ready = $.when( sectionReady, controlReady );
    57375975
    57385976            // Set up the section desription behaviors.
    5739             ready.done( function setupSectionDescription( section, control ) {
     5977            sectionReady.done( function setupSectionDescription( section ) {
     5978                var control = api.control( 'custom_css' );
    57405979
    57415980                // Close the section description when clicking the close button.
     
    57485987
    57495988                // Reveal help text if setting is empty.
    5750                 if ( ! control.setting.get() ) {
     5989                if ( control && ! control.setting.get() ) {
    57515990                    section.container.find( '.section-meta .customize-section-description:first' )
    57525991                        .addClass( 'open' )
     
    57555994                }
    57565995            });
    5757 
    5758             // Set up the code editor itself.
    5759             if ( api.settings.customCss && api.settings.customCss.codeEditor ) {
    5760 
    5761                 // Set up the syntax highlighting editor.
    5762                 ready.done( function setupSyntaxHighlightingEditor( section, control ) {
    5763                     var $textarea = control.container.find( 'textarea' ), settings, suspendEditorUpdate = false;
    5764 
    5765                     // Make sure editor gets focused when control is focused.
    5766                     control.focus = (function( originalFocus ) { // eslint-disable-line max-nested-callbacks
    5767                         return function( params ) { // eslint-disable-line max-nested-callbacks
    5768                             var extendedParams = _.extend( {}, params ), originalCompleteCallback;
    5769                             originalCompleteCallback = extendedParams.completeCallback;
    5770                             extendedParams.completeCallback = function() {
    5771                                 if ( originalCompleteCallback ) {
    5772                                     originalCompleteCallback();
    5773                                 }
    5774                                 if ( control.editor ) {
    5775                                     control.editor.codemirror.focus();
    5776                                 }
    5777                             };
    5778                             originalFocus.call( this, extendedParams );
    5779                         };
    5780                     })( control.focus );
    5781 
    5782                     settings = _.extend( {}, api.settings.customCss.codeEditor, {
    5783 
    5784                         /**
    5785                          * Handle tabbing to the field after the editor.
    5786                          *
    5787                          * @returns {void}
    5788                          */
    5789                         onTabNext: function onTabNext() {
    5790                             var controls, controlIndex;
    5791                             controls = section.controls();
    5792                             controlIndex = controls.indexOf( control );
    5793                             if ( controls.length === controlIndex + 1 ) {
    5794                                 $( '#customize-footer-actions .collapse-sidebar' ).focus();
    5795                             } else {
    5796                                 controls[ controlIndex + 1 ].container.find( ':focusable:first' ).focus();
    5797                             }
    5798                         },
    5799 
    5800                         /**
    5801                          * Handle tabbing to the field before the editor.
    5802                          *
    5803                          * @returns {void}
    5804                          */
    5805                         onTabPrevious: function onTabPrevious() {
    5806                             var controls, controlIndex;
    5807                             controls = section.controls();
    5808                             controlIndex = controls.indexOf( control );
    5809                             if ( 0 === controlIndex ) {
    5810                                 section.contentContainer.find( '.customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close' ).last().focus();
    5811                             } else {
    5812                                 controls[ controlIndex - 1 ].contentContainer.find( ':focusable:first' ).focus();
    5813                             }
    5814                         },
    5815 
    5816                         /**
    5817                          * Update error notice.
    5818                          *
    5819                          * @param {Array} errorAnnotations - Error annotations.
    5820                          * @returns {void}
    5821                          */
    5822                         onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
    5823                             var message;
    5824                             control.setting.notifications.remove( 'csslint_error' );
    5825 
    5826                             if ( 0 !== errorAnnotations.length ) {
    5827                                 if ( 1 === errorAnnotations.length ) {
    5828                                     message = api.l10n.customCssError.singular.replace( '%d', '1' );
    5829                                 } else {
    5830                                     message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) );
    5831                                 }
    5832                                 control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', {
    5833                                     message: message,
    5834                                     type: 'error'
    5835                                 } ) );
    5836                             }
    5837                         }
    5838                     });
    5839 
    5840                     control.editor = wp.codeEditor.initialize( $textarea, settings );
    5841 
    5842                     // Refresh when receiving focus.
    5843                     control.editor.codemirror.on( 'focus', function( codemirror ) {
    5844                         codemirror.refresh();
    5845                     });
    5846 
    5847                     /*
    5848                      * When the CodeMirror instance changes, mirror to the textarea,
    5849                      * where we have our "true" change event handler bound.
    5850                      */
    5851                     control.editor.codemirror.on( 'change', function( codemirror ) {
    5852                         suspendEditorUpdate = true;
    5853                         $textarea.val( codemirror.getValue() ).trigger( 'change' );
    5854                         suspendEditorUpdate = false;
    5855                     });
    5856 
    5857                     // Update CodeMirror when the setting is changed by another plugin.
    5858                     control.setting.bind( function( value ) {
    5859                         if ( ! suspendEditorUpdate ) {
    5860                             control.editor.codemirror.setValue( value );
    5861                         }
    5862                     });
    5863 
    5864                     // Prevent collapsing section when hitting Esc to tab out of editor.
    5865                     control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
    5866                         var escKeyCode = 27;
    5867                         if ( escKeyCode === event.keyCode ) {
    5868                             event.stopPropagation();
    5869                         }
    5870                     });
    5871                 });
    5872             } else {
    5873 
    5874                 // Allow tabs to be entered in Custom CSS textarea.
    5875                 ready.done( function allowTabs( section, control ) {
    5876 
    5877                     var $textarea = control.container.find( 'textarea' ), textarea = $textarea[0];
    5878 
    5879                     $textarea.on( 'blur', function onBlur() {
    5880                         $textarea.data( 'next-tab-blurs', false );
    5881                     } );
    5882 
    5883                     $textarea.on( 'keydown', function onKeydown( event ) {
    5884                         var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27;
    5885 
    5886                         if ( escKeyCode === event.keyCode ) {
    5887                             if ( ! $textarea.data( 'next-tab-blurs' ) ) {
    5888                                 $textarea.data( 'next-tab-blurs', true );
    5889                                 event.stopPropagation(); // Prevent collapsing the section.
    5890                             }
    5891                             return;
    5892                         }
    5893 
    5894                         // Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed.
    5895                         if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) {
    5896                             return;
    5897                         }
    5898 
    5899                         // Prevent capturing Tab characters if Esc was pressed.
    5900                         if ( $textarea.data( 'next-tab-blurs' ) ) {
    5901                             return;
    5902                         }
    5903 
    5904                         selectionStart = textarea.selectionStart;
    5905                         selectionEnd = textarea.selectionEnd;
    5906                         value = textarea.value;
    5907 
    5908                         if ( selectionStart >= 0 ) {
    5909                             textarea.value = value.substring( 0, selectionStart ).concat( '\t', value.substring( selectionEnd ) );
    5910                             $textarea.selectionStart = textarea.selectionEnd = selectionStart + 1;
    5911                         }
    5912 
    5913                         event.stopPropagation();
    5914                         event.preventDefault();
    5915                     });
    5916                 });
    5917             }
    59185996        })();
    59195997
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r41550 r41558  
    214214
    215215    /**
    216      * Code Editor Settings for Custom CSS.
    217      *
    218      * This variable contains the settings returned by `wp_enqueue_code_editor()` which are then later output
    219      * to the client in `WP_Customize_Manager::customize_pane_settings()`. A value of false means that the
    220      * Custom CSS section or control was removed, or that the Syntax Highlighting user pref was turned off.
    221      *
    222      * @see wp_enqueue_code_editor()
    223      * @see WP_Customize_Manager::enqueue_control_scripts()
    224      * @see WP_Customize_Manager::customize_pane_settings()
    225      * @since 4.9.0
    226      * @var array|false
    227      */
    228     private $_custom_css_code_editor_settings = false;
    229 
    230     /**
    231216     * Constructor.
    232217     *
     
    292277        require_once( ABSPATH . WPINC . '/customize/class-wp-customize-header-image-control.php' );
    293278        require_once( ABSPATH . WPINC . '/customize/class-wp-customize-theme-control.php' );
     279        require_once( ABSPATH . WPINC . '/customize/class-wp-customize-code-editor-control.php' );
    294280        require_once( ABSPATH . WPINC . '/customize/class-wp-widget-area-customize-control.php' );
    295281        require_once( ABSPATH . WPINC . '/customize/class-wp-widget-form-customize-control.php' );
     
    33383324            $control->enqueue();
    33393325        }
    3340 
    3341         if ( $this->get_section( 'custom_css' ) && $this->get_control( 'custom_css' ) ) {
    3342             $this->_custom_css_code_editor_settings = wp_enqueue_code_editor( array(
    3343                 'type' => 'text/css',
    3344             ) );
    3345         }
    33463326    }
    33473327
     
    36003580                'stylesheet' => $this->get_stylesheet(),
    36013581                'active'     => $this->is_theme_active(),
    3602             ),
    3603             'customCss' => array(
    3604                 'codeEditor' => $this->_custom_css_code_editor_settings,
    36053582            ),
    36063583            'url'      => array(
     
    37373714        $this->register_control_type( 'WP_Customize_Site_Icon_Control' );
    37383715        $this->register_control_type( 'WP_Customize_Theme_Control' );
     3716        $this->register_control_type( 'WP_Customize_Code_Editor_Control' );
    37393717
    37403718        /* Themes */
     
    42404218        $this->add_setting( $custom_css_setting );
    42414219
    4242         $this->add_control( 'custom_css', array(
    4243             'type'     => 'textarea',
     4220        $this->add_control( new WP_Customize_Code_Editor_Control( $this, 'custom_css', array(
    42444221            'section'  => 'custom_css',
    42454222            'settings' => array( 'default' => $custom_css_setting->id ),
    4246             'input_attrs' => array(
    4247                 'class' => 'code', // Ensures contents displayed as LTR instead of RTL.
    4248             ),
    4249         ) );
     4223            'code_type' => 'text/css',
     4224        ) ) );
    42504225    }
    42514226
  • trunk/src/wp-includes/general-template.php

    r41376 r41558  
    31263126 *     Args.
    31273127 *
    3128  *     @type string   $type     The MIME type of the file to be edited.
    3129  *     @type string   $file     Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param.
    3130  *     @type array    $settings Settings to merge on top of defaults which derive from `$type` or `$file` args.
    3131  *     @type WP_Theme $theme    Theme being edited when on theme editor.
    3132  *     @type string   $plugin   Plugin being edited when on plugin editor.
     3128 *     @type string   $type       The MIME type of the file to be edited.
     3129 *     @type string   $file       Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param.
     3130 *     @type WP_Theme $theme      Theme being edited when on theme editor.
     3131 *     @type string   $plugin     Plugin being edited when on plugin editor.
     3132 *     @type array    $codemirror Additional CodeMirror setting overrides.
     3133 *     @type array    $csslint    CSSLint rule overrides.
     3134 *     @type array    $jshint     JSHint rule overrides.
     3135 *     @type array    $htmlhint   JSHint rule overrides.
    31333136 * }
    31343137 * @returns array|false Settings for the enqueued code editor, or false if the editor was not enqueued .
     
    34093412
    34103413    // Let settings supplied via args override any defaults.
    3411     if ( isset( $args['settings'] ) ) {
    3412         foreach ( $args['settings'] as $key => $value ) {
    3413             $settings[ $key ] = array_merge(
    3414                 $settings[ $key ],
    3415                 $value
    3416             );
    3417         }
     3414    foreach ( wp_array_slice_assoc( $args, array( 'codemirror', 'csslint', 'jshint', 'htmlhint' ) ) as $key => $value ) {
     3415        $settings[ $key ] = array_merge(
     3416            $settings[ $key ],
     3417            $value
     3418        );
    34183419    }
    34193420
     
    34293430     *     Args passed when calling `wp_enqueue_code_editor()`.
    34303431     *
    3431      *     @type string   $type     The MIME type of the file to be edited.
    3432      *     @type string   $file     Filename being edited.
    3433      *     @type array    $settings Settings to merge on top of defaults which derive from `$type` or `$file` args.
    3434      *     @type WP_Theme $theme    Theme being edited when on theme editor.
    3435      *     @type string   $plugin   Plugin being edited when on plugin editor.
     3432     *     @type string   $type       The MIME type of the file to be edited.
     3433     *     @type string   $file       Filename being edited.
     3434     *     @type WP_Theme $theme      Theme being edited when on theme editor.
     3435     *     @type string   $plugin     Plugin being edited when on plugin editor.
     3436     *     @type array    $codemirror Additional CodeMirror setting overrides.
     3437     *     @type array    $csslint    CSSLint rule overrides.
     3438     *     @type array    $jshint     JSHint rule overrides.
     3439     *     @type array    $htmlhint   JSHint rule overrides.
    34363440     * }
    34373441     */
     
    34443448    wp_enqueue_script( 'code-editor' );
    34453449    wp_enqueue_style( 'code-editor' );
    3446 
    3447     wp_enqueue_script( 'codemirror' );
    3448     wp_enqueue_style( 'codemirror' );
    34493450
    34503451    if ( isset( $settings['codemirror']['mode'] ) ) {
  • trunk/src/wp-includes/script-loader.php

    r41554 r41558  
    464464    );
    465465
    466     $scripts->add( 'codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.29.1-alpha-ee20357' );
     466    $scripts->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.29.1-alpha-ee20357' );
    467467    $scripts->add( 'csslint', '/wp-includes/js/codemirror/csslint.js', array(), '1.0.5' );
    468468    $scripts->add( 'jshint', '/wp-includes/js/codemirror/jshint.js', array(), '2.9.5' );
     
    470470    $scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' );
    471471    $scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) );
    472     $scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'codemirror' ) );
     472    $scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'wp-codemirror' ) );
    473473    $scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'code-editor', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ) );
    474474    did_action( 'init' ) && $scripts->add_inline_script( 'wp-theme-plugin-editor', sprintf( 'wp.themePluginEditor.l10n = %s;', wp_json_encode( wp_array_slice_assoc(
     
    953953    $styles->add( 'site-icon',           "/wp-admin/css/site-icon$suffix.css" );
    954954    $styles->add( 'l10n',                "/wp-admin/css/l10n$suffix.css" );
    955     $styles->add( 'code-editor',         "/wp-admin/css/code-editor$suffix.css", array( 'codemirror' ) );
     955    $styles->add( 'code-editor',         "/wp-admin/css/code-editor$suffix.css", array( 'wp-codemirror' ) );
    956956
    957957    $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' ) );
     
    988988    $styles->add( 'wp-mediaelement',     "/wp-includes/js/mediaelement/wp-mediaelement$suffix.css", array( 'mediaelement' ) );
    989989    $styles->add( 'thickbox',            '/wp-includes/js/thickbox/thickbox.css', array( 'dashicons' ) );
    990     $styles->add( 'codemirror',          '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' );
     990    $styles->add( 'wp-codemirror',       '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' );
    991991
    992992    // Deprecated CSS
  • trunk/src/wp-includes/widgets/class-wp-widget-custom-html.php

    r41376 r41558  
    161161        $settings = wp_enqueue_code_editor( array(
    162162            'type' => 'text/html',
     163            'codemirror' => array(
     164                'indentUnit' => 2,
     165                'tabSize' => 2,
     166            ),
    163167        ) );
    164168
  • trunk/tests/phpunit/tests/customize/manager.php

    r41376 r41558  
    23522352        $this->assertNotEmpty( $data );
    23532353
    2354         $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'customCss', 'changeset', 'timeouts' ), array_keys( $data ) );
     2354        $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'changeset', 'timeouts' ), array_keys( $data ) );
    23552355        $this->assertEquals( $autofocus, $data['autofocus'] );
    23562356        $this->assertArrayHasKey( 'save', $data['nonce'] );
Note: See TracChangeset for help on using the changeset viewer.