WordPress.org

Plugin Directory

Changeset 1722335


Ignore:
Timestamp:
08/30/17 23:59:45 (3 weeks ago)
Author:
westonruter
Message:

Bump 0.5.0

Location:
better-code-editing/trunk
Files:
1 added
109 deleted
14 edited

Legend:

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

    r1720408 r1722335  
    44 * Plugin URI: https://wordpress.org/plugins/better-code-editing/ 
    55 * Description: Code highlighting and linting, powered by CodeMirror. 
    6  * Version: 0.4.0 
     6 * Version: 0.5.0 
    77 * Author: The WordPress Team 
    88 * Text Domain: better-code-editing 
     
    1111 */ 
    1212 
    13 define( 'BETTER_CODE_EDITING_PLUGIN_VERSION', '0.4.0' ); 
     13define( 'BETTER_CODE_EDITING_PLUGIN_VERSION', '0.5.0' ); 
    1414define( 'BETTER_CODE_EDITING_PLUGIN_FILE', __FILE__ ); 
    1515 
  • better-code-editing/trunk/readme.txt

    r1720408 r1722335  
    22Contributors: georgestephanis, westonruter, obenland, melchoyce, wordpressdotorg 
    33Tags: codemirror, syntax-highlighter, linting 
    4 Stable tag: 0.4.0 
     4Stable tag: trunk 
    55Requires at least: 4.7 
    66Tested up to: 4.9-alpha 
     
    2121 
    2222== Changelog == 
     23 
     24= 0.5.0 - 2017-08-30 = 
     25 
     26* Prevent saving when lint errors present. See [#69](https://github.com/WordPress/better-code-editing/pull/69). Fixes [#69](https://github.com/WordPress/better-code-editing/issues/69). 
     27* Remove unused assets; register likely-used assets; allow recognized file types to be edited; allow passing type when getting settings in addition to file. See [#66](https://github.com/WordPress/better-code-editing/pull/66). Fixes [#4](https://github.com/WordPress/better-code-editing/issues/4). 
     28* Add recognition for JSON mode. 
     29* Align styling matchbracket with matchtag. See [#63](https://github.com/WordPress/better-code-editing/pull/63). Fixes [#56](https://github.com/WordPress/better-code-editing/issues/56). 
     30* Redesign warning/error messages. See [#62](https://github.com/WordPress/better-code-editing/pull/62). Fixes [#44](https://github.com/WordPress/better-code-editing/issues/44), [#45](https://github.com/WordPress/better-code-editing/issues/45). 
     31* 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). 
     32* Add `wp_enqueue_code_editor` action. See [#68](https://github.com/WordPress/better-code-editing/pull/68). 
    2333 
    2434= 0.4.0 - 2017-08-28 = 
  • better-code-editing/trunk/wp-admin/css/code-editor.css

    r1720408 r1722335  
    11.cm-trailingspace { 
    2     background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==); 
    3     background-position: bottom left; 
    4     background-repeat: repeat-x; 
     2    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==) repeat-x bottom left; 
    53} 
     4 
     5.wrap [class*="CodeMirror-lint-marker"], 
     6.wp-core-ui [class*="CodeMirror-lint-message"], 
     7.wrap .CodeMirror-lint-marker-multiple { 
     8    background-image: none; 
     9} 
     10 
     11.wrap [class*="CodeMirror-lint-marker"]:before { 
     12    font: normal 18px/1 dashicons; 
     13    position: relative; 
     14    top: -2px; 
     15} 
     16 
     17.wp-core-ui [class*="CodeMirror-lint-message"]:before { 
     18    font: normal 16px/1 dashicons; 
     19    left: 16px; 
     20    position: absolute; 
     21} 
     22 
     23.wp-core-ui .CodeMirror-lint-message-error, 
     24.wp-core-ui .CodeMirror-lint-message-warning { 
     25    box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 ); 
     26    margin: 5px 0 2px; 
     27    padding: 3px 12px 3px 28px; 
     28} 
     29 
     30.wp-core-ui .CodeMirror-lint-message-warning { 
     31    background-color: #fff8e5; 
     32    border-left: 4px solid #ffb900; 
     33} 
     34 
     35.wrap .CodeMirror-lint-marker-warning:before, 
     36.wp-core-ui .CodeMirror-lint-message-warning:before { 
     37    content: "\f534"; 
     38    color: #f6a306; 
     39} 
     40 
     41.wp-core-ui .CodeMirror-lint-message-error { 
     42    background-color: #fbeaea; 
     43    border-left: 4px solid #dc3232; 
     44} 
     45 
     46.wrap .CodeMirror-lint-marker-error:before, 
     47.wp-core-ui .CodeMirror-lint-message-error:before { 
     48    content: "\f153"; 
     49    color: #dc3232; 
     50} 
     51 
     52.wp-core-ui .CodeMirror-lint-tooltip { 
     53    background: none; 
     54    border: none; 
     55    border-radius: 0; 
     56} 
     57 
     58.wrap .CodeMirror .CodeMirror-matchingbracket { 
     59    background: rgba(255, 150, 0, .3); 
     60    color: inherit; 
     61} 
  • better-code-editing/trunk/wp-admin/css/common.css

    r1720408 r1722335  
    31063106} 
    31073107 
     3108#file-editor-linting-error { 
     3109    margin-top: 1em; 
     3110    margin-bottom: 1em; 
     3111} 
     3112#file-editor-linting-error > .notice { 
     3113    margin: 0; 
     3114    display: inline-block; 
     3115} 
     3116#file-editor-linting-error > .notice > p { 
     3117    width: auto; 
     3118} 
     3119#template .submit { 
     3120    margin-top: 1em; 
     3121    padding: 0; 
     3122} 
     3123 
     3124#template .submit input[type=submit][disabled] { 
     3125    cursor: not-allowed; 
     3126} 
    31083127#templateside { 
    31093128    float: right; 
  • better-code-editing/trunk/wp-admin/css/customize-controls-addendum.css

    r1720408 r1722335  
    66    z-index: 500000 !important; 
    77} 
     8 
     9.customize-section-description ul { 
     10    margin-left: 1em; 
     11} 
     12.customize-section-description ul > li { 
     13    list-style: disc; 
     14} 
     15 
     16.customize-section-description-container + #customize-control-custom_css:last-child .customize-control-notifications-container { 
     17    margin-left: 12px; 
     18    margin-right: 12px; 
     19} 
  • better-code-editing/trunk/wp-admin/css/widgets-addendum.css

    r1720408 r1722335  
    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] { 
     14    cursor: not-allowed; 
     15} 
  • better-code-editing/trunk/wp-admin/file-editor-addendum.php

    r1720408 r1722335  
    77 */ 
    88 
     9add_filter( 'editable_extensions', '_better_code_editing_filter_editable_extensions' ); 
     10add_filter( 'wp_theme_editor_filetypes', '_better_code_editing_filter_editable_extensions' ); 
    911add_action( 'admin_enqueue_scripts', '_better_code_editing_admin_enqueue_scripts_for_file_editor' ); 
     12 
     13/** 
     14 * Add extensions that are editable. 
     15 * 
     16 * @param array $extensions Extensions. 
     17 * @return array Merged extensions. 
     18 */ 
     19function _better_code_editing_filter_editable_extensions( $extensions ) { 
     20    return array_merge( $extensions, array( 
     21        'conf', 
     22        'css', 
     23        'diff', 
     24        'patch', 
     25        'html', 
     26        'htm', 
     27        'http', 
     28        'js', 
     29        'json', 
     30        'jsx', 
     31        'less', 
     32        'md', 
     33        'php', 
     34        'phtml', 
     35        'php3', 
     36        'php4', 
     37        'php5', 
     38        'php7', 
     39        'phps', 
     40        'scss', 
     41        'sass', 
     42        'sh', 
     43        'bash', 
     44        'sql', 
     45        'svg', 
     46        'xml', 
     47        'yml', 
     48        'yaml', 
     49        'txt', 
     50    ) ); 
     51} 
    1052 
    1153/** 
     
    5799    } 
    58100 
    59     wp_enqueue_script( 'jquery-ui-core' ); // For :tabbable pseudo-selector. 
    60101    wp_enqueue_code_editor( $settings ); 
     102    wp_enqueue_script( 'wp-theme-plugin-editor' ); 
    61103 
    62     ob_start(); 
    63     ?> 
    64     <script> 
    65         jQuery( function( $ ) { 
    66             var settings = {}; 
    67             settings = <?php echo wp_json_encode( $settings ); ?>; 
    68             settings.handleTabPrev = function() { 
    69                 $( '#templateside' ).find( ':tabbable' ).last().focus(); 
    70             }; 
    71             settings.handleTabNext = function() { 
    72                 $( '#template' ).find( ':tabbable:not(.CodeMirror-code)' ).first().focus(); 
    73             }; 
    74             wp.codeEditor.initialize( $( '#newcontent' ), settings ); 
    75         } ); 
    76         </script> 
    77     <?php 
    78     wp_add_inline_script( 'code-editor', str_replace( array( '<script>', '</script>' ), '', ob_get_clean() ) ); 
     104    $l10n = wp_array_slice_assoc( 
     105        /* translators: placeholder is error count */ 
     106        _n_noop( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.', 'better-code-editing' ), 
     107        array( 'singular', 'plural' ) 
     108    ); 
     109    wp_add_inline_script( 'wp-theme-plugin-editor', sprintf( 'wp.themePluginEditor.l10n = %s;', wp_json_encode( $l10n ) ) ); 
     110    wp_add_inline_script( 'wp-theme-plugin-editor', sprintf( 'jQuery( function() { wp.themePluginEditor.init( %s ); } )', wp_json_encode( $settings ) ) ); 
    79111} 
  • better-code-editing/trunk/wp-admin/js/code-editor.js

    r1720408 r1722335  
    6969        instanceSettings.codemirror = $.extend( {}, instanceSettings.codemirror ); 
    7070 
    71         if ( true === instanceSettings.codemirror.lint ) { 
     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            } 
    7281 
    7382            // Configure JSHint. 
    74             if ( 'text/javascript' === instanceSettings.codemirror.mode && true === instanceSettings.codemirror.lint && instanceSettings.jshint && instanceSettings.jshint.rules ) { 
    75                 instanceSettings.codemirror.lint = instanceSettings.jshint.rules; 
     83            if ( 'javascript' === instanceSettings.codemirror.mode && instanceSettings.jshint && instanceSettings.jshint.rules ) { 
     84                instanceSettings.codemirror.lint.options = $.extend( {}, instanceSettings.jshint.rules, instanceSettings.codemirror.lint.options ); 
    7685            } 
    7786 
    7887            // Configure HTMLHint. 
    79             if ( 'htmlmixed' === instanceSettings.codemirror.mode && true === instanceSettings.codemirror.lint && instanceSettings.htmlhint && instanceSettings.htmlhint.rules ) { 
    80                 instanceSettings.codemirror.lint = $.extend( {}, instanceSettings.htmlhint ); 
     88            if ( 'htmlmixed' === instanceSettings.codemirror.mode && instanceSettings.htmlhint && instanceSettings.htmlhint.rules ) { 
     89                instanceSettings.codemirror.lint.options = $.extend( {}, instanceSettings.htmlhint, instanceSettings.codemirror.lint.options ); 
    8190 
    8291                if ( instanceSettings.jshint && instanceSettings.jshint.rules ) { 
    83                     instanceSettings.codemirror.lint.rules.jshint = instanceSettings.jshint.rules; 
     92                    instanceSettings.codemirror.lint.options.rules.jshint = $.extend( {}, instanceSettings.jshint.rules, instanceSettings.codemirror.lint.options.rules.jshint ); 
    8493                } 
    8594                if ( instanceSettings.csslint && instanceSettings.csslint.rules ) { 
    86                     instanceSettings.codemirror.lint.rules.csslint = instanceSettings.csslint.rules; 
     95                    instanceSettings.codemirror.lint.options.rules.csslint = $.extend( {}, instanceSettings.csslint.rules, instanceSettings.codemirror.lint.options.rules.csslint ); 
    8796                } 
    8897            } 
  • better-code-editing/trunk/wp-admin/js/customize-controls-addendum.js

    r1720408 r1722335  
    1212            } 
    1313 
    14             // Workaround for disabling server-sent syntax checking notifications. 
    15             // @todo Listen for errors in CodeMirror and opt-to add invalidity notifications for them? The presence of such notification error allows saving to be blocked. 
     14            // Workaround for disabling server-sent syntax checking notifications. This can be removed from core in the merge. 
    1615            control.setting.notifications.add = (function( originalAdd ) { // eslint-disable-line max-nested-callbacks 
    1716                return function( id, notification ) { // eslint-disable-line max-nested-callbacks 
     
    1918                        return null; 
    2019                    } else { 
    21                         return originalAdd( id, notification ); 
     20                        return originalAdd.call( this, id, notification ); 
    2221                    } 
    2322                }; 
    24             })( control.setting.notifications ); 
     23            })( control.setting.notifications.add ); 
     24 
     25            // Make sure editor gets focused when control is focused. 
     26            control.focus = (function( originalFocus ) { // eslint-disable-line max-nested-callbacks 
     27                return function( params ) { // eslint-disable-line max-nested-callbacks 
     28                    var extendedParams = _.extend( {}, params ), originalCompleteCallback; 
     29                    originalCompleteCallback = extendedParams.completeCallback; 
     30                    extendedParams.completeCallback = function() { 
     31                        if ( originalCompleteCallback ) { 
     32                            originalCompleteCallback(); 
     33                        } 
     34                        if ( control.editor ) { 
     35                            control.editor.focus(); 
     36                        } 
     37                    }; 
     38                    originalFocus.call( this, extendedParams ); 
     39                }; 
     40            })( control.focus ); 
    2541 
    2642            onceExpanded = function() { 
    27                 var $textarea = control.container.find( 'textarea' ); 
     43                var $textarea = control.container.find( 'textarea' ), settings, previousErrorCount = 0, currentErrorAnnotations = []; 
    2844 
    29                 control.editor = wp.codeEditor.initialize( $textarea, _.extend( {}, api.settings.codeEditor, { 
     45                settings = _.extend( {}, api.settings.codeEditor, { 
    3046                    handleTabNext: function() { 
    3147                        var controls, controlIndex; 
     
    4864                        } 
    4965                    } 
    50                 } ) ); 
     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                } 
     119 
     120                control.editor = wp.codeEditor.initialize( $textarea, settings ); 
    51121 
    52122                // Refresh when receiving focus. 
    53123                control.editor.on( 'focus', function( editor ) { 
    54124                    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(); 
    55133                }); 
    56134 
  • better-code-editing/trunk/wp-admin/js/widgets/custom-html-widgets.js

    r1720408 r1722335  
    11/* global wp */ 
    22/* eslint consistent-this: [ "error", "control" ] */ 
     3/* eslint no-magic-numbers: ["error", { "ignore": [0,1,-1] }] */ 
    34wp.customHtmlWidgets = ( function( $ ) { 
    45    'use strict'; 
     
    67    var component = { 
    78        idBases: [ 'custom_html' ], 
    8         codeEditorSettings: {} 
     9        codeEditorSettings: {}, 
     10        l10n: { 
     11            errorNotice: { 
     12                singular: '', 
     13                plural: '' 
     14            } 
     15        } 
    916    }; 
    1017 
     
    4552            Backbone.View.prototype.initialize.call( control, options ); 
    4653            control.syncContainer = options.syncContainer; 
     54            control.widgetIdBase = control.syncContainer.parent().find( '.id_base' ).val(); 
     55            control.widgetNumber = control.syncContainer.parent().find( '.widget_number' ).val(); 
     56            control.customizeSettingId = 'widget_' + control.widgetIdBase + '[' + String( control.widgetNumber ) + ']'; 
    4757 
    4858            control.$el.addClass( 'custom-html-widget-fields' ); 
    4959            control.$el.html( wp.template( 'widget-custom-html-control-fields' )( { codeEditorDisabled: component.codeEditorSettings.disabled } ) ); 
     60 
     61            control.errorNoticeContainer = control.$el.find( '.code-editor-error-container' ); 
     62            control.currentErrorAnnotations = []; 
     63            control.previousErrorCount = 0; 
     64            control.saveButton = control.syncContainer.add( control.syncContainer.parent().find( '.widget-control-actions' ) ).find( '.widget-control-save, #savewidget' ); 
     65            control.saveButton.addClass( 'custom-html-widget-save-button' ); // To facilitate style targeting. 
    5066 
    5167            control.fields = { 
     
    86102            } 
    87103 
    88             control.contentUpdateBypassed = control.fields.content.is( document.activeElement ) || control.editor && control.editor.state.focused; 
     104            /* 
     105             * Prevent updating content when the editor is focused or if there are current error annotations, 
     106             * to prevent the editor's contents from getting sanitized as soon as a user removes focus from 
     107             * the editor. This is particularly important for users who cannot unfiltered_html. 
     108             */ 
     109            control.contentUpdateBypassed = control.fields.content.is( document.activeElement ) || control.editor && control.editor.state.focused || 0 !== control.currentErrorAnnotations; 
    89110            if ( ! control.contentUpdateBypassed ) { 
    90111                syncInput = control.syncContainer.find( '.sync-input.content' ); 
     
    94115 
    95116        /** 
     117         * Show linting error notice. 
     118         * 
     119         * @returns {void} 
     120         */ 
     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 ) { 
     132                message = component.l10n.errorNotice.singular.replace( '%d', '1' ); 
     133            } else { 
     134                message = component.l10n.errorNotice.plural.replace( '%d', String( control.currentErrorAnnotations.length ) ); 
     135            } 
     136 
     137            if ( wp.customize && wp.customize.has( control.customizeSettingId ) ) { 
     138                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', { 
     142                        message: message, 
     143                        type: 'error' 
     144                    } ) ); 
     145                } 
     146            } else if ( 0 !== control.currentErrorAnnotations.length ) { 
     147                errorNotice = $( '<div class="inline notice notice-error notice-alt"></div>' ); 
     148                errorNotice.append( $( '<p></p>', { 
     149                    text: message 
     150                } ) ); 
     151                control.errorNoticeContainer.empty(); 
     152                control.errorNoticeContainer.append( errorNotice ); 
     153                control.errorNoticeContainer.slideDown( 'fast' ); 
     154                wp.a11y.speak( message ); 
     155            } else { 
     156                control.errorNoticeContainer.slideUp( 'fast' ); 
     157            } 
     158        }, 
     159 
     160        /** 
    96161         * Initialize editor. 
    97162         * 
     
    99164         */ 
    100165        initializeEditor: function initializeEditor() { 
    101             var control = this; 
     166            var control = this, settings; 
    102167 
    103168            if ( component.codeEditorSettings.disabled ) { 
     
    105170            } 
    106171 
    107             control.editor = wp.codeEditor.initialize( 
    108                 control.fields.content, 
    109                 _.extend( {}, component.codeEditorSettings, { 
    110                     handleTabPrev: function() { 
    111                         control.fields.title.focus(); 
    112                     }, 
    113                     handleTabNext: function() { 
    114                         var tabbables = control.syncContainer.add( control.syncContainer.parent().find( '.widget-position, .widget-control-actions' ) ).find( ':tabbable' ); 
    115                         tabbables.first().focus(); 
     172            settings = _.extend( {}, component.codeEditorSettings, { 
     173                handleTabPrev: function() { 
     174                    control.fields.title.focus(); 
     175                }, 
     176                handleTabNext: function() { 
     177                    var tabbables = control.syncContainer.add( control.syncContainer.parent().find( '.widget-position, .widget-control-actions' ) ).find( ':tabbable' ); 
     178                    tabbables.first().focus(); 
     179                } 
     180            }); 
     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                        } 
    116201                    } 
    117                 }) 
    118             ); 
     202                }); 
     203            } 
     204 
     205            control.editor = wp.codeEditor.initialize( control.fields.content, settings ); 
    119206            control.fields.content.on( 'change', function() { 
    120207                if ( this.value !== control.editor.getValue() ) { 
     
    128215                } 
    129216            }); 
     217 
     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            } 
    130227 
    131228            // 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. 
  • better-code-editing/trunk/wp-includes/customize-manager-addendum.php

    r1720408 r1722335  
    2929    } 
    3030 
    31     $section->description = sprintf( '%s<br /><a href="%s" class="external-link" target="_blank">%s<span class="screen-reader-text">%s</span></a>', 
    32         sprintf( 
    33             /* translators: placeholder is profile URL */ 
    34             __( 'CSS allows you to customize the appearance and layout of your site with code. Separate CSS is saved for each of your themes. In the editing area the Tab key enters a tab character. To move keyboard focus to another element, press the Esc key followed by the Tab key for the next element or Shift+Tab key for the previous element. You can disable the code syntax highlighter in your <a href="%s" target="blank" class="external-link">user profile</a>. This will allow you to work in plain text mode.', 'better-code-editing' ), 
    35             esc_url( get_edit_profile_url() . '#syntax_highlighting' ) 
    36         ), 
     31    $section->description = '<p>'; 
     32    $section->description .= __( 'Add your own CSS code here to customize the appearance and layout of your site.', 'better-code-editing' ); 
     33    $section->description .= sprintf( 
     34        ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text">%3$s</span></a>', 
    3735        esc_url( __( 'https://codex.wordpress.org/CSS', 'default' ) ), 
    3836        __( 'Learn more about CSS', 'default' ), 
     
    4038        __( '(opens in a new window)', 'default' ) 
    4139    ); 
     40    $section->description .= '</p>'; 
     41 
     42    $section->description .= '<p>' . __( 'When using a keyboard to navigate:', 'better-code-editing' ) . '</p>'; 
     43    $section->description .= '<ul>'; 
     44    $section->description .= '<li>' . __( 'In the CSS edit field, Tab enters a tab character.', 'better-code-editing' ) . '</li>'; 
     45    $section->description .= '<li>' . __( 'To move keyboard focus, press Esc then Tab for the next element, or Esc then Shift+Tab for the previous element.', 'better-code-editing' ) . '</li>'; 
     46    $section->description .= '</ul>'; 
     47 
     48    $section->description .= '<p>'; 
     49    $section->description .= sprintf( 
     50        /* 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' ), 
     52        sprintf( 
     53            ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text">%3$s</span></a>', 
     54            esc_url( get_edit_profile_url() . '#syntax_highlighting' ), 
     55            __( 'user profile', 'better-code-editing' ), 
     56            /* translators: accessibility text */ 
     57            __( '(opens in a new window)', 'default' ) 
     58        ) 
     59    ); 
     60    $section->description .= '</p>'; 
    4261} 
    4362 
     
    6382function _better_code_editing_amend_customize_pane_settings() { 
    6483    global $wp_customize; 
    65     if ( ! empty( $wp_customize->custom_css_code_editor_settings ) ) { 
    66         printf( '<script>window._wpCustomizeSettings.codeEditor = %s</script>;', wp_json_encode( $wp_customize->custom_css_code_editor_settings ) ); 
     84    if ( empty( $wp_customize->custom_css_code_editor_settings ) ) { 
     85        return; 
    6786    } 
     87    printf( '<script>window._wpCustomizeSettings.codeEditor = %s</script>;', wp_json_encode( $wp_customize->custom_css_code_editor_settings ) ); 
     88 
     89    /* translators: placeholder is error count */ 
     90    $l10n = _n_noop( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.', 'better-code-editing' ); 
     91    printf( '<script>window._wpCustomizeControlsL10n.customCssErrorNotice = %s</script>;', wp_json_encode( wp_array_slice_assoc( $l10n, array( 'singular', 'plural' ) ) ) ); 
    6892} 
  • better-code-editing/trunk/wp-includes/general-template-addendum.php

    r1720408 r1722335  
    1212 * @since 4.9.0 
    1313 * 
    14  * @param array $context Context. 
     14 * @param array $context { 
     15 *     Context. 
     16 * 
     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 * } 
    1520 * @return array|false Settings for code editor or false if disabled. 
    1621 */ 
     
    96101 
    97102    $type = ''; 
    98     $extension = ''; 
    99     if ( isset( $context['file'] ) && false !== strpos( basename( $context['file'] ), '.' ) ) { 
     103    if ( isset( $context['type'] ) ) { 
     104        $type = $context['type']; 
     105 
     106        // Remap MIME types to ones that CodeMirror modes will recognize. 
     107        if ( 'application/x-patch' === $type || 'text/x-patch' === $type ) { 
     108            $type = 'text/x-diff'; 
     109        } 
     110    } elseif ( isset( $context['file'] ) && false !== strpos( basename( $context['file'] ), '.' ) ) { 
    100111        $extension = strtolower( pathinfo( $context['file'], PATHINFO_EXTENSION ) ); 
    101         if ( ! empty( $extension ) ) { 
    102             foreach ( wp_get_mime_types() as $exts => $mime ) { 
    103                 if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) { 
    104                     $type = $mime; 
    105                     break; 
    106                 } 
     112        foreach ( wp_get_mime_types() as $exts => $mime ) { 
     113            if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) { 
     114                $type = $mime; 
     115                break; 
    107116            } 
    108117        } 
    109     } 
    110     if ( empty( $extension ) ) { 
    111         _doing_it_wrong( __FUNCTION__, __( 'Missing valid "file" name in supplied context array.', 'better-code-editing' ), '4.9.0' ); 
    112     } 
    113  
    114     if ( 'text/css' === $type || in_array( $extension, array( 'sass', 'scss', 'less' ), true ) ) { 
    115         $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
    116             'mode' => 'text/css', 
     118 
     119        // Supply any types that are not matched by wp_get_mime_types(). 
     120        if ( empty( $type ) ) { 
     121            switch ( $extension ) { 
     122                case 'conf': 
     123                    $type = 'text/nginx'; 
     124                    break; 
     125                case 'css': 
     126                    $type = 'text/css'; 
     127                    break; 
     128                case 'diff': 
     129                case 'patch': 
     130                    $type = 'text/x-diff'; 
     131                    break; 
     132                case 'html': 
     133                case 'htm': 
     134                    $type = 'text/html'; 
     135                    break; 
     136                case 'http': 
     137                    $type = 'message/http'; 
     138                    break; 
     139                case 'js': 
     140                    $type = 'text/javascript'; 
     141                    break; 
     142                case 'json': 
     143                    $type = 'application/json'; 
     144                    break; 
     145                case 'jsx': 
     146                    $type = 'text/jsx'; 
     147                    break; 
     148                case 'less': 
     149                    $type = 'text/x-less'; 
     150                    break; 
     151                case 'md': 
     152                    $type = 'text/x-gfm'; 
     153                    break; 
     154                case 'php': 
     155                case 'phtml': 
     156                case 'php3': 
     157                case 'php4': 
     158                case 'php5': 
     159                case 'php7': 
     160                case 'phps': 
     161                    $type = 'application/x-httpd-php'; 
     162                    break; 
     163                case 'scss': 
     164                    $type = 'text/x-scss'; 
     165                    break; 
     166                case 'sass': 
     167                    $type = 'text/x-sass'; 
     168                    break; 
     169                case 'sh': 
     170                case 'bash': 
     171                    $type = 'text/x-sh'; 
     172                    break; 
     173                case 'sql': 
     174                    $type = 'text/x-sql'; 
     175                    break; 
     176                case 'svg': 
     177                    $type = 'application/svg+xml'; 
     178                    break; 
     179                case 'xml': 
     180                    $type = 'text/xml'; 
     181                    break; 
     182                case 'yml': 
     183                case 'yaml': 
     184                    $type = 'text/x-yaml'; 
     185                    break; 
     186                case 'txt': 
     187                default: 
     188                    $type = 'text/plain'; 
     189                    break; 
     190            } 
     191        } 
     192    } 
     193 
     194    if ( 'text/css' === $type ) { 
     195        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     196            'mode' => 'css', 
    117197            'lint' => true, 
    118198            'autoCloseBrackets' => true, 
    119199            'matchBrackets' => true, 
    120200        ) ); 
    121     } elseif ( in_array( $extension, array( 'php', 'phtml', 'php3', 'php4', 'php5', 'php7', 'phps' ), true ) ) { 
    122         $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
    123             'mode' => 'application/x-httpd-php', 
    124             'autoCloseBrackets' => true, 
    125             'autoCloseTags' => true, 
    126             'matchBrackets' => true, 
    127             'matchTags' => array( 
    128                 'bothTags' => true, 
    129             ), 
    130         ) ); 
    131     } elseif ( 'application/javascript' === $type ) { 
    132         $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
    133             'mode' => 'text/javascript', 
    134             'lint' => true, 
    135             'autoCloseBrackets' => true, 
    136             'matchBrackets' => true, 
     201    } elseif ( 'text/x-scss' === $type || 'text/x-less' === $type || 'text/x-sass' === $type ) { 
     202        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     203            'mode' => $type, 
     204            'autoCloseBrackets' => true, 
     205            'matchBrackets' => true, 
     206        ) ); 
     207    } elseif ( 'text/x-diff' === $type ) { 
     208        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     209            'mode' => 'diff', 
    137210        ) ); 
    138211    } elseif ( 'text/html' === $type ) { 
     
    150223            $settings['htmlhint']['rules']['kses'] = wp_kses_allowed_html( 'post' ); 
    151224        } 
    152     } elseif ( false !== strpos( $type, 'xml' ) || in_array( $extension, array( 'xml', 'svg' ), true ) ) { 
    153         $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
    154             'mode' => 'application/xml', 
     225    } elseif ( 'text/x-gfm' === $type ) { 
     226        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     227            'mode' => 'gfm', 
     228            'highlightFormatting' => true, 
     229            'showTrailingSpace' => false, // GitHub-flavored markdown uses trailing spaces as a feature. 
     230        ) ); 
     231    } elseif ( 'application/javascript' === $type || 'text/javascript' === $type ) { 
     232        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     233            'mode' => 'javascript', 
     234            'lint' => true, 
     235            'autoCloseBrackets' => true, 
     236            'matchBrackets' => true, 
     237        ) ); 
     238    } elseif ( false !== strpos( $type, 'json' ) ) { 
     239        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     240            'mode' => array( 
     241                'name' => 'javascript', 
     242            ), 
     243            'lint' => true, 
     244            'autoCloseBrackets' => true, 
     245            'matchBrackets' => true, 
     246        ) ); 
     247        if ( 'application/ld+json' === $type ) { 
     248            $settings['codemirror']['mode']['jsonld'] = true; 
     249        } else { 
     250            $settings['codemirror']['mode']['json'] = true; 
     251        } 
     252    } elseif ( false !== strpos( $type, 'jsx' ) ) { 
     253        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     254            'mode' => 'jsx', 
     255            'autoCloseBrackets' => true, 
     256            'matchBrackets' => true, 
     257        ) ); 
     258    } elseif ( 'text/x-markdown' === $type ) { 
     259        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     260            'mode' => 'markdown', 
     261            'highlightFormatting' => true, 
     262        ) ); 
     263    } elseif ( 'text/nginx' === $type ) { 
     264        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     265            'mode' => 'nginx', 
     266        ) ); 
     267    } elseif ( 'application/x-httpd-php' === $type ) { 
     268        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     269            'mode' => 'php', 
     270            'autoCloseBrackets' => true, 
     271            'autoCloseTags' => true, 
     272            'matchBrackets' => true, 
     273            'matchTags' => array( 
     274                'bothTags' => true, 
     275            ), 
     276        ) ); 
     277    } elseif ( 'text/x-sql' === $type || 'text/x-mysql' === $type ) { 
     278        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     279            'mode' => 'sql', 
     280            'autoCloseBrackets' => true, 
     281            'matchBrackets' => true, 
     282        ) ); 
     283    } elseif ( false !== strpos( $type, 'xml' ) ) { 
     284        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     285            'mode' => 'xml', 
    155286            'autoCloseBrackets' => true, 
    156287            'autoCloseTags' => true, 
     
    159290            ), 
    160291        ) ); 
     292    } elseif ( 'text/x-yaml' === $type ) { 
     293        $settings['codemirror'] = array_merge( $settings['codemirror'], array( 
     294            'mode' => 'yaml', 
     295        ) ); 
    161296    } else { 
    162         $settings['codemirror']['mode'] = 'text/plain'; 
     297        $settings['codemirror']['mode'] = $type; 
    163298    } 
    164299 
     
    204339    wp_enqueue_script( 'code-editor' ); 
    205340    wp_enqueue_style( 'code-editor' ); 
     341 
     342    // @todo All of the following could be done in JS instead, similar to the post Editor? 
    206343    wp_enqueue_script( 'codemirror' ); 
    207344    wp_enqueue_style( 'codemirror' ); 
    208     if ( ! empty( $settings['codemirror']['showTrailingSpace'] ) ) { 
    209         wp_enqueue_script( 'codemirror-addon-edit-trailingspace' ); 
    210     } 
    211     if ( ! empty( $settings['codemirror']['styleActiveLine'] ) ) { 
    212         wp_enqueue_script( 'codemirror-addon-selection-active-line' ); 
    213     } 
    214     if ( ! empty( $settings['codemirror']['autoCloseBrackets'] ) ) { 
    215         wp_enqueue_script( 'codemirror-addon-edit-closebrackets' ); 
    216     } 
    217     if ( ! empty( $settings['codemirror']['matchBrackets'] ) ) { 
    218         wp_enqueue_script( 'codemirror-addon-edit-matchbrackets' ); 
    219     } 
    220     if ( ! empty( $settings['codemirror']['autoCloseTags'] ) ) { 
    221         wp_enqueue_script( 'codemirror-addon-edit-closetag' ); 
    222     } 
    223     if ( ! empty( $settings['codemirror']['matchTags'] ) ) { 
    224         wp_enqueue_script( 'codemirror-addon-edit-matchtags' ); 
    225     } 
    226     if ( ! empty( $settings['codemirror']['continueComments'] ) ) { 
    227         wp_enqueue_script( 'codemirror-addon-comment-continuecomment' ); 
     345 
     346    // Enqueue addons. 
     347    $option_asset_mappings = array( 
     348        'showTrailingSpace' => array( 'codemirror-addon-edit-trailingspace' ), 
     349        'styleActiveLine'   => array( 'codemirror-addon-selection-active-line' ), 
     350        'autoCloseBrackets' => array( 'codemirror-addon-edit-closebrackets' ), 
     351        'matchBrackets'     => array( 'codemirror-addon-edit-matchbrackets' ), 
     352        'autoCloseTags'     => array( 'codemirror-addon-edit-closetag' ), 
     353        'matchTags'         => array( 'codemirror-addon-edit-matchtags' ), 
     354        'continueComments'  => array( 'codemirror-addon-comment-continuecomment' ), 
     355        // @todo Add recognition for all of the addon configs. 
     356    ); 
     357    foreach ( $option_asset_mappings as $option => $handles ) { 
     358        if ( ! empty( $settings['codemirror'][ $option ] ) ) { 
     359            foreach ( $handles as $handle ) { 
     360                wp_enqueue_script( $handle ); 
     361            } 
     362        } 
    228363    } 
    229364    wp_enqueue_script( 'codemirror-addon-comment' ); 
    230365 
    231366    if ( isset( $settings['codemirror']['mode'] ) ) { 
    232         switch ( $settings['codemirror']['mode'] ) { 
     367        $mode = $settings['codemirror']['mode']; 
     368        if ( is_string( $mode ) ) { 
     369            $mode = array( 
     370                'name' => $mode, 
     371            ); 
     372        } 
     373 
     374        switch ( $mode['name'] ) { 
     375            case 'css': 
     376            case 'text/css': 
     377            case 'text/x-scss': 
     378            case 'text/x-less': 
     379                wp_enqueue_script( 'codemirror-mode-css' ); 
     380                wp_enqueue_script( 'codemirror-addon-hint-css' ); 
     381                wp_enqueue_style( 'codemirror-addon-show-hint' ); 
     382 
     383                if ( ! empty( $settings['codemirror']['lint'] ) ) { 
     384                    wp_enqueue_script( 'codemirror-addon-lint-css' ); 
     385                } 
     386                break; 
     387            case 'diff': 
     388            case 'text/x-diff': 
     389                wp_enqueue_script( 'codemirror-mode-diff' ); 
     390                break; 
     391            case 'gfm': 
     392            case 'text/x-gfm': 
     393                wp_enqueue_script( 'codemirror-mode-gfm' ); 
     394                break; 
     395            case 'htmlmixed': 
     396            case 'text/html': 
     397            case 'php': 
    233398            case 'application/x-httpd-php': 
    234                 wp_enqueue_script( 'codemirror-mode-php' ); 
    235                 wp_enqueue_script( 'codemirror-addon-hint-show' ); 
    236                 /* falls through */ 
    237             case 'htmlmixed': 
    238                 wp_enqueue_script( 'codemirror-mode-html' ); 
     399            case 'text/x-php': 
     400                if ( false !== strpos( $mode['name'], 'php' ) ) { 
     401                    wp_enqueue_script( 'codemirror-mode-php' ); 
     402                } 
     403 
     404                wp_enqueue_script( 'codemirror-mode-htmlmixed' ); 
    239405                wp_enqueue_script( 'codemirror-addon-hint-html' ); 
    240406                wp_enqueue_script( 'codemirror-addon-hint-javascript' ); 
     
    249415                } 
    250416                break; 
    251             case 'text/javascript': 
     417            case 'http': 
     418            case 'message/http': 
     419                wp_enqueue_script( 'codemirror-mode-http' ); 
     420                break; 
     421            case 'javascript': 
     422            case 'application/ecmascript': 
     423            case 'application/json': 
     424            case 'application/javascript': 
     425            case 'application/ld+json': 
     426            case 'text/typescript': 
     427            case 'application/typescript': 
    252428                wp_enqueue_script( 'codemirror-mode-javascript' ); 
    253429                wp_enqueue_script( 'codemirror-addon-hint-javascript' ); 
     
    255431 
    256432                if ( ! empty( $settings['codemirror']['lint'] ) ) { 
    257                     wp_enqueue_script( 'codemirror-addon-lint-javascript' ); 
     433                    if ( ! empty( $mode['json'] ) || ! empty( $mode['jsonld'] ) ) { 
     434                            wp_enqueue_script( 'codemirror-addon-lint-json' ); 
     435                    } else { 
     436                        wp_enqueue_script( 'codemirror-addon-lint-javascript' ); 
     437                    } 
    258438                } 
    259439                break; 
     440            case 'jsx': 
     441            case 'text/jsx': 
     442            case 'text/typescript-jsx': 
     443                wp_enqueue_script( 'codemirror-mode-jsx' ); 
     444                break; 
     445            case 'markdown': 
     446            case 'text/x-markdown': 
     447                wp_enqueue_script( 'codemirror-mode-markdown' ); 
     448                break; 
     449            case 'nginx': 
     450            case 'text/nginx': 
     451                wp_enqueue_script( 'codemirror-mode-nginx' ); 
     452                break; 
     453            case 'sass': 
     454            case 'text/x-sass': 
     455                wp_enqueue_script( 'codemirror-mode-sass' ); 
     456                break; 
     457            case 'sh': 
     458            case 'text/x-sh': 
     459            case 'application/x-sh': 
     460                wp_enqueue_script( 'codemirror-mode-shell' ); 
     461                break; 
     462            case 'sql': 
     463            case 'text/x-sql': 
     464            case 'text/x-mysql': 
     465            case 'text/x-mariadb': 
     466            case 'text/x-cassandra': 
     467            case 'text/x-plsql': 
     468            case 'text/x-mssql': 
     469            case 'text/x-hive': 
     470            case 'text/x-pgsql': 
     471            case 'text/x-gql': 
     472            case 'text/x-gpsql': 
     473                wp_enqueue_script( 'codemirror-mode-sql' ); 
     474                break; 
     475            case 'xml': 
    260476            case 'application/xml': 
     477            case 'application/svg+xml': 
    261478                wp_enqueue_script( 'codemirror-mode-xml' ); 
    262479                break; 
    263             case 'text/css': 
    264                 wp_enqueue_script( 'codemirror-mode-css' ); 
    265                 wp_enqueue_script( 'codemirror-addon-hint-css' ); 
    266                 wp_enqueue_style( 'codemirror-addon-show-hint' ); 
    267  
    268                 if ( ! empty( $settings['codemirror']['lint'] ) ) { 
    269                     wp_enqueue_script( 'codemirror-addon-lint-css' ); 
    270                 } 
     480            case 'yaml': 
     481            case 'codemirror-mode-yaml': 
     482                wp_enqueue_script( 'codemirror-mode-yaml' ); 
    271483                break; 
    272484        } 
     
    279491    wp_add_inline_script( 'code-editor', sprintf( 'jQuery.extend( wp.codeEditor.defaultSettings, %s );', wp_json_encode( $settings ) ) ); 
    280492 
     493    /** 
     494     * Fires when scripts and styles are enqueued for the code editor. 
     495     * 
     496     * @since 4.9.0 
     497     * 
     498     * @param array $settings Settings for the enqueued code editor. 
     499     */ 
     500    do_action( 'wp_enqueue_code_editor', $settings ); 
     501 
    281502    return true; 
    282503} 
  • better-code-editing/trunk/wp-includes/script-loader-addendum.php

    r1720408 r1722335  
    1919    $scripts->add( 'codemirror', plugins_url( 'wp-includes/js/codemirror/lib/codemirror.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array(), $codemirror_version ); 
    2020 
     21    $scripts->add( 'codemirror-keymap-emacs',   plugins_url( 'wp-includes/js/codemirror/keymap/emacs.js', BETTER_CODE_EDITING_PLUGIN_FILE ),   array( 'codemirror' ), $codemirror_version ); 
     22    $scripts->add( 'codemirror-keymap-sublime', plugins_url( 'wp-includes/js/codemirror/keymap/sublime.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     23    $scripts->add( 'codemirror-keymap-vim',     plugins_url( 'wp-includes/js/codemirror/keymap/vim.js', BETTER_CODE_EDITING_PLUGIN_FILE ),    array( 'codemirror' ), $codemirror_version ); 
     24 
    2125    $scripts->add( 'codemirror-addon-hint-show',       plugins_url( 'wp-includes/js/codemirror/addon/hint/show-hint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror' ), $codemirror_version ); 
     26    $scripts->add( 'codemirror-addon-hint-anyword',    plugins_url( 'wp-includes/js/codemirror/addon/hint/anyword-hint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),    array( 'codemirror' ), $codemirror_version ); 
    2227    $scripts->add( 'codemirror-addon-hint-css',        plugins_url( 'wp-includes/js/codemirror/addon/hint/css-hint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),        array( 'codemirror-addon-hint-show', 'codemirror-mode-css' ), $codemirror_version ); 
    23     $scripts->add( 'codemirror-addon-hint-html',       plugins_url( 'wp-includes/js/codemirror/addon/hint/html-hint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror-addon-hint-show', 'codemirror-addon-hint-xml', 'codemirror-mode-html' ), $codemirror_version ); 
     28    $scripts->add( 'codemirror-addon-hint-html',       plugins_url( 'wp-includes/js/codemirror/addon/hint/html-hint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror-addon-hint-show', 'codemirror-addon-hint-xml', 'codemirror-mode-htmlmixed' ), $codemirror_version ); 
    2429    $scripts->add( 'codemirror-addon-hint-javascript', plugins_url( 'wp-includes/js/codemirror/addon/hint/javascript-hint.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror-addon-hint-show', 'codemirror-mode-javascript' ), $codemirror_version ); 
    2530    $scripts->add( 'codemirror-addon-hint-sql',        plugins_url( 'wp-includes/js/codemirror/addon/hint/sql-hint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),        array( 'codemirror-addon-hint-show', 'codemirror-mode-sql' ), $codemirror_version ); 
     
    3035    $scripts->add( 'htmlhint', plugins_url( 'wp-includes/js/htmlhint.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array(), '0.9.14-xwp' ); 
    3136    $scripts->add( 'jshint',   plugins_url( 'wp-includes/js/jshint.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array(), '2.9.5' ); 
    32     $scripts->add( 'jsonlint', plugins_url( 'wp-includes/js/jsonlint.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array(), BETTER_CODE_EDITING_PLUGIN_VERSION ); // @todo Remove. 
     37    $scripts->add( 'jsonlint', plugins_url( 'wp-includes/js/jsonlint.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array(), '1.6.2' ); 
    3338 
    3439    $scripts->add( 'htmlhint-kses', plugins_url( 'wp-includes/js/htmlhint-kses.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'htmlhint' ), BETTER_CODE_EDITING_PLUGIN_VERSION ); 
     
    3843    $scripts->add( 'codemirror-addon-lint-html',       plugins_url( 'wp-includes/js/codemirror/addon/lint/html-lint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror-addon-lint', 'htmlhint', 'csslint', 'jshint' ), $codemirror_version ); 
    3944    $scripts->add( 'codemirror-addon-lint-javascript', plugins_url( 'wp-includes/js/codemirror/addon/lint/javascript-lint.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror-addon-lint', 'jshint' ), $codemirror_version ); 
    40     $scripts->add( 'codemirror-addon-lint-json',       plugins_url( 'wp-includes/js/codemirror/addon/lint/json-lint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror-addon-lint', 'jsonlint' ), $codemirror_version ); // @todo Remove. 
     45    $scripts->add( 'codemirror-addon-lint-json',       plugins_url( 'wp-includes/js/codemirror/addon/lint/json-lint.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror-addon-lint', 'jsonlint' ), $codemirror_version ); 
    4146 
    4247    $scripts->add( 'codemirror-addon-comment',                 plugins_url( 'wp-includes/js/codemirror/addon/comment/comment.js', BETTER_CODE_EDITING_PLUGIN_FILE ),         array( 'codemirror' ), $codemirror_version ); 
    4348    $scripts->add( 'codemirror-addon-comment-continuecomment', plugins_url( 'wp-includes/js/codemirror/addon/comment/continuecomment.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
    4449    $scripts->add( 'codemirror-addon-fold-xml-fold',           plugins_url( 'wp-includes/js/codemirror/addon/fold/xml-fold.js', BETTER_CODE_EDITING_PLUGIN_FILE ),           array( 'codemirror' ), $codemirror_version ); 
     50    $scripts->add( 'codemirror-addon-mode-overlay',            plugins_url( 'wp-includes/js/codemirror/addon/mode/overlay.js', BETTER_CODE_EDITING_PLUGIN_FILE ),            array( 'codemirror' ), $codemirror_version ); 
    4551 
    4652    $scripts->add( 'codemirror-addon-edit-closebrackets', plugins_url( 'wp-includes/js/codemirror/addon/edit/closebrackets.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     
    5157    $scripts->add( 'codemirror-addon-edit-trailingspace', plugins_url( 'wp-includes/js/codemirror/addon/edit/trailingspace.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
    5258 
     59    $scripts->add( 'codemirror-addon-dialog', plugins_url( 'wp-includes/js/codemirror/addon/dialog/dialog.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     60 
     61    $scripts->add( 'codemirror-addon-display-autorefresh', plugins_url( 'wp-includes/js/codemirror/addon/display/autorefresh.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     62    $scripts->add( 'codemirror-addon-display-fullscreen',  plugins_url( 'wp-includes/js/codemirror/addon/display/fullscreen.js', BETTER_CODE_EDITING_PLUGIN_FILE ),  array( 'codemirror' ), $codemirror_version ); 
     63    $scripts->add( 'codemirror-addon-display-panel',       plugins_url( 'wp-includes/js/codemirror/addon/display/panel.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror' ), $codemirror_version ); 
     64    $scripts->add( 'codemirror-addon-display-placeholder', plugins_url( 'wp-includes/js/codemirror/addon/display/placeholder.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     65    $scripts->add( 'codemirror-addon-display-rulers',      plugins_url( 'wp-includes/js/codemirror/addon/display/rulers.js', BETTER_CODE_EDITING_PLUGIN_FILE ),      array( 'codemirror' ), $codemirror_version ); 
     66 
     67    $scripts->add( 'codemirror-addon-fold-brace-fold',    plugins_url( 'wp-includes/js/codemirror/addon/fold/brace-fold.js', BETTER_CODE_EDITING_PLUGIN_FILE ),    array( 'codemirror' ), $codemirror_version ); 
     68    $scripts->add( 'codemirror-addon-fold-comment-fold',  plugins_url( 'wp-includes/js/codemirror/addon/fold/comment-fold.js', BETTER_CODE_EDITING_PLUGIN_FILE ),  array( 'codemirror' ), $codemirror_version ); 
     69    $scripts->add( 'codemirror-addon-fold-foldcode',      plugins_url( 'wp-includes/js/codemirror/addon/fold/foldcode.js', BETTER_CODE_EDITING_PLUGIN_FILE ),      array( 'codemirror' ), $codemirror_version ); 
     70    $scripts->add( 'codemirror-addon-fold-foldgutter',    plugins_url( 'wp-includes/js/codemirror/addon/fold/foldgutter.js', BETTER_CODE_EDITING_PLUGIN_FILE ),    array( 'codemirror' ), $codemirror_version ); 
     71    $scripts->add( 'codemirror-addon-fold-indent-fold',   plugins_url( 'wp-includes/js/codemirror/addon/fold/indent-fold.js', BETTER_CODE_EDITING_PLUGIN_FILE ),   array( 'codemirror' ), $codemirror_version ); 
     72    $scripts->add( 'codemirror-addon-fold-markdown-fold', plugins_url( 'wp-includes/js/codemirror/addon/fold/markdown-fold.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     73 
     74    $scripts->add( 'codemirror-addon-merge', plugins_url( 'wp-includes/js/codemirror/addon/merge/merge.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     75 
     76    $scripts->add( 'codemirror-addon-mode-loadmode',  plugins_url( 'wp-includes/js/codemirror/addon/mode/loadmode.js', BETTER_CODE_EDITING_PLUGIN_FILE ),  array( 'codemirror' ), $codemirror_version ); 
     77    $scripts->add( 'codemirror-addon-mode-multiplex', plugins_url( 'wp-includes/js/codemirror/addon/mode/multiplex.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     78    $scripts->add( 'codemirror-addon-mode-simple',    plugins_url( 'wp-includes/js/codemirror/addon/mode/simple.js', BETTER_CODE_EDITING_PLUGIN_FILE ),    array( 'codemirror' ), $codemirror_version ); 
     79 
     80    $scripts->add( 'codemirror-addon-runmode',                    plugins_url( 'wp-includes/js/codemirror/addon/runmode/runmode.js', BETTER_CODE_EDITING_PLUGIN_FILE ),            array( 'codemirror' ), $codemirror_version ); 
     81    $scripts->add( 'codemirror-addon-runmode-colorize',           plugins_url( 'wp-includes/js/codemirror/addon/runmode/colorize.js', BETTER_CODE_EDITING_PLUGIN_FILE ),           array( 'codemirror' ), $codemirror_version ); 
     82    $scripts->add( 'codemirror-addon-runmode-runmode-standalone', plugins_url( 'wp-includes/js/codemirror/addon/runmode/runmode-standalone.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     83 
     84    $scripts->add( 'codemirror-addon-scroll-annotatescrollbar', plugins_url( 'wp-includes/js/codemirror/addon/scroll/annotatescrollbar.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     85    $scripts->add( 'codemirror-addon-scroll-scrollpastend'    , plugins_url( 'wp-includes/js/codemirror/addon/scroll/scrollpastend.js', BETTER_CODE_EDITING_PLUGIN_FILE ),     array( 'codemirror' ), $codemirror_version ); 
     86    $scripts->add( 'codemirror-addon-scroll-simplescrollbars',  plugins_url( 'wp-includes/js/codemirror/addon/scroll/simplescrollbars.js', BETTER_CODE_EDITING_PLUGIN_FILE ),  array( 'codemirror' ), $codemirror_version ); 
     87 
     88    $scripts->add( 'codemirror-addon-search',                    plugins_url( 'wp-includes/js/codemirror/addon/search/search.js', BETTER_CODE_EDITING_PLUGIN_FILE ),             array( 'codemirror' ), $codemirror_version ); 
     89    $scripts->add( 'codemirror-addon-search-jump-to-line',       plugins_url( 'wp-includes/js/codemirror/addon/search/jump-to-line.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror' ), $codemirror_version ); 
     90    $scripts->add( 'codemirror-addon-search-match-highlighter',  plugins_url( 'wp-includes/js/codemirror/addon/search/match-highlighter.js', BETTER_CODE_EDITING_PLUGIN_FILE ),  array( 'codemirror' ), $codemirror_version ); 
     91    $scripts->add( 'codemirror-addon-search-matchesonscrollbar', plugins_url( 'wp-includes/js/codemirror/addon/search/matchesonscrollbar.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     92    $scripts->add( 'codemirror-addon-search-searchcursor',       plugins_url( 'wp-includes/js/codemirror/addon/search/searchcursor.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror' ), $codemirror_version ); 
     93 
     94    $scripts->add( 'codemirror-addon-tern',        plugins_url( 'wp-includes/js/codemirror/addon/tern/tern.js', BETTER_CODE_EDITING_PLUGIN_FILE ),   array( 'codemirror' ), $codemirror_version ); 
     95    $scripts->add( 'codemirror-addon-tern-worker', plugins_url( 'wp-includes/js/codemirror/addon/tern/worker.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     96 
     97    $scripts->add( 'codemirror-addon-wrap-hardwrap', plugins_url( 'wp-includes/js/codemirror/addon/wrap/hardwrap.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     98 
    5399    $scripts->add( 'codemirror-addon-selection-active-line',    plugins_url( 'wp-includes/js/codemirror/addon/selection/active-line.js', BETTER_CODE_EDITING_PLUGIN_FILE ),       array( 'codemirror' ), $codemirror_version ); 
    54100    $scripts->add( 'codemirror-addon-selection-mark-selection', plugins_url( 'wp-includes/js/codemirror/addon/selection/mark-selection.js', BETTER_CODE_EDITING_PLUGIN_FILE ),    array( 'codemirror' ), $codemirror_version ); 
    55101    $scripts->add( 'codemirror-addon-selection-pointer',        plugins_url( 'wp-includes/js/codemirror/addon/selection/selection-pointer.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
    56102 
     103    $scripts->add( 'codemirror-mode-meta',       plugins_url( 'wp-includes/js/codemirror/mode/meta.js', BETTER_CODE_EDITING_PLUGIN_FILE ),                   array( 'codemirror' ), $codemirror_version ); 
    57104    $scripts->add( 'codemirror-mode-clike',      plugins_url( 'wp-includes/js/codemirror/mode/clike/clike.js', BETTER_CODE_EDITING_PLUGIN_FILE ),           array( 'codemirror' ), $codemirror_version ); 
    58     $scripts->add( 'codemirror-mode-css',        plugins_url( 'wp-includes/js/codemirror/mode/css/css.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror', 'codemirror-addon-edit-matchbrackets' ), $codemirror_version ); 
     105    $scripts->add( 'codemirror-mode-css',        plugins_url( 'wp-includes/js/codemirror/mode/css/css.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror' ), $codemirror_version ); 
    59106    $scripts->add( 'codemirror-mode-diff',       plugins_url( 'wp-includes/js/codemirror/mode/diff/diff.js', BETTER_CODE_EDITING_PLUGIN_FILE ),             array( 'codemirror' ), $codemirror_version ); 
    60     $scripts->add( 'codemirror-mode-html',       plugins_url( 'wp-includes/js/codemirror/mode/htmlmixed/htmlmixed.js', BETTER_CODE_EDITING_PLUGIN_FILE ),   array( 'codemirror', 'codemirror-mode-css', 'codemirror-mode-javascript', 'codemirror-mode-xml' ), $codemirror_version ); 
     107    $scripts->add( 'codemirror-mode-htmlmixed',  plugins_url( 'wp-includes/js/codemirror/mode/htmlmixed/htmlmixed.js', BETTER_CODE_EDITING_PLUGIN_FILE ),   array( 'codemirror', 'codemirror-mode-css', 'codemirror-mode-javascript', 'codemirror-mode-xml' ), $codemirror_version ); 
    61108    $scripts->add( 'codemirror-mode-http',       plugins_url( 'wp-includes/js/codemirror/mode/http/http.js', BETTER_CODE_EDITING_PLUGIN_FILE ),             array( 'codemirror' ), $codemirror_version ); 
    62109    $scripts->add( 'codemirror-mode-javascript', plugins_url( 'wp-includes/js/codemirror/mode/javascript/javascript.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
    63     $scripts->add( 'codemirror-mode-markdown',   plugins_url( 'wp-includes/js/codemirror/mode/markdown/markdown.js', BETTER_CODE_EDITING_PLUGIN_FILE ),     array( 'codemirror' ), $codemirror_version ); 
    64     $scripts->add( 'codemirror-mode-php',        plugins_url( 'wp-includes/js/codemirror/mode/php/php.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror-mode-clike', 'codemirror-addon-edit-matchbrackets' ), $codemirror_version ); 
     110    $scripts->add( 'codemirror-mode-jsx',        plugins_url( 'wp-includes/js/codemirror/mode/jsx/jsx.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror', 'codemirror-mode-javascript', 'codemirror-mode-xml' ), $codemirror_version ); 
     111    $scripts->add( 'codemirror-mode-markdown',   plugins_url( 'wp-includes/js/codemirror/mode/markdown/markdown.js', BETTER_CODE_EDITING_PLUGIN_FILE ),     array( 'codemirror', 'codemirror-mode-xml' ), $codemirror_version ); 
     112    $scripts->add( 'codemirror-mode-gfm',        plugins_url( 'wp-includes/js/codemirror/mode/gfm/gfm.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror', 'codemirror-addon-mode-overlay', 'codemirror-mode-markdown' ), $codemirror_version ); 
     113    $scripts->add( 'codemirror-mode-nginx',      plugins_url( 'wp-includes/js/codemirror/mode/nginx/nginx.js', BETTER_CODE_EDITING_PLUGIN_FILE ),           array( 'codemirror' ), $codemirror_version ); 
     114    $scripts->add( 'codemirror-mode-php',        plugins_url( 'wp-includes/js/codemirror/mode/php/php.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror-mode-clike', 'codemirror-mode-xml', 'codemirror-mode-javascript', 'codemirror-mode-css', 'codemirror-mode-htmlmixed' ), $codemirror_version ); 
     115    $scripts->add( 'codemirror-mode-sass',       plugins_url( 'wp-includes/js/codemirror/mode/sass/sass.js', BETTER_CODE_EDITING_PLUGIN_FILE ),             array( 'codemirror', 'codemirror-mode-css' ), $codemirror_version ); 
    65116    $scripts->add( 'codemirror-mode-shell',      plugins_url( 'wp-includes/js/codemirror/mode/shell/shell.js', BETTER_CODE_EDITING_PLUGIN_FILE ),           array( 'codemirror' ), $codemirror_version ); 
    66117    $scripts->add( 'codemirror-mode-sql',        plugins_url( 'wp-includes/js/codemirror/mode/sql/sql.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror' ), $codemirror_version ); 
    67118    $scripts->add( 'codemirror-mode-xml',        plugins_url( 'wp-includes/js/codemirror/mode/xml/xml.js', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror' ), $codemirror_version ); 
     119    $scripts->add( 'codemirror-mode-yaml',       plugins_url( 'wp-includes/js/codemirror/mode/yaml/yaml.js', BETTER_CODE_EDITING_PLUGIN_FILE ),             array( 'codemirror' ), $codemirror_version ); 
    68120 
    69121    $scripts->add( 'code-editor', plugins_url( 'wp-admin/js/code-editor.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'jquery', 'codemirror' ), BETTER_CODE_EDITING_PLUGIN_VERSION ); 
    70122 
    71     $scripts->add( 'custom-html-widgets', plugins_url( 'wp-admin/js/widgets/custom-html-widgets.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'code-editor', 'jquery', 'backbone', 'wp-util' ), BETTER_CODE_EDITING_PLUGIN_VERSION ); 
     123    $scripts->add( 'custom-html-widgets', plugins_url( 'wp-admin/js/widgets/custom-html-widgets.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'code-editor', 'jquery', 'backbone', 'wp-util', 'jquery-ui-core', 'wp-a11y' ), BETTER_CODE_EDITING_PLUGIN_VERSION ); 
     124    $scripts->add( 'wp-theme-plugin-editor', plugins_url( 'wp-admin/js/theme-plugin-editor.js', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'code-editor', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ), BETTER_CODE_EDITING_PLUGIN_VERSION ); 
     125 
     126    if ( defined( 'SCRIPT_DEBUG' ) ) { 
     127        _better_code_editing_report_asset_errors( $scripts ); 
     128    } 
    72129} 
    73130 
     
    86143    $styles->registered['common']->ver = BETTER_CODE_EDITING_PLUGIN_VERSION; 
    87144 
    88     $styles->add( 'codemirror',                 plugins_url( 'wp-includes/js/codemirror/lib/codemirror.css', BETTER_CODE_EDITING_PLUGIN_FILE ),       array(),               $codemirror_version ); 
    89     $styles->add( 'codemirror-addon-show-hint', plugins_url( 'wp-includes/js/codemirror/addon/hint/show-hint.css', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
    90     $styles->add( 'codemirror-addon-lint',      plugins_url( 'wp-includes/js/codemirror/addon/lint/lint.css', BETTER_CODE_EDITING_PLUGIN_FILE ),      array( 'codemirror' ), $codemirror_version ); 
     145    $styles->add( 'codemirror',                                 plugins_url( 'wp-includes/js/codemirror/lib/codemirror.css', BETTER_CODE_EDITING_PLUGIN_FILE ),                  array(),               $codemirror_version ); 
     146    $styles->add( 'codemirror-addon-show-hint',                 plugins_url( 'wp-includes/js/codemirror/addon/hint/show-hint.css', BETTER_CODE_EDITING_PLUGIN_FILE ),            array( 'codemirror' ), $codemirror_version ); 
     147    $styles->add( 'codemirror-addon-lint',                      plugins_url( 'wp-includes/js/codemirror/addon/lint/lint.css', BETTER_CODE_EDITING_PLUGIN_FILE ),                 array( 'codemirror' ), $codemirror_version ); 
     148    $styles->add( 'codemirror-addon-dialog',                    plugins_url( 'wp-includes/js/codemirror/addon/dialog/dialog.css', BETTER_CODE_EDITING_PLUGIN_FILE ),             array( 'codemirror' ), $codemirror_version ); 
     149    $styles->add( 'codemirror-addon-display-fullscreen',        plugins_url( 'wp-includes/js/codemirror/addon/display/fullscreen.css', BETTER_CODE_EDITING_PLUGIN_FILE ),        array( 'codemirror' ), $codemirror_version ); 
     150    $styles->add( 'codemirror-addon-fold-foldgutter',           plugins_url( 'wp-includes/js/codemirror/addon/fold/foldgutter.css', BETTER_CODE_EDITING_PLUGIN_FILE ),           array( 'codemirror' ), $codemirror_version ); 
     151    $styles->add( 'codemirror-addon-merge',                     plugins_url( 'wp-includes/js/codemirror/addon/merge/merge.css', BETTER_CODE_EDITING_PLUGIN_FILE ),               array( 'codemirror' ), $codemirror_version ); 
     152    $styles->add( 'codemirror-addon-scroll-simplescrollbars',   plugins_url( 'wp-includes/js/codemirror/addon/scroll/simplescrollbars.css', BETTER_CODE_EDITING_PLUGIN_FILE ),   array( 'codemirror' ), $codemirror_version ); 
     153    $styles->add( 'codemirror-addon-search-matchesonscrollbar', plugins_url( 'wp-includes/js/codemirror/addon/search/matchesonscrollbar.css', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), $codemirror_version ); 
     154    $styles->add( 'codemirror-addon-tern',                      plugins_url( 'wp-includes/js/codemirror/addon/tern/tern.css', BETTER_CODE_EDITING_PLUGIN_FILE ),                 array( 'codemirror' ), $codemirror_version ); 
    91155 
    92156    $styles->add( 'code-editor', plugins_url( 'wp-admin/css/code-editor.css', BETTER_CODE_EDITING_PLUGIN_FILE ), array( 'codemirror' ), BETTER_CODE_EDITING_PLUGIN_VERSION ); 
     
    95159    $styles->add_inline_style( 'widgets', file_get_contents( dirname( BETTER_CODE_EDITING_PLUGIN_FILE ) . '/wp-admin/css/widgets-addendum.css' ) ); 
    96160    $styles->add_inline_style( 'customize-controls', file_get_contents( dirname( BETTER_CODE_EDITING_PLUGIN_FILE ) . '/wp-admin/css/customize-controls-addendum.css' ) ); 
     161 
     162    if ( defined( 'SCRIPT_DEBUG' ) ) { 
     163        _better_code_editing_report_asset_errors( $styles ); 
     164    } 
    97165} 
     166 
     167/** 
     168 * Make sure all CodeMirror assets present are registered. 
     169 * 
     170 * This will not be included in core merge. 
     171 * 
     172 * @param WP_Scripts|WP_Styles $dependencies Dependencies. 
     173 */ 
     174function _better_code_editing_report_asset_errors( $dependencies ) { 
     175    $plugin_dir_url = plugins_url( '', BETTER_CODE_EDITING_PLUGIN_FILE ); 
     176    $codemirror_path = 'wp-includes/js/codemirror'; 
     177    $codemirror_registered_paths = array(); 
     178    $plugin_dir_path = plugin_dir_path( BETTER_CODE_EDITING_PLUGIN_FILE ); 
     179    $type = $dependencies instanceof WP_Styles ? 'style' : 'script'; 
     180 
     181    foreach ( $dependencies->registered as $handle => $style ) { 
     182        if ( 'common' === $handle ) { 
     183            continue; 
     184        } 
     185 
     186        if ( 0 === strpos( $style->src, $plugin_dir_url ) ) { 
     187            $path = substr( $style->src, strlen( $plugin_dir_url ) + 1 ); 
     188            if ( ! file_exists( $plugin_dir_path . $path ) ) { 
     189                trigger_error( "Missing '$handle' $type src: $path'", E_USER_WARNING ); 
     190            } 
     191            if ( 0 === strpos( $path, $codemirror_path ) ) { 
     192                $codemirror_registered_paths[] = $path; 
     193            } 
     194        } 
     195    } 
     196 
     197    $directory = new RecursiveDirectoryIterator( $plugin_dir_path . $codemirror_path ); 
     198    $iterator = new RecursiveIteratorIterator( $directory ); 
     199    $file_iterator = new RegexIterator( $iterator, $dependencies instanceof WP_Styles ? '#\.css$#' : '#\.js$#' ); 
     200 
     201    $codemirror_existing_paths = array(); 
     202    foreach ( $file_iterator as $js_file ) { 
     203        $codemirror_existing_paths[] = substr( $js_file->getPathname(), strlen( $plugin_dir_path ) ); 
     204    } 
     205    $unregistered_assets = array_diff( $codemirror_existing_paths, $codemirror_registered_paths ); 
     206    if ( ! empty( $unregistered_assets ) ) { 
     207        trigger_error( 
     208            sprintf( 
     209                'There are %d %s assets from CodeMirror that are not registered: %s', 
     210                count( $unregistered_assets ), 
     211                $type, 
     212                join( ', ', $unregistered_assets ) 
     213            ), 
     214            E_USER_WARNING 
     215        ); 
     216    } 
     217 
     218} 
  • better-code-editing/trunk/wp-includes/widgets/class-wp-widget-custom-html-codemirror.php

    r1720408 r1722335  
    4545        // Note that the widgets component in the customizer will also do the 'admin_footer-widgets.php' action in WP_Customize_Widgets::print_footer_scripts(). 
    4646        add_action( 'admin_footer-widgets.php', array( 'WP_Widget_Custom_HTML_CodeMirror', 'render_control_template_scripts' ) ); 
     47 
     48        // Note this action is used to ensure the help text is added to the end. 
     49        add_action( 'admin_head-widgets.php', array( 'WP_Widget_Custom_HTML_CodeMirror', 'add_help_text' ) ); 
    4750    } 
    4851 
     
    6669        } 
    6770        wp_add_inline_script( 'custom-html-widgets', sprintf( 'wp.customHtmlWidgets.init( %s );', wp_json_encode( $settings ) ), 'after' ); 
     71 
     72        $l10n = array( 
     73            'errorNotice' => wp_array_slice_assoc( 
     74                /* translators: placeholder is error count */ 
     75                _n_noop( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.', 'better-code-editing' ), 
     76                array( 'singular', 'plural' ) 
     77            ), 
     78        ); 
     79        wp_add_inline_script( 'custom-html-widgets', sprintf( 'jQuery.extend( wp.customHtmlWidgets.l10n, %s );', wp_json_encode( $l10n ) ), 'after' ); 
    6880    } 
    6981 
     
    118130                <?php endif; ?> 
    119131            <?php endif; ?> 
     132 
     133            <div class="code-editor-error-container"></div> 
    120134        </script> 
    121135        <?php 
    122136    } 
     137 
     138    /** 
     139     * Add help text to widgets admin screen. 
     140     * 
     141     * @since 4.9.0 
     142     */ 
     143    static public function add_help_text() { 
     144        $screen = get_current_screen(); 
     145 
     146        $content = '<p>'; 
     147        $content .= __( 'Use the Custom HTML widget to add arbitrary HTML code to your widget areas.', 'better-code-editing' ); 
     148        $content .= '</p>'; 
     149 
     150        $content .= '<p>' . __( 'When using a keyboard to navigate:', 'better-code-editing' ) . '</p>'; 
     151        $content .= '<ul>'; 
     152        $content .= '<li>' . __( 'In the HTML edit field, Tab enters a tab character.', 'better-code-editing' ) . '</li>'; 
     153        $content .= '<li>' . __( 'To move keyboard focus, press Esc then Tab for the next element, or Esc then Shift+Tab for the previous element.', 'better-code-editing' ) . '</li>'; 
     154        $content .= '</ul>'; 
     155 
     156        $content .= '<p>'; 
     157        $content .= sprintf( 
     158            /* translators: placeholder is link to user profile */ 
     159            __( 'The edit field automatically highlights code syntax. You can disable this in your %s to work in plan text mode.', 'better-code-editing' ), 
     160            sprintf( 
     161                ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text">%3$s</span></a>', 
     162                esc_url( get_edit_profile_url() . '#syntax_highlighting' ), 
     163                __( 'user profile', 'better-code-editing' ), 
     164                /* translators: accessibility text */ 
     165                __( '(opens in a new window)', 'default' ) 
     166            ) 
     167        ); 
     168        $content .= '</p>'; 
     169 
     170        $screen->add_help_tab( array( 
     171            'id' => 'custom_html_widget', 
     172            'title' => __( 'Custom HTML Widget', 'better-code-editing' ), 
     173            'content' => $content, 
     174        ) ); 
     175    } 
    123176} 
Note: See TracChangeset for help on using the changeset viewer.