Skip to content

Commit 7caa272

Browse files
committed
Provide linter autofixes
Signed-off-by: Yukai Huang <yukaihuangtw@gmail.com>
1 parent f946b5b commit 7caa272

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

public/js/lib/editor/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as utils from './utils'
66
import config from './config'
77
import statusBarTemplate from './statusbar.html'
88
import toolBarTemplate from './toolbar.html'
9-
import './markdown-lint'
9+
import { linterOptions } from './markdown-lint'
1010
import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from './spellcheck'
1111
import { initTableEditor } from './table-editor'
1212
import { availableThemes } from './constants'
@@ -674,7 +674,7 @@ export default class Editor {
674674
this.editor.setOption('gutters', gutters.filter(g => g !== lintGutter))
675675
Cookies.remove('linter')
676676
}
677-
this.editor.setOption('lint', enable)
677+
this.editor.setOption('lint', enable ? linterOptions : false)
678678
}
679679

680680
setLinter () {
@@ -685,7 +685,7 @@ export default class Editor {
685685
}
686686

687687
linterToggle.click(() => {
688-
const lintEnable = this.editor.getOption('lint')
688+
const lintEnable = !!this.editor.getOption('lint')
689689
this.toggleLinter.bind(this)(!lintEnable)
690690
updateLinterStatus(!lintEnable)
691691
})

public/js/lib/editor/markdown-lint/index.js

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
// load CM lint plugin explicitly
44
import '@hackmd/codemirror/addon/lint/lint'
55

6+
import '@hackmd/codemirror/addon/hint/show-hint.css'
7+
import helpers from 'markdownlint-rule-helpers'
8+
69
window.markdownit = require('markdown-it')
710
// eslint-disable-next-line
811
require('script-loader!markdownlint');
@@ -26,22 +29,76 @@ require('script-loader!markdownlint');
2629
}
2730

2831
return {
29-
messageHTML: `${ruleNames.join('/')}: ${ruleDescription}`,
32+
messageHTML: `${ruleNames.slice(0, 1)}: ${ruleDescription}`,
3033
severity: 'error',
3134
from: CodeMirror.Pos(lineNumber, start),
32-
to: CodeMirror.Pos(lineNumber, end)
35+
to: CodeMirror.Pos(lineNumber, end),
36+
__ruleNames: ruleNames,
37+
__ruleDescription: ruleDescription,
38+
__error: error,
39+
__lineNumber: lineNumber
3340
}
3441
})
3542
}
3643

3744
CodeMirror.registerHelper('lint', 'markdown', validator)
3845
})
3946

47+
export const linterOptions = {
48+
fixedTooltip: true,
49+
contextmenu: annotations => {
50+
const singleFixMenus = annotations
51+
.filter(ann => ann.__error.fixInfo)
52+
.map(annotation => {
53+
const error = annotation.__error
54+
return {
55+
content: `Fix ${error.ruleDescription}`,
56+
onClick () {
57+
const doc = window.editor.doc
58+
const fixInfo = error.fixInfo
59+
const line = fixInfo.lineNumber - 1
60+
const lineContent = doc.getLine(line) || ''
61+
const fixedText = helpers.applyFix(lineContent, error.fixInfo, '\n')
62+
63+
let from = { line, ch: 0 }
64+
let to = { line, ch: lineContent ? lineContent.length - 1 : 0 }
65+
66+
if (typeof fixedText === 'string') {
67+
doc.replaceRange(fixedText, from, to)
68+
} else {
69+
if (fixInfo.lineNumber === 1) {
70+
if (document.lineCount > 1) {
71+
const nextLine = doc.getLine(to.line + 1) || ''
72+
to = {
73+
line: nextLine,
74+
ch: 0
75+
}
76+
}
77+
} else {
78+
const previousLine = doc.getLine(from.line - 1) || ''
79+
from = {
80+
line: previousLine,
81+
ch: previousLine.length
82+
}
83+
}
84+
85+
// !FIXME: certain range out of bound
86+
doc.replaceRange('', from, to)
87+
}
88+
}
89+
}
90+
})
91+
92+
return singleFixMenus
93+
}
94+
}
95+
4096
function lint (content) {
4197
const { content: errors } = window.markdownlint.sync({
4298
strings: {
4399
content
44-
}
100+
},
101+
resultVersion: 3
45102
})
46103
return errors
47104
}

0 commit comments

Comments
 (0)