Skip to content

Commit

Permalink
feat: allow ignore option in no-uninstalled-addons
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini committed Apr 28, 2023
1 parent fe90e1f commit f06c588
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 12 deletions.
27 changes: 22 additions & 5 deletions docs/rules/no-uninstalled-addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

## Rule Details

This rule checks if all addons registered in `.storybook/main.js` are properly listed in the root package.json of your project.
This rule checks if all addons registered in `.storybook/main.js` are properly listed in the root `package.json` of your project.

For instance, if the `@storybook/addon-links` is in the `.storybook/main.js` but is not listed in the `package.json` of the project, this rule will notify the user to add the addon to the package.json and install it.
For instance, if the `@storybook/addon-links` is in the `.storybook/main.js` but is not listed in the `package.json` of the project, this rule will notify the user to add the addon to the `package.json` and install it.

As an important side note, this rule will check for the `package.json` in the **root level** of your project. You can customize the location of the `package.json` by [setting the `packageJsonPath` option](#configure).
As an important side note, this rule will check for the `package.json` in the **root level** of your project. You can customize the location of the `package.json` by [setting the `packageJsonLocation` option](#configure).

Another very important side note: your ESLint config must allow the linting of the `.storybook` folder. By default, ESLint ignores all dot-files so this folder will be ignored. In order to allow this rule to lint the `.storybook/main.js` file, it's important to configure ESLint to lint this file. This can be achieved by writing something like:

Expand Down Expand Up @@ -68,7 +68,9 @@ module.exports = {

### Configure

This rule assumes that the `package.json` is located in the root of your project. You can customize this by setting the `packageJsonPath` option of the rule:
#### `packageJsonLocation`

This rule assumes that the `package.json` is located in the root of your project. You can customize this by setting the `packageJsonLocation` option of the rule:

```js
module.exports = {
Expand All @@ -80,6 +82,21 @@ module.exports = {

Note that the path must be relative to where ESLint runs from, which is usually relative to the root of the project.

#### `ignore`

You can also ignore certain addons by providing an ignore array in the options:

```js
module.exports = {
rules: {
'storybook/no-uninstalled-addons': [
'error',
{ packageJsonLocation: './folder/package.json', ignore: ['custom-addon'] },
],
},
}
```

### What if I use a different storybook config directory?

Some Storybook folders use a different name for their config directory other than `.storybook`. This rule will not be applied there by default. If you have a custom location for your storybook config directory, then you must add an override in your `.eslintrc.js` file, defining your config directory:
Expand All @@ -103,4 +120,4 @@ This rule is very handy to be used because if the user tries to start storybook

## Further Reading

Check the issue in GitHub: https://github.com/storybookjs/eslint-plugin-storybook/issues/95
Check the issue in GitHub: [https://github.com/storybookjs/eslint-plugin-storybook/issues/95](https://github.com/storybookjs/eslint-plugin-storybook/issues/95)
32 changes: 26 additions & 6 deletions lib/rules/no-uninstalled-addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ import { TSESTree } from '@typescript-eslint/utils'

export = createStorybookRule({
name: 'no-uninstalled-addons',
defaultOptions: [],
defaultOptions: [
{
packageJsonLocation: '' as string,
ignore: [] as string[],
},
],
meta: {
type: 'problem',
docs: {
Expand All @@ -46,16 +51,31 @@ export = createStorybookRule({
packageJsonLocation: {
type: 'string',
},
ignore: {
type: 'array',
items: {
type: 'string',
},
},
},
},
], // Add a schema if the rule has options. Otherwise remove this
],
},

create(context) {
// variables should be defined here
const packageJsonLocation = context.options.reduce((acc, val) => {
return val['packageJsonLocation'] || acc
}, '')
const { packageJsonLocation, ignore } = context.options.reduce<{
packageJsonLocation: string
ignore: string[]
}>(
(acc, val) => {
return {
packageJsonLocation: val['packageJsonLocation'] || acc.packageJsonLocation,
ignore: val['ignore'] || acc.ignore,
}
},
{ packageJsonLocation: '', ignore: [] }
)

//----------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -103,7 +123,7 @@ export = createStorybookRule({
const result = addons
// remove local addons (e.g. ./my-addon/register.js)
.filter(filterLocalAddons)
.filter((addon) => !isAddonInstalled(addon, installedSbAddons))
.filter((addon) => !isAddonInstalled(addon, installedSbAddons) && !ignore.includes(addon))
.map((addon) => ({ name: addon }))
return result.length ? result : false
}
Expand Down
20 changes: 19 additions & 1 deletion tests/lib/rules/no-uninstalled-addons.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'

import rule from '../../../lib/rules/no-uninstalled-addons'
import ruleTester from '../../utils/rule-tester'
import { sep } from 'path';
import { sep } from 'path'

jest.mock('fs', () => ({
...jest.requireActual('fs'),
Expand Down Expand Up @@ -118,6 +118,24 @@ ruleTester.run('no-uninstalled-addons', rule, {
]
}
`,
{
code: `
module.exports = {
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/not-installed-addon"
]
}
`,
options: [
{
packageJsonLocation: '',
ignore: ['@storybook/addon-not-installed-addon'],
},
],
},
],
invalid: [
{
Expand Down

0 comments on commit f06c588

Please sign in to comment.