Skip to content

Commit b252294

Browse files
authored
Merge pull request #202 from bmish/config-emoji-missing-notice
2 parents 5981e42 + 6145dfd commit b252294

File tree

3 files changed

+158
-62
lines changed

3 files changed

+158
-62
lines changed

lib/rule-notices.ts

Lines changed: 78 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,51 @@ export const NOTICE_TYPE_DEFAULT_PRESENCE_AND_ORDERING: {
3838
[NOTICE_TYPE.TYPE]: false,
3939
};
4040

41+
function severityToTerminology(severity: SEVERITY_TYPE) {
42+
switch (severity) {
43+
case SEVERITY_TYPE.error:
44+
return 'is enabled';
45+
case SEVERITY_TYPE.warn:
46+
return '_warns_';
47+
case SEVERITY_TYPE.off:
48+
return 'is _disabled_';
49+
/* istanbul ignore next -- this shouldn't happen */
50+
default:
51+
throw new Error(`Unknown severity: ${severity}`);
52+
}
53+
}
54+
55+
function configsToNoticeSentence(
56+
configs: string[],
57+
severity: SEVERITY_TYPE,
58+
configsLinkOrWord: string,
59+
configLinkOrWord: string,
60+
configEmojis: ConfigEmojis,
61+
useGenericConfigEmoji: boolean
62+
): string | undefined {
63+
// Create CSV list of configs with their emojis.
64+
const csv = configs
65+
.map((config) => {
66+
const emoji = findConfigEmoji(configEmojis, config);
67+
return `${emoji ? `${emoji} ` : ''}\`${config}\``;
68+
})
69+
.join(', ');
70+
71+
const term = severityToTerminology(severity);
72+
const sentence =
73+
configs.length > 1
74+
? `This rule ${term} in the following ${configsLinkOrWord}: ${csv}.`
75+
: configs.length === 1
76+
? `This rule ${term} in the ${
77+
// If the config's emoji isn't already being used at the front of the notice, include it here by using the CSV.
78+
// If the config's emoji IS already being used, just use the config name only here.
79+
useGenericConfigEmoji ? csv : `\`${configs?.[0]}\``
80+
} ${configLinkOrWord}.`
81+
: undefined;
82+
83+
return sentence;
84+
}
85+
4186
/**
4287
* An object containing the text for each notice type (as a string or function to generate the string).
4388
*/
@@ -82,10 +127,9 @@ const RULE_NOTICES: {
82127

83128
// If one applicable config with an emoji, use the emoji for that config, otherwise use the general config emoji.
84129
let emoji = '';
85-
if (
86-
configsEnabled.length + configsWarn.length + configsDisabled.length >
87-
1
88-
) {
130+
const useGenericConfigEmoji =
131+
configsEnabled.length + configsWarn.length + configsDisabled.length > 1;
132+
if (useGenericConfigEmoji) {
89133
emoji = EMOJI_CONFIG;
90134
} else if (configsEnabled.length > 0) {
91135
// @ts-expect-error -- will always be a string thanks to fallback
@@ -107,63 +151,36 @@ const RULE_NOTICES: {
107151
});
108152
}
109153

110-
// List of configs that enable the rule.
111-
const configsEnabledCSV = configsEnabled
112-
.map((configEnabled) => {
113-
const emoji = configEmojis.find(
114-
(configEmoji) => configEmoji.config === configEnabled
115-
)?.emoji;
116-
return `${emoji ? `${emoji} ` : ''}\`${configEnabled}\``;
117-
})
118-
.join(', ');
119-
120-
// List of configs that warn for the rule.
121-
const configsWarnCSV = configsWarn
122-
.map((configWarn) => {
123-
const emoji = configEmojis.find(
124-
(configEmoji) => configEmoji.config === configWarn
125-
)?.emoji;
126-
return `${emoji ? `${emoji} ` : ''}\`${configWarn}\``;
127-
})
128-
.join(', ');
129-
130-
// List of configs that disable the rule.
131-
const configsDisabledCSV = configsDisabled
132-
.map((configDisabled) => {
133-
const emoji = configEmojis.find(
134-
(configEmoji) => configEmoji.config === configDisabled
135-
)?.emoji;
136-
return `${emoji ? `${emoji} ` : ''}\`${configDisabled}\``;
137-
})
138-
.join(', ');
139-
140-
// Complete sentence for configs that enable the rule.
141-
const SENTENCE_ENABLED =
142-
configsEnabled.length > 1
143-
? `This rule is enabled in the following ${configsLinkOrWord}: ${configsEnabledCSV}.`
144-
: configsEnabled.length === 1
145-
? `This rule is enabled in the \`${configsEnabled?.[0]}\` ${configLinkOrWord}.`
146-
: undefined;
147-
148-
// Complete sentence for configs that warn for the rule.
149-
const SENTENCE_WARN =
150-
configsWarn.length > 1
151-
? `This rule _warns_ in the following ${configsLinkOrWord}: ${configsWarnCSV}.`
152-
: configsWarn.length === 1
153-
? `This rule _warns_ in the \`${configsWarn?.[0]}\` ${configLinkOrWord}.`
154-
: undefined;
155-
156-
// Complete sentence for configs that disable the rule.
157-
const SENTENCE_DISABLED =
158-
configsDisabled.length > 1
159-
? `This rule is _disabled_ in the following ${configsLinkOrWord}: ${configsDisabledCSV}.`
160-
: configsDisabled.length === 1
161-
? `This rule is _disabled_ in the \`${configsDisabled?.[0]}\` ${configLinkOrWord}.`
162-
: undefined;
163-
164-
return `${emoji} ${[SENTENCE_ENABLED, SENTENCE_WARN, SENTENCE_DISABLED]
165-
.filter((sentence) => sentence !== undefined)
166-
.join(' ')}`;
154+
const sentences = [
155+
configsToNoticeSentence(
156+
configsEnabled,
157+
SEVERITY_TYPE.error,
158+
configsLinkOrWord,
159+
configLinkOrWord,
160+
configEmojis,
161+
useGenericConfigEmoji
162+
),
163+
configsToNoticeSentence(
164+
configsWarn,
165+
SEVERITY_TYPE.warn,
166+
configsLinkOrWord,
167+
configLinkOrWord,
168+
configEmojis,
169+
useGenericConfigEmoji
170+
),
171+
configsToNoticeSentence(
172+
configsDisabled,
173+
SEVERITY_TYPE.off,
174+
configsLinkOrWord,
175+
configLinkOrWord,
176+
configEmojis,
177+
useGenericConfigEmoji
178+
),
179+
]
180+
.filter(Boolean)
181+
.join(' ');
182+
183+
return `${emoji} ${sentences}`;
167184
},
168185

169186
// Deprecated notice has optional "replaced by" rules list.

test/lib/__snapshots__/generator-test.ts.snap

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ exports[`generator #generate rules that are disabled or set to warn generates th
650650
exports[`generator #generate rules that are disabled or set to warn generates the documentation 4`] = `
651651
"# Description of no-baz (\`test/no-baz\`)
652652
653-
💼 This rule is enabled in the \`recommended\` config. This rule is _disabled_ in the \`other\` config.
653+
💼 This rule is enabled in the \`recommended\` config. This rule is _disabled_ in the \`other\` config.
654654
655655
<!-- end auto-generated rule header -->
656656
"
@@ -726,6 +726,31 @@ exports[`generator #generate rules that are disabled or set to warn, only one co
726726
"
727727
`;
728728

729+
exports[`generator #generate rules that are disabled or set to warn, two configs present generates the documentation 1`] = `
730+
"## Rules
731+
<!-- begin auto-generated rules list -->
732+
733+
💼 Configurations enabled in.\\
734+
✅<sup>⚠️</sup> Warns in the \`recommended\` configuration.\\
735+
⌨️<sup>🚫</sup> Disabled in the \`typescript\` configuration.
736+
737+
| Name | Description | 💼 |
738+
| :----------------------------- | :--------------------- | :------------------------------------------------------------------------------------------------------------- |
739+
| [no-foo](docs/rules/no-foo.md) | Description of no-foo. | <span style="white-space:nowrap">✅<sup>⚠️</sup></span> <span style="white-space:nowrap">⌨️<sup>🚫</sup></span> |
740+
741+
<!-- end auto-generated rules list -->
742+
"
743+
`;
744+
745+
exports[`generator #generate rules that are disabled or set to warn, two configs present generates the documentation 2`] = `
746+
"# Description of no-foo (\`test/no-foo\`)
747+
748+
💼 This rule _warns_ in the ✅ \`recommended\` config. This rule is _disabled_ in the ⌨️ \`typescript\` config.
749+
750+
<!-- end auto-generated rule header -->
751+
"
752+
`;
753+
729754
exports[`generator #generate shows column and notice for requiresTypeChecking updates the documentation 1`] = `
730755
"<!-- begin auto-generated rules list -->
731756

test/lib/generator-test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,60 @@ describe('generator', function () {
20152015
});
20162016
});
20172017

2018+
describe('rules that are disabled or set to warn, two configs present', function () {
2019+
beforeEach(function () {
2020+
mockFs({
2021+
'package.json': JSON.stringify({
2022+
name: 'eslint-plugin-test',
2023+
main: 'index.js',
2024+
type: 'module',
2025+
}),
2026+
2027+
'index.js': `
2028+
export default {
2029+
rules: {
2030+
'no-foo': {
2031+
meta: { docs: { description: 'Description of no-foo.' }, },
2032+
create(context) {},
2033+
},
2034+
},
2035+
configs: {
2036+
recommended: {
2037+
rules: {
2038+
'test/no-foo': 1,
2039+
}
2040+
},
2041+
typescript: {
2042+
rules: {
2043+
'test/no-foo': 0,
2044+
}
2045+
},
2046+
}
2047+
};`,
2048+
2049+
'README.md': '## Rules\n',
2050+
2051+
'docs/rules/no-foo.md': '',
2052+
2053+
// Needed for some of the test infrastructure to work.
2054+
node_modules: mockFs.load(
2055+
resolve(__dirname, '..', '..', 'node_modules')
2056+
),
2057+
});
2058+
});
2059+
2060+
afterEach(function () {
2061+
mockFs.restore();
2062+
jest.resetModules();
2063+
});
2064+
2065+
it('generates the documentation', async function () {
2066+
await generate('.');
2067+
expect(readFileSync('README.md', 'utf8')).toMatchSnapshot();
2068+
expect(readFileSync('docs/rules/no-foo.md', 'utf8')).toMatchSnapshot();
2069+
});
2070+
});
2071+
20182072
describe('config emoji matches off/warn emoji superscript', function () {
20192073
beforeEach(function () {
20202074
mockFs({

0 commit comments

Comments
 (0)