diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d1e8ec3b..ca8225e5 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -159,6 +159,10 @@ "message": "Reset", "description": "Used in various parts of UI to indicate that something may be reset to its original state" }, + "genericSavedMessage": { + "message": "Saved", + "description": "Used in various parts of the UI to indicate that something was saved" + }, "confirmNo": { "message": "No", "description": "'No' button in a confirm dialog" @@ -531,6 +535,10 @@ "message": "Invalid JSON format", "description": "Setting linter rules with invalid JSON message" }, + "setLinterInvalidRuleError": { + "message": "Not saved due to these invalid rules:", + "description": "Invalid linter rules will show a message followed by a list of invalid rules" + }, "showCSSLintSettings": { "message": "(Set rules: 0 = disabled; 1 = warning; 2 = error)", "description": "CSSLint rule settings values" diff --git a/edit/edit.css b/edit/edit.css index ea015e6e..83ca4e93 100644 --- a/edit/edit.css +++ b/edit/edit.css @@ -374,16 +374,13 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar right: 4px; top: .5em; } -#help-popup .error { +#help-popup .saved-message { display: none; + color: #090; margin-left: 10px; - color: #900; font-weight: bold; } -#help-popup .error a { - color: #f00; -} -#help-popup .error.show, +#help-popup .saved-message.show, #options .linter-settings { display: inline-block; } @@ -467,6 +464,9 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar #lint td[role="message"] { text-align: left; } +#message-box.center.lint-config #message-box-contents { + text-align: left; +} /************ CSS beautifier ************/ .beautify-options { diff --git a/edit/lint.js b/edit/lint.js index d3e44cd5..796a8974 100644 --- a/edit/lint.js +++ b/edit/lint.js @@ -1,4 +1,4 @@ -/* global CodeMirror CSSLint editors makeSectionVisible showHelp showCodeMirrorPopup */ +/* global CodeMirror CSSLint editors makeSectionVisible showHelp showCodeMirrorPopup messageBox */ /* global stylelintDefaultConfig csslintDefaultRuleset onDOMscripted injectCSS require */ 'use strict'; @@ -56,8 +56,7 @@ function updateLinter(linter) { loadSelectedLinter(linter).then(() => { updateEditors(); }); - $('#linter-settings').style.display = linter === 'null' ? - 'none' : 'inline-block'; + $('#linter-settings').style.display = linter === 'null' ? 'none' : 'inline-block'; } function updateLintReport(cm, delay) { @@ -236,6 +235,27 @@ function showLintHelp() { return showHelp(t('issues'), header + list + ''); } +function showLinterErrorMessage(title, contents) { + messageBox({ + title, + contents, + className: 'danger center lint-config', + buttons: [t('confirmOK')], + }); +} + +function showSavedMessage() { + $('#help-popup .saved-message').classList.add('show'); + clearTimeout($('#help-popup .contents').timer); + $('#help-popup .contents').timer = setTimeout(() => { + // popup may be closed at this point + const msg = $('#help-popup .saved-message'); + if (msg) { + msg.classList.remove('show'); + } + }, 2000); +} + function checkLinter(linter = prefs.get('editor.linter')) { linter = linter.toLowerCase(); if (prefs.get('editor.linter') !== linter) { @@ -244,29 +264,41 @@ function checkLinter(linter = prefs.get('editor.linter')) { return linter; } +function checkRules(linter, rules) { + const invalid = []; + const linterRules = linter === 'stylelint' + ? Object.keys(window.stylelint.rules) + : CSSLint.getRules().map(rule => rule.id); + Object.keys(rules).forEach(rule => { + if (!linterRules.includes(rule)) { + invalid.push(rule); + } + }); + return invalid; +} + function setupLinterSettingsEvents(popup) { $('.save', popup).addEventListener('click', event => { event.preventDefault(); const linter = checkLinter(event.target.dataset.linter); const json = tryJSONparse(popup.codebox.getValue()); if (json && json.rules) { - // it is possible to have stylelint rules popup open & switch to csslint + const invalid = checkRules(linter, json.rules); + if (invalid.length) { + return showLinterErrorMessage( + linter, + t('setLinterInvalidRuleError') + `` + ); + } if (linter === 'stylelint') { setStylelintRules(json.rules); } else { setCSSLintRules(json.rules); } updateLinter(linter); + showSavedMessage(); } else { - $('#help-popup .error').classList.add('show'); - clearTimeout($('#help-popup .contents').timer); - $('#help-popup .contents').timer = setTimeout(() => { - // popup may be closed at this point - const error = $('#help-popup .error'); - if (error) { - error.classList.remove('show'); - } - }, 3000); + showLinterErrorMessage(linter, t('setLinterError')); } }); $('.reset', popup).addEventListener('click', event => { @@ -334,8 +366,8 @@ function setupLinterPopup(rules) { makeButton('reset', 'genericResetLabel'), $element({ tag: 'span', - className: 'error', - textContent: t('setLinterError') + className: 'saved-message', + textContent: t('genericSavedMessage') }) ] })); @@ -357,10 +389,12 @@ function loadSelectedLinter(name) { if (name !== 'null' && !$('script[src*="css-lint.js"]')) { // inject css injectCSS('vendor/codemirror/addon/lint/lint.css'); + injectCSS('msgbox/msgbox.css'); // load CodeMirror lint code scripts.push( 'vendor/codemirror/addon/lint/lint.js', - 'vendor-overwrites/codemirror/addon/lint/css-lint.js' + 'vendor-overwrites/codemirror/addon/lint/css-lint.js', + 'msgbox/msgbox.js' ); } if (name === 'csslint' && !window.CSSLint) {