Merge branch 'next' into build/ts-up-addon-docs

This commit is contained in:
Norbert de Langen 2022-11-10 09:37:59 +01:00
commit 149deb8ec4
No known key found for this signature in database
GPG Key ID: FD0E78AF9A837762
49 changed files with 439 additions and 134 deletions

View File

@ -248,7 +248,7 @@ jobs:
cd ../cra-bench
rm -rf node_modules
mkdir node_modules
npx -p @storybook/bench@0.7.6--canary.14.6702e4f.0 sb-bench 'yarn install' --label cra
npx -p @storybook/bench@next sb-bench 'yarn install' --label cra
- run:
name: prep artifacts
when: always
@ -288,7 +288,7 @@ jobs:
cd ../react-vite-bench
rm -rf node_modules
mkdir node_modules
npx -p @storybook/bench@0.7.6--canary.14.6702e4f.0 sb-bench 'yarn install' --label react-vite
npx -p @storybook/bench@next sb-bench 'yarn install' --label react-vite
- run:
name: prep artifacts
when: always

View File

@ -52,6 +52,19 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -51,6 +51,19 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -46,6 +46,16 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -46,7 +46,7 @@ function createBabelOptions({ babelOptions, mdxBabelOptions, configureJSX }: Bab
};
}
export async function webpack(
async function webpack(
webpackConfig: any = {},
options: Options &
BabelParams & {
@ -160,7 +160,7 @@ export async function webpack(
return result;
}
export const storyIndexers = (indexers: CoreCommon_StoryIndexer[] | null) => {
const storyIndexers = (indexers: CoreCommon_StoryIndexer[] | null) => {
const mdxIndexer = async (fileName: string, opts: CoreCommon_IndexerOptions) => {
let code = (await fs.readFile(fileName, 'utf-8')).toString();
const { compile } = await import('@storybook/mdx2-csf');
@ -176,7 +176,7 @@ export const storyIndexers = (indexers: CoreCommon_StoryIndexer[] | null) => {
];
};
export const docs = (docsOptions: DocsOptions) => {
const docs = (docsOptions: DocsOptions) => {
return {
...docsOptions,
enabled: true,
@ -184,3 +184,13 @@ export const docs = (docsOptions: DocsOptions) => {
docsPage: true,
};
};
/*
* This is a workaround for https://github.com/Swatinem/rollup-plugin-dts/issues/162
* something down the dependency chain is using typescript namespaces, which are not supported by rollup-plugin-dts
*/
const webpackX = webpack as any;
const storyIndexersX = webpack as any;
const docsX = docs as any;
export { webpackX as webpack, storyIndexersX as storyIndexers, docsX as docs };

View File

@ -27,6 +27,76 @@
"import": "./dist/index.mjs",
"types": "./dist/index.d.ts"
},
"./actions/preview": {
"require": "./dist/actions/preview.js",
"import": "./dist/actions/preview.mjs",
"types": "./dist/actions/preview.d.ts"
},
"./actions/manager": {
"require": "./dist/actions/manager.js",
"import": "./dist/actions/manager.mjs",
"types": "./dist/actions/manager.d.ts"
},
"./backgrounds/preview": {
"require": "./dist/backgrounds/preview.js",
"import": "./dist/backgrounds/preview.mjs",
"types": "./dist/backgrounds/preview.d.ts"
},
"./backgrounds/manager": {
"require": "./dist/backgrounds/manager.js",
"import": "./dist/backgrounds/manager.mjs",
"types": "./dist/backgrounds/manager.d.ts"
},
"./controls/manager": {
"require": "./dist/controls/manager.js",
"import": "./dist/controls/manager.mjs",
"types": "./dist/controls/manager.d.ts"
},
"./docs/preview": {
"require": "./dist/docs/preview.js",
"import": "./dist/docs/preview.mjs",
"types": "./dist/docs/preview.d.ts"
},
"./docs/preset": {
"require": "./dist/docs/preset.js",
"import": "./dist/docs/preset.mjs",
"types": "./dist/docs/preset.d.ts"
},
"./highlight/preview": {
"require": "./dist/highlight/preview.js",
"import": "./dist/highlight/preview.mjs",
"types": "./dist/highlight/preview.d.ts"
},
"./measure/preview": {
"require": "./dist/measure/preview.js",
"import": "./dist/measure/preview.mjs",
"types": "./dist/measure/preview.d.ts"
},
"./measure/manager": {
"require": "./dist/measure/manager.js",
"import": "./dist/measure/manager.mjs",
"types": "./dist/measure/manager.d.ts"
},
"./outline/preview": {
"require": "./dist/outline/preview.js",
"import": "./dist/outline/preview.mjs",
"types": "./dist/outline/preview.d.ts"
},
"./outline/manager": {
"require": "./dist/outline/manager.js",
"import": "./dist/outline/manager.mjs",
"types": "./dist/outline/manager.d.ts"
},
"./toolbars/manager": {
"require": "./dist/toolbars/manager.js",
"import": "./dist/toolbars/manager.mjs",
"types": "./dist/toolbars/manager.d.ts"
},
"./viewport/manager": {
"require": "./dist/viewport/manager.js",
"import": "./dist/viewport/manager.mjs",
"types": "./dist/viewport/manager.d.ts"
},
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -70,7 +140,21 @@
},
"bundler": {
"entries": [
"./src/index.ts"
"./src/index.ts",
"./src/actions/preview.ts",
"./src/actions/manager.ts",
"./src/backgrounds/preview.ts",
"./src/backgrounds/manager.ts",
"./src/controls/manager.ts",
"./src/docs/preview.ts",
"./src/docs/preset.ts",
"./src/highlight/preview.ts",
"./src/measure/preview.ts",
"./src/measure/manager.ts",
"./src/outline/preview.ts",
"./src/outline/manager.ts",
"./src/toolbars/manager.ts",
"./src/viewport/manager.ts"
],
"platform": "node"
},

View File

@ -0,0 +1,2 @@
// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762
export * from '@storybook/addon-actions/manager';

View File

@ -0,0 +1,4 @@
/* eslint-disable import/export */
// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered
export * from '@storybook/addon-actions/preview';

View File

@ -0,0 +1,2 @@
// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762
export * from '@storybook/addon-backgrounds/manager';

View File

@ -0,0 +1,4 @@
/* eslint-disable import/export */
// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered
export * from '@storybook/addon-backgrounds/preview';

View File

@ -0,0 +1,2 @@
// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762
export * from '@storybook/addon-controls/manager';

View File

@ -0,0 +1 @@
export * from '@storybook/addon-docs/dist/preset';

View File

@ -0,0 +1 @@
export * from '@storybook/addon-docs/dist/preview';

View File

@ -0,0 +1,4 @@
/* eslint-disable import/export */
// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered
export * from '@storybook/addon-highlight/preview';

View File

@ -1,4 +1,4 @@
import path, { dirname, join } from 'path';
import path from 'path';
import { logger } from '@storybook/node-logger';
import { serverRequire } from '@storybook/core-common';
@ -24,7 +24,8 @@ const requireMain = (configDir: string) => {
};
export function addons(options: PresetOptions) {
const checkInstalled = (addon: string, main: any) => {
const checkInstalled = (addonName: string, main: any) => {
const addon = `@storybook/addon-${addonName}`;
const existingAddon = main.addons?.find((entry: string | { name: string }) => {
const name = typeof entry === 'string' ? entry : entry.name;
return name?.startsWith(addon);
@ -36,35 +37,21 @@ export function addons(options: PresetOptions) {
};
const main = requireMain(options.configDir);
return (
[
'docs',
'controls',
'actions',
'backgrounds',
'viewport',
'toolbars',
'measure',
'outline',
'highlight',
]
.filter((key) => (options as any)[key] !== false)
.map((key) => `@storybook/addon-${key}`)
.filter((addon) => !checkInstalled(addon, main))
// Use `require.resolve` to ensure Yarn PnP compatibility
// Files of various addons should be resolved in the context of `addon-essentials` as they are listed as deps here
// and not in `@storybook/core` nor in SB user projects. If `@storybook/core` make the require itself Yarn 2 will
// throw an error saying that the package to require must be added as a dependency. Doing `require.resolve` will
// allow `@storybook/core` to work with absolute path directly, no more require of dep no more issue.
// File to load can be `preset.js`, `register.js`, or the package entry point, so we need to check all these cases
// as it's done in `lib/core/src/server/presets.js`.
.map((addon) => {
try {
return dirname(require.resolve(join(addon, 'package.json')));
// eslint-disable-next-line no-empty
} catch (err) {}
return require.resolve(addon);
})
);
return [
'docs',
'controls',
'actions',
'backgrounds',
'viewport',
'toolbars',
'measure',
'outline',
'highlight',
]
.filter((key) => (options as any)[key] !== false)
.filter((addon) => !checkInstalled(addon, main))
.map((addon) => {
// We point to the re-export from addon-essentials to support yarn pnp and pnpm.
return `@storybook/addon-essentials/${addon}`;
});
}

View File

@ -0,0 +1,2 @@
// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762
export * from '@storybook/addon-measure/manager';

View File

@ -0,0 +1,4 @@
/* eslint-disable import/export */
// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered
export * from '@storybook/addon-measure/preview';

View File

@ -0,0 +1,2 @@
// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762
export * from '@storybook/addon-outline/manager';

View File

@ -0,0 +1,4 @@
/* eslint-disable import/export */
// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered
export * from '@storybook/addon-outline/preview';

View File

@ -0,0 +1,2 @@
// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762
export * from '@storybook/addon-toolbars/manager';

View File

@ -0,0 +1,2 @@
// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762
export * from '@storybook/addon-viewport/manager';

View File

@ -30,15 +30,25 @@
"types": "./dist/index.d.ts"
},
"./preview": {
"require": "./dist/highlight.js",
"import": "./dist/highlight.mjs",
"types": "./dist/highlight.d.ts"
"require": "./dist/preview.js",
"import": "./dist/preview.mjs",
"types": "./dist/preview.d.ts"
},
"./package.json": "./package.json"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",
@ -64,7 +74,7 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/highlight.ts"
"./src/preview.ts"
]
},
"gitHead": "b58a29b785462f8a8b711b6bb2d7223fd6dc17fd",

View File

@ -1 +1 @@
export * from './dist/highlight';
export * from './dist/preview';

View File

@ -33,9 +33,9 @@
"types": "./dist/manager.d.ts"
},
"./preview": {
"require": "./dist/preset/preview.js",
"import": "./dist/preset/preview.mjs",
"types": "./dist/preset/preview.d.ts"
"require": "./dist/preview.js",
"import": "./dist/preview.mjs",
"types": "./dist/preview.d.ts"
},
"./register.js": {
"require": "./dist/manager.js",
@ -47,6 +47,19 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",
@ -99,7 +112,7 @@
"entries": [
"./src/index.ts",
"./src/manager.tsx",
"./src/preset/preview.ts",
"./src/preview.ts",
"./src/preset/checkActionsLoaded.ts"
],
"platform": "node"

View File

@ -1 +1 @@
export * from './dist/preset/preview';
export * from './dist/preview';

View File

@ -48,6 +48,16 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -52,6 +52,19 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -50,6 +50,19 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -39,9 +39,9 @@
"types": "./dist/manager.d.ts"
},
"./preview": {
"require": "./dist/preset/preview.js",
"import": "./dist/preset/preview.mjs",
"types": "./dist/preset/preview.d.ts"
"require": "./dist/preview.js",
"import": "./dist/preview.mjs",
"types": "./dist/preview.d.ts"
},
"./register": {
"require": "./dist/manager.js",
@ -53,6 +53,19 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",
@ -95,7 +108,7 @@
"entries": [
"./src/index.ts",
"./src/manager.tsx",
"./src/preset/preview.tsx"
"./src/preview.tsx"
]
},
"gitHead": "b58a29b785462f8a8b711b6bb2d7223fd6dc17fd",

View File

@ -1 +1 @@
export * from './dist/preset/preview';
export * from './dist/preview';

View File

@ -1,5 +1,5 @@
import { withOutline } from '../withOutline';
import { PARAM_KEY } from '../constants';
import { withOutline } from './withOutline';
import { PARAM_KEY } from './constants';
export const decorators = [withOutline];

View File

@ -46,6 +46,16 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -48,6 +48,19 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"manager": [
"dist/manager.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",

View File

@ -1,8 +1,13 @@
// exports for builder-vite
import * as clientApi from '@storybook/client-api';
// client-api exposes both a class, and individual named exports.
// The class is used in StoryStoreV7 and the individual exports in SSv6
const { ClientApi } = clientApi;
export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage';
export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket';
export { addons } from '@storybook/addons';
export { composeConfigs, PreviewWeb } from '@storybook/preview-web';
export { ClientApi } from '@storybook/client-api';
export { clientApi, ClientApi };
export type { StorybookConfig } from '@storybook/builder-vite';

View File

@ -1,8 +1,13 @@
// exports for builder-vite
import * as clientApi from '@storybook/client-api';
// client-api exposes both a class, and individual named exports.
// The class is used in StoryStoreV7 and the individual exports in SSv6
const { ClientApi } = clientApi;
export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage';
export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket';
export { addons } from '@storybook/addons';
export { composeConfigs, PreviewWeb } from '@storybook/preview-web';
export { ClientApi } from '@storybook/client-api';
export { clientApi, ClientApi };
export type { StorybookConfig } from '@storybook/builder-vite';

View File

@ -1,8 +1,13 @@
// exports for builder-vite
import * as clientApi from '@storybook/client-api';
// client-api exposes both a class, and individual named exports.
// The class is used in StoryStoreV7 and the individual exports in SSv6
const { ClientApi } = clientApi;
export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage';
export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket';
export { addons } from '@storybook/addons';
export { composeConfigs, PreviewWeb } from '@storybook/preview-web';
export { ClientApi } from '@storybook/client-api';
export { clientApi, ClientApi };
export type { StorybookConfig } from '@storybook/builder-vite';

View File

@ -1,8 +1,13 @@
// exports for builder-vite
import * as clientApi from '@storybook/client-api';
// client-api exposes both a class, and individual named exports.
// The class is used in StoryStoreV7 and the individual exports in SSv6
const { ClientApi } = clientApi;
export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage';
export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket';
export { addons } from '@storybook/addons';
export { composeConfigs, PreviewWeb } from '@storybook/preview-web';
export { ClientApi } from '@storybook/client-api';
export { clientApi, ClientApi };
export type { StorybookConfig } from '@storybook/builder-vite';

View File

@ -1,8 +1,13 @@
// exports for builder-vite
import * as clientApi from '@storybook/client-api';
// client-api exposes both a class, and individual named exports.
// The class is used in StoryStoreV7 and the individual exports in SSv6
const { ClientApi } = clientApi;
export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage';
export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket';
export { addons } from '@storybook/addons';
export { composeConfigs, PreviewWeb } from '@storybook/preview-web';
export { ClientApi } from '@storybook/client-api';
export { clientApi, ClientApi };
export type { StorybookConfig } from '@storybook/builder-vite';

View File

@ -1,22 +1,23 @@
import { isAbsolute, resolve } from 'path';
import { getRendererName } from '@storybook/core-common';
import { getRendererName, getFrameworkName } from '@storybook/core-common';
import type { PreviewAnnotation } from '@storybook/types';
import { virtualPreviewFile, virtualStoriesFile } from './virtual-file-names';
import { transformAbsPath } from './utils/transform-abs-path';
import type { ExtendedOptions } from './types';
import { processPreviewAnnotation } from './utils/process-preview-annotation';
export async function generateIframeScriptCode(options: ExtendedOptions) {
const { presets } = options;
const rendererName = await getRendererName(options);
const previewAnnotations = await presets.apply('previewAnnotations', [], options);
const resolvedPreviewAnnotations = previewAnnotations.map((entry) =>
isAbsolute(entry) ? entry : resolve(entry)
);
const configEntries = [...resolvedPreviewAnnotations].filter(Boolean);
const frameworkName = await getFrameworkName(options);
const absoluteFilesToImport = (files: string[], name: string) =>
files
.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'${transformAbsPath(el)}'`)
.join('\n');
const previewAnnotations = await presets.apply<PreviewAnnotation[]>(
'previewAnnotations',
[],
options
);
const configEntries = [...previewAnnotations].filter(Boolean).map(processPreviewAnnotation);
const filesToImport = (files: string[], name: string) =>
files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'${el}'`).join('\n');
const importArray = (name: string, length: number) =>
new Array(length).fill(0).map((_, i) => `${name}_${i}`);
@ -28,10 +29,8 @@ export async function generateIframeScriptCode(options: ExtendedOptions) {
// Ensure that the client API is initialized by the framework before any other iframe code
// is loaded. That way our client-apis can assume the existence of the API+store
import { configure } from '${rendererName}';
import * as clientApi from "@storybook/client-api";
import { logger } from '@storybook/client-logger';
${absoluteFilesToImport(configEntries, 'config')}
import { clientApi } from '${frameworkName}';
${filesToImport(configEntries, 'config')}
import * as preview from '${virtualPreviewFile}';
import { configStories } from '${virtualStoriesFile}';

View File

@ -1,21 +1,22 @@
import { isAbsolute, resolve } from 'path';
import { loadPreviewOrConfigFile, getFrameworkName } from '@storybook/core-common';
import type { PreviewAnnotation } from '@storybook/types';
import { virtualStoriesFile, virtualAddonSetupFile } from './virtual-file-names';
import { transformAbsPath } from './utils/transform-abs-path';
import type { ExtendedOptions } from './types';
import { processPreviewAnnotation } from './utils/process-preview-annotation';
export async function generateModernIframeScriptCode(options: ExtendedOptions) {
const { presets, configDir } = options;
const frameworkName = await getFrameworkName(options);
const previewOrConfigFile = loadPreviewOrConfigFile({ configDir });
const previewAnnotations = await presets.apply('previewAnnotations', [], options);
const resolvedPreviewAnnotations = [...previewAnnotations].map((entry) =>
isAbsolute(entry) ? entry : resolve(entry)
const previewAnnotations = await presets.apply<PreviewAnnotation[]>(
'previewAnnotations',
[],
options
);
const relativePreviewAnnotations = [...resolvedPreviewAnnotations, previewOrConfigFile]
const relativePreviewAnnotations = [...previewAnnotations, previewOrConfigFile]
.filter(Boolean)
.map((configEntry) => transformAbsPath(configEntry as string));
.map(processPreviewAnnotation);
// eslint-disable-next-line @typescript-eslint/no-shadow
const generateHMRHandler = (frameworkName: string): string => {

View File

@ -0,0 +1,33 @@
import type { PreviewAnnotation } from '@storybook/types';
import { resolve } from 'path';
/**
* Preview annotations can take several forms, and vite needs them to be
* a bit more restrained.
*
* For node_modules, we want bare imports (so vite can process them),
* and for files in the user's source,
* we want absolute paths.
*/
export function processPreviewAnnotation(path: PreviewAnnotation | undefined) {
// If entry is an object, take the first, which is the
// bare (non-absolute) specifier.
// This is so that webpack can use an absolute path, and
// continue supporting super-addons in pnp/pnpm without
// requiring them to re-export their sub-addons as we do
// in addon-essentials.
if (typeof path === 'object') {
return path.bare;
}
// resolve relative paths into absolute paths, but don't resolve "bare" imports
if (path?.startsWith('./') || path?.startsWith('../')) {
return resolve(path);
}
// This should not occur, since we use `.filter(Boolean)` prior to
// calling this function, but this makes typescript happy
if (!path) {
throw new Error('Could not determine path for previewAnnotation');
}
return path;
}

View File

@ -1,11 +0,0 @@
import path from 'path';
import { normalizePath } from 'vite';
// We need to convert from an absolute path, to a traditional node module import path,
// so that vite can correctly pre-bundle/optimize
export function transformAbsPath(absPath: string) {
const splits = absPath.split(`node_modules${path.sep}`);
// Return everything after the final "node_modules/"
const module = normalizePath(splits[splits.length - 1]);
return module;
}

View File

@ -25,15 +25,15 @@
"import": "./dist/index.mjs",
"types": "./dist/index.d.ts"
},
"./presets/custom-webpack-preset.js": {
"require": "./presets/custom-webpack-preset.js",
"import": "./presets/custom-webpack-preset.mjs",
"types": "./presets/custom-webpack-preset.d.ts"
"./presets/custom-webpack-preset": {
"require": "./dist/presets/custom-webpack-preset.js",
"import": "./dist/presets/custom-webpack-preset.mjs",
"types": "./dist/presets/custom-webpack-preset.d.ts"
},
"./presets/preview-preset.js": {
"require": "./presets/preview-preset.js",
"import": "./presets/preview-preset.mjs",
"types": "./presets/preview-preset.d.ts"
"./presets/preview-preset": {
"require": "./dist/presets/preview-preset.js",
"import": "./dist/presets/preview-preset.mjs",
"types": "./dist/presets/preview-preset.d.ts"
},
"./templates/virtualModuleModernEntry.js.handlebars": "./templates/virtualModuleModernEntry.js.handlebars",
"./package.json": "./package.json"

View File

@ -7,7 +7,7 @@ import TerserWebpackPlugin from 'terser-webpack-plugin';
import VirtualModulePlugin from 'webpack-virtual-modules';
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
import type { Options, CoreConfig, DocsOptions } from '@storybook/types';
import type { Options, CoreConfig, DocsOptions, PreviewAnnotation } from '@storybook/types';
import {
getRendererName,
stringifyProcessEnvs,
@ -82,7 +82,18 @@ export default async (
const docsOptions = await presets.apply<DocsOptions>('docs');
const previewAnnotations = [
...(await presets.apply('previewAnnotations', [], options)),
...(await presets.apply<PreviewAnnotation[]>('previewAnnotations', [], options)).map(
(entry) => {
// If entry is an object, use the absolute import specifier.
// This is to maintain back-compat with community addons that bundle other addons
// and package managers that "hide" sub dependencies (e.g. pnpm / yarn pnp)
// The vite builder uses the bare import specifier.
if (typeof entry === 'object') {
return entry.absolute;
}
return entry;
}
),
loadPreviewOrConfigFile(options),
].filter(Boolean);
const entries = (await presets.apply('entries', [], options)) as string[];

View File

@ -1,6 +1,5 @@
import { dedent } from 'ts-dedent';
import { logger } from '@storybook/node-logger';
import { dirname } from 'path';
import type {
BuilderOptions,
CLIOptions,
@ -82,35 +81,26 @@ export const resolveAddonName = (
}
}
const absolutePackageJson = resolved && resolve(`${name}/package.json`);
// We want to absolutize the package name part to a path on disk
// (i.e. '/Users/foo/.../node_modules/@addons/foo') as otherwise
// we may not be able to import the package in certain module systems (eg. pnpm, yarn pnp)
const absoluteDir = absolutePackageJson && dirname(absolutePackageJson);
// If the package has an export (e.g. `/preview`), absolutize it, eg. to
// /Users/foo/.../node_modules/@addons/foo/preview
// NOTE: this looks like the path of an absolute file, but it DOES NOT exist.
// - However it is importable by webpack.
// - Vite needs to strip off the absolute part to import it though
// (vite cannot import absolute files: https://github.com/vitejs/vite/issues/5494
// this also means vite suffers issues with pnpm etc)
const absolutizeExport = (exportName: string) => {
if (resolve(`${name}${exportName}`)) return `${absoluteDir}${exportName}`;
const checkExists = (exportName: string) => {
if (resolve(`${name}${exportName}`)) return `${name}${exportName}`;
return undefined;
};
const path = name;
// This is used to maintain back-compat with community addons that do not
// re-export their sub-addons but reference the sub-addon name directly.
// We need to turn it into an absolute path so that webpack can
// serve it up correctly when yarn pnp or pnpm is being used.
// Vite will be broken in such cases, because it does not process absolute paths,
// and it will try to import from the bare import, breaking in pnp/pnpm.
const absolutizeExport = (exportName: string) => {
return resolve(`${name}${exportName}`);
};
// We don't want to resolve an import path (e.g. '@addons/foo/preview') to the file on disk,
// because you are not allowed to import arbitrary files in packages in Vite.
// Instead we check if the export exists and "absolutize" it.
const managerFile = absolutizeExport(`/manager`);
const registerFile = absolutizeExport(`/register`) || absolutizeExport(`/register-panel`);
const previewFile = absolutizeExport(`/preview`);
// Presets are imported by node, so therefore fine to be a path on disk (at this stage anyway)
const presetFile = resolve(`${path}/preset`);
const previewFile = checkExists(`/preview`);
const previewFileAbsolute = absolutizeExport('/preview');
const presetFile = absolutizeExport(`/preset`);
if (!(managerFile || previewFile) && presetFile) {
return {
@ -132,9 +122,17 @@ export const resolveAddonName = (
return {
type: 'virtual',
name: path,
name,
...(managerEntries.length ? { managerEntries } : {}),
...(previewFile ? { previewAnnotations: [previewFile] } : {}),
...(previewFile
? {
previewAnnotations: [
previewFileAbsolute
? { bare: previewFile, absolute: previewFileAbsolute }
: previewFile,
],
}
: {}),
...(presetFile ? { presets: [{ name: presetFile, options }] } : {}),
};
}
@ -233,7 +231,6 @@ export async function loadPreset(
logger.warn(warning);
logger.error(e);
return [];
}
}

View File

@ -1,7 +1,7 @@
import type { Options } from '@storybook/types';
// `addons/x` is for the monorepo, `addon-x` is for normal usage
const packageRe = /(addons\/|addon-)(docs|controls)/;
const packageRe = /(addons\/|addon-|addon-essentials\/)(docs|controls)/;
export const hasDocsOrControls = (options: Options) =>
options.presetsList?.some((preset) => packageRe.test(preset.name));

View File

@ -462,11 +462,13 @@ export interface CoreCommon_ResolvedAddonPreset {
name: string;
}
export type PreviewAnnotation = string | { bare: string; absolute: string };
export interface CoreCommon_ResolvedAddonVirtual {
type: 'virtual';
name: string;
managerEntries?: string[];
previewAnnotations?: string[];
previewAnnotations?: PreviewAnnotation[];
presets?: (string | { name: string; options?: any })[];
}