Dynamically load linter when selected

This commit is contained in:
Rob Garrison 2017-08-20 09:06:17 -05:00
parent b1a7f8d4a2
commit 29851a8de9
7 changed files with 71 additions and 101484 deletions

View File

@ -34,16 +34,6 @@
<script src="vendor/codemirror/addon/edit/matchbrackets.js"></script>
<!-- CSSLint -->
<script src="vendor/csslint/csslint-worker.js"></script>
<!-- stylelint -->
<script src="vendor-overwrites/stylelint/stylelint-bundle.min.js"></script>
<script src="vendor-overwrites/codemirror/addon/lint/stylelint-config.js"></script>
<!-- linter -->
<link rel="stylesheet" href="vendor/codemirror/addon/lint/lint.css" />
<script src="vendor/codemirror/addon/lint/lint.js"></script>
<script src="vendor-overwrites/codemirror/addon/lint/css-lint.js"></script>
<link rel="stylesheet" href="vendor/codemirror/addon/hint/show-hint.css" />
<script src="vendor/codemirror/addon/hint/show-hint.js"></script>
<script src="vendor/codemirror/addon/hint/css-hint.js"></script>
@ -196,12 +186,13 @@
<label id="linter-label" for="editor.linter" i18n-text="cm_linter"></label>
<select id="editor.linter">
<option value="csslint" selected>CSSLint</option>
<option value="stylelint">stylelint</option>
<option value="stylelint">Stylelint</option>
<option value="null" i18n-text="genericDisabledLabel"></option>
</select>
<span class="linter-settings" i18n-title="stylelintConfig">
<svg id="stylelint-settings" class="svg-icon settings">
<use xlink:href="#svg-icon-settings"/>
</svg>
</svg>&nbsp;
</span>
</section>
<section id="lint"><h2 i18n-text="issues">: <span id="issue-count"></span><svg id="lint-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg></h2><div></div></section>

View File

@ -154,6 +154,9 @@ function setCleanSection(section) {
function initCodeMirror() {
const CM = CodeMirror;
const isWindowsOS = navigator.appVersion.indexOf('Windows') > 0;
// lint.js is not loaded initially
const hasLinter = typeof getLinterConfigForCodeMirror !== 'undefined' ?
getLinterConfigForCodeMirror(prefs.get('editor.linter')) : false;
// CodeMirror miserably fails on keyMap='' so let's ensure it's not
if (!prefs.get('editor.keyMap')) {
@ -170,7 +173,7 @@ function initCodeMirror() {
matchBrackets: true,
highlightSelectionMatches: {showToken: /[#.\-\w]/, annotateScrollbar: true},
hintOptions: {},
lint: getLinterConfigForCodeMirror(prefs.get('editor.linter')),
lint: hasLinter,
lintReportDelay: prefs.get('editor.lintReportDelay'),
styleActiveLine: true,
theme: 'default',
@ -352,9 +355,7 @@ function acmeEventListener(event) {
}
break;
case 'linter':
if (value !== null && editors.length) {
updateLinter(value);
}
break;
}
CodeMirror.setOption(option, value);
@ -427,7 +428,7 @@ function indicateCodeChange(cm) {
const section = cm.getSection();
setCleanItem(section, cm.isClean(section.savedValue));
updateTitle();
updateLintReport(cm);
updateLintReportIfEnabled(cm);
}
function getSectionForChild(e) {
@ -554,7 +555,7 @@ window.onbeforeunload = () => {
if (isCleanGlobal()) {
return;
}
updateLintReport(null, 0);
updateLintReportIfEnabled(null, 0);
return confirm(t('styleChangesNotSaved'));
};
@ -1223,12 +1224,14 @@ function initWithStyle({style, codeIsUpdated}) {
const sectionDiv = addSection(null, queue.shift());
maximizeCodeHeight(sectionDiv, !queue.length);
const cm = sectionDiv.CodeMirror;
if (CodeMirror.lint) {
setTimeout(() => {
cm.setOption('lint', CodeMirror.defaults.lint);
// update lint issue table after a short delay
updateLintReport(cm, 200);
}, prefs.get('editor.lintDelay'));
}
}
}
function initHooks() {
@ -1365,8 +1368,14 @@ function validate() {
return null;
}
function updateLintReportIfEnabled(cm, time) {
if (CodeMirror.lint) {
updateLintReport(cm, time);
}
}
function save() {
updateLintReport(null, 0);
updateLintReportIfEnabled(null, 0);
// save the contents of the CodeMirror editors back into the textareas
for (let i = 0; i < editors.length; i++) {

View File

@ -1,5 +1,5 @@
/* global CodeMirror CSSLint editors makeSectionVisible showHelp showCodeMirrorPopup */
/* global stylelintDefaultConfig onDOMscripted */
/* global stylelintDefaultConfig onDOMscripted injectCSS require */
'use strict';
function initLint() {
@ -23,19 +23,29 @@ function setStylelintRules(rules = {}) {
}
function getLinterConfigForCodeMirror(name) {
return {
return CodeMirror.lint && CodeMirror.lint[name] ? {
getAnnotations: CodeMirror.lint[name],
delay: prefs.get('editor.lintDelay')
};
} : false;
}
function updateLinter(name = 'csslint') {
function updateLinter(name) {
function updateEditors() {
const options = getLinterConfigForCodeMirror(name);
CodeMirror.defaults.lint = options === 'null' ? false : options;
editors.forEach(cm => {
// set lint to "null" to disable
cm.setOption('lint', options);
cm.refresh(); // enabling/disabling linting changes the gutter width
updateLintReport(cm, 200);
});
}
if (prefs.get('editor.linter') !== name) {
prefs.set('editor.linter', name);
}
editors.forEach(cm => {
cm.setOption('lint', getLinterConfigForCodeMirror(name));
updateLintReport(cm, 200);
// load scripts
loadSelectedLinter(name).then(() => {
updateEditors();
});
$('#stylelint-settings').style.display = name === 'stylelint' ?
'inline-block' : 'none';
@ -228,7 +238,7 @@ function setupStylelintSettingsEvents(popup) {
}, 3000);
}
});
popup.querySelector('reset').addEventListener('click', event => {
popup.querySelector('.reset').addEventListener('click', event => {
event.preventDefault();
setStylelintRules();
popup.codebox.setValue(JSON.stringify({rules: stylelintDefaultConfig.rules}, null, 2));
@ -254,6 +264,7 @@ function setupStylelintPopup(rules) {
}
function setJSONMode(cm) {
cm.setOption('mode', 'application/json');
cm.setOption('lint', 'json');
}
const popup = showCodeMirrorPopup(t('setStylelintRules'), $element({
className: 'contents',
@ -278,18 +289,32 @@ function setupStylelintPopup(rules) {
]
}));
const contents = popup.querySelector('.contents');
const loadJSON = window.jsonlint ? [] : ['vendor/codemirror/addon/lint/json-lint.js'];
contents.insertBefore(popup.codebox.display.wrapper, contents.firstElementChild);
popup.codebox.focus();
popup.codebox.setValue(rules);
if (!$('script[src*="json-lint.js"]')) {
onDOMscripted(
['vendor/codemirror/addon/lint/json-lint.js'],
() => {
setJSONMode(popup.codebox);
}
);
} else {
setJSONMode(popup.codebox);
}
onDOMscripted(loadJSON, () => { setJSONMode(popup.codebox); });
setupStylelintSettingsEvents(popup);
}
function loadSelectedLinter(name) {
let scripts = [];
if (name !== 'null' && !$('script[src*="css-lint.js"]')) {
// inject css
injectCSS('vendor/codemirror/addon/lint/lint.css');
// load CodeMirror lint code
scripts = scripts.concat([
'vendor/codemirror/addon/lint/lint.js',
'vendor-overwrites/codemirror/addon/lint/css-lint.js'
]);
}
if (name === 'csslint' && !window.CSSLint) {
scripts.push('vendor/csslint/csslint-worker.js');
} else if (name === 'stylelint' && !window.stylelint) {
scripts = scripts.concat([
'vendor-overwrites/stylelint/stylelint-bundle.min.js',
'vendor-overwrites/codemirror/addon/lint/stylelint-config.js'
]);
}
return onDOMscripted(scripts);
}

View File

@ -64,8 +64,8 @@ CodeMirror.registerHelper("lint", "csslint", function(text) {
CodeMirror.registerHelper("lint", "stylelint", function(text) {
let found = [];
const stylelint = require('stylelint').lint;
if (stylelint) {
window.stylelint = require('stylelint').lint;
if (window.stylelint) {
return BG.chromeLocal.getValue('editorStylelintRules').then((rules = stylelintDefaultConfig.rules) => {
// stylelintDefaultConfig stored in stylelint-config.js & loaded by edit.html
if (Object.keys(rules).length === 0) {

View File

@ -1,4 +1,4 @@
const stylelintDefaultConfig = (defaultSeverity => ({
window.stylelintDefaultConfig = (defaultSeverity => ({
// 'sugarss' is a indent-based syntax like Sass or Stylus
// ref: https://github.com/postcss/postcss#syntaxes
syntax: 'sugarss',

File diff suppressed because one or more lines are too long

View File

@ -21,3 +21,4 @@ Stylelint bundle file created by:
This prevents a js error when stylelint attempts to access a local file. The
other `fs.readFile` entries are not accessed because we're using stylelint's
standalone method.
5. The script was then "minified" by manually running it through Google's [Closure Compiler](http://closure-compiler.appspot.com/home) set to "Whitespace only".