| | |
| | |
| | |
| |
|
| | if ( 'undefined' === typeof window.wp ) { |
| | |
| | |
| | |
| | window.wp = {}; |
| | } |
| | if ( 'undefined' === typeof window.wp.codeEditor ) { |
| | |
| | |
| | |
| | window.wp.codeEditor = {}; |
| | } |
| |
|
| | ( function( $, wp ) { |
| | 'use strict'; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | wp.codeEditor.defaultSettings = { |
| | codemirror: {}, |
| | csslint: {}, |
| | htmlhint: {}, |
| | jshint: {}, |
| | onTabNext: function() {}, |
| | onTabPrevious: function() {}, |
| | onChangeLintingErrors: function() {}, |
| | onUpdateErrorNotice: function() {} |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | function configureLinting( editor, settings ) { |
| | var currentErrorAnnotations = [], previouslyShownErrorAnnotations = []; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | function updateErrorNotice() { |
| | if ( settings.onUpdateErrorNotice && ! _.isEqual( currentErrorAnnotations, previouslyShownErrorAnnotations ) ) { |
| | settings.onUpdateErrorNotice( currentErrorAnnotations, editor ); |
| | previouslyShownErrorAnnotations = currentErrorAnnotations; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | function getLintOptions() { |
| | var options = editor.getOption( 'lint' ); |
| |
|
| | if ( ! options ) { |
| | return false; |
| | } |
| |
|
| | if ( true === options ) { |
| | options = {}; |
| | } else if ( _.isObject( options ) ) { |
| | options = $.extend( {}, options ); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | if ( ! options.options ) { |
| | options.options = {}; |
| | } |
| |
|
| | |
| | if ( 'javascript' === settings.codemirror.mode && settings.jshint ) { |
| | $.extend( options.options, settings.jshint ); |
| | } |
| |
|
| | |
| | if ( 'css' === settings.codemirror.mode && settings.csslint ) { |
| | $.extend( options.options, settings.csslint ); |
| | } |
| |
|
| | |
| | if ( 'htmlmixed' === settings.codemirror.mode && settings.htmlhint ) { |
| | options.options.rules = $.extend( {}, settings.htmlhint ); |
| |
|
| | if ( settings.jshint ) { |
| | options.options.rules.jshint = settings.jshint; |
| | } |
| | if ( settings.csslint ) { |
| | options.options.rules.csslint = settings.csslint; |
| | } |
| | } |
| |
|
| | |
| | options.onUpdateLinting = (function( onUpdateLintingOverridden ) { |
| | return function( annotations, annotationsSorted, cm ) { |
| | var errorAnnotations = _.filter( annotations, function( annotation ) { |
| | return 'error' === annotation.severity; |
| | } ); |
| |
|
| | if ( onUpdateLintingOverridden ) { |
| | onUpdateLintingOverridden.apply( annotations, annotationsSorted, cm ); |
| | } |
| |
|
| | |
| | if ( _.isEqual( errorAnnotations, currentErrorAnnotations ) ) { |
| | return; |
| | } |
| |
|
| | currentErrorAnnotations = errorAnnotations; |
| |
|
| | if ( settings.onChangeLintingErrors ) { |
| | settings.onChangeLintingErrors( errorAnnotations, annotations, annotationsSorted, cm ); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | if ( ! editor.state.focused || 0 === currentErrorAnnotations.length || previouslyShownErrorAnnotations.length > 0 ) { |
| | updateErrorNotice(); |
| | } |
| | }; |
| | })( options.onUpdateLinting ); |
| |
|
| | return options; |
| | } |
| |
|
| | editor.setOption( 'lint', getLintOptions() ); |
| |
|
| | |
| | editor.on( 'optionChange', function( cm, option ) { |
| | var options, gutters, gutterName = 'CodeMirror-lint-markers'; |
| | if ( 'lint' !== option ) { |
| | return; |
| | } |
| | gutters = editor.getOption( 'gutters' ) || []; |
| | options = editor.getOption( 'lint' ); |
| | if ( true === options ) { |
| | if ( ! _.contains( gutters, gutterName ) ) { |
| | editor.setOption( 'gutters', [ gutterName ].concat( gutters ) ); |
| | } |
| | editor.setOption( 'lint', getLintOptions() ); |
| | } else if ( ! options ) { |
| | editor.setOption( 'gutters', _.without( gutters, gutterName ) ); |
| | } |
| |
|
| | |
| | if ( editor.getOption( 'lint' ) ) { |
| | editor.performLint(); |
| | } else { |
| | currentErrorAnnotations = []; |
| | updateErrorNotice(); |
| | } |
| | } ); |
| |
|
| | |
| | editor.on( 'blur', updateErrorNotice ); |
| |
|
| | |
| | editor.on( 'startCompletion', function() { |
| | editor.off( 'blur', updateErrorNotice ); |
| | } ); |
| | editor.on( 'endCompletion', function() { |
| | var editorRefocusWait = 500; |
| | editor.on( 'blur', updateErrorNotice ); |
| |
|
| | |
| | _.delay( function() { |
| | if ( ! editor.state.focused ) { |
| | updateErrorNotice(); |
| | } |
| | }, editorRefocusWait ); |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | $( document.body ).on( 'mousedown', function( event ) { |
| | if ( editor.state.focused && ! $.contains( editor.display.wrapper, event.target ) && ! $( event.target ).hasClass( 'CodeMirror-hint' ) ) { |
| | updateErrorNotice(); |
| | } |
| | }); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | function configureTabbing( codemirror, settings ) { |
| | var $textarea = $( codemirror.getTextArea() ); |
| |
|
| | codemirror.on( 'blur', function() { |
| | $textarea.data( 'next-tab-blurs', false ); |
| | }); |
| | codemirror.on( 'keydown', function onKeydown( editor, event ) { |
| | var tabKeyCode = 9, escKeyCode = 27; |
| |
|
| | |
| | if ( escKeyCode === event.keyCode ) { |
| | $textarea.data( 'next-tab-blurs', true ); |
| | return; |
| | } |
| |
|
| | |
| | if ( tabKeyCode !== event.keyCode || ! $textarea.data( 'next-tab-blurs' ) ) { |
| | return; |
| | } |
| |
|
| | |
| | if ( event.shiftKey ) { |
| | settings.onTabPrevious( codemirror, event ); |
| | } else { |
| | settings.onTabNext( codemirror, event ); |
| | } |
| |
|
| | |
| | $textarea.data( 'next-tab-blurs', false ); |
| |
|
| | |
| | event.preventDefault(); |
| | }); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | wp.codeEditor.initialize = function initialize( textarea, settings ) { |
| | var $textarea, codemirror, instanceSettings, instance; |
| | if ( 'string' === typeof textarea ) { |
| | $textarea = $( '#' + textarea ); |
| | } else { |
| | $textarea = $( textarea ); |
| | } |
| |
|
| | instanceSettings = $.extend( {}, wp.codeEditor.defaultSettings, settings ); |
| | instanceSettings.codemirror = $.extend( {}, instanceSettings.codemirror ); |
| |
|
| | codemirror = wp.CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror ); |
| |
|
| | configureLinting( codemirror, instanceSettings ); |
| |
|
| | instance = { |
| | settings: instanceSettings, |
| | codemirror: codemirror |
| | }; |
| |
|
| | if ( codemirror.showHint ) { |
| | codemirror.on( 'keyup', function( editor, event ) { |
| | var shouldAutocomplete, isAlphaKey = /^[a-zA-Z]$/.test( event.key ), lineBeforeCursor, innerMode, token; |
| | if ( codemirror.state.completionActive && isAlphaKey ) { |
| | return; |
| | } |
| |
|
| | |
| | token = codemirror.getTokenAt( codemirror.getCursor() ); |
| | if ( 'string' === token.type || 'comment' === token.type ) { |
| | return; |
| | } |
| |
|
| | innerMode = wp.CodeMirror.innerMode( codemirror.getMode(), token.state ).mode.name; |
| | lineBeforeCursor = codemirror.doc.getLine( codemirror.doc.getCursor().line ).substr( 0, codemirror.doc.getCursor().ch ); |
| | if ( 'html' === innerMode || 'xml' === innerMode ) { |
| | shouldAutocomplete = |
| | '<' === event.key || |
| | '/' === event.key && 'tag' === token.type || |
| | isAlphaKey && 'tag' === token.type || |
| | isAlphaKey && 'attribute' === token.type || |
| | '=' === token.string && token.state.htmlState && token.state.htmlState.tagName; |
| | } else if ( 'css' === innerMode ) { |
| | shouldAutocomplete = |
| | isAlphaKey || |
| | ':' === event.key || |
| | ' ' === event.key && /:\s+$/.test( lineBeforeCursor ); |
| | } else if ( 'javascript' === innerMode ) { |
| | shouldAutocomplete = isAlphaKey || '.' === event.key; |
| | } else if ( 'clike' === innerMode && 'php' === codemirror.options.mode ) { |
| | shouldAutocomplete = 'keyword' === token.type || 'variable' === token.type; |
| | } |
| | if ( shouldAutocomplete ) { |
| | codemirror.showHint( { completeSingle: false } ); |
| | } |
| | }); |
| | } |
| |
|
| | |
| | configureTabbing( codemirror, settings ); |
| |
|
| | return instance; |
| | }; |
| |
|
| | })( window.jQuery, window.wp ); |
| |
|