diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js
index 4893b342..1abd15a9 100644
--- a/browser/components/CodeEditor.js
+++ b/browser/components/CodeEditor.js
@@ -26,6 +26,8 @@ import {languageMaps} from '../lib/CMLanguageList'
import snippetManager from '../lib/SnippetManager'
import {generateInEditor, tocExistsInEditor} from 'browser/lib/markdown-toc-generator'
import markdownlint from 'markdownlint'
+import Jsonlint from 'jsonlint-mod'
+import { DEFAULT_CONFIG } from '../main/lib/ConfigManager'
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
@@ -38,38 +40,6 @@ function translateHotkey (hotkey) {
return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl')
}
-const validatorOfMarkdown = (text, updateLinting) => {
- const lintOptions = {
- 'strings': {
- 'content': text
- }
- }
-
- return markdownlint(lintOptions, (err, result) => {
- if (!err) {
- const foundIssues = []
- result.content.map(item => {
- let ruleNames = ''
- item.ruleNames.map((ruleName, index) => {
- ruleNames += ruleName
- if (index === item.ruleNames.length - 1) {
- ruleNames += ': '
- } else {
- ruleNames += '/'
- }
- })
- foundIssues.push({
- from: CodeMirror.Pos(item.lineNumber, 0),
- to: CodeMirror.Pos(item.lineNumber, 1),
- message: ruleNames + item.ruleDescription,
- severity: 'warning'
- })
- })
- updateLinting(foundIssues)
- }
- })
-}
-
export default class CodeEditor extends React.Component {
constructor (props) {
super(props)
@@ -116,6 +86,8 @@ export default class CodeEditor extends React.Component {
this.searchHandler = (e, msg) => this.handleSearch(msg)
this.searchState = null
this.scrollToLineHandeler = this.scrollToLine.bind(this)
+ this.getCodeEditorLintConfig = this.getCodeEditorLintConfig.bind(this)
+ this.validatorOfMarkdown = this.validatorOfMarkdown.bind(this)
this.formatTable = () => this.handleFormatTable()
@@ -283,13 +255,12 @@ export default class CodeEditor extends React.Component {
}
componentDidMount () {
- const { rulers, enableRulers } = this.props
+ const { rulers, enableRulers, enableMarkdownLint } = this.props
eventEmitter.on('line:jump', this.scrollToLineHandeler)
snippetManager.init()
this.updateDefaultKeyMap()
- const checkMarkdownNoteIsOpening = this.props.mode === 'Boost Flavored Markdown'
this.value = this.props.value
this.editor = CodeMirror(this.refs.root, {
rulers: buildCMRulers(rulers, enableRulers),
@@ -306,10 +277,7 @@ export default class CodeEditor extends React.Component {
inputStyle: 'textarea',
dragDrop: false,
foldGutter: true,
- lint: checkMarkdownNoteIsOpening ? {
- 'getAnnotations': validatorOfMarkdown,
- 'async': true
- } : false,
+ lint: enableMarkdownLint ? this.getCodeEditorLintConfig() : false,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
autoCloseBrackets: {
pairs: this.props.matchingPairs,
@@ -320,6 +288,8 @@ export default class CodeEditor extends React.Component {
extraKeys: this.defaultKeyMap
})
+ document.querySelector('.CodeMirror-lint-markers').style.display = enableMarkdownLint ? 'inline-block' : 'none'
+
if (!this.props.mode && this.props.value && this.props.autoDetect) {
this.autoDetectLanguage(this.props.value)
} else {
@@ -546,7 +516,9 @@ export default class CodeEditor extends React.Component {
let needRefresh = false
const {
rulers,
- enableRulers
+ enableRulers,
+ enableMarkdownLint,
+ customMarkdownLintConfig
} = this.props
if (prevProps.mode !== this.props.mode) {
this.setMode(this.props.mode)
@@ -564,6 +536,16 @@ export default class CodeEditor extends React.Component {
if (prevProps.keyMap !== this.props.keyMap) {
needRefresh = true
}
+ if (prevProps.enableMarkdownLint !== enableMarkdownLint || prevProps.customMarkdownLintConfig !== customMarkdownLintConfig) {
+ if (!enableMarkdownLint) {
+ this.editor.setOption('lint', {default: false})
+ document.querySelector('.CodeMirror-lint-markers').style.display = 'none'
+ } else {
+ this.editor.setOption('lint', this.getCodeEditorLintConfig())
+ document.querySelector('.CodeMirror-lint-markers').style.display = 'inline-block'
+ }
+ needRefresh = true
+ }
if (
prevProps.enableRulers !== enableRulers ||
@@ -644,6 +626,56 @@ export default class CodeEditor extends React.Component {
}
}
+ getCodeEditorLintConfig () {
+ const { mode } = this.props
+ const checkMarkdownNoteIsOpen = mode === 'Boost Flavored Markdown'
+
+ return checkMarkdownNoteIsOpen ? {
+ 'getAnnotations': this.validatorOfMarkdown,
+ 'async': true
+ } : false
+ }
+
+ validatorOfMarkdown (text, updateLinting) {
+ const { customMarkdownLintConfig } = this.props
+ let lintConfigJson
+ try {
+ Jsonlint.parse(customMarkdownLintConfig)
+ lintConfigJson = JSON.parse(customMarkdownLintConfig)
+ } catch (err) {
+ eventEmitter.emit('APP_SETTING_ERROR')
+ return
+ }
+ const lintOptions = {
+ 'strings': {
+ 'content': text
+ },
+ 'config': lintConfigJson
+ }
+
+ return markdownlint(lintOptions, (err, result) => {
+ if (!err) {
+ const foundIssues = []
+ const splitText = text.split('\n')
+ result.content.map(item => {
+ let ruleNames = ''
+ item.ruleNames.map((ruleName, index) => {
+ ruleNames += ruleName
+ ruleNames += (index === item.ruleNames.length - 1) ? ': ' : '/'
+ })
+ const lineNumber = item.lineNumber - 1
+ foundIssues.push({
+ from: CodeMirror.Pos(lineNumber, 0),
+ to: CodeMirror.Pos(lineNumber, splitText[lineNumber].length),
+ message: ruleNames + item.ruleDescription,
+ severity: 'warning'
+ })
+ })
+ updateLinting(foundIssues)
+ }
+ })
+ }
+
setMode (mode) {
let syntax = CodeMirror.findModeByName(convertModeName(mode || 'text'))
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
@@ -1105,13 +1137,11 @@ export default class CodeEditor extends React.Component {
}
ref='root'
tabIndex='-1'
- style={
- {
+ style={{
fontFamily,
fontSize: fontSize,
width: width
- }
- }
+ }}
onDrop={
e => this.handleDropImage(e)
}
@@ -1149,7 +1179,9 @@ CodeEditor.propTypes = {
onChange: PropTypes.func,
readOnly: PropTypes.bool,
autoDetect: PropTypes.bool,
- spellCheck: PropTypes.bool
+ spellCheck: PropTypes.bool,
+ enableMarkdownLint: PropTypes.bool,
+ customMarkdownLintConfig: PropTypes.string
}
CodeEditor.defaultProps = {
@@ -1161,5 +1193,7 @@ CodeEditor.defaultProps = {
indentSize: 4,
indentType: 'space',
autoDetect: false,
- spellCheck: false
+ spellCheck: false,
+ enableMarkdownLint: DEFAULT_CONFIG.editor.enableMarkdownLint,
+ customMarkdownLintConfig: DEFAULT_CONFIG.editor.customMarkdownLintConfig
}
diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js
index 593f7d99..526ecb39 100644
--- a/browser/components/MarkdownEditor.js
+++ b/browser/components/MarkdownEditor.js
@@ -319,6 +319,8 @@ class MarkdownEditor extends React.Component {
enableSmartPaste={config.editor.enableSmartPaste}
hotkey={config.hotkey}
switchPreview={config.editor.switchPreview}
+ enableMarkdownLint={config.editor.enableMarkdownLint}
+ customMarkdownLintConfig={config.editor.customMarkdownLintConfig}
/>