Add stylelint settings popup & cleanup
This commit is contained in:
parent
07dce1006d
commit
06cd78b643
|
@ -506,6 +506,23 @@
|
||||||
"message": "Remove section",
|
"message": "Remove section",
|
||||||
"description": "Label for the button to remove a section"
|
"description": "Label for the button to remove a section"
|
||||||
},
|
},
|
||||||
|
"setStylelintLink": {
|
||||||
|
"message": "Get a full list of rules from $link$",
|
||||||
|
"description": "Stylelint rules link",
|
||||||
|
"placeholders": {
|
||||||
|
"link": {
|
||||||
|
"content": "$1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"setStylelintRules": {
|
||||||
|
"message": "Set stylelint rules",
|
||||||
|
"description": "Stylelint popup header"
|
||||||
|
},
|
||||||
|
"setStylelintError": {
|
||||||
|
"message": "Invalid JSON format",
|
||||||
|
"description": "Stylelint invalid JSON message"
|
||||||
|
},
|
||||||
"shortcuts": {
|
"shortcuts": {
|
||||||
"message": "Shortcuts",
|
"message": "Shortcuts",
|
||||||
"description": "Go to shortcut configuration"
|
"description": "Go to shortcut configuration"
|
||||||
|
|
|
@ -198,6 +198,9 @@
|
||||||
<option value="csslint" selected>CSSLint</option>
|
<option value="csslint" selected>CSSLint</option>
|
||||||
<option value="stylelint">stylelint</option>
|
<option value="stylelint">stylelint</option>
|
||||||
</select>
|
</select>
|
||||||
|
<svg id="stylelint-settings" class="svg-icon settings">
|
||||||
|
<use xlink:href="#svg-icon-settings"/>
|
||||||
|
</svg>
|
||||||
</section>
|
</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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
@ -219,6 +222,9 @@
|
||||||
<symbol id="svg-icon-close" height="16" width="12" viewBox="0 0 12 16">
|
<symbol id="svg-icon-close" height="16" width="12" viewBox="0 0 12 16">
|
||||||
<path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path>
|
<path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
<symbol id="svg-icon-settings" height="12" width="12" viewBox="0 0 16 16">
|
||||||
|
<path d="M16 9.45V6.52l-1.8-.3c-.14-.5-.34-.95-.56-1.35L14.7 3.4l-2.07-2.1-1.5 1.03c-.43-.24-.9-.43-1.37-.56L9.46 0H6.54l-.3 1.8c-.5.13-.94.33-1.36.55L3.4 1.32 1.3 3.4l1.07 1.45c-.24.45-.44.92-.57 1.42L0 6.53v2.95l1.8.3c.14.52.33.95.57 1.37l-1.07 1.5 2.06 2.08 1.5-1.07c.44.24.9.45 1.4.57l.3 1.77H9.5l.32-1.8c.47-.13.95-.32 1.34-.56l1.5 1.06 2.07-2.05-1.03-1.5c.24-.45.44-.9.56-1.36L16 9.44v-.02zm-8 1.6C6.3 11.05 4.93 9.7 4.93 8S6.33 4.9 8 4.9s3.06 1.4 3.06 3.1S9.7 11.04 8 11.04z"/>
|
||||||
|
</symbol>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -77,16 +77,19 @@ input[type="checkbox"] {
|
||||||
h2 .svg-icon, label .svg-icon {
|
h2 .svg-icon, label .svg-icon {
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
}
|
}
|
||||||
.svg-icon.info {
|
.svg-icon.info,
|
||||||
|
.svg-icon.settings {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
.svg-icon:hover,
|
.svg-icon:hover,
|
||||||
.svg-icon.info {
|
.svg-icon.info,
|
||||||
|
.svg-icon.settings {
|
||||||
fill: #666;
|
fill: #666;
|
||||||
}
|
}
|
||||||
.svg-icon,
|
.svg-icon,
|
||||||
.svg-icon.info:hover {
|
.svg-icon.info:hover,
|
||||||
|
.svg-icon.settings:hover {
|
||||||
fill: #000;
|
fill: #000;
|
||||||
}
|
}
|
||||||
#enabled {
|
#enabled {
|
||||||
|
@ -365,11 +368,28 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
max-height: calc(100vh - 8rem);
|
max-height: calc(100vh - 8rem);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
#help-popup .settings {
|
||||||
|
min-width: 500px;
|
||||||
|
min-height: 200px;
|
||||||
|
max-width: 48vw;
|
||||||
|
}
|
||||||
#help-popup .dismiss {
|
#help-popup .dismiss {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 4px;
|
right: 4px;
|
||||||
top: .5em;
|
top: .5em;
|
||||||
}
|
}
|
||||||
|
#help-popup .error {
|
||||||
|
display: none;
|
||||||
|
margin-left: 10px;
|
||||||
|
color: #900;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#help-popup .error a {
|
||||||
|
color: #f00;
|
||||||
|
}
|
||||||
|
#help-popup .error.show {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.keymap-list {
|
.keymap-list {
|
||||||
font-size: 85%;
|
font-size: 85%;
|
||||||
|
@ -417,7 +437,6 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.0;
|
line-height: 1.0;
|
||||||
width: 245px;
|
|
||||||
}
|
}
|
||||||
#lint table:last-child {
|
#lint table:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
16
edit/edit.js
16
edit/edit.js
|
@ -1,5 +1,5 @@
|
||||||
/* eslint brace-style: 0, operator-linebreak: 0 */
|
/* eslint brace-style: 0, operator-linebreak: 0 */
|
||||||
/* global CodeMirror exports css_beautify parserlib CSSLint initLintHooks setLinter updateLintReport renderLintReport */
|
/* global CodeMirror exports css_beautify parserlib CSSLint initLint setLinter updateLintReport renderLintReport updateLinter */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let styleId = null;
|
let styleId = null;
|
||||||
|
@ -168,7 +168,7 @@ function initCodeMirror() {
|
||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
highlightSelectionMatches: {showToken: /[#.\-\w]/, annotateScrollbar: true},
|
highlightSelectionMatches: {showToken: /[#.\-\w]/, annotateScrollbar: true},
|
||||||
hintOptions: {},
|
hintOptions: {},
|
||||||
lint: setLinter('csslint'),
|
lint: setLinter(prefs.get('editor.linter')),
|
||||||
lintReportDelay: prefs.get('editor.lintReportDelay'),
|
lintReportDelay: prefs.get('editor.lintReportDelay'),
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
theme: 'default',
|
theme: 'default',
|
||||||
|
@ -351,15 +351,7 @@ function acmeEventListener(event) {
|
||||||
break;
|
break;
|
||||||
case 'linter':
|
case 'linter':
|
||||||
if (value !== null && editors.length) {
|
if (value !== null && editors.length) {
|
||||||
if (prefs.get(el.id) !== value) {
|
updateLinter(value);
|
||||||
prefs.set(el.id, value || 'csslint');
|
|
||||||
}
|
|
||||||
editors.forEach(cm => {
|
|
||||||
console.log('set linter to', value);
|
|
||||||
cm.setOption('lint', setLinter(value || 'csslint'));
|
|
||||||
});
|
|
||||||
// CodeMirror.signal(editors.lastActive || editors[0], "change");
|
|
||||||
// save();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1251,7 +1243,7 @@ function initHooks() {
|
||||||
document.getElementById('sections-help').addEventListener('click', showSectionHelp, false);
|
document.getElementById('sections-help').addEventListener('click', showSectionHelp, false);
|
||||||
document.getElementById('keyMap-help').addEventListener('click', showKeyMapHelp, false);
|
document.getElementById('keyMap-help').addEventListener('click', showKeyMapHelp, false);
|
||||||
document.getElementById('cancel-button').addEventListener('click', goBackToManage);
|
document.getElementById('cancel-button').addEventListener('click', goBackToManage);
|
||||||
initLintHooks();
|
initLint();
|
||||||
|
|
||||||
if (!FIREFOX) {
|
if (!FIREFOX) {
|
||||||
$$([
|
$$([
|
||||||
|
|
73
edit/lint.js
73
edit/lint.js
|
@ -1,15 +1,24 @@
|
||||||
/* global CodeMirror CSSLint editors makeSectionVisible showHelp */
|
/* global CodeMirror CSSLint editors makeSectionVisible showHelp stylelintDefaultConfig BG */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function initLintHooks() {
|
function initLint() {
|
||||||
document.getElementById('lint-help').addEventListener('click', showLintHelp);
|
document.getElementById('lint-help').addEventListener('click', showLintHelp);
|
||||||
document.getElementById('lint').addEventListener('click', gotoLintIssue);
|
document.getElementById('lint').addEventListener('click', gotoLintIssue);
|
||||||
window.addEventListener('resize', resizeLintReport);
|
window.addEventListener('resize', resizeLintReport);
|
||||||
|
document.getElementById('stylelint-settings').addEventListener('click', openStylelintSettings);
|
||||||
|
|
||||||
// touch devices don't have onHover events so the element we'll be toggled via clicking (touching)
|
// touch devices don't have onHover events so the element we'll be toggled via clicking (touching)
|
||||||
if ('ontouchstart' in document.body) {
|
if ('ontouchstart' in document.body) {
|
||||||
document.querySelector('#lint h2').addEventListener('click', toggleLintReport);
|
document.querySelector('#lint h2').addEventListener('click', toggleLintReport);
|
||||||
}
|
}
|
||||||
|
BG.chromeLocal.getValue('editorStylelintRules').then(rules => setStylelintRules(rules));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStylelintRules(rules = {}) {
|
||||||
|
if (Object.keys(rules).length === 0) {
|
||||||
|
rules = deepCopy(stylelintDefaultConfig.rules);
|
||||||
|
}
|
||||||
|
BG.chromeLocal.setValue('editorStylelintRules', rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLinter(name) {
|
function setLinter(name) {
|
||||||
|
@ -19,6 +28,18 @@ function setLinter(name) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateLinter(name = 'csslint') {
|
||||||
|
if (prefs.get('editor.linter') !== name) {
|
||||||
|
prefs.set('editor.linter', name);
|
||||||
|
}
|
||||||
|
editors.forEach(cm => {
|
||||||
|
cm.setOption('lint', setLinter(name));
|
||||||
|
updateLintReport(cm, 200);
|
||||||
|
});
|
||||||
|
$('#stylelint-settings').style.display = name === 'stylelint' ?
|
||||||
|
'inline-block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
function updateLintReport(cm, delay) {
|
function updateLintReport(cm, delay) {
|
||||||
if (delay === 0) {
|
if (delay === 0) {
|
||||||
// immediately show pending csslint/stylelint messages in onbeforeunload and save
|
// immediately show pending csslint/stylelint messages in onbeforeunload and save
|
||||||
|
@ -178,3 +199,51 @@ function showLintHelp() {
|
||||||
}
|
}
|
||||||
return showHelp(t('issues'), header + list + '</ul>');
|
return showHelp(t('issues'), header + list + '</ul>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupStylelintSettingsEvents() {
|
||||||
|
let timer;
|
||||||
|
$('#help-popup .save').addEventListener('click', () => {
|
||||||
|
try {
|
||||||
|
setStylelintRules(JSON.parse($('#help-popup textarea').value).rules);
|
||||||
|
// it is possible to have stylelint rules popup open & switch to csslint
|
||||||
|
if (prefs.get('editor.linter') === 'stylelint') {
|
||||||
|
updateLinter('stylelint');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
$('#help-popup .error').classList.add('show');
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
// popup may be closed at this point
|
||||||
|
const error = $('#help-popup .error');
|
||||||
|
if (error) {
|
||||||
|
error.classList.remove('show');
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('#help-popup .reset').addEventListener('click', () => {
|
||||||
|
setStylelintRules();
|
||||||
|
$('#help-popup .settings').value = JSON.stringify({rules: stylelintDefaultConfig.rules}, null, 2);
|
||||||
|
if (prefs.get('editor.linter') === 'stylelint') {
|
||||||
|
updateLinter('stylelint');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openStylelintSettings() {
|
||||||
|
BG.chromeLocal.getValue('editorStylelintRules').then((rules = stylelintDefaultConfig.rules) => {
|
||||||
|
const link = '<a target="_blank" href="https://stylelint.io/demo/">Stylelint</a>';
|
||||||
|
const text = JSON.stringify({rules: rules}, null, 2);
|
||||||
|
const content = `<textarea class="contents settings">${text}</textarea>
|
||||||
|
<p>${t('setStylelintLink', link)}</p>
|
||||||
|
<button class="save" type="button">Save</button>
|
||||||
|
<button class="reset" type="button">Reset</button>
|
||||||
|
<span class="error">
|
||||||
|
${t('setStylelintError')} (<a target="_blank" href="https://jsonlint.com/">JSONLint</a>)
|
||||||
|
</span>`;
|
||||||
|
showHelp(t('setStylelintRules'), content);
|
||||||
|
setupStylelintSettingsEvents();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -66,26 +66,34 @@ CodeMirror.registerHelper("lint", "stylelint", function(text) {
|
||||||
let found = [];
|
let found = [];
|
||||||
const stylelint = require('stylelint').lint;
|
const stylelint = require('stylelint').lint;
|
||||||
if (stylelint) {
|
if (stylelint) {
|
||||||
return stylelint({
|
return BG.chromeLocal.getValue('editorStylelintRules').then((rules = stylelintDefaultConfig.rules) => {
|
||||||
code: text,
|
// stylelintDefaultConfig stored in stylelint-config.js & loaded by edit.html
|
||||||
// stylelintConfig stored in stylelint-config.js & loaded by edit.html
|
if (Object.keys(rules).length === 0) {
|
||||||
config: stylelintConfig
|
rules = stylelintDefaultConfig.rules;
|
||||||
}).then(output => {
|
|
||||||
const warnings = output.results.length ? output.results[0].warnings : [],
|
|
||||||
len = warnings.length;
|
|
||||||
let i, warning;
|
|
||||||
if (len) {
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
warning = warnings[i];
|
|
||||||
found.push({
|
|
||||||
from: CodeMirror.Pos(warning.line - 1, warning.column - 1),
|
|
||||||
to: CodeMirror.Pos(warning.line - 1, warning.column),
|
|
||||||
message: warning.text,
|
|
||||||
severity : warning.severity
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return found;
|
return stylelint({
|
||||||
|
code: text,
|
||||||
|
config: {
|
||||||
|
syntax: stylelintDefaultConfig.syntax,
|
||||||
|
rules: rules
|
||||||
|
}
|
||||||
|
}).then(output => {
|
||||||
|
const warnings = output.results.length ? output.results[0].warnings : [],
|
||||||
|
len = warnings.length;
|
||||||
|
let i, warning;
|
||||||
|
if (len) {
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
warning = warnings[i];
|
||||||
|
found.push({
|
||||||
|
from: CodeMirror.Pos(warning.line - 1, warning.column - 1),
|
||||||
|
to: CodeMirror.Pos(warning.line - 1, warning.column),
|
||||||
|
message: warning.text,
|
||||||
|
severity : warning.severity
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const stylelintConfig = {
|
const stylelintDefaultConfig = {
|
||||||
// 'sugarss' is a indent-based syntax like Sass or Stylus
|
// 'sugarss' is a indent-based syntax like Sass or Stylus
|
||||||
// ref: https://github.com/postcss/postcss#syntaxes
|
// ref: https://github.com/postcss/postcss#syntaxes
|
||||||
syntax: 'sugarss',
|
syntax: 'sugarss',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user