diff --git a/edit.html b/edit.html index 950dfcad..da93b705 100644 --- a/edit.html +++ b/edit.html @@ -93,6 +93,7 @@ + diff --git a/edit/linter-help-dialog.js b/edit/linter-help-dialog.js new file mode 100644 index 00000000..98c11903 --- /dev/null +++ b/edit/linter-help-dialog.js @@ -0,0 +1,56 @@ +/* global showHelp editorWorker */ +'use strict'; + +function createLinterHelpDialog(getIssues) { + let csslintRules; + let preparing; + return {show}; + + function show() { + // FIXME: implement a linterChooser? + const linter = $('#editor.linter').value; + const baseUrl = linter === 'stylelint' + ? 'https://stylelint.io/user-guide/rules/' + // some CSSLint rules do not have a url + : 'https://github.com/CSSLint/csslint/issues/535'; + let headerLink, template; + if (linter === 'csslint') { + headerLink = $createLink('https://github.com/CSSLint/csslint/wiki/Rules', 'CSSLint'); + template = ({rule: ruleID}) => { + const rule = csslintRules.find(rule => rule.id === ruleID); + return rule && + $create('li', [ + $create('b', $createLink(rule.url || baseUrl, rule.name)), + $create('br'), + rule.desc, + ]); + }; + } else { + headerLink = $createLink(baseUrl, 'stylelint'); + template = ({rule}) => + $create('li', + rule === 'CssSyntaxError' ? rule : $createLink(baseUrl + rule, rule)); + } + const header = t('linterIssuesHelp', '\x01').split('\x01'); + const activeRules = getIssues(); + Promise.resolve(linter === 'csslint' && prepareCsslintRules()) + .then(() => + showHelp(t('linterIssues'), + $create([ + header[0], headerLink, header[1], + $create('ul.rules', [...activeRules.values()].map(template)), + ]) + ) + ); + } + + function prepareCsslintRules() { + if (!preparing) { + preparing = editorWorker.getCsslintRules() + .then(rules => { + csslintRules = rules; + }); + } + return preparing; + } +} diff --git a/edit/linter-report.js b/edit/linter-report.js index eec4bd9c..4800223a 100644 --- a/edit/linter-report.js +++ b/edit/linter-report.js @@ -1,8 +1,9 @@ -/* global linter editors clipString */ +/* global linter editors clipString createLinterHelpDialog makeSectionVisible */ 'use strict'; var linterReport = (() => { // eslint-disable-line no-var const cms = new Map(); + const helpDialog = createLinterHelpDialog(getIssues); linter.onChange((annotationsNotSorted, annotations, cm) => { let table = cms.get(cm); @@ -31,12 +32,22 @@ var linterReport = (() => { // eslint-disable-line no-var }); document.addEventListener('DOMContentLoaded', () => { - $('#lint-help').addEventListener('click', showLintHelp); + $('#lint-help').addEventListener('click', helpDialog.show); $('#linter-settings').addEventListener('click', showLintConfig); }, {once: true}); return {refresh}; + function getIssues() { + const issues = new Set(); + for (const table of cms.values()) { + for (const tr of table.trs) { + issues.add(tr.getAnnotation()); + } + } + return issues; + } + function findNextSibling(cms, cm) { let i = editors.indexOf(cm) + 1; while (i < editors.length) { @@ -55,7 +66,13 @@ var linterReport = (() => { // eslint-disable-line no-var const table = $create('table', [caption, tbody]); const trs = []; let empty = true; - return {updateAnnotations, update, isEmpty, element: table}; + return { + element: table, + trs, + updateAnnotations, + update, + isEmpty + }; function isEmpty() { return empty; @@ -112,7 +129,8 @@ var linterReport = (() => { // eslint-disable-line no-var ]); return { element: trElement, - update + update, + getAnnotation: () => anno }; function update(_anno) { @@ -135,7 +153,5 @@ var linterReport = (() => { // eslint-disable-line no-var cm.setSelection(anno.from); } - function showLintHelp() {} - function showLintConfig() {} })();