diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c0d554b6714..649310bf1c11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,17 @@ -## 7.6.15 +## 7.6.17 + +- Addon-docs: Fix Table of Contents heading leak - [#23677](https://github.com/storybookjs/storybook/pull/23677), thanks [@vmizg](https://github.com/vmizg)! +- Core: Update ip version to fix CVE-2023-42282 - [#26086](https://github.com/storybookjs/storybook/pull/26086), thanks [@drik98](https://github.com/drik98)! + +## 7.6.16 +- Addon Themes: Make type generic less strict - [#26042](https://github.com/storybookjs/storybook/pull/26042), thanks [@yannbf](https://github.com/yannbf)! - Interaction: Make sure that adding spies doesn't cause infinite loops with self referencing args [#26019](https://github.com/storybookjs/storybook/pull/26019), thanks @kasperpeulen! +## 7.6.15 + +This release accidentally didn't contain anything. + ## 7.6.14 - Core: Fix boolean `true` args in URL getting ignored - [#25950](https://github.com/storybookjs/storybook/pull/25950), thanks [@JReinhold](https://github.com/JReinhold)! diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 620e9307a8a7..72fc40a832a8 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,32 @@ +## 8.0.0-beta.4 + +- Addon-actions: Warn when argTypesRegex is used together with the visual test addon - [#26094](https://github.com/storybookjs/storybook/pull/26094), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Addon-docs: Fix Table of Contents heading leak - [#23677](https://github.com/storybookjs/storybook/pull/23677), thanks [@vmizg](https://github.com/vmizg)! +- CLI: Add `legacyMdx1` & `@storybook/mdx1-csf` automigration - [#26102](https://github.com/storybookjs/storybook/pull/26102), thanks [@ndelangen](https://github.com/ndelangen)! +- CLI: Add line ignoring storybook's `.log` files upon `init` - [#26099](https://github.com/storybookjs/storybook/pull/26099), thanks [@ndelangen](https://github.com/ndelangen)! +- CLI: Add support for custom vite config to autoblocker - [#26087](https://github.com/storybookjs/storybook/pull/26087), thanks [@ndelangen](https://github.com/ndelangen)! +- CLI: Add webpack5 compiler automigration - [#26000](https://github.com/storybookjs/storybook/pull/26000), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- CLI: Remove argTypesRegex automigration - [#26001](https://github.com/storybookjs/storybook/pull/26001), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- CLI: Remove the logging to file feature from autoblockers - [#26100](https://github.com/storybookjs/storybook/pull/26100), thanks [@ndelangen](https://github.com/ndelangen)! +- Core: Add addon removal telemetry - [#26077](https://github.com/storybookjs/storybook/pull/26077), thanks [@shilman](https://github.com/shilman)! +- Core: Fix fail to load `main.ts` error message - [#26035](https://github.com/storybookjs/storybook/pull/26035), thanks [@ndelangen](https://github.com/ndelangen)! +- Core: Update ip version to fix CVE-2023-42282 - [#26086](https://github.com/storybookjs/storybook/pull/26086), thanks [@drik98](https://github.com/drik98)! +- Next.js: Support getImageProps API - [#25745](https://github.com/storybookjs/storybook/pull/25745), thanks [@piratetaco](https://github.com/piratetaco)! +- Svelte: Remove deprecated SvelteComponentTyped in favor of SvelteComponent - [#26113](https://github.com/storybookjs/storybook/pull/26113), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Vite: Fix bug that meant we always warned about TS plugin - [#26051](https://github.com/storybookjs/storybook/pull/26051), thanks [@tmeasday](https://github.com/tmeasday)! +- Vite: Fix config typing issue of the `typescript` property - [#26046](https://github.com/storybookjs/storybook/pull/26046), thanks [@ndelangen](https://github.com/ndelangen)! +- Vite: Fix issue getting preview stats with Vite builder - [#26093](https://github.com/storybookjs/storybook/pull/26093), thanks [@tmeasday](https://github.com/tmeasday)! + +## 8.0.0-beta.3 + +- Addon-actions: Add spy to action for explicit actions - [#26033](https://github.com/storybookjs/storybook/pull/26033), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Addon-themes: Make type generic less strict - [#26042](https://github.com/storybookjs/storybook/pull/26042), thanks [@yannbf](https://github.com/yannbf)! +- Addon-docs: Fix pnpm+Vite failing to build with `@storybook/theming` Rollup error - [#26024](https://github.com/storybookjs/storybook/pull/26024), thanks [@JReinhold](https://github.com/JReinhold)! +- CLI: Refactor to add autoblockers - [#25934](https://github.com/storybookjs/storybook/pull/25934), thanks [@ndelangen](https://github.com/ndelangen)! +- Codemod: Migrate to test package - [#25958](https://github.com/storybookjs/storybook/pull/25958), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Portable stories: Only provide a play function wrapper if it exists - [#25974](https://github.com/storybookjs/storybook/pull/25974), thanks [@yannbf](https://github.com/yannbf)! +- Test: Bump user-event to 14.5.2 - [#25889](https://github.com/storybookjs/storybook/pull/25889), thanks [@kasperpeulen](https://github.com/kasperpeulen)! + ## 8.0.0-beta.2 - Core: Fix boolean `true` args in URL getting ignored - [#25950](https://github.com/storybookjs/storybook/pull/25950), thanks [@JReinhold](https://github.com/JReinhold)! diff --git a/MIGRATION.md b/MIGRATION.md index 391c868cfa5b..77d77356d46e 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -127,6 +127,7 @@ - [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates) - [Changed decorator order between preview.js and addons/frameworks](#changed-decorator-order-between-previewjs-and-addonsframeworks) - [Dark mode detection](#dark-mode-detection) + - [`addons.setConfig` should now be imported from `@storybook/manager-api`.](#addonssetconfig-should-now-be-imported-from-storybookmanager-api) - [7.0 core addons changes](#70-core-addons-changes) - [Removed auto injection of @storybook/addon-actions decorator](#removed-auto-injection-of-storybookaddon-actions-decorator) - [Addon-backgrounds: Removed deprecated grid parameter](#addon-backgrounds-removed-deprecated-grid-parameter) @@ -468,7 +469,10 @@ In Storybook 7, these packages existed for backwards compatibility, but were mar - `@storybook/store` - this package has been merged into `@storybook/preview-api`. - `@storybook/api` - this package has been replaced with `@storybook/manager-api`. -This section explains the rationale, and the required changed you might have to make: [New Addons API](#new-addons-api) +These sections explain the rationale, and the required changes you might have to make: + +- [New Addons API](#new-addons-api) +- [`addons.setConfig` should now be imported from `@storybook/manager-api`.](#addonssetconfig-should-now-be-imported-from-storybookmanager-api) ### Framework-specific Vite plugins have to be explicitly added @@ -2029,6 +2033,19 @@ Earlier versions used the light theme by default, so if you don't set a theme an To learn more about theming, read our [documentation](https://storybook.js.org/docs/react/configure/theming). +#### `addons.setConfig` should now be imported from `@storybook/manager-api`. + +The previous package, `@storybook/addons`, is now deprecated and will be removed in 8.0. + +```diff +- import { addons } from '@storybook/addons'; ++ import { addons } from '@storybook/manager-api'; + +addons.setConfig({ + // ... +}) +``` + ### 7.0 core addons changes #### Removed auto injection of @storybook/addon-actions decorator diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index ae09048b7f43..12bb4e5890d9 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index 7f67bd1206c6..ae4890094098 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Get UI feedback when an action is performed on an interactive element", "keywords": [ "storybook", diff --git a/code/addons/actions/src/runtime/action.ts b/code/addons/actions/src/runtime/action.ts index f6779d1a1a64..a647a8eb0d1b 100644 --- a/code/addons/actions/src/runtime/action.ts +++ b/code/addons/actions/src/runtime/action.ts @@ -103,6 +103,7 @@ export function action(name: string, options: ActionOptions = {}): HandlerFuncti channel.emit(EVENT_ID, actionDisplayToEmit); }; handler.isAction = true; + handler.implicit = options.implicit; return handler; } diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index d0735711dad2..22066c742a1c 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Switch backgrounds to view components in different settings", "keywords": [ "addon", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index ece248545b76..e288b4ef3167 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-controls", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Interact with component inputs dynamically in the Storybook UI", "keywords": [ "addon", diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index 4455f7a0890c..ae1036bd400d 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Document component usage and properties in Markdown", "keywords": [ "addon", diff --git a/code/addons/docs/src/preset.ts b/code/addons/docs/src/preset.ts index 45c832b5fe42..68c7efb39f8b 100644 --- a/code/addons/docs/src/preset.ts +++ b/code/addons/docs/src/preset.ts @@ -149,8 +149,14 @@ export const viteFinal = async (config: any, options: Options) => { react, 'react-dom': reactDom, '@mdx-js/react': mdx, + /** + * The following aliases are used to ensure a single instance of these packages are used in situations where they are duplicated + * The packages will be duplicated by the package manager when the user has react installed with another version than 18.2.0 + */ + '@storybook/theming': dirname(require.resolve('@storybook/theming')), + '@storybook/components': dirname(require.resolve('@storybook/components')), + '@storybook/blocks': dirname(require.resolve('@storybook/blocks')), }, - dedupe: ['@storybook/theming', '@storybook/components', '@storybook/blocks'], }, }), }; diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index 6ff40fb86d80..ea8882c06e3b 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-essentials", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Curated addons to bring out the best of Storybook", "keywords": [ "addon", diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json index b80b72c7fc93..9b7093338682 100644 --- a/code/addons/gfm/package.json +++ b/code/addons/gfm/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-mdx-gfm", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "GitHub Flavored Markdown in Storybook", "keywords": [ "addon", diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index 00aaed7b475f..354a0f77fdf5 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-highlight", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Highlight DOM nodes within your stories", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 0cf9b95103fd..e7c096e811e1 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-interactions", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Automate, test and debug user interactions", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/src/preview.ts b/code/addons/interactions/src/preview.ts index d751cbf7bc58..e0cc0aeae87a 100644 --- a/code/addons/interactions/src/preview.ts +++ b/code/addons/interactions/src/preview.ts @@ -1,11 +1,11 @@ -/* eslint-disable no-underscore-dangle */ import type { - Args, - LoaderFunction, + ArgsEnhancer, PlayFunction, PlayFunctionContext, + Renderer, StepLabel, } from '@storybook/types'; +import { fn, isMockFunction } from '@storybook/test'; import { instrument } from '@storybook/instrumenter'; export const { step: runStep } = instrument( @@ -16,26 +16,47 @@ export const { step: runStep } = instrument( { intercept: true } ); -const instrumentSpies: LoaderFunction = ({ initialArgs }) => { - const argTypesWithAction = Object.entries(initialArgs).filter( - ([, value]) => - typeof value === 'function' && - '_isMockFunction' in value && - value._isMockFunction && - !value._instrumented - ); - - return argTypesWithAction.reduce((acc, [key, value]) => { - const instrumented = instrument({ [key]: () => value }, { retain: true })[key]; - acc[key] = instrumented(); - // this enhancer is being called multiple times - - value._instrumented = true; - return acc; - }, {} as Args); +const traverseArgs = (value: unknown, depth = 0, key?: string): any => { + // Make sure to not get in infinite loops with self referencing args + if (depth > 5) return value; + if (value == null) return value; + if (isMockFunction(value)) { + // Makes sure we get the arg name in the interactions panel + if (key) value.mockName(key); + return value; + } + + // wrap explicit actions in a spy + if ( + typeof value === 'function' && + 'isAction' in value && + value.isAction && + !('implicit' in value && value.implicit) + ) { + const mock = fn(value as any); + if (key) mock.mockName(key); + return mock; + } + + if (Array.isArray(value)) { + depth++; + return value.map((item) => traverseArgs(item, depth)); + } + + if (typeof value === 'object' && value.constructor === Object) { + depth++; + // We have to mutate the original object for this to survive HMR. + for (const [k, v] of Object.entries(value)) { + (value as Record)[k] = traverseArgs(v, depth, k); + } + return value; + } + return value; }; -export const argsEnhancers = [instrumentSpies]; +const wrapActionsInSpyFns: ArgsEnhancer = ({ initialArgs }) => traverseArgs(initialArgs); + +export const argsEnhancers = [wrapActionsInSpyFns]; export const parameters = { throwPlayFunctionExceptions: false, diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index dc65c436571a..a354c64199f9 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "React storybook addon that show component jest report", "keywords": [ "addon", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index 58bba6fc839f..0695b925b6ca 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Link stories together to build demos and prototypes with your UI components", "keywords": [ "addon", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index d790f15d3b06..686313c6b98b 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-measure", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Inspect layouts by visualizing the box model", "keywords": [ "storybook-addons", diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index f7657f6cf0f7..c34149c39d55 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-outline", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Outline all elements with CSS to help with layout placement and alignment", "keywords": [ "storybook-addons", diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index 7ab40549e9fa..646cb28606a8 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "View a story’s source code to see how it works and paste into your app", "keywords": [ "addon", diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json index a0b8e601f203..08c5b27a4130 100644 --- a/code/addons/themes/package.json +++ b/code/addons/themes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-themes", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Switch between multiple themes for you components in Storybook", "keywords": [ "css", diff --git a/code/addons/themes/src/decorators/class-name.decorator.tsx b/code/addons/themes/src/decorators/class-name.decorator.tsx index ccbe4fbf7f31..0306c5ea9912 100644 --- a/code/addons/themes/src/decorators/class-name.decorator.tsx +++ b/code/addons/themes/src/decorators/class-name.decorator.tsx @@ -13,7 +13,8 @@ const DEFAULT_ELEMENT_SELECTOR = 'html'; const classStringToArray = (classString: string) => classString.split(' ').filter(Boolean); -export const withThemeByClassName = ({ +// TODO check with @kasperpeulen: change the types so they can be correctly inferred from context e.g. any> +export const withThemeByClassName = ({ themes, defaultTheme, parentSelector = DEFAULT_ELEMENT_SELECTOR, diff --git a/code/addons/themes/src/decorators/data-attribute.decorator.tsx b/code/addons/themes/src/decorators/data-attribute.decorator.tsx index 546885db8d62..4009fd9073a0 100644 --- a/code/addons/themes/src/decorators/data-attribute.decorator.tsx +++ b/code/addons/themes/src/decorators/data-attribute.decorator.tsx @@ -12,7 +12,8 @@ export interface DataAttributeStrategyConfiguration { const DEFAULT_ELEMENT_SELECTOR = 'html'; const DEFAULT_DATA_ATTRIBUTE = 'data-theme'; -export const withThemeByDataAttribute = ({ +// TODO check with @kasperpeulen: change the types so they can be correctly inferred from context e.g. any> +export const withThemeByDataAttribute = ({ themes, defaultTheme, parentSelector = DEFAULT_ELEMENT_SELECTOR, diff --git a/code/addons/themes/src/decorators/provider.decorator.tsx b/code/addons/themes/src/decorators/provider.decorator.tsx index 6063034eb859..0466a29e6ac8 100644 --- a/code/addons/themes/src/decorators/provider.decorator.tsx +++ b/code/addons/themes/src/decorators/provider.decorator.tsx @@ -16,7 +16,8 @@ export interface ProviderStrategyConfiguration { const pluckThemeFromKeyPairTuple = ([_, themeConfig]: [string, Theme]): Theme => themeConfig; -export const withThemeFromJSXProvider = ({ +// TODO check with @kasperpeulen: change the types so they can be correctly inferred from context e.g. any> +export const withThemeFromJSXProvider = ({ Provider, GlobalStyles, defaultTheme, diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index 61e4794a1048..cef626a37355 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 3f8ed938ff27..119fa13a2fce 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Build responsive components by adjusting Storybook’s viewport size and orientation", "keywords": [ "addon", diff --git a/code/builders/builder-manager/package.json b/code/builders/builder-manager/package.json index bac171608295..efe651986f45 100644 --- a/code/builders/builder-manager/package.json +++ b/code/builders/builder-manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-manager", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook manager builder", "keywords": [ "storybook" diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index 5e5a9277d64b..556cf6c23ecb 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-vite", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "A plugin to run and build Storybooks with Vite", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme", "bugs": { diff --git a/code/builders/builder-vite/src/build.ts b/code/builders/builder-vite/src/build.ts index ebf4f030e8b8..ff8f46c8bed3 100644 --- a/code/builders/builder-vite/src/build.ts +++ b/code/builders/builder-vite/src/build.ts @@ -41,7 +41,7 @@ export async function build(options: Options) { const turbosnapPluginName = 'rollup-plugin-turbosnap'; const hasTurbosnapPlugin = - finalConfig.plugins && hasVitePlugins(finalConfig.plugins, [turbosnapPluginName]); + finalConfig.plugins && (await hasVitePlugins(finalConfig.plugins, [turbosnapPluginName])); if (hasTurbosnapPlugin) { logger.warn(dedent`Found '${turbosnapPluginName}' which is now included by default in Storybook 8. Removing from your plugins list. Ensure you pass \`--webpack-stats-json\` to generate stats. @@ -53,6 +53,9 @@ export async function build(options: Options) { await viteBuild(await sanitizeEnvVars(options, finalConfig)); - const statsPlugin = findPlugin(finalConfig, 'rollup-plugin-webpack-stats') as WebpackStatsPlugin; + const statsPlugin = findPlugin( + finalConfig, + 'storybook:rollup-plugin-webpack-stats' + ) as WebpackStatsPlugin; return statsPlugin?.storybookGetStats(); } diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index ebcccddcdeb6..8ff13a72b582 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/e2e-tests/addon-docs.spec.ts b/code/e2e-tests/addon-docs.spec.ts index 9be08c4b674a..4ae3da33e99e 100644 --- a/code/e2e-tests/addon-docs.spec.ts +++ b/code/e2e-tests/addon-docs.spec.ts @@ -34,8 +34,7 @@ test.describe('addon-docs', () => { await expect(anotherStory).toContainText('Another button, just to show multiple stories'); }); - // FIXME - get rid of the flake - test.skip('should show source=code view for stories', async ({ page }) => { + test('should show source=code view for stories', async ({ page }) => { const skipped = [ // SSv6 does not render stories in the correct order in our sandboxes 'internal\\/ssv6', diff --git a/code/e2e-tests/tags.spec.ts b/code/e2e-tests/tags.spec.ts index e3d79723c8f8..37fb76fb814c 100644 --- a/code/e2e-tests/tags.spec.ts +++ b/code/e2e-tests/tags.spec.ts @@ -3,8 +3,7 @@ import { SbPage } from './util'; const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; -// FIXME - get rid of the flake -test.describe.skip('tags', () => { +test.describe('tags', () => { test.beforeEach(async ({ page }) => { await page.goto(storybookUrl); await new SbPage(page).waitUntilLoaded(); diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index a5cd680014a7..dd6f6cf884b5 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index 8b1bbcbc7208..c28e9fa27808 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember", "bugs": { diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json index 78ae2ded1c53..8679c848c44a 100644 --- a/code/frameworks/html-vite/package.json +++ b/code/frameworks/html-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-vite", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index d800e8bc0bc0..375f3555cd35 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index d4e3346a826b..f4aad1a0751f 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/nextjs", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Next.js", "keywords": [ "storybook", @@ -128,7 +128,7 @@ "@types/babel__preset-env": "^7", "@types/loader-utils": "^2.0.5", "@types/react-refresh": "^0", - "next": "^14.0.2", + "next": "^14.1.0", "typescript": "^5.3.2", "webpack": "^5.65.0" }, diff --git a/code/frameworks/nextjs/src/images/next-image.tsx b/code/frameworks/nextjs/src/images/next-image.tsx index f2e2d9d1467c..ea1e1f2eb844 100644 --- a/code/frameworks/nextjs/src/images/next-image.tsx +++ b/code/frameworks/nextjs/src/images/next-image.tsx @@ -1,7 +1,8 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import is aliased in webpack config -import OriginalNextImage from 'sb-original/next/image'; +import * as NextImageNamespace from 'sb-original/next/image'; import type * as _NextImage from 'next/image'; + import React from 'react'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -11,6 +12,8 @@ import { ImageContext as ImageContextValue } from '@storybook/nextjs/dist/image- import { type ImageContext as ImageContextType } from '../image-context'; import { defaultLoader } from './next-image-default-loader'; +const OriginalNextImage = NextImageNamespace.default; +const { getImageProps: originalGetImageProps } = NextImageNamespace; const ImageContext = ImageContextValue as typeof ImageContextType; const MockedNextImage = React.forwardRef( @@ -30,4 +33,7 @@ const MockedNextImage = React.forwardRef + originalGetImageProps?.({ loader: defaultLoader, ...props }); + export default MockedNextImage; diff --git a/code/frameworks/nextjs/src/preset.ts b/code/frameworks/nextjs/src/preset.ts index bb7ac0ddf153..e76db8104d1b 100644 --- a/code/frameworks/nextjs/src/preset.ts +++ b/code/frameworks/nextjs/src/preset.ts @@ -117,7 +117,8 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (baseConfig, }); const babelRCPath = join(getProjectRoot(), '.babelrc'); - const hasBabelConfig = fs.existsSync(babelRCPath); + const babelConfigPath = join(getProjectRoot(), 'babel.config.js'); + const hasBabelConfig = fs.existsSync(babelRCPath) || fs.existsSync(babelConfigPath); const nextjsVersion = getNextjsVersion(); const isDevelopment = options.configType !== 'PRODUCTION'; diff --git a/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts b/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts index 0d47f4cc64e2..d70579d8fc72 100644 --- a/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts +++ b/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts @@ -92,6 +92,8 @@ async function loaderTransform(this: any, parentTrace: any, source?: string, inp swcCacheDir, relativeFilePathFromRoot, serverComponents, + // @ts-expect-error Relevant for Next.js < 14.1 + // TODO: Remove this when Next.js < 14.1 is no longer supported isReactServerLayer, }); diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/GetImageProps.stories.jsx b/code/frameworks/nextjs/template/stories_nextjs-default-js/GetImageProps.stories.jsx new file mode 100644 index 000000000000..7c8e75a09083 --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-default-js/GetImageProps.stories.jsx @@ -0,0 +1,33 @@ +import { getImageProps } from 'next/image'; +import React from 'react'; + +import Accessibility from '../../assets/accessibility.svg'; +import Testing from '../../assets/testing.png'; + +// referenced from https://nextjs.org/docs/pages/api-reference/components/image#theme-detection-picture +const Component = (props) => { + const { + props: { srcSet: dark }, + } = getImageProps({ src: Accessibility, ...props }); + const { + // capture rest on one to spread to img as default; it doesn't matter which barring art direction + props: { srcSet: light, ...rest }, + } = getImageProps({ src: Testing, ...props }); + + return ( + + + + + + ); +}; + +export default { + component: Component, + args: { + alt: 'getImageProps Example', + }, +}; + +export const Default = {}; diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index c34b21e89ad7..1b228d5b0af2 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-vite", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index b33e68211d80..3d33c3af950b 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index 053aa9b35282..8d0738041d5f 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-vite", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-vite/src/types.ts b/code/frameworks/react-vite/src/types.ts index 0f31ea91db51..2499ae4bf93a 100644 --- a/code/frameworks/react-vite/src/types.ts +++ b/code/frameworks/react-vite/src/types.ts @@ -56,7 +56,7 @@ type TypescriptOptions = TypescriptOptionsBase & { */ export type StorybookConfig = Omit< StorybookConfigBase, - keyof StorybookConfigVite | keyof StorybookConfigFramework + keyof StorybookConfigVite | keyof StorybookConfigFramework | 'typescript' > & StorybookConfigVite & StorybookConfigFramework & { diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index 32215f431682..b3aec9df3836 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index 8855bfd2e442..389569798629 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 961969e507f7..78d2347568ed 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-vite", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index ff1f2b245f63..eebe0738192b 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index 83f70b36b126..4c451ff5e4d7 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/sveltekit", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for SvelteKit", "keywords": [ "storybook", diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index eed6922b71bc..456ba9beb140 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-vite", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index c05c303d988f..2e3b51a2e145 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json index 224a0ee3b6ed..5e71c90cdb89 100644 --- a/code/frameworks/web-components-vite/package.json +++ b/code/frameworks/web-components-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-vite", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index e9974bfdf16d..2fcec48139e5 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-webpack5", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit", diff --git a/code/lib/channels/package.json b/code/lib/channels/package.json index 0be834c503cc..94160358b093 100644 --- a/code/lib/channels/package.json +++ b/code/lib/channels/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/channels", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index 27b64dae50cd..b02d98f7bbbc 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -1,6 +1,6 @@ { "name": "sb", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index 7a26a80642cb..6a0866a23243 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json index 2ea8e20d58b0..cdcc81a0032e 100644 --- a/code/lib/cli/package.json +++ b/code/lib/cli/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/cli", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook's CLI - install, dev, build, upgrade, and more", "keywords": [ "cli", @@ -56,6 +56,7 @@ "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts" }, "dependencies": { + "@babel/core": "^7.23.0", "@babel/types": "^7.23.0", "@ndelangen/get-tarball": "^3.0.7", "@storybook/codemod": "workspace:*", @@ -98,6 +99,7 @@ "@types/util-deprecate": "^1.0.0", "boxen": "^7.1.1", "slash": "^5.0.0", + "strip-ansi": "^7.1.0", "strip-json-comments": "^3.1.1", "typescript": "^5.3.2" }, diff --git a/code/lib/cli/src/autoblock/block-dependencies-versions.ts b/code/lib/cli/src/autoblock/block-dependencies-versions.ts index 284562aa9f6d..fb052e60c62e 100644 --- a/code/lib/cli/src/autoblock/block-dependencies-versions.ts +++ b/code/lib/cli/src/autoblock/block-dependencies-versions.ts @@ -43,9 +43,6 @@ export const blocker = createBlocker({ return acc; }, false); }, - message(options, data) { - return `Found ${data.packageName} version: ${data.installedVersion}, please upgrade to ${data.minimumVersion} or higher.`; - }, log(options, data) { switch (data.packageName) { case 'react-scripts': diff --git a/code/lib/cli/src/autoblock/block-node-version.ts b/code/lib/cli/src/autoblock/block-node-version.ts index 220b29823e4e..8d67cdd51018 100644 --- a/code/lib/cli/src/autoblock/block-node-version.ts +++ b/code/lib/cli/src/autoblock/block-node-version.ts @@ -11,9 +11,6 @@ export const blocker = createBlocker({ } return false; }, - message(options, data) { - return `Please use Node.js v18 or higher.`; - }, log(options, data) { return dedent` We've detected you're using Node.js v${data.nodeVersion}. diff --git a/code/lib/cli/src/autoblock/block-stories-mdx.ts b/code/lib/cli/src/autoblock/block-stories-mdx.ts index b868d913ecd0..3c1fadeda351 100644 --- a/code/lib/cli/src/autoblock/block-stories-mdx.ts +++ b/code/lib/cli/src/autoblock/block-stories-mdx.ts @@ -11,12 +11,7 @@ export const blocker = createBlocker({ } return { files }; }, - message(options, data) { - return `Found ${data.files.length} stories.mdx ${ - data.files.length === 1 ? 'file' : 'files' - }, these must be migrated.`; - }, - log() { + log(options, data) { return dedent` Support for *.stories.mdx files has been removed. Please see the migration guide for more information: @@ -26,6 +21,10 @@ export const blocker = createBlocker({ Check the migration guide for more information: https://mdxjs.com/blog/v3/ + Found ${data.files.length} stories.mdx ${ + data.files.length === 1 ? 'file' : 'files' + }, these must be migrated. + Manually run the migration script to convert your stories.mdx files to CSF format documented here: https://storybook.js.org/docs/migration-guide#storiesmdx-to-mdxcsf `; diff --git a/code/lib/cli/src/autoblock/block-storystorev6.ts b/code/lib/cli/src/autoblock/block-storystorev6.ts index 40a9f8822ac9..cd9eaffb6a7a 100644 --- a/code/lib/cli/src/autoblock/block-storystorev6.ts +++ b/code/lib/cli/src/autoblock/block-storystorev6.ts @@ -1,4 +1,3 @@ -import { relative } from 'path'; import { createBlocker } from './types'; import { dedent } from 'ts-dedent'; import type { StorybookConfigRaw } from '@storybook/types'; @@ -15,10 +14,6 @@ export const blocker = createBlocker({ } return false; }, - message(options, data) { - const mainConfigPath = relative(process.cwd(), options.mainConfigPath); - return `StoryStoreV7 feature must be removed from ${mainConfigPath}`; - }, log() { return dedent` StoryStoreV7 feature must be removed from your Storybook configuration. diff --git a/code/lib/cli/src/autoblock/index.test.ts b/code/lib/cli/src/autoblock/index.test.ts index ce5fa3170411..18be67a4e6d8 100644 --- a/code/lib/cli/src/autoblock/index.test.ts +++ b/code/lib/cli/src/autoblock/index.test.ts @@ -2,8 +2,8 @@ import { expect, test, vi } from 'vitest'; import { autoblock } from './index'; import { JsPackageManagerFactory } from '@storybook/core-common'; import { createBlocker } from './types'; -import { writeFile as writeFileRaw } from 'node:fs/promises'; -import { logger } from '@storybook/node-logger'; +import { logger as loggerRaw } from '@storybook/node-logger'; +import stripAnsi from 'strip-ansi'; vi.mock('node:fs/promises', () => ({ writeFile: vi.fn(), @@ -19,26 +19,23 @@ vi.mock('@storybook/node-logger', () => ({ }, })); -const writeFile = vi.mocked(writeFileRaw); +const logger = vi.mocked(loggerRaw); const blockers = { alwaysPass: createBlocker({ id: 'alwaysPass', check: async () => false, - message: () => 'Always pass', log: () => 'Always pass', }), alwaysFail: createBlocker({ id: 'alwaysFail', check: async () => ({ bad: true }), - message: () => 'Always fail', - log: () => '...', + log: () => 'Always fail', }), alwaysFail2: createBlocker({ id: 'alwaysFail2', check: async () => ({ disaster: true }), - message: () => 'Always fail 2', - log: () => '...', + log: () => 'Always fail 2', }), } as const; @@ -75,17 +72,15 @@ test('1 fail', async () => { Promise.resolve({ blocker: blockers.alwaysPass }), Promise.resolve({ blocker: blockers.alwaysFail }), ]); - expect(writeFile).toHaveBeenCalledWith( - expect.any(String), - expect.stringContaining('alwaysFail'), - expect.any(Object) - ); + expect(result).toBe('alwaysFail'); expect(logger.plain).toHaveBeenCalledWith(expect.stringContaining('Oh no..')); + expect(stripAnsi(logger.plain.mock.calls[1][0])).toMatchInlineSnapshot(` + "Blocking your upgrade because of the following issues: + + Always fail - expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` - "(alwaysFail): - ..." + Fix the above issues and try running the upgrade command again." `); }); @@ -95,14 +90,14 @@ test('multiple fails', async () => { Promise.resolve({ blocker: blockers.alwaysFail }), Promise.resolve({ blocker: blockers.alwaysFail2 }), ]); - expect(writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` - "(alwaysFail): - ... + expect(stripAnsi(logger.plain.mock.calls[1][0])).toMatchInlineSnapshot(` + "Blocking your upgrade because of the following issues: + + Always fail - ---- + Always fail 2 - (alwaysFail2): - ..." + Fix the above issues and try running the upgrade command again." `); expect(result).toBe('alwaysFail'); diff --git a/code/lib/cli/src/autoblock/index.ts b/code/lib/cli/src/autoblock/index.ts index ca8116d890cb..a6c45a2318ba 100644 --- a/code/lib/cli/src/autoblock/index.ts +++ b/code/lib/cli/src/autoblock/index.ts @@ -2,7 +2,6 @@ import type { AutoblockOptions, Blocker } from './types'; import { logger } from '@storybook/node-logger'; import chalk from 'chalk'; import boxen from 'boxen'; -import { writeFile } from 'node:fs/promises'; const excludesFalse = (x: T | false): x is T => x !== false; @@ -34,7 +33,6 @@ export const autoblock = async ( return { id: blocker.id, value: true, - message: blocker.message(options, result), log: blocker.log(options, result), }; } else { @@ -46,12 +44,9 @@ export const autoblock = async ( const faults = out.filter(excludesFalse); if (faults.length > 0) { - const LOG_FILE_NAME = 'migration-storybook.log'; - const messages = { welcome: `Blocking your upgrade because of the following issues:`, reminder: chalk.yellow('Fix the above issues and try running the upgrade command again.'), - logfile: chalk.yellow(`You can find more details in ./${LOG_FILE_NAME}.`), }; const borderColor = '#FC521F'; @@ -59,22 +54,13 @@ export const autoblock = async ( logger.plain( boxen( [messages.welcome] - .concat(faults.map((i) => i.message)) + .concat(faults.map((i) => i.log)) .concat([messages.reminder]) - .concat([messages.logfile]) .join('\n\n'), { borderStyle: 'round', padding: 1, borderColor } ) ); - await writeFile( - LOG_FILE_NAME, - faults.map((i) => '(' + i.id + '):\n' + i.log).join('\n\n----\n\n'), - { - encoding: 'utf-8', - } - ); - return faults[0].id; } diff --git a/code/lib/cli/src/autoblock/types.ts b/code/lib/cli/src/autoblock/types.ts index 62be9625c76e..39e6c728921a 100644 --- a/code/lib/cli/src/autoblock/types.ts +++ b/code/lib/cli/src/autoblock/types.ts @@ -21,13 +21,6 @@ export interface Blocker { * @returns A truthy value to activate the block, return false to proceed. */ check: (options: AutoblockOptions) => Promise; - /** - * Format a message to be printed to the log-file. - * @param context - * @param data returned from the check method. - * @returns The string to print to the terminal. - */ - message: (options: AutoblockOptions, data: T) => string; /** * Format a message to be printed to the log-file. * @param context diff --git a/code/lib/cli/src/automigrate/fixes/angular-builders-multiproject.ts b/code/lib/cli/src/automigrate/fixes/angular-builders-multiproject.ts index 9bf74a288416..d57fbd28a10c 100644 --- a/code/lib/cli/src/automigrate/fixes/angular-builders-multiproject.ts +++ b/code/lib/cli/src/automigrate/fixes/angular-builders-multiproject.ts @@ -10,7 +10,7 @@ interface AngularBuildersMultiprojectRunOptions {} export const angularBuildersMultiproject: Fix = { id: 'angular-builders-multiproject', - promptOnly: true, + promptType: 'manual', async check({ packageManager, mainConfig }) { // Skip in case of NX diff --git a/code/lib/cli/src/automigrate/fixes/incompatible-addons.ts b/code/lib/cli/src/automigrate/fixes/incompatible-addons.ts index ce9d01ccd96a..469383834cc1 100644 --- a/code/lib/cli/src/automigrate/fixes/incompatible-addons.ts +++ b/code/lib/cli/src/automigrate/fixes/incompatible-addons.ts @@ -9,7 +9,7 @@ interface IncompatibleAddonsOptions { export const incompatibleAddons: Fix = { id: 'incompatible-addons', - promptOnly: true, + promptType: 'manual', async check({ mainConfig, packageManager }) { const incompatibleAddonList = await getIncompatibleAddons(mainConfig, packageManager); diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index 030e31baa6dc..68b642586f2b 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -5,6 +5,7 @@ import { webpack5 } from './webpack5'; import { vite4 } from './vite4'; import { vue3 } from './vue3'; import { mdxgfm } from './mdx-gfm'; +import { removeLegacyMDX1 } from './remove-legacymdx1'; import { eslintPlugin } from './eslint-plugin'; import { builderVite } from './builder-vite'; import { viteConfigFile } from './vite-config-file'; @@ -21,6 +22,8 @@ import { wrapRequire } from './wrap-require'; import { reactDocgen } from './react-docgen'; import { removeReactDependency } from './prompt-remove-react'; import { storyshotsMigration } from './storyshots-migration'; +import { removeArgtypesRegex } from './remove-argtypes-regex'; +import { webpack5CompilerSetup } from './webpack5-compiler-setup'; import { removeJestTestingLibrary } from './remove-jest-testing-library'; export * from '../types'; @@ -37,6 +40,7 @@ export const allFixes: Fix[] = [ sbBinary, sbScripts, incompatibleAddons, + removeArgtypesRegex, removeJestTestingLibrary, removedGlobalClientAPIs, mdx1to2, @@ -48,6 +52,8 @@ export const allFixes: Fix[] = [ reactDocgen, storyshotsMigration, removeReactDependency, + removeLegacyMDX1, + webpack5CompilerSetup, ]; export const initFixes: Fix[] = [eslintPlugin]; diff --git a/code/lib/cli/src/automigrate/fixes/mdx-gfm.test.ts b/code/lib/cli/src/automigrate/fixes/mdx-gfm.test.ts index dab0a301ac41..c917fe321ee9 100644 --- a/code/lib/cli/src/automigrate/fixes/mdx-gfm.test.ts +++ b/code/lib/cli/src/automigrate/fixes/mdx-gfm.test.ts @@ -40,6 +40,7 @@ describe('no-ops', () => { packageManager: {}, main: { features: { + // @ts-expect-error (user might be upgrading from a version that had this option) legacyMdx1: true, }, }, diff --git a/code/lib/cli/src/automigrate/fixes/mdx-gfm.ts b/code/lib/cli/src/automigrate/fixes/mdx-gfm.ts index f844decf1443..7fc07b63349e 100644 --- a/code/lib/cli/src/automigrate/fixes/mdx-gfm.ts +++ b/code/lib/cli/src/automigrate/fixes/mdx-gfm.ts @@ -54,6 +54,7 @@ export const mdxgfm: Fix = { return files.some((f) => f.endsWith('.mdx')); }, Promise.resolve(false)); + // @ts-expect-error (user might be upgrading from an older version that still had it) const usesMDX1 = mainConfig?.features?.legacyMdx1 === true || false; const skip = usesMDX1 || diff --git a/code/lib/cli/src/automigrate/fixes/prompt-remove-react.ts b/code/lib/cli/src/automigrate/fixes/prompt-remove-react.ts index eb93ce015b08..a7586a03ff15 100644 --- a/code/lib/cli/src/automigrate/fixes/prompt-remove-react.ts +++ b/code/lib/cli/src/automigrate/fixes/prompt-remove-react.ts @@ -5,7 +5,7 @@ import type { Fix } from '../types'; export const removeReactDependency: Fix<{}> = { id: 'remove-react-dependency', - promptOnly: true, + promptType: 'manual', async check({ packageManager, mainConfig, storybookVersion }) { // when the user is using the react renderer, we should not prompt them to remove react diff --git a/code/lib/cli/src/automigrate/fixes/remove-argtypes-regex.ts b/code/lib/cli/src/automigrate/fixes/remove-argtypes-regex.ts new file mode 100644 index 000000000000..6a517fc0be0c --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/remove-argtypes-regex.ts @@ -0,0 +1,81 @@ +import type { Fix } from '../types'; +import * as fs from 'node:fs/promises'; +import * as babel from '@babel/core'; +import type { BabelFile, NodePath } from '@babel/core'; +import { babelParse } from '@storybook/csf-tools'; +import dedent from 'ts-dedent'; +import chalk from 'chalk'; + +export const removeArgtypesRegex: Fix<{ argTypesRegex: NodePath; previewConfigPath: string }> = { + id: 'remove-argtypes-regex', + promptType: 'manual', + async check({ previewConfigPath }) { + if (!previewConfigPath) return null; + + const previewFile = await fs.readFile(previewConfigPath, { encoding: 'utf-8' }); + + // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606 + const file: BabelFile = new babel.File( + { filename: previewConfigPath }, + { code: previewFile, ast: babelParse(previewFile) } + ); + + let argTypesRegex; + + file.path.traverse({ + Identifier: (path) => { + if (path.node.name === 'argTypesRegex') { + argTypesRegex = path; + } + }, + }); + + return argTypesRegex ? { argTypesRegex, previewConfigPath } : null; + }, + prompt({ argTypesRegex, previewConfigPath }) { + const snippet = dedent` + import { fn } from '@storybook/test'; + export default { + args: { onClick: fn() }, // will log to the action panel when clicked + };`; + + // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606 + const file: BabelFile = new babel.File( + { file: 'story.tsx' }, + { code: snippet, ast: babelParse(snippet) } + ); + + let formattedSnippet; + file.path.traverse({ + Identifier: (path) => { + if (path.node.name === 'fn') { + formattedSnippet = path.buildCodeFrameError(``).message; + } + }, + }); + + return dedent` + ${chalk.bold('Attention')}: We've detected that you're using argTypesRegex: + + ${argTypesRegex.buildCodeFrameError(`${previewConfigPath}`).message} + + In Storybook 8, we recommend removing this regex. + Assign explicit spies with the ${chalk.cyan('fn')} function instead: + ${formattedSnippet} + + The above pattern is needed when using spies in the play function, ${chalk.bold( + 'even' + )} if you keep using argTypesRegex. + Implicit spies (based on a combination of argTypesRegex and docgen) is not supported in Storybook 8. + + Use the following command to check for spy usages in your play functions: + ${chalk.cyan( + 'npx storybook migrate find-implicit-spies --glob="**/*.stories.@(js|jsx|ts|tsx)"' + )} + + Make sure to assign an explicit ${chalk.cyan('fn')} to your args for those usages. + + For more information please visit our migration guide: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function + `; + }, +}; diff --git a/code/lib/cli/src/automigrate/fixes/remove-global-client-apis.ts b/code/lib/cli/src/automigrate/fixes/remove-global-client-apis.ts index 4a1304dae1a6..2f25e5277096 100644 --- a/code/lib/cli/src/automigrate/fixes/remove-global-client-apis.ts +++ b/code/lib/cli/src/automigrate/fixes/remove-global-client-apis.ts @@ -19,7 +19,7 @@ interface GlobalClientAPIOptions { export const removedGlobalClientAPIs: Fix = { id: 'removedglobalclientapis', - promptOnly: true, + promptType: 'manual', async check({ previewConfigPath }) { if (previewConfigPath) { diff --git a/code/lib/cli/src/automigrate/fixes/remove-jest-testing-library.ts b/code/lib/cli/src/automigrate/fixes/remove-jest-testing-library.ts index 87cf964468b3..ba238dd2740a 100644 --- a/code/lib/cli/src/automigrate/fixes/remove-jest-testing-library.ts +++ b/code/lib/cli/src/automigrate/fixes/remove-jest-testing-library.ts @@ -4,7 +4,7 @@ import type { Fix } from '../types'; export const removeJestTestingLibrary: Fix<{ incompatiblePackages: string[] }> = { id: 'remove-jest-testing-library', - promptOnly: true, + promptType: 'manual', async check({ mainConfig, packageManager }) { const deps = await packageManager.getAllDependencies(); diff --git a/code/lib/cli/src/automigrate/fixes/remove-legacymdx1.ts b/code/lib/cli/src/automigrate/fixes/remove-legacymdx1.ts new file mode 100644 index 000000000000..57f90e8403af --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/remove-legacymdx1.ts @@ -0,0 +1,56 @@ +import { dedent } from 'ts-dedent'; + +import { writeConfig } from '@storybook/csf-tools'; + +import type { Fix } from '../types'; +import { updateMainConfig } from '../helpers/mainConfigFile'; + +const logger = console; + +interface RemoveLegacyMDX1Options { + hasFeature: boolean; +} + +/** + * Does the user have 'legacyMdx1' in their main.ts? + * + * If so, prompt them to upgrade to delete it. + */ +export const removeLegacyMDX1: Fix = { + id: 'builder-vite', + + async check({ mainConfig }) { + if (mainConfig.features) { + // + return { + hasFeature: !!Object.hasOwn(mainConfig.features, 'legacyMdx1'), + }; + } + + return null; + }, + + prompt({}) { + return dedent` + You have features.legacyMdx1 in your Storybook main config file. This feature has been removed. Shall we remove it from your Storybook main config file? + + Link: https://storybook.js.org/docs/8.0/migration-guide + `; + }, + + async run({ dryRun, mainConfigPath, skipInstall, packageManager }) { + logger.info(`✅ Removing legacyMdx1 feature`); + if (!dryRun) { + await updateMainConfig({ dryRun: !!dryRun, mainConfigPath }, async (main) => { + main.removeField(['features', 'legacyMdx1']); + await writeConfig(main); + }); + + const packageJson = await packageManager.retrievePackageJson(); + + await packageManager.removeDependencies({ skipInstall: skipInstall, packageJson }, [ + '@storybook/mdx1-csf', + ]); + } + }, +}; diff --git a/code/lib/cli/src/automigrate/fixes/storyshots-migration.ts b/code/lib/cli/src/automigrate/fixes/storyshots-migration.ts index 6d047f88449f..6d132037c3e0 100644 --- a/code/lib/cli/src/automigrate/fixes/storyshots-migration.ts +++ b/code/lib/cli/src/automigrate/fixes/storyshots-migration.ts @@ -4,7 +4,7 @@ import type { Fix } from '../types'; export const storyshotsMigration: Fix = { id: 'storyshots-migration', - promptOnly: true, + promptType: 'manual', async check({ mainConfig, packageManager }) { const allDeps = await packageManager.getAllDependencies(); diff --git a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts index f8047a839af9..899c3807ed3a 100644 --- a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts +++ b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts @@ -5,7 +5,7 @@ import { getFrameworkPackageName } from '../helpers/mainConfigFile'; import { frameworkToRenderer } from '../../helpers'; import { frameworkPackages } from '@storybook/core-common'; -interface Webpack5RunOptions { +interface ViteConfigFileRunOptions { plugins: string[]; existed: boolean; } @@ -14,12 +14,12 @@ export const viteConfigFile = { id: 'viteConfigFile', async check({ mainConfig, packageManager }) { - const viteConfigPath = await findUp([ + let isViteConfigFileFound = !!(await findUp([ 'vite.config.js', 'vite.config.mjs', 'vite.config.cjs', 'vite.config.ts', - ]); + ])); const rendererToVitePluginMap: Record = { preact: '@preact/preset-vite', @@ -45,7 +45,16 @@ export const viteConfigFile = { const rendererName = frameworkToRenderer[frameworkName as keyof typeof frameworkToRenderer]; - if (!viteConfigPath && isUsingViteBuilder) { + if ( + !isViteConfigFileFound && + mainConfig.core?.builder && + typeof mainConfig.core?.builder !== 'string' && + mainConfig.core?.builder.options + ) { + isViteConfigFileFound = !!mainConfig.core?.builder.options.viteConfigPath; + } + + if (!isViteConfigFileFound && isUsingViteBuilder) { const plugins = []; if (rendererToVitePluginMap[rendererName]) { @@ -54,7 +63,7 @@ export const viteConfigFile = { return { plugins, - existed: !!viteConfigPath, + existed: isViteConfigFileFound, }; } @@ -66,7 +75,7 @@ export const viteConfigFile = { const pluginVersion = await packageManager.getPackageVersion(plugin); - if (viteConfigPath && isUsingViteBuilder && !pluginVersion) { + if (isViteConfigFileFound && isUsingViteBuilder && !pluginVersion) { const plugins = []; if (plugin) { @@ -75,7 +84,7 @@ export const viteConfigFile = { return { plugins, - existed: !viteConfigPath, + existed: !isViteConfigFileFound, }; } @@ -108,4 +117,4 @@ export const viteConfigFile = { This change was necessary to support newer versions of Vite. `; }, -} satisfies Fix; +} satisfies Fix; diff --git a/code/lib/cli/src/automigrate/fixes/vite4.ts b/code/lib/cli/src/automigrate/fixes/vite4.ts index d04c4abd10d7..f85cc4d57cef 100644 --- a/code/lib/cli/src/automigrate/fixes/vite4.ts +++ b/code/lib/cli/src/automigrate/fixes/vite4.ts @@ -5,7 +5,7 @@ import type { Fix } from '../types'; const logger = console; -interface Webpack5RunOptions { +interface Vite4RunOptions { viteVersion: string | null; } @@ -40,4 +40,4 @@ export const vite4 = { await packageManager.addDependencies({ installAsDevDependencies: true }, deps); } }, -} satisfies Fix; +} satisfies Fix; diff --git a/code/lib/cli/src/automigrate/fixes/webpack5-compiler-setup.test.ts b/code/lib/cli/src/automigrate/fixes/webpack5-compiler-setup.test.ts new file mode 100644 index 000000000000..dcebc1f28b8b --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/webpack5-compiler-setup.test.ts @@ -0,0 +1,518 @@ +import { vi, describe, it, expect } from 'vitest'; +import type { StorybookConfig } from '@storybook/types'; +import type { JsPackageManager } from '@storybook/core-common'; +import { webpack5CompilerSetup } from './webpack5-compiler-setup'; +import { CoreWebpackCompilers } from '../../project_types'; + +const check = async ({ + packageManager, + mainConfig, + storybookVersion = '8.0.0', +}: { + packageManager?: Partial; + main?: Partial & Record; + storybookVersion?: string; + mainConfig?: Partial; +}) => { + return webpack5CompilerSetup.check({ + packageManager: packageManager as any, + configDir: '', + storybookVersion, + mainConfig: mainConfig as any, + }); +}; + +const promptMocks = vi.hoisted(() => { + return { + default: vi.fn(), + }; +}); + +vi.mock('prompts', () => { + return { + default: promptMocks.default, + }; +}); + +// mock chalk yellow and cyan +vi.mock('chalk', () => { + return { + default: { + yellow: (str: string) => str, + cyan: (str: string) => str, + }, + }; +}); + +describe('webpack5Migration check function', () => { + describe('return null', async () => { + it('should return null if one of the addons is already installed', async () => { + const result = check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + addons: ['@storybook/addon-webpack5-compiler-swc'], + framework: { + name: '@storybook/react-webpack5', + options: { + builder: { + useSWC: true, + }, + }, + }, + }, + }); + + expect(result).resolves.toBeNull(); + }); + + it('should return null if the builder is not webpack5', async () => { + const result = check({ + mainConfig: { + framework: { + name: '@storybook/react-vite', + }, + }, + }); + + await expect(result).resolves.toBeNull(); + }); + + it('should return null if the framework is Angular', async () => { + const result = check({ + mainConfig: { + framework: '@storybook/angular', + }, + }); + + await expect(result).resolves.toBeNull(); + // ... + }); + + it('should return null if the framework is Ember', async () => { + const result = check({ + mainConfig: { + framework: { + name: '@storybook/ember', + }, + }, + }); + + await expect(result).resolves.toBeNull(); + }); + + it('should return null if the framework is Webpack5 based but a different framework builder is used', async () => { + const result = check({ + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + options: { + builder: '@storybook/builder-vite', + }, + }, + }, + }); + + await expect(result).resolves.toBeNull(); + }); + + it('should return null if the framework is Webpack5 based but a different core builder is used', async () => { + const result = check({ + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + }, + core: { + builder: '@storybook/builder-vite', + }, + }, + }); + + await expect(result).resolves.toBeNull(); + }); + + it('should return null if the framework is CRA based', async () => { + const result = check({ + packageManager: { + getPackageVersion: (name) => { + if (name === 'react-scripts') { + return Promise.resolve('5.0.0'); + } + + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + }, + }, + }); + + await expect(result).resolves.toBeNull(); + }); + }); + + describe('useSWC', () => { + it('should return shouldRemoveSWCFlag: true when useSWC flag is set to true', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + options: { + builder: { + useSWC: true, + }, + }, + }, + }, + }); + + expect(result).contains({ + shouldRemoveSWCFlag: true, + }); + }); + + it('should return shouldRemoveSWCFlag: true when useSWC flag is set to false', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + options: { + builder: { + useSWC: false, + }, + }, + }, + }, + }); + + expect(result).contains({ + shouldRemoveSWCFlag: true, + }); + }); + + it('should return shouldRemoveSWCFlag: false when useSWC flag is not set', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + options: { + builder: {}, + }, + }, + }, + }); + + expect(result).contains({ + shouldRemoveSWCFlag: false, + }); + }); + }); + + describe('Next.js', () => { + it('should return isNextJs: true when the framework is nextjs', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/nextjs', + }, + }, + }); + + expect(result).contains({ + isNextJs: true, + }); + }); + + it('should return isNextJs: true AND should return shouldRemoveSWCFlag: true when useSWC flag is set', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/nextjs', + options: { + builder: { + useSWC: true, + }, + }, + }, + }, + }); + + expect(result).contains({ + isNextJs: true, + shouldRemoveSWCFlag: true, + }); + }); + + it('should return isNextJs: false when the framework is not nextjs', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + }, + }, + }); + + expect(result).contains({ + isNextJs: false, + }); + }); + }); + + describe('return options', () => { + it('should return defaultCompiler: babel when useSWC flag is not set', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + }, + }, + }); + + expect(result).contains({ + defaultCompiler: CoreWebpackCompilers.Babel, + }); + }); + + describe('user selects swc', () => { + it('should return defaultCompiler: swc when useSWC flag is set', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/react-webpack5', + options: { + builder: { + useSWC: true, + }, + }, + }, + }, + }); + + expect(result).contains({ + defaultCompiler: CoreWebpackCompilers.SWC, + }); + }); + }); + + it('should return options if the framework is unknown but webpack5 was detected', async () => { + const result = await check({ + packageManager: { + getPackageVersion: (name) => { + if (name === 'webpack') { + return Promise.resolve('5.0.0'); + } + + return Promise.resolve(null); + }, + }, + mainConfig: { + framework: { + name: '@storybook/unknown', + }, + }, + }); + + expect(result).not.toBeNull(); + }); + }); +}); + +describe('promptOnly', () => { + it('should return notification if isNextJs = true and shouldRemoveSWCFlag = false', () => { + const promptType = webpack5CompilerSetup.promptType({ + isNextJs: true, + shouldRemoveSWCFlag: false, + defaultCompiler: undefined, + }); + + expect(promptType).toBe('notification'); + }); + + it('should return auto if isNextJs = false', () => { + const promptType = webpack5CompilerSetup.promptType({ + isNextJs: false, + shouldRemoveSWCFlag: false, + defaultCompiler: undefined, + }); + + expect(promptType).toBe('auto'); + }); + + it('should return auto if shouldRemoveSWCFlag is true', () => { + const promptType = webpack5CompilerSetup.promptType({ + isNextJs: true, + shouldRemoveSWCFlag: true, + defaultCompiler: undefined, + }); + + expect(promptType).toBe('auto'); + }); +}); + +describe('prompt', () => { + it('shouldRemoveSWCFlag = true', async () => { + const prompt = webpack5CompilerSetup.prompt({ + shouldRemoveSWCFlag: true, + isNextJs: false, + defaultCompiler: CoreWebpackCompilers.SWC, + }); + + expect(prompt).toMatchInlineSnapshot(` + "We need to update your Storybook configuration for Webpack 5. + The framework.options.builder.useSWC flag will be removed. + + Storybook's Webpack5 builder is now compiler agnostic, meaning you have to install an additional addon to set up a compiler for Webpack5. + + We have detected, that you want to use SWC as the compiler for Webpack5. + + In the next step, Storybook will install @storybook/addon-webpack5-compiler-swc and will add it to your addons list in your Storybook config. + + After the migration, you can switch Webpack5 compilers by swapping the addon in your project. + You can find more information here: https://storybook.js.org/docs/8.0/builders/webpack#compiler-support" + `); + }); + + it('shouldRemoveSWCFlag = false', async () => { + const prompt = webpack5CompilerSetup.prompt({ + shouldRemoveSWCFlag: false, + isNextJs: false, + defaultCompiler: CoreWebpackCompilers.SWC, + }); + + expect(prompt).toMatchInlineSnapshot(` + "Storybook's Webpack5 builder is now compiler agnostic, meaning you have to install an additional addon to set up a compiler for Webpack5. + + We have detected, that you want to use SWC as the compiler for Webpack5. + + In the next step, Storybook will install @storybook/addon-webpack5-compiler-swc and will add it to your addons list in your Storybook config. + + After the migration, you can switch Webpack5 compilers by swapping the addon in your project. + You can find more information here: https://storybook.js.org/docs/8.0/builders/webpack#compiler-support" + `); + }); + + it('defaultCompiler = babel', async () => { + const prompt = webpack5CompilerSetup.prompt({ + shouldRemoveSWCFlag: false, + isNextJs: false, + defaultCompiler: CoreWebpackCompilers.Babel, + }); + + expect(prompt).toMatchInlineSnapshot(` + "Storybook's Webpack5 builder is now compiler agnostic, meaning you can choose a compiler addon that best fits your project: + + - Babel: A vast ecosystem and is battle-tested. It's a robust choice if you have an extensive Babel setup or need specific Babel plugins for your project. + - SWC: Fast and easy to configure. Ideal if you want faster builds and have a straightforward configuration without the need for Babel's extensibility. + + In the next step, Storybook will ask you to choose a compiler to automatically set it up for you. + + After the migration, you can switch Webpack5 compilers by swapping the addon in your project. + You can find more information here: https://storybook.js.org/docs/8.0/builders/webpack#compiler-support" + `); + }); + + it('isNextJs = true', () => { + const prompt = webpack5CompilerSetup.prompt({ + shouldRemoveSWCFlag: true, + isNextJs: true, + defaultCompiler: CoreWebpackCompilers.SWC, + }); + + expect(prompt).toMatchInlineSnapshot(` + "We need to update your Storybook configuration for Webpack 5. + The framework.options.builder.useSWC flag will be removed. + + Storybook now detects whether it should use Babel or SWC as a compiler by applying the same logic as Next.js itself: + + - If you have a .babelrc (or babel.config.js) file in your project, Storybook will use Babel as the compiler. + - If you have a .babelrc (or babel.config.js) file in your project and you have set + experimental.forceSwcTransforms = true in your next.config.js file, + Storybook will use SWC as the compiler. + - If you don't have a .babelrc (or babel.config.js) file in your project, Storybook will use SWC as the compiler." + `); + }); + + it('isNextjs = false AND defaultCompiler = swc', () => { + const prompt = webpack5CompilerSetup.prompt({ + shouldRemoveSWCFlag: false, + isNextJs: false, + defaultCompiler: CoreWebpackCompilers.SWC, + }); + + expect(prompt).toMatchInlineSnapshot(` + "Storybook's Webpack5 builder is now compiler agnostic, meaning you have to install an additional addon to set up a compiler for Webpack5. + + We have detected, that you want to use SWC as the compiler for Webpack5. + + In the next step, Storybook will install @storybook/addon-webpack5-compiler-swc and will add it to your addons list in your Storybook config. + + After the migration, you can switch Webpack5 compilers by swapping the addon in your project. + You can find more information here: https://storybook.js.org/docs/8.0/builders/webpack#compiler-support" + `); + }); + + it('isNextjs = false AND defaultCompiler = babel', () => { + const prompt = webpack5CompilerSetup.prompt({ + shouldRemoveSWCFlag: false, + isNextJs: false, + defaultCompiler: CoreWebpackCompilers.Babel, + }); + + expect(prompt).toMatchInlineSnapshot(` + "Storybook's Webpack5 builder is now compiler agnostic, meaning you can choose a compiler addon that best fits your project: + + - Babel: A vast ecosystem and is battle-tested. It's a robust choice if you have an extensive Babel setup or need specific Babel plugins for your project. + - SWC: Fast and easy to configure. Ideal if you want faster builds and have a straightforward configuration without the need for Babel's extensibility. + + In the next step, Storybook will ask you to choose a compiler to automatically set it up for you. + + After the migration, you can switch Webpack5 compilers by swapping the addon in your project. + You can find more information here: https://storybook.js.org/docs/8.0/builders/webpack#compiler-support" + `); + }); +}); diff --git a/code/lib/cli/src/automigrate/fixes/webpack5-compiler-setup.ts b/code/lib/cli/src/automigrate/fixes/webpack5-compiler-setup.ts new file mode 100644 index 000000000000..a22f8a55fdd0 --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/webpack5-compiler-setup.ts @@ -0,0 +1,210 @@ +import prompts from 'prompts'; +import type { SupportedFrameworks } from '@storybook/types'; +import { frameworkPackages } from '@storybook/core-common'; +import type { Fix } from '../types'; +import { + getAddonNames, + getBuilderPackageName, + getFrameworkOptions, + getFrameworkPackageName, + updateMainConfig, +} from '../helpers/mainConfigFile'; +import { frameworkToDefaultBuilder } from '../../helpers'; +import { + CoreBuilder, + CoreWebpackCompilers, + builderNameToCoreBuilder, + compilerNameToCoreCompiler, +} from '../../project_types'; +import dedent from 'ts-dedent'; +import chalk from 'chalk'; +import { add } from '../../add'; + +type Options = { + defaultCompiler?: CoreWebpackCompilers; + shouldRemoveSWCFlag: boolean; + isNextJs: boolean; +}; + +export const webpack5CompilerSetup = { + id: 'webpack5-compiler-setup', + + promptType(result) { + return result.isNextJs && !result.shouldRemoveSWCFlag ? 'notification' : 'auto'; + }, + + async check({ mainConfig, packageManager }) { + const addons = getAddonNames(mainConfig); + + if ( + addons.find( + (addon) => + addon.includes(CoreWebpackCompilers.Babel) || addon.includes(CoreWebpackCompilers.SWC) + ) + ) { + return null; + } + + const frameworkName = Object.entries(frameworkPackages).find( + ([name]) => name === getFrameworkPackageName(mainConfig) + )?.[1]; + + const builderPackageName = getBuilderPackageName(mainConfig); + const customCoreBuilder = builderPackageName + ? builderNameToCoreBuilder[builderPackageName] + : null; + + const defaultCoreBuilder = frameworkName + ? frameworkToDefaultBuilder[frameworkName] + : await (async () => { + const webpackVersion = await packageManager.getPackageVersion('webpack'); + return !!webpackVersion ? CoreBuilder.Webpack5 : CoreBuilder.Vite; + })(); + + const builder = customCoreBuilder || defaultCoreBuilder; + + if (builder !== CoreBuilder.Webpack5) { + return null; + } + + const excludedFrameworks: SupportedFrameworks[] = ['angular', 'ember']; + + const isExcludedFramework = frameworkName ? excludedFrameworks.includes(frameworkName) : false; + + if (isExcludedFramework) { + return null; + } + + const hasReactScriptsDependency = !!(await packageManager.getPackageVersion('react-scripts')); + + if (hasReactScriptsDependency) { + return null; + } + + const frameworkOptions = getFrameworkOptions(mainConfig); + + const defaultCompiler = frameworkOptions?.builder?.useSWC + ? CoreWebpackCompilers.SWC + : CoreWebpackCompilers.Babel; + + const shouldRemoveSWCFlag = frameworkOptions?.builder + ? 'useSWC' in frameworkOptions.builder + : false; + + if (frameworkName === 'nextjs') { + return { + compiler: undefined, + compilerPackageName: undefined, + shouldRemoveSWCFlag, + isNextJs: true, + }; + } + + return { + defaultCompiler, + shouldRemoveSWCFlag, + isNextJs: false, + }; + }, + + prompt({ defaultCompiler, shouldRemoveSWCFlag, isNextJs }) { + const message = []; + + if (shouldRemoveSWCFlag) { + message.push(dedent` + We need to update your Storybook configuration for Webpack 5. + The ${chalk.yellow('framework.options.builder.useSWC')} flag will be removed.`); + } + + if (isNextJs) { + message.push(dedent` + Storybook now detects whether it should use Babel or SWC as a compiler by applying the same logic as Next.js itself:\n + - If you have a ${chalk.yellow('.babelrc')} (or ${chalk.yellow( + 'babel.config.js' + )}) file in your project, Storybook will use Babel as the compiler. + - If you have a ${chalk.yellow('.babelrc')} (or ${chalk.yellow( + 'babel.config.js' + )}) file in your project and you have set + ${chalk.yellow('experimental.forceSwcTransforms = true')} in your ${chalk.yellow( + 'next.config.js' + )} file, + Storybook will use SWC as the compiler. + - If you don't have a ${chalk.yellow('.babelrc')} (or ${chalk.yellow( + 'babel.config.js' + )}) file in your project, Storybook will use SWC as the compiler. + `); + } else if (defaultCompiler === CoreWebpackCompilers.Babel) { + message.push(dedent` + Storybook's Webpack5 builder is now compiler agnostic, meaning you can choose a compiler addon that best fits your project:\n + - Babel: A vast ecosystem and is battle-tested. It's a robust choice if you have an extensive Babel setup or need specific Babel plugins for your project. + - SWC: Fast and easy to configure. Ideal if you want faster builds and have a straightforward configuration without the need for Babel's extensibility.\n + In the next step, Storybook will ask you to choose a compiler to automatically set it up for you.\n + After the migration, you can switch Webpack5 compilers by swapping the addon in your project. + You can find more information here: ${chalk.yellow( + 'https://storybook.js.org/docs/8.0/builders/webpack#compiler-support' + )} + `); + } else { + message.push(dedent` + Storybook's Webpack5 builder is now compiler agnostic, meaning you have to install an additional addon to set up a compiler for Webpack5.\n + We have detected, that you want to use SWC as the compiler for Webpack5.\n + In the next step, Storybook will install @storybook/addon-webpack5-compiler-swc and will add it to your addons list in your Storybook config.\n + After the migration, you can switch Webpack5 compilers by swapping the addon in your project. + You can find more information here: ${chalk.yellow( + 'https://storybook.js.org/docs/8.0/builders/webpack#compiler-support' + )} + `); + } + + return message.join('\n\n'); + }, + + async run({ result, mainConfigPath, packageManager, skipInstall, dryRun }) { + const { defaultCompiler, shouldRemoveSWCFlag, isNextJs } = result; + + if (shouldRemoveSWCFlag) { + await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, (main) => { + main.removeField(['framework', 'options', 'builder', 'useSWC']); + }); + } + + if (!isNextJs) { + const compiler: CoreWebpackCompilers = + defaultCompiler === CoreWebpackCompilers.Babel + ? await askUserForCompilerChoice() + : CoreWebpackCompilers.SWC; + + const compilerPackageName = Object.entries(compilerNameToCoreCompiler).find( + ([, coreCompiler]) => coreCompiler === compiler + )![0]; + + await add(compilerPackageName, { + packageManager: packageManager.type, + skipPostinstall: !!skipInstall, + }); + } + }, +} satisfies Fix; + +async function askUserForCompilerChoice() { + const response = await prompts<'compiler'>({ + type: 'select', + name: 'compiler', + message: `Which compiler would you like to use?`, + choices: [ + { + title: 'Babel', + description: 'Choose Babel for a vast ecosystem and battle-tested reliability.', + value: CoreWebpackCompilers.Babel, + }, + { + title: 'SWC', + description: 'Choose SWC for fast builds and simple configuration.', + value: CoreWebpackCompilers.SWC, + }, + ], + initial: 0, + }); + + return response.compiler as CoreWebpackCompilers; +} diff --git a/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts b/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts index c721dae39a31..2ba805c95614 100644 --- a/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts +++ b/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts @@ -42,11 +42,20 @@ export const getFrameworkPackageName = (mainConfig?: StorybookConfigRaw) => { * @returns - The package name of the builder. If not found, returns null. */ export const getBuilderPackageName = (mainConfig?: StorybookConfigRaw) => { - const packageNameOrPath = + const frameworkOptions = getFrameworkOptions(mainConfig); + + const frameworkBuilder = frameworkOptions?.builder; + + const frameworkBuilderName = + typeof frameworkBuilder === 'string' ? frameworkBuilder : frameworkBuilder?.options?.name; + + const coreBuilderName = typeof mainConfig?.core?.builder === 'string' ? mainConfig.core.builder : mainConfig?.core?.builder?.name; + const packageNameOrPath = coreBuilderName ?? frameworkBuilderName; + if (!packageNameOrPath) { return null; } @@ -56,6 +65,17 @@ export const getBuilderPackageName = (mainConfig?: StorybookConfigRaw) => { return builderPackages.find((pkg) => normalizedPath.endsWith(pkg)) || packageNameOrPath; }; +/** + * Given a Storybook configuration object, retrieves the configuration for the framework. + * @param mainConfig - The main Storybook configuration object to lookup. + * @returns - The configuration for the framework. If not found, returns null. + */ +export const getFrameworkOptions = ( + mainConfig?: StorybookConfigRaw +): Record | null => { + return typeof mainConfig?.framework === 'string' ? null : mainConfig?.framework?.options ?? null; +}; + /** * Returns a renderer package name given a framework package name. * @param frameworkPackageName - The package name of the framework to lookup. diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 19d4ee8922e9..1e78d57863ce 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -20,6 +20,7 @@ import type { FixSummary, PreCheckFailure, AutofixOptionsFromCLI, + Prompt, } from './fixes'; import { FixStatus, allFixes } from './fixes'; import { cleanLog } from './helpers/cleanLog'; @@ -217,15 +218,29 @@ export async function runFixes({ } if (result) { + const promptType: Prompt = + typeof f.promptType === 'function' ? await f.promptType(result) : f.promptType ?? 'auto'; + logger.info(`\n🔎 found a '${chalk.cyan(f.id)}' migration:`); const message = f.prompt(result); + const getTitle = () => { + switch (promptType) { + case 'auto': + return 'Automigration detected'; + case 'manual': + return 'Manual migration detected'; + case 'notification': + return 'Migration notification'; + } + }; + logger.info( boxen(message, { borderStyle: 'round', padding: 1, borderColor: '#F1618C', - title: f.promptOnly ? 'Manual migration detected' : 'Automigration detected', + title: getTitle(), }) ); @@ -236,11 +251,11 @@ export async function runFixes({ runAnswer = { fix: false }; } else if (yes) { runAnswer = { fix: true }; - if (f.promptOnly) { + if (promptType === 'manual') { fixResults[f.id] = FixStatus.MANUAL_SUCCEEDED; fixSummary.manual.push(f.id); } - } else if (f.promptOnly) { + } else if (promptType === 'manual') { fixResults[f.id] = FixStatus.MANUAL_SUCCEEDED; fixSummary.manual.push(f.id); @@ -266,7 +281,7 @@ export async function runFixes({ fixResults[f.id] = FixStatus.MANUAL_SKIPPED; break; } - } else { + } else if (promptType === 'auto') { runAnswer = await prompts( { type: 'confirm', @@ -280,12 +295,26 @@ export async function runFixes({ }, } ); + } else if (promptType === 'notification') { + runAnswer = await prompts( + { + type: 'confirm', + name: 'fix', + message: `Do you want to continue?`, + initial: true, + }, + { + onCancel: () => { + throw new Error(); + }, + } + ); } } catch (err) { break; } - if (!f.promptOnly) { + if (promptType === 'auto') { invariant(runAnswer, 'runAnswer must be defined if not promptOnly'); if (runAnswer.fix) { try { diff --git a/code/lib/cli/src/automigrate/types.ts b/code/lib/cli/src/automigrate/types.ts index 97d20c09dc45..510cdcda24c1 100644 --- a/code/lib/cli/src/automigrate/types.ts +++ b/code/lib/cli/src/automigrate/types.ts @@ -19,9 +19,17 @@ export interface RunOptions { skipInstall?: boolean; } +/** + * promptType defines how the user will be prompted to apply an automigration fix + * - auto: the fix will be applied automatically + * - manual: the user will be prompted to apply the fix + * - notification: the user will be notified about the some changes. A fix isn't required + */ +export type Prompt = 'auto' | 'manual' | 'notification'; + export interface Fix { id: string; - promptOnly?: boolean; + promptType?: Prompt | ((result: ResultType) => Promise | Prompt); check: (options: CheckOptions) => Promise; prompt: (result: ResultType) => string; run?: (options: RunOptions) => Promise; diff --git a/code/lib/cli/src/dirs.ts b/code/lib/cli/src/dirs.ts index 213b1877aaee..1f41620b4ea6 100644 --- a/code/lib/cli/src/dirs.ts +++ b/code/lib/cli/src/dirs.ts @@ -6,9 +6,10 @@ import * as tempy from 'tempy'; import invariant from 'tiny-invariant'; import { externalFrameworks } from './project_types'; -import type { SupportedFrameworks, SupportedRenderers } from './project_types'; +import type { SupportedRenderers } from './project_types'; import type { JsPackageManager } from '@storybook/core-common'; import { versions } from '@storybook/core-common'; +import type { SupportedFrameworks } from '@storybook/types'; export function getCliDir() { return dirname(require.resolve('@storybook/cli/package.json')); diff --git a/code/lib/cli/src/generate.ts b/code/lib/cli/src/generate.ts index 250cd200d206..b4e02c322b46 100644 --- a/code/lib/cli/src/generate.ts +++ b/code/lib/cli/src/generate.ts @@ -6,13 +6,19 @@ import { sync as readUpSync } from 'read-pkg-up'; import invariant from 'tiny-invariant'; import { logger } from '@storybook/node-logger'; -import { addToGlobalContext } from '@storybook/telemetry'; -import { parseList, getEnvConfig, JsPackageManagerFactory, versions } from '@storybook/core-common'; +import { addToGlobalContext, telemetry } from '@storybook/telemetry'; +import { + parseList, + getEnvConfig, + JsPackageManagerFactory, + versions, + removeAddon as remove, +} from '@storybook/core-common'; +import { withTelemetry } from '@storybook/core-server'; import type { CommandOptions } from './generators/types'; import { initiate } from './initiate'; import { add } from './add'; -import { removeAddon as remove } from '@storybook/core-common'; import { migrate } from './migrate'; import { upgrade, type UpgradeOptions } from './upgrade'; import { sandbox } from './sandbox'; @@ -71,7 +77,14 @@ command('remove ') '--package-manager ', 'Force package manager for installing dependencies' ) - .action((addonName: string, options: any) => remove(addonName, options)); + .action((addonName: string, options: any) => + withTelemetry('remove', { cliOptions: options }, async () => { + await remove(addonName, options); + if (!options.disableTelemetry) { + await telemetry('remove', { addon: addonName, source: 'cli' }); + } + }) + ); command('upgrade') .description(`Upgrade your Storybook packages to v${versions.storybook}`) diff --git a/code/lib/cli/src/generators/baseGenerator.ts b/code/lib/cli/src/generators/baseGenerator.ts index 3c3cae9e5e5e..2f85d0af4549 100644 --- a/code/lib/cli/src/generators/baseGenerator.ts +++ b/code/lib/cli/src/generators/baseGenerator.ts @@ -5,8 +5,9 @@ import ora from 'ora'; import invariant from 'tiny-invariant'; import type { JsPackageManager } from '@storybook/core-common'; import { getPackageDetails, versions as packageVersions } from '@storybook/core-common'; +import type { SupportedFrameworks } from '@storybook/types'; import type { NpmOptions } from '../NpmOptions'; -import type { SupportedRenderers, SupportedFrameworks, Builder } from '../project_types'; +import type { SupportedRenderers, Builder } from '../project_types'; import { SupportedLanguage, externalFrameworks } from '../project_types'; import { copyTemplateFiles } from '../helpers'; import { configureMain, configurePreview } from './configure'; diff --git a/code/lib/cli/src/helpers.ts b/code/lib/cli/src/helpers.ts index bbf81816a061..ed273831eefb 100644 --- a/code/lib/cli/src/helpers.ts +++ b/code/lib/cli/src/helpers.ts @@ -13,7 +13,9 @@ import type { PackageJson, PackageJsonWithDepsAndDevDeps, } from '@storybook/core-common'; -import type { SupportedFrameworks, SupportedRenderers } from './project_types'; +import type { SupportedFrameworks } from '@storybook/types'; +import type { SupportedRenderers } from './project_types'; +import { CoreBuilder } from './project_types'; import { SupportedLanguage } from './project_types'; import { versions as storybookMonorepoPackages } from '@storybook/core-common'; @@ -134,22 +136,59 @@ export const frameworkToRenderer: Record< SupportedFrameworks | SupportedRenderers, SupportedRenderers | 'vue' > = { + // frameworks angular: 'angular', ember: 'ember', - html: 'html', + 'html-vite': 'html', + 'html-webpack5': 'html', nextjs: 'react', - preact: 'preact', + 'preact-vite': 'preact', + 'preact-webpack5': 'preact', qwik: 'qwik', - react: 'react', - 'react-native': 'react', - server: 'react', + 'react-vite': 'react', + 'react-webpack5': 'react', + 'server-webpack5': 'server', solid: 'solid', - svelte: 'svelte', + 'svelte-vite': 'svelte', + 'svelte-webpack5': 'svelte', sveltekit: 'svelte', - vue3: 'vue', + 'vue3-vite': 'vue3', + 'vue3-webpack5': 'vue3', + 'web-components-vite': 'web-components', + 'web-components-webpack5': 'web-components', + // renderers + html: 'html', + preact: 'preact', + 'react-native': 'react-native', + react: 'react', + server: 'server', + svelte: 'svelte', + vue3: 'vue3', 'web-components': 'web-components', }; +export const frameworkToDefaultBuilder: Record = { + angular: CoreBuilder.Webpack5, + ember: CoreBuilder.Webpack5, + 'html-vite': CoreBuilder.Vite, + 'html-webpack5': CoreBuilder.Webpack5, + nextjs: CoreBuilder.Webpack5, + 'preact-vite': CoreBuilder.Vite, + 'preact-webpack5': CoreBuilder.Webpack5, + qwik: CoreBuilder.Vite, + 'react-vite': CoreBuilder.Vite, + 'react-webpack5': CoreBuilder.Webpack5, + 'server-webpack5': CoreBuilder.Webpack5, + solid: CoreBuilder.Vite, + 'svelte-vite': CoreBuilder.Vite, + 'svelte-webpack5': CoreBuilder.Webpack5, + sveltekit: CoreBuilder.Vite, + 'vue3-vite': CoreBuilder.Vite, + 'vue3-webpack5': CoreBuilder.Webpack5, + 'web-components-vite': CoreBuilder.Vite, + 'web-components-webpack5': CoreBuilder.Webpack5, +}; + export async function copyTemplateFiles({ packageManager, renderer, diff --git a/code/lib/cli/src/initiate.ts b/code/lib/cli/src/initiate.ts index 703002ec7cca..3d647f923a43 100644 --- a/code/lib/cli/src/initiate.ts +++ b/code/lib/cli/src/initiate.ts @@ -1,4 +1,6 @@ +import { appendFile, readFile } from 'fs/promises'; import type { PackageJson } from 'read-pkg-up'; +import findUp from 'find-up'; import chalk from 'chalk'; import prompts from 'prompts'; import { telemetry } from '@storybook/telemetry'; @@ -10,6 +12,7 @@ import { JsPackageManagerFactory, commandLog, paddedLog, + getProjectRoot, } from '@storybook/core-common'; import type { JsPackageManager } from '@storybook/core-common'; @@ -369,6 +372,15 @@ export async function doInitiate( return { shouldRunDev: false }; } + const foundGitIgnoreFile = await findUp('.gitignore'); + const rootDirectory = getProjectRoot(); + if (foundGitIgnoreFile && foundGitIgnoreFile.includes(rootDirectory)) { + const contents = await readFile(foundGitIgnoreFile, 'utf-8'); + if (!contents.includes('*storybook.log')) { + await appendFile(foundGitIgnoreFile, '\n*storybook.log'); + } + } + const storybookCommand = projectType === ProjectType.ANGULAR ? `ng run ${installResult.projectName}:storybook` diff --git a/code/lib/cli/src/project_types.ts b/code/lib/cli/src/project_types.ts index 0a0073d84664..3a5cda3781ef 100644 --- a/code/lib/cli/src/project_types.ts +++ b/code/lib/cli/src/project_types.ts @@ -1,4 +1,5 @@ import { minVersion, validRange } from 'semver'; +import type { SupportedFrameworks } from '@storybook/types'; function eqMajor(versionRange: string, major: number) { // Uses validRange to avoid a throw from minVersion if an invalid range gets passed @@ -21,9 +22,6 @@ export const externalFrameworks: ExternalFramework[] = [ { name: 'solid', frameworks: ['storybook-solidjs-vite'], renderer: 'storybook-solidjs' }, ]; -// Should match @storybook/ -export type SupportedFrameworks = 'nextjs' | 'angular' | 'sveltekit' | 'qwik' | 'solid' | 'ember'; - // Should match @storybook/ export type SupportedRenderers = | 'react' @@ -79,6 +77,21 @@ export enum CoreBuilder { Vite = 'vite', } +export enum CoreWebpackCompilers { + Babel = 'babel', + SWC = 'swc', +} + +export const compilerNameToCoreCompiler: Record = { + '@storybook/addon-webpack5-compiler-babel': CoreWebpackCompilers.Babel, + '@storybook/addon-webpack5-compiler-swc': CoreWebpackCompilers.SWC, +}; + +export const builderNameToCoreBuilder: Record = { + '@storybook/builder-webpack5': CoreBuilder.Webpack5, + '@storybook/builder-vite': CoreBuilder.Vite, +}; + // The `& {}` bit allows for auto-complete, see: https://github.com/microsoft/TypeScript/issues/29729 export type Builder = CoreBuilder | (string & {}); diff --git a/code/lib/cli/src/upgrade.ts b/code/lib/cli/src/upgrade.ts index e9f4a8151b1c..cb96bd797912 100644 --- a/code/lib/cli/src/upgrade.ts +++ b/code/lib/cli/src/upgrade.ts @@ -6,6 +6,7 @@ import { withTelemetry } from '@storybook/core-server'; import { UpgradeStorybookToLowerVersionError, UpgradeStorybookToSameVersionError, + UpgradeStorybookUnknownCurrentVersionError, } from '@storybook/core-events/server-errors'; import chalk from 'chalk'; @@ -22,7 +23,6 @@ import { } from '@storybook/core-common'; import { automigrate } from './automigrate/index'; import { autoblock } from './autoblock/index'; -import { PreCheckFailure } from './automigrate/types'; type Package = { package: string; @@ -189,26 +189,11 @@ export const doUpgrade = async ({ ); const configDir = userSpecifiedConfigDir || inferredConfigDir || '.storybook'; - let mainConfigLoadingError = ''; - - const mainConfig = await loadMainConfig({ configDir }).catch((err) => { - mainConfigLoadingError = String(err); - return false; - }); + const mainConfig = await loadMainConfig({ configDir }); // GUARDS if (!storybookVersion) { - logger.info(missingStorybookVersionMessage()); - results = { preCheckFailure: PreCheckFailure.UNDETECTED_SB_VERSION }; - } else if ( - typeof mainConfigPath === 'undefined' || - mainConfigLoadingError.includes('No configuration files have been found') - ) { - logger.info(mainjsNotFoundMessage(configDir)); - results = { preCheckFailure: PreCheckFailure.MAINJS_NOT_FOUND }; - } else if (typeof mainConfig === 'boolean') { - logger.info(mainjsExecutionFailureMessage(mainConfigPath, mainConfigLoadingError)); - results = { preCheckFailure: PreCheckFailure.MAINJS_EVALUATION }; + throw new UpgradeStorybookUnknownCurrentVersionError(); } // BLOCKERS @@ -293,32 +278,6 @@ export const doUpgrade = async ({ } }; -function missingStorybookVersionMessage(): string { - return dedent` - [Storybook automigrate] ❌ Unable to determine Storybook version so that the automigrations will be skipped. - 🤔 Are you running automigrate from your project directory? Please specify your Storybook config directory with the --config-dir flag. - `; -} - -function mainjsExecutionFailureMessage( - mainConfigPath: string, - mainConfigLoadingError: string -): string { - return dedent` - [Storybook automigrate] ❌ Failed trying to evaluate ${chalk.blue( - mainConfigPath - )} with the following error: ${mainConfigLoadingError} - - Please fix the error and try again. - `; -} - -function mainjsNotFoundMessage(configDir: string): string { - return dedent`[Storybook automigrate] Could not find or evaluate your Storybook main.js config directory at ${chalk.blue( - configDir - )} so the automigrations will be skipped. You might be running this command in a monorepo or a non-standard project structure. If that is the case, please rerun this command by specifying the path to your Storybook config directory via the --config-dir option.`; -} - export async function upgrade(options: UpgradeOptions): Promise { await withTelemetry('upgrade', { cliOptions: options }, () => doUpgrade(options)); } diff --git a/code/lib/client-logger/package.json b/code/lib/client-logger/package.json index d75bb42b8ab4..dc92a87c27ad 100644 --- a/code/lib/client-logger/package.json +++ b/code/lib/client-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/client-logger", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index 259aae0056a3..e4898dc76490 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/codemod", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "A collection of codemod scripts written with JSCodeshift", "keywords": [ "storybook" @@ -29,6 +29,7 @@ "./dist/transforms/add-component-parameters.js": "./dist/transforms/add-component-parameters.js", "./dist/transforms/csf-2-to-3.js": "./dist/transforms/csf-2-to-3.js", "./dist/transforms/csf-hoist-story-annotations.js": "./dist/transforms/csf-hoist-story-annotations.js", + "./dist/transforms/find-implicit-spies.js": "./dist/transforms/find-implicit-spies.js", "./dist/transforms/move-builtin-addons.js": "./dist/transforms/move-builtin-addons.js", "./dist/transforms/mdx-to-csf.js": "./dist/transforms/mdx-to-csf.js", "./dist/transforms/migrate-to-test-package.js": "./dist/transforms/migrate-to-test-package.js", @@ -93,6 +94,7 @@ "./src/transforms/add-component-parameters.js", "./src/transforms/csf-2-to-3.ts", "./src/transforms/csf-hoist-story-annotations.js", + "./src/transforms/find-implicit-spies.ts", "./src/transforms/mdx-to-csf.ts", "./src/transforms/migrate-to-test-package.ts", "./src/transforms/move-builtin-addons.js", diff --git a/code/lib/codemod/src/transforms/__tests__/find-implicit-spies.test.ts b/code/lib/codemod/src/transforms/__tests__/find-implicit-spies.test.ts new file mode 100644 index 000000000000..c3885605e8ed --- /dev/null +++ b/code/lib/codemod/src/transforms/__tests__/find-implicit-spies.test.ts @@ -0,0 +1,71 @@ +import { beforeEach, expect, test, vi } from 'vitest'; +import transform from '../find-implicit-spies'; +import dedent from 'ts-dedent'; +import ansiRegex from 'ansi-regex'; + +expect.addSnapshotSerializer({ + print: (val, print) => print((val as string).replace(ansiRegex(), '')), + test: (value) => typeof value === 'string' && ansiRegex().test(value), +}); + +const tsTransform = async (source: string) => transform({ source, path: 'Component.stories.tsx' }); + +const warn = vi.spyOn(console, 'warn'); + +beforeEach(() => { + warn.mockImplementation(() => {}); +}); + +test('Warn for possible implicit actions', async () => { + const input = dedent` + export default { title: 'foo/bar', args: {onClick: fn() }, argTypes: { onHover: {action: true} } }; + const Template = (args) => { }; + export const A = Template.bind({}); + A.args = { onBla: fn() }; + A.play = async ({ args }) => { + await userEvent.click(screen.getByRole("button")); + await expect(args.onImplicit).toHaveBeenCalled(); + await expect(args.onClick).toHaveBeenCalled(); + await expect(args.onHover).toHaveBeenCalled(); + await expect(args.onBla).toHaveBeenCalled(); + }; + + export const B = { + args: {onBla: fn() }, + play: async ({ args }) => { + await userEvent.click(screen.getByRole("button")); + await expect(args.onImplicit).toHaveBeenCalled(); + await expect(args.onClick).toHaveBeenCalled(); + await expect(args.onHover).toHaveBeenCalled(); + await expect(args.onBla).toHaveBeenCalled(); + } + }; + `; + + await tsTransform(input); + + expect(warn.mock.calls).toMatchInlineSnapshot(` + [ + [ + "Component.stories.tsx Possible implicit spy found + 5 | A.play = async ({ args }) => { + 6 | await userEvent.click(screen.getByRole("button")); + > 7 | await expect(args.onImplicit).toHaveBeenCalled(); + | ^^^^^^^^^^ + 8 | await expect(args.onClick).toHaveBeenCalled(); + 9 | await expect(args.onHover).toHaveBeenCalled(); + 10 | await expect(args.onBla).toHaveBeenCalled();", + ], + [ + "Component.stories.tsx Possible implicit spy found + 15 | play: async ({ args }) => { + 16 | await userEvent.click(screen.getByRole("button")); + > 17 | await expect(args.onImplicit).toHaveBeenCalled(); + | ^^^^^^^^^^ + 18 | await expect(args.onClick).toHaveBeenCalled(); + 19 | await expect(args.onHover).toHaveBeenCalled(); + 20 | await expect(args.onBla).toHaveBeenCalled();", + ], + ] + `); +}); diff --git a/code/lib/codemod/src/transforms/find-implicit-spies.ts b/code/lib/codemod/src/transforms/find-implicit-spies.ts new file mode 100644 index 000000000000..558cde383aa7 --- /dev/null +++ b/code/lib/codemod/src/transforms/find-implicit-spies.ts @@ -0,0 +1,144 @@ +/* eslint-disable no-underscore-dangle */ +import type { FileInfo } from 'jscodeshift'; +import { loadCsf } from '@storybook/csf-tools'; +import type { BabelFile } from '@babel/core'; +import * as babel from '@babel/core'; +import { isIdentifier, isObjectExpression, isObjectProperty } from '@babel/types'; + +function findImplicitSpies(path: babel.NodePath, file: string, keys: string[]) { + path.traverse({ + Identifier: (identifier) => { + if (!keys.includes(identifier.node.name) && /^on[A-Z].*/.test(identifier.node.name)) { + console.warn(identifier.buildCodeFrameError(`${file} Possible implicit spy found`).message); + } + }, + }); +} + +function getAnnotationKeys(file: BabelFile, storyName: string, annotationName: string) { + const argKeys: string[] = []; + + file.path.traverse({ + // CSF2 play function Story.args = + AssignmentExpression: (path) => { + const left = path.get('left'); + if (!left.isMemberExpression()) return; + const object = left.get('object'); + + if (!(object.isIdentifier() && object.node.name === storyName)) return; + + const property = left.get('property'); + const right = path.get('right'); + if ( + property.isIdentifier() && + property.node.name === annotationName && + right.isObjectExpression() + ) { + argKeys.push( + ...right.node.properties.flatMap((value) => + isObjectProperty(value) && isIdentifier(value.key) ? [value.key.name] : [] + ) + ); + } + }, + // CSF3 const Story = {args: () => {} }; + VariableDeclarator: (path) => { + const id = path.get('id'); + const init = path.get('init'); + if (!(id.isIdentifier() && id.node.name === storyName) || !init.isObjectExpression()) return; + + const args = init + .get('properties') + .flatMap((it) => (it.isObjectProperty() ? [it] : [])) + .find((it) => { + const argKey = it.get('key'); + return argKey.isIdentifier() && argKey.node.name === annotationName; + }); + + if (!args) return; + const argsValue = args.get('value'); + + if (!argsValue || !argsValue.isObjectExpression()) return; + argKeys.push( + ...argsValue.node.properties.flatMap((value) => + isObjectProperty(value) && isIdentifier(value.key) ? [value.key.name] : [] + ) + ); + }, + }); + + return argKeys; +} + +const getObjectExpressionKeys = (node: babel.Node | undefined) => { + return isObjectExpression(node) + ? node.properties.flatMap((value) => + isObjectProperty(value) && isIdentifier(value.key) ? [value.key.name] : [] + ) + : []; +}; + +export default async function transform(info: FileInfo) { + const csf = loadCsf(info.source, { makeTitle: (title) => title }); + const fileNode = csf._ast; + // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606 + const file: BabelFile = new babel.File( + { filename: info.path }, + { code: info.source, ast: fileNode } + ); + + csf.parse(); + + const metaKeys = [ + ...getObjectExpressionKeys(csf._metaAnnotations.args), + ...getObjectExpressionKeys(csf._metaAnnotations.argTypes), + ]; + + Object.entries(csf.stories).forEach(([key, { name }]) => { + if (!name) return; + const allKeys = [ + ...metaKeys, + ...getAnnotationKeys(file, name, 'args'), + ...getAnnotationKeys(file, name, 'argTypes'), + ]; + + file.path.traverse({ + // CSF2 play function Story.play = + AssignmentExpression: (path) => { + const left = path.get('left'); + if (!left.isMemberExpression()) return; + const object = left.get('object'); + + if (!(object.isIdentifier() && object.node.name === name)) return; + + const property = left.get('property'); + if (property.isIdentifier() && property.node.name === 'play') { + findImplicitSpies(path, info.path, allKeys); + } + }, + + // CSF3 play function: const Story = {play: () => {} }; + VariableDeclarator: (path) => { + const id = path.get('id'); + const init = path.get('init'); + if (!(id.isIdentifier() && id.node.name === name) || !init.isObjectExpression()) return; + + const play = init + .get('properties') + .flatMap((it) => (it.isObjectProperty() ? [it] : [])) + .find((it) => { + const argKey = it.get('key'); + return argKey.isIdentifier() && argKey.node.name === 'play'; + }); + + if (play) { + findImplicitSpies(play, info.path, allKeys); + } + }, + }); + }); + + return; +} + +export const parser = 'tsx'; diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json index 9a963332582d..983366675162 100644 --- a/code/lib/core-common/package.json +++ b/code/lib/core-common/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-common", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/core-common/src/utils/get-storybook-info.ts b/code/lib/core-common/src/utils/get-storybook-info.ts index acf5aae77b91..2c90d90fd674 100644 --- a/code/lib/core-common/src/utils/get-storybook-info.ts +++ b/code/lib/core-common/src/utils/get-storybook-info.ts @@ -1,6 +1,6 @@ import path from 'path'; import fse from 'fs-extra'; -import type { CoreCommon_StorybookInfo, PackageJson } from '@storybook/types'; +import type { CoreCommon_StorybookInfo, PackageJson, SupportedFrameworks } from '@storybook/types'; import { getStorybookConfiguration } from './get-storybook-configuration'; export const rendererPackages: Record = { @@ -25,7 +25,7 @@ export const rendererPackages: Record = { '@storybook/vue': 'vue', }; -export const frameworkPackages: Record = { +export const frameworkPackages: Record = { '@storybook/angular': 'angular', '@storybook/ember': 'ember', '@storybook/html-vite': 'html-vite', @@ -94,7 +94,7 @@ export const findConfigFile = (prefix: string, configDir: string) => { return extension ? `${filePrefix}.${extension}` : null; }; -const getConfigInfo = (packageJson: PackageJson, configDir?: string) => { +export const getConfigInfo = (packageJson: PackageJson, configDir?: string) => { let storybookConfigDir = configDir ?? '.storybook'; const storybookScript = packageJson.scripts?.['storybook']; if (storybookScript && !configDir) { diff --git a/code/lib/core-common/src/utils/load-main-config.ts b/code/lib/core-common/src/utils/load-main-config.ts index 492ede4f669d..b5001418597c 100644 --- a/code/lib/core-common/src/utils/load-main-config.ts +++ b/code/lib/core-common/src/utils/load-main-config.ts @@ -1,7 +1,12 @@ -import path from 'path'; +import path, { relative } from 'path'; import type { StorybookConfig } from '@storybook/types'; import { serverRequire, serverResolve } from './interpret-require'; import { validateConfigurationFiles } from './validate-configuration-files'; +import { readFile } from 'fs/promises'; +import { + MainFileESMOnlyImportError, + MainFileEvaluationError, +} from '@storybook/core-events/server-errors'; export async function loadMainConfig({ configDir = '.storybook', @@ -18,5 +23,40 @@ export async function loadMainConfig({ delete require.cache[mainJsPath]; } - return serverRequire(mainJsPath); + try { + const out = await serverRequire(mainJsPath); + return out; + } catch (e) { + if (!(e instanceof Error)) { + throw e; + } + if (e.message.match(/Cannot use import statement outside a module/)) { + const location = relative(process.cwd(), mainJsPath); + const numFromStack = e.stack?.match(new RegExp(`${location}:(\\d+):(\\d+)`))?.[1]; + let num; + let line; + + if (numFromStack) { + const contents = await readFile(mainJsPath, 'utf-8'); + const lines = contents.split('\n'); + num = parseInt(numFromStack, 10) - 1; + line = lines[num]; + } + + const out = new MainFileESMOnlyImportError({ + line, + location, + num, + }); + + delete out.stack; + + throw out; + } + + throw new MainFileEvaluationError({ + location: relative(process.cwd(), mainJsPath), + error: e, + }); + } } diff --git a/code/lib/core-common/src/utils/validate-configuration-files.ts b/code/lib/core-common/src/utils/validate-configuration-files.ts index 57e1cffeab79..0f7c1ecaaeb5 100644 --- a/code/lib/core-common/src/utils/validate-configuration-files.ts +++ b/code/lib/core-common/src/utils/validate-configuration-files.ts @@ -5,6 +5,7 @@ import slash from 'slash'; import { once } from '@storybook/node-logger'; import { boost } from './interpret-files'; +import { MainFileMissingError } from '@storybook/core-events/server-errors'; export async function validateConfigurationFiles(configDir: string) { const extensionsPattern = `{${Array.from(boost).join(',')}}`; @@ -20,9 +21,6 @@ export async function validateConfigurationFiles(configDir: string) { } if (!mainConfigPath) { - throw new Error(dedent` - No configuration files have been found in your configDir (${path.resolve(configDir)}). - Storybook needs "main.js" file, please add it (or pass a custom config dir flag to Storybook to tell where your main.js file is located at). - `); + throw new MainFileMissingError({ location: configDir }); } } diff --git a/code/lib/core-common/src/versions.ts b/code/lib/core-common/src/versions.ts index 28ddbab5e59a..011e54bc40c1 100644 --- a/code/lib/core-common/src/versions.ts +++ b/code/lib/core-common/src/versions.ts @@ -1,82 +1,82 @@ // auto generated file, do not edit export default { - '@storybook/addon-a11y': '8.0.0-beta.2', - '@storybook/addon-actions': '8.0.0-beta.2', - '@storybook/addon-backgrounds': '8.0.0-beta.2', - '@storybook/addon-controls': '8.0.0-beta.2', - '@storybook/addon-docs': '8.0.0-beta.2', - '@storybook/addon-essentials': '8.0.0-beta.2', - '@storybook/addon-highlight': '8.0.0-beta.2', - '@storybook/addon-interactions': '8.0.0-beta.2', - '@storybook/addon-jest': '8.0.0-beta.2', - '@storybook/addon-links': '8.0.0-beta.2', - '@storybook/addon-mdx-gfm': '8.0.0-beta.2', - '@storybook/addon-measure': '8.0.0-beta.2', - '@storybook/addon-outline': '8.0.0-beta.2', - '@storybook/addon-storysource': '8.0.0-beta.2', - '@storybook/addon-themes': '8.0.0-beta.2', - '@storybook/addon-toolbars': '8.0.0-beta.2', - '@storybook/addon-viewport': '8.0.0-beta.2', - '@storybook/angular': '8.0.0-beta.2', - '@storybook/blocks': '8.0.0-beta.2', - '@storybook/builder-manager': '8.0.0-beta.2', - '@storybook/builder-vite': '8.0.0-beta.2', - '@storybook/builder-webpack5': '8.0.0-beta.2', - '@storybook/channels': '8.0.0-beta.2', - '@storybook/cli': '8.0.0-beta.2', - '@storybook/client-logger': '8.0.0-beta.2', - '@storybook/codemod': '8.0.0-beta.2', - '@storybook/components': '8.0.0-beta.2', - '@storybook/core-common': '8.0.0-beta.2', - '@storybook/core-events': '8.0.0-beta.2', - '@storybook/core-server': '8.0.0-beta.2', - '@storybook/core-webpack': '8.0.0-beta.2', - '@storybook/csf-plugin': '8.0.0-beta.2', - '@storybook/csf-tools': '8.0.0-beta.2', - '@storybook/docs-tools': '8.0.0-beta.2', - '@storybook/ember': '8.0.0-beta.2', - '@storybook/html': '8.0.0-beta.2', - '@storybook/html-vite': '8.0.0-beta.2', - '@storybook/html-webpack5': '8.0.0-beta.2', - '@storybook/instrumenter': '8.0.0-beta.2', - '@storybook/manager': '8.0.0-beta.2', - '@storybook/manager-api': '8.0.0-beta.2', - '@storybook/nextjs': '8.0.0-beta.2', - '@storybook/node-logger': '8.0.0-beta.2', - '@storybook/preact': '8.0.0-beta.2', - '@storybook/preact-vite': '8.0.0-beta.2', - '@storybook/preact-webpack5': '8.0.0-beta.2', - '@storybook/preset-create-react-app': '8.0.0-beta.2', - '@storybook/preset-html-webpack': '8.0.0-beta.2', - '@storybook/preset-preact-webpack': '8.0.0-beta.2', - '@storybook/preset-react-webpack': '8.0.0-beta.2', - '@storybook/preset-server-webpack': '8.0.0-beta.2', - '@storybook/preset-svelte-webpack': '8.0.0-beta.2', - '@storybook/preset-vue3-webpack': '8.0.0-beta.2', - '@storybook/preview': '8.0.0-beta.2', - '@storybook/preview-api': '8.0.0-beta.2', - '@storybook/react': '8.0.0-beta.2', - '@storybook/react-dom-shim': '8.0.0-beta.2', - '@storybook/react-vite': '8.0.0-beta.2', - '@storybook/react-webpack5': '8.0.0-beta.2', - '@storybook/router': '8.0.0-beta.2', - '@storybook/server': '8.0.0-beta.2', - '@storybook/server-webpack5': '8.0.0-beta.2', - '@storybook/source-loader': '8.0.0-beta.2', - '@storybook/svelte': '8.0.0-beta.2', - '@storybook/svelte-vite': '8.0.0-beta.2', - '@storybook/svelte-webpack5': '8.0.0-beta.2', - '@storybook/sveltekit': '8.0.0-beta.2', - '@storybook/telemetry': '8.0.0-beta.2', - '@storybook/test': '8.0.0-beta.2', - '@storybook/theming': '8.0.0-beta.2', - '@storybook/types': '8.0.0-beta.2', - '@storybook/vue3': '8.0.0-beta.2', - '@storybook/vue3-vite': '8.0.0-beta.2', - '@storybook/vue3-webpack5': '8.0.0-beta.2', - '@storybook/web-components': '8.0.0-beta.2', - '@storybook/web-components-vite': '8.0.0-beta.2', - '@storybook/web-components-webpack5': '8.0.0-beta.2', - sb: '8.0.0-beta.2', - storybook: '8.0.0-beta.2', + '@storybook/addon-a11y': '8.0.0-beta.4', + '@storybook/addon-actions': '8.0.0-beta.4', + '@storybook/addon-backgrounds': '8.0.0-beta.4', + '@storybook/addon-controls': '8.0.0-beta.4', + '@storybook/addon-docs': '8.0.0-beta.4', + '@storybook/addon-essentials': '8.0.0-beta.4', + '@storybook/addon-highlight': '8.0.0-beta.4', + '@storybook/addon-interactions': '8.0.0-beta.4', + '@storybook/addon-jest': '8.0.0-beta.4', + '@storybook/addon-links': '8.0.0-beta.4', + '@storybook/addon-mdx-gfm': '8.0.0-beta.4', + '@storybook/addon-measure': '8.0.0-beta.4', + '@storybook/addon-outline': '8.0.0-beta.4', + '@storybook/addon-storysource': '8.0.0-beta.4', + '@storybook/addon-themes': '8.0.0-beta.4', + '@storybook/addon-toolbars': '8.0.0-beta.4', + '@storybook/addon-viewport': '8.0.0-beta.4', + '@storybook/angular': '8.0.0-beta.4', + '@storybook/blocks': '8.0.0-beta.4', + '@storybook/builder-manager': '8.0.0-beta.4', + '@storybook/builder-vite': '8.0.0-beta.4', + '@storybook/builder-webpack5': '8.0.0-beta.4', + '@storybook/channels': '8.0.0-beta.4', + '@storybook/cli': '8.0.0-beta.4', + '@storybook/client-logger': '8.0.0-beta.4', + '@storybook/codemod': '8.0.0-beta.4', + '@storybook/components': '8.0.0-beta.4', + '@storybook/core-common': '8.0.0-beta.4', + '@storybook/core-events': '8.0.0-beta.4', + '@storybook/core-server': '8.0.0-beta.4', + '@storybook/core-webpack': '8.0.0-beta.4', + '@storybook/csf-plugin': '8.0.0-beta.4', + '@storybook/csf-tools': '8.0.0-beta.4', + '@storybook/docs-tools': '8.0.0-beta.4', + '@storybook/ember': '8.0.0-beta.4', + '@storybook/html': '8.0.0-beta.4', + '@storybook/html-vite': '8.0.0-beta.4', + '@storybook/html-webpack5': '8.0.0-beta.4', + '@storybook/instrumenter': '8.0.0-beta.4', + '@storybook/manager': '8.0.0-beta.4', + '@storybook/manager-api': '8.0.0-beta.4', + '@storybook/nextjs': '8.0.0-beta.4', + '@storybook/node-logger': '8.0.0-beta.4', + '@storybook/preact': '8.0.0-beta.4', + '@storybook/preact-vite': '8.0.0-beta.4', + '@storybook/preact-webpack5': '8.0.0-beta.4', + '@storybook/preset-create-react-app': '8.0.0-beta.4', + '@storybook/preset-html-webpack': '8.0.0-beta.4', + '@storybook/preset-preact-webpack': '8.0.0-beta.4', + '@storybook/preset-react-webpack': '8.0.0-beta.4', + '@storybook/preset-server-webpack': '8.0.0-beta.4', + '@storybook/preset-svelte-webpack': '8.0.0-beta.4', + '@storybook/preset-vue3-webpack': '8.0.0-beta.4', + '@storybook/preview': '8.0.0-beta.4', + '@storybook/preview-api': '8.0.0-beta.4', + '@storybook/react': '8.0.0-beta.4', + '@storybook/react-dom-shim': '8.0.0-beta.4', + '@storybook/react-vite': '8.0.0-beta.4', + '@storybook/react-webpack5': '8.0.0-beta.4', + '@storybook/router': '8.0.0-beta.4', + '@storybook/server': '8.0.0-beta.4', + '@storybook/server-webpack5': '8.0.0-beta.4', + '@storybook/source-loader': '8.0.0-beta.4', + '@storybook/svelte': '8.0.0-beta.4', + '@storybook/svelte-vite': '8.0.0-beta.4', + '@storybook/svelte-webpack5': '8.0.0-beta.4', + '@storybook/sveltekit': '8.0.0-beta.4', + '@storybook/telemetry': '8.0.0-beta.4', + '@storybook/test': '8.0.0-beta.4', + '@storybook/theming': '8.0.0-beta.4', + '@storybook/types': '8.0.0-beta.4', + '@storybook/vue3': '8.0.0-beta.4', + '@storybook/vue3-vite': '8.0.0-beta.4', + '@storybook/vue3-webpack5': '8.0.0-beta.4', + '@storybook/web-components': '8.0.0-beta.4', + '@storybook/web-components-vite': '8.0.0-beta.4', + '@storybook/web-components-webpack5': '8.0.0-beta.4', + sb: '8.0.0-beta.4', + storybook: '8.0.0-beta.4', }; diff --git a/code/lib/core-events/package.json b/code/lib/core-events/package.json index e582c124ddd9..04b89085e701 100644 --- a/code/lib/core-events/package.json +++ b/code/lib/core-events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-events", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Event names used in storybook core", "keywords": [ "storybook" @@ -81,6 +81,7 @@ "ts-dedent": "^2.0.0" }, "devDependencies": { + "chalk": "^4.1.0", "typescript": "^5.3.2" }, "publishConfig": { diff --git a/code/lib/core-events/src/errors/server-errors.ts b/code/lib/core-events/src/errors/server-errors.ts index 2b522ad291f3..a9a9e758d70e 100644 --- a/code/lib/core-events/src/errors/server-errors.ts +++ b/code/lib/core-events/src/errors/server-errors.ts @@ -1,3 +1,4 @@ +import { bold, gray, grey, white, yellow, underline } from 'chalk'; import dedent from 'ts-dedent'; import { StorybookError } from './storybook-error'; @@ -394,6 +395,98 @@ export class NoMatchingExportError extends StorybookError { } } +export class MainFileESMOnlyImportError extends StorybookError { + readonly category = Category.CORE_SERVER; + + readonly code = 5; + + public documentation = + 'https://github.com/storybookjs/storybook/issues/23972#issuecomment-1948534058'; + + constructor( + public data: { location: string; line: string | undefined; num: number | undefined } + ) { + super(); + } + + template() { + const message = [ + `Storybook failed to load ${this.data.location}`, + '', + `It looks like the file tried to load/import an ESM only module.`, + `Support for this is currently limited in ${this.data.location}`, + `You can import ESM modules in your main file, but only as dynamic import.`, + '', + ]; + if (this.data.line) { + message.push( + white( + `In your ${yellow(this.data.location)} file, line ${bold.cyan( + this.data.num + )} threw an error:` + ), + grey(this.data.line) + ); + } + + message.push( + '', + white(`Convert the static import to a dynamic import ${underline('where they are used')}.`), + white(`Example:`) + ' ' + gray(`await import();`), + '' + ); + + return message.join('\n'); + } +} + +export class MainFileMissingError extends StorybookError { + readonly category = Category.CORE_SERVER; + + readonly code = 6; + + readonly stack = ''; + + public readonly documentation = 'https://storybook.js.org/docs/configure'; + + constructor(public data: { location: string }) { + super(); + } + + template() { + return dedent` + No configuration files have been found in your configDir: ${yellow(this.data.location)}. + Storybook needs a "main.js" file, please add it. + + You can pass a --config-dir flag to tell Storybook, where your main.js file is located at). + `; + } +} + +export class MainFileEvaluationError extends StorybookError { + readonly category = Category.CORE_SERVER; + + readonly code = 7; + + readonly stack = ''; + + constructor(public data: { location: string; error: Error }) { + super(); + } + + template() { + const errorText = white( + (this.data.error.stack || this.data.error.message).replaceAll(process.cwd(), '') + ); + + return dedent` + Storybook couldn't evaluate your ${yellow(this.data.location)} file. + + ${errorText} + `; + } +} + export class GenerateNewProjectOnInitError extends StorybookError { readonly category = Category.CLI_INIT; @@ -468,3 +561,18 @@ export class UpgradeStorybookToSameVersionError extends StorybookError { `; } } + +export class UpgradeStorybookUnknownCurrentVersionError extends StorybookError { + readonly category = Category.CLI_UPGRADE; + + readonly code = 5; + + template() { + return dedent` + We couldn't determine the current version of Storybook in your project. + + Are you running the Storybook CLI in a project without Storybook? + It might help if you specify your Storybook config directory with the --config-dir flag. + `; + } +} diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index 1d00fe7feb56..8acb9a7ec16d 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-server", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" @@ -56,6 +56,7 @@ }, "dependencies": { "@aw-web-design/x-default-browser": "1.4.126", + "@babel/core": "^7.23.9", "@discoveryjs/json-ext": "^0.5.3", "@storybook/builder-manager": "workspace:*", "@storybook/channels": "workspace:*", @@ -83,7 +84,7 @@ "express": "^4.17.3", "fs-extra": "^11.1.0", "globby": "^11.0.2", - "ip": "^2.0.0", + "ip": "^2.0.1", "lodash": "^4.17.21", "open": "^8.4.0", "pretty-hrtime": "^1.0.3", diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts index 67990ff2d430..582d2328086e 100644 --- a/code/lib/core-server/src/build-dev.ts +++ b/code/lib/core-server/src/build-dev.ts @@ -11,20 +11,21 @@ import { import prompts from 'prompts'; import invariant from 'tiny-invariant'; import { global } from '@storybook/global'; -import { telemetry, oneWayHash } from '@storybook/telemetry'; +import { oneWayHash, telemetry } from '@storybook/telemetry'; import { join, relative, resolve } from 'path'; import { deprecate } from '@storybook/node-logger'; -import dedent from 'ts-dedent'; +import { dedent } from 'ts-dedent'; import { readFile } from 'fs-extra'; import { MissingBuilderError } from '@storybook/core-events/server-errors'; import { storybookDevServer } from './dev-server'; import { outputStats } from './utils/output-stats'; import { outputStartupInformation } from './utils/output-startup-information'; import { updateCheck } from './utils/update-check'; -import { getServerPort, getServerChannelUrl } from './utils/server-address'; +import { getServerChannelUrl, getServerPort } from './utils/server-address'; import { getManagerBuilder, getPreviewBuilder } from './utils/get-builders'; import { warnOnIncompatibleAddons } from './utils/warnOnIncompatibleAddons'; +import { warnWhenUsingArgTypesRegex } from './utils/warnWhenUsingArgTypesRegex'; import { buildOrThrow } from './utils/build-or-throw'; export async function buildDevStandalone( @@ -93,6 +94,10 @@ export async function buildDevStandalone( console.warn('Storybook failed to check addon compatibility', e); } + try { + await warnWhenUsingArgTypesRegex(packageJson, configDir, config); + } catch (e) {} + // Load first pass: We need to determine the builder // We need to do this because builders might introduce 'overridePresets' which we need to take into account // We hope to remove this in SB8 diff --git a/code/lib/core-server/src/presets/common-preset.ts b/code/lib/core-server/src/presets/common-preset.ts index 4e0c183ea7c1..6dcd6366eff0 100644 --- a/code/lib/core-server/src/presets/common-preset.ts +++ b/code/lib/core-server/src/presets/common-preset.ts @@ -7,7 +7,7 @@ import { getPreviewBodyTemplate, getPreviewHeadTemplate, loadEnvs, - removeAddon, + removeAddon as removeAddonBase, } from '@storybook/core-common'; import type { CLIOptions, @@ -162,10 +162,16 @@ const optionalEnvToBoolean = (input: string | undefined): boolean | undefined => }; // eslint-disable-next-line @typescript-eslint/naming-convention -export const experimental_serverAPI = (extension: Record) => ({ - ...extension, - removeAddon, -}); +export const experimental_serverAPI = (extension: Record, options: Options) => { + let removeAddon = removeAddonBase; + if (!options.disableTelemetry) { + removeAddon = async (id: string, opts: any) => { + await telemetry('remove', { addon: id, source: 'api' }); + return removeAddonBase(id, opts); + }; + } + return { ...extension, removeAddon }; +}; /** * If for some reason this config is not applied, the reason is that diff --git a/code/lib/core-server/src/utils/warnWhenUsingArgTypesRegex.ts b/code/lib/core-server/src/utils/warnWhenUsingArgTypesRegex.ts new file mode 100644 index 000000000000..fa336373a8a4 --- /dev/null +++ b/code/lib/core-server/src/utils/warnWhenUsingArgTypesRegex.ts @@ -0,0 +1,56 @@ +import type { PackageJson, StorybookConfig } from '@storybook/types'; +import { getConfigInfo } from '@storybook/core-common'; +import { readFile } from 'fs-extra'; +import * as babel from '@babel/core'; +import type { BabelFile } from '@babel/core'; +import { babelParse } from '@storybook/csf-tools'; +import dedent from 'ts-dedent'; +import chalk from 'chalk'; + +export async function warnWhenUsingArgTypesRegex( + packageJson: PackageJson, + configDir: string, + config: StorybookConfig +) { + const { previewConfig } = getConfigInfo(packageJson, configDir); + const previewContent = previewConfig ? await readFile(previewConfig, 'utf8') : ''; + + const hasVisualTestAddon = + config?.addons?.some((it) => + typeof it === 'string' + ? it === '@chromatic-com/storybook' + : it.name === '@chromatic-com/storybook' + ) ?? false; + + if (hasVisualTestAddon && previewConfig && previewContent.includes('argTypesRegex')) { + // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606 + const file: BabelFile = new babel.File( + { filename: previewConfig }, + { code: previewContent, ast: babelParse(previewContent) } + ); + + file.path.traverse({ + Identifier: (path) => { + if (path.node.name === 'argTypesRegex') { + const message = dedent` + ${chalk.bold('Attention')}: We've detected that you're using ${chalk.cyan( + 'actions.argTypesRegex' + )} together with the visual test addon: + + ${path.buildCodeFrameError(previewConfig).message} + + We recommend removing the ${chalk.cyan( + 'argTypesRegex' + )} and assigning explicit action with the ${chalk.cyan( + 'fn' + )} function from ${chalk.cyan('@storybook/test')} instead: + https://storybook.js.org/docs/essentials/actions#via-storybooktest-fn-spy-function + + The build used by the addon for snapshot testing doesn't take the regex into account, which can cause hard to debug problems when a snapshot depends on the presence of action props. + `; + console.warn(message); + } + }, + }); + } +} diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index 29ed3fa3ac6f..e9d2232351e4 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-webpack", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json index 8fbe1df9e82a..ee8387cb21dd 100644 --- a/code/lib/csf-plugin/package.json +++ b/code/lib/csf-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-plugin", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Enrich CSF files via static analysis", "keywords": [ "storybook" diff --git a/code/lib/csf-tools/package.json b/code/lib/csf-tools/package.json index a34e88502aa8..4e1703cec773 100644 --- a/code/lib/csf-tools/package.json +++ b/code/lib/csf-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-tools", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Parse and manipulate CSF and Storybook config files", "keywords": [ "storybook" diff --git a/code/lib/docs-tools/package.json b/code/lib/docs-tools/package.json index 3db128a20be1..557c5a7c8e57 100644 --- a/code/lib/docs-tools/package.json +++ b/code/lib/docs-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/docs-tools", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Shared utility functions for frameworks to implement docs", "keywords": [ "storybook" diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json index d09086c92186..1e94deaef00b 100644 --- a/code/lib/instrumenter/package.json +++ b/code/lib/instrumenter/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/instrumenter", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 71713bc50a6a..3eeb6ea86ed8 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -432,7 +432,9 @@ export class Instrumenter { return { __element__: { prefix, localName, id, classNames, innerText } }; } if (typeof value === 'function') { - return { __function__: { name: value.name } }; + return { + __function__: { name: 'getMockName' in value ? value.getMockName() : value.name }, + }; } if (typeof value === 'symbol') { return { __symbol__: { description: value.description } }; diff --git a/code/lib/manager-api/package.json b/code/lib/manager-api/package.json index 8d8d7003ac71..261d5d5536d3 100644 --- a/code/lib/manager-api/package.json +++ b/code/lib/manager-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager-api", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Core Storybook Manager API & Context", "keywords": [ "storybook" diff --git a/code/lib/manager-api/src/version.ts b/code/lib/manager-api/src/version.ts index 2a37c88d9038..5fa094928cb2 100644 --- a/code/lib/manager-api/src/version.ts +++ b/code/lib/manager-api/src/version.ts @@ -1 +1 @@ -export const version = '8.0.0-beta.2'; +export const version = '8.0.0-beta.4'; diff --git a/code/lib/node-logger/package.json b/code/lib/node-logger/package.json index 32b27fc56792..8ec068205efc 100644 --- a/code/lib/node-logger/package.json +++ b/code/lib/node-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/node-logger", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" diff --git a/code/lib/preview-api/README-client-api.md b/code/lib/preview-api/README-client-api.md deleted file mode 100644 index c459b4c8d425..000000000000 --- a/code/lib/preview-api/README-client-api.md +++ /dev/null @@ -1,16 +0,0 @@ -# `@storybook/client-api` -- Deprecated Story APIs (`storiesOf`) - -**NOTE** This API is deprecated, and the CSF format is preferred for all stories. - -## `storiesOf` API - -The `@storybook/client` API provides the [`storiesOf()` API](./docs/storiesOf.md), which is proxied through to the CSF API. - -### Internals - -In order to appear to the store like the CSF API, a call to `storiesOf().add()` does the following: - -- Tracks the story added in a synthetic `StoryIndex` data structure -- Constructs a `moduleExports` object that is equivalent to the exports from a CSF file that produced the same stories. - -In order to achieve the old `storySort` functionality, the client API also needs access to the project annotations. diff --git a/code/lib/preview-api/README.md b/code/lib/preview-api/README.md index 864bbbb11e7f..cb5788bbb0f4 100644 --- a/code/lib/preview-api/README.md +++ b/code/lib/preview-api/README.md @@ -7,7 +7,6 @@ TODO write proper documentation of this package This package used to be multiple packages (they have been combined into this one): - `@storybook/addons` [read (old) docs](./README-addons.md) -- `@storybook/client-api` [read (old) docs](./README-client-api.md) - `@storybook/core-client` [read (old) docs](./README-core-client.md) - `@storybook/preview-web` [read (old) docs](./README-preview-web.md) - `@storybook/store` [read (old) docs](./README-store.md) diff --git a/code/lib/preview-api/docs/storiesOf.md b/code/lib/preview-api/docs/storiesOf.md deleted file mode 100644 index 08e7009a9d0d..000000000000 --- a/code/lib/preview-api/docs/storiesOf.md +++ /dev/null @@ -1,97 +0,0 @@ -## storiesOf (Legacy) API - -`storiesOf` is Storybook's Legacy API for adding stories. Up until Storybook 5.2, it has been the primary way to create stories in Storybook. - -In Storybook 5.2 we introduced a simpler and more portable [Component Story Format](https://storybook.js.org/docs/react/api/csf), and all future tools and infrastructure will be oriented towards CSF. Therefore, we recommend migrating your stories out of `storiesOf` API, and even provide [automated tools to do this](#component-story-format-migration). - -That said, the `storiesOf` API is no longer actively maintained and has been removed as part of the Storybook 8 release. If you're working with a custom indexer or similar tooling that implements this API, we encourage using custom story indexers instead. Read our [Indexer API documentation](https://storybook.js.org/docs/api/main-config-indexers) for more information. - -## storiesOf API - -A Storybook is a collection of stories. Each story represents a single visual state of a component. - -Here's a basic story file in the `storiesOf` API: - -```js -import React from 'react'; -import { storiesOf } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; -import Button from '../components/Button'; - -storiesOf('Button', module) - .add('with text', () => ) - .add('with some emoji', () => ( - - )); -``` - -The string argument to `storiesOf` is the component title. If you pass a string like `'Widgets|Button/Button'` it can also be used to position your component's story within Storybook's story hierarchy. - -The second argument of `storiesOf` is a webpack `module`, which is available on the global (per-file) scope. Storybook needs it to enable hot-module-replacement. If it's not included you'll need to refresh your browser with each change you make. - -Each `.add` call takes a story name, a story function that returns a renderable object (JSX in the case of React), and optionally some parameters, which are described below. - -## Decorators and parameters - -[Decorators](https://storybook.js.org/docs/react/writing-stories/decorators) and [parameters](https://storybook.js.org/docs/react/writing-stories/parameters) can be specified globally, at the component level, or locally at the story level. - -In the `storiesOf` API, story-level parameters are provided as a third argument to `.add`: - -```js -storiesOf('Button', module).add( - 'with text', - () => , - { notes: someNotes } -); -``` - -Story-level decorators are provided via parameters: - -```js -storiesOf('Button', module).add( - 'with text', - () => , - { decorators: [withKnobs] } -); -``` - -We can control how the component's stories will render with parameters and decorators. You can use as many `.addDecorators` as you need (but make sure you add them all before your first story), but you can only use one `.addParameters`, as you can see in the example below: - -```js -storiesOf('Button', module) - .addParameters({ backgrounds: { values: [{ name: 'red', value: '#f00' }] } }) - .addDecorator((Story) => ( -
- -
- )) - .addDecorator((Story) => ( -
- -
- )) - .add('with text', () => ) - .add('with some emoji', () => ( - - )); -``` - -Parameters and decorators can also be used globally, you can define them in your .storybook/preview.js. Take a look [here](https://storybook.js.org/docs/react/writing-stories/parameters#global-parameters) to learn more about global parameters and [here](https://storybook.js.org/docs/react/writing-stories/decorators#global-decorators) for global decorators. - -## Component Story Format migration - -To make it easier to adopt the new [Component Story Format (CSF)](https://storybook.js.org/docs/react/api/csf), we've created an automatic migration tool to transform `storiesOf` API to Module format. - -```sh -sb migrate storiesof-to-csf --glob=src/**/*.stories.js -``` - -For more information, see the CLI's [Codemod README](https://github.com/storybookjs/storybook/tree/next/code/lib/codemod). diff --git a/code/lib/preview-api/package.json b/code/lib/preview-api/package.json index 4fd21320cb69..8cd4208ad007 100644 --- a/code/lib/preview-api/package.json +++ b/code/lib/preview-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview-api", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" diff --git a/code/lib/preview-api/src/modules/preview-web/render/StoryRender.test.ts b/code/lib/preview-api/src/modules/preview-web/render/StoryRender.test.ts index 73845a00348d..df4b37b840ae 100644 --- a/code/lib/preview-api/src/modules/preview-web/render/StoryRender.test.ts +++ b/code/lib/preview-api/src/modules/preview-web/render/StoryRender.test.ts @@ -1,3 +1,4 @@ +// @vitest-environment jsdom import { describe, it, expect, vi } from 'vitest'; import { Channel } from '@storybook/channels'; import type { Renderer, StoryIndexEntry } from '@storybook/types'; diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts index 2ad7f7500f5b..af775f27360b 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts @@ -1,3 +1,4 @@ +// @vitest-environment node import { describe, expect, vi, it } from 'vitest'; import { composeStory, composeStories } from './portable-stories'; diff --git a/code/lib/preview-api/vitest.config.ts b/code/lib/preview-api/vitest.config.ts index 622642938f21..ddec70e554d4 100644 --- a/code/lib/preview-api/vitest.config.ts +++ b/code/lib/preview-api/vitest.config.ts @@ -6,7 +6,7 @@ export default mergeConfig( vitestCommonConfig, defineConfig({ test: { - environment: 'jsdom', + environment: 'node', name: __dirname.split(sep).slice(-2).join(posix.sep), }, }) diff --git a/code/lib/preview/package.json b/code/lib/preview/package.json index 6d8eb3ddf8b1..cb3b76862c82 100644 --- a/code/lib/preview/package.json +++ b/code/lib/preview/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" diff --git a/code/lib/react-dom-shim/package.json b/code/lib/react-dom-shim/package.json index 2eff5f1f9b77..a3d8d360788c 100644 --- a/code/lib/react-dom-shim/package.json +++ b/code/lib/react-dom-shim/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-dom-shim", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" diff --git a/code/lib/router/package.json b/code/lib/router/package.json index 926d45aa0ef5..903bb8763982 100644 --- a/code/lib/router/package.json +++ b/code/lib/router/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/router", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Core Storybook Router", "keywords": [ "storybook" diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index 978970834cc1..35a82147aaf1 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/source-loader", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Source loader", "keywords": [ "lib", diff --git a/code/lib/telemetry/package.json b/code/lib/telemetry/package.json index 6792a8b06d75..f05f4467dce3 100644 --- a/code/lib/telemetry/package.json +++ b/code/lib/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/telemetry", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Telemetry logging for crash reports and usage statistics", "keywords": [ "storybook" diff --git a/code/lib/telemetry/src/types.ts b/code/lib/telemetry/src/types.ts index 8f091703bcae..846e7adb9556 100644 --- a/code/lib/telemetry/src/types.ts +++ b/code/lib/telemetry/src/types.ts @@ -15,7 +15,8 @@ export type EventType = | 'error' | 'error-metadata' | 'version-update' - | 'core-config'; + | 'core-config' + | 'remove'; export interface Dependency { version: string | undefined; diff --git a/code/lib/test/package.json b/code/lib/test/package.json index e50699b89c0b..fbd8b21509c9 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/test", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "", "keywords": [ "storybook" @@ -49,7 +49,7 @@ "@storybook/preview-api": "workspace:*", "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^6.4.0", - "@testing-library/user-event": "14.3.0", + "@testing-library/user-event": "^14.5.2", "@vitest/expect": "1.1.3", "@vitest/spy": "^1.1.3", "chai": "^4.3.7", diff --git a/code/lib/theming/package.json b/code/lib/theming/package.json index 0f5d3d6289be..4a47bd2bd25e 100644 --- a/code/lib/theming/package.json +++ b/code/lib/theming/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/theming", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/lib/types/package.json b/code/lib/types/package.json index 1849c1a5b2c1..fee0ab7fbddf 100644 --- a/code/lib/types/package.json +++ b/code/lib/types/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/types", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Core Storybook TS Types", "keywords": [ "storybook" @@ -58,6 +58,7 @@ "access": "public" }, "bundler": { + "pre": "./scripts/generate-available-frameworks.js", "entries": [ "./src/index.ts" ] diff --git a/code/lib/types/scripts/generate-available-frameworks.js b/code/lib/types/scripts/generate-available-frameworks.js new file mode 100644 index 000000000000..dced66c06707 --- /dev/null +++ b/code/lib/types/scripts/generate-available-frameworks.js @@ -0,0 +1,35 @@ +// read ./code/frameworks subfolders and generate a list of available frameworks +// save this list into ./code/lib/cli/src/frameworks.ts and export it as a union type. The name of the type is `SupportedFrameworks`. Add additionally 'qwik' and `solid` to that list. + +import { readdir, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import prettier from 'prettier'; +import dedent from 'ts-dedent'; + +const thirdPartyFrameworks = ['qwik', 'solid']; + +const run = async () => { + const frameworks = await readdir(path.join(__dirname, '..', '..', '..', 'frameworks')); + const supportedFrameworks = frameworks.map((framework) => `'${framework}'`).join(' | '); + const fileContent = dedent` + // auto generated file, do not edit + // the file gets generated by the script ./code/lib/types/scripts/generate-available-frameworks.js + export type SupportedFrameworks = ${supportedFrameworks} | ${thirdPartyFrameworks + .map((framework) => `'${framework}'`) + .join(' | ')}; +`; + const frameworksFile = path.join(__dirname, '..', 'src', 'modules', 'frameworks.ts'); + const prettierConfig = await prettier.resolveConfig(frameworksFile); + + const formattedFileContent = await prettier.format(fileContent, { + ...prettierConfig, + parser: 'typescript', + }); + + await writeFile(frameworksFile, formattedFileContent); +}; + +run().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/code/lib/types/src/index.ts b/code/lib/types/src/index.ts index 756b3d2634cb..0eb7547ccb6b 100644 --- a/code/lib/types/src/index.ts +++ b/code/lib/types/src/index.ts @@ -10,3 +10,4 @@ export * from './modules/api-stories'; export * from './modules/indexer'; export * from './modules/composedStory'; export * from './modules/channelApi'; +export * from './modules/frameworks'; diff --git a/code/lib/types/src/modules/core-common.ts b/code/lib/types/src/modules/core-common.ts index 7a6bd8a99699..380508211121 100644 --- a/code/lib/types/src/modules/core-common.ts +++ b/code/lib/types/src/modules/core-common.ts @@ -355,11 +355,6 @@ export interface StorybookConfigRaw { */ argTypeTargetsV7?: boolean; - /** - * Use legacy MDX1, to help smooth migration to 7.0 - */ - legacyMdx1?: boolean; - /** * Apply decorators from preview.js before decorators from addons or frameworks */ diff --git a/code/lib/types/src/modules/frameworks.ts b/code/lib/types/src/modules/frameworks.ts new file mode 100644 index 000000000000..c1ea25abe7b0 --- /dev/null +++ b/code/lib/types/src/modules/frameworks.ts @@ -0,0 +1,22 @@ +// auto generated file, do not edit +// the file gets generated by the script ./code/lib/types/scripts/generate-available-frameworks.js +export type SupportedFrameworks = + | 'angular' + | 'ember' + | 'html-vite' + | 'html-webpack5' + | 'nextjs' + | 'preact-vite' + | 'preact-webpack5' + | 'react-vite' + | 'react-webpack5' + | 'server-webpack5' + | 'svelte-vite' + | 'svelte-webpack5' + | 'sveltekit' + | 'vue3-vite' + | 'vue3-webpack5' + | 'web-components-vite' + | 'web-components-webpack5' + | 'qwik' + | 'solid'; diff --git a/code/package.json b/code/package.json index ae2ef37fd85a..1d6e075439ea 100644 --- a/code/package.json +++ b/code/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/root", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "private": true, "description": "Storybook root", "homepage": "https://storybook.js.org/", @@ -194,7 +194,7 @@ "eslint": "^8.56.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-local-rules": "portal:../scripts/eslint-plugin-local-rules", - "eslint-plugin-storybook": "^0.6.15", + "eslint-plugin-storybook": "^0.8.0", "fs-extra": "^11.1.0", "github-release-from-changelog": "^2.1.1", "glob": "^10.0.0", diff --git a/code/presets/create-react-app/package.json b/code/presets/create-react-app/package.json index 888077e98cd5..ae34d5d15e9d 100644 --- a/code/presets/create-react-app/package.json +++ b/code/presets/create-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-create-react-app", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Create React App preset", "keywords": [ "storybook" diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json index 5ed62bbe8a09..00aa92b4086f 100644 --- a/code/presets/html-webpack/package.json +++ b/code/presets/html-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-html-webpack", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json index 9bf4e57057b3..387c187b3ec6 100644 --- a/code/presets/preact-webpack/package.json +++ b/code/presets/preact-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-preact-webpack", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index 1178459c5875..07cbf84d2f6c 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-react-webpack", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading", "keywords": [ "storybook" diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json index 429a852c91aa..ec4df0997e9c 100644 --- a/code/presets/server-webpack/package.json +++ b/code/presets/server-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-server-webpack", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index 06dc39cc959e..008078d8721c 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-svelte-webpack", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json index 1ee320a0a21f..e10eb25c1991 100644 --- a/code/presets/vue3-webpack/package.json +++ b/code/presets/vue3-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-vue3-webpack", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json index 21989c8648d9..d3592cd30c09 100644 --- a/code/renderers/html/package.json +++ b/code/renderers/html/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook HTML renderer", "keywords": [ "storybook" diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index 4b22d0909b43..374873be5692 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook Preact renderer", "keywords": [ "storybook" diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index 1aab923414bf..f4239531cb51 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook React renderer", "keywords": [ "storybook" diff --git a/code/renderers/server/package.json b/code/renderers/server/package.json index 5cca1880cb39..911edce348b9 100644 --- a/code/renderers/server/package.json +++ b/code/renderers/server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook Server renderer", "keywords": [ "storybook" diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index e1eb7d92163d..d7efba34d699 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook Svelte renderer", "keywords": [ "storybook" diff --git a/code/renderers/svelte/src/public-types.test.ts b/code/renderers/svelte/src/public-types.test.ts index 54773fe2de91..42e43bcb9111 100644 --- a/code/renderers/svelte/src/public-types.test.ts +++ b/code/renderers/svelte/src/public-types.test.ts @@ -3,7 +3,7 @@ import { describe, it } from 'vitest'; import { satisfies } from '@storybook/core-common'; import type { ComponentAnnotations, StoryAnnotations } from '@storybook/types'; import { expectTypeOf } from 'expect-type'; -import type { ComponentProps, SvelteComponentTyped } from 'svelte'; +import type { ComponentProps, SvelteComponent } from 'svelte'; import Button from './__test__/Button.svelte'; import Decorator1 from './__test__/Decorator.svelte'; import Decorator2 from './__test__/Decorator2.svelte'; @@ -11,7 +11,7 @@ import Decorator2 from './__test__/Decorator2.svelte'; import type { Decorator, Meta, StoryObj } from './public-types'; import type { SvelteRenderer } from './types'; -type SvelteStory = StoryAnnotations< +type SvelteStory = StoryAnnotations< SvelteRenderer, Args, RequiredArgs diff --git a/code/renderers/svelte/src/public-types.ts b/code/renderers/svelte/src/public-types.ts index ac03670f698a..54ba3e28e466 100644 --- a/code/renderers/svelte/src/public-types.ts +++ b/code/renderers/svelte/src/public-types.ts @@ -12,7 +12,7 @@ import type { ProjectAnnotations, } from '@storybook/types'; -import type { ComponentType, ComponentProps, SvelteComponentTyped } from 'svelte'; +import type { ComponentType, ComponentProps, SvelteComponent } from 'svelte'; import type { SetOptional, Simplify } from 'type-fest'; import type { SvelteRenderer } from './types'; @@ -23,7 +23,7 @@ export type { Args, ArgTypes, Parameters, StrictArgs } from '@storybook/types'; * * @see [Default export](https://storybook.js.org/docs/formats/component-story-format/#default-export) */ -export type Meta = CmpOrArgs extends SvelteComponentTyped +export type Meta = CmpOrArgs extends SvelteComponent ? ComponentAnnotations, Props> : ComponentAnnotations; /** @@ -31,7 +31,7 @@ export type Meta = CmpOrArgs extends SvelteComponentTyped = TCmpOrArgs extends SvelteComponentTyped +export type StoryFn = TCmpOrArgs extends SvelteComponent ? AnnotatedStoryFn : AnnotatedStoryFn; @@ -54,7 +54,7 @@ export type StoryObj = MetaOrCmpOrArgs extends { SetOptional> > : never - : MetaOrCmpOrArgs extends SvelteComponentTyped + : MetaOrCmpOrArgs extends SvelteComponent ? StoryAnnotations, ComponentProps> : StoryAnnotations; diff --git a/code/renderers/svelte/src/types.ts b/code/renderers/svelte/src/types.ts index 43d42e010677..3bbc8e2e7878 100644 --- a/code/renderers/svelte/src/types.ts +++ b/code/renderers/svelte/src/types.ts @@ -1,5 +1,5 @@ import type { StoryContext as StoryContextBase, WebRenderer } from '@storybook/types'; -import type { ComponentConstructorOptions, ComponentEvents, SvelteComponentTyped } from 'svelte'; +import type { ComponentConstructorOptions, ComponentEvents, SvelteComponent } from 'svelte'; export type StoryContext = StoryContextBase; @@ -26,13 +26,13 @@ type ComponentType< Props extends Record = any, Events extends Record = any, > = new (options: ComponentConstructorOptions) => { - [P in keyof SvelteComponentTyped as P extends `$$${string}` - ? never - : P]: SvelteComponentTyped[P]; + [P in keyof SvelteComponent as P extends `$$${string}` ? never : P]: SvelteComponent< + Props, + Events + >[P]; }; -export interface SvelteRenderer - extends WebRenderer { +export interface SvelteRenderer extends WebRenderer { component: ComponentType ? this['T'] : any>; storyResult: this['T'] extends Record ? SvelteStoryResult> diff --git a/code/renderers/vue3/package.json b/code/renderers/vue3/package.json index 1803817d1357..18d032af1bce 100644 --- a/code/renderers/vue3/package.json +++ b/code/renderers/vue3/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook Vue 3 renderer", "keywords": [ "storybook" diff --git a/code/renderers/web-components/package.json b/code/renderers/web-components/package.json index ff50940d4c28..7e7c724f6d40 100644 --- a/code/renderers/web-components/package.json +++ b/code/renderers/web-components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook web-components renderer", "keywords": [ "lit", diff --git a/code/ui/blocks/package.json b/code/ui/blocks/package.json index 0369a178e992..3a29e0ed9ded 100644 --- a/code/ui/blocks/package.json +++ b/code/ui/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Storybook Doc Blocks", "keywords": [ "storybook" diff --git a/code/ui/blocks/src/components/TableOfContents.tsx b/code/ui/blocks/src/components/TableOfContents.tsx index 479f589411e4..b3b2e7b1f4a3 100644 --- a/code/ui/blocks/src/components/TableOfContents.tsx +++ b/code/ui/blocks/src/components/TableOfContents.tsx @@ -142,14 +142,13 @@ export const TableOfContents = ({ tocSelector: '.toc-wrapper', contentSelector: contentsSelector ?? '.sbdocs-content', headingSelector: headingSelector ?? 'h3', - ignoreSelector: ignoreSelector ?? '.skip-toc', - headingsOffset: 40, - scrollSmoothOffset: -40, /** * Ignore headings that did not * come from the main markdown code. */ - // ignoreSelector: ':not(.sbdocs), .hide-from-toc', + ignoreSelector: ignoreSelector ?? '.docs-story *, .skip-toc', + headingsOffset: 40, + scrollSmoothOffset: -40, orderedList: false, /** * Prevent default linking behavior, diff --git a/code/ui/components/package.json b/code/ui/components/package.json index a02aa17fbc32..3a8eefd42741 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/components", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/ui/manager/package.json b/code/ui/manager/package.json index b4046fecbf0f..48cb90b99e2e 100644 --- a/code/ui/manager/package.json +++ b/code/ui/manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager", - "version": "8.0.0-beta.2", + "version": "8.0.0-beta.4", "description": "Core Storybook UI", "keywords": [ "storybook" diff --git a/code/vitest.workspace.ts b/code/vitest.workspace.ts index f09d1adbfd44..9adcc717f753 100644 --- a/code/vitest.workspace.ts +++ b/code/vitest.workspace.ts @@ -25,7 +25,7 @@ const threadCount = process.env.CI ? 8 : undefined; export const vitestCommonConfig = defineConfig({ test: { clearMocks: true, - setupFiles: [resolve('./vitest-setup.ts')], + setupFiles: [resolve(__dirname, './vitest-setup.ts')], globals: true, poolOptions: { threads: { diff --git a/code/yarn.lock b/code/yarn.lock index 755a51216c17..07c7d2bd6b0e 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -467,6 +467,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/core@npm:7.23.9" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.6" + "@babel/helper-compilation-targets": "npm:^7.23.6" + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 03883300bf1252ab4c9ba5b52f161232dd52873dbe5cde9289bb2bb26e935c42682493acbac9194a59a3b6cbd17f4c4c84030db8d6d482588afe64531532ff9b + languageName: node + linkType: hard + "@babel/generator@npm:7.23.0": version: 7.23.0 resolution: "@babel/generator@npm:7.23.0" @@ -740,6 +763,17 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/helpers@npm:7.23.9" + dependencies: + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: f69fd0aca96a6fb8bd6dd044cd8a5c0f1851072d4ce23355345b9493c4032e76d1217f86b70df795e127553cf7f3fcd1587ede9d1b03b95e8b62681ca2165b87 + languageName: node + linkType: hard + "@babel/highlight@npm:^7.23.4": version: 7.23.4 resolution: "@babel/highlight@npm:7.23.4" @@ -760,6 +794,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/parser@npm:7.23.9" + bin: + parser: ./bin/babel-parser.js + checksum: 7df97386431366d4810538db4b9ec538f4377096f720c0591c7587a16f6810e62747e9fbbfa1ff99257fd4330035e4fb1b5b77c7bd3b97ce0d2e3780a6618975 + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.15, @babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.23.3": version: 7.23.3 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.23.3" @@ -2220,6 +2263,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/template@npm:7.23.9" + dependencies: + "@babel/code-frame": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: 0e8b60119433787742bc08ae762bbd8d6755611c4cabbcb7627b292ec901a55af65d93d1c88572326069efb64136ef151ec91ffb74b2df7689bbab237030833a + languageName: node + linkType: hard + "@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.7, @babel/traverse@npm:^7.4.5": version: 7.23.7 resolution: "@babel/traverse@npm:7.23.7" @@ -2238,6 +2292,24 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/traverse@npm:7.23.9" + dependencies: + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.6" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-hoist-variables": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + debug: "npm:^4.3.1" + globals: "npm:^11.1.0" + checksum: d1615d1d02f04d47111a7ea4446a1a6275668ca39082f31d51f08380de9502e19862be434eaa34b022ce9a17dbb8f9e2b73a746c654d9575f3a680a7ffdf5630 + languageName: node + linkType: hard + "@babel/types@npm:^7.0.0, @babel/types@npm:^7.11.5, @babel/types@npm:^7.18.9, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.4, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.6, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.6.1, @babel/types@npm:^7.7.2, @babel/types@npm:^7.8.3, @babel/types@npm:^7.9.6": version: 7.23.6 resolution: "@babel/types@npm:7.23.6" @@ -2249,6 +2321,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/types@npm:7.23.9" + dependencies: + "@babel/helper-string-parser": "npm:^7.23.4" + "@babel/helper-validator-identifier": "npm:^7.22.20" + to-fast-properties: "npm:^2.0.0" + checksum: edc7bb180ce7e4d2aea10c6972fb10474341ac39ba8fdc4a27ffb328368dfdfbf40fca18e441bbe7c483774500d5c05e222cec276c242e952853dcaf4eb884f7 + languageName: node + linkType: hard + "@base2/pretty-print-object@npm:1.0.1": version: 1.0.1 resolution: "@base2/pretty-print-object@npm:1.0.1" @@ -3658,72 +3741,72 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:14.0.4": - version: 14.0.4 - resolution: "@next/env@npm:14.0.4" - checksum: 59b893d30aea0556379a24f6e4eac830677feb149bd8416b72383ea2600ce194fa22a79b2dd86e0b295c4a8f0702e461f48edaff1ac9173eddef42a4cce7fd98 +"@next/env@npm:14.1.0": + version: 14.1.0 + resolution: "@next/env@npm:14.1.0" + checksum: f45ce1e3dad87cdbddc58b06bd411f44a6d21dfc2c344d02a5e1b07f56fbc9a39e192c0b0917df9f2e9e4e2156306a8c78f173ca4b53932c2793e67797462a23 languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-darwin-arm64@npm:14.0.4" +"@next/swc-darwin-arm64@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-darwin-arm64@npm:14.1.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-darwin-x64@npm:14.0.4" +"@next/swc-darwin-x64@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-darwin-x64@npm:14.1.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-arm64-gnu@npm:14.0.4" +"@next/swc-linux-arm64-gnu@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-linux-arm64-gnu@npm:14.1.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-arm64-musl@npm:14.0.4" +"@next/swc-linux-arm64-musl@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-linux-arm64-musl@npm:14.1.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-x64-gnu@npm:14.0.4" +"@next/swc-linux-x64-gnu@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-linux-x64-gnu@npm:14.1.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-x64-musl@npm:14.0.4" +"@next/swc-linux-x64-musl@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-linux-x64-musl@npm:14.1.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-win32-arm64-msvc@npm:14.0.4" +"@next/swc-win32-arm64-msvc@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-win32-arm64-msvc@npm:14.1.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-win32-ia32-msvc@npm:14.0.4" +"@next/swc-win32-ia32-msvc@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-win32-ia32-msvc@npm:14.1.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-win32-x64-msvc@npm:14.0.4" +"@next/swc-win32-x64-msvc@npm:14.1.0": + version: 14.1.0 + resolution: "@next/swc-win32-x64-msvc@npm:14.1.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -5354,6 +5437,7 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/cli@workspace:lib/cli" dependencies: + "@babel/core": "npm:^7.23.0" "@babel/types": "npm:^7.23.0" "@ndelangen/get-tarball": "npm:^3.0.7" "@storybook/codemod": "workspace:*" @@ -5390,6 +5474,7 @@ __metadata: read-pkg-up: "npm:^7.0.1" semver: "npm:^7.3.7" slash: "npm:^5.0.0" + strip-ansi: "npm:^7.1.0" strip-json-comments: "npm:^3.1.1" tempy: "npm:^1.0.1" tiny-invariant: "npm:^1.3.1" @@ -5528,6 +5613,7 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/core-events@workspace:lib/core-events" dependencies: + chalk: "npm:^4.1.0" ts-dedent: "npm:^2.0.0" typescript: "npm:^5.3.2" languageName: unknown @@ -5538,6 +5624,7 @@ __metadata: resolution: "@storybook/core-server@workspace:lib/core-server" dependencies: "@aw-web-design/x-default-browser": "npm:1.4.126" + "@babel/core": "npm:^7.23.9" "@discoveryjs/json-ext": "npm:^0.5.3" "@storybook/addon-docs": "workspace:*" "@storybook/builder-manager": "workspace:*" @@ -5571,7 +5658,7 @@ __metadata: express: "npm:^4.17.3" fs-extra: "npm:^11.1.0" globby: "npm:^11.0.2" - ip: "npm:^2.0.0" + ip: "npm:^2.0.1" lodash: "npm:^4.17.21" node-fetch: "npm:^3.3.1" open: "npm:^8.4.0" @@ -5956,7 +6043,7 @@ __metadata: fs-extra: "npm:^11.1.0" image-size: "npm:^1.0.0" loader-utils: "npm:^3.2.1" - next: "npm:^14.0.2" + next: "npm:^14.1.0" node-polyfill-webpack-plugin: "npm:^2.0.1" pnp-webpack-plugin: "npm:^1.7.0" postcss: "npm:^8.4.21" @@ -6431,7 +6518,7 @@ __metadata: eslint: "npm:^8.56.0" eslint-import-resolver-typescript: "npm:^3.6.1" eslint-plugin-local-rules: "portal:../scripts/eslint-plugin-local-rules" - eslint-plugin-storybook: "npm:^0.6.15" + eslint-plugin-storybook: "npm:^0.8.0" fs-extra: "npm:^11.1.0" github-release-from-changelog: "npm:^2.1.1" glob: "npm:^10.0.0" @@ -6647,7 +6734,7 @@ __metadata: "@storybook/preview-api": "workspace:*" "@testing-library/dom": "npm:^9.3.1" "@testing-library/jest-dom": "npm:^6.4.0" - "@testing-library/user-event": "npm:14.3.0" + "@testing-library/user-event": "npm:^14.5.2" "@vitest/expect": "npm:1.1.3" "@vitest/spy": "npm:^1.1.3" chai: "npm:^4.3.7" @@ -6973,21 +7060,21 @@ __metadata: languageName: node linkType: hard -"@testing-library/user-event@npm:14.3.0": - version: 14.3.0 - resolution: "@testing-library/user-event@npm:14.3.0" +"@testing-library/user-event@npm:^14.4.0, @testing-library/user-event@npm:^14.4.3": + version: 14.5.1 + resolution: "@testing-library/user-event@npm:14.5.1" peerDependencies: "@testing-library/dom": ">=7.21.4" - checksum: 8a0e708709f2510287568dff668bc7d6f5c4e7e17407452b7aa0fcf74732dccf511c63fc76ac514d753cb1f0586c1def59ba7f5245a9523715d37a8f198745d3 + checksum: 1e00d6ead23377885b906db6e46e259161a0efb4138f7527481d7435f3c8f65cb7e3eab2900e2ac1886fa6dd03416e773a3a60dea87a9a2086a7127dee315f6f languageName: node linkType: hard -"@testing-library/user-event@npm:^14.4.0, @testing-library/user-event@npm:^14.4.3": - version: 14.5.1 - resolution: "@testing-library/user-event@npm:14.5.1" +"@testing-library/user-event@npm:^14.5.2": + version: 14.5.2 + resolution: "@testing-library/user-event@npm:14.5.2" peerDependencies: "@testing-library/dom": ">=7.21.4" - checksum: 1e00d6ead23377885b906db6e46e259161a0efb4138f7527481d7435f3c8f65cb7e3eab2900e2ac1886fa6dd03416e773a3a60dea87a9a2086a7127dee315f6f + checksum: 68a0c2aa28a3c8e6eb05cafee29705438d7d8a9427423ce5064d44f19c29e89b5636de46dd2f28620fb10abba75c67130185bbc3aa23ac1163a227a5f36641e1 languageName: node linkType: hard @@ -8302,7 +8389,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.45.0": +"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.62.0": version: 5.62.0 resolution: "@typescript-eslint/utils@npm:5.62.0" dependencies: @@ -11116,13 +11203,20 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565": +"caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565": version: 1.0.30001570 resolution: "caniuse-lite@npm:1.0.30001570" checksum: e47230d2016edea56e002fa462a5289f697b48dcfbf703fb01aecc6c98ad4ecaf945ab23c253cb7af056c2d05f266e4e4cbebf45132100e2c9367439cb95b95b languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001579": + version: 1.0.30001581 + resolution: "caniuse-lite@npm:1.0.30001581" + checksum: 34b048156514eab5932212807428905cbecdef918f7c3d2153d5e8b6885d929e5c0b649f9e135cb1e03e413fbad8e00d1f24ed04cbcca52adc660ef98cad9032 + languageName: node + linkType: hard + "case-sensitive-paths-webpack-plugin@npm:^2.4.0": version: 2.4.0 resolution: "case-sensitive-paths-webpack-plugin@npm:2.4.0" @@ -14205,17 +14299,17 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-storybook@npm:^0.6.15": - version: 0.6.15 - resolution: "eslint-plugin-storybook@npm:0.6.15" +"eslint-plugin-storybook@npm:^0.8.0": + version: 0.8.0 + resolution: "eslint-plugin-storybook@npm:0.8.0" dependencies: "@storybook/csf": "npm:^0.0.1" - "@typescript-eslint/utils": "npm:^5.45.0" - requireindex: "npm:^1.1.0" + "@typescript-eslint/utils": "npm:^5.62.0" + requireindex: "npm:^1.2.0" ts-dedent: "npm:^2.2.0" peerDependencies: eslint: ">=6" - checksum: c61f5f2af72b614c30e8b36644672cfa25ca28e963e5e6cfab438f0cb287a6270f875a2dd8cd600a04c9864b9c549e269d95ea8da88c412e2b868fcd6a3605a4 + checksum: c76f6decdd4c826cd6a8bb613085e0cde804f4648093a0464a39867cc0ba4e1d34be15ff91eed827730da5efbbf55ae5e71af648bb0b461946d5e41384669ab8 languageName: node linkType: hard @@ -17270,6 +17364,13 @@ __metadata: languageName: node linkType: hard +"ip@npm:^2.0.1": + version: 2.0.1 + resolution: "ip@npm:2.0.1" + checksum: cab8eb3e88d0abe23e4724829621ec4c4c5cb41a7f936a2e626c947128c1be16ed543448d42af7cca95379f9892bfcacc1ccd8d09bc7e8bea0e86d492ce33616 + languageName: node + linkType: hard + "ipaddr.js@npm:1.9.1": version: 1.9.1 resolution: "ipaddr.js@npm:1.9.1" @@ -21276,27 +21377,26 @@ __metadata: languageName: node linkType: hard -"next@npm:^14.0.2": - version: 14.0.4 - resolution: "next@npm:14.0.4" +"next@npm:^14.1.0": + version: 14.1.0 + resolution: "next@npm:14.1.0" dependencies: - "@next/env": "npm:14.0.4" - "@next/swc-darwin-arm64": "npm:14.0.4" - "@next/swc-darwin-x64": "npm:14.0.4" - "@next/swc-linux-arm64-gnu": "npm:14.0.4" - "@next/swc-linux-arm64-musl": "npm:14.0.4" - "@next/swc-linux-x64-gnu": "npm:14.0.4" - "@next/swc-linux-x64-musl": "npm:14.0.4" - "@next/swc-win32-arm64-msvc": "npm:14.0.4" - "@next/swc-win32-ia32-msvc": "npm:14.0.4" - "@next/swc-win32-x64-msvc": "npm:14.0.4" + "@next/env": "npm:14.1.0" + "@next/swc-darwin-arm64": "npm:14.1.0" + "@next/swc-darwin-x64": "npm:14.1.0" + "@next/swc-linux-arm64-gnu": "npm:14.1.0" + "@next/swc-linux-arm64-musl": "npm:14.1.0" + "@next/swc-linux-x64-gnu": "npm:14.1.0" + "@next/swc-linux-x64-musl": "npm:14.1.0" + "@next/swc-win32-arm64-msvc": "npm:14.1.0" + "@next/swc-win32-ia32-msvc": "npm:14.1.0" + "@next/swc-win32-x64-msvc": "npm:14.1.0" "@swc/helpers": "npm:0.5.2" busboy: "npm:1.6.0" - caniuse-lite: "npm:^1.0.30001406" + caniuse-lite: "npm:^1.0.30001579" graceful-fs: "npm:^4.2.11" postcss: "npm:8.4.31" styled-jsx: "npm:5.1.1" - watchpack: "npm:2.4.0" peerDependencies: "@opentelemetry/api": ^1.1.0 react: ^18.2.0 @@ -21328,7 +21428,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: e6c829fd473d8c3605b2b62d15e1bf41e9d90cf59a2c213b4adeadff2846999bc9a653ffef18f6aa13cc9f5d6de02469c222acf5a4184901a4690a4504bd468f + checksum: dbb1ef8d22eec29a9127d28ed46eb34f14e3f7f7b4e4b91dc96027feb4d9ead554a804275484d9a54026e6e55d632d3997561e598c1fb8e8956e77614f39765f languageName: node linkType: hard @@ -24972,7 +25072,7 @@ __metadata: languageName: node linkType: hard -"requireindex@npm:^1.1.0, requireindex@npm:^1.2.0": +"requireindex@npm:^1.2.0": version: 1.2.0 resolution: "requireindex@npm:1.2.0" checksum: 7fb42aed73bf8de9acc4d6716cf07acc7fbe180e58729433bafcf702e76e7bb10e54f8266c06bfec62d752e0ac14d50e8758833de539e6f4e2cd642077866153 @@ -26780,7 +26880,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.0, strip-ansi@npm:^7.0.1": +"strip-ansi@npm:^7.0.0, strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": version: 7.1.0 resolution: "strip-ansi@npm:7.1.0" dependencies: @@ -29301,7 +29401,7 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:2.4.0, watchpack@npm:^2.2.0, watchpack@npm:^2.4.0": +"watchpack@npm:^2.2.0, watchpack@npm:^2.4.0": version: 2.4.0 resolution: "watchpack@npm:2.4.0" dependencies: diff --git a/docs/api/csf.md b/docs/api/csf.md index 5ddbab04d894..b91f45fd57a4 100644 --- a/docs/api/csf.md +++ b/docs/api/csf.md @@ -204,7 +204,7 @@ A good use case for the `play` function is a form component. With previous Story When the story renders in the UI, Storybook executes each step defined in the `play` function and runs the assertions without the need for user interaction. - + ## Custom render functions @@ -226,6 +226,7 @@ Starting in Storybook 6.4, you can write your stories as JavaScript objects, red 'solid/component-story-with-custom-render-function.ts.mdx', ]} usesCsf3 + csf2Path="api/csf#snippet-component-story-with-custom-render-function" /> @@ -430,7 +431,7 @@ Now, let's rewrite it as a story object in CSF 3 with an explicit `render` funct ]} /> - + Learn more about [render functions](#custom-render-functions). @@ -452,7 +453,7 @@ CSF 3 provides default render functions for each renderer. If all you're doing i - + For more information, see the section on [custom render functions](#custom-render-functions). diff --git a/docs/api/doc-block-markdown.md b/docs/api/doc-block-markdown.md index 8e05ca60d08a..e37ba196ee97 100644 --- a/docs/api/doc-block-markdown.md +++ b/docs/api/doc-block-markdown.md @@ -24,6 +24,8 @@ import { Button } from "@storybook/design-system"; ```md + + // DON'T do this, will error import ReadMe from './README.md'; // DO this, will work diff --git a/docs/api/main-config-features.md b/docs/api/main-config-features.md index afbab0b01695..1d773b6e1eaf 100644 --- a/docs/api/main-config-features.md +++ b/docs/api/main-config-features.md @@ -10,7 +10,6 @@ Type: { argTypeTargetsV7?: boolean; legacyDecoratorFileOrder?: boolean; - legacyMdx1?: boolean; } ``` diff --git a/docs/api/main-config-indexers.md b/docs/api/main-config-indexers.md index 256dd9b2c990..79e7fa2f2651 100644 --- a/docs/api/main-config-indexers.md +++ b/docs/api/main-config-indexers.md @@ -351,9 +351,7 @@ function JsonStoriesPlugin(): PluginOption { Generating stories with an alternative API -You can use a custom indexer and builder plugin to create your own API for defining stories, such as imperatively defining stories similar to the legacy [`storiesOf`](https://github.com/storybookjs/storybook/blob/main/code/lib/preview-api/docs/storiesOf.md) format. - -The [dynamic stories proof of concept](https://stackblitz.com/edit/github-h2rgfk?file=README.md) is an elaborate, functional example of doing just that. It contains everything needed to support such a feature, including the indexer, a Vite plugin and a Webpack loader. +You can use a custom indexer and builder plugin to create your API to define stories extending the CSF format. To learn more, see the following [proof of concept](https://stackblitz.com/edit/github-h2rgfk?file=README.md) to set up a custom indexer to generate stories dynamically. It contains everything needed to support such a feature, including the indexer, a Vite plugin, and a Webpack loader. diff --git a/docs/configure/frameworks-feature-support.md b/docs/configure/frameworks-feature-support.md index 7ae41614e248..79013ad8fc4b 100644 --- a/docs/configure/frameworks-feature-support.md +++ b/docs/configure/frameworks-feature-support.md @@ -110,8 +110,8 @@ Community frameworks have fewer contributors which means they may not be as up t To align the Storybook ecosystem with the current state of frontend development, the following features and addons are now deprecated, no longer maintained, and will be removed in future versions of Storybook -| Feature | Status | -| -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Knobs](https://github.com/storybookjs/addon-knobs) | The Knobs addon was officially deprecated with the release of Storybook 6.3 and is no longer actively maintained. We recommend using the [controls](../essentials/controls.md) instead. | -| [Storyshots](../writing-tests/snapshot-testing.md) | The Storyshots addon was officially deprecated with the release of Storybook 7.6, is no longer actively maintained and was removed in Storybook 8. See the [migration guide](../writing-tests/storyshots-migration-guide.md) for the available alternatives. | -| [`StoriesOf`](https://github.com/storybookjs/storybook/blob/next/code/lib/preview-api/docs/storiesOf.md) | The `storiesOf` API was officially removed with the release of Storybook 8 and is no longer maintained. We recommend using the [CSF API](../api/csf.md) instead for writing stories.
See the [migration guide](../migration-guide.md#storiesof-to-csf) for more information. | +| Feature | Status | +| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Knobs](https://github.com/storybookjs/addon-knobs) | The Knobs addon was officially deprecated with the release of Storybook 6.3 and is no longer actively maintained. We recommend using the [controls](../essentials/controls.md) instead. | +| [Storyshots](../writing-tests/snapshot-testing.md) | The Storyshots addon was officially deprecated with the release of Storybook 7.6, is no longer actively maintained and was removed in Storybook 8. See the [migration guide](../writing-tests/storyshots-migration-guide.md) for the available alternatives. | +| StoriesOf | The `storiesOf` API was officially removed with the release of Storybook 8 and is no longer maintained. We recommend using the [CSF API](../api/csf.md) instead for writing stories.
See the [migration guide](../migration-guide.md#storiesof-to-csf) for more information. | diff --git a/docs/faq.md b/docs/faq.md index 6e6ce176787a..1cceba208102 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -230,112 +230,110 @@ With the release of version 6.0, we updated our documentation as well. That does We're only covering versions 5.3 and 5.0 as they were important milestones for Storybook. If you want to go back in time a little more, you'll have to check the specific release in the monorepo. -| Section | Page | Current Location | Version 5.3 location | Version 5.0 location | -| ---------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -| N/A | Why Storybook | [See current documentation](./why-storybook.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| Get started | Install | [See current documentation](./get-started/install.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides/quick-start-guide) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/guides/quick-start-guide) | -| | What's a story | [See current documentation](./get-started/whats-a-story.md) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/guides) | -| | Browse Stories | [See current documentation](./get-started/browse-stories.md) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/blob/release/5.0/docs/src/pages/guides) | -| | Setup | [See current documentation](./get-started/setup.md) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/guides) | -| Write stories | Introduction | [See current documentation](./writing-stories/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories) | -| | Parameters | [See current documentation](./writing-stories/parameters.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories/index.md#parameters) | Non existing feature or undocumented | -| | Decorators | [See current documentation](./writing-stories/decorators.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories/index.md#decorators) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories/index.md#using-decorators) | -| | Naming components and hierarchy | [See current documentation](./writing-stories/naming-components-and-hierarchy.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories) | -| | Build pages and screens | [See current documentation](./writing-stories/build-pages-with-storybook.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Stories for multiple components | [See current documentation](./writing-stories/stories-for-multiple-components.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| Write docs | Autodocs | [See current documentation](./writing-docs/autodocs.md) | See versioned addon documentation | Non existing feature or undocumented | -| | MDX | [See current documentation](./writing-docs/mdx.md) | See versioned addon documentation | Non existing feature or undocumented | -| | Doc Blocks | [See current documentation](./writing-docs/doc-blocks.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Preview and build docs | [See current documentation](./writing-docs/build-documentation.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| Testing | Visual tests | [See current documentation](./writing-tests/visual-testing.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/automated-visual-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/automated-visual-testing) | -| | Accessibility tests | [See current documentation](./writing-tests/accessibility-testing.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Interaction tests | [See current documentation](./writing-tests/interaction-testing.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/interaction-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/interaction-testing) | -| | Snapshot tests | [See current documentation](./writing-tests/snapshot-testing.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/structural-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/structural-testing) | -| | Import stories in tests/Unit tests | [See current documentation](./writing-tests/stories-in-unit-tests.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/react-ui-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/react-ui-testing) | -| | Import stories in tests/End-to-end testing | [See current documentation](./writing-tests/stories-in-end-to-end-tests.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/react-ui-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/react-ui-testing) | -| Sharing | Publish Storybook | [See current documentation](./sharing/publish-storybook.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/exporting-storybook) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/exporting-storybook) | -| | Embed | [See current documentation](./sharing/embed.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Composition | [See current documentation](./sharing/storybook-composition.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Package Composition | [See current documentation](./sharing/package-composition.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| Essential addons | Controls | [See current documentation](./essentials/controls.md) | Controls are specific to version 6.0 see [Knobs versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/knobs) | Controls are specific to version 6.0 see [Knobs versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/knobs) | -| | Actions | [See current documentation](./essentials/actions.md) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/actions) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/actions) | -| | Viewport | [See current documentation](./essentials/viewport.md) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/viewport) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/viewport) | -| | Backgrounds | [See current documentation](./essentials/backgrounds.md) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/backgrounds) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/backgrounds) | -| | Toolbars and globals | [See current documentation](./essentials/toolbars-and-globals.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/toolbar-guide) | Non existing feature or undocumented | -| Configure | Overview | [See current documentation](./configure/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/overview) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories) | -| | Integration/Frameworks | [See current documentation](./configure/frameworks.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Integration/Framework support for frameworks | [See current documentation](./configure/frameworks-feature-support.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Integration/Compilers | [See current documentation](./configure/compilers.md) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/custom-babel-config) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/custom-babel-config) | -| | Integration/Typescript | [See current documentation](./configure/typescript.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/typescript-config) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/typescript-config) | -| | Integration/Styling and CSS | [See current documentation](./configure/styling-and-css.md) | See versioned documentation | See versioned documentation | -| | Integration/Images and assets | [See current documentation](./configure/images-and-assets.md) | See versioned documentation | See versioned documentation | -| | Story rendering | [See current documentation](./configure/story-rendering.md) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/add-custom-head-tags) and [here](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/add-custom-body) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/add-custom-head-tags) | -| | Story Layout | [See current documentation](./configure/story-layout.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | User Interface/Features and behavior | [See current documentation](./configure/features-and-behavior.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/options-parameter) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/options-parameter) | -| | User Interface/Theming | [See current documentation](./configure/theming.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/theming) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/theming) | -| | User Interface/Sidebar & URLS | [See current documentation](./configure/sidebar-and-urls.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/options-parameter) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/options-parameter) | -| | Environment variables | [See current documentation](./configure/environment-variables.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/env-vars) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/env-vars) | -| Builders | Introduction | [See current documentation](./builders/index.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Vite | [See current documentation](./builders/vite.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Webpack | [See current documentation](./builders/webpack.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/custom-webpack-config/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/custom-webpack-config/index.md) | -| | Builder API | [See current documentation](./builders/builder-api.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| Addons | Introduction | [See current documentation](./addons/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/writing-addons) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/writing-addons) | -| | Install addons | [See current documentation](./addons/install-addons.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/using-addons/) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/using-addons/) | -| | Writing Addons | [See current documentation](./addons/writing-addons.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/writing-addons) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/writing-addons) | -| | Writing Presets | [See current documentation](./addons/writing-presets.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/presets/writing-presets) | Non existing feature or undocumented | -| | Addons Knowledge Base | [See current documentation](./addons/addon-knowledge-base.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/writing-addons) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/writing-addons) | -| | Types of addons | [See current documentation](./addons/addon-types.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Addons API | [See current documentation](./addons/addons-api.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/api) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/api) | -| API | @storybook/blocks/ArgTypes | [See current documentation](./api/doc-block-argtypes.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Canvas | [See current documentation](./api/doc-block-canvas.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/ColorPalette | [See current documentation](./api/doc-block-colorpalette.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Controls | [See current documentation](./api/doc-block-controls.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Description | [See current documentation](./api/doc-description.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/IconGallery | [See current documentation](./api/doc-block-icongallery.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Markdown | [See current documentation](./api/doc-block-markdown.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Meta | [See current documentation](./api/doc-block-meta.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Primary | [See current documentation](./api/doc-block-primary.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Source | [See current documentation](./api/doc-block-source.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Stories | [See current documentation](./api/doc-block-stories.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Story | [See current documentation](./api/doc-block-story.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Subtitle | [See current documentation](./api/doc-block-subtitle.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Title | [See current documentation](./api/doc-block-title.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Typeset | [See current documentation](./api/doc-block-typeset.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/Unstyled | [See current documentation](./api/doc-block-unstyled.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | @storybook/blocks/useOf | [See current documentation](./api/doc-block-useof.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Stories/Component Story Format | [See current documentation](./api/csf.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/formats/component-story-format) | Non existing feature or undocumented | -| | Stories/StoriesOF format (see note below) | [See current documentation](https://github.com/storybookjs/storybook/blob/main/code/lib/preview-api/docs/storiesOf.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/formats/storiesof-api) | Non existing feature or undocumented | -| | ArgTypes | [See current documentation](./api/arg-types.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/Overview | [See current documentation](./api/main-config.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/framework | [See current documentation](./api/main-config-framework.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/stories | [See current documentation](./api/main-config-stories.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/addons | [See current documentation](./api/main-config-addons.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/babel | [See current documentation](./api/main-config-babel.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/babelDefault | [See current documentation](./api/main-config-babel-default.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/build | [See current documentation](./api/main-config-build.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/core | [See current documentation](./api/main-config-core.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/docs | [See current documentation](./api/main-config-docs.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/env | [See current documentation](./api/main-config-env.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/features | [See current documentation](./api/main-config-features.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/indexers | [See current documentation](./api/main-config-indexers.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/logLevel | [See current documentation](./api/main-config-log-level.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/managerHead | [See current documentation](./api/main-config-manager-head.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/previewAnnotations | [See current documentation](./api/main-config-preview-annotations.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/previewBody | [See current documentation](./api/main-config-preview-body.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/previewHead | [See current documentation](./api/main-config-preview-head.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/refs | [See current documentation](./api/main-config-refs.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/staticDirs | [See current documentation](./api/main-config-static-dirs.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/swc | [See current documentation](./api/main-config-swc.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/typescript | [See current documentation](./api/main-config-typescript.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/viteFinal | [See current documentation](./api/main-config-vite-final.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | `main.js` configuration/webpackFinal | [See current documentation](./api/main-config-webpack-final.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | Frameworks | [See current documentation](./api/new-frameworks.md) | Non existing feature or undocumented | Non existing feature or undocumented | -| | CLI options | [See current documentation](./api/cli-options.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/cli-options) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/cli-options) | - - +| Section | Page | Current Location | Version 5.3 location | Version 5.0 location | +| ---------------- | ----------------------------------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| N/A | Why Storybook | [See current documentation](./why-storybook.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| Get started | Install | [See current documentation](./get-started/install.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides/quick-start-guide) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/guides/quick-start-guide) | +| | What's a story | [See current documentation](./get-started/whats-a-story.md) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/guides) | +| | Browse Stories | [See current documentation](./get-started/browse-stories.md) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/blob/release/5.0/docs/src/pages/guides) | +| | Setup | [See current documentation](./get-started/setup.md) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/guides) | [See versioned documentation for your framework](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/guides) | +| Write stories | Introduction | [See current documentation](./writing-stories/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories) | +| | Parameters | [See current documentation](./writing-stories/parameters.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories/index.md#parameters) | Non existing feature or undocumented | +| | Decorators | [See current documentation](./writing-stories/decorators.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories/index.md#decorators) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories/index.md#using-decorators) | +| | Naming components and hierarchy | [See current documentation](./writing-stories/naming-components-and-hierarchy.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/writing-stories) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories) | +| | Build pages and screens | [See current documentation](./writing-stories/build-pages-with-storybook.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Stories for multiple components | [See current documentation](./writing-stories/stories-for-multiple-components.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| Write docs | Autodocs | [See current documentation](./writing-docs/autodocs.md) | See versioned addon documentation | Non existing feature or undocumented | +| | MDX | [See current documentation](./writing-docs/mdx.md) | See versioned addon documentation | Non existing feature or undocumented | +| | Doc Blocks | [See current documentation](./writing-docs/doc-blocks.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Preview and build docs | [See current documentation](./writing-docs/build-documentation.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| Testing | Visual tests | [See current documentation](./writing-tests/visual-testing.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/automated-visual-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/automated-visual-testing) | +| | Accessibility tests | [See current documentation](./writing-tests/accessibility-testing.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Interaction tests | [See current documentation](./writing-tests/interaction-testing.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/interaction-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/interaction-testing) | +| | Snapshot tests | [See current documentation](./writing-tests/snapshot-testing.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/structural-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/structural-testing) | +| | Import stories in tests/Unit tests | [See current documentation](./writing-tests/stories-in-unit-tests.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/react-ui-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/react-ui-testing) | +| | Import stories in tests/End-to-end testing | [See current documentation](./writing-tests/stories-in-end-to-end-tests.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/testing/react-ui-testing) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/testing/react-ui-testing) | +| Sharing | Publish Storybook | [See current documentation](./sharing/publish-storybook.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/exporting-storybook) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/exporting-storybook) | +| | Embed | [See current documentation](./sharing/embed.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Composition | [See current documentation](./sharing/storybook-composition.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Package Composition | [See current documentation](./sharing/package-composition.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| Essential addons | Controls | [See current documentation](./essentials/controls.md) | Controls are specific to version 6.0 see [Knobs versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/knobs) | Controls are specific to version 6.0 see [Knobs versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/knobs) | +| | Actions | [See current documentation](./essentials/actions.md) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/actions) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/actions) | +| | Viewport | [See current documentation](./essentials/viewport.md) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/viewport) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/viewport) | +| | Backgrounds | [See current documentation](./essentials/backgrounds.md) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/addons/backgrounds) | [See addon versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/addons/backgrounds) | +| | Toolbars and globals | [See current documentation](./essentials/toolbars-and-globals.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/basics/toolbar-guide) | Non existing feature or undocumented | +| Configure | Overview | [See current documentation](./configure/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/overview) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/basics/writing-stories) | +| | Integration/Frameworks | [See current documentation](./configure/frameworks.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Integration/Framework support for frameworks | [See current documentation](./configure/frameworks-feature-support.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Integration/Compilers | [See current documentation](./configure/compilers.md) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/custom-babel-config) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/custom-babel-config) | +| | Integration/Typescript | [See current documentation](./configure/typescript.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/typescript-config) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/typescript-config) | +| | Integration/Styling and CSS | [See current documentation](./configure/styling-and-css.md) | See versioned documentation | See versioned documentation | +| | Integration/Images and assets | [See current documentation](./configure/images-and-assets.md) | See versioned documentation | See versioned documentation | +| | Story rendering | [See current documentation](./configure/story-rendering.md) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/add-custom-head-tags) and [here](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/add-custom-body) | See versioned documentation [here](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/add-custom-head-tags) | +| | Story Layout | [See current documentation](./configure/story-layout.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | User Interface/Features and behavior | [See current documentation](./configure/features-and-behavior.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/options-parameter) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/options-parameter) | +| | User Interface/Theming | [See current documentation](./configure/theming.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/theming) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/theming) | +| | User Interface/Sidebar & URLS | [See current documentation](./configure/sidebar-and-urls.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/options-parameter) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/options-parameter) | +| | Environment variables | [See current documentation](./configure/environment-variables.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/env-vars) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/env-vars) | +| Builders | Introduction | [See current documentation](./builders/index.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Vite | [See current documentation](./builders/vite.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Webpack | [See current documentation](./builders/webpack.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/custom-webpack-config/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/custom-webpack-config/index.md) | +| | Builder API | [See current documentation](./builders/builder-api.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| Addons | Introduction | [See current documentation](./addons/index.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/writing-addons) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/writing-addons) | +| | Install addons | [See current documentation](./addons/install-addons.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/using-addons/) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/using-addons/) | +| | Writing Addons | [See current documentation](./addons/writing-addons.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/writing-addons) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/writing-addons) | +| | Writing Presets | [See current documentation](./addons/writing-presets.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/presets/writing-presets) | Non existing feature or undocumented | +| | Addons Knowledge Base | [See current documentation](./addons/addon-knowledge-base.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/writing-addons) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/writing-addons) | +| | Types of addons | [See current documentation](./addons/addon-types.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Addons API | [See current documentation](./addons/addons-api.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/addons/api) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/addons/api) | +| API | @storybook/blocks/ArgTypes | [See current documentation](./api/doc-block-argtypes.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Canvas | [See current documentation](./api/doc-block-canvas.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/ColorPalette | [See current documentation](./api/doc-block-colorpalette.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Controls | [See current documentation](./api/doc-block-controls.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Description | [See current documentation](./api/doc-description.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/IconGallery | [See current documentation](./api/doc-block-icongallery.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Markdown | [See current documentation](./api/doc-block-markdown.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Meta | [See current documentation](./api/doc-block-meta.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Primary | [See current documentation](./api/doc-block-primary.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Source | [See current documentation](./api/doc-block-source.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Stories | [See current documentation](./api/doc-block-stories.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Story | [See current documentation](./api/doc-block-story.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Subtitle | [See current documentation](./api/doc-block-subtitle.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Title | [See current documentation](./api/doc-block-title.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Typeset | [See current documentation](./api/doc-block-typeset.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/Unstyled | [See current documentation](./api/doc-block-unstyled.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | @storybook/blocks/useOf | [See current documentation](./api/doc-block-useof.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Stories/Component Story Format (see note below) | [See current documentation](./api/csf.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/formats/component-story-format) | Non existing feature or undocumented | +| | ArgTypes | [See current documentation](./api/arg-types.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/Overview | [See current documentation](./api/main-config.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/framework | [See current documentation](./api/main-config-framework.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/stories | [See current documentation](./api/main-config-stories.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/addons | [See current documentation](./api/main-config-addons.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/babel | [See current documentation](./api/main-config-babel.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/babelDefault | [See current documentation](./api/main-config-babel-default.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/build | [See current documentation](./api/main-config-build.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/core | [See current documentation](./api/main-config-core.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/docs | [See current documentation](./api/main-config-docs.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/env | [See current documentation](./api/main-config-env.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/features | [See current documentation](./api/main-config-features.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/indexers | [See current documentation](./api/main-config-indexers.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/logLevel | [See current documentation](./api/main-config-log-level.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/managerHead | [See current documentation](./api/main-config-manager-head.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/previewAnnotations | [See current documentation](./api/main-config-preview-annotations.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/previewBody | [See current documentation](./api/main-config-preview-body.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/previewHead | [See current documentation](./api/main-config-preview-head.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/refs | [See current documentation](./api/main-config-refs.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/staticDirs | [See current documentation](./api/main-config-static-dirs.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/swc | [See current documentation](./api/main-config-swc.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/typescript | [See current documentation](./api/main-config-typescript.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/viteFinal | [See current documentation](./api/main-config-vite-final.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | `main.js` configuration/webpackFinal | [See current documentation](./api/main-config-webpack-final.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | Frameworks | [See current documentation](./api/new-frameworks.md) | Non existing feature or undocumented | Non existing feature or undocumented | +| | CLI options | [See current documentation](./api/cli-options.md) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.3/docs/src/pages/configurations/cli-options) | [See versioned documentation](https://github.com/storybookjs/storybook/tree/release/5.0/docs/src/pages/configurations/cli-options) | + -With the release of version 5.3, we've updated how you can write your stories more compactly and easily. It doesn't mean that the `storiesOf` format has been removed. For the time being, we're still supporting it, and we have documentation for it. But be advised that this is bound to change in the future. +If you have stories written with the older `storiesOf` format, it was removed in Storybook 8.0 and is no longer maintained. We recommend that you migrate your stories to CSF. See the [migration guide](./migration-guide.md#storiesof-to-csf) for more information. However, if you need, you can still access the old `storiesOf` [documentation](https://github.com/storybookjs/storybook/blob/release/5.3/docs/src/pages/formats/storiesof-api/index.md) for reference. diff --git a/docs/versions/next.json b/docs/versions/next.json index 615ec622d172..1c9c15870c34 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.0.0-beta.2","info":{"plain":"- Core: Fix boolean `true` args in URL getting ignored - [#25950](https://github.com/storybookjs/storybook/pull/25950), thanks [@JReinhold](https://github.com/JReinhold)!\n- Core: Move @types packages to dev deps in core-common - [#25387](https://github.com/storybookjs/storybook/pull/25387), thanks [@kyletsang](https://github.com/kyletsang)!\n- Maintenance: Rename testing-utils paths to portable-stories - [#25888](https://github.com/storybookjs/storybook/pull/25888), thanks [@yannbf](https://github.com/yannbf)!\n- Portable stories: Pass story context to the play function of a composed story - [#25943](https://github.com/storybookjs/storybook/pull/25943), thanks [@yannbf](https://github.com/yannbf)!\n- UI: Fix `display=true` warning in console - [#25951](https://github.com/storybookjs/storybook/pull/25951), thanks [@JReinhold](https://github.com/JReinhold)!\n- UI: Update deprecated Icons with the new @storybook/icons in addons - [#25822](https://github.com/storybookjs/storybook/pull/25822), thanks [@cdedreuille](https://github.com/cdedreuille)!\n- Vite: Add a `rollup-plugin-webpack-stats` to allow stats from preview builds - [#25923](https://github.com/storybookjs/storybook/pull/25923), thanks [@tmeasday](https://github.com/tmeasday)!"}} +{"version":"8.0.0-beta.4","info":{"plain":"- Addon-actions: Warn when argTypesRegex is used together with the visual test addon - [#26094](https://github.com/storybookjs/storybook/pull/26094), thanks [@kasperpeulen](https://github.com/kasperpeulen)!\n- Addon-docs: Fix Table of Contents heading leak - [#23677](https://github.com/storybookjs/storybook/pull/23677), thanks [@vmizg](https://github.com/vmizg)!\n- CLI: Add `legacyMdx1` & `@storybook/mdx1-csf` automigration - [#26102](https://github.com/storybookjs/storybook/pull/26102), thanks [@ndelangen](https://github.com/ndelangen)!\n- CLI: Add line ignoring storybook's `.log` files upon `init` - [#26099](https://github.com/storybookjs/storybook/pull/26099), thanks [@ndelangen](https://github.com/ndelangen)!\n- CLI: Add support for custom vite config to autoblocker - [#26087](https://github.com/storybookjs/storybook/pull/26087), thanks [@ndelangen](https://github.com/ndelangen)!\n- CLI: Add webpack5 compiler automigration - [#26000](https://github.com/storybookjs/storybook/pull/26000), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- CLI: Remove argTypesRegex automigration - [#26001](https://github.com/storybookjs/storybook/pull/26001), thanks [@kasperpeulen](https://github.com/kasperpeulen)!\n- CLI: Remove the logging to file feature from autoblockers - [#26100](https://github.com/storybookjs/storybook/pull/26100), thanks [@ndelangen](https://github.com/ndelangen)!\n- Core: Add addon removal telemetry - [#26077](https://github.com/storybookjs/storybook/pull/26077), thanks [@shilman](https://github.com/shilman)!\n- Core: Fix fail to load `main.ts` error message - [#26035](https://github.com/storybookjs/storybook/pull/26035), thanks [@ndelangen](https://github.com/ndelangen)!\n- Core: Update ip version to fix CVE-2023-42282 - [#26086](https://github.com/storybookjs/storybook/pull/26086), thanks [@drik98](https://github.com/drik98)!\n- Next.js: Support getImageProps API - [#25745](https://github.com/storybookjs/storybook/pull/25745), thanks [@piratetaco](https://github.com/piratetaco)!\n- Svelte: Remove deprecated SvelteComponentTyped in favor of SvelteComponent - [#26113](https://github.com/storybookjs/storybook/pull/26113), thanks [@kasperpeulen](https://github.com/kasperpeulen)!\n- Vite: Fix bug that meant we always warned about TS plugin - [#26051](https://github.com/storybookjs/storybook/pull/26051), thanks [@tmeasday](https://github.com/tmeasday)!\n- Vite: Fix config typing issue of the `typescript` property - [#26046](https://github.com/storybookjs/storybook/pull/26046), thanks [@ndelangen](https://github.com/ndelangen)!\n- Vite: Fix issue getting preview stats with Vite builder - [#26093](https://github.com/storybookjs/storybook/pull/26093), thanks [@tmeasday](https://github.com/tmeasday)!"}} diff --git a/docs/writing-docs/autodocs.md b/docs/writing-docs/autodocs.md index a89dd0a51d2f..cad2b6e901d4 100644 --- a/docs/writing-docs/autodocs.md +++ b/docs/writing-docs/autodocs.md @@ -133,14 +133,14 @@ Storybook's auto-generated documentation pages can be quite long and difficult t By default, the table of contents on the documentation page will only show the `h3` headings that are automatically generated. However, if you want to customize the table of contents, you can add more parameters to the `toc` property. The following options and examples of how to use them are available. -| Option | Description | -| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `contentsSelector` | Defines the container's CSS selector for search for the headings
`toc: { contentsSelector: '.sbdocs-content' }` | -| `disable` | Hides the table of contents for the documentation pages
`toc: { disable: true }` | -| `headingSelector` | Defines the list of headings to feature in the table of contents
`toc: { headingSelector: 'h1, h2, h3' }` | -| `ignoreSelector` | Configures the table of contents to ignore specific headings or stories
`toc: { ignoreSelector: 'h2' }` | -| `title` | Defines a title caption for the table of contents.
Accepts one of: `string`, `null`, React element
`toc: { title: 'Table of Contents' }` | -| `unsafeTocbotOptions` | Provides additional [`TocBot`](https://tscanlin.github.io/tocbot/) configuration options
`toc: { unsafeTocbotOptions: { orderedList: true } }` | +| Option | Description | +| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `contentsSelector` | Defines the container's CSS selector for search for the headings
`toc: { contentsSelector: '.sbdocs-content' }` | +| `disable` | Hides the table of contents for the documentation pages
`toc: { disable: true }` | +| `headingSelector` | Defines the list of headings to feature in the table of contents
`toc: { headingSelector: 'h1, h2, h3' }` | +| `ignoreSelector` | Configures the table of contents to ignore specific headings or stories. By default, the table of contents will ignore all content placed within Story blocks
`toc: { ignoreSelector: '.docs-story h2' }` | +| `title` | Defines a title caption for the table of contents.
Accepts one of: `string`, `null`, React element
`toc: { title: 'Table of Contents' }` | +| `unsafeTocbotOptions` | Provides additional [`TocBot`](https://tscanlin.github.io/tocbot/) configuration options
`toc: { unsafeTocbotOptions: { orderedList: true } }` | diff --git a/docs/writing-stories/args.md b/docs/writing-stories/args.md index 49952701c8b0..c6b44c7ea88e 100644 --- a/docs/writing-stories/args.md +++ b/docs/writing-stories/args.md @@ -160,7 +160,7 @@ Args are useful when writing stories for composite components that are assembled - + diff --git a/scripts/package.json b/scripts/package.json index 1bb83d136ea6..01818aa20d40 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -126,7 +126,7 @@ "esbuild-plugin-alias": "^0.2.1", "esbuild-register": "^3.5.0", "eslint": "^8.56.0", - "eslint-plugin-storybook": "^0.6.15", + "eslint-plugin-storybook": "^0.8.0", "execa": "^6.1.0", "express": "^4.17.3", "fast-folder-size": "^2.1.0", diff --git a/scripts/yarn.lock b/scripts/yarn.lock index c92afc1e9ed1..180d2bf8f179 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -2786,7 +2786,7 @@ __metadata: esbuild-plugin-alias: "npm:^0.2.1" esbuild-register: "npm:^3.5.0" eslint: "npm:^8.56.0" - eslint-plugin-storybook: "npm:^0.6.15" + eslint-plugin-storybook: "npm:^0.8.0" execa: "npm:^6.1.0" express: "npm:^4.17.3" fast-folder-size: "npm:^2.1.0" @@ -3654,7 +3654,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.45.0": +"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.62.0": version: 5.62.0 resolution: "@typescript-eslint/utils@npm:5.62.0" dependencies: @@ -6935,17 +6935,17 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-storybook@npm:^0.6.15": - version: 0.6.15 - resolution: "eslint-plugin-storybook@npm:0.6.15" +"eslint-plugin-storybook@npm:^0.8.0": + version: 0.8.0 + resolution: "eslint-plugin-storybook@npm:0.8.0" dependencies: "@storybook/csf": "npm:^0.0.1" - "@typescript-eslint/utils": "npm:^5.45.0" - requireindex: "npm:^1.1.0" + "@typescript-eslint/utils": "npm:^5.62.0" + requireindex: "npm:^1.2.0" ts-dedent: "npm:^2.2.0" peerDependencies: eslint: ">=6" - checksum: c61f5f2af72b614c30e8b36644672cfa25ca28e963e5e6cfab438f0cb287a6270f875a2dd8cd600a04c9864b9c549e269d95ea8da88c412e2b868fcd6a3605a4 + checksum: c76f6decdd4c826cd6a8bb613085e0cde804f4648093a0464a39867cc0ba4e1d34be15ff91eed827730da5efbbf55ae5e71af648bb0b461946d5e41384669ab8 languageName: node linkType: hard @@ -13262,7 +13262,7 @@ __metadata: languageName: node linkType: hard -"requireindex@npm:^1.1.0, requireindex@npm:^1.2.0": +"requireindex@npm:^1.2.0": version: 1.2.0 resolution: "requireindex@npm:1.2.0" checksum: 7fb42aed73bf8de9acc4d6716cf07acc7fbe180e58729433bafcf702e76e7bb10e54f8266c06bfec62d752e0ac14d50e8758833de539e6f4e2cd642077866153