Skip to content

Commit c5ae40f

Browse files
authored
Merge pull request #148 from bmish/name-col-wrap
2 parents cc2727c + 046e7a9 commit c5ae40f

File tree

6 files changed

+149
-32
lines changed

6 files changed

+149
-32
lines changed

lib/legend.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ const LEGENDS: {
2929
configEmojis,
3030
urlConfigs,
3131
ignoreConfig,
32-
}: {
33-
plugin: Plugin;
34-
configEmojis: ConfigEmojis;
35-
ignoreConfig: string[];
36-
urlConfigs?: string;
3732
}) => {
3833
/* istanbul ignore next -- this shouldn't happen */
3934
if (!plugin.configs) {
@@ -83,7 +78,7 @@ const LEGENDS: {
8378
},
8479

8580
// Legends are included for each rule type present.
86-
[COLUMN_TYPE.TYPE]: ({ plugin }: { plugin: Plugin }) => {
81+
[COLUMN_TYPE.TYPE]: ({ plugin }) => {
8782
/* istanbul ignore next -- this shouldn't happen */
8883
if (!plugin.rules) {
8984
throw new Error(

lib/rule-list-columns.ts

+28-11
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,11 @@ export const COLUMN_HEADER: {
3535
configNames: string[];
3636
configEmojis: ConfigEmojis;
3737
ignoreConfig: string[];
38+
details: RuleDetails[];
3839
}) => string);
3940
} = {
4041
// Use the general config emoji if there are multiple configs or the sole config doesn't have an emoji.
41-
[COLUMN_TYPE.CONFIGS]: ({
42-
configNames,
43-
configEmojis,
44-
ignoreConfig,
45-
}: {
46-
configNames: string[];
47-
configEmojis: ConfigEmojis;
48-
ignoreConfig: string[];
49-
urlConfigs?: string;
50-
}) => {
42+
[COLUMN_TYPE.CONFIGS]: ({ configNames, configEmojis, ignoreConfig }) => {
5143
const configNamesWithoutIgnored = configNames.filter(
5244
(configName) => !ignoreConfig?.includes(configName)
5345
);
@@ -58,12 +50,37 @@ export const COLUMN_HEADER: {
5850
)?.emoji ?? EMOJI_CONFIG;
5951
},
6052

53+
[COLUMN_TYPE.NAME]: ({ details }) => {
54+
const ruleNames = details.map((detail) => detail.name);
55+
const longestRuleNameLength = Math.max(
56+
...ruleNames.map(({ length }) => length)
57+
);
58+
const ruleDescriptions = details.map((detail) => detail.description);
59+
const longestRuleDescriptionLength = Math.max(
60+
...ruleDescriptions.map((description) =>
61+
description ? description.length : 0
62+
)
63+
);
64+
65+
const title = 'Name';
66+
67+
// Add nbsp spaces to prevent rule names from wrapping to multiple lines.
68+
// Generally only needed when long descriptions are present causing the name column to wrap.
69+
const spaces =
70+
ruleNames.length > 0 &&
71+
longestRuleDescriptionLength >= 60 &&
72+
longestRuleNameLength > title.length
73+
? ' '.repeat(longestRuleNameLength - title.length)
74+
: '';
75+
76+
return `${title}${spaces}`;
77+
},
78+
6179
// Simple strings.
6280
[COLUMN_TYPE.DEPRECATED]: EMOJI_DEPRECATED,
6381
[COLUMN_TYPE.DESCRIPTION]: 'Description',
6482
[COLUMN_TYPE.FIXABLE]: EMOJI_FIXABLE,
6583
[COLUMN_TYPE.HAS_SUGGESTIONS]: EMOJI_HAS_SUGGESTIONS,
66-
[COLUMN_TYPE.NAME]: 'Name',
6784
[COLUMN_TYPE.REQUIRES_TYPE_CHECKING]: EMOJI_REQUIRES_TYPE_CHECKING,
6885
[COLUMN_TYPE.TYPE]: EMOJI_TYPE,
6986
};

lib/rule-list.ts

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ function generateRulesListMarkdown(
104104
configNames: Object.keys(configsToRules),
105105
configEmojis,
106106
ignoreConfig,
107+
details,
107108
})
108109
: headerStrOrFn,
109110
];

lib/rule-notices.ts

+3-15
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,7 @@ const RULE_NOTICES: {
4949
}) => string);
5050
} = {
5151
// Configs notice varies based on whether the rule is enabled in one or more configs.
52-
[NOTICE_TYPE.CONFIGS]: ({
53-
configsEnabled,
54-
configEmojis,
55-
urlConfigs,
56-
}: {
57-
configsEnabled?: string[];
58-
configEmojis: ConfigEmojis;
59-
urlConfigs?: string;
60-
}) => {
52+
[NOTICE_TYPE.CONFIGS]: ({ configsEnabled, configEmojis, urlConfigs }) => {
6153
// Add link to configs documentation if provided.
6254
const configsLinkOrWord = urlConfigs
6355
? `[configs](${urlConfigs})`
@@ -93,18 +85,14 @@ const RULE_NOTICES: {
9385
},
9486

9587
// Deprecated notice has optional "replaced by" rules list.
96-
[NOTICE_TYPE.DEPRECATED]: ({
97-
replacedBy,
98-
}: {
99-
replacedBy?: readonly string[] | undefined;
100-
}) =>
88+
[NOTICE_TYPE.DEPRECATED]: ({ replacedBy }) =>
10189
`${EMOJI_DEPRECATED} This rule is deprecated.${
10290
replacedBy && replacedBy.length > 0
10391
? ` It was replaced by ${ruleNamesToList(replacedBy)}.`
10492
: ''
10593
}`,
10694

107-
[NOTICE_TYPE.TYPE]: ({ type }: { type?: RULE_TYPE }) => {
95+
[NOTICE_TYPE.TYPE]: ({ type }) => {
10896
/* istanbul ignore next -- this shouldn't happen */
10997
if (!type) {
11098
throw new Error(

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

+38
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,44 @@ Pre-existing notice about the rule being recommended.
439439
Details."
440440
`;
441441

442+
exports[`generator #generate rule with long-enough description to require name column wrapping avoidance adds spaces to the name column 1`] = `
443+
"## Rules
444+
<!-- begin rules list -->
445+
446+
| Name&nbsp;&nbsp; | Description |
447+
| :----------------------------- | :---------------------------------------------------------------------------------- |
448+
| [no-foo](docs/rules/no-foo.md) | over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars |
449+
450+
<!-- end rules list -->
451+
"
452+
`;
453+
454+
exports[`generator #generate rule with long-enough description to require name column wrapping avoidance adds spaces to the name column 2`] = `
455+
"# Over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars (\`test/no-foo\`)
456+
457+
<!-- end rule header -->
458+
"
459+
`;
460+
461+
exports[`generator #generate rule with long-enough description to require name column wrapping avoidance but rule name too short does not add spaces to name column 1`] = `
462+
"## Rules
463+
<!-- begin rules list -->
464+
465+
| Name | Description |
466+
| :----------------------- | :---------------------------------------------------------------------------------- |
467+
| [foo](docs/rules/foo.md) | over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars |
468+
469+
<!-- end rules list -->
470+
"
471+
`;
472+
473+
exports[`generator #generate rule with long-enough description to require name column wrapping avoidance but rule name too short does not add spaces to name column 2`] = `
474+
"# Over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars (\`test/foo\`)
475+
476+
<!-- end rule header -->
477+
"
478+
`;
479+
442480
exports[`generator #generate rule with type, type column enabled displays the type 1`] = `
443481
"## Rules
444482
<!-- begin rules list -->

test/lib/generator-test.ts

+78
Original file line numberDiff line numberDiff line change
@@ -3146,5 +3146,83 @@ describe('generator', function () {
31463146
expect(readFileSync('docs/rules/no-foo.md', 'utf8')).toMatchSnapshot();
31473147
});
31483148
});
3149+
3150+
describe('rule with long-enough description to require name column wrapping avoidance', function () {
3151+
beforeEach(function () {
3152+
mockFs({
3153+
'package.json': JSON.stringify({
3154+
name: 'eslint-plugin-test',
3155+
main: 'index.js',
3156+
type: 'module',
3157+
}),
3158+
3159+
'index.js': `
3160+
export default {
3161+
rules: {
3162+
'no-foo': { meta: { docs: { description: 'over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars'} }, create(context) {} },
3163+
},
3164+
};`,
3165+
3166+
'README.md': '## Rules\n',
3167+
3168+
'docs/rules/no-foo.md': '',
3169+
3170+
// Needed for some of the test infrastructure to work.
3171+
node_modules: mockFs.load(
3172+
resolve(__dirname, '..', '..', 'node_modules')
3173+
),
3174+
});
3175+
});
3176+
3177+
afterEach(function () {
3178+
mockFs.restore();
3179+
jest.resetModules();
3180+
});
3181+
3182+
it('adds spaces to the name column', async function () {
3183+
await generate('.');
3184+
expect(readFileSync('README.md', 'utf8')).toMatchSnapshot();
3185+
expect(readFileSync('docs/rules/no-foo.md', 'utf8')).toMatchSnapshot();
3186+
});
3187+
});
3188+
3189+
describe('rule with long-enough description to require name column wrapping avoidance but rule name too short', function () {
3190+
beforeEach(function () {
3191+
mockFs({
3192+
'package.json': JSON.stringify({
3193+
name: 'eslint-plugin-test',
3194+
main: 'index.js',
3195+
type: 'module',
3196+
}),
3197+
3198+
'index.js': `
3199+
export default {
3200+
rules: {
3201+
'foo': { meta: { docs: { description: 'over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars over 60 chars'} }, create(context) {} },
3202+
},
3203+
};`,
3204+
3205+
'README.md': '## Rules\n',
3206+
3207+
'docs/rules/foo.md': '',
3208+
3209+
// Needed for some of the test infrastructure to work.
3210+
node_modules: mockFs.load(
3211+
resolve(__dirname, '..', '..', 'node_modules')
3212+
),
3213+
});
3214+
});
3215+
3216+
afterEach(function () {
3217+
mockFs.restore();
3218+
jest.resetModules();
3219+
});
3220+
3221+
it('does not add spaces to name column', async function () {
3222+
await generate('.');
3223+
expect(readFileSync('README.md', 'utf8')).toMatchSnapshot();
3224+
expect(readFileSync('docs/rules/foo.md', 'utf8')).toMatchSnapshot();
3225+
});
3226+
});
31493227
});
31503228
});

0 commit comments

Comments
 (0)