diff --git a/edit.html b/edit.html
index 3368a28b..b8d2b243 100644
--- a/edit.html
+++ b/edit.html
@@ -8,8 +8,8 @@
-
+
@@ -34,6 +34,7 @@
+
diff --git a/edit/edit.js b/edit/edit.js
index 34b8eadd..b6ebaa74 100644
--- a/edit/edit.js
+++ b/edit/edit.js
@@ -162,8 +162,6 @@ function initCodeMirror() {
const CM = CodeMirror;
const isWindowsOS = navigator.appVersion.indexOf('Windows') > 0;
// lint.js is not loaded initially
- const hasLinter = window.linterConfig ? linterConfig.getForCodeMirror() : false;
-
// CodeMirror miserably fails on keyMap='' so let's ensure it's not
if (!prefs.get('editor.keyMap')) {
prefs.reset('editor.keyMap');
@@ -175,11 +173,15 @@ function initCodeMirror() {
lineNumbers: true,
lineWrapping: true,
foldGutter: true,
- gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
+ gutters: [
+ 'CodeMirror-linenumbers',
+ 'CodeMirror-foldgutter',
+ ...(prefs.get('editor.linter') ? ['CodeMirror-lint-markers'] : []),
+ ],
matchBrackets: true,
highlightSelectionMatches: {showToken: /[#.\-\w]/, annotateScrollbar: true},
hintOptions: {},
- lint: hasLinter,
+ lint: linterConfig.getForCodeMirror(),
lintReportDelay: prefs.get('editor.lintReportDelay'),
styleActiveLine: true,
theme: 'default',
@@ -370,7 +372,7 @@ function acmeEventListener(event) {
option = 'highlightSelectionMatches';
break;
case 'linter':
- updateLinter(value);
+ debounce(updateLinter);
break;
}
CodeMirror.setOption(option, value);
diff --git a/edit/lint.js b/edit/lint.js
index 802d8196..5bb30033 100644
--- a/edit/lint.js
+++ b/edit/lint.js
@@ -3,6 +3,8 @@
/* global onDOMscripted injectCSS require CSSLint stylelint */
'use strict';
+loadLinterAssets();
+
// eslint-disable-next-line no-var
var linterConfig = {
csslint: {},
@@ -133,19 +135,49 @@ function initLint() {
}
function updateLinter(linter = prefs.get('editor.linter')) {
+ const GUTTERS_CLASS = 'CodeMirror-lint-markers';
+
function updateEditors() {
- const options = linterConfig.getForCodeMirror(linter);
- CodeMirror.defaults.lint = options;
+ CodeMirror.defaults.lint = linterConfig.getForCodeMirror(linter);
+ const guttersOption = prepareGuttersOption();
editors.forEach(cm => {
- // set lint to "null" to disable
- cm.setOption('lint', options);
- // enabling/disabling linting changes the gutter width
+ cm.setOption('lint', CodeMirror.defaults.lint);
+ if (guttersOption) {
+ cm.setOption('guttersOption', guttersOption);
+ updateGutters(cm, guttersOption);
+ }
cm.refresh();
updateLintReport(cm, 200);
});
}
+
+ function prepareGuttersOption() {
+ const gutters = CodeMirror.defaults.gutters;
+ const needRefresh = Boolean(linter) !== gutters.includes(GUTTERS_CLASS);
+ if (needRefresh) {
+ if (linter) {
+ gutters.push(GUTTERS_CLASS);
+ } else {
+ gutters.splice(gutters.indexOf(GUTTERS_CLASS), 1);
+ }
+ }
+ return needRefresh && gutters;
+ }
+
+ function updateGutters(cm, guttersOption) {
+ cm.options.gutters = guttersOption;
+ const el = $('.' + GUTTERS_CLASS, cm.display.gutters);
+ if (linter && !el) {
+ cm.display.gutters.appendChild($element({
+ className: 'CodeMirror-gutter ' + GUTTERS_CLASS
+ }));
+ } else if (!linter && el) {
+ el.remove();
+ }
+ }
+
// load scripts
- loadSelectedLinter(linter).then(() => {
+ loadLinterAssets(linter).then(() => {
updateEditors();
});
$('#linter-settings').style.display = !linter ? 'none' : 'inline-block';
@@ -159,8 +191,10 @@ function updateLintReport(cm, delay) {
}
if (delay > 0) {
setTimeout(cm => {
- cm.performLint();
- update(cm);
+ if (cm.performLint) {
+ cm.performLint();
+ update(cm);
+ }
}, delay, cm);
return;
}
@@ -374,7 +408,7 @@ function setupLinterSettingsEvents(popup) {
}
linterConfig.save(json);
linterConfig.showSavedMessage();
- debounce(updateLinter, 0, linter);
+ debounce(updateLinter);
} else {
showLinterErrorMessage(linter, t('linterJSONError'));
}
@@ -450,7 +484,11 @@ function setupLinterPopup(config) {
setupLinterSettingsEvents(popup);
}
-function loadSelectedLinter(name) {
+function loadLinterAssets(name = prefs.get('editor.linter')) {
+ if (loadLinterAssets.loadingName === name) {
+ return onDOMscripted();
+ }
+ loadLinterAssets.loadingName = name;
const scripts = [];
if (name === 'csslint' && !window.CSSLint) {
scripts.push(
@@ -473,5 +511,6 @@ function loadSelectedLinter(name) {
'msgbox/msgbox.js'
);
}
- return onDOMscripted(scripts);
+ return onDOMscripted(scripts)
+ .then(() => (loadLinterAssets.loadingName = null));
}