forked from jest-community/eslint-plugin-jest
/
rule-notices.ts
116 lines (96 loc) · 3.41 KB
/
rule-notices.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import plugin from '../src';
enum MESSAGE_TYPE {
CONFIGS = 'configs',
DEPRECATED = 'deprecated',
FIXABLE = 'fixable',
HAS_SUGGESTIONS = 'hasSuggestions',
}
export const MESSAGES = {
[MESSAGE_TYPE.CONFIGS]:
'💼 This rule is enabled in the following [configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations):',
[MESSAGE_TYPE.DEPRECATED]: '❌ This rule is deprecated.',
[MESSAGE_TYPE.FIXABLE]:
'🔧 This rule is automatically fixable using the `--fix` [option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) on the command line.',
[MESSAGE_TYPE.HAS_SUGGESTIONS]:
'💡 This rule provides [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) that can be applied manually.',
};
type Rule = typeof plugin.rules[string];
/**
* Get config names that a given rule belongs to.
*/
function getConfigsForRule(ruleName: string) {
const { configs } = plugin;
const configNames: Array<keyof typeof configs> = [];
let configName: keyof typeof configs;
for (configName in configs) {
const config = configs[configName];
const value = config.rules[`jest/${ruleName}`];
const isEnabled = [2, 'error'].includes(value);
if (isEnabled) {
configNames.push(configName);
}
}
return configNames.sort();
}
/**
* Convert list of configs to string list of formatted names.
*/
function configNamesToList(configNames: readonly string[]) {
return `\`${configNames.join('`, `')}\``;
}
/**
* Convert list of rule names to string list of links.
*/
function rulesNamesToList(ruleNames: readonly string[]) {
return ruleNames.map(ruleName => `[${ruleName}](${ruleName}.md)`).join(', ');
}
/**
* Determine which notices should and should not be included at the top of a rule doc.
*/
export function getNoticesForRule(rule: Rule) {
const notices: {
[key in MESSAGE_TYPE]: boolean;
} = {
[MESSAGE_TYPE.CONFIGS]: !rule.meta.deprecated,
[MESSAGE_TYPE.DEPRECATED]: rule.meta.deprecated || false,
[MESSAGE_TYPE.FIXABLE]: Boolean(rule.meta.fixable),
[MESSAGE_TYPE.HAS_SUGGESTIONS]: rule.meta.hasSuggestions || false,
};
return notices;
}
/**
* Get the lines for the notice section at the top of a rule doc.
*/
export function getRuleNoticeLines(ruleName: string) {
const lines: string[] = [];
const rule = plugin.rules[ruleName];
const notices = getNoticesForRule(rule);
let messageType: keyof typeof notices;
for (messageType in notices) {
const expected = notices[messageType];
if (!expected) {
// This notice should not be included.
continue;
}
lines.push(''); // Blank line first.
if (messageType === MESSAGE_TYPE.CONFIGS) {
// This notice should have a list of the rule's configs.
const configsEnabled = getConfigsForRule(ruleName);
const message = `${MESSAGES[MESSAGE_TYPE.CONFIGS]} ${configNamesToList(
configsEnabled,
)}.`;
lines.push(message);
} else if (messageType === MESSAGE_TYPE.DEPRECATED) {
// This notice should include links to the replacement rule(s) if available.
const message = rule.meta.replacedBy
? `${MESSAGES[messageType]} It was replaced by ${rulesNamesToList(
rule.meta.replacedBy,
)}.`
: MESSAGES[messageType];
lines.push(message);
} else {
lines.push(MESSAGES[messageType]);
}
}
return lines;
}