Merge pull request #1654 from hackmdio/feature/autofix-linting

Autofix linter errors
This commit is contained in:
Yukai Huang 2021-03-12 11:46:51 +08:00 committed by GitHub
commit a7d392c6ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 208 additions and 757 deletions

858
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -105,7 +105,7 @@
"ws": "~7.1.1" "ws": "~7.1.1"
}, },
"devDependencies": { "devDependencies": {
"@hackmd/codemirror": "~5.49.8", "@hackmd/codemirror": "~5.57.7",
"@hackmd/emojify.js": "^2.1.0", "@hackmd/emojify.js": "^2.1.0",
"@hackmd/idle-js": "~1.0.1", "@hackmd/idle-js": "~1.0.1",
"@hackmd/js-sequence-diagrams": "~0.0.1-alpha.3", "@hackmd/js-sequence-diagrams": "~0.0.1-alpha.3",
@ -163,7 +163,8 @@
"markdown-it-ruby": "^0.1.1", "markdown-it-ruby": "^0.1.1",
"markdown-it-sub": "~1.0.0", "markdown-it-sub": "~1.0.0",
"markdown-it-sup": "~1.0.0", "markdown-it-sup": "~1.0.0",
"markdownlint": "^0.17.0", "markdownlint": "^0.22.0",
"markdownlint-rule-helpers": "^0.13.0",
"markmap-lib": "^0.4.2", "markmap-lib": "^0.4.2",
"mathjax": "~2.7.5", "mathjax": "~2.7.5",
"mermaid": "~8.6.4", "mermaid": "~8.6.4",

View File

@ -6,7 +6,7 @@ import * as utils from './utils'
import config from './config' import config from './config'
import statusBarTemplate from './statusbar.html' import statusBarTemplate from './statusbar.html'
import toolBarTemplate from './toolbar.html' import toolBarTemplate from './toolbar.html'
import './markdown-lint' import { linterOptions } from './markdown-lint'
import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from './spellcheck' import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from './spellcheck'
import { initTableEditor } from './table-editor' import { initTableEditor } from './table-editor'
import { availableThemes } from './constants' import { availableThemes } from './constants'
@ -674,7 +674,7 @@ export default class Editor {
this.editor.setOption('gutters', gutters.filter(g => g !== lintGutter)) this.editor.setOption('gutters', gutters.filter(g => g !== lintGutter))
Cookies.remove('linter') Cookies.remove('linter')
} }
this.editor.setOption('lint', enable) this.editor.setOption('lint', enable ? linterOptions : false)
} }
setLinter () { setLinter () {
@ -685,7 +685,7 @@ export default class Editor {
} }
linterToggle.click(() => { linterToggle.click(() => {
const lintEnable = this.editor.getOption('lint') const lintEnable = !!this.editor.getOption('lint')
this.toggleLinter.bind(this)(!lintEnable) this.toggleLinter.bind(this)(!lintEnable)
updateLinterStatus(!lintEnable) updateLinterStatus(!lintEnable)
}) })

View File

@ -3,6 +3,9 @@
// load CM lint plugin explicitly // load CM lint plugin explicitly
import '@hackmd/codemirror/addon/lint/lint' import '@hackmd/codemirror/addon/lint/lint'
import '@hackmd/codemirror/addon/hint/show-hint.css'
import helpers from 'markdownlint-rule-helpers'
window.markdownit = require('markdown-it') window.markdownit = require('markdown-it')
// eslint-disable-next-line // eslint-disable-next-line
require('script-loader!markdownlint'); require('script-loader!markdownlint');
@ -26,10 +29,11 @@ require('script-loader!markdownlint');
} }
return { return {
messageHTML: `${ruleNames.join('/')}: ${ruleDescription}`, messageHTML: `${ruleNames.join('/')}: ${ruleDescription} <small>markdownlint(${ruleNames[0]})</small>`,
severity: 'error', severity: 'error',
from: CodeMirror.Pos(lineNumber, start), from: CodeMirror.Pos(lineNumber, start),
to: CodeMirror.Pos(lineNumber, end) to: CodeMirror.Pos(lineNumber, end),
__error: error
} }
}) })
} }
@ -37,11 +41,84 @@ require('script-loader!markdownlint');
CodeMirror.registerHelper('lint', 'markdown', validator) CodeMirror.registerHelper('lint', 'markdown', validator)
}) })
export const linterOptions = {
fixedTooltip: true,
contextmenu: annotations => {
const singleFixMenus = annotations
.map(annotation => {
const error = annotation.__error
const ruleNameAlias = error.ruleNames.join('/')
if (annotation.__error.fixInfo) {
return {
content: `Click to fix this violoation of ${ruleNameAlias}`,
onClick () {
const doc = window.editor.doc
const fixInfo = normalizeFixInfo(error.fixInfo, error.lineNumber)
const line = fixInfo.lineNumber - 1
const lineContent = doc.getLine(line) || ''
const fixedText = helpers.applyFix(lineContent, fixInfo, '\n')
let from = { line, ch: 0 }
let to = { line, ch: lineContent ? lineContent.length : 0 }
if (typeof fixedText === 'string') {
doc.replaceRange(fixedText, from, to)
} else {
if (fixInfo.lineNumber === 1) {
if (doc.lineCount() > 1) {
const nextLineStart = doc.indexFromPos({
line: to.line + 1,
ch: 0
})
to = doc.posFromIndex(nextLineStart)
}
} else {
const previousLineEnd = doc.indexFromPos(from) - 1
from = doc.posFromIndex(previousLineEnd)
}
doc.replaceRange('', from, to)
}
}
}
} else {
return {
content: `Click for more information about ${ruleNameAlias}`,
onClick () {
window.open(error.ruleInformation, '_blank')
}
}
}
})
return singleFixMenus
}
}
function lint (content) { function lint (content) {
const { content: errors } = window.markdownlint.sync({ const { content: errors } = window.markdownlint.sync({
strings: { strings: {
content content
} },
resultVersion: 3
}) })
return errors return errors
} }
// Taken from https://github.com/DavidAnson/markdownlint/blob/2a9274ece586514ba3e2819cec3eb74312dc1b84/helpers/helpers.js#L611
/**
* Normalizes the fields of a RuleOnErrorFixInfo instance.
*
* @param {Object} fixInfo RuleOnErrorFixInfo instance.
* @param {number} [lineNumber] Line number.
* @returns {Object} Normalized RuleOnErrorFixInfo instance.
*/
function normalizeFixInfo (fixInfo, lineNumber) {
return {
lineNumber: fixInfo.lineNumber || lineNumber,
editColumn: fixInfo.editColumn || 1,
deleteCount: fixInfo.deleteCount || 0,
insertText: fixInfo.insertText || ''
}
}

View File

@ -71,3 +71,11 @@
background-position: right bottom; background-position: right bottom;
width: 100%; height: 100%; width: 100%; height: 100%;
} }
.CodeMirror-hints {
background: #333;
}
.CodeMirror-hint {
color: white;
}

View File

@ -522,7 +522,8 @@ module.exports = {
}] }]
}, },
node: { node: {
fs: 'empty' fs: 'empty',
os: 'empty'
}, },
stats: { stats: {