Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
const path = require('path');
const fs = require('fs');

const { loadWorkspaceAddon, registerTsPaths, registerRules, rules } = require('@fluentui/scripts-storybook');
const {
loadWorkspaceAddon,
registerTsPaths,
processBabelLoaderOptions,
getImportMappingsForExportToSandboxAddon,
} = require('@fluentui/scripts-storybook');

const tsConfigPath = path.resolve(__dirname, '../tsconfig.base.json');

Expand Down Expand Up @@ -62,13 +67,24 @@ module.exports = /** @type {Omit<StorybookConfig,'typescript'|'babel'>} */ ({

// internal monorepo custom addons

/** @see ../packages/react-components/react-storybook-addon */
/** {@link file://./../packages/react-components/react-storybook-addon/package.json} */
loadWorkspaceAddon('@fluentui/react-storybook-addon', { tsConfigPath }),
loadWorkspaceAddon('@fluentui/react-storybook-addon-export-to-sandbox', { tsConfigPath }),
/** {@link file://./../packages/react-components/react-storybook-addon-export-to-sandbox/package.json} */
loadWorkspaceAddon('@fluentui/react-storybook-addon-export-to-sandbox', {
tsConfigPath,
/** @type {import('../packages/react-components/react-storybook-addon-export-to-sandbox/src/public-types').PresetConfig} */
options: {
importMappings: getImportMappingsForExportToSandboxAddon(),
babelLoaderOptionsUpdater: processBabelLoaderOptions,
webpackRule: {
test: /\.stories\.tsx$/,
include: /stories/,
},
},
}),
],
webpackFinal: config => {
registerTsPaths({ config, configFile: tsConfigPath });
registerRules({ config, rules: [rules.codesandboxRule] });

if ((process.env.CI || process.env.TF_BUILD || process.env.LAGE_PACKAGE_NAME) && config.plugins) {
// Disable ProgressPlugin in PR/CI builds to reduce log verbosity (warnings and errors are still logged)
Expand Down
3 changes: 0 additions & 3 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ export const parameters = {
excludeDecorators: true,
type: 'source',
},
// This config reuses sources generated for CodeSandbox export feature
// (@fluentui/babel-preset-storybook-full-source).
transformSource: (snippet, story) => story.parameters.fullSource,
},
exportToSandbox: {
provider: 'codesandbox-browser',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import * as Babel from '@babel/core';
export type BabelPluginOptions = Record<string, DependencyEntry>;

// @public
export function fullSourcePlugin(babel: typeof Babel, options: BabelPluginOptions): Babel.PluginObj;
function fullSourcePlugin(babel: typeof Babel, options: BabelPluginOptions): Babel.PluginObj;
export default fullSourcePlugin;

// (No @packageDocumentation comment for this package)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.1",
"description": "Babel preset that adds the makes the full source code of stories available",
"private": true,
"main": "./src/index.dev.js",
"typings": "./src/index.dev.d.ts",
"main": "./lib-commonjs/index.js",
"typings": "./dist/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/fluentui"
Expand Down Expand Up @@ -33,9 +33,14 @@
},
"exports": {
".": {
"types": "./src/index.dev.d.ts",
"node": "./src/index.dev.js",
"require": "./src/index.dev.js"
"types": "./dist/index.d.ts",
"node": "./lib-commonjs/index.js",
"require": "./lib-commonjs/index.js"
},
"./__dev": {
"types": "./src/index.ts",
"node": "./src/index.ts",
"require": "./src/index.ts"
},
"./package.json": "./package.json"
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { fullSourcePlugin } from './fullsource';
import { fullSourcePlugin } from './fullsource';

export type { BabelPluginOptions } from './types';
export default fullSourcePlugin;
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@swc/helpers": "^0.5.1",
"@types/dedent": "0.7.0",
"codesandbox-import-utils": "2.2.3",
"@fluentui/babel-preset-storybook-full-source": "~0.0.1",
"dedent": "0.7.0"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/* eslint-disable no-shadow */

const preset = require('./lib/preset/preset');

function config(entry = []) {
return [...entry, require.resolve('./lib/preset/preview')];
}

module.exports = { config };
module.exports = { config, ...preset };
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { webpack, WebpackFinalConfig, WebpackFinalOptions } from '../webpack';

export function webpackFinal(config: WebpackFinalConfig, options: WebpackFinalOptions) {
return webpack(config, options);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
import type { Parameters } from '@storybook/addons';
import type { StoryContextForEnhancers } from '@storybook/csf';

import { withExportToSandboxButton } from '../decorators/with-export-to-sandbox-button';

export const decorators = [withExportToSandboxButton];

export const parameters: Parameters = {
docs: {
/**
* Override source code shown within "Show Code" Docs tab.
* @see https://github.com/storybookjs/storybook/blob/release-6-5/addons/docs/docs/recipes.md#customizing-source-snippets
*/
transformSource: (source: string, storyContext: StoryContextForEnhancers) => {
// This config renders story source generated via `fullSource` parameter that is being added by @fluentui/babel-preset-storybook-full-source plugin, which is registered as part of this preset
return storyContext.parameters.fullSource;
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ interface ParametersConfig {
export interface ParametersExtension {
exportToSandbox?: ParametersConfig;
}

export interface PresetConfig {
importMappings: import('@fluentui/babel-preset-storybook-full-source').BabelPluginOptions;
webpackRule?: import('webpack').RuleSetRule;
babelLoaderOptionsUpdater?: (value: import('@babel/core').TransformOptions) => typeof value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe(`sabdbox-utils`, () => {
expect(actual).toBe(null);
expect(consoleErrorSpy.mock.calls.flat()).toMatchInlineSnapshot(`
Array [
"Export to CodeSandbox: Couldn't find source for story Showcase. Did you install the babel plugin?",
"Export to Sandbox Addon: Couldn't find source for story Showcase. Did you install the babel plugin?",
]
`);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function prepareData(context: StoryContext): Data | null {

if (!storyFile) {
console.error(
dedent`Export to CodeSandbox: Couldn't find source for story ${context.story}. Did you install the babel plugin?`,
dedent`Export to Sandbox Addon: Couldn't find source for story ${context.story}. Did you install the babel plugin?`,
);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { StoryContext as StoryContextOrigin, Parameters } from '@storybook/addons';
import type { ParametersExtension } from './public-types';
import type { ParametersExtension, PresetConfig } from './public-types';

export interface StoryContext extends StoryContextOrigin {
parameters: Parameters & ParametersExtension;
}

export type { ParametersExtension };
export type { ParametersExtension, PresetConfig };
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { PresetConfig } from './public-types';
import { webpack, WebpackFinalOptions } from './webpack';
describe(`webpack`, () => {
it(`should register webpack preset with defaults`, () => {
const actual = webpack({ module: { rules: [] } }, {
presetsList: [
{
name: 'node_modules/@fluentui/react-storybook-addon-export-to-sandbox/lib/preset.js',
preset: {},
options: {},
},
],
} as WebpackFinalOptions);

expect(actual.module?.rules).toEqual([
{
enforce: 'post',
test: /\.stories\.(jsx?$|tsx?$)/,
use: {
loader: 'babel-loader',
options: {
plugins: [[expect.stringContaining('babel-preset-storybook-full-source'), undefined]],
},
},
},
]);
});

it(`should register webpack preset with user provided options`, () => {
const actual = webpack({ module: { rules: [] } }, {
presetsList: [
{
name: 'node_modules/@fluentui/react-storybook-addon-export-to-sandbox/lib/preset.js',
preset: {},
options: {
importMappings: {
'@proj/foo': { replace: '@proj/moo' },
},
webpackRule: { test: /\.stories\.tsx?/, include: /foo-stories/ },
babelLoaderOptionsUpdater: value => {
return Object.assign(value, { presets: ['babel-foo-bar-preset'] });
},
} as PresetConfig,
},
],
} as WebpackFinalOptions);

expect(actual.module?.rules).toEqual([
{
enforce: 'post',
test: /\.stories\.tsx?/,
include: /foo-stories/,
use: {
loader: 'babel-loader',
options: {
plugins: [
[
expect.stringContaining('babel-preset-storybook-full-source'),
{ '@proj/foo': { replace: '@proj/moo' } },
],
],
presets: ['babel-foo-bar-preset'],
},
},
},
]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import type { PresetConfig } from './types';

type WebpackFinalFn = NonNullable<import('@storybook/core-common').StorybookConfig['webpackFinal']>;
export type WebpackFinalConfig = Parameters<WebpackFinalFn>[0];
export type WebpackFinalOptions = Parameters<WebpackFinalFn>[1];

export function webpack(config: WebpackFinalConfig, options: WebpackFinalOptions) {
const addonPresetConfig = getAddonOptions(options);

registerRules({ config, rules: [createRule(addonPresetConfig)] });

return config;
}

const identity = <T extends unknown>(value: T) => value;
const addonFilePattern = /react-storybook-addon-export-to-sandbox\/[a-z/]+.[jt]s$/;
const defaultOptions = {
webpackRule: {},
babelLoaderOptionsUpdater: identity,
};

const PLUGIN_PATH =
process.env.NODE_ENV !== 'production'
? '@fluentui/babel-preset-storybook-full-source/__dev'
: '@fluentui/babel-preset-storybook-full-source';

function createRule(config: Required<PresetConfig>): import('webpack').RuleSetRule {
const { babelLoaderOptionsUpdater, importMappings, webpackRule } = config;

const plugin = [require.resolve(PLUGIN_PATH), importMappings];

return {
test: /\.stories\.(jsx?$|tsx?$)/,
...webpackRule,
/**
* why the usage of 'post' ? - we need to run this loader after all storybook webpack rules/loaders have been executed.
* while we can use Array.prototype.unshift to "override" the indexes this approach is more declarative without additional hacks.
*/
enforce: 'post',
use: {
loader: 'babel-loader',
options: babelLoaderOptionsUpdater({
plugins: [plugin],
}),
},
};
}

/**
*
* register custom Webpack Rules to webpack config
*/
function registerRules(options: { rules: import('webpack').RuleSetRule[]; config: import('webpack').Configuration }) {
const { config, rules } = options;
config.module = config.module ?? {};
config.module.rules = config.module.rules ?? [];
config.module.rules.push(...rules);

return config;
}

function getAddonOptions(options: WebpackFinalOptions): Required<PresetConfig> {
const presetRegistration = options.presetsList?.find(preset => {
return addonFilePattern.test(preset.name);
});

const addonOptions = presetRegistration?.options ?? {};

return { ...defaultOptions, ...addonOptions };
}
3 changes: 1 addition & 2 deletions scripts/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"type-check": "tsc -b tsconfig.json"
},
"dependencies": {
"@fluentui/scripts-monorepo": "*",
"@fluentui/babel-preset-storybook-full-source": "*"
"@fluentui/scripts-monorepo": "*"
}
}
2 changes: 2 additions & 0 deletions scripts/storybook/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export {
registerTsPaths,
registerRules,
overrideDefaultBabelLoader,
processBabelLoaderOptions,
getImportMappingsForExportToSandboxAddon,
} from './utils';

export * as rules from './rules';
11 changes: 10 additions & 1 deletion scripts/storybook/src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
const rules = require('./rules');
const { getPackageStoriesGlob, loadWorkspaceAddon, registerRules, registerTsPaths } = require('./utils');
const {
getPackageStoriesGlob,
loadWorkspaceAddon,
registerRules,
registerTsPaths,
processBabelLoaderOptions,
getImportMappingsForExportToSandboxAddon,
} = require('./utils');

module.exports = {
getPackageStoriesGlob,
loadWorkspaceAddon,
registerRules,
registerTsPaths,
rules,
getImportMappingsForExportToSandboxAddon,
processBabelLoaderOptions,
};
8 changes: 0 additions & 8 deletions scripts/storybook/src/rules.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const { _createCodesandboxRule } = require('./utils');

/**
* @type {import("webpack").RuleSetRule}
*/
Expand Down Expand Up @@ -92,13 +90,7 @@ const griffelRule = {
],
};

/**
* @type {import("webpack").RuleSetRule}
*/
const codesandboxRule = _createCodesandboxRule();

exports.tsRule = tsRule;
exports.scssRule = scssRule;
exports.cssRule = cssRule;
exports.griffelRule = griffelRule;
exports.codesandboxRule = codesandboxRule;
Loading