@modern-js/storybook-builder 0.0.0-next-20230913035856

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.eslintrc.js +7 -0
  2. package/.turbo/turbo-build.log +6 -0
  3. package/CHANGELOG.md +24 -0
  4. package/LICENSE +21 -0
  5. package/dist/cjs/addons/components/modern.js +65 -0
  6. package/dist/cjs/addons/constants.js +11 -0
  7. package/dist/cjs/addons/index.js +20 -0
  8. package/dist/cjs/addons/preset/preview.js +14 -0
  9. package/dist/cjs/addons/type.js +4 -0
  10. package/dist/cjs/addons/withPluginRuntime.js +20 -0
  11. package/dist/cjs/build.js +109 -0
  12. package/dist/cjs/core.js +40 -0
  13. package/dist/cjs/docgen/actualNameHandler.js +34 -0
  14. package/dist/cjs/docgen/index.js +74 -0
  15. package/dist/cjs/docgen/loader.js +37 -0
  16. package/dist/cjs/docgen/process.js +39 -0
  17. package/dist/cjs/index.js +35 -0
  18. package/dist/cjs/plugin-storybook.js +316 -0
  19. package/dist/cjs/preset.js +61 -0
  20. package/dist/cjs/types.js +11 -0
  21. package/dist/cjs/utils.js +142 -0
  22. package/dist/esm/addons/components/modern.js +44 -0
  23. package/dist/esm/addons/constants.js +1 -0
  24. package/dist/esm/addons/index.js +5 -0
  25. package/dist/esm/addons/preset/preview.js +4 -0
  26. package/dist/esm/addons/type.js +1 -0
  27. package/dist/esm/addons/withPluginRuntime.js +10 -0
  28. package/dist/esm/build.js +83 -0
  29. package/dist/esm/core.js +30 -0
  30. package/dist/esm/docgen/actualNameHandler.js +24 -0
  31. package/dist/esm/docgen/index.js +54 -0
  32. package/dist/esm/docgen/loader.js +26 -0
  33. package/dist/esm/docgen/process.js +28 -0
  34. package/dist/esm/index.js +6 -0
  35. package/dist/esm/plugin-storybook.js +296 -0
  36. package/dist/esm/preset.js +36 -0
  37. package/dist/esm/types.js +1 -0
  38. package/dist/esm/utils.js +95 -0
  39. package/dist/types/addons/components/modern.d.ts +5 -0
  40. package/dist/types/addons/constants.d.ts +1 -0
  41. package/dist/types/addons/index.d.ts +2 -0
  42. package/dist/types/addons/preset/preview.d.ts +1 -0
  43. package/dist/types/addons/type.d.ts +4 -0
  44. package/dist/types/addons/withPluginRuntime.d.ts +2 -0
  45. package/dist/types/build.d.ts +7 -0
  46. package/dist/types/core.d.ts +4 -0
  47. package/dist/types/docgen/actualNameHandler.d.ts +14 -0
  48. package/dist/types/docgen/index.d.ts +9 -0
  49. package/dist/types/docgen/loader.d.ts +2 -0
  50. package/dist/types/docgen/process.d.ts +10 -0
  51. package/dist/types/index.d.ts +3 -0
  52. package/dist/types/plugin-storybook.d.ts +6 -0
  53. package/dist/types/preset.d.ts +6 -0
  54. package/dist/types/types.d.ts +15 -0
  55. package/dist/types/utils.d.ts +12 -0
  56. package/index.js +24 -0
  57. package/modern.config.js +5 -0
  58. package/package.json +96 -0
  59. package/src/addons/components/modern.tsx +52 -0
  60. package/src/addons/constants.ts +1 -0
  61. package/src/addons/index.ts +8 -0
  62. package/src/addons/preset/preview.ts +3 -0
  63. package/src/addons/type.ts +4 -0
  64. package/src/addons/withPluginRuntime.ts +18 -0
  65. package/src/build.ts +119 -0
  66. package/src/core.ts +51 -0
  67. package/src/docgen/actualNameHandler.ts +57 -0
  68. package/src/docgen/index.ts +100 -0
  69. package/src/docgen/loader.ts +34 -0
  70. package/src/docgen/process.ts +44 -0
  71. package/src/index.ts +7 -0
  72. package/src/plugin-storybook.ts +462 -0
  73. package/src/preset.ts +59 -0
  74. package/src/types.ts +21 -0
  75. package/src/utils.ts +131 -0
  76. package/templates/preview.ejs +54 -0
  77. package/templates/virtualModuleModernEntry.js.handlebars +43 -0
  78. package/tsconfig.json +16 -0
@@ -0,0 +1,30 @@
1
+ import { createBuilder, mergeBuilderConfig } from "@modern-js/builder";
2
+ import { loadConfig } from "@modern-js/core";
3
+ import { getProvider, runWithErrorMsg } from "./utils";
4
+ import { pluginStorybook } from "./plugin-storybook";
5
+ export async function getCompiler(cwd, frameworkConfig, options) {
6
+ const bundler = frameworkConfig.bundler || "webpack";
7
+ const { presets } = options;
8
+ const entries = await presets.apply("entries", []);
9
+ const res = await runWithErrorMsg(() => loadConfig(cwd, frameworkConfig.configPath || "modern.config.ts"), "Failed to load config");
10
+ const loadedConfig = res ? res.config : {};
11
+ const otherBuilderConfig = await presets.apply("modern", loadedConfig) || {};
12
+ const builderConfig = mergeBuilderConfig(otherBuilderConfig, loadedConfig);
13
+ const provider = await getProvider(bundler, builderConfig);
14
+ if (!provider) {
15
+ throw new Error(`@modern-js/builder-${bundler}-provider not found `);
16
+ }
17
+ const builder = await createBuilder(provider, {
18
+ cwd,
19
+ target: "web",
20
+ framework: "modern.js storybook",
21
+ entry: {
22
+ main: entries
23
+ }
24
+ });
25
+ builder.addPlugins([
26
+ pluginStorybook(cwd, options),
27
+ ...loadedConfig.builderPlugins || []
28
+ ]);
29
+ return builder.createCompiler();
30
+ }
@@ -0,0 +1,24 @@
1
+ import { namedTypes as t } from "ast-types";
2
+ import { getNameOrValue, isReactForwardRefCall } from "react-docgen/dist/utils";
3
+ export default function actualNameHandler(documentation, path, importer) {
4
+ if (t.ClassDeclaration.check(path.node) || t.FunctionDeclaration.check(path.node)) {
5
+ documentation.set("actualName", getNameOrValue(path.get("id")));
6
+ } else if (t.ArrowFunctionExpression.check(path.node) || t.FunctionExpression.check(path.node) || isReactForwardRefCall(path, importer)) {
7
+ let currentPath = path;
8
+ while (currentPath.parent) {
9
+ if (t.VariableDeclarator.check(currentPath.parent.node)) {
10
+ documentation.set("actualName", getNameOrValue(currentPath.parent.get("id")));
11
+ return;
12
+ }
13
+ if (t.AssignmentExpression.check(currentPath.parent.node)) {
14
+ const leftPath = currentPath.parent.get("left");
15
+ if (t.Identifier.check(leftPath.node) || t.Literal.check(leftPath.node)) {
16
+ documentation.set("actualName", getNameOrValue(leftPath));
17
+ return;
18
+ }
19
+ }
20
+ currentPath = currentPath.parent;
21
+ }
22
+ documentation.set("actualName", "");
23
+ }
24
+ }
@@ -0,0 +1,54 @@
1
+ import { CHAIN_ID, logger } from "@modern-js/utils";
2
+ export async function applyDocgenWebpack(chain, options) {
3
+ const typescriptOptions = await options.presets.apply("typescript", {});
4
+ const { reactDocgen, reactDocgenTypescriptOptions } = typescriptOptions || {};
5
+ if (typeof reactDocgen !== "string") {
6
+ return;
7
+ }
8
+ if (reactDocgen === "react-docgen-typescript") {
9
+ const { ReactDocgenTypeScriptPlugin } = await import("@storybook/react-docgen-typescript-plugin");
10
+ chain.plugin("Storybook-docgen").use(ReactDocgenTypeScriptPlugin, [
11
+ {
12
+ ...reactDocgenTypescriptOptions,
13
+ savePropValueAsString: true
14
+ }
15
+ ]);
16
+ } else if (reactDocgen === "react-docgen") {
17
+ const loader = require.resolve("./loader");
18
+ const resolveOptions = chain.toConfig().resolve;
19
+ chain.module.rule(CHAIN_ID.RULE.JS).use(CHAIN_ID.USE.REACT_DOCGEN).loader(loader).options({
20
+ resolveOptions
21
+ }).after(CHAIN_ID.USE.BABEL).after(CHAIN_ID.USE.ESBUILD).after(CHAIN_ID.USE.SWC).end();
22
+ const tsRuls = chain.module.rule(CHAIN_ID.RULE.TS);
23
+ if (tsRuls.uses.values().length !== 0) {
24
+ tsRuls.use(CHAIN_ID.USE.REACT_DOCGEN).loader(loader).options({
25
+ resolveOptions
26
+ }).after(CHAIN_ID.USE.TS).after(CHAIN_ID.USE.ESBUILD).after(CHAIN_ID.USE.SWC).end();
27
+ }
28
+ }
29
+ }
30
+ export async function applyDocgenRspack(config, options) {
31
+ var _config, _config_module;
32
+ const typescriptOptions = await options.presets.apply("typescript", {});
33
+ const { reactDocgen } = typescriptOptions || {};
34
+ if (reactDocgen !== "react-docgen") {
35
+ if (reactDocgen !== false && reactDocgen !== void 0) {
36
+ logger.warn(`Rspack currently only support 'typescript.reactDocgen: react-docgen' for auto docs generation, but you specified ${reactDocgen}`);
37
+ }
38
+ return;
39
+ }
40
+ var _module;
41
+ (_module = (_config = config).module) !== null && _module !== void 0 ? _module : _config.module = {};
42
+ var _rules;
43
+ (_rules = (_config_module = config.module).rules) !== null && _rules !== void 0 ? _rules : _config_module.rules = [];
44
+ config.module.rules.push({
45
+ test: /\.(tsx?|jsx?)$/,
46
+ exclude: /node_modules/,
47
+ use: {
48
+ loader: require.resolve("./loader"),
49
+ options: {
50
+ resolveOptions: config.resolve
51
+ }
52
+ }
53
+ });
54
+ }
@@ -0,0 +1,26 @@
1
+ let tinyPoolPromise = null;
2
+ async function docLoader(source, map, data) {
3
+ const callback = this.async();
4
+ if (!tinyPoolPromise) {
5
+ tinyPoolPromise = import("tinypool").then(({ Tinypool }) => {
6
+ return new Tinypool({
7
+ filename: require.resolve("./process")
8
+ });
9
+ });
10
+ }
11
+ const tinyPool = await tinyPoolPromise;
12
+ const result = await tinyPool.run({
13
+ source,
14
+ map,
15
+ filename: this.resourcePath,
16
+ data
17
+ });
18
+ if (result) {
19
+ const [docgen, outputMap] = result;
20
+ callback(null, `${source}
21
+ ${docgen}`, outputMap, data);
22
+ } else {
23
+ callback(null, source, map, data);
24
+ }
25
+ }
26
+ export default docLoader;
@@ -0,0 +1,28 @@
1
+ import { importers, resolver, handlers, parse } from "react-docgen";
2
+ import actualNameHandler from "./actualNameHandler";
3
+ const defaultHandlers = Object.values(handlers).map((handler) => handler);
4
+ const importer = importers.makeFsImporter();
5
+ export default ({ source, map, filename }) => {
6
+ try {
7
+ const results = parse(source, resolver.findAllExportedComponentDefinitions, [
8
+ ...defaultHandlers,
9
+ actualNameHandler
10
+ ], {
11
+ filename,
12
+ importer
13
+ });
14
+ const docgen = results.map((result) => {
15
+ const { actualName, ...docgenInfo } = result;
16
+ if (actualName) {
17
+ return `${actualName}.__docgenInfo=${JSON.stringify(docgenInfo)}`;
18
+ }
19
+ return "";
20
+ }).filter(Boolean).join(";");
21
+ return [
22
+ docgen,
23
+ map
24
+ ];
25
+ } catch (e) {
26
+ return null;
27
+ }
28
+ };
@@ -0,0 +1,6 @@
1
+ import { join } from "path";
2
+ export { start, build, bail, getConfig } from "./build";
3
+ export * from "./types";
4
+ export const corePresets = [
5
+ join(__dirname, "./preset.js")
6
+ ];
@@ -0,0 +1,296 @@
1
+ import { isAbsolute, join, resolve } from "path";
2
+ import { slash, watch, globby } from "@modern-js/utils";
3
+ import { mergeBuilderConfig } from "@modern-js/builder-shared";
4
+ import { normalizeStories, stringifyProcessEnvs, handlebars, readTemplate, loadPreviewOrConfigFile } from "@storybook/core-common";
5
+ import { globals } from "@storybook/preview/globals";
6
+ import { unplugin as csfPlugin } from "@storybook/csf-plugin";
7
+ import { minimatch } from "minimatch";
8
+ import { toImportFn, virtualModule, maybeGetAbsolutePath } from "./utils";
9
+ import { applyDocgenRspack, applyDocgenWebpack } from "./docgen";
10
+ const STORIES_FILENAME = "storybook-stories.js";
11
+ const STORYBOOK_CONFIG_ENTRY = "storybook-config-entry.js";
12
+ const closeFn = [];
13
+ const onClose = (f) => {
14
+ closeFn.push(f);
15
+ };
16
+ export async function finalize() {
17
+ await Promise.all([
18
+ closeFn.map((close) => close())
19
+ ]);
20
+ }
21
+ export const pluginStorybook = (cwd, options) => {
22
+ return {
23
+ name: "builder-plugin-storybook",
24
+ remove: [
25
+ "builder-plugin-inline"
26
+ ],
27
+ async setup(api) {
28
+ const matchers = await options.presets.apply("stories", [], options);
29
+ const storyPatterns = normalizeStories(matchers, {
30
+ configDir: options.configDir,
31
+ workingDir: options.configDir
32
+ }).map(({ directory, files }) => {
33
+ const pattern = join(directory, files);
34
+ const absolutePattern = isAbsolute(pattern) ? pattern : join(options.configDir, pattern);
35
+ return absolutePattern;
36
+ });
37
+ api.modifyBuilderConfig(async (builderConfig) => {
38
+ await prepareStorybookModules(api.context.cachePath, cwd, options, builderConfig, storyPatterns);
39
+ await applyDefines(builderConfig, options);
40
+ await applyHTML(builderConfig, options);
41
+ await applyReact(builderConfig, options);
42
+ applyExternals(builderConfig);
43
+ });
44
+ const modifyConfig = async (config) => {
45
+ var _config;
46
+ var _resolve;
47
+ (_resolve = (_config = config).resolve) !== null && _resolve !== void 0 ? _resolve : _config.resolve = {};
48
+ config.resolve.conditionNames = [
49
+ "require",
50
+ "node",
51
+ ...config.resolve.conditionNames || []
52
+ ];
53
+ config.resolve.fullySpecified = false;
54
+ await applyMdxLoader(config, options);
55
+ await applyCsfPlugin(config, options);
56
+ };
57
+ if ("modifyWebpackConfig" in api) {
58
+ api.modifyWebpackConfig(modifyConfig);
59
+ api.modifyWebpackChain(async (chain) => {
60
+ await applyDocgenWebpack(chain, options);
61
+ });
62
+ } else if ("modifyRspackConfig" in api) {
63
+ api.modifyRspackConfig(async (config) => {
64
+ await modifyConfig(config);
65
+ await applyDocgenRspack(config, options);
66
+ });
67
+ }
68
+ }
69
+ };
70
+ };
71
+ async function applyCsfPlugin(config, options) {
72
+ var _addons_find;
73
+ var _config;
74
+ const { presets } = options;
75
+ const addons = await presets.apply("addons", []);
76
+ const { options: { bundler } } = await presets.apply("frameworkOptions");
77
+ var _addons_find_options;
78
+ const docsOptions = (_addons_find_options = (_addons_find = addons.find((a) => [
79
+ a,
80
+ a.name
81
+ ].includes("@storybook/addon-docs"))) === null || _addons_find === void 0 ? void 0 : _addons_find.options) !== null && _addons_find_options !== void 0 ? _addons_find_options : {};
82
+ var _plugins;
83
+ (_plugins = (_config = config).plugins) !== null && _plugins !== void 0 ? _plugins : _config.plugins = [];
84
+ config.plugins.push(bundler === "rspack" ? csfPlugin.rspack(docsOptions) : csfPlugin.webpack(docsOptions));
85
+ }
86
+ async function prepareStorybookModules(tempDir, cwd, options, builderConfig, storyPatterns) {
87
+ var _builderConfig;
88
+ const mappings = await createStorybookModules(cwd, options, storyPatterns);
89
+ const componentsPath = maybeGetAbsolutePath(`@storybook/components`);
90
+ const routerPath = maybeGetAbsolutePath(`@storybook/router`);
91
+ const themingPath = maybeGetAbsolutePath(`@storybook/theming`);
92
+ const storybookPaths = {
93
+ ...componentsPath ? {
94
+ [`@storybook/components`]: componentsPath
95
+ } : {},
96
+ ...routerPath ? {
97
+ [`@storybook/router`]: routerPath
98
+ } : {},
99
+ ...themingPath ? {
100
+ [`@storybook/theming`]: themingPath
101
+ } : {}
102
+ };
103
+ const [mappingsAlias, write] = await virtualModule(tempDir, cwd, mappings);
104
+ var _source;
105
+ (_source = (_builderConfig = builderConfig).source) !== null && _source !== void 0 ? _source : _builderConfig.source = {};
106
+ builderConfig.source.alias = {
107
+ ...builderConfig.source.alias,
108
+ ...storybookPaths,
109
+ ...mappingsAlias
110
+ };
111
+ const watcher = await watchStories(storyPatterns, cwd, write);
112
+ onClose(async () => {
113
+ await watcher.close();
114
+ });
115
+ }
116
+ async function applyDefines(builderConfig, options) {
117
+ var _builderConfig;
118
+ const { presets } = options;
119
+ const envs = await presets.apply("env");
120
+ var _source;
121
+ (_source = (_builderConfig = builderConfig).source) !== null && _source !== void 0 ? _source : _builderConfig.source = {};
122
+ builderConfig.source.define = {
123
+ ...builderConfig.source.define,
124
+ ...stringifyProcessEnvs(envs),
125
+ "process.env": JSON.stringify(envs),
126
+ NODE_ENV: JSON.stringify(process.env.NODE_ENV)
127
+ };
128
+ }
129
+ async function applyHTML(builderConfig, options) {
130
+ var _builderConfig;
131
+ const { presets, packageJson, configType, features, previewUrl, serverChannelUrl } = options;
132
+ const [coreOptions, frameworkOptions, logLevel, headHtmlSnippet, bodyHtmlSnippet, template, docsOptions] = await Promise.all([
133
+ presets.apply("core"),
134
+ presets.apply("frameworkOptions"),
135
+ presets.apply("logLevel", void 0),
136
+ presets.apply("previewHead"),
137
+ presets.apply("previewBody"),
138
+ presets.apply("previewMainTemplate"),
139
+ presets.apply("docs")
140
+ ]);
141
+ var _tools;
142
+ (_tools = (_builderConfig = builderConfig).tools) !== null && _tools !== void 0 ? _tools : _builderConfig.tools = {};
143
+ builderConfig.tools.htmlPlugin = {
144
+ ...builderConfig.tools.htmlPlugin,
145
+ template,
146
+ filename: "iframe.html",
147
+ templateParameters: {
148
+ ...builderConfig.tools.htmlPlugin ? builderConfig.tools.htmlPlugin.templateParameters || {} : {},
149
+ version: packageJson.version || "",
150
+ globals: {
151
+ CONFIG_TYPE: configType,
152
+ LOGLEVEL: logLevel,
153
+ FRAMEWORK_OPTIONS: frameworkOptions,
154
+ CHANNEL_OPTIONS: coreOptions.channelOptions,
155
+ FEATURES: features,
156
+ PREVIEW_URL: previewUrl,
157
+ DOCS_OPTIONS: docsOptions,
158
+ SERVER_CHANNEL_URL: serverChannelUrl
159
+ },
160
+ headHtmlSnippet,
161
+ bodyHtmlSnippet
162
+ },
163
+ inject: false
164
+ };
165
+ }
166
+ async function applyMdxLoader(config, options) {
167
+ var _mdxPluginOptions, _mdxPluginOptions_mdxCompileOptions, _mdxPluginOptions1, _options_features;
168
+ var _config, _config_module;
169
+ const { presets, mdxPluginOptions } = options;
170
+ const remarkExternalLinks = await import("remark-external-links");
171
+ const remarkSlug = await import("remark-slug");
172
+ var _mdxPluginOptions_mdxCompileOptions_remarkPlugins;
173
+ const mdxLoaderOptions = await presets.apply("mdxLoaderOptions", {
174
+ skipCsf: true,
175
+ mdxCompileOptions: {
176
+ providerImportSource: "@storybook/addon-docs/mdx-react-shim",
177
+ ...(_mdxPluginOptions = mdxPluginOptions) === null || _mdxPluginOptions === void 0 ? void 0 : _mdxPluginOptions.mdxCompileOptions,
178
+ remarkPlugins: [
179
+ remarkSlug,
180
+ remarkExternalLinks,
181
+ ...(_mdxPluginOptions_mdxCompileOptions_remarkPlugins = (_mdxPluginOptions1 = mdxPluginOptions) === null || _mdxPluginOptions1 === void 0 ? void 0 : (_mdxPluginOptions_mdxCompileOptions = _mdxPluginOptions1.mdxCompileOptions) === null || _mdxPluginOptions_mdxCompileOptions === void 0 ? void 0 : _mdxPluginOptions_mdxCompileOptions.remarkPlugins) !== null && _mdxPluginOptions_mdxCompileOptions_remarkPlugins !== void 0 ? _mdxPluginOptions_mdxCompileOptions_remarkPlugins : []
182
+ ]
183
+ }
184
+ });
185
+ const mdxLoader = ((_options_features = options.features) === null || _options_features === void 0 ? void 0 : _options_features.legacyMdx1) ? require.resolve("@storybook/mdx1-csf/loader") : require.resolve("@storybook/mdx2-csf/loader");
186
+ var _module;
187
+ (_module = (_config = config).module) !== null && _module !== void 0 ? _module : _config.module = {};
188
+ var _rules;
189
+ (_rules = (_config_module = config.module).rules) !== null && _rules !== void 0 ? _rules : _config_module.rules = [];
190
+ config.module.rules.push({
191
+ test: /(stories|story)\.mdx$/,
192
+ use: [
193
+ {
194
+ loader: mdxLoader,
195
+ options: {
196
+ ...mdxLoaderOptions,
197
+ skipCsf: false
198
+ }
199
+ }
200
+ ]
201
+ }, {
202
+ test: /\.mdx$/,
203
+ exclude: /(stories|story)\.mdx$/,
204
+ use: [
205
+ {
206
+ loader: mdxLoader,
207
+ options: mdxLoaderOptions
208
+ }
209
+ ]
210
+ });
211
+ }
212
+ function applyExternals(builderConfig) {
213
+ var _builderConfig_output;
214
+ const config = mergeBuilderConfig({
215
+ output: {
216
+ externals: (_builderConfig_output = builderConfig.output) === null || _builderConfig_output === void 0 ? void 0 : _builderConfig_output.externals
217
+ }
218
+ }, {
219
+ output: {
220
+ externals: globals
221
+ }
222
+ });
223
+ builderConfig.output = config.output;
224
+ }
225
+ function getStoriesEntryPath(cwd) {
226
+ return resolve(join(cwd, STORIES_FILENAME));
227
+ }
228
+ function getStoriesConfigPath(cwd) {
229
+ return resolve(join(cwd, STORYBOOK_CONFIG_ENTRY));
230
+ }
231
+ async function createStorybookModules(cwd, options, storyPatterns) {
232
+ const virtualModuleMappings = {};
233
+ const { presets } = options;
234
+ const storiesEntry = await createStoriesEntry(cwd, storyPatterns);
235
+ virtualModuleMappings[getStoriesEntryPath(cwd)] = storiesEntry;
236
+ const configEntryPath = getStoriesConfigPath(cwd);
237
+ const previewAnnotations = [
238
+ ...(await presets.apply("previewAnnotations", [], options)).map((entry) => {
239
+ if (typeof entry === "object") {
240
+ return entry.absolute;
241
+ }
242
+ return resolve(cwd, slash(entry));
243
+ }),
244
+ loadPreviewOrConfigFile(options)
245
+ ].filter(Boolean);
246
+ virtualModuleMappings[configEntryPath] = handlebars(await readTemplate(require.resolve("@modern-js/storybook-builder/templates/virtualModuleModernEntry.js.handlebars")), {
247
+ storiesFilename: STORIES_FILENAME,
248
+ previewAnnotations
249
+ }).replace(/\\/g, "\\\\");
250
+ return virtualModuleMappings;
251
+ }
252
+ async function createStoriesEntry(cwd, storyPatterns) {
253
+ const stories = (await Promise.all(storyPatterns.map((pattern) => {
254
+ return globby(slash(pattern), {
255
+ followSymbolicLinks: true
256
+ });
257
+ }))).reduce((carry, stories2) => carry.concat(stories2), []);
258
+ return await toImportFn(cwd, stories);
259
+ }
260
+ async function applyReact(config, options) {
261
+ let version = "18.0.0";
262
+ try {
263
+ ({ version } = await import("react-dom/package.json"));
264
+ } catch (_) {
265
+ }
266
+ const { legacyRootApi } = await options.presets.apply("frameworkOptions") || {};
267
+ const isReact18 = version.startsWith("18") || version.startsWith("0.0.0");
268
+ const useReact17 = legacyRootApi !== null && legacyRootApi !== void 0 ? legacyRootApi : !isReact18;
269
+ if (!useReact17) {
270
+ var _config, _config_source;
271
+ var _source;
272
+ (_source = (_config = config).source) !== null && _source !== void 0 ? _source : _config.source = {};
273
+ var _alias;
274
+ (_alias = (_config_source = config.source).alias) !== null && _alias !== void 0 ? _alias : _config_source.alias = {};
275
+ config.source.alias["@storybook/react-dom-shim"] = "@storybook/react-dom-shim/dist/react-18";
276
+ }
277
+ }
278
+ async function watchStories(patterns, cwd, writeModule) {
279
+ const watcher = watch(cwd, async ({ changeType, changedFilePath }) => {
280
+ if (changeType !== "add" && changeType !== "unlink") {
281
+ return;
282
+ }
283
+ if (patterns.some((entry) => minimatch(changedFilePath, entry))) {
284
+ const stories = (await Promise.all(patterns.map((pattern) => {
285
+ return globby(slash(pattern), {
286
+ followSymbolicLinks: true
287
+ });
288
+ }))).reduce((carry, stories2) => carry.concat(stories2), []);
289
+ const newStories = await toImportFn(cwd, stories);
290
+ writeModule(getStoriesEntryPath(cwd), newStories);
291
+ }
292
+ }, [
293
+ /node_modules/
294
+ ]);
295
+ return watcher;
296
+ }
@@ -0,0 +1,36 @@
1
+ import { join, resolve } from "path";
2
+ import { getConfig } from "./build";
3
+ import { STORYBOOK_CONFIG_ENTRY } from "./utils";
4
+ export const previewMainTemplate = () => {
5
+ return require.resolve("@modern-js/storybook-builder/templates/preview.ejs");
6
+ };
7
+ function getStoriesConfigPath(cwd) {
8
+ return resolve(join(cwd, STORYBOOK_CONFIG_ENTRY));
9
+ }
10
+ export const entries = async (_, options) => {
11
+ const result = [];
12
+ const { bundler } = await getConfig(options);
13
+ if (options.configType === "DEVELOPMENT") {
14
+ result.push(...[
15
+ `${require.resolve("webpack-hot-middleware/client")}?reload=true&quiet=false&noInfo=${options.quiet}`,
16
+ bundler === "rspack" ? require.resolve("@rspack/dev-client/react-refresh-entry") : null
17
+ ].filter(Boolean));
18
+ }
19
+ result.push(getStoriesConfigPath(process.cwd()));
20
+ return result;
21
+ };
22
+ export const modern = (builderConfig, options) => {
23
+ var _builderConfig_output;
24
+ return {
25
+ ...builderConfig,
26
+ output: {
27
+ ...builderConfig.output,
28
+ disableInlineRuntimeChunk: true,
29
+ distPath: {
30
+ ...(_builderConfig_output = builderConfig.output) === null || _builderConfig_output === void 0 ? void 0 : _builderConfig_output.distPath,
31
+ root: options.outputDir
32
+ }
33
+ }
34
+ };
35
+ };
36
+ export { decorators } from "./addons/preset/preview";
@@ -0,0 +1 @@
1
+ export { defineConfig } from "@modern-js/builder/cli";
@@ -0,0 +1,95 @@
1
+ import path, { dirname, join } from "path";
2
+ import { createRequire } from "node:module";
3
+ import { fs, logger } from "@modern-js/utils";
4
+ export const VIRTUAL_MODULE_BASE = ".MODERN_STORYBOOK";
5
+ export const STORIES_FILENAME = "storybook-stories.js";
6
+ export const STORYBOOK_CONFIG_ENTRY = "storybook-config-entry.js";
7
+ export const requireResolve = (importer, path2) => {
8
+ const require1 = createRequire(importer);
9
+ require1.resolve(path2);
10
+ };
11
+ export async function getProvider(bundler, builderConfig) {
12
+ try {
13
+ if (bundler === "webpack") {
14
+ const { builderWebpackProvider } = await import("@modern-js/builder-webpack-provider");
15
+ return builderWebpackProvider({
16
+ builderConfig
17
+ });
18
+ } else {
19
+ const { builderRspackProvider } = await import("@modern-js/builder-rspack-provider");
20
+ return builderRspackProvider({
21
+ builderConfig
22
+ });
23
+ }
24
+ } catch (e) {
25
+ logger.error(`Cannot find provider, you need to install @modern-js/builder-${bundler}-provider first`);
26
+ }
27
+ }
28
+ export async function virtualModule(tempDir, cwd, virtualModuleMap) {
29
+ fs.ensureDirSync(tempDir);
30
+ const alias = {};
31
+ await Promise.all(Reflect.ownKeys(virtualModuleMap).map((k) => {
32
+ const virtualPath = k;
33
+ const relativePath = path.relative(cwd, virtualPath);
34
+ const realPath = path.join(tempDir, relativePath);
35
+ alias[virtualPath] = realPath;
36
+ return fs.writeFile(realPath, virtualModuleMap[virtualPath]);
37
+ }));
38
+ return [
39
+ alias,
40
+ (virtualPath, content) => {
41
+ const relativePath = path.relative(cwd, virtualPath);
42
+ const realPath = path.join(tempDir, relativePath);
43
+ fs.writeFileSync(realPath, content);
44
+ }
45
+ ];
46
+ }
47
+ export async function toImportFn(cwd, stories) {
48
+ const objectEntries = stories.map((file) => {
49
+ const ext = path.extname(file);
50
+ const relativePath = path.relative(cwd, file);
51
+ if (![
52
+ ".js",
53
+ ".jsx",
54
+ ".ts",
55
+ ".tsx",
56
+ ".mdx"
57
+ ].includes(ext)) {
58
+ logger.warn(`Cannot process ${ext} file with storyStoreV7: ${relativePath}`);
59
+ }
60
+ return ` '${toImportPath(relativePath)}': async () => import('${file}')`;
61
+ });
62
+ return `
63
+ const importers = {
64
+ ${objectEntries.join(",\n")}
65
+ };
66
+
67
+ export async function importFn(path) {
68
+ return importers[path]();
69
+ }
70
+ `;
71
+ }
72
+ function toImportPath(relativePath) {
73
+ return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
74
+ }
75
+ export function getAbsolutePath(input) {
76
+ return dirname(require.resolve(join(input, "package.json")));
77
+ }
78
+ export function maybeGetAbsolutePath(input) {
79
+ try {
80
+ return getAbsolutePath(input);
81
+ } catch (e) {
82
+ return false;
83
+ }
84
+ }
85
+ export async function runWithErrorMsg(op, msg) {
86
+ try {
87
+ return await op();
88
+ } catch (e) {
89
+ logger.error(msg);
90
+ console.error(e);
91
+ }
92
+ }
93
+ export function isDev() {
94
+ return process.env.NODE_ENV === "development";
95
+ }
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ import type { Plugin } from '@modern-js/runtime';
3
+ import type { IConfig } from '../type';
4
+ export declare const WrapProviders: (storyFn: any, config: IConfig) => JSX.Element;
5
+ export declare const resolvePlugins: (runtime: IConfig['modernConfigRuntime']) => Plugin[];
@@ -0,0 +1 @@
1
+ export declare const ADDON_ID = "storybook/modern-runtime";
@@ -0,0 +1,2 @@
1
+ declare const _default: {};
2
+ export default _default;
@@ -0,0 +1 @@
1
+ export declare const decorators: import("@storybook/types").DecoratorFunction[];
@@ -0,0 +1,4 @@
1
+ export interface IConfig {
2
+ modernConfigRuntime: any;
3
+ modernConfigDesignToken: any;
4
+ }
@@ -0,0 +1,2 @@
1
+ import { DecoratorFunction } from '@storybook/types';
2
+ export declare const withPluginRuntime: DecoratorFunction;
@@ -0,0 +1,7 @@
1
+ import type { Builder as RawStorybookBuilder, Stats } from '@storybook/types';
2
+ import type { FrameworkOptions } from './types';
3
+ export type StorybookBuilder = RawStorybookBuilder<FrameworkOptions, Stats>;
4
+ export declare const getConfig: StorybookBuilder['getConfig'];
5
+ export declare const build: StorybookBuilder['build'];
6
+ export declare const start: StorybookBuilder['start'];
7
+ export declare const bail: () => Promise<void>;
@@ -0,0 +1,4 @@
1
+ import type { Options } from '@storybook/types';
2
+ import type { Compiler } from '@modern-js/utils/webpack-dev-middleware';
3
+ import type { FrameworkOptions } from './types';
4
+ export declare function getCompiler(cwd: string, frameworkConfig: FrameworkOptions, options: Options): Promise<Compiler>;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * This is heavily based on the react-docgen `displayNameHandler`
3
+ * (https://github.com/reactjs/react-docgen/blob/26c90c0dd105bf83499a83826f2a6ff7a724620d/src/handlers/displayNameHandler.ts)
4
+ * but instead defines an `actualName` property on the generated docs that is taken first from the component's actual name.
5
+ * This addresses an issue where the name that the generated docs are stored under is incorrectly named with the `displayName`
6
+ * and not the component's actual name.
7
+ *
8
+ * This is inspired by `actualNameHandler` from https://github.com/storybookjs/babel-plugin-react-docgen, but is modified
9
+ * directly from displayNameHandler, using the same approach as babel-plugin-react-docgen.
10
+ */
11
+ import type { NodePath } from 'ast-types/lib/node-path';
12
+ import type { Importer } from 'react-docgen/dist/parse';
13
+ import type Documentation from 'react-docgen/dist/Documentation';
14
+ export default function actualNameHandler(documentation: Documentation, path: NodePath, importer: Importer): void;
@@ -0,0 +1,9 @@
1
+ import type { Options } from '@storybook/types';
2
+ import { RspackConfig } from '@modern-js/builder-rspack-provider';
3
+ import { WebpackChain } from '@modern-js/builder-webpack-provider';
4
+ export type DocgenOptions = {
5
+ reactDocgen?: 'react-docgen' | 'react-docgen-typescript' | false;
6
+ reactDocgenTypescriptOptions?: any;
7
+ };
8
+ export declare function applyDocgenWebpack(chain: WebpackChain, options: Options): Promise<void>;
9
+ export declare function applyDocgenRspack(config: RspackConfig, options: Options): Promise<void>;