diff --git a/README.md b/README.md
index ea0d498..e71ab72 100644
--- a/README.md
+++ b/README.md
@@ -169,6 +169,7 @@ This plugin does not support MDX files.
| [`storybook/csf-component`](./docs/rules/csf-component.md) | The component property should be set | |
|
| [`storybook/default-exports`](./docs/rules/default-exports.md) | Story files should have a default export | 🔧 | - csf
- flat/csf
- recommended
- flat/recommended
|
| [`storybook/hierarchy-separator`](./docs/rules/hierarchy-separator.md) | Deprecated hierarchy separator in title property | 🔧 | - csf
- flat/csf
- recommended
- flat/recommended
|
+| [`storybook/meta-inline-properties`](./docs/rules/meta-inline-properties.md) | Meta should only have inline properties | | N/A |
| [`storybook/no-redundant-story-name`](./docs/rules/no-redundant-story-name.md) | A story should not have a redundant name property | 🔧 | - csf
- flat/csf
- recommended
- flat/recommended
|
| [`storybook/no-stories-of`](./docs/rules/no-stories-of.md) | storiesOf is deprecated and should not be used | | - csf-strict
- flat/csf-strict
|
| [`storybook/no-title-property-in-meta`](./docs/rules/no-title-property-in-meta.md) | Do not define a title in meta | 🔧 | - csf-strict
- flat/csf-strict
|
diff --git a/docs/rules/await-interactions.md b/docs/rules/await-interactions.md
index b89cea0..3f34ec0 100644
--- a/docs/rules/await-interactions.md
+++ b/docs/rules/await-interactions.md
@@ -8,12 +8,12 @@
## Rule Details
-Storybook provides an instrumented version of testing library in the [@storybook/testing-library](https://github.com/storybookjs/testing-library/) package. When [writing interactions](https://storybook.js.org/docs/react/essentials/interactions), make sure to **await** them, so that addon-interactions can intercept these helper functions and allow you to step through them when debugging.
+Storybook provides an instrumented version of testing library in the [@storybook/test](https://github.com/storybookjs/storybook/tree/next/code/lib/test) library (formerly available in [@storybook/testing-library](https://github.com/storybookjs/testing-library/) library). When [writing interactions](https://storybook.js.org/docs/essentials/interactions), make sure to **await** them, so that addon-interactions can intercept these helper functions and allow you to step through them when debugging.
Examples of **incorrect** code for this rule:
```js
-import { within, userEvent } from '@storybook/testing-library'
+import { within, userEvent } from '@storybook/test' // or from the legacy package "@storybook/testing-library";
MyStory.play = (context) => {
const canvas = within(context.canvasElement)
@@ -25,7 +25,7 @@ MyStory.play = (context) => {
Examples of **correct** code for this rule:
```js
-import { within, userEvent } from '@storybook/testing-library'
+import { within, userEvent } from '@storybook/test' // or from the legacy package "@storybook/testing-library";
MyStory.play = async (context) => {
const canvas = within(context.canvasElement)
diff --git a/docs/rules/csf-component.md b/docs/rules/csf-component.md
index 5cbfb1f..2a71b7f 100644
--- a/docs/rules/csf-component.md
+++ b/docs/rules/csf-component.md
@@ -33,4 +33,4 @@ While we encourage each CSF file to clearly correspond to a single component, it
## Further Reading
-- [Automatic argType inference](https://storybook.js.org/docs/react/api/argtypes#automatic-argtype-inference)
+- [Automatic argType inference](https://storybook.js.org/docs/api/argtypes#automatic-argtype-inference)
diff --git a/docs/rules/default-exports.md b/docs/rules/default-exports.md
index 557af7b..7de9d6c 100644
--- a/docs/rules/default-exports.md
+++ b/docs/rules/default-exports.md
@@ -8,7 +8,7 @@
## Rule Details
-In [CSF](https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format), a story file should contain a _default export_ that describes the component, and _named exports_ that describe the stories. This rule enforces the definition of a default export in story files.
+In [CSF](https://storybook.js.org/docs/writing-stories#component-story-format), a story file should contain a _default export_ that describes the component, and _named exports_ that describe the stories. This rule enforces the definition of a default export in story files.
Examples of **incorrect** code for this rule:
@@ -36,4 +36,4 @@ If you're using Storybook 6.5 and [CSF in MDX](https://github.com/storybookjs/st
## Further Reading
-More information about defining stories here: https://storybook.js.org/docs/react/writing-stories/introduction#defining-stories
+More information about defining stories here: https://storybook.js.org/docs/writing-stories#defining-stories
diff --git a/docs/rules/meta-inline-properties.md b/docs/rules/meta-inline-properties.md
index 0ba7df3..d962b37 100644
--- a/docs/rules/meta-inline-properties.md
+++ b/docs/rules/meta-inline-properties.md
@@ -1,6 +1,9 @@
# Meta should only have inline properties (meta-inline-properties)
+
+**Included in these configurations**: N/A
+
## Rule Details
diff --git a/docs/rules/no-stories-of.md b/docs/rules/no-stories-of.md
index ec61c1a..3d5280f 100644
--- a/docs/rules/no-stories-of.md
+++ b/docs/rules/no-stories-of.md
@@ -8,7 +8,7 @@
## Rule Details
-Since Storybook 5.2, the [CSF format](https://storybook.js.org/docs/react/api/csf) was introduced and the `storiesOf` API has been deprecated.
+Since Storybook 5.2, the [CSF format](https://storybook.js.org/docs/api/csf) was introduced and the `storiesOf` API has been deprecated.
Examples of **incorrect** code for this rule:
diff --git a/docs/rules/prefer-pascal-case.md b/docs/rules/prefer-pascal-case.md
index be0423f..1612edf 100644
--- a/docs/rules/prefer-pascal-case.md
+++ b/docs/rules/prefer-pascal-case.md
@@ -8,7 +8,7 @@
## Rule Details
-As a best practice, stories should be defined in [_PascalCase_](https://en.wiktionary.org/wiki/Pascal_case). This makes it simpler to visually differ stories to other code. Plus, it makes it simpler to define regexes for [non-story exports](https://storybook.js.org/docs/react/api/csf#non-story-exports).
+As a best practice, stories should be defined in [_PascalCase_](https://en.wiktionary.org/wiki/Pascal_case). This makes it simpler to visually differ stories to other code. Plus, it makes it simpler to define regexes for [non-story exports](https://storybook.js.org/docs/api/csf#non-story-exports).
Examples of **incorrect** code for this rule:
@@ -24,4 +24,4 @@ export const PrimaryButton = {}
## Further Reading
-More information about naming stories can be found here: https://storybook.js.org/docs/react/writing-stories/introduction#defining-stories
+More information about naming stories can be found here: https://storybook.js.org/docs/writing-stories#defining-stories
diff --git a/docs/rules/story-exports.md b/docs/rules/story-exports.md
index df63c9d..ae4f95e 100644
--- a/docs/rules/story-exports.md
+++ b/docs/rules/story-exports.md
@@ -8,7 +8,7 @@
## Rule Details
-In [CSF](https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format), a story file should contain a _default export_ that describes the component, and at _named exports_ that describe the stories. This rule enforces the definition of at least one named export in story files.
+In [CSF](https://storybook.js.org/docs/writing-stories#component-story-format), a story file should contain a _default export_ that describes the component, and at _named exports_ that describe the stories. This rule enforces the definition of at least one named export in story files.
Examples of **incorrect** code for this rule:
@@ -38,4 +38,4 @@ This rule should only be applied in your `.stories.*` files. Please ensure you a
## Further Reading
-More information about defining stories here: https://storybook.js.org/docs/react/writing-stories/introduction#defining-stories
+More information about defining stories here: https://storybook.js.org/docs/writing-stories#defining-stories
diff --git a/docs/rules/use-storybook-expect.md b/docs/rules/use-storybook-expect.md
index eb772fd..a8ec3d7 100644
--- a/docs/rules/use-storybook-expect.md
+++ b/docs/rules/use-storybook-expect.md
@@ -8,26 +8,29 @@
## Rule Details
-Storybook provides a browser compatible version of Jest's expect via the [@storybook/jest](https://github.com/storybookjs/jest) library.
-When [writing interactions](https://storybook.js.org/docs/react/essentials/interactions) and asserting values, you should always use `expect` from the `@storybook/jest` library.
+Storybook provides a browser compatible version of `expect` via the [@storybook/test](https://github.com/storybookjs/storybook/tree/next/code/lib/test) library (formerly available in the legacy [@storybook/jest](https://github.com/storybookjs/jest) library).
+When [writing interactions](https://storybook.js.org/docs/essentials/interactions) and asserting values, you should always use `expect` from the `@storybook/test` library.
Examples of **incorrect** code for this rule:
```js
-Default.play = () => {
+Default.play = async () => {
// using global expect from Jest. Will break on the browser
- expect(123).toEqual(123)
+ await expect(123).toEqual(123)
}
```
Examples of **correct** code for this rule:
```js
+// correct import.
+import { expect } from '@storybook/test'
+// or this, which is now considered legacy
import { expect } from '@storybook/jest'
-Default.play = () => {
+Default.play = async () => {
// using imported expect from storybook package
- expect(123).toEqual(123)
+ await expect(123).toEqual(123)
}
```
diff --git a/docs/rules/use-storybook-testing-library.md b/docs/rules/use-storybook-testing-library.md
index 1ba500a..0abdfd3 100644
--- a/docs/rules/use-storybook-testing-library.md
+++ b/docs/rules/use-storybook-testing-library.md
@@ -8,8 +8,8 @@
## Rule Details
-Storybook provides an instrumented version of testing library in the [@storybook/testing-library](https://github.com/storybookjs/testing-library/) package.
-When [writing interactions](https://storybook.js.org/docs/react/essentials/interactions), make sure to use the helper functions from `@storybook/testing-library`, so that addon-interactions can intercept these helper functions and allow you to step through them when debugging.
+Storybook provides an instrumented version of testing library in the [@storybook/test](https://github.com/storybookjs/storybook/tree/next/code/lib/test) library (formerly available in [@storybook/testing-library](https://github.com/storybookjs/testing-library/) library).
+When [writing interactions](https://storybook.js.org/docs/essentials/interactions), make sure to use the helper functions from `@storybook/test`, so that addon-interactions can intercept these helper functions and allow you to step through them when debugging.
Examples of **incorrect** code for this rule:
@@ -26,6 +26,8 @@ Examples of **correct** code for this rule:
```js
// correct import.
+import { within } from '@storybook/test'
+// or this, which is now considered legacy
import { within } from '@storybook/testing-library'
Default.play = async (context) => {
diff --git a/lib/index.ts b/lib/index.ts
index be3f92e..5fac0ab 100644
--- a/lib/index.ts
+++ b/lib/index.ts
@@ -19,6 +19,7 @@ import contextInPlayFunction from './rules/context-in-play-function'
import csfComponent from './rules/csf-component'
import defaultExports from './rules/default-exports'
import hierarchySeparator from './rules/hierarchy-separator'
+import metaInlineProperties from './rules/meta-inline-properties'
import noRedundantStoryName from './rules/no-redundant-story-name'
import noStoriesOf from './rules/no-stories-of'
import noTitlePropertyInMeta from './rules/no-title-property-in-meta'
@@ -49,6 +50,7 @@ export = {
'csf-component': csfComponent,
'default-exports': defaultExports,
'hierarchy-separator': hierarchySeparator,
+ 'meta-inline-properties': metaInlineProperties,
'no-redundant-story-name': noRedundantStoryName,
'no-stories-of': noStoriesOf,
'no-title-property-in-meta': noTitlePropertyInMeta,
diff --git a/tests/integrations/flat-config.spec.ts b/tests/integrations/flat-config.spec.ts
index 8a9f43e..2aad67a 100644
--- a/tests/integrations/flat-config.spec.ts
+++ b/tests/integrations/flat-config.spec.ts
@@ -30,11 +30,12 @@ describe('Integration with flat config', () => {
}
const result = JSON.parse(
- cp.execSync(`${ESLINT} a.stories.tsx --max-warnings 1 --format=json`, {
+ cp.execSync(`${ESLINT} a.stories.tsx --max-warnings 2 --format=json`, {
encoding: 'utf-8',
})
)
expect(result.length).toBe(1)
expect(result[0].messages[0].messageId).toBe('shouldHaveStoryExport')
+ expect(result[0].messages[1].messageId).toBe('metaShouldHaveInlineProperties')
})
})
diff --git a/tests/integrations/flat-config/a.stories.tsx b/tests/integrations/flat-config/a.stories.tsx
index 0d5133e..b07c30c 100644
--- a/tests/integrations/flat-config/a.stories.tsx
+++ b/tests/integrations/flat-config/a.stories.tsx
@@ -1,6 +1,4 @@
const Input = () => 'This is an input component'
-export default {
- title: 'Input',
- component: Input,
-}
+const title = 'foo';
+export default { title }
diff --git a/tests/integrations/flat-config/eslint.config.js b/tests/integrations/flat-config/eslint.config.js
index 02feb2c..e584222 100644
--- a/tests/integrations/flat-config/eslint.config.js
+++ b/tests/integrations/flat-config/eslint.config.js
@@ -6,6 +6,7 @@ export default [
files: ['**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)', '**/*.story.@(ts|tsx|js|jsx|mjs|cjs)'],
rules: {
'storybook/story-exports': 'warn',
+ 'storybook/meta-inline-properties': 'warn',
},
},
]
diff --git a/tests/integrations/legacy-config.spec.ts b/tests/integrations/legacy-config.spec.ts
index f441480..2bb9e8c 100644
--- a/tests/integrations/legacy-config.spec.ts
+++ b/tests/integrations/legacy-config.spec.ts
@@ -30,11 +30,12 @@ describe('Integration with legacy config', () => {
}
const result = JSON.parse(
- cp.execSync(`${ESLINT} a.stories.tsx --max-warnings 1 --format=json`, {
+ cp.execSync(`${ESLINT} a.stories.tsx --max-warnings 2 --format=json`, {
encoding: 'utf-8',
})
)
expect(result.length).toBe(1)
expect(result[0].messages[0].messageId).toBe('shouldHaveStoryExport')
+ expect(result[0].messages[1].messageId).toBe('metaShouldHaveInlineProperties')
})
})
diff --git a/tests/integrations/legacy-config/.eslintrc.json b/tests/integrations/legacy-config/.eslintrc.json
index 171b300..2c0fa80 100644
--- a/tests/integrations/legacy-config/.eslintrc.json
+++ b/tests/integrations/legacy-config/.eslintrc.json
@@ -9,7 +9,8 @@
{
"files": ["*.stories.@(ts|tsx|js|jsx|mjs|cjs)"],
"rules": {
- "storybook/story-exports": "warn"
+ "storybook/story-exports": "warn",
+ "storybook/meta-inline-properties": "warn"
}
}
]
diff --git a/tests/integrations/legacy-config/a.stories.tsx b/tests/integrations/legacy-config/a.stories.tsx
index 0d5133e..b07c30c 100644
--- a/tests/integrations/legacy-config/a.stories.tsx
+++ b/tests/integrations/legacy-config/a.stories.tsx
@@ -1,6 +1,4 @@
const Input = () => 'This is an input component'
-export default {
- title: 'Input',
- component: Input,
-}
+const title = 'foo';
+export default { title }
diff --git a/tools/update-rules-list.ts b/tools/update-rules-list.ts
index c6eb54d..2d3f9d6 100644
--- a/tools/update-rules-list.ts
+++ b/tools/update-rules-list.ts
@@ -28,11 +28,13 @@ const rulesList: TRulesList[] = Object.entries(rules)
return [
rule.name,
createRuleLink(rule.name),
- rule.meta.docs.description,
+ rule.meta.docs?.description || '',
rule.meta.fixable ? emojiKey.fixable : '',
- rule.meta.docs.categories
- ? `${rule.meta.docs.categories.map((c) => `- ${c}
- flat/${c}
`).join('')}
`
- : '',
+ rule.meta.docs?.excludeFromConfig
+ ? 'N/A'
+ : rule.meta.docs?.categories
+ ? `${rule.meta.docs?.categories.map((c) => `- ${c}
- flat/${c}
`).join('')}
`
+ : '',
]
})
diff --git a/tools/utils/categories.ts b/tools/utils/categories.ts
index 775e74b..29e5d4e 100644
--- a/tools/utils/categories.ts
+++ b/tools/utils/categories.ts
@@ -24,13 +24,13 @@ for (const categoryId of categoryIds) {
categoriesConfig[categoryId].rules = []
for (const rule of rules) {
- const ruleCategories = rule.meta.docs.categories
+ const ruleCategories = rule.meta.docs?.categories
// Throw if rule does not have a category
if (!ruleCategories?.length) {
throw new Error(`Rule "${rule.ruleId}" does not have any category.`)
}
- if (ruleCategories.includes(categoryId)) {
+ if (ruleCategories.includes(categoryId) && rule.meta.docs?.excludeFromConfig !== true) {
categoriesConfig[categoryId].rules?.push(rule)
}
}
diff --git a/tools/utils/docs.ts b/tools/utils/docs.ts
index a4f6e66..d734879 100644
--- a/tools/utils/docs.ts
+++ b/tools/utils/docs.ts
@@ -106,7 +106,7 @@ export const updateRulesDocs = async (rulesList: TRulesList[]) => {
const updatedDocFile = await format(overWriteRuleDocs(rule, ruleDocFile), {
parser: 'markdown',
- ...prettierConfig,
+ ...(await prettierConfig),
})
await writeFile(ruleDocFilePath, updatedDocFile)
diff --git a/tools/utils/rules.ts b/tools/utils/rules.ts
index 6b1c2fa..e2f2ace 100644
--- a/tools/utils/rules.ts
+++ b/tools/utils/rules.ts
@@ -28,8 +28,6 @@ const rules = fs
meta,
}
})
- // We might have rules which are almost ready but should not be shipped
- .filter((rule) => !rule.meta.docs?.excludeFromConfig)
export type TRules = typeof rules