WordPress.org

Plugin Directory

Changeset 1727131


Ignore:
Timestamp:
09/08/17 23:11:37 (6 weeks ago)
Author:
westonruter
Message:

Committing 0.6.0 to trunk

Location:
better-code-editing/trunk
Files:
4 added
19 edited

Legend:

Unmodified
Added
Removed
  • better-code-editing/trunk/better-code-editing.php

    r1722335 r1727131  
    44 * Plugin URI: https://wordpress.org/plugins/better-code-editing/ 
    55 * Description: Code highlighting and linting, powered by CodeMirror. 
    6  * Version: 0.5.0 
     6 * Version: 0.6.0 
    77 * Author: The WordPress Team 
    88 * Text Domain: better-code-editing 
     
    1111 */ 
    1212 
    13 define( 'BETTER_CODE_EDITING_PLUGIN_VERSION', '0.5.0' ); 
     13define( 'BETTER_CODE_EDITING_PLUGIN_VERSION', '0.6.0' ); 
    1414define( 'BETTER_CODE_EDITING_PLUGIN_FILE', __FILE__ ); 
    1515 
     
    2828} 
    2929 
     30/** 
     31 * Show admin notice when npm install has not been run. 
     32 */ 
     33function _better_code_editing_plugin_npm_install_required() { 
     34    ?> 
     35    <div class="notice notice-error"> 
     36        <p><?php _e( 'The Better Code Editing plugin\'s has been installed from source. In order complete installation, you must run <code>npm install</code> from the command line. Otherwise, please install the plugin from WordPress.org or via a ZIP from the GitHub releases page..', 'better-code-editing' ); ?></p> 
     37    </div> 
     38    <?php 
     39} 
     40 
    3041// Short-circuit when the functionality is already merged into core. 
    31 if ( function_exists( 'wp_code_editor_settings' ) ) { 
     42if ( function_exists( 'wp_enqueue_code_editor' ) ) { 
    3243    add_action( 'admin_notices', '_better_code_editing_plugin_obsolete_admin_notice' ); 
     44    return; 
     45} 
     46 
     47// Show notice if repo was cloned from source without running npm install. 
     48if ( ! file_exists( dirname( __FILE__ ) . '/wp-includes/js/codemirror/lib/codemirror.js' ) ) { 
     49    add_action( 'admin_notices', '_better_code_editing_plugin_npm_install_required' ); 
    3350    return; 
    3451} 
  • better-code-editing/trunk/readme.txt

    r1722335 r1727131  
    22Contributors: georgestephanis, westonruter, obenland, melchoyce, wordpressdotorg 
    33Tags: codemirror, syntax-highlighter, linting 
    4 Stable tag: trunk 
     4Stable tag: 0.6.0 
    55Requires at least: 4.7 
    66Tested up to: 4.9-alpha 
     
    2222== Changelog == 
    2323 
     24= 0.6.0 - 2017-09-08 = 
     25 
     26* Improve frequency for when linting error notifications are shown and remove some overly-strict rules. See [#86](https://github.com/WordPress/better-code-editing/pull/86). Fixes [#13](https://github.com/WordPress/better-code-editing/pull/13). 
     27* Improve disabling of save button for Custom HTML widget. See [#87](https://github.com/WordPress/better-code-editing/pull/87). 
     28* Enable search addon so that attempting to do a find inside the editor will search contents of file and not use browser find dialog. See [#76](https://github.com/WordPress/better-code-editing/pull/76). Fixes [#75](https://github.com/WordPress/better-code-editing/pull/75). 
     29* Auto-show Custom CSS section description when value is empty, add close link to bottom of description, and remove default placeholder value for Custom CSS field. See [#84](https://github.com/WordPress/better-code-editing/pull/84). Fixes [#79](https://github.com/WordPress/better-code-editing/pull/79) and [core#39892](https://core.trac.wordpress.org/ticket/39892). 
     30* Improve passing of linting rulesets to CodeMirror and update CodeMirror to 5.29.1-alpha. See [#59](https://github.com/WordPress/better-code-editing/pull/59). 
     31* Merge `wp_code_editor_settings()` into `wp_enqueue_code_editor()`. See [#81](https://github.com/WordPress/better-code-editing/pull/81). Fixes [#55](https://github.com/WordPress/better-code-editing/pull/55). 
     32* Add support for RTL languages. See [#80](https://github.com/WordPress/better-code-editing/pull/80). Fixes [#72](https://github.com/WordPress/better-code-editing/pull/72). 
     33* Add admin notice to instruct `npm install` when plugin installed from source. See [#74](https://github.com/WordPress/better-code-editing/pull/74). Fixes [#73](https://github.com/WordPress/better-code-editing/pull/73). 
     34* Update dev-lib to use local tools and add PHPCompatibility sniffs. See [#82](https://github.com/WordPress/better-code-editing/pull/82). 
     35* See full commit log and diff: [0.5.0...0.6.0](https://github.com/WordPress/better-code-editing/compare/0.5.0...0.6.0). 
     36 
    2437= 0.5.0 - 2017-08-30 = 
    2538 
     
    3144* Improve help text in widgets admin screen and Additional CSS in Customizer. See [#65](https://github.com/WordPress/better-code-editing/pull/65). Fixes [#36](https://github.com/WordPress/better-code-editing/issues/36). 
    3245* Add `wp_enqueue_code_editor` action. See [#68](https://github.com/WordPress/better-code-editing/pull/68). 
     46* See full commit log and diff: [0.4.0...0.5.0](https://github.com/WordPress/better-code-editing/compare/0.4.0...0.5.0) 
    3347 
    3448= 0.4.0 - 2017-08-28 = 
  • better-code-editing/trunk/wp-admin/css/code-editor.css

    r1722335 r1727131  
    1515} 
    1616 
     17/*rtl:ignore*/ 
    1718.wp-core-ui [class*="CodeMirror-lint-message"]:before { 
    1819    font: normal 16px/1 dashicons; 
     
    2122} 
    2223 
     24/*rtl:ignore*/ 
    2325.wp-core-ui .CodeMirror-lint-message-error, 
    2426.wp-core-ui .CodeMirror-lint-message-warning { 
     
    2830} 
    2931 
     32/*rtl:ignore*/ 
    3033.wp-core-ui .CodeMirror-lint-message-warning { 
    3134    background-color: #fff8e5; 
     
    3336} 
    3437 
     38/* rtl:ignore */ 
    3539.wrap .CodeMirror-lint-marker-warning:before, 
    3640.wp-core-ui .CodeMirror-lint-message-warning:before { 
     
    3943} 
    4044 
     45/*rtl:ignore*/ 
    4146.wp-core-ui .CodeMirror-lint-message-error { 
    4247    background-color: #fbeaea; 
     
    4449} 
    4550 
     51/* rtl:ignore */ 
    4652.wrap .CodeMirror-lint-marker-error:before, 
    4753.wp-core-ui .CodeMirror-lint-message-error:before { 
     
    5056} 
    5157 
     58/* rtl:ignore */ 
    5259.wp-core-ui .CodeMirror-lint-tooltip { 
    5360    background: none; 
    5461    border: none; 
    5562    border-radius: 0; 
     63    direction: ltr; 
    5664} 
    5765 
     
    6068    color: inherit; 
    6169} 
     70/* rtl:ignore */ 
     71.CodeMirror { 
     72    text-align: left; 
     73} 
  • better-code-editing/trunk/wp-admin/css/customize-controls-addendum.css

    r1722335 r1727131  
    1818    margin-right: 12px; 
    1919} 
     20 
     21.section-description-buttons { 
     22    text-align: right; 
     23} 
     24 
     25.section-description-buttons button.button-link { 
     26    color: #0073aa; /* @todo Color scheme? */ 
     27    text-decoration: underline; 
     28} 
  • better-code-editing/trunk/wp-admin/css/widgets-addendum.css

    r1722335 r1727131  
    1111    z-index: 101; /* Due to z-index 100 set on .widget.open */ 
    1212} 
    13 .widget-control-actions .custom-html-widget-save-button.button[disabled] { 
     13.widget-control-actions .custom-html-widget-save-button.button.validation-blocked { 
    1414    cursor: not-allowed; 
    1515} 
  • better-code-editing/trunk/wp-admin/file-editor-addendum.php

    r1722335 r1727131  
    6262    } 
    6363 
    64     $context = array(); 
     64    $args = array(); 
    6565 
    6666    if ( 'theme-editor.php' === $hook ) { 
     
    7171 
    7272        if ( isset( $_REQUEST['file'] ) ) { 
    73             $context['file'] = sanitize_text_field( wp_unslash( $_REQUEST['file'] ) ); 
     73            $args['file'] = sanitize_text_field( wp_unslash( $_REQUEST['file'] ) ); 
    7474        } else { 
    75             $context['file'] = 'style.css'; 
     75            $args['file'] = 'style.css'; 
    7676        } 
    7777    } elseif ( 'plugin-editor.php' === $hook ) { 
    78         $context['plugin'] = isset( $_REQUEST['plugin'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['plugin'] ) ) : ''; 
    79         $context['file'] = isset( $_REQUEST['file'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['file'] ) ) : ''; 
     78        $args['plugin'] = isset( $_REQUEST['plugin'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['plugin'] ) ) : ''; 
     79        $args['file'] = isset( $_REQUEST['file'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['file'] ) ) : ''; 
    8080 
    81         if ( empty( $context['plugin'] ) ) { 
     81        if ( empty( $args['plugin'] ) ) { 
    8282            $file_paths = array_keys( get_plugins() ); 
    83             $context['plugin'] = $context['file'] ? $context['file'] : array_shift( $file_paths ); 
    84         } elseif ( 0 !== validate_file( $context['plugin'] ) ) { 
     83            $args['plugin'] = $args['file'] ? $args['file'] : array_shift( $file_paths ); 
     84        } elseif ( 0 !== validate_file( $args['plugin'] ) ) { 
    8585            wp_die( __( 'Sorry, that file cannot be edited.', 'better-code-editing' ) ); 
    8686        } 
    8787 
    88         $plugin_files = get_plugin_files( $context['plugin'] ); 
    89         if ( empty( $context['file'] ) ) { 
    90             $context['file'] = $plugin_files[0]; 
     88        $plugin_files = get_plugin_files( $args['plugin'] ); 
     89        if ( empty( $args['file'] ) ) { 
     90            $args['file'] = $plugin_files[0]; 
    9191        } 
    9292 
    93         $context['file'] = validate_file_to_edit( $context['file'], $plugin_files ); 
     93        $args['file'] = validate_file_to_edit( $args['file'], $plugin_files ); 
    9494    } 
    9595 
    96     $settings = wp_code_editor_settings( $context ); 
     96    $settings = wp_enqueue_code_editor( $args ); 
    9797    if ( empty( $settings ) ) { 
    9898        return; 
    9999    } 
    100100 
    101     wp_enqueue_code_editor( $settings ); 
    102101    wp_enqueue_script( 'wp-theme-plugin-editor' ); 
    103102 
  • better-code-editing/trunk/wp-admin/js/code-editor.js

    r1722335 r1727131  
    1 /* global CodeMirror, CSSLint */ 
     1/* global CodeMirror */ 
    22if ( 'undefined' === typeof window.wp ) { 
    33    window.wp = {}; 
     
    2121        htmlhint: {}, 
    2222        jshint: {}, 
    23         handleTabNext: function() {}, 
    24         handleTabPrev: function() {} 
     23        onTabNext: function() {}, 
     24        onTabPrevious: function() {}, 
     25        onChangeLintingErrors: function() {}, 
     26        onUpdateErrorNotice: function() {} 
    2527    }; 
    2628 
     
    3436 
    3537    /** 
    36      * Override which CSSLint rules are added. 
    37      * 
    38      * @param {Array} rules - Subset or rules. 
     38     * Configure linting. 
     39     * 
     40     * @param {CodeMirror} editor - Editor. 
     41     * @param {object}     settings - Code editor settings. 
     42     * @param {object}     settings.codeMirror - Settings for CodeMirror. 
     43     * @param {Function}   settings.onChangeLintingErrors - Callback for when there are changes to linting errors. 
     44     * @param {Function}   settings.onUpdateErrorNotice - Callback to update error notice. 
    3945     * @returns {void} 
    4046     */ 
    41     function updateCSSLintRules( rules ) { 
    42         var allRules = CSSLint.getRules(), i; 
    43         CSSLint.clearRules(); 
    44         for ( i = 0; i < allRules.length; i++ ) { 
    45             if ( rules[ allRules[ i ].id ] ) { 
    46                 CSSLint.addRule( allRules[ i ] ); 
    47             } 
    48         } 
     47    function configureLinting( editor, settings ) { // eslint-disable-line complexity 
     48        var lintOptions = editor.getOption( 'lint' ), currentErrorAnnotations = [], updateErrorNotice, previouslyShownErrorAnnotations = []; 
     49        if ( ! lintOptions ) { 
     50            return; 
     51        } 
     52 
     53        if ( true === lintOptions ) { 
     54            lintOptions = {}; 
     55        } else { 
     56            lintOptions = $.extend( {}, lintOptions ); 
     57        } 
     58 
     59        // 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>. 
     60        if ( ! lintOptions.options ) { 
     61            lintOptions.options = {}; 
     62        } 
     63 
     64        // Configure JSHint. 
     65        if ( 'javascript' === lintOptions.mode && settings.jshint ) { 
     66            $.extend( lintOptions.options, settings.jshint ); 
     67        } 
     68 
     69        // Configure CSSLint. 
     70        if ( 'css' === lintOptions.mode && settings.csslint ) { 
     71            $.extend( lintOptions.options, settings.csslint ); 
     72        } 
     73 
     74        // Configure HTMLHint. 
     75        if ( 'htmlmixed' === lintOptions.mode && settings.htmlhint ) { 
     76            lintOptions.options.rules = $.extend( {}, settings.htmlhint ); 
     77 
     78            if ( settings.jshint ) { 
     79                lintOptions.options.rules.jshint = settings.jshint; 
     80            } 
     81            if ( settings.csslint ) { 
     82                lintOptions.options.rules.csslint = settings.csslint; 
     83            } 
     84        } 
     85 
     86        /** 
     87         * Call the onUpdateErrorNotice if there are new errors to show. 
     88         * 
     89         * @returns {void} 
     90         */ 
     91        updateErrorNotice = function() { 
     92            if ( settings.onUpdateErrorNotice && ! _.isEqual( currentErrorAnnotations, previouslyShownErrorAnnotations ) ) { 
     93                settings.onUpdateErrorNotice( currentErrorAnnotations, editor ); 
     94                previouslyShownErrorAnnotations = currentErrorAnnotations; 
     95            } 
     96        }; 
     97 
     98        // Wrap the onUpdateLinting CodeMirror event to route to onChangeLintingErrors and onUpdateErrorNotice. 
     99        lintOptions.onUpdateLinting = (function( onUpdateLintingOverridden ) { 
     100            return function( annotations, annotationsSorted, cm ) { 
     101                var errorAnnotations = _.filter( annotations, function( annotation ) { 
     102                    return 'error' === annotation.severity; 
     103                } ); 
     104 
     105                if ( onUpdateLintingOverridden ) { 
     106                    onUpdateLintingOverridden.apply( annotations, annotationsSorted, cm ); 
     107                } 
     108 
     109                // Skip if there are no changes to the errors. 
     110                if ( _.isEqual( errorAnnotations, currentErrorAnnotations ) ) { 
     111                    return; 
     112                } 
     113 
     114                currentErrorAnnotations = errorAnnotations; 
     115 
     116                if ( settings.onChangeLintingErrors ) { 
     117                    settings.onChangeLintingErrors( errorAnnotations, annotations, annotationsSorted, cm ); 
     118                } 
     119 
     120                /* 
     121                 * Update notifications when the editor is not focused to prevent error message 
     122                 * from overwhelming the user during input, unless there are now no errors or there 
     123                 * were previously errors shown. In these cases, update immediately so they can know 
     124                 * that they fixed the errors. 
     125                 */ 
     126                if ( ! cm.state.focused || 0 === currentErrorAnnotations.length || previouslyShownErrorAnnotations.length > 0 ) { 
     127                    updateErrorNotice(); 
     128                } 
     129            }; 
     130        })( lintOptions.onUpdateLinting ); 
     131 
     132        editor.setOption( 'lint', lintOptions ); 
     133 
     134        // Update error notice when leaving the editor. 
     135        editor.on( 'blur', updateErrorNotice ); 
     136 
     137        // Work around hint selection with mouse causing focus to leave editor. 
     138        editor.on( 'startCompletion', function() { 
     139            editor.off( 'blur', updateErrorNotice ); 
     140        } ); 
     141        editor.on( 'endCompletion', function() { 
     142            var editorRefocusWait = 500; 
     143            editor.on( 'blur', updateErrorNotice ); 
     144 
     145            // Wait for editor to possibly get re-focused after selection. 
     146            _.delay( function() { 
     147                if ( ! editor.state.focused ) { 
     148                    updateErrorNotice(); 
     149                } 
     150            }, editorRefocusWait ); 
     151        }); 
     152 
     153        /* 
     154         * Make sure setting validities are set if the user tries to click Publish 
     155         * while an autocomplete dropdown is still open. The Customizer will block 
     156         * saving when a setting has an error notifications on it. This is only 
     157         * necessary for mouse interactions because keyboards will have already 
     158         * blurred the field and cause onUpdateErrorNotice to have already been 
     159         * called. 
     160         */ 
     161        $( document.body ).on( 'mousedown', function( event ) { 
     162            if ( editor.state.focused && ! $.contains( editor.display.wrapper, event.target ) && ! $( event.target ).hasClass( 'CodeMirror-hint' ) ) { 
     163                updateErrorNotice(); 
     164            } 
     165        }); 
    49166    } 
    50167 
    51168    /** 
     169     * Configure tabbing. 
     170     * 
     171     * @param {CodeMirror} codemirror - Editor. 
     172     * @param {object}     settings - Code editor settings. 
     173     * @param {object}     settings.codeMirror - Settings for CodeMirror. 
     174     * @param {Function}   settings.onTabNext - Callback to handle tabbing to the next tabbable element. 
     175     * @param {Function}   settings.onTabPrevious - Callback to handle tabbing to the previous tabbable element. 
     176     * @returns {void} 
     177     */ 
     178    function configureTabbing( codemirror, settings ) { 
     179        var $textarea = $( codemirror.getTextArea() ); 
     180 
     181        codemirror.on( 'blur', function() { 
     182            $textarea.data( 'next-tab-blurs', false ); 
     183        }); 
     184        codemirror.on( 'focus', function() { 
     185            if ( codemirror.display.wrapper.scrollIntoViewIfNeeded ) { 
     186                codemirror.display.wrapper.scrollIntoViewIfNeeded(); 
     187            } else { 
     188                codemirror.display.wrapper.scrollIntoView(); 
     189            } 
     190        }); 
     191        codemirror.on( 'keydown', function onKeydown( editor, event ) { 
     192            var tabKeyCode = 9, escKeyCode = 27; 
     193 
     194            // Take note of the ESC keypress so that the next TAB can focus outside the editor. 
     195            if ( escKeyCode === event.keyCode ) { 
     196                $textarea.data( 'next-tab-blurs', true ); 
     197                return; 
     198            } 
     199 
     200            // Short-circuit if tab key is not being pressed or the tab key press should move focus. 
     201            if ( tabKeyCode !== event.keyCode || ! $textarea.data( 'next-tab-blurs' ) ) { 
     202                return; 
     203            } 
     204 
     205            // Focus on previous or next focusable item. 
     206            if ( event.shiftKey ) { 
     207                settings.onTabPrevious( codemirror, event ); 
     208            } else { 
     209                settings.onTabNext( codemirror, event ); 
     210            } 
     211 
     212            // Reset tab state. 
     213            $textarea.data( 'next-tab-blurs', false ); 
     214 
     215            // Prevent tab character from being added. 
     216            event.preventDefault(); 
     217        }); 
     218    } 
     219 
     220    /** 
    52221     * Initialize Code Editor (CodeMirror) for an existing textarea. 
    53222     * 
    54223     * @since 4.9.0 
    55224     * 
    56      * @param {string|jQuery|Element} textarea The HTML id, jQuery object, or DOM Element for the textarea that is used for the editor. 
    57      * @param {object} [settings] Settings to override defaults. 
     225     * @param {string|jQuery|Element} textarea - The HTML id, jQuery object, or DOM Element for the textarea that is used for the editor. 
     226     * @param {object}                [settings] - Settings to override defaults. 
     227     * @param {Function}              [settings.onChangeLintingErrors] - Callback for when the linting errors have changed. 
     228     * @param {Function}              [settings.onUpdateErrorNotice] - Callback for when error notice should be displayed. 
     229     * @param {Function}              [settings.onTabPrevious] - Callback to handle tabbing to the previous tabbable element. 
     230     * @param {Function}              [settings.onTabNext] - Callback to handle tabbing to the next tabbable element. 
     231     * @param {object}                [settings.codemirror] - Options for CodeMirror. 
     232     * @param {object}                [settings.csslint] - Rules for CSSLint. 
     233     * @param {object}                [settings.htmlhint] - Rules for HTMLHint. 
     234     * @param {object}                [settings.jshint] - Rules for JSHint. 
    58235     * @returns {CodeMirror} CodeMirror instance. 
    59236     */ 
    60     wp.codeEditor.initialize = function initialize( textarea, settings ) { // eslint-disable-line complexity 
    61         var $textarea, editor, instanceSettings; 
     237    wp.codeEditor.initialize = function initialize( textarea, settings ) { 
     238        var $textarea, codemirror, instanceSettings, instance; 
    62239        if ( 'string' === typeof textarea ) { 
    63240            $textarea = $( '#' + textarea ); 
     
    69246        instanceSettings.codemirror = $.extend( {}, instanceSettings.codemirror ); 
    70247 
    71         // @todo This can be moved to PHP. 
    72         if ( instanceSettings.codemirror.lint ) { 
    73             if ( true === instanceSettings.codemirror.lint ) { 
    74                 instanceSettings.codemirror.lint = {}; 
    75             } 
    76  
    77             // Note that rules must be sent in the "deprecated" lint.options property to prevent linter from complaining about unrecognized options. 
    78             if ( ! instanceSettings.codemirror.lint.options ) { 
    79                 instanceSettings.codemirror.lint.options = {}; 
    80             } 
    81  
    82             // Configure JSHint. 
    83             if ( 'javascript' === instanceSettings.codemirror.mode && instanceSettings.jshint && instanceSettings.jshint.rules ) { 
    84                 instanceSettings.codemirror.lint.options = $.extend( {}, instanceSettings.jshint.rules, instanceSettings.codemirror.lint.options ); 
    85             } 
    86  
    87             // Configure HTMLHint. 
    88             if ( 'htmlmixed' === instanceSettings.codemirror.mode && instanceSettings.htmlhint && instanceSettings.htmlhint.rules ) { 
    89                 instanceSettings.codemirror.lint.options = $.extend( {}, instanceSettings.htmlhint, instanceSettings.codemirror.lint.options ); 
    90  
    91                 if ( instanceSettings.jshint && instanceSettings.jshint.rules ) { 
    92                     instanceSettings.codemirror.lint.options.rules.jshint = $.extend( {}, instanceSettings.jshint.rules, instanceSettings.codemirror.lint.options.rules.jshint ); 
    93                 } 
    94                 if ( instanceSettings.csslint && instanceSettings.csslint.rules ) { 
    95                     instanceSettings.codemirror.lint.options.rules.csslint = $.extend( {}, instanceSettings.csslint.rules, instanceSettings.codemirror.lint.options.rules.csslint ); 
    96                 } 
    97             } 
    98  
    99             // Configure CSSLint. 
    100             if ( 'undefined' !== typeof CSSLint && instanceSettings.csslint && instanceSettings.csslint.rules ) { 
    101                 updateCSSLintRules( instanceSettings.csslint.rules ); 
    102             } 
    103         } 
    104  
    105         editor = CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror ); 
     248        codemirror = CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror ); 
     249 
     250        configureLinting( codemirror, instanceSettings ); 
     251 
     252        instance = { 
     253            settings: instanceSettings, 
     254            codemirror: codemirror 
     255        }; 
    106256 
    107257        // Keep track of the instances that have been created. 
    108         wp.codeEditor.instances.push( editor ); 
    109  
    110         if ( editor.showHint ) { 
    111             editor.on( 'keyup', function( _editor, event ) { // eslint-disable-line complexity 
     258        wp.codeEditor.instances.push( instance ); 
     259 
     260        if ( codemirror.showHint ) { 
     261            codemirror.on( 'keyup', function( editor, event ) { // eslint-disable-line complexity 
    112262                var shouldAutocomplete, isAlphaKey = /^[a-zA-Z]$/.test( event.key ), lineBeforeCursor, innerMode, token; 
    113                 if ( editor.state.completionActive && isAlphaKey ) { 
     263                if ( codemirror.state.completionActive && isAlphaKey ) { 
    114264                    return; 
    115265                } 
    116266 
    117267                // Prevent autocompletion in string literals or comments. 
    118                 token = editor.getTokenAt( editor.getCursor() ); 
     268                token = codemirror.getTokenAt( codemirror.getCursor() ); 
    119269                if ( 'string' === token.type || 'comment' === token.type ) { 
    120270                    return; 
    121271                } 
    122272 
    123                 innerMode = CodeMirror.innerMode( editor.getMode(), token.state ).mode.name; 
    124                 lineBeforeCursor = editor.doc.getLine( editor.doc.getCursor().line ).substr( 0, editor.doc.getCursor().ch ); 
     273                innerMode = CodeMirror.innerMode( codemirror.getMode(), token.state ).mode.name; 
     274                lineBeforeCursor = codemirror.doc.getLine( codemirror.doc.getCursor().line ).substr( 0, codemirror.doc.getCursor().ch ); 
    125275                if ( 'html' === innerMode || 'xml' === innerMode ) { 
    126276                    shouldAutocomplete = 
     
    137287                } else if ( 'javascript' === innerMode ) { 
    138288                    shouldAutocomplete = isAlphaKey || '.' === event.key; 
    139                 } else if ( 'clike' === innerMode && 'application/x-httpd-php' === editor.options.mode ) { 
     289                } else if ( 'clike' === innerMode && 'application/x-httpd-php' === codemirror.options.mode ) { 
    140290                    shouldAutocomplete = 'keyword' === token.type || 'variable' === token.type; 
    141291                } 
    142292                if ( shouldAutocomplete ) { 
    143                     CodeMirror.commands.autocomplete( editor, null, { completeSingle: false } ); 
     293                    codemirror.showHint( { completeSingle: false } ); 
    144294                } 
    145295            }); 
    146296        } 
    147297 
    148         // Make sure the editor gets updated if the content was updated on the server (sanitization) but not updated in the editor since it was focused. 
    149         editor.on( 'blur', function() { 
    150             $textarea.data( 'next-tab-blurs', false ); 
    151         }); 
    152  
    153         editor.on( 'focus', function() { 
    154             if ( editor.display.wrapper.scrollIntoViewIfNeeded ) { 
    155                 editor.display.wrapper.scrollIntoViewIfNeeded(); 
    156             } else { 
    157                 editor.display.wrapper.scrollIntoView(); 
    158             } 
    159         }); 
    160  
    161         editor.on( 'keydown', function onKeydown( _editor, event ) { 
    162             var tabKeyCode = 9, escKeyCode = 27; 
    163  
    164             // Take note of the ESC keypress so that the next TAB can focus outside the editor. 
    165             if ( escKeyCode === event.keyCode ) { 
    166                 $textarea.data( 'next-tab-blurs', true ); 
    167                 return; 
    168             } 
    169  
    170             // Short-circuit if tab key is not being pressed or the tab key press should move focus. 
    171             if ( tabKeyCode !== event.keyCode || ! $textarea.data( 'next-tab-blurs' ) ) { 
    172                 return; 
    173             } 
    174  
    175             // Focus on previous or next focusable item. 
    176             if ( event.shiftKey ) { 
    177                 settings.handleTabPrev( editor, event ); 
    178             } else { 
    179                 settings.handleTabNext( editor, event ); 
    180             } 
    181  
    182             // Reset tab state. 
    183             $textarea.data( 'next-tab-blurs', false ); 
    184  
    185             // Prevent tab character from being added. 
    186             event.preventDefault(); 
    187         }); 
    188  
    189         return editor; 
     298        // Facilitate tabbing out of the editor. 
     299        configureTabbing( codemirror, settings ); 
     300 
     301        return instance; 
    190302    }; 
    191303 
  • better-code-editing/trunk/wp-admin/js/customize-controls-addendum.js

    r1722335 r1727131  
    44 
    55    api.section( 'custom_css', function( section ) { 
     6        if ( ! api.settings.customCss ) { 
     7            return; 
     8        } 
     9 
     10        // Close the section description when clicking the close button. 
     11        section.container.find( '.section-description-buttons .section-description-close' ).on( 'click', function() { 
     12            section.container.find( '.section-meta .customize-section-description:first' ) 
     13                .removeClass( 'open' ) 
     14                .slideUp() 
     15                .attr( 'aria-expanded', 'false' ); 
     16        }); 
     17 
    618        api.control( 'custom_css', function( control ) { 
    719            var onceExpanded, onExpandedChange; 
    820 
    921            // Abort if CodeMirror disabled via customizer_custom_css_codemirror_opts filter. 
    10             if ( ! api.settings.codeEditor ) { 
     22            if ( ! api.settings.customCss.codeEditor ) { 
    1123                return; 
    1224            } 
     
    3345                        } 
    3446                        if ( control.editor ) { 
    35                             control.editor.focus(); 
     47                            control.editor.codemirror.focus(); 
    3648                        } 
    3749                    }; 
     
    4153 
    4254            onceExpanded = function() { 
    43                 var $textarea = control.container.find( 'textarea' ), settings, previousErrorCount = 0, currentErrorAnnotations = []; 
     55                var $textarea = control.container.find( 'textarea' ), settings, suspendEditorUpdate = false; 
    4456 
    45                 settings = _.extend( {}, api.settings.codeEditor, { 
    46                     handleTabNext: function() { 
     57                if ( ! control.setting.get() ) { 
     58                    section.container.find( '.section-meta .customize-section-description:first' ) 
     59                        .addClass( 'open' ) 
     60                        .show() 
     61                        .attr( 'aria-expanded', 'true' ); 
     62                } 
     63 
     64                settings = _.extend( {}, api.settings.customCss.codeEditor, { 
     65 
     66                    /** 
     67                     * Handle tabbing to the field after the editor. 
     68                     * 
     69                     * @returns {void} 
     70                     */ 
     71                    onTabNext: function onTabNext() { 
    4772                        var controls, controlIndex; 
    4873                        controls = section.controls(); 
     
    5479                        } 
    5580                    }, 
    56                     handleTabPrev: function() { 
     81 
     82                    /** 
     83                     * Handle tabbing to the field before the editor. 
     84                     * 
     85                     * @returns {void} 
     86                     */ 
     87                    onTabPrevious: function onTabPrevious() { 
    5788                        var controls, controlIndex; 
    5889                        controls = section.controls(); 
     
    6394                            controls[ controlIndex - 1 ].container.find( ':focusable:first' ).focus(); 
    6495                        } 
     96                    }, 
     97 
     98                    /** 
     99                     * Update error notice. 
     100                     * 
     101                     * @param {Array} errorAnnotations - Error annotations. 
     102                     * @returns {void} 
     103                     */ 
     104                    onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) { 
     105                        var message; 
     106                        control.setting.notifications.remove( 'csslint_error' ); 
     107 
     108                        if ( 0 !== errorAnnotations.length ) { 
     109                            if ( 1 === errorAnnotations.length ) { 
     110                                message = api.l10n.customCssErrorNotice.singular.replace( '%d', '1' ); 
     111                            } else { 
     112                                message = api.l10n.customCssErrorNotice.plural.replace( '%d', String( errorAnnotations.length ) ); 
     113                            } 
     114                            control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', { 
     115                                message: message, 
     116                                type: 'error' 
     117                            } ) ); 
     118                        } 
    65119                    } 
    66                 } ); 
    67  
    68                 /** 
    69                  * Update notifications on the setting based on the current CSSLint annotations. 
    70                  * 
    71                  * @returns {void} 
    72                  */ 
    73                 function updateNotifications() { 
    74                     var message; 
    75  
    76                     // Short-circuit if there are no changes to the error. 
    77                     if ( previousErrorCount === currentErrorAnnotations.length ) { 
    78                         return; 
    79                     } 
    80                     previousErrorCount = currentErrorAnnotations.length; 
    81  
    82                     control.setting.notifications.remove( 'csslint_error' ); 
    83  
    84                     if ( 0 !== currentErrorAnnotations.length ) { 
    85                         if ( 1 === currentErrorAnnotations.length ) { 
    86                             message = api.l10n.customCssErrorNotice.singular.replace( '%d', '1' ); 
    87                         } else { 
    88                             message = api.l10n.customCssErrorNotice.plural.replace( '%d', String( currentErrorAnnotations.length ) ); 
    89                         } 
    90                         control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', { 
    91                             message: message, 
    92                             type: 'error' 
    93                         } ) ); 
    94                     } 
    95                 } 
    96  
    97                 if ( settings.codemirror.lint ) { 
    98                     if ( true === settings.codemirror.lint ) { 
    99                         settings.codemirror.lint = {}; 
    100                     } 
    101                     settings.codemirror.lint = _.extend( {}, settings.codemirror.lint, { 
    102                         onUpdateLinting: function( annotations, sortedAnnotations, editor ) { 
    103                             currentErrorAnnotations = _.filter( annotations, function( annotation ) { 
    104                                 return 'error' === annotation.severity; 
    105                             } ); 
    106  
    107                             /* 
    108                              * Update notifications when the editor is not focused to prevent error message 
    109                              * from overwhelming the user during input, unless there are no annotations 
    110                              * or there are previous notifications already being displayed, and in that 
    111                              * case update immediately so they can know that they fixed the errors. 
    112                              */ 
    113                             if ( ! editor.state.focused || 0 === currentErrorAnnotations.length || previousErrorCount > 0 ) { 
    114                                 updateNotifications(); 
    115                             } 
    116                         } 
    117                     } ); 
    118                 } 
     120                }); 
    119121 
    120122                control.editor = wp.codeEditor.initialize( $textarea, settings ); 
    121123 
    122124                // Refresh when receiving focus. 
    123                 control.editor.on( 'focus', function( editor ) { 
    124                     editor.refresh(); 
    125                 }); 
    126  
    127                 // Update notifications when blurring the field to prevent user from being inundated with errors during input. 
    128                 control.editor.on( 'blur', function() { 
    129                     updateNotifications(); 
    130                 }); 
    131                 $( control.editor.display.wrapper ).on( 'mouseout', function() { 
    132                     updateNotifications(); 
     125                control.editor.codemirror.on( 'focus', function( codemirror ) { 
     126                    codemirror.refresh(); 
    133127                }); 
    134128 
     
    137131                 * where we have our "true" change event handler bound. 
    138132                 */ 
    139                 control.editor.on( 'change', function( editor ) { 
    140                     $textarea.val( editor.getValue() ).trigger( 'change' ); 
     133                control.editor.codemirror.on( 'change', function( codemirror ) { 
     134                    suspendEditorUpdate = true; 
     135                    $textarea.val( codemirror.getValue() ).trigger( 'change' ); 
     136                    suspendEditorUpdate = false; 
    141137                }); 
    142138 
    143                 control.editor.on( 'keydown', function onKeydown( editor, event ) { 
     139                // Update CodeMirror when the setting is changed by another plugin. 
     140                control.setting.bind( function( value ) { 
     141                    if ( ! suspendEditorUpdate ) { 
     142                        control.editor.codemirror.setValue( value ); 
     143                    } 
     144                }); 
     145 
     146                // Prevent collapsing section when hitting Esc to tab out of editor. 
     147                control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) { 
    144148                    var escKeyCode = 27; 
    145149                    if ( escKeyCode === event.keyCode ) { 
    146                         event.stopPropagation(); // Prevent collapsing the section. 
     150                        event.stopPropagation(); 
    147151                    } 
    148                 } ); 
    149  
    150                 // @todo: bind something to setting change, so that we can catch other plugins modifying the css and update CodeMirror? 
     152                }); 
    151153            }; 
    152154 
  • better-code-editing/trunk/wp-admin/js/theme-plugin-editor.js

    r1722335 r1727131  
    2525     */ 
    2626    component.init = function( settings ) { 
    27         var codeEditorSettings, noticeContainer, errorNotice, updateNotice, currentErrorAnnotations = [], editor, previousErrorCount = 0; 
     27        var codeEditorSettings, noticeContainer, errorNotice = [], editor; 
    2828 
    2929        codeEditorSettings = $.extend( {}, settings ); 
    3030 
    31         codeEditorSettings.handleTabPrev = function() { 
     31        /** 
     32         * Handle tabbing to the field before the editor. 
     33         * 
     34         * @returns {void} 
     35         */ 
     36        codeEditorSettings.onTabPrevious = function() { 
    3237            $( '#templateside' ).find( ':tabbable' ).last().focus(); 
    3338        }; 
    34         codeEditorSettings.handleTabNext = function() { 
     39 
     40        /** 
     41         * Handle tabbing to the field after the editor. 
     42         * 
     43         * @returns {void} 
     44         */ 
     45        codeEditorSettings.onTabNext = function() { 
    3546            $( '#template' ).find( ':tabbable:not(.CodeMirror-code)' ).first().focus(); 
    3647        }; 
    3748 
    38         updateNotice = function() { 
     49        // Create the error notice container. 
     50        noticeContainer = $( '<div id="file-editor-linting-error"></div>' ); 
     51        errorNotice = $( '<div class="inline notice notice-error"></div>' ); 
     52        noticeContainer.append( errorNotice ); 
     53        noticeContainer.hide(); 
     54        $( 'p.submit' ).before( noticeContainer ); 
     55 
     56        /** 
     57         * Update error notice. 
     58         * 
     59         * @param {Array} errorAnnotations - Error annotations. 
     60         * @returns {void} 
     61         */ 
     62        codeEditorSettings.onUpdateErrorNotice = function onUpdateErrorNotice( errorAnnotations ) { 
    3963            var message; 
    4064 
    41             // Short-circuit if there is no update for the message. 
    42             if ( currentErrorAnnotations.length === previousErrorCount ) { 
    43                 return; 
    44             } 
     65            $( '#submit' ).prop( 'disabled', 0 !== errorAnnotations.length ); 
    4566 
    46             previousErrorCount = currentErrorAnnotations.length; 
    47  
    48             $( '#submit' ).prop( 'disabled', 0 !== currentErrorAnnotations.length ); 
    49             if ( 0 !== currentErrorAnnotations.length ) { 
     67            if ( 0 !== errorAnnotations.length ) { 
    5068                errorNotice.empty(); 
    51                 if ( 1 === currentErrorAnnotations.length ) { 
     69                if ( 1 === errorAnnotations.length ) { 
    5270                    message = component.l10n.singular.replace( '%d', '1' ); 
    5371                } else { 
    54                     message = component.l10n.plural.replace( '%d', String( currentErrorAnnotations.length ) ); 
     72                    message = component.l10n.plural.replace( '%d', String( errorAnnotations.length ) ); 
    5573                } 
    5674                errorNotice.append( $( '<p></p>', { 
     
    6482        }; 
    6583 
    66         if ( codeEditorSettings.codemirror.lint ) { 
    67             if ( true === codeEditorSettings.codemirror.lint ) { 
    68                 codeEditorSettings.codemirror.lint = {}; 
    69             } 
    70             noticeContainer = $( '<div id="file-editor-linting-error"></div>' ); 
    71             errorNotice = $( '<div class="inline notice notice-error"></div>' ); 
    72             noticeContainer.append( errorNotice ); 
    73             noticeContainer.hide(); 
    74             $( 'p.submit' ).before( noticeContainer ); 
    75             codeEditorSettings.codemirror.lint = _.extend( {}, codeEditorSettings.codemirror.lint, { 
    76                 onUpdateLinting: function( annotations, annotationsSorted, cm ) { 
    77                     currentErrorAnnotations = _.filter( annotations, function( annotation ) { 
    78                         return 'error' === annotation.severity; 
    79                     } ); 
    80  
    81                     /* 
    82                      * Update notifications when the editor is not focused to prevent error message 
    83                      * from overwhelming the user during input, unless there are no annotations 
    84                      * or there are previous notifications already being displayed, and in that 
    85                      * case update immediately so they can know that they fixed the errors. 
    86                      */ 
    87                     if ( ! cm.state.focused || 0 === currentErrorAnnotations.length || previousErrorCount > 0 ) { 
    88                         updateNotice(); 
    89                     } 
    90                 } 
    91             } ); 
    92         } 
    9384        editor = wp.codeEditor.initialize( $( '#newcontent' ), codeEditorSettings ); 
    94  
    95         if ( codeEditorSettings.codemirror.lint ) { 
    96             editor.on( 'blur', function() { 
    97                 updateNotice(); 
    98             }); 
    99             $( editor.display.wrapper ).on( 'mouseout', function() { 
    100                 updateNotice(); 
    101             }); 
    102         } 
    10385 
    10486        component.instance = editor; 
  • better-code-editing/trunk/wp-admin/js/widgets/custom-html-widgets.js

    r1722335 r1727131  
    6161            control.errorNoticeContainer = control.$el.find( '.code-editor-error-container' ); 
    6262            control.currentErrorAnnotations = []; 
    63             control.previousErrorCount = 0; 
    6463            control.saveButton = control.syncContainer.add( control.syncContainer.parent().find( '.widget-control-actions' ) ).find( '.widget-control-save, #savewidget' ); 
    6564            control.saveButton.addClass( 'custom-html-widget-save-button' ); // To facilitate style targeting. 
     
    107106             * the editor. This is particularly important for users who cannot unfiltered_html. 
    108107             */ 
    109             control.contentUpdateBypassed = control.fields.content.is( document.activeElement ) || control.editor && control.editor.state.focused || 0 !== control.currentErrorAnnotations; 
     108            control.contentUpdateBypassed = control.fields.content.is( document.activeElement ) || control.editor && control.editor.codemirror.state.focused || 0 !== control.currentErrorAnnotations; 
    110109            if ( ! control.contentUpdateBypassed ) { 
    111110                syncInput = control.syncContainer.find( '.sync-input.content' ); 
     
    117116         * Show linting error notice. 
    118117         * 
     118         * @param {Array} errorAnnotations - Error annotations. 
    119119         * @returns {void} 
    120120         */ 
    121         updateErrorNotice: function() { 
    122             var control = this, errorNotice, message, customizeSetting; 
    123  
    124             if ( control.previousErrorCount === control.currentErrorAnnotations.length ) { 
    125                 return; 
    126             } 
    127             control.previousErrorCount = control.currentErrorAnnotations.length; 
    128  
    129             control.saveButton.prop( 'disabled', 0 !== control.currentErrorAnnotations.length ); 
    130  
    131             if ( 1 === control.currentErrorAnnotations.length ) { 
     121        updateErrorNotice: function( errorAnnotations ) { 
     122            var control = this, errorNotice, message = '', customizeSetting; 
     123 
     124            if ( 1 === errorAnnotations.length ) { 
    132125                message = component.l10n.errorNotice.singular.replace( '%d', '1' ); 
    133             } else { 
    134                 message = component.l10n.errorNotice.plural.replace( '%d', String( control.currentErrorAnnotations.length ) ); 
     126            } else if ( errorAnnotations.length > 1 ) { 
     127                message = component.l10n.errorNotice.plural.replace( '%d', String( errorAnnotations.length ) ); 
     128            } 
     129 
     130            if ( control.fields.content[0].setCustomValidity ) { 
     131                control.fields.content[0].setCustomValidity( message ); 
    135132            } 
    136133 
    137134            if ( wp.customize && wp.customize.has( control.customizeSettingId ) ) { 
    138135                customizeSetting = wp.customize( control.customizeSettingId ); 
    139                 customizeSetting.notifications.remove( 'htmllint_error' ); 
    140                 if ( 0 !== control.currentErrorAnnotations.length ) { 
    141                     customizeSetting.notifications.add( 'htmllint_error', new wp.customize.Notification( 'htmllint_error', { 
     136                customizeSetting.notifications.remove( 'htmlhint_error' ); 
     137                if ( 0 !== errorAnnotations.length ) { 
     138                    customizeSetting.notifications.add( 'htmlhint_error', new wp.customize.Notification( 'htmlhint_error', { 
    142139                        message: message, 
    143140                        type: 'error' 
    144141                    } ) ); 
    145142                } 
    146             } else if ( 0 !== control.currentErrorAnnotations.length ) { 
     143            } else if ( 0 !== errorAnnotations.length ) { 
    147144                errorNotice = $( '<div class="inline notice notice-error notice-alt"></div>' ); 
    148145                errorNotice.append( $( '<p></p>', { 
     
    171168 
    172169            settings = _.extend( {}, component.codeEditorSettings, { 
    173                 handleTabPrev: function() { 
     170 
     171                /** 
     172                 * Handle tabbing to the field before the editor. 
     173                 * 
     174                 * @returns {void} 
     175                 */ 
     176                onTabPrevious: function onTabPrevious() { 
    174177                    control.fields.title.focus(); 
    175178                }, 
    176                 handleTabNext: function() { 
     179 
     180                /** 
     181                 * Handle tabbing to the field after the editor. 
     182                 * 
     183                 * @returns {void} 
     184                 */ 
     185                onTabNext: function onTabNext() { 
    177186                    var tabbables = control.syncContainer.add( control.syncContainer.parent().find( '.widget-position, .widget-control-actions' ) ).find( ':tabbable' ); 
    178187                    tabbables.first().focus(); 
     188                }, 
     189 
     190                /** 
     191                 * Disable save button and store linting errors for use in updateFields. 
     192                 * 
     193                 * @param {Array} errorAnnotations - Error notifications. 
     194                 * @returns {void} 
     195                 */ 
     196                onChangeLintingErrors: function onChangeLintingErrors( errorAnnotations ) { 
     197                    control.currentErrorAnnotations = errorAnnotations; 
     198                }, 
     199 
     200                /** 
     201                 * Update error notice. 
     202                 * 
     203                 * @param {Array} errorAnnotations - Error annotations. 
     204                 * @returns {void} 
     205                 */ 
     206                onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) { 
     207                    control.saveButton.toggleClass( 'validation-blocked', errorAnnotations.length ); 
     208                    control.updateErrorNotice( errorAnnotations ); 
    179209                } 
    180210            }); 
    181  
    182             if ( settings.codemirror.lint ) { 
    183                 if ( true === settings.codemirror.lint ) { 
    184                     settings.codemirror.lint = {}; 
    185                 } 
    186                 settings.codemirror.lint = _.extend( {}, settings.codemirror.lint, { 
    187                     onUpdateLinting: function( annotations, annotationsSorted, editor ) { 
    188                         control.currentErrorAnnotations = _.filter( annotations, function( annotation ) { 
    189                             return 'error' === annotation.severity; 
    190                         } ); 
    191  
    192                         /* 
    193                          * Update notifications when the editor is not focused to prevent error message 
    194                          * from overwhelming the user during input, unless there are no annotations 
    195                          * or there are previous notifications already being displayed, and in that 
    196                          * case update immediately so they can know that they fixed the errors. 
    197                          */ 
    198                         if ( ! editor.state.focused || 0 === control.currentErrorAnnotations.length || control.previousErrorCount > 0 ) { 
    199                             control.updateErrorNotice(); 
    200                         } 
    201                     } 
    202                 }); 
    203             } 
    204211 
    205212            control.editor = wp.codeEditor.initialize( control.fields.content, settings ); 
    206213            control.fields.content.on( 'change', function() { 
    207                 if ( this.value !== control.editor.getValue() ) { 
    208                     control.editor.setValue( this.value ); 
     214                if ( this.value !== control.editor.codemirror.getValue() ) { 
     215                    control.editor.codemirror.setValue( this.value ); 
    209216                } 
    210217            }); 
    211             control.editor.on( 'change', function() { 
    212                 var value = control.editor.getValue(); 
     218            control.editor.codemirror.on( 'change', function() { 
     219                var value = control.editor.codemirror.getValue(); 
    213220                if ( value !== control.fields.content.val() ) { 
    214221                    control.fields.content.val( value ).trigger( 'change' ); 
     
    216223            }); 
    217224 
    218             // Show the error notice when the user leaves the editor. 
    219             if ( settings.codemirror.lint ) { 
    220                 control.editor.on( 'blur', function() { 
    221                     control.updateErrorNotice(); 
    222                 }); 
    223                 $( control.editor.display.wrapper ).on( 'mouseout', function() { 
    224                     control.updateErrorNotice(); 
    225                 }); 
    226             } 
    227  
    228225            // Make sure the editor gets updated if the content was updated on the server (sanitization) but not updated in the editor since it was focused. 
    229             control.editor.on( 'blur', function() { 
     226            control.editor.codemirror.on( 'blur', function() { 
    230227                if ( control.contentUpdateBypassed ) { 
    231228                    control.syncContainer.find( '.sync-input.content' ).trigger( 'change' ); 
    232229                } 
    233230            }); 
     231 
     232            // Prevent hitting Esc from collapsing the widget control. 
     233            if ( wp.customize ) { 
     234                control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) { 
     235                    var escKeyCode = 27; 
     236                    if ( escKeyCode === event.keyCode ) { 
     237                        event.stopPropagation(); 
     238                    } 
     239                }); 
     240            } 
    234241        } 
    235242    }); 
  • better-code-editing/trunk/wp-includes/customize-manager-addendum.php

    r1722335 r1727131  
    1616 */ 
    1717function _better_code_editing_amend_custom_css_help_text( WP_Customize_Manager $wp_customize ) { 
    18     $wp_customize->custom_css_code_editor_settings = wp_code_editor_settings( array( 
    19         'file' => 'custom.css', 
    20     ) ); 
    21  
    22     if ( empty( $wp_customize->custom_css_code_editor_settings ) ) { 
     18    if ( 'false' === wp_get_current_user()->syntax_highlighting ) { 
    2319        return; 
    2420    } 
     
    2723    if ( ! $section ) { 
    2824        return; 
     25    } 
     26 
     27    // Remove default value from Custom CSS setting. 
     28    foreach ( $wp_customize->settings() as $setting ) { 
     29        if ( $setting instanceof WP_Customize_Custom_CSS_Setting ) { 
     30            $setting->default = ''; 
     31        } 
    2932    } 
    3033 
     
    4952    $section->description .= sprintf( 
    5053        /* translators: placeholder is link to user profile */ 
    51         __( 'The edit field automatically highlights code syntax. You can disable this in your %s to work in plan text mode.', 'better-code-editing' ), 
     54        __( 'The edit field automatically highlights code syntax. You can disable this in your %s to work in plain text mode.', 'better-code-editing' ), 
    5255        sprintf( 
    5356            ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text">%3$s</span></a>', 
     
    5861        ) 
    5962    ); 
     63    $section->description .= '</p>'; 
     64 
     65    $section->description .= '<p class="section-description-buttons">'; 
     66    $section->description .= '<button type="button" class="button-link section-description-close">' . __( 'Close', 'default' ) . '</button>'; 
    6067    $section->description .= '</p>'; 
    6168} 
     
    6875function _better_code_editing_customize_controls_enqueue_scripts() { 
    6976    global $wp_customize; 
    70     if ( ! empty( $wp_customize->custom_css_code_editor_settings ) ) { 
    71         wp_enqueue_code_editor( $wp_customize->custom_css_code_editor_settings ); 
    72     } 
     77    $wp_customize->custom_css_code_editor_settings = wp_enqueue_code_editor( array( 
     78        'type' => 'text/css', 
     79    ) ); 
    7380    wp_add_inline_script( 'customize-controls', file_get_contents( dirname( BETTER_CODE_EDITING_PLUGIN_FILE ) . '/wp-admin/js/customize-controls-addendum.js' ) ); 
    7481} 
     
    8592        return; 
    8693    } 
    87     printf( '<script>window._wpCustomizeSettings.codeEditor = %s</script>;', wp_json_encode( $wp_customize->custom_css_code_editor_settings ) ); 
     94    $custom_css_setting = $wp_customize->get_setting( sprintf( 'custom_css[%s]', get_stylesheet() ) ); 
     95    if ( ! $custom_css_setting ) { 
     96        return; 
     97    } 
     98 
     99    $settings = array( 
     100        'codeEditor' => $wp_customize->custom_css_code_editor_settings, 
     101    ); 
     102 
     103    printf( '<script>window._wpCustomizeSettings.customCss = %s</script>;', wp_json_encode( $settings ) ); 
    88104 
    89105    /* translators: placeholder is error count */ 
  • better-code-editing/trunk/wp-includes/general-template-addendum.php

    r1722335 r1727131  
    88 
    99/** 
    10  * Gets settings for initializing the code editor. 
     10 * Enqueue assets needed by the code editor for the given settings. 
    1111 * 
    1212 * @since 4.9.0 
    1313 * 
    14  * @param array $context { 
    15  *     Context. 
     14 * @see wp_enqueue_editor() 
     15 * @see _WP_Editors::parse_settings() 
     16 * @param array $args { 
     17 *     Args. 
    1618 * 
    17  *     @type string $type The MIME type of the file to be edited. 
    18  *     @type string $file Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param. 
     19 *     @type string   $type     The MIME type of the file to be edited. 
     20 *     @type string   $file     Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param. 
     21 *     @type array    $settings Settings to merge on top of defaults which derive from `$type` or `$file` args. 
     22 *     @type WP_Theme $theme    Theme being edited when on theme editor. 
     23 *     @type string   $plugin   Plugin being edited when on plugin editor. 
    1924 * } 
    20  * @return array|false Settings for code editor or false if disabled. 
     25 * @returns array|false Settings for the enqueued code editor, or false if the editor was not enqueued . 
    2126 */ 
    22 function wp_code_editor_settings( $context ) { 
    23  
     27function wp_enqueue_code_editor( $args ) { 
    2428    if ( is_user_logged_in() && 'false' === wp_get_current_user()->syntax_highlighting ) { 
    2529        return false; 
     
    3337            'lineNumbers' => true, 
    3438            'lineWrapping' => true, 
    35             'showTrailingSpace' => true, 
    3639            'styleActiveLine' => true, 
    3740            'continueComments' => true, 
     
    4043                'Ctrl-/' => 'toggleComment', 
    4144                'Cmd-/' => 'toggleComment', 
     45                'Alt-F' => 'findPersistent', 
    4246            ), 
     47            'direction' => 'ltr', // Code is shown in LTR even in RTL languages. 
    4348        ), 
    4449        'csslint' => array( 
    45             'rules' => array( 
    46                 'errors' => true, // Parsing errors. 
    47                 'box-model' => true, 
    48                 'display-property-grouping' => true, 
    49                 'duplicate-properties' => true, 
    50                 'empty-rules' => true, 
    51                 'known-properties' => true, 
    52                 'outline-none' => true, 
    53             ), 
     50            'errors' => true, // Parsing errors. 
     51            'box-model' => true, 
     52            'display-property-grouping' => true, 
     53            'duplicate-properties' => true, 
     54            'known-properties' => true, 
     55            'outline-none' => true, 
    5456        ), 
    5557        'jshint' => array( 
    56             'rules' => array( 
    57                 // The following are copied from <https://github.com/WordPress/wordpress-develop/blob/4.8.1/.jshintrc>. 
    58                 'boss' => true, 
    59                 'curly' => true, 
    60                 'eqeqeq' => true, 
    61                 'eqnull' => true, 
    62                 'es3' => true, 
    63                 'expr' => true, 
    64                 'immed' => true, 
    65                 'noarg' => true, 
    66                 'nonbsp' => true, 
    67                 'onevar' => true, 
    68                 'quotmark' => 'single', 
    69                 'trailing' => true, 
    70                 'undef' => true, 
    71                 'unused' => true, 
    72  
    73                 'browser' => true, 
    74  
    75                 'globals' => array( 
    76                     '_' => false, 
    77                     'Backbone' => false, 
    78                     'jQuery' => false, 
    79                     'JSON' => false, 
    80                     'wp' => false, 
    81                 ), 
     58            // The following are copied from <https://github.com/WordPress/wordpress-develop/blob/4.8.1/.jshintrc>. 
     59            'boss' => true, 
     60            'curly' => true, 
     61            'eqeqeq' => true, 
     62            'eqnull' => true, 
     63            'es3' => true, 
     64            'expr' => true, 
     65            'immed' => true, 
     66            'noarg' => true, 
     67            'nonbsp' => true, 
     68            'onevar' => true, 
     69            'quotmark' => 'single', 
     70            'trailing' => true, 
     71            'undef' => true, 
     72            'unused' => true, 
     73 
     74            'browser' => true, 
     75 
     76            'globals' => array( 
     77                '_' => false, 
     78                'Backbone' => false, 
     79                'jQuery' => false, 
     80                'JSON' => false, 
     81                'wp' => false, 
    8282            ), 
    8383        ), 
    8484        'htmlhint' => array( 
    85             'rules' => array( 
    86                 'tagname-lowercase' => true, 
    87                 'attr-lowercase' => true, 
    88                 'attr-value-double-quotes' => true, 
    89                 'doctype-first' => false, 
    90                 'tag-pair' => true, 
    91                 'spec-char-escape' => true, 
    92                 'id-unique' => true, 
    93                 'src-not-empty' => true, 
    94                 'attr-no-duplication' => true, 
    95                 'alt-require' => true, 
    96                 'space-tab-mixed-disabled' => 'tab', 
    97                 'attr-unsafe-chars' => true, 
    98             ), 
     85            'tagname-lowercase' => true, 
     86            'attr-lowercase' => true, 
     87            'attr-value-double-quotes' => true, 
     88            'doctype-first' => false, 
     89            'tag-pair' => true, 
     90            'spec-char-escape' => true, 
     91            'id-unique' => true, 
     92            'src-not-empty' => true, 
     93            'attr-no-duplication' => true, 
     94            'alt-require' => true, 
     95            'space-tab-mixed-disabled' => 'tab', 
     96            'attr-unsafe-chars' => true, 
    9997        ), 
    10098    ); 
    10199 
    102100    $type = ''; 
    103     if ( isset( $context['type'] ) ) { 
    104         $type = $context['type']; 
     101    if ( isset( $args['type'] ) ) { 
     102        $type = $args['type']; 
    105103 
    106104        // Remap MIME types to ones that CodeMirror modes will recognize. 
     
    108106            $type = 'text/x-diff'; 
    109107        } 
    110     } elseif ( isset( $context['file'] ) && false !== strpos( basename( $context['file'] ), '.' ) ) { 
    111         $extension = strtolower( pathinfo( $context['file'], PATHINFO_EXTENSION ) ); 
     108    } elseif ( isset( $args['file'] ) && false !== strpos( basename( $args['file'] ), '.' ) ) { 
     109        $extension = strtolower( pathinfo( $args['file'], PATHINFO_EXTENSION ) ); 
    112110        foreach ( wp_get_mime_types() as $exts => $mime ) { 
    113111            if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) { 
     
    227225            'mode' => 'gfm', 
    228226            'highlightFormatting' => true, 
    229             'showTrailingSpace' => false, // GitHub-flavored markdown uses trailing spaces as a feature. 
    230227        ) ); 
    231228    } elseif ( 'application/javascript' === $type || 'text/javascript' === $type ) { 
     
    300297    if ( ! empty( $settings['codemirror']['lint'] ) ) { 
    301298        $settings['codemirror']['gutters'][] = 'CodeMirror-lint-markers'; 
     299    } 
     300 
     301    // Let settings supplied via args override any defaults. 
     302    if ( isset( $args['settings'] ) ) { 
     303        foreach ( $args['settings'] as $key => $value ) { 
     304            $settings[ $key ] = array_merge( 
     305                $settings[ $key ], 
     306                $value 
     307            ); 
     308        } 
    302309    } 
    303310 
     
    310317     * 
    311318     * @param array $settings The array of settings passed to the code editor. A falsey value disables the editor. 
    312      * @param array $context { 
    313      *     Context for where the editor will appear. 
     319     * @param array $args { 
     320     *     Args passed when calling `wp_enqueue_code_editor()`. 
    314321     * 
    315      *     @type string    $file   File being edited. 
    316      *     @type WP_Theme  $theme  Theme being edited when on theme editor. 
    317      *     @type string    $plugin Plugin being edited when on plugin editor. 
     322     *     @type string   $type     The MIME type of the file to be edited. 
     323     *     @type string   $file     Filename being edited. 
     324     *     @type array    $settings Settings to merge on top of defaults which derive from `$type` or `$file` args. 
     325     *     @type WP_Theme $theme    Theme being edited when on theme editor. 
     326     *     @type string   $plugin   Plugin being edited when on plugin editor. 
    318327     * } 
    319328     */ 
    320     $settings = apply_filters( 'wp_code_editor_settings', $settings, $context ); 
    321  
    322     return $settings; 
    323 } 
    324  
    325 /** 
    326  * Enqueue assets needed by the code editor for the given settings. 
    327  * 
    328  * @since 4.9.0 
    329  * 
    330  * @see wp_code_editor_settings() 
    331  * @param array|false $settings Code editor settings. 
    332  * @returns boolean Whether assets were enqueued. 
    333  */ 
    334 function wp_enqueue_code_editor( $settings ) { 
     329    $settings = apply_filters( 'wp_code_editor_settings', $settings, $args ); 
     330 
    335331    if ( empty( $settings ) || empty( $settings['codemirror'] ) ) { 
    336332        return false; 
     
    362358        } 
    363359    } 
     360 
    364361    wp_enqueue_script( 'codemirror-addon-comment' ); 
     362    wp_enqueue_script( 'codemirror-addon-dialog' ); 
     363    wp_enqueue_style( 'codemirror-addon-dialog' ); 
     364    wp_enqueue_script( 'codemirror-addon-search-searchcursor' ); 
     365    wp_enqueue_script( 'codemirror-addon-search' ); 
     366    wp_enqueue_script( 'codemirror-addon-scroll-annotatescrollbar' ); 
     367    wp_enqueue_script( 'codemirror-addon-search-matchesonscrollbar' ); 
     368    wp_enqueue_script( 'codemirror-addon-search-jump-to-line' ); 
    365369 
    366370    if ( isset( $settings['codemirror']['mode'] ) ) { 
     
    500504    do_action( 'wp_enqueue_code_editor', $settings ); 
    501505 
    502     return true; 
     506    return $settings; 
    503507} 
  • better-code-editing/trunk/wp-includes/js/codemirror/addon/hint/show-hint.js

    r1719147 r1727131  
    303303    }); 
    304304 
    305     CodeMirror.signal(data, "select", completions[0], hints.firstChild); 
     305    CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); 
    306306    return true; 
    307307  } 
  • better-code-editing/trunk/wp-includes/js/codemirror/addon/lint/css-lint.js

    r1719147 r1727131  
    1616"use strict"; 
    1717 
    18 CodeMirror.registerHelper("lint", "css", function(text) { 
     18CodeMirror.registerHelper("lint", "css", function(text, options) { 
    1919  var found = []; 
    2020  if (!window.CSSLint) { 
     
    2424    return found; 
    2525  } 
    26   var results = CSSLint.verify(text), messages = results.messages, message = null; 
     26  var results = CSSLint.verify(text, options), messages = results.messages, message = null; 
    2727  for ( var i = 0; i < messages.length; i++) { 
    2828    message = messages[i]; 
  • better-code-editing/trunk/wp-includes/js/codemirror/lib/codemirror.js

    r1720408 r1727131  
    28842884    if (cm.options.lineWrapping) { 
    28852885      var assign; 
    2886       ((assign = wrappedLineExtent(cm, lineObj, preparedMeasure, y), begin = assign.begin, end = assign.end, assign)); 
     2886      ((assign = wrappedLineExtent(cm, lineObj, preparedMeasure, y), begin = assign.begin, end = assign.end)); 
    28872887    } 
    28882888    pos = new Pos(lineNo$$1, Math.floor(begin + (end - begin) / 2)); 
     
    30953095} 
    30963096 
     3097function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } 
     3098 
    30973099// Draws the given range as a highlighted selection 
    30983100function drawSelectionRange(cm, range$$1, output) { 
     
    31183120 
    31193121    iterateBidiSections(getOrder(lineObj, doc.direction), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) { 
    3120       var leftPos = coords(from, "left"), rightPos, left, right; 
    3121       if (from == to) { 
    3122         rightPos = leftPos; 
    3123         left = right = leftPos.left; 
    3124       } else { 
    3125         rightPos = coords(to - 1, "right"); 
    3126         if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } 
    3127         left = leftPos.left; 
    3128         right = rightPos.right; 
     3122      var fromPos, toPos; 
     3123      if (dir == "ltr") { 
     3124        fromPos = coords(from, "left"); 
     3125        toPos = coords(to - 1, "right"); 
     3126        var fromLeft = fromArg == null && from == 0 ? leftSide : fromPos.left; 
     3127        var toRight = toArg == null && to == lineLen ? rightSide : toPos.right; 
     3128        if (toPos.top - fromPos.top <= 3) { // Single line 
     3129          add(fromLeft, toPos.top, toRight - fromLeft, toPos.bottom); 
     3130        } else { // Multiple lines 
     3131          add(fromLeft, fromPos.top, null, fromPos.bottom); 
     3132          if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } 
     3133          add(leftSide, toPos.top, toPos.right, toPos.bottom); 
     3134        } 
     3135      } else { // RTL 
     3136        fromPos = coords(from, "right"); 
     3137        toPos = coords(to - 1, "left"); 
     3138        var fromRight = fromArg == null && from == 0 ? rightSide : fromPos.right; 
     3139        var toLeft = toArg == null && to == lineLen ? leftSide : toPos.left; 
     3140        if (toPos.top - fromPos.top <= 3) { // Single line 
     3141          add(toLeft, toPos.top, fromRight - toLeft, toPos.bottom); 
     3142        } else { // Multiple lines 
     3143          add(leftSide, fromPos.top, fromRight - leftSide, fromPos.bottom); 
     3144          if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } 
     3145          add(toLeft, toPos.top, null, toPos.bottom); 
     3146        } 
    31293147      } 
    3130       if (fromArg == null && from == 0) { left = leftSide; } 
    3131       if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part 
    3132         add(left, leftPos.top, null, leftPos.bottom); 
    3133         left = leftSide; 
    3134         if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top); } 
    3135       } 
    3136       if (toArg == null && to == lineLen) { right = rightSide; } 
    3137       if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) 
    3138         { start = leftPos; } 
    3139       if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) 
    3140         { end = rightPos; } 
    3141       if (left < leftSide + 1) { left = leftSide; } 
    3142       add(left, rightPos.top, right - left, rightPos.bottom); 
     3148 
     3149      if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; } 
     3150      if (cmpCoords(toPos, start) < 0) { start = toPos; } 
     3151      if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; } 
     3152      if (cmpCoords(toPos, end) < 0) { end = toPos; } 
    31433153    }); 
    31443154    return {start: start, end: end} 
     
    54795489 
    54805490LeafChunk.prototype = { 
    5481   chunkSize: function chunkSize() { return this.lines.length }, 
     5491  chunkSize: function() { return this.lines.length }, 
    54825492 
    54835493  // Remove the n lines at offset 'at'. 
    5484   removeInner: function removeInner(at, n) { 
     5494  removeInner: function(at, n) { 
    54855495    var this$1 = this; 
    54865496 
     
    54955505 
    54965506  // Helper used to collapse a small branch into a single leaf. 
    5497   collapse: function collapse(lines) { 
     5507  collapse: function(lines) { 
    54985508    lines.push.apply(lines, this.lines); 
    54995509  }, 
     
    55015511  // Insert the given array of lines at offset 'at', count them as 
    55025512  // having the given height. 
    5503   insertInner: function insertInner(at, lines, height) { 
     5513  insertInner: function(at, lines, height) { 
    55045514    var this$1 = this; 
    55055515 
     
    55105520 
    55115521  // Used to iterate over a part of the tree. 
    5512   iterN: function iterN(at, n, op) { 
     5522  iterN: function(at, n, op) { 
    55135523    var this$1 = this; 
    55145524 
     
    55345544 
    55355545BranchChunk.prototype = { 
    5536   chunkSize: function chunkSize() { return this.size }, 
    5537  
    5538   removeInner: function removeInner(at, n) { 
     5546  chunkSize: function() { return this.size }, 
     5547 
     5548  removeInner: function(at, n) { 
    55395549    var this$1 = this; 
    55405550 
     
    55625572  }, 
    55635573 
    5564   collapse: function collapse(lines) { 
     5574  collapse: function(lines) { 
    55655575    var this$1 = this; 
    55665576 
     
    55685578  }, 
    55695579 
    5570   insertInner: function insertInner(at, lines, height) { 
     5580  insertInner: function(at, lines, height) { 
    55715581    var this$1 = this; 
    55725582 
     
    55975607 
    55985608  // When a node has grown, check whether it should be split. 
    5599   maybeSpill: function maybeSpill() { 
     5609  maybeSpill: function() { 
    56005610    if (this.children.length <= 10) { return } 
    56015611    var me = this; 
     
    56195629  }, 
    56205630 
    5621   iterN: function iterN(at, n, op) { 
     5631  iterN: function(at, n, op) { 
    56225632    var this$1 = this; 
    56235633 
     
    94859495addLegacyProps(CodeMirror$1); 
    94869496 
    9487 CodeMirror$1.version = "5.29.0"; 
     9497CodeMirror$1.version = "5.29.1"; 
    94889498 
    94899499return CodeMirror$1; 
  • better-code-editing/trunk/wp-includes/js/codemirror/mode/javascript/javascript.js

    r1720408 r1727131  
    399399    if (cx.state.fatArrowAt == cx.stream.start) { 
    400400      var body = noComma ? arrowBodyNoComma : arrowBody; 
    401       if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); 
     401      if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext); 
    402402      else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); 
    403403    } 
     
    492492      cx.marked = "property"; 
    493493      if (value == "get" || value == "set") return cont(getterSetter); 
     494      var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params 
     495      if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false))) 
     496        cx.state.fatArrowAt = cx.stream.pos + m[0].length 
    494497      return cont(afterprop); 
    495498    } else if (type == "number" || type == "string") { 
     
    675678      return cont(classBody); 
    676679    } 
    677     if (type == "variable") { 
     680    if (type == "variable" || cx.style == "keyword") { 
    678681      cx.marked = "property"; 
    679682      return cont(isTS ? classfield : functiondef, classBody); 
  • better-code-editing/trunk/wp-includes/js/codemirror/mode/markdown/markdown.js

    r1720408 r1727131  
    840840 
    841841    indent: function(state, textAfter, line) { 
    842       if (state.block == htmlBlock) return htmlMode.indent(state.htmlState, textAfter, line) 
    843       if (state.localState) return state.localMode.indent(state.localState, textAfter, line) 
     842      if (state.block == htmlBlock && htmlMode.indent) return htmlMode.indent(state.htmlState, textAfter, line) 
     843      if (state.localState && state.localMode.indent) return state.localMode.indent(state.localState, textAfter, line) 
    844844      return CodeMirror.Pass 
    845845    }, 
  • better-code-editing/trunk/wp-includes/script-loader-addendum.php

    r1722335 r1727131  
    1515 */ 
    1616function _better_code_editing_default_scripts( WP_Scripts $scripts ) { 
    17     $codemirror_version = '5.29.0'; 
     17    $codemirror_version = '5.29.1-alpha-' . BETTER_CODE_EDITING_PLUGIN_VERSION; 
    1818 
    1919    $scripts->add( 'codemirror', plugins_url( 'wp-includes/js/codemirror/lib/codemirror.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array(), $codemirror_version ); 
     
    135135 */ 
    136136function _better_code_editing_register_styles( WP_Styles $styles ) { 
    137     $codemirror_version = '5.29.0'; 
     137    $codemirror_version = '5.29.1-alpha-' . BETTER_CODE_EDITING_PLUGIN_VERSION; 
    138138 
    139139    /* 
     
    142142    $styles->registered['common']->src = plugins_url( 'wp-admin/css/common.css', BETTER_CODE_EDITING_PLUGIN_FILE ); 
    143143    $styles->registered['common']->ver = BETTER_CODE_EDITING_PLUGIN_VERSION; 
     144    unset( $styles->registered['common']->extra['suffix'] ); // Prevent minified version from being attempted. 
    144145 
    145146    $styles->add( 'codemirror',                                 plugins_url( 'wp-includes/js/codemirror/lib/codemirror.css', BETTER_CODE_EDITING_PLUGIN_FILE ),                  array(),               $codemirror_version ); 
     
    156157    $styles->add( 'code-editor', plugins_url( 'wp-admin/css/code-editor.css', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), BETTER_CODE_EDITING_PLUGIN_VERSION ); 
    157158 
     159    // RTL CSS. 
     160    $rtl_styles = array( 
     161        'code-editor', 
     162    ); 
     163    foreach ( $rtl_styles as $rtl_style ) { 
     164        $styles->add_data( $rtl_style, 'rtl', 'replace' ); 
     165    } 
     166 
    158167    // Patch the stylesheets. 
    159     $styles->add_inline_style( 'widgets', file_get_contents( dirname( BETTER_CODE_EDITING_PLUGIN_FILE ) . '/wp-admin/css/widgets-addendum.css' ) ); 
    160     $styles->add_inline_style( 'customize-controls', file_get_contents( dirname( BETTER_CODE_EDITING_PLUGIN_FILE ) . '/wp-admin/css/customize-controls-addendum.css' ) ); 
     168    if ( function_exists( 'is_rtl' ) && is_rtl() && file_exists( plugin_dir_path( BETTER_CODE_EDITING_PLUGIN_FILE ) . 'wp-admin/css/common-rtl.css' ) ) { 
     169        $suffix = '-rtl.css'; 
     170    } else { 
     171        $suffix = '.css'; 
     172    } 
     173    $styles->add_inline_style( 'widgets', file_get_contents( dirname( BETTER_CODE_EDITING_PLUGIN_FILE ) . '/wp-admin/css/widgets-addendum' . $suffix ) ); 
     174    $styles->add_inline_style( 'customize-controls', file_get_contents( dirname( BETTER_CODE_EDITING_PLUGIN_FILE ) . '/wp-admin/css/customize-controls-addendum' . $suffix ) ); 
    161175 
    162176    if ( defined( 'SCRIPT_DEBUG' ) ) { 
  • better-code-editing/trunk/wp-includes/widgets/class-wp-widget-custom-html-codemirror.php

    r1722335 r1727131  
    5656     */ 
    5757    public function enqueue_admin_scripts() { 
    58         $settings = wp_code_editor_settings( array( 
    59             'file' => 'custom_html_widget.html', // @todo This faux filename is not really the best. 
     58        $settings = wp_enqueue_code_editor( array( 
     59            'type' => 'text/html', 
    6060        ) ); 
    6161 
     
    6565                'disabled' => true, 
    6666            ); 
    67         } else { 
    68             wp_enqueue_code_editor( $settings ); 
    6967        } 
    7068        wp_add_inline_script( 'custom-html-widgets', sprintf( 'wp.customHtmlWidgets.init( %s );', wp_json_encode( $settings ) ), 'after' ); 
Note: See TracChangeset for help on using the changeset viewer.