Skip to content

Commit 3152382

Browse files
committed
chore: rework how severities are defined when creating rules
1 parent 8d281d4 commit 3152382

23 files changed

+39
-52
lines changed

CONTRIBUTING.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { CategoryId } from '../utils/constants'
4242

4343
module.exports = {
4444
meta: {
45+
severity: 'error', // whether the rule should yield 'warn' or 'error'
4546
docs: {
4647
categories: [CategoryId.RECOMMENDED], // You should always use an existing category from the CategoryId enum], or create a new one there
4748
excludeFromConfig: true, // If the rule is not ready to be shipped in any category, set this flag to true, otherwise remove it
@@ -82,7 +83,7 @@ ruleTester.run('my-rule-name', rule, {
8283
When you make changes to rules or create/delete rules, the configuration files and documentation have to be updated. For that, run the following command:
8384

8485
```sh
85-
yarn update-all
86+
pnpm run update-all
8687
```
8788

8889
### Useful resources

lib/configs/flat/addon-interactions.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export = [
88
name: 'storybook:addon-interactions:setup',
99
plugins: {
1010
get storybook() {
11+
// eslint-disable-next-line @typescript-eslint/no-require-imports
1112
return require('../../index')
1213
},
1314
},

lib/configs/flat/csf.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export = [
88
name: 'storybook:csf:setup',
99
plugins: {
1010
get storybook() {
11+
// eslint-disable-next-line @typescript-eslint/no-require-imports
1112
return require('../../index')
1213
},
1314
},

lib/configs/flat/recommended.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export = [
88
name: 'storybook:recommended:setup',
99
plugins: {
1010
get storybook() {
11+
// eslint-disable-next-line @typescript-eslint/no-require-imports
1112
return require('../../index')
1213
},
1314
},

lib/rules/await-interactions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ export = createStorybookRule({
2929
name: 'await-interactions',
3030
defaultOptions: [],
3131
meta: {
32+
severity: 'error',
3233
docs: {
3334
description: 'Interactions should be awaited',
3435
categories: [CategoryId.ADDON_INTERACTIONS, CategoryId.RECOMMENDED],
35-
recommended: 'strict',
3636
},
3737
messages: {
3838
interactionShouldBeAwaited: 'Interaction should be awaited: {{method}}',

lib/rules/context-in-play-function.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ export = createStorybookRule({
2727
defaultOptions: [],
2828
meta: {
2929
type: 'problem',
30+
severity: 'error',
3031
docs: {
3132
description: 'Pass a context when invoking play function of another story',
3233
categories: [CategoryId.RECOMMENDED, CategoryId.ADDON_INTERACTIONS],
33-
recommended: 'strict',
3434
},
3535
messages: {
3636
passContextToPlayFunction: 'Pass a context when invoking play function of another story',

lib/rules/csf-component.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ export = createStorybookRule({
1818
defaultOptions: [],
1919
meta: {
2020
type: 'suggestion',
21+
severity: 'warn',
2122
docs: {
2223
description: 'The component property should be set',
2324
categories: [CategoryId.CSF],
24-
recommended: 'recommended',
2525
},
2626
messages: {
2727
missingComponentProperty: 'Missing component property.',

lib/rules/default-exports.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ export = createStorybookRule({
1919
defaultOptions: [],
2020
meta: {
2121
type: 'problem',
22+
severity: 'error',
2223
docs: {
2324
description: 'Story files should have a default export',
2425
categories: [CategoryId.CSF, CategoryId.RECOMMENDED],
25-
recommended: 'strict',
2626
},
2727
messages: {
2828
shouldHaveDefaultExport: 'The file should have a default export.',

lib/rules/hierarchy-separator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ export = createStorybookRule({
2020
type: 'problem',
2121
fixable: 'code',
2222
hasSuggestions: true,
23+
severity: 'warn',
2324
docs: {
2425
description: 'Deprecated hierarchy separator in title property',
2526
categories: [CategoryId.CSF, CategoryId.RECOMMENDED],
26-
recommended: 'recommended',
2727
},
2828
messages: {
2929
useCorrectSeparators: 'Use correct separators',

lib/rules/meta-inline-properties.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ export = createStorybookRule({
2121
defaultOptions: [{ csfVersion: 3 }],
2222
meta: {
2323
type: 'problem',
24+
severity: 'error',
2425
docs: {
2526
description: 'Meta should only have inline properties',
2627
categories: [CategoryId.CSF, CategoryId.RECOMMENDED],
2728
excludeFromConfig: true,
28-
recommended: 'strict',
2929
},
3030
messages: {
3131
metaShouldHaveInlineProperties: 'Meta should only have inline properties: {{property}}',

lib/rules/no-redundant-story-name.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ export = createStorybookRule({
2929
type: 'suggestion',
3030
fixable: 'code',
3131
hasSuggestions: true,
32+
severity: 'warn',
3233
docs: {
3334
description: 'A story should not have a redundant name property',
3435
categories: [CategoryId.CSF, CategoryId.RECOMMENDED],
35-
recommended: 'recommended',
3636
},
3737
messages: {
3838
removeRedundantName: 'Remove redundant name',

lib/rules/no-stories-of.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ export = createStorybookRule({
1515
defaultOptions: [],
1616
meta: {
1717
type: 'problem',
18+
severity: 'error',
1819
docs: {
1920
description: 'storiesOf is deprecated and should not be used',
2021
categories: [CategoryId.CSF_STRICT],
21-
recommended: 'strict',
2222
},
2323
messages: {
2424
doNotUseStoriesOf: 'storiesOf is deprecated and should not be used',

lib/rules/no-title-property-in-meta.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ export = createStorybookRule({
2020
type: 'problem',
2121
fixable: 'code',
2222
hasSuggestions: true,
23+
severity: 'error',
2324
docs: {
2425
description: 'Do not define a title in meta',
2526
categories: [CategoryId.CSF_STRICT],
26-
recommended: 'strict',
2727
},
2828
messages: {
2929
removeTitleInMeta: 'Remove title property from meta',

lib/rules/no-uninstalled-addons.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ export = createStorybookRule({
3535
],
3636
meta: {
3737
type: 'problem',
38+
severity: 'error',
3839
docs: {
3940
description:
4041
'This rule identifies storybook addons that are invalid because they are either not installed or contain a typo in their name.',
4142
categories: [CategoryId.RECOMMENDED],
42-
recommended: 'strict',
4343
},
4444
messages: {
4545
addonIsNotInstalled: `The {{ addonName }} is not installed in {{packageJsonPath}}. Did you forget to install it or is your package.json in a different location?`,

lib/rules/prefer-pascal-case.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ export = createStorybookRule({
2222
type: 'suggestion',
2323
fixable: 'code',
2424
hasSuggestions: true,
25+
severity: 'warn',
2526
docs: {
2627
description: 'Stories should use PascalCase',
2728
categories: [CategoryId.RECOMMENDED],
28-
recommended: 'stylistic',
2929
},
3030
messages: {
3131
convertToPascalCase: 'Use pascal case',

lib/rules/story-exports.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ export = createStorybookRule({
2424
defaultOptions: [],
2525
meta: {
2626
type: 'problem',
27+
severity: 'error',
2728
docs: {
2829
description: 'A story file must contain at least one story export',
2930
categories: [CategoryId.RECOMMENDED, CategoryId.CSF],
30-
recommended: 'strict',
3131
},
3232
messages: {
3333
shouldHaveStoryExport: 'The file should have at least one story export',

lib/rules/use-storybook-expect.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ export = createStorybookRule<TDefaultOptions, string>({
2424
type: 'suggestion',
2525
fixable: 'code',
2626
schema: [],
27+
severity: 'error',
2728
docs: {
2829
description: 'Use expect from `@storybook/test` or `@storybook/jest`',
2930
categories: [CategoryId.ADDON_INTERACTIONS, CategoryId.RECOMMENDED],
30-
recommended: 'strict',
3131
},
3232
messages: {
3333
useExpectFromStorybook:
34-
'Do not use global expect directly in the story. You should import it from `@storybook/test` or `@storybook/jest` instead.',
34+
'Do not use global expect directly in the story. You should import it from `@storybook/test` (preferrably) or `@storybook/jest` instead.',
3535
},
3636
},
3737

lib/rules/use-storybook-testing-library.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ export = createStorybookRule({
1818
type: 'suggestion',
1919
fixable: 'code',
2020
hasSuggestions: true,
21+
severity: 'error',
2122
docs: {
2223
description: 'Do not use testing-library directly on stories',
2324
categories: [CategoryId.ADDON_INTERACTIONS, CategoryId.RECOMMENDED],
24-
recommended: 'strict',
2525
},
2626
schema: [],
2727
messages: {
2828
updateImports: 'Update imports',
2929
dontUseTestingLibraryDirectly:
30-
'Do not use `{{library}}` directly in the story. You should import the functions from `@storybook/testing-library` instead.',
30+
'Do not use `{{library}}` directly in the story. You should import the functions from `@storybook/test` (preferrably) or `@storybook/testing-library` instead.',
3131
},
3232
},
3333

lib/types/index.ts

+9-14
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import { TSESLint } from '@typescript-eslint/utils'
22
import { CategoryId } from '../utils/constants'
3-
import {
4-
RuleRecommendation,
5-
RuleRecommendationAcrossConfigs,
6-
} from '@typescript-eslint/utils/ts-eslint'
73

84
export type RuleModule = TSESLint.RuleModule<'', []> & {
9-
meta: { hasSuggestions?: boolean; docs: { recommendedConfig?: 'error' | 'warn' } }
5+
meta: { hasSuggestions?: boolean }
106
}
117

128
// These 2 types are copied from @typescript-eslint/experimental-utils' CreateRuleMeta
@@ -20,23 +16,21 @@ export type StorybookRuleMetaDocs = TSESLint.RuleMetaDataDocs & {
2016
* Which configs the rule should be part of
2117
*/
2218
categories?: CategoryId[]
23-
24-
/**
25-
* If a string config name, which starting config this rule is enabled in.
26-
* If an object, which settings it has enabled in each of those configs.
27-
*/
28-
recommended?: RuleRecommendation | RuleRecommendationAcrossConfigs<unknown[]>
2919
}
3020

31-
export type StorybookRuleMeta<TMessageIds extends string> = TSESLint.RuleMetaData<
21+
export type StorybookRuleMeta<TMessageIds extends string = ''> = TSESLint.RuleMetaData<
3222
TMessageIds,
3323
StorybookRuleMetaDocs
34-
>
24+
> & {
25+
/**
26+
* Severity of the rule to be defined in eslint config
27+
*/
28+
severity: 'off' | 'warn' | 'error'
29+
}
3530

3631
// Comment out for testing purposes:
3732
// const docs: StorybookRuleMetaDocs = {
3833
// description: 'bla',
39-
// recommended: 'strict',
4034
// }
4135

4236
// const meta: StorybookRuleMeta<'someId'> = {
@@ -46,4 +40,5 @@ export type StorybookRuleMeta<TMessageIds extends string> = TSESLint.RuleMetaDat
4640
// type: 'problem',
4741
// schema: [],
4842
// docs,
43+
// severity: 'error',
4944
// }

tools/generate-rule.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ const generateRule = async () => {
8080
defaultOptions: [],
8181
meta: {
8282
type: 'problem', // \`problem\`, \`suggestion\`, or \`layout\`
83+
severity: 'error', // or 'warn'
8384
docs: {
8485
description: '${ruleDescription}',
8586
// Add the categories that suit this rule.
8687
categories: [CategoryId.RECOMMENDED],
87-
recommended: 'recommended',
8888
},
8989
messages: {
9090
anyMessageIdHere: 'Fill me in',

tools/update-lib-flat-configs.ts

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function formatCategory(category: TCategory) {
2828
name: 'storybook:${category.categoryId}:setup',
2929
plugins: {
3030
get storybook() {
31+
// eslint-disable-next-line @typescript-eslint/no-require-imports
3132
return require('../../index')
3233
}
3334
}

tools/utils/rules.ts

+5-18
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@ import fs from 'fs'
22
import path from 'path'
33

44
import { createStorybookRule } from '../../lib/utils/create-storybook-rule'
5+
import { StorybookRuleMeta } from '../../lib/types'
56

67
const ROOT = path.resolve(__dirname, '../../lib/rules')
78

89
export type TRule = ReturnType<typeof createStorybookRule> & {
9-
meta: {
10-
docs: {
11-
categories?: string[]
12-
category?: string
13-
excludeFromConfig?: boolean
14-
}
15-
}
10+
meta: StorybookRuleMeta
1611
}
1712

1813
const rules = fs
@@ -21,28 +16,20 @@ const rules = fs
2116
.map((file) => path.basename(file, '.ts'))
2217
.map((name) => {
2318
const rule = require(path.join(ROOT, name)) as TRule
24-
const meta = { ...rule.meta }
19+
const meta: StorybookRuleMeta = { ...rule.meta }
2520
if (meta.docs && !meta.docs.categories) {
2621
meta.docs = { ...meta.docs }
2722
meta.docs.categories = []
28-
29-
if (meta.docs.category) {
30-
meta.docs.categories.push(meta.docs.category)
31-
delete meta.docs.category
32-
}
33-
34-
if (meta.docs.recommended) {
35-
meta.docs.categories.push('recommended')
36-
}
3723
}
24+
3825
return {
3926
ruleId: `storybook/${name}`,
4027
name,
4128
meta,
4229
}
4330
})
4431
// We might have rules which are almost ready but should not be shipped
45-
.filter((rule) => !rule.meta.docs.excludeFromConfig)
32+
.filter((rule) => !rule.meta.docs?.excludeFromConfig)
4633

4734
export type TRules = typeof rules
4835

tools/utils/updates.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function formatRules(rules: TCategory['rules'], exclude?: string[]) {
1515
const obj = rules.reduce(
1616
(setting, rule) => {
1717
if (!exclude?.includes(rule.ruleId)) {
18-
setting[rule.ruleId] = rule.meta.docs.recommended || 'error'
18+
setting[rule.ruleId] = rule.meta.severity || 'error'
1919
}
2020
return setting
2121
},
@@ -26,7 +26,7 @@ export function formatRules(rules: TCategory['rules'], exclude?: string[]) {
2626
}
2727

2828
export function formatSingleRule(rules: TCategory['rules'], ruleId: string) {
29-
const ruleOpt = rules.find((rule) => rule.ruleId === ruleId)?.meta.docs.recommended || 'error'
29+
const ruleOpt = rules.find((rule) => rule.ruleId === ruleId)?.meta.severity || 'error'
3030

3131
return JSON.stringify({ [ruleId]: ruleOpt }, null, 2)
3232
}

0 commit comments

Comments
 (0)