From dfaabab99018dec5a42f700da5ec3206c7bdd02b Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Mon, 21 Feb 2022 15:29:53 +0200 Subject: [PATCH] feat(storybook): add styles and stylePreprocessorOptions to the executors --- .../api-storybook/executors/build.md | 6 +++ .../api-storybook/executors/storybook.md | 6 +++ .../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 | 52 +++++++++++++++++++ packages/storybook/src/executors/models.ts | 4 ++ .../src/executors/storybook/schema.json | 52 +++++++++++++++++++ .../src/executors/storybook/storybook.impl.ts | 4 +- packages/storybook/src/executors/utils.ts | 25 +++++++++ 10 files changed, 185 insertions(+), 2 deletions(-) diff --git a/docs/generated/api-storybook/executors/build.md b/docs/generated/api-storybook/executors/build.md index 138ffdcfe9900d..04bede3897adcb 100644 --- a/docs/generated/api-storybook/executors/build.md +++ b/docs/generated/api-storybook/executors/build.md @@ -46,3 +46,9 @@ Default: `true` Type: `boolean` Suppress verbose build output. + +### styles + +Type: `array` + +Global styles to be included in the build. This is for Angular projects only, as an option of 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 3b42edcca32ee9..865985448214b0 100644 --- a/docs/generated/api-storybook/executors/storybook.md +++ b/docs/generated/api-storybook/executors/storybook.md @@ -85,6 +85,12 @@ Type: `array` Directory where to load static files from, array of strings +### styles + +Type: `array` + +Global styles to be included in the build. This is for Angular projects only, as an option of 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 792597b46b6287..ab12c6f3ab93ef 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 + +The Angular builder 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. Check out the [Angular Workspace Configuration](https://angular.io/guide/workspace-config#styles-and-scripts-configuration) documentation for more information. 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 builder setup. These will be passed down to the [Storybook builder](https://github.com/storybookjs/storybook/pull/16675) and then to the Angular builder. + +```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 471f800bf9bf82..94e3f761a7ac3e 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 cb7b8f55ace701..256224a5a629ca 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 01909d742c9d58..f45cdaa16a5f6b 100644 --- a/packages/storybook/src/executors/build-storybook/schema.json +++ b/packages/storybook/src/executors/build-storybook/schema.json @@ -18,6 +18,27 @@ "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 of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "items": { + "$ref": "#/definitions/extraEntryPoint" + } + }, + "stylePreprocessorOptions": { + "description": "Options to pass to style preprocessors. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "type": "object", + "properties": { + "includePaths": { + "description": "Paths to include. Paths will be resolved to workspace root.", + "type": "array", + "items": { + "type": "string" + }, + "default": [] + } + } + }, "config": { "type": "object", "description": ".storybook configuration", @@ -51,5 +72,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 b3b7c8de69d86a..b695d8a7594188 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 64f870affd199c..e5dedff12ca23d 100644 --- a/packages/storybook/src/executors/storybook/schema.json +++ b/packages/storybook/src/executors/storybook/schema.json @@ -58,6 +58,27 @@ "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 of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "items": { + "$ref": "#/definitions/extraEntryPoint" + } + }, + "stylePreprocessorOptions": { + "description": "Options to pass to style preprocessors. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "type": "object", + "properties": { + "includePaths": { + "description": "Paths to include. Paths will be resolved to workspace root.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "default": "" + }, "config": { "type": "object", "description": ".storybook configuration", @@ -91,5 +112,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 c9bed0f39e8f1f..2256087289ce52 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 a30c22a0d487a5..08b17b0f198f5d 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; +}