use CSSLint in a web werkker
This commit is contained in:
parent
f3cf6e1856
commit
99512da9da
|
@ -40,6 +40,8 @@ body {
|
|||
box-shadow: 0 0 3rem -1.2rem black;
|
||||
box-sizing: border-box;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#header h1 {
|
||||
margin-top: 0;
|
||||
|
@ -468,9 +470,9 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
|||
}
|
||||
|
||||
/************ lint ************/
|
||||
#lint > div {
|
||||
#lint {
|
||||
overflow-y: auto;
|
||||
}
|
||||
overflow-x: hidden;}
|
||||
#lint table {
|
||||
font-size: 100%;
|
||||
border-spacing: 0;
|
||||
|
@ -505,6 +507,7 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
|||
}
|
||||
#lint td[role="message"] {
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#message-box.center.lint-config #message-box-contents {
|
||||
text-align: left;
|
||||
|
|
|
@ -1,38 +1,20 @@
|
|||
/* global CodeMirror CSSLint parserlib stylelint linterConfig */
|
||||
'use strict';
|
||||
|
||||
CodeMirror.registerHelper('lint', 'csslint', code => {
|
||||
if (!CSSLint.suppressUsoVarError) {
|
||||
CSSLint.suppressUsoVarError = true;
|
||||
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
|
||||
const isUsoVar = ({value}) => value.startsWith('/*[[') && value.endsWith(']]*/');
|
||||
CSSLint.addRule({
|
||||
id: 'uso-vars',
|
||||
init(parser, reporter) {
|
||||
parser.addListener('error', function ({message, line, col}) {
|
||||
if (!isUsoVar(this._tokenStream._token)) {
|
||||
const {_lt, _ltIndex: i} = this._tokenStream;
|
||||
if (i < 2 || !_lt.slice(0, i - 1).reverse().some(isUsoVar)) {
|
||||
reporter.error(message, line, col);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
const rules = deepCopy(linterConfig.getCurrent('csslint'));
|
||||
Object.defineProperty(rules, 'errors', {get: () => 0, set: () => 0});
|
||||
rules['uso-vars'] = 1;
|
||||
return CSSLint.verify(code, rules).messages
|
||||
.map(({line, col, message, rule, type}) => line && {
|
||||
message,
|
||||
from: {line: line - 1, ch: col - 1},
|
||||
to: {line: line - 1, ch: col},
|
||||
rule: rule.id,
|
||||
severity: type
|
||||
})
|
||||
.filter(Boolean);
|
||||
});
|
||||
CodeMirror.registerHelper('lint', 'csslint', code => new Promise(resolve => {
|
||||
CSSLint.onmessage = ({data}) => {
|
||||
resolve(
|
||||
data.map(({line, col, message, rule, type}) => line && {
|
||||
message,
|
||||
from: {line: line - 1, ch: col - 1},
|
||||
to: {line: line - 1, ch: col},
|
||||
rule: rule.id,
|
||||
severity: type
|
||||
}).filter(Boolean));
|
||||
};
|
||||
const config = deepCopy(linterConfig.getCurrent('csslint'));
|
||||
CSSLint.postMessage({action: 'verify', code, config});
|
||||
}));
|
||||
|
||||
CodeMirror.registerHelper('lint', 'stylelint', code =>
|
||||
stylelint.lint({
|
||||
|
|
52
edit/lint.js
52
edit/lint.js
|
@ -38,6 +38,9 @@ var linterConfig = {
|
|||
return CodeMirror.lint && CodeMirror.lint[linter] ? {
|
||||
getAnnotations: CodeMirror.lint[linter],
|
||||
delay: prefs.get('editor.lintDelay'),
|
||||
onUpdateLinting(annotationsNotSorted, annotations, cm) {
|
||||
updateLintReport(cm, 0);
|
||||
},
|
||||
} : false;
|
||||
},
|
||||
|
||||
|
@ -64,12 +67,18 @@ var linterConfig = {
|
|||
|
||||
findInvalidRules(config, linter = linterConfig.getDefault()) {
|
||||
const rules = linter === 'stylelint' ? config.rules : config;
|
||||
const allRules = new Set(
|
||||
linter === 'stylelint'
|
||||
? Object.keys(stylelint.rules)
|
||||
: CSSLint.getRules().map(rule => rule.id)
|
||||
);
|
||||
return Object.keys(rules).filter(rule => !allRules.has(rule));
|
||||
return new Promise(resolve => {
|
||||
if (linter === 'stylelint') {
|
||||
resolve(Object.keys(stylelint.rules));
|
||||
} else {
|
||||
CSSLint.onmessage = ({data}) =>
|
||||
resolve(data.map(rule => rule.id));
|
||||
CSSLint.postMessage({action: 'getRules'});
|
||||
}
|
||||
}).then(allRules => {
|
||||
allRules = new Set(allRules);
|
||||
return Object.keys(rules).filter(rule => !allRules.has(rule));
|
||||
});
|
||||
},
|
||||
|
||||
stringify(config = this.getCurrent()) {
|
||||
|
@ -140,7 +149,6 @@ function initLint() {
|
|||
$('#lint-help').addEventListener('click', showLintHelp);
|
||||
$('#lint').addEventListener('click', gotoLintIssue);
|
||||
$('#linter-settings').addEventListener('click', linterConfig.openOnClick);
|
||||
window.addEventListener('resize', resizeLintReport);
|
||||
|
||||
updateLinter();
|
||||
linterConfig.watchStorage();
|
||||
|
@ -332,22 +340,6 @@ function renderLintReport(someBlockChanged) {
|
|||
$('#issue-count').textContent = issueCount;
|
||||
container.replaceChild(newContent, content);
|
||||
container.classList.toggle('hidden', !newContent.children.length);
|
||||
resizeLintReport();
|
||||
}
|
||||
}
|
||||
|
||||
function resizeLintReport() {
|
||||
// subtracted value to prevent scrollbar
|
||||
const magicBuffer = 20;
|
||||
const content = $('#lint table');
|
||||
if (content) {
|
||||
const bounds = content.getBoundingClientRect();
|
||||
const newMaxHeight = bounds.bottom <= window.innerHeight ? '' :
|
||||
// subtract out a bit of padding or the vertical scrollbar extends beyond the viewport
|
||||
(window.innerHeight - bounds.top - magicBuffer) + 'px';
|
||||
if (newMaxHeight !== content.style.maxHeight) {
|
||||
content.parentNode.style.maxHeight = newMaxHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,7 +413,11 @@ function setupLinterSettingsEvents(popup) {
|
|||
const linter = linterConfig.setLinter(event.target.dataset.linter);
|
||||
const json = tryJSONparse(popup.codebox.getValue());
|
||||
if (json) {
|
||||
const invalid = linterConfig.findInvalidRules(json, linter);
|
||||
showLinterErrorMessage(linter, t('linterJSONError'));
|
||||
popup.codebox.focus();
|
||||
return;
|
||||
}
|
||||
linterConfig.findInvalidRules(json, linter).then(invalid => {
|
||||
if (invalid.length) {
|
||||
showLinterErrorMessage(linter, [
|
||||
t('linterInvalidConfigError'),
|
||||
|
@ -436,10 +432,8 @@ function setupLinterSettingsEvents(popup) {
|
|||
linterConfig.save(json);
|
||||
linterConfig.showSavedMessage();
|
||||
popup.codebox.markClean();
|
||||
} else {
|
||||
showLinterErrorMessage(linter, t('linterJSONError'));
|
||||
}
|
||||
popup.codebox.focus();
|
||||
popup.codebox.focus();
|
||||
});
|
||||
});
|
||||
$('.reset', popup).addEventListener('click', event => {
|
||||
event.preventDefault();
|
||||
|
@ -524,8 +518,8 @@ function loadLinterAssets(name = linterConfig.getDefault()) {
|
|||
|
||||
function loadLibrary() {
|
||||
if (name === 'csslint' && !window.CSSLint) {
|
||||
window.CSSLint = new Worker('/vendor-overwrites/csslint/csslint-worker.js');
|
||||
return loadScript([
|
||||
'/vendor-overwrites/csslint/csslint-worker.js',
|
||||
'/edit/lint-defaults-csslint.js'
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -10931,31 +10931,40 @@ CSSLint.addFormatter({
|
|||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Web worker for CSSLint
|
||||
*/
|
||||
if (!CSSLint.suppressUsoVarError) {
|
||||
CSSLint.suppressUsoVarError = true;
|
||||
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
|
||||
const isUsoVar = ({value}) => value.startsWith('/*[[') && value.endsWith(']]*/');
|
||||
CSSLint.addRule({
|
||||
id: 'uso-vars',
|
||||
init(parser, reporter) {
|
||||
parser.addListener('error', function ({message, line, col}) {
|
||||
if (!isUsoVar(this._tokenStream._token)) {
|
||||
const {_lt, _ltIndex: i} = this._tokenStream;
|
||||
if (i < 2 || !_lt.slice(0, i - 1).reverse().some(isUsoVar)) {
|
||||
reporter.error(message, line, col);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/* global self, JSON */
|
||||
self.onmessage = ({data: {action, code, config}}) => {
|
||||
switch (action) {
|
||||
|
||||
// message indicates to start linting
|
||||
self.onmessage = function(event) {
|
||||
"use strict";
|
||||
var data = event.data,
|
||||
message,
|
||||
text,
|
||||
ruleset,
|
||||
results;
|
||||
case 'getRules':
|
||||
self.postMessage(CSSLint.getRules());
|
||||
return;
|
||||
|
||||
try {
|
||||
message = JSON.parse(data);
|
||||
text = message.text;
|
||||
ruleset = message.ruleset;
|
||||
} catch (ex) {
|
||||
text = data;
|
||||
}
|
||||
|
||||
results = CSSLint.verify(text, ruleset);
|
||||
|
||||
// Not all browsers support structured clone, so JSON stringify results
|
||||
self.postMessage(JSON.stringify(results));
|
||||
case 'verify':
|
||||
Object.defineProperty(config, 'errors', {get: () => 0, set: () => 0});
|
||||
config['uso-vars'] = 1;
|
||||
self.postMessage(CSSLint.verify(code, config).messages.map(m => {
|
||||
// the functions are non-tranferable and we need only an id
|
||||
m.rule = {id: m.rule.id};
|
||||
return m;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user