From 77547c5c833cb1830a6091a608105c89fca3256a Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Fri, 10 May 2024 21:15:33 +0800 Subject: [PATCH 1/3] 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 000000000000..3c96d7b7bc1d --- /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 000000000000..1924423a8be6 --- /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 72f3eb9a605d..1c12a596fb24 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 6183274669fe..f4a6232d9e7a 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( From aa60391d94df71e7e951236289c3bb072e433ee0 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Fri, 10 May 2024 22:33:21 +0800 Subject: [PATCH 2/3] Address review comments --- .../src/automigrate/fixes/autodocs-tags.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/autodocs-tags.ts b/code/lib/cli/src/automigrate/fixes/autodocs-tags.ts index 1924423a8be6..531bcc0ec69d 100644 --- a/code/lib/cli/src/automigrate/fixes/autodocs-tags.ts +++ b/code/lib/cli/src/automigrate/fixes/autodocs-tags.ts @@ -7,8 +7,12 @@ import type { Fix } from '../types'; const logger = console; +const MIGRATION = + 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#mainjs-docsautodocs-is-deprecated'; + interface Options { autodocs: DocsOptions['autodocs']; + mainConfigPath?: string; previewConfigPath?: string; } @@ -17,29 +21,27 @@ interface Options { export const autodocsTags: Fix = { id: 'autodocs-tags', versionRange: ['*.*.*', '>=8.0.*'], - async check({ mainConfig, previewConfigPath }) { + async check({ mainConfig, mainConfigPath, 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' + mainConfigPath )}. - There is no preview config file to add the ${chalk.cyan('autodocs')} tag to. + There is no preview config file in which to add the ${chalk.cyan('autodocs')} tag. - Please perform the migration by hand: ${chalk.yellow( - 'github.com/storybookjs/storybook/blob/next/MIGRATION.md#mainjs-docsautodocs-is-deprecated' - )} + Please perform the migration by hand: ${chalk.yellow(MIGRATION)} `); return null; } - return { autodocs, previewConfigPath }; + return { autodocs, mainConfigPath, previewConfigPath }; }, - prompt({ autodocs, previewConfigPath }) { + prompt({ autodocs, mainConfigPath, previewConfigPath }) { let falseMessage = '', trueMessage = ''; @@ -56,12 +58,10 @@ export const autodocsTags: Fix = { return dedent` The ${chalk.cyan('docs.autodocs')} setting in ${chalk.cyan( - '.storybook/main.js' + mainConfigPath )} is deprecated.${falseMessage} - Learn more: ${chalk.yellow( - 'github.com/storybookjs/storybook/blob/next/MIGRATION.md#mainjs-docsautodocs-is-deprecated' - )} + Learn more: ${chalk.yellow(MIGRATION)} Remove ${chalk.cyan('docs.autodocs')}${trueMessage}? `; From 4f48add15309ac9e6161f38231b8678df1dd5b21 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Fri, 10 May 2024 23:40:13 +0800 Subject: [PATCH 3/3] Fix TS errors --- code/lib/preview-api/src/modules/store/csf/prepareStory.ts | 3 --- 1 file changed, 3 deletions(-) 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 f4a6232d9e7a..ce99cef8f1e0 100644 --- a/code/lib/preview-api/src/modules/store/csf/prepareStory.ts +++ b/code/lib/preview-api/src/modules/store/csf/prepareStory.ts @@ -1,6 +1,4 @@ /* eslint-disable @typescript-eslint/no-loop-func,no-underscore-dangle */ -import { dedent } from 'ts-dedent'; - import { global } from '@storybook/global'; import type { Args, @@ -23,7 +21,6 @@ import type { } from '@storybook/types'; import { type CleanupCallback, includeConditionalArg, combineTags } from '@storybook/csf'; import { global as globalThis } from '@storybook/global'; -import { once } from '@storybook/client-logger'; import { applyHooks } from '../../addons'; import { combineParameters } from '../parameters';