Skip to content

Commit 1316ab0

Browse files
committed
feat: Add link to rule at error; show rule description when mouseovered
1 parent da6c3ff commit 1316ab0

File tree

6 files changed

+44
-52
lines changed

6 files changed

+44
-52
lines changed

packages/backend/api/init.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
const loadRules = require('eslint/lib/load-rules');
1+
const { Linter } = require('eslint');
22
const reactPlugin = require('eslint-plugin-react');
33
const jsxA11yPlugin = require('eslint-plugin-jsx-a11y');
44

5+
const eslintRules = new Linter().getRules();
6+
57
const airbnb = require('eslint-config-airbnb');
68
const google = require('eslint-config-google');
79
const standard = require('eslint-config-standard');
@@ -30,10 +32,15 @@ const configs = {
3032
eslint: getRules(eslint)
3133
};
3234

35+
const getRuleInfo = ([name, value]) => ({
36+
name,
37+
docs: value.meta.docs
38+
});
39+
3340
const rulesList = {
34-
eslint: Object.keys(loadRules()),
35-
react: Object.keys(reactPlugin.rules),
36-
'jsx-a11y': Object.keys(jsxA11yPlugin.rules)
41+
eslint: [...eslintRules].map(getRuleInfo),
42+
react: Object.entries(reactPlugin.rules).map(getRuleInfo),
43+
'jsx-a11y': Object.entries(jsxA11yPlugin.rules).map(getRuleInfo)
3744
};
3845

3946
module.exports = (req, res) => {

packages/frontend/Messages.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import bindNode from 'matreshka/bindnode';
44
import display from 'matreshka/binders/display';
55

66
export default class Messages extends MatreshkaArray {
7-
itemRenderer = '<pre class="result-item">{{ line }}:{{ column }} {{ type }} {{ message }}</pre>';
7+
itemRenderer = '<pre class="result-item">{{ line }}:{{ column }} {{ type }} {{ message }} (<a href="{{ link }}" target="_blank">{{ ruleId }}</a>) </pre>';
88
constructor(data, parent) {
99
super()
1010
.bindNode({
@@ -17,6 +17,22 @@ export default class Messages extends MatreshkaArray {
1717
})
1818
.on('*@render', ({ self }) => {
1919
calc(self, 'type', 'severity', severity => (severity === 1 ? 'warning' : 'error'));
20+
calc(self, 'link', 'ruleId', (ruleId) => {
21+
const [groupName, ruleName] = ruleId.split('/');
22+
if (!ruleName) {
23+
return `http://eslint.org/docs/rules/${groupName}`;
24+
}
25+
26+
if (groupName === 'react') {
27+
return `https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/${ruleName}.md`;
28+
}
29+
30+
if (groupName === 'jsx-a11y') {
31+
return `https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/${ruleName}.md`;
32+
}
33+
34+
return null;
35+
});
2036
bindNode(self, 'type', ':sandbox', {
2137
setValue(type, { node }) {
2238
node.classList.add(`result-${type}`);

packages/frontend/Rules/Rule.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
import MatreshkaObject from 'matreshka/object';
22

33
export default class Rule extends MatreshkaObject {
4-
renderer = `<label title="{{ dynamicValueJSON }}" class="col-md-4 col-sm-6 col-xs-12 form-check-label">
5-
<input type="checkbox" checked="{{ isOn }}"> {{ name }}
4+
renderer = ({ docs, name }) => `<label
5+
title="${docs.description || ''}"
6+
class="col-md-4 col-sm-6 col-xs-12 form-check-label"
7+
>
8+
<input
9+
title="{{ dynamicValueJSON }}"
10+
type="checkbox"
11+
checked="{{ isOn }}"
12+
>
13+
${name}
614
</label>`;
715
constructor(data) {
816
super(data)

packages/frontend/Rules/index.js

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import MatreshkaArray from 'matreshka/array';
22
import RulesGroup from './RulesGroup';
3-
// import plugins from '../lint/plugins';
43

54
export default class Rules extends MatreshkaArray {
65
Model = RulesGroup;
@@ -14,36 +13,9 @@ export default class Rules extends MatreshkaArray {
1413
this.trigger('rulechange');
1514
}
1615
});
17-
// .render()
18-
// .recreate(plugins)
19-
// .update(data);
2016
}
2117

22-
/* async render() {
23-
const { payload } = await ( await fetch('/api/init') ).json();
24-
25-
this.recreate(Object.entries(payload).map(([pluginName, value]) => ({
26-
pluginName,
27-
rules: value.map(name => ({ name, value: 'off' }))
28-
})))
29-
}*/
30-
3118
update(config) {
32-
/* const groups = {};
33-
for(const [fullRuleName, value] of Object.entries(config)) {
34-
let [groupName, ruleName] = fullRuleName.split('/');
35-
36-
if(!ruleName) {
37-
groupName = 'eslint';
38-
ruleName = fullRuleName;
39-
}
40-
41-
const group = groups[groupName] || {};
42-
groups[groupName] = group;
43-
44-
group[ruleName] = value;
45-
}*/
46-
4719
for (const group of this) {
4820
for (const rule of group) {
4921
const fullRuleName = group.getFullRuleName(rule.name);
@@ -52,22 +24,6 @@ export default class Rules extends MatreshkaArray {
5224
}
5325

5426
return this;
55-
56-
// console.log(groups)
57-
/* if (!rules) return this;
58-
59-
for (const group of this) {
60-
for (const rule of group) {
61-
const fullRuleName = group.getFullRuleName(rule.ruleName, group.name);
62-
const recommended = (this.useRecommended
63-
&& group.plugin.configs
64-
&& group.plugin.configs.recommended
65-
&& group.plugin.configs.recommended.rules)
66-
|| {};
67-
68-
rule.value = rules[fullRuleName] || recommended[fullRuleName] || 'off';
69-
}
70-
}*/
7127
}
7228

7329
toJSON() {

packages/frontend/css/style.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,11 @@ button[type="reset"]:active {}
983983
border: 1px solid transparent;
984984
margin: 15px 0;
985985
padding: 0.8em;
986+
white-space: normal;
987+
}
988+
989+
.result-item a {
990+
white-space: nowrap;
986991
}
987992

988993
.result-item:empty {

packages/frontend/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ module.exports = new class App extends MatreshkaObject {
6262

6363
this.rules.recreate(Object.entries(rulesList).map(([pluginName, value]) => ({
6464
pluginName,
65-
rules: value.map(name => ({ name, value: 'off' }))
65+
rules: value.map(({ name, docs }) => ({ name, docs, value: 'off' }))
6666
})));
6767
}
6868

0 commit comments

Comments
 (0)