@@ -26,6 +26,8 @@ import {languageMaps} from '../lib/CMLanguageList'
26
26
import snippetManager from '../lib/SnippetManager'
27
27
import { generateInEditor , tocExistsInEditor } from 'browser/lib/markdown-toc-generator'
28
28
import markdownlint from 'markdownlint'
29
+ import Jsonlint from 'jsonlint-mod'
30
+ import { DEFAULT_CONFIG } from '../main/lib/ConfigManager'
29
31
30
32
CodeMirror . modeURL = '../node_modules/codemirror/mode/%N/%N.js'
31
33
@@ -38,38 +40,6 @@ function translateHotkey (hotkey) {
38
40
return hotkey . replace ( / \s * \+ \s * / g, '-' ) . replace ( / C o m m a n d / g, 'Cmd' ) . replace ( / C o n t r o l / g, 'Ctrl' )
39
41
}
40
42
41
- const validatorOfMarkdown = ( text , updateLinting ) => {
42
- const lintOptions = {
43
- 'strings' : {
44
- 'content' : text
45
- }
46
- }
47
-
48
- return markdownlint ( lintOptions , ( err , result ) => {
49
- if ( ! err ) {
50
- const foundIssues = [ ]
51
- result . content . map ( item => {
52
- let ruleNames = ''
53
- item . ruleNames . map ( ( ruleName , index ) => {
54
- ruleNames += ruleName
55
- if ( index === item . ruleNames . length - 1 ) {
56
- ruleNames += ': '
57
- } else {
58
- ruleNames += '/'
59
- }
60
- } )
61
- foundIssues . push ( {
62
- from : CodeMirror . Pos ( item . lineNumber , 0 ) ,
63
- to : CodeMirror . Pos ( item . lineNumber , 1 ) ,
64
- message : ruleNames + item . ruleDescription ,
65
- severity : 'warning'
66
- } )
67
- } )
68
- updateLinting ( foundIssues )
69
- }
70
- } )
71
- }
72
-
73
43
export default class CodeEditor extends React . Component {
74
44
constructor ( props ) {
75
45
super ( props )
@@ -116,6 +86,8 @@ export default class CodeEditor extends React.Component {
116
86
this . searchHandler = ( e , msg ) => this . handleSearch ( msg )
117
87
this . searchState = null
118
88
this . scrollToLineHandeler = this . scrollToLine . bind ( this )
89
+ this . getCodeEditorLintConfig = this . getCodeEditorLintConfig . bind ( this )
90
+ this . validatorOfMarkdown = this . validatorOfMarkdown . bind ( this )
119
91
120
92
this . formatTable = ( ) => this . handleFormatTable ( )
121
93
@@ -283,13 +255,12 @@ export default class CodeEditor extends React.Component {
283
255
}
284
256
285
257
componentDidMount ( ) {
286
- const { rulers, enableRulers } = this . props
258
+ const { rulers, enableRulers, enableMarkdownLint } = this . props
287
259
eventEmitter . on ( 'line:jump' , this . scrollToLineHandeler )
288
260
289
261
snippetManager . init ( )
290
262
this . updateDefaultKeyMap ( )
291
263
292
- const checkMarkdownNoteIsOpening = this . props . mode === 'Boost Flavored Markdown'
293
264
this . value = this . props . value
294
265
this . editor = CodeMirror ( this . refs . root , {
295
266
rulers : buildCMRulers ( rulers , enableRulers ) ,
@@ -306,10 +277,7 @@ export default class CodeEditor extends React.Component {
306
277
inputStyle : 'textarea' ,
307
278
dragDrop : false ,
308
279
foldGutter : true ,
309
- lint : checkMarkdownNoteIsOpening ? {
310
- 'getAnnotations' : validatorOfMarkdown ,
311
- 'async' : true
312
- } : false ,
280
+ lint : enableMarkdownLint ? this . getCodeEditorLintConfig ( ) : false ,
313
281
gutters : [ 'CodeMirror-linenumbers' , 'CodeMirror-foldgutter' , 'CodeMirror-lint-markers' ] ,
314
282
autoCloseBrackets : {
315
283
pairs : this . props . matchingPairs ,
@@ -320,6 +288,8 @@ export default class CodeEditor extends React.Component {
320
288
extraKeys : this . defaultKeyMap
321
289
} )
322
290
291
+ document . querySelector ( '.CodeMirror-lint-markers' ) . style . display = enableMarkdownLint ? 'inline-block' : 'none'
292
+
323
293
if ( ! this . props . mode && this . props . value && this . props . autoDetect ) {
324
294
this . autoDetectLanguage ( this . props . value )
325
295
} else {
@@ -546,7 +516,9 @@ export default class CodeEditor extends React.Component {
546
516
let needRefresh = false
547
517
const {
548
518
rulers,
549
- enableRulers
519
+ enableRulers,
520
+ enableMarkdownLint,
521
+ customMarkdownLintConfig
550
522
} = this . props
551
523
if ( prevProps . mode !== this . props . mode ) {
552
524
this . setMode ( this . props . mode )
@@ -564,6 +536,16 @@ export default class CodeEditor extends React.Component {
564
536
if ( prevProps . keyMap !== this . props . keyMap ) {
565
537
needRefresh = true
566
538
}
539
+ if ( prevProps . enableMarkdownLint !== enableMarkdownLint || prevProps . customMarkdownLintConfig !== customMarkdownLintConfig ) {
540
+ if ( ! enableMarkdownLint ) {
541
+ this . editor . setOption ( 'lint' , { default : false } )
542
+ document . querySelector ( '.CodeMirror-lint-markers' ) . style . display = 'none'
543
+ } else {
544
+ this . editor . setOption ( 'lint' , this . getCodeEditorLintConfig ( ) )
545
+ document . querySelector ( '.CodeMirror-lint-markers' ) . style . display = 'inline-block'
546
+ }
547
+ needRefresh = true
548
+ }
567
549
568
550
if (
569
551
prevProps . enableRulers !== enableRulers ||
@@ -644,6 +626,56 @@ export default class CodeEditor extends React.Component {
644
626
}
645
627
}
646
628
629
+ getCodeEditorLintConfig ( ) {
630
+ const { mode } = this . props
631
+ const checkMarkdownNoteIsOpen = mode === 'Boost Flavored Markdown'
632
+
633
+ return checkMarkdownNoteIsOpen ? {
634
+ 'getAnnotations' : this . validatorOfMarkdown ,
635
+ 'async' : true
636
+ } : false
637
+ }
638
+
639
+ validatorOfMarkdown ( text , updateLinting ) {
640
+ const { customMarkdownLintConfig } = this . props
641
+ let lintConfigJson
642
+ try {
643
+ Jsonlint . parse ( customMarkdownLintConfig )
644
+ lintConfigJson = JSON . parse ( customMarkdownLintConfig )
645
+ } catch ( err ) {
646
+ eventEmitter . emit ( 'APP_SETTING_ERROR' )
647
+ return
648
+ }
649
+ const lintOptions = {
650
+ 'strings' : {
651
+ 'content' : text
652
+ } ,
653
+ 'config' : lintConfigJson
654
+ }
655
+
656
+ return markdownlint ( lintOptions , ( err , result ) => {
657
+ if ( ! err ) {
658
+ const foundIssues = [ ]
659
+ const splitText = text . split ( '\n' )
660
+ result . content . map ( item => {
661
+ let ruleNames = ''
662
+ item . ruleNames . map ( ( ruleName , index ) => {
663
+ ruleNames += ruleName
664
+ ruleNames += ( index === item . ruleNames . length - 1 ) ? ': ' : '/'
665
+ } )
666
+ const lineNumber = item . lineNumber - 1
667
+ foundIssues . push ( {
668
+ from : CodeMirror . Pos ( lineNumber , 0 ) ,
669
+ to : CodeMirror . Pos ( lineNumber , splitText [ lineNumber ] . length ) ,
670
+ message : ruleNames + item . ruleDescription ,
671
+ severity : 'warning'
672
+ } )
673
+ } )
674
+ updateLinting ( foundIssues )
675
+ }
676
+ } )
677
+ }
678
+
647
679
setMode ( mode ) {
648
680
let syntax = CodeMirror . findModeByName ( convertModeName ( mode || 'text' ) )
649
681
if ( syntax == null ) syntax = CodeMirror . findModeByName ( 'Plain Text' )
@@ -1105,13 +1137,11 @@ export default class CodeEditor extends React.Component {
1105
1137
}
1106
1138
ref = 'root'
1107
1139
tabIndex = '-1'
1108
- style = {
1109
- {
1140
+ style = { {
1110
1141
fontFamily,
1111
1142
fontSize : fontSize ,
1112
1143
width : width
1113
- }
1114
- }
1144
+ } }
1115
1145
onDrop = {
1116
1146
e => this . handleDropImage ( e )
1117
1147
}
@@ -1149,7 +1179,9 @@ CodeEditor.propTypes = {
1149
1179
onChange : PropTypes . func ,
1150
1180
readOnly : PropTypes . bool ,
1151
1181
autoDetect : PropTypes . bool ,
1152
- spellCheck : PropTypes . bool
1182
+ spellCheck : PropTypes . bool ,
1183
+ enableMarkdownLint : PropTypes . bool ,
1184
+ customMarkdownLintConfig : PropTypes . string
1153
1185
}
1154
1186
1155
1187
CodeEditor . defaultProps = {
@@ -1161,5 +1193,7 @@ CodeEditor.defaultProps = {
1161
1193
indentSize : 4 ,
1162
1194
indentType : 'space' ,
1163
1195
autoDetect : false ,
1164
- spellCheck : false
1196
+ spellCheck : false ,
1197
+ enableMarkdownLint : DEFAULT_CONFIG . editor . enableMarkdownLint ,
1198
+ customMarkdownLintConfig : DEFAULT_CONFIG . editor . customMarkdownLintConfig
1165
1199
}
0 commit comments