119 lines
3.0 KiB
JavaScript
119 lines
3.0 KiB
JavaScript
|
/* global importScripts parseMozFormat parserlib CSSLint require */
|
||
|
'use strict';
|
||
|
|
||
|
createAPI({
|
||
|
csslint: (code, config) => {
|
||
|
loadParserLib();
|
||
|
loadScript(['/vendor-overwrites/csslint/csslint.js']);
|
||
|
return CSSLint.verify(code, config).messages
|
||
|
.map(m => Object.assign(m, {rule: {id: m.rule.id}}));
|
||
|
},
|
||
|
stylelint: (code, config) => {
|
||
|
loadScript(['/vendor/stylelint-bundle/stylelint-bundle.min.js']);
|
||
|
return require('stylelint').lint({code, config});
|
||
|
},
|
||
|
parseMozFormat: data => {
|
||
|
loadParserLib();
|
||
|
loadScript(['/js/moz-parser.js']);
|
||
|
return parseMozFormat(data);
|
||
|
},
|
||
|
getStylelintRules,
|
||
|
getCsslintRules
|
||
|
});
|
||
|
|
||
|
function getCsslintRules() {
|
||
|
loadScript(['/vendor-overwrites/csslint/csslint.js']);
|
||
|
return CSSLint.getRules().map(rule => {
|
||
|
const output = {};
|
||
|
for (const [key, value] of Object.entries(rule)) {
|
||
|
if (typeof value !== 'function') {
|
||
|
output[key] = value;
|
||
|
}
|
||
|
}
|
||
|
return output;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getStylelintRules() {
|
||
|
loadScript(['/vendor/stylelint-bundle/stylelint-bundle.min.js']);
|
||
|
const stylelint = require('stylelint');
|
||
|
const options = {};
|
||
|
const rxPossible = /\bpossible:("(?:[^"]*?)"|\[(?:[^\]]*?)\]|\{(?:[^}]*?)\})/g;
|
||
|
const rxString = /"([-\w\s]{3,}?)"/g;
|
||
|
for (const id of Object.keys(stylelint.rules)) {
|
||
|
const ruleCode = String(stylelint.rules[id]);
|
||
|
const sets = [];
|
||
|
let m, mStr;
|
||
|
while ((m = rxPossible.exec(ruleCode))) {
|
||
|
const possible = m[1];
|
||
|
const set = [];
|
||
|
while ((mStr = rxString.exec(possible))) {
|
||
|
const s = mStr[1];
|
||
|
if (s.includes(' ')) {
|
||
|
set.push(...s.split(/\s+/));
|
||
|
} else {
|
||
|
set.push(s);
|
||
|
}
|
||
|
}
|
||
|
if (possible.includes('ignoreAtRules')) {
|
||
|
set.push('ignoreAtRules');
|
||
|
}
|
||
|
if (possible.includes('ignoreShorthands')) {
|
||
|
set.push('ignoreShorthands');
|
||
|
}
|
||
|
if (set.length) {
|
||
|
sets.push(set);
|
||
|
}
|
||
|
}
|
||
|
if (sets.length) {
|
||
|
options[id] = sets;
|
||
|
}
|
||
|
}
|
||
|
return options;
|
||
|
}
|
||
|
|
||
|
function loadParserLib() {
|
||
|
if (typeof parserlib !== 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
importScripts('/vendor-overwrites/csslint/parserlib.js');
|
||
|
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
|
||
|
}
|
||
|
|
||
|
const loadedUrls = new Set();
|
||
|
function loadScript(urls) {
|
||
|
urls = urls.filter(u => !loadedUrls.has(u));
|
||
|
importScripts(...urls);
|
||
|
urls.forEach(u => loadedUrls.add(u));
|
||
|
}
|
||
|
|
||
|
function createAPI(methods) {
|
||
|
self.onmessage = e => {
|
||
|
const message = e.data;
|
||
|
Promise.resolve()
|
||
|
.then(() => methods[message.action](...message.args))
|
||
|
.then(result => ({
|
||
|
id: message.id,
|
||
|
error: false,
|
||
|
data: result
|
||
|
}))
|
||
|
.catch(err => ({
|
||
|
id: message.id,
|
||
|
error: true,
|
||
|
data: cloneError(err)
|
||
|
}))
|
||
|
.then(data => self.postMessage(data));
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function cloneError(err) {
|
||
|
return Object.assign({
|
||
|
name: err.name,
|
||
|
stack: err.stack,
|
||
|
message: err.message,
|
||
|
lineNumber: err.lineNumber,
|
||
|
columnNumber: err.columnNumber,
|
||
|
fileName: err.fileName
|
||
|
}, err);
|
||
|
}
|