@@ -11,9 +11,12 @@ import eventEmitter from 'browser/main/lib/eventEmitter'
11
11
import iconv from 'iconv-lite'
12
12
import crypto from 'crypto'
13
13
import consts from 'browser/lib/consts'
14
+ import styles from '../components/CodeEditor.styl'
14
15
import fs from 'fs'
15
- const { ipcRenderer } = require ( 'electron' )
16
+ const { ipcRenderer, remote } = require ( 'electron' )
16
17
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
18
+ const spellcheck = require ( 'browser/lib/spellcheck' )
19
+ const buildEditorContextMenu = require ( 'browser/lib/contextMenuBuilder' )
17
20
import TurndownService from 'turndown'
18
21
import { gfm } from 'turndown-plugin-gfm'
19
22
@@ -30,7 +33,7 @@ export default class CodeEditor extends React.Component {
30
33
leading : false ,
31
34
trailing : true
32
35
} )
33
- this . changeHandler = e => this . handleChange ( e )
36
+ this . changeHandler = ( editor , changeObject ) => this . handleChange ( editor , changeObject )
34
37
this . focusHandler = ( ) => {
35
38
ipcRenderer . send ( 'editor:focused' , true )
36
39
}
@@ -62,6 +65,12 @@ export default class CodeEditor extends React.Component {
62
65
this . scrollToLineHandeler = this . scrollToLine . bind ( this )
63
66
64
67
this . formatTable = ( ) => this . handleFormatTable ( )
68
+ this . contextMenuHandler = function ( editor , event ) {
69
+ const menu = buildEditorContextMenu ( editor , event )
70
+ if ( menu != null ) {
71
+ setTimeout ( ( ) => menu . popup ( remote . getCurrentWindow ( ) ) , 30 )
72
+ }
73
+ }
65
74
this . editorActivityHandler = ( ) => this . handleEditorActivity ( )
66
75
67
76
this . turndownService = new TurndownService ( )
@@ -232,6 +241,7 @@ export default class CodeEditor extends React.Component {
232
241
this . editor . on ( 'blur' , this . blurHandler )
233
242
this . editor . on ( 'change' , this . changeHandler )
234
243
this . editor . on ( 'paste' , this . pasteHandler )
244
+ this . editor . on ( 'contextmenu' , this . contextMenuHandler )
235
245
eventEmitter . on ( 'top:search' , this . searchHandler )
236
246
237
247
eventEmitter . emit ( 'code:init' )
@@ -248,6 +258,10 @@ export default class CodeEditor extends React.Component {
248
258
249
259
this . textEditorInterface = new TextEditorInterface ( this . editor )
250
260
this . tableEditor = new TableEditor ( this . textEditorInterface )
261
+ if ( this . props . spellCheck ) {
262
+ this . editor . addPanel ( this . createSpellCheckPanel ( ) , { position : 'bottom' } )
263
+ }
264
+
251
265
eventEmitter . on ( 'code:format-table' , this . formatTable )
252
266
253
267
this . tableEditorOptions = options ( {
@@ -395,9 +409,11 @@ export default class CodeEditor extends React.Component {
395
409
this . editor . off ( 'paste' , this . pasteHandler )
396
410
eventEmitter . off ( 'top:search' , this . searchHandler )
397
411
this . editor . off ( 'scroll' , this . scrollHandler )
412
+ this . editor . off ( 'contextmenu' , this . contextMenuHandler )
398
413
const editorTheme = document . getElementById ( 'editorTheme' )
399
414
editorTheme . removeEventListener ( 'load' , this . loadStyleHandler )
400
415
416
+ spellcheck . setLanguage ( null , spellcheck . SPELLCHECK_DISABLED )
401
417
eventEmitter . off ( 'code:format-table' , this . formatTable )
402
418
}
403
419
@@ -465,6 +481,16 @@ export default class CodeEditor extends React.Component {
465
481
needRefresh = true
466
482
}
467
483
484
+ if ( prevProps . spellCheck !== this . props . spellCheck ) {
485
+ if ( this . props . spellCheck === false ) {
486
+ spellcheck . setLanguage ( this . editor , spellcheck . SPELLCHECK_DISABLED )
487
+ let elem = document . getElementById ( 'editor-bottom-panel' )
488
+ elem . parentNode . removeChild ( elem )
489
+ } else {
490
+ this . editor . addPanel ( this . createSpellCheckPanel ( ) , { position : 'bottom' } )
491
+ }
492
+ }
493
+
468
494
if ( needRefresh ) {
469
495
this . editor . refresh ( )
470
496
}
@@ -478,10 +504,11 @@ export default class CodeEditor extends React.Component {
478
504
CodeMirror . autoLoadMode ( this . editor , syntax . mode )
479
505
}
480
506
481
- handleChange ( e ) {
482
- this . value = this . editor . getValue ( )
507
+ handleChange ( editor , changeObject ) {
508
+ spellcheck . handleChange ( editor , changeObject )
509
+ this . value = editor . getValue ( )
483
510
if ( this . props . onChange ) {
484
- this . props . onChange ( e )
511
+ this . props . onChange ( editor )
485
512
}
486
513
}
487
514
@@ -718,6 +745,25 @@ export default class CodeEditor extends React.Component {
718
745
/>
719
746
)
720
747
}
748
+
749
+ createSpellCheckPanel ( ) {
750
+ const panel = document . createElement ( 'div' )
751
+ panel . className = 'panel bottom'
752
+ panel . id = 'editor-bottom-panel'
753
+ const dropdown = document . createElement ( 'select' )
754
+ dropdown . title = 'Spellcheck'
755
+ dropdown . className = styles [ 'spellcheck-select' ]
756
+ dropdown . addEventListener ( 'change' , ( e ) => spellcheck . setLanguage ( this . editor , dropdown . value ) )
757
+ const options = spellcheck . getAvailableDictionaries ( )
758
+ for ( const op of options ) {
759
+ const option = document . createElement ( 'option' )
760
+ option . value = op . value
761
+ option . innerHTML = op . label
762
+ dropdown . appendChild ( option )
763
+ }
764
+ panel . appendChild ( dropdown )
765
+ return panel
766
+ }
721
767
}
722
768
723
769
CodeEditor . propTypes = {
@@ -728,7 +774,8 @@ CodeEditor.propTypes = {
728
774
className : PropTypes . string ,
729
775
onBlur : PropTypes . func ,
730
776
onChange : PropTypes . func ,
731
- readOnly : PropTypes . bool
777
+ readOnly : PropTypes . bool ,
778
+ spellCheck : PropTypes . bool
732
779
}
733
780
734
781
CodeEditor . defaultProps = {
@@ -738,5 +785,6 @@ CodeEditor.defaultProps = {
738
785
fontSize : 14 ,
739
786
fontFamily : 'Monaco, Consolas' ,
740
787
indentSize : 4 ,
741
- indentType : 'space'
788
+ indentType : 'space' ,
789
+ spellCheck : false
742
790
}
0 commit comments