Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(storybook): add styles and stylePreprocessorOptions to the executors #9057

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/generated/api-storybook/executors/build.md
Expand Up @@ -46,3 +46,15 @@ Default: `true`
Type: `boolean`

Suppress verbose build output.

### stylePreprocessorOptions.includePaths

Type: `array`

Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.

### styles

Type: `array`

Global styles to be included in the build. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.
12 changes: 12 additions & 0 deletions docs/generated/api-storybook/executors/storybook.md
Expand Up @@ -85,6 +85,18 @@ Type: `array`

Directory where to load static files from, array of strings

### stylePreprocessorOptions.includePaths

Type: `array`

Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.

### styles

Type: `array`

Global styles to be included in the build. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.

### watch

Default: `true`
Expand Down
30 changes: 30 additions & 0 deletions docs/shared/guides/storybook/plugin-angular.md
Expand Up @@ -252,6 +252,36 @@ nx build-storybook my-project --projectBuildConfig=my-project:build-storybook

> In a pure Angular/Storybook setup (**not** an Nx workspace), the Angular application/project would have an `angular.json` file. That file would have a property called `defaultProject`. In an Nx workspace the `defaultProject` property would be specified in the `nx.json` file. Previously, Nx would try to resolve the `defaultProject` of the workspace, and use the build configuration of that project. In most cases, the `defaultProject`'s build configuration would not work for some other project set up with Storybook, since there would most probably be mismatches in paths or other project-specific options.

### Configuring styles and preprocessor options

Angular supports including extra entry-point files for styles. Also, in case you use Sass, you can add extra base paths that will be checked for imports. In your project's `project.json` file you can use the `styles` and `stylePreprocessorOptions` properties in your `storybook` and `build-storybook` target `options`, as you would in your Storybook or your Angular configurations. Check out the [Angular Workspace Configuration](https://angular.io/guide/workspace-config#styles-and-scripts-configuration) documentation for more information.

```json
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
...
"styles": ["some-styles.css"],
"stylePreprocessorOptions": {
"includePaths": ["some-style-paths"]
}
},
...
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
...
"options": {
...
"styles": ["some-styles.css"],
"stylePreprocessorOptions": {
"includePaths": ["some-style-paths"]
}
},
...
}
```

## More Documentation

For more on using Storybook, see the [official Storybook documentation](https://storybook.js.org/docs/basics/introduction/).
Expand Down
Expand Up @@ -44,6 +44,10 @@ describe('Build storybook', () => {
uiFramework,
outputPath,
projectBuildConfig: 'proj',
stylePreprocessorOptions: {
includePaths: ['my-path/my-style-options'],
},
styles: ['my-other-path/my-other-styles.scss'],
config,
};

Expand Down
Expand Up @@ -4,6 +4,7 @@ import 'dotenv/config';
import { CommonNxStorybookConfig } from '../models';
import {
getStorybookFrameworkPath,
normalizeAngularBuilderStylesOptions,
resolveCommonStorybookOptionMapper,
runStorybookSetupCheck,
} from '../utils';
Expand All @@ -21,8 +22,9 @@ export default async function buildStorybookExecutor(
logger.info(`NX ui framework: ${options.uiFramework}`);

const frameworkPath = getStorybookFrameworkPath(options.uiFramework);

const { default: frameworkOptions } = await import(frameworkPath);

options = normalizeAngularBuilderStylesOptions(options, options.uiFramework);
const option = storybookOptionMapper(options, frameworkOptions, context);

// print warnings
Expand Down
45 changes: 45 additions & 0 deletions packages/storybook/src/executors/build-storybook/schema.json
Expand Up @@ -18,6 +18,20 @@
"type": "string",
"description": "Workspace project where Storybook reads the Webpack config from"
},
"styles": {
"type": "array",
"description": "Global styles to be included in the build. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.",
"items": {
"$ref": "#/definitions/extraEntryPoint"
}
},
"stylePreprocessorOptions.includePaths": {
"description": "Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.",
"type": "array",
"items": {
"type": "string"
}
},
"config": {
"type": "object",
"description": ".storybook configuration",
Expand Down Expand Up @@ -51,5 +65,36 @@
"default": true
}
},
"definitions": {
"extraEntryPoint": {
"oneOf": [
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The file to include."
},
"bundleName": {
"type": "string",
"pattern": "^[\\w\\-.]*$",
"description": "The bundle name for this extra entry point."
},
"inject": {
"type": "boolean",
"description": "If the bundle will be referenced in the HTML file.",
"default": true
}
},
"additionalProperties": false,
"required": ["input"]
},
{
"type": "string",
"description": "The file to include."
}
]
}
},
"required": ["uiFramework", "config"]
}
4 changes: 4 additions & 0 deletions packages/storybook/src/executors/models.ts
Expand Up @@ -16,5 +16,9 @@ export interface CommonNxStorybookConfig {
| '@storybook/svelte'
| '@storybook/react-native';
projectBuildConfig?: string;
styles?: any[];
stylePreprocessorOptions?: {
includePaths?: string[];
};
config: StorybookConfig;
}
45 changes: 45 additions & 0 deletions packages/storybook/src/executors/storybook/schema.json
Expand Up @@ -58,6 +58,20 @@
"type": "string",
"description": "Workspace project where Storybook reads the Webpack config from"
},
"styles": {
"type": "array",
"description": "Global styles to be included in the build. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.",
"items": {
"$ref": "#/definitions/extraEntryPoint"
}
},
"stylePreprocessorOptions.includePaths": {
"description": "Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option for the Storybook/Angular builder. It will be ignored in non-Angular projects.",
"type": "array",
"items": {
"type": "string"
}
},
"config": {
"type": "object",
"description": ".storybook configuration",
Expand Down Expand Up @@ -91,5 +105,36 @@
"default": true
}
},
"definitions": {
"extraEntryPoint": {
"oneOf": [
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The file to include."
},
"bundleName": {
"type": "string",
"pattern": "^[\\w\\-.]*$",
"description": "The bundle name for this extra entry point."
},
"inject": {
"type": "boolean",
"description": "If the bundle will be referenced in the HTML file.",
"default": true
}
},
"additionalProperties": false,
"required": ["input"]
},
{
"type": "string",
"description": "The file to include."
}
]
}
},
"required": ["uiFramework", "config"]
}
Expand Up @@ -4,6 +4,7 @@ import 'dotenv/config';
import { CommonNxStorybookConfig } from '../models';
import {
getStorybookFrameworkPath,
normalizeAngularBuilderStylesOptions,
resolveCommonStorybookOptionMapper,
runStorybookSetupCheck,
} from '../utils';
Expand All @@ -24,8 +25,9 @@ export default async function* storybookExecutor(
context: ExecutorContext
): AsyncGenerator<{ success: boolean }> {
let frameworkPath = getStorybookFrameworkPath(options.uiFramework);

const frameworkOptions = (await import(frameworkPath)).default;

options = normalizeAngularBuilderStylesOptions(options, options.uiFramework);
const option = storybookOptionMapper(options, frameworkOptions, context);

// print warnings
Expand Down
25 changes: 25 additions & 0 deletions packages/storybook/src/executors/utils.ts
Expand Up @@ -18,7 +18,9 @@ import {
findOrCreateConfig,
readCurrentWorkspaceStorybookVersionFromExecutor,
} from '../utils/utilities';
import { StorybookBuilderOptions } from './build-storybook/build-storybook.impl';
import { CommonNxStorybookConfig } from './models';
import { StorybookExecutorOptions } from './storybook/storybook.impl';

export interface NodePackage {
name: string;
Expand Down Expand Up @@ -322,3 +324,26 @@ export function findStorybookAndBuildTargets(targets: {
});
return returnObject;
}

export function normalizeAngularBuilderStylesOptions(
builderOptions: StorybookBuilderOptions | StorybookExecutorOptions,
uiFramework:
| '@storybook/angular'
| '@storybook/react'
| '@storybook/html'
| '@storybook/web-components'
| '@storybook/vue'
| '@storybook/vue3'
| '@storybook/svelte'
| '@storybook/react-native'
): StorybookBuilderOptions | StorybookExecutorOptions {
if (uiFramework !== '@storybook/angular') {
if (builderOptions.styles) {
delete builderOptions.styles;
}
if (builderOptions.stylePreprocessorOptions) {
delete builderOptions.stylePreprocessorOptions;
}
}
return builderOptions;
}