From 77547c5c833cb1830a6091a608105c89fca3256a Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Fri, 10 May 2024 21:15:33 +0800 Subject: [PATCH] CLI: Add main.js docs.autodocs automigration --- .../automigrate/fixes/autodocs-tags.test.ts | 74 +++++++++++++++ .../src/automigrate/fixes/autodocs-tags.ts | 90 +++++++++++++++++++ code/lib/cli/src/automigrate/fixes/index.ts | 2 + .../src/modules/store/csf/prepareStory.ts | 7 -- 4 files changed, 166 insertions(+), 7 deletions(-) create mode 100644 code/lib/cli/src/automigrate/fixes/autodocs-tags.test.ts create mode 100644 code/lib/cli/src/automigrate/fixes/autodocs-tags.ts diff --git a/code/lib/cli/src/automigrate/fixes/autodocs-tags.test.ts b/code/lib/cli/src/automigrate/fixes/autodocs-tags.test.ts new file mode 100644 index 00000000000..3c96d7b7bc1 --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/autodocs-tags.test.ts @@ -0,0 +1,74 @@ +import { describe, expect, it } from 'vitest'; +import type { StorybookConfig } from '@storybook/types'; +import { autodocsTags } from './autodocs-tags'; + +const check = async ({ + main: mainConfig, + storybookVersion = '7.0.0', + previewConfigPath, +}: { + main: Partial & Record; + storybookVersion?: string; + previewConfigPath?: string; +}) => { + return autodocsTags.check({ + packageManager: {} as any, + configDir: '', + mainConfig: mainConfig as any, + storybookVersion, + previewConfigPath, + }); +}; + +it('with no docs setting', async () => { + await expect( + check({ + main: {}, + }) + ).resolves.toBeFalsy(); +}); + +describe('docs.autodocs = true', () => { + it('errors with no preview.js', async () => { + await expect( + check({ + main: { + docs: { autodocs: true }, + }, + }) + ).rejects.toThrowError(); + }); + + it('continues with preview.js', async () => { + await expect( + check({ + main: { + docs: { autodocs: true }, + }, + previewConfigPath: '.storybook/preview.js', + }) + ).resolves.toBeTruthy(); + }); +}); + +describe('docs.autodocs != true', () => { + it('docs.autodocs = false', async () => { + await expect( + check({ + main: { + docs: { autodocs: false }, + }, + }) + ).resolves.toBeTruthy(); + }); + + it('docs.autodocs = "tag"', async () => { + await expect( + check({ + main: { + docs: { autodocs: 'tag' }, + }, + }) + ).resolves.toBeTruthy(); + }); +}); diff --git a/code/lib/cli/src/automigrate/fixes/autodocs-tags.ts b/code/lib/cli/src/automigrate/fixes/autodocs-tags.ts new file mode 100644 index 00000000000..1924423a8be --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/autodocs-tags.ts @@ -0,0 +1,90 @@ +import { dedent } from 'ts-dedent'; +import chalk from 'chalk'; +import type { DocsOptions } from '@storybook/types'; +import { readConfig, writeConfig } from '@storybook/csf-tools'; +import { updateMainConfig } from '../helpers/mainConfigFile'; +import type { Fix } from '../types'; + +const logger = console; + +interface Options { + autodocs: DocsOptions['autodocs']; + previewConfigPath?: string; +} + +/** + */ +export const autodocsTags: Fix = { + id: 'autodocs-tags', + versionRange: ['*.*.*', '>=8.0.*'], + async check({ mainConfig, previewConfigPath }) { + const autodocs = mainConfig?.docs?.autodocs; + if (autodocs === undefined) return null; + + if (autodocs === true && !previewConfigPath) { + throw Error(dedent` + ❌ Failed to remove the deprecated ${chalk.cyan('docs.autodocs')} setting from ${chalk.cyan( + '.storybook/main.js' + )}. + + There is no preview config file to add the ${chalk.cyan('autodocs')} tag to. + + Please perform the migration by hand: ${chalk.yellow( + 'github.com/storybookjs/storybook/blob/next/MIGRATION.md#mainjs-docsautodocs-is-deprecated' + )} + `); + return null; + } + + return { autodocs, previewConfigPath }; + }, + + prompt({ autodocs, previewConfigPath }) { + let falseMessage = '', + trueMessage = ''; + + if (autodocs === false) { + falseMessage = dedent` + + + There is no ${chalk.cyan('docs.autodocs = false')} equivalent. + You'll need to check your stories to ensure none are tagged with ${chalk.cyan('autodocs')}. + `; + } else if (autodocs === true) { + trueMessage = ` and update ${chalk.cyan(previewConfigPath)}`; + } + + return dedent` + The ${chalk.cyan('docs.autodocs')} setting in ${chalk.cyan( + '.storybook/main.js' + )} is deprecated.${falseMessage} + + Learn more: ${chalk.yellow( + 'github.com/storybookjs/storybook/blob/next/MIGRATION.md#mainjs-docsautodocs-is-deprecated' + )} + + Remove ${chalk.cyan('docs.autodocs')}${trueMessage}? + `; + }, + + async run({ dryRun, mainConfigPath, result }) { + if (!dryRun) { + if (result.autodocs === true) { + logger.info(`✅ Adding "autodocs" tag to ${result.previewConfigPath}`); + const previewConfig = await readConfig(result.previewConfigPath!); + const tags = previewConfig.getFieldNode(['tags']); + if (tags) { + previewConfig.appendValueToArray(['tags'], 'autodocs'); + } else { + previewConfig.setFieldValue(['tags'], ['autodocs']); + } + await writeConfig(previewConfig); + } + + await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, async (main) => { + logger.info(`✅ Removing "docs.autodocs" from ${mainConfigPath}`); + main.removeField(['docs', 'autodocs']); + }); + } + }, +}; diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index 72f3eb9a605..1c12a596fb2 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -28,6 +28,7 @@ import { mdx1to3 } from './mdx-1-to-3'; import { addonPostCSS } from './addon-postcss'; import { vta } from './vta'; import { upgradeStorybookRelatedDependencies } from './upgrade-storybook-related-dependencies'; +import { autodocsTags } from './autodocs-tags'; export * from '../types'; @@ -60,6 +61,7 @@ export const allFixes: Fix[] = [ mdx1to3, upgradeStorybookRelatedDependencies, vta, + autodocsTags, ]; export const initFixes: Fix[] = [eslintPlugin]; diff --git a/code/lib/preview-api/src/modules/store/csf/prepareStory.ts b/code/lib/preview-api/src/modules/store/csf/prepareStory.ts index 6183274669f..f4a6232d9e7 100644 --- a/code/lib/preview-api/src/modules/store/csf/prepareStory.ts +++ b/code/lib/preview-api/src/modules/store/csf/prepareStory.ts @@ -159,13 +159,6 @@ function preparePartialAnnotations( // will have a limited cost. If this proves misguided, we can refactor it. const defaultTags = ['dev', 'test']; - if (typeof globalThis.DOCS_OPTIONS?.autodocs !== 'undefined') { - once.warn(dedent` - The \`docs.autodocs\` setting in '.storybook/main.js' is deprecated. Use \`tags: ['autodocs']\` in \`.storybook/preview.js\` instead. - - For more info see: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#mainjs-docsautodocs-is-deprecated - `); - } const extraTags = globalThis.DOCS_OPTIONS?.autodocs === true ? ['autodocs'] : []; const tags = combineTags(