From fc018cd438976945665c73c1c68c03feb089c7c1 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Mon, 21 Feb 2022 16:40:59 +0200 Subject: [PATCH] feat(storybook): add styles and stylePreprocessorOptions to the executors (#9057) --- .../api-storybook/executors/build.md | 12 +++++ .../api-storybook/executors/storybook.md | 12 +++++ .../shared/guides/storybook/plugin-angular.md | 30 +++++++++++++ .../build-storybook.impl.spec.ts | 4 ++ .../build-storybook/build-storybook.impl.ts | 4 +- .../src/executors/build-storybook/schema.json | 45 +++++++++++++++++++ packages/storybook/src/executors/models.ts | 4 ++ .../src/executors/storybook/schema.json | 45 +++++++++++++++++++ .../src/executors/storybook/storybook.impl.ts | 4 +- packages/storybook/src/executors/utils.ts | 25 +++++++++++ 10 files changed, 183 insertions(+), 2 deletions(-) diff --git a/docs/generated/api-storybook/executors/build.md b/docs/generated/api-storybook/executors/build.md index 138ffdcfe9900..3b5b83ca7de73 100644 --- a/docs/generated/api-storybook/executors/build.md +++ b/docs/generated/api-storybook/executors/build.md @@ -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. diff --git a/docs/generated/api-storybook/executors/storybook.md b/docs/generated/api-storybook/executors/storybook.md index 3b42edcca32ee..8202562f16fca 100644 --- a/docs/generated/api-storybook/executors/storybook.md +++ b/docs/generated/api-storybook/executors/storybook.md @@ -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` diff --git a/docs/shared/guides/storybook/plugin-angular.md b/docs/shared/guides/storybook/plugin-angular.md index 792597b46b628..2470f6d9c5ca7 100644 --- a/docs/shared/guides/storybook/plugin-angular.md +++ b/docs/shared/guides/storybook/plugin-angular.md @@ -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/). diff --git a/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts b/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts index 471f800bf9bf8..94e3f761a7ac3 100644 --- a/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts +++ b/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts @@ -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, }; diff --git a/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts b/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts index cb7b8f55ace70..256224a5a629c 100644 --- a/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts +++ b/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts @@ -4,6 +4,7 @@ import 'dotenv/config'; import { CommonNxStorybookConfig } from '../models'; import { getStorybookFrameworkPath, + normalizeAngularBuilderStylesOptions, resolveCommonStorybookOptionMapper, runStorybookSetupCheck, } from '../utils'; @@ -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 diff --git a/packages/storybook/src/executors/build-storybook/schema.json b/packages/storybook/src/executors/build-storybook/schema.json index 01909d742c9d5..acdf15a4329ff 100644 --- a/packages/storybook/src/executors/build-storybook/schema.json +++ b/packages/storybook/src/executors/build-storybook/schema.json @@ -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", @@ -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"] } diff --git a/packages/storybook/src/executors/models.ts b/packages/storybook/src/executors/models.ts index b3b7c8de69d86..b695d8a759418 100644 --- a/packages/storybook/src/executors/models.ts +++ b/packages/storybook/src/executors/models.ts @@ -16,5 +16,9 @@ export interface CommonNxStorybookConfig { | '@storybook/svelte' | '@storybook/react-native'; projectBuildConfig?: string; + styles?: any[]; + stylePreprocessorOptions?: { + includePaths?: string[]; + }; config: StorybookConfig; } diff --git a/packages/storybook/src/executors/storybook/schema.json b/packages/storybook/src/executors/storybook/schema.json index 64f870affd199..312389fbf6c82 100644 --- a/packages/storybook/src/executors/storybook/schema.json +++ b/packages/storybook/src/executors/storybook/schema.json @@ -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", @@ -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"] } diff --git a/packages/storybook/src/executors/storybook/storybook.impl.ts b/packages/storybook/src/executors/storybook/storybook.impl.ts index c9bed0f39e8f1..2256087289ce5 100644 --- a/packages/storybook/src/executors/storybook/storybook.impl.ts +++ b/packages/storybook/src/executors/storybook/storybook.impl.ts @@ -4,6 +4,7 @@ import 'dotenv/config'; import { CommonNxStorybookConfig } from '../models'; import { getStorybookFrameworkPath, + normalizeAngularBuilderStylesOptions, resolveCommonStorybookOptionMapper, runStorybookSetupCheck, } from '../utils'; @@ -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 diff --git a/packages/storybook/src/executors/utils.ts b/packages/storybook/src/executors/utils.ts index a30c22a0d487a..08b17b0f198f5 100644 --- a/packages/storybook/src/executors/utils.ts +++ b/packages/storybook/src/executors/utils.ts @@ -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; @@ -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; +}