@storybook/angular 9.0.0-beta.1 → 9.0.0-beta.10
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.
- package/dist/builders/build-storybook/index.d.ts +2 -16
- package/dist/builders/build-storybook/index.mjs +78 -0
- package/dist/builders/build-storybook/index.spec.mjs +187 -0
- package/dist/builders/build-storybook/schema.json +2 -4
- package/dist/builders/start-storybook/index.d.ts +2 -14
- package/dist/builders/start-storybook/index.mjs +99 -0
- package/dist/builders/start-storybook/index.spec.mjs +186 -0
- package/dist/builders/start-storybook/schema.json +3 -6
- package/dist/builders/utils/error-handler.mjs +33 -0
- package/dist/builders/utils/run-compodoc.mjs +31 -0
- package/dist/builders/utils/run-compodoc.spec.mjs +74 -0
- package/dist/builders/utils/standalone-options.mjs +1 -0
- package/dist/client/angular-beta/AbstractRenderer.mjs +164 -0
- package/dist/client/angular-beta/CanvasRenderer.mjs +9 -0
- package/dist/client/angular-beta/ComputesTemplateFromComponent.mjs +154 -0
- package/dist/client/angular-beta/ComputesTemplateFromComponent.test.mjs +728 -0
- package/dist/client/angular-beta/DocsRenderer.mjs +35 -0
- package/dist/client/angular-beta/RendererFactory.mjs +50 -0
- package/dist/client/angular-beta/RendererFactory.test.mjs +233 -0
- package/dist/client/angular-beta/StorybookModule.mjs +23 -0
- package/dist/client/angular-beta/StorybookModule.test.mjs +319 -0
- package/dist/client/angular-beta/StorybookProvider.mjs +22 -0
- package/dist/client/angular-beta/StorybookWrapperComponent.mjs +123 -0
- package/dist/client/angular-beta/__testfixtures__/input.component.mjs +73 -0
- package/dist/client/angular-beta/__testfixtures__/test.module.mjs +17 -0
- package/dist/client/angular-beta/utils/BootstrapQueue.mjs +49 -0
- package/dist/client/angular-beta/utils/BootstrapQueue.test.mjs +162 -0
- package/dist/client/angular-beta/utils/NgComponentAnalyzer.mjs +84 -0
- package/dist/client/angular-beta/utils/NgComponentAnalyzer.test.mjs +386 -0
- package/dist/client/angular-beta/utils/NgModulesAnalyzer.mjs +37 -0
- package/dist/client/angular-beta/utils/NgModulesAnalyzer.test.mjs +22 -0
- package/dist/client/angular-beta/utils/PropertyExtractor.mjs +158 -0
- package/dist/client/angular-beta/utils/PropertyExtractor.test.mjs +175 -0
- package/dist/client/angular-beta/utils/StoryUID.mjs +38 -0
- package/dist/client/argsToTemplate.mjs +55 -0
- package/dist/client/argsToTemplate.test.mjs +100 -0
- package/dist/client/config.mjs +4 -0
- package/dist/client/decorateStory.mjs +45 -0
- package/dist/client/decorateStory.test.mjs +301 -0
- package/dist/client/decorators.mjs +63 -0
- package/dist/client/decorators.test.mjs +157 -0
- package/dist/client/docs/__testfixtures__/doc-button/input.mjs +201 -0
- package/dist/client/docs/angular-properties.test.mjs +34 -0
- package/dist/client/docs/compodoc.mjs +244 -0
- package/dist/client/docs/compodoc.test.mjs +130 -0
- package/dist/client/docs/config.mjs +16 -0
- package/dist/client/docs/index.mjs +1 -0
- package/dist/client/docs/sourceDecorator.mjs +48 -0
- package/dist/client/docs/types.mjs +1 -0
- package/dist/client/globals.mjs +31 -0
- package/dist/client/index.mjs +9 -0
- package/dist/client/portable-stories.mjs +26 -0
- package/dist/client/preview-prod.mjs +2 -0
- package/dist/client/public-types.mjs +1 -0
- package/dist/client/render.mjs +14 -0
- package/dist/client/types.mjs +1 -0
- package/dist/node/index.mjs +3 -0
- package/dist/server/__mocks-ng-workspace__/minimal-config/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/some-config/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/with-angularBrowserTarget/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/with-lib/projects/pattern-lib/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/with-nx/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/with-nx-workspace/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/with-options-styles/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/without-projects-entry/projects/pattern-lib/src/main.mjs +2 -0
- package/dist/server/__mocks-ng-workspace__/without-tsConfig/src/main.mjs +2 -0
- package/dist/server/angular-cli-webpack.mjs +80 -0
- package/dist/server/framework-preset-angular-cli.mjs +81 -0
- package/dist/server/framework-preset-angular-docs.mjs +6 -0
- package/dist/server/framework-preset-angular-ivy.mjs +56 -0
- package/dist/server/plugins/storybook-normalize-angular-entry-plugin.mjs +52 -0
- package/dist/server/preset-options.mjs +1 -0
- package/dist/server/utils/filter-out-styling-rules.mjs +13 -0
- package/dist/server/utils/module-is-available.mjs +9 -0
- package/package.json +5 -15
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CLIOptions } from 'storybook/internal/types';
|
|
2
|
-
import { BuilderOutput } from '@angular-devkit/architect';
|
|
2
|
+
import { BuilderOutput, Builder as DevkitBuilder } from '@angular-devkit/architect';
|
|
3
3
|
import { StylePreprocessorOptions } from '@angular-devkit/build-angular';
|
|
4
4
|
import { AssetPattern, SourceMapUnion, StyleElement } from '@angular-devkit/build-angular/src/builders/browser/schema';
|
|
5
5
|
import { JsonObject } from '@angular-devkit/core';
|
|
@@ -21,19 +21,5 @@ export type StorybookBuilderOptions = JsonObject & {
|
|
|
21
21
|
export type StorybookBuilderOutput = JsonObject & BuilderOutput & {
|
|
22
22
|
[key: string]: any;
|
|
23
23
|
};
|
|
24
|
-
declare const _default:
|
|
25
|
-
browserTarget?: string | null;
|
|
26
|
-
tsConfig?: string;
|
|
27
|
-
test: boolean;
|
|
28
|
-
docs: boolean;
|
|
29
|
-
compodoc: boolean;
|
|
30
|
-
compodocArgs: string[];
|
|
31
|
-
enableProdMode?: boolean;
|
|
32
|
-
styles?: StyleElement[];
|
|
33
|
-
stylePreprocessorOptions?: StylePreprocessorOptions;
|
|
34
|
-
preserveSymlinks?: boolean;
|
|
35
|
-
assets?: AssetPattern[];
|
|
36
|
-
sourceMap?: SourceMapUnion;
|
|
37
|
-
experimentalZoneless?: boolean;
|
|
38
|
-
} & Pick<CLIOptions, "statsJson" | "outputDir" | "configDir" | "loglevel" | "quiet" | "test" | "webpackStatsJson" | "disableTelemetry" | "debugWebpack" | "previewUrl">>;
|
|
24
|
+
declare const _default: DevkitBuilder<StorybookBuilderOptions & JsonObject>;
|
|
39
25
|
export default _default;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { getEnvConfig, versions } from 'storybook/internal/common';
|
|
2
|
+
import { buildStaticStandalone, withTelemetry } from 'storybook/internal/core-server';
|
|
3
|
+
import { addToGlobalContext } from 'storybook/internal/telemetry';
|
|
4
|
+
import { createBuilder, targetFromTargetString, } from '@angular-devkit/architect';
|
|
5
|
+
import { findPackageSync } from 'fd-package-json';
|
|
6
|
+
import { sync as findUpSync } from 'find-up';
|
|
7
|
+
import { from, of, throwError } from 'rxjs';
|
|
8
|
+
import { catchError, map, mapTo, switchMap } from 'rxjs/operators';
|
|
9
|
+
import { errorSummary, printErrorDetails } from '../utils/error-handler';
|
|
10
|
+
import { runCompodoc } from '../utils/run-compodoc';
|
|
11
|
+
addToGlobalContext('cliVersion', versions.storybook);
|
|
12
|
+
const commandBuilder = (options, context) => {
|
|
13
|
+
const builder = from(setup(options, context)).pipe(switchMap(({ tsConfig }) => {
|
|
14
|
+
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
|
|
15
|
+
const runCompodoc$ = options.compodoc
|
|
16
|
+
? runCompodoc({ compodocArgs: options.compodocArgs, tsconfig: docTSConfig ?? tsConfig }, context).pipe(mapTo({ tsConfig }))
|
|
17
|
+
: of({});
|
|
18
|
+
return runCompodoc$.pipe(mapTo({ tsConfig }));
|
|
19
|
+
}), map(({ tsConfig }) => {
|
|
20
|
+
getEnvConfig(options, {
|
|
21
|
+
staticDir: 'SBCONFIG_STATIC_DIR',
|
|
22
|
+
outputDir: 'SBCONFIG_OUTPUT_DIR',
|
|
23
|
+
configDir: 'SBCONFIG_CONFIG_DIR',
|
|
24
|
+
});
|
|
25
|
+
const { browserTarget, stylePreprocessorOptions, styles, configDir, docs, loglevel, test, outputDir, quiet, enableProdMode = true, webpackStatsJson, statsJson, debugWebpack, disableTelemetry, assets, previewUrl, sourceMap = false, preserveSymlinks = false, experimentalZoneless = false, } = options;
|
|
26
|
+
const standaloneOptions = {
|
|
27
|
+
packageJson: findPackageSync(__dirname),
|
|
28
|
+
configDir,
|
|
29
|
+
...(docs ? { docs } : {}),
|
|
30
|
+
loglevel,
|
|
31
|
+
outputDir,
|
|
32
|
+
test,
|
|
33
|
+
quiet,
|
|
34
|
+
enableProdMode,
|
|
35
|
+
disableTelemetry,
|
|
36
|
+
angularBrowserTarget: browserTarget,
|
|
37
|
+
angularBuilderContext: context,
|
|
38
|
+
angularBuilderOptions: {
|
|
39
|
+
...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
|
|
40
|
+
...(styles ? { styles } : {}),
|
|
41
|
+
...(assets ? { assets } : {}),
|
|
42
|
+
sourceMap,
|
|
43
|
+
preserveSymlinks,
|
|
44
|
+
experimentalZoneless,
|
|
45
|
+
},
|
|
46
|
+
tsConfig,
|
|
47
|
+
webpackStatsJson,
|
|
48
|
+
statsJson,
|
|
49
|
+
debugWebpack,
|
|
50
|
+
previewUrl,
|
|
51
|
+
};
|
|
52
|
+
return standaloneOptions;
|
|
53
|
+
}), switchMap((standaloneOptions) => runInstance({ ...standaloneOptions, mode: 'static' })), map(() => {
|
|
54
|
+
return { success: true };
|
|
55
|
+
}));
|
|
56
|
+
return builder;
|
|
57
|
+
};
|
|
58
|
+
export default createBuilder(commandBuilder);
|
|
59
|
+
async function setup(options, context) {
|
|
60
|
+
let browserOptions;
|
|
61
|
+
let browserTarget;
|
|
62
|
+
if (options.browserTarget) {
|
|
63
|
+
browserTarget = targetFromTargetString(options.browserTarget);
|
|
64
|
+
browserOptions = await context.validateOptions(await context.getTargetOptions(browserTarget), await context.getBuilderNameForTarget(browserTarget));
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
tsConfig: options.tsConfig ??
|
|
68
|
+
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
|
69
|
+
browserOptions.tsConfig,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function runInstance(options) {
|
|
73
|
+
return from(withTelemetry('build', {
|
|
74
|
+
cliOptions: options,
|
|
75
|
+
presetOptions: { ...options, corePresets: [], overridePresets: [] },
|
|
76
|
+
printError: printErrorDetails,
|
|
77
|
+
}, () => buildStaticStandalone(options))).pipe(catchError((error) => throwError(errorSummary(error))));
|
|
78
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { Architect, createBuilder } from '@angular-devkit/architect';
|
|
2
|
+
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
|
3
|
+
import { schema } from '@angular-devkit/core';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
+
const buildDevStandaloneMock = vi.fn();
|
|
7
|
+
const buildStaticStandaloneMock = vi.fn();
|
|
8
|
+
const buildMock = {
|
|
9
|
+
buildDevStandalone: buildDevStandaloneMock,
|
|
10
|
+
buildStaticStandalone: buildStaticStandaloneMock,
|
|
11
|
+
withTelemetry: (name, options, fn) => fn(),
|
|
12
|
+
};
|
|
13
|
+
vi.doMock('storybook/internal/core-server', () => buildMock);
|
|
14
|
+
vi.doMock('storybook/internal/common', () => ({
|
|
15
|
+
JsPackageManagerFactory: {
|
|
16
|
+
getPackageManager: () => ({
|
|
17
|
+
runPackageCommand: mockRunScript,
|
|
18
|
+
}),
|
|
19
|
+
},
|
|
20
|
+
getEnvConfig: (options) => options,
|
|
21
|
+
versions: {
|
|
22
|
+
storybook: 'x.x.x',
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
vi.doMock('find-up', () => ({ sync: () => './storybook/tsconfig.ts' }));
|
|
26
|
+
const mockRunScript = vi.fn();
|
|
27
|
+
// Randomly fails on CI. TODO: investigate why
|
|
28
|
+
describe.skip('Build Storybook Builder', () => {
|
|
29
|
+
let architect;
|
|
30
|
+
let architectHost;
|
|
31
|
+
beforeEach(async () => {
|
|
32
|
+
const registry = new schema.CoreSchemaRegistry();
|
|
33
|
+
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
|
34
|
+
architectHost = new TestingArchitectHost();
|
|
35
|
+
architect = new Architect(architectHost, registry);
|
|
36
|
+
architectHost.addBuilder('@angular-devkit/build-angular:browser', createBuilder(() => {
|
|
37
|
+
return { success: true };
|
|
38
|
+
}));
|
|
39
|
+
architectHost.addTarget({ project: 'angular-cli', target: 'build-2' }, '@angular-devkit/build-angular:browser', {
|
|
40
|
+
outputPath: 'dist/angular-cli',
|
|
41
|
+
index: 'src/index.html',
|
|
42
|
+
main: 'src/main.ts',
|
|
43
|
+
polyfills: 'src/polyfills.ts',
|
|
44
|
+
tsConfig: 'src/tsconfig.app.json',
|
|
45
|
+
assets: ['src/favicon.ico', 'src/assets'],
|
|
46
|
+
styles: ['src/styles.css'],
|
|
47
|
+
scripts: [],
|
|
48
|
+
});
|
|
49
|
+
// This will either take a Node package name, or a path to the directory
|
|
50
|
+
// for the package.json file.
|
|
51
|
+
await architectHost.addBuilderFromPackage(path.join(__dirname, '../../..'));
|
|
52
|
+
});
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
buildStaticStandaloneMock.mockImplementation((_options) => Promise.resolve(_options));
|
|
55
|
+
});
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
vi.clearAllMocks();
|
|
58
|
+
});
|
|
59
|
+
it('should start storybook with angularBrowserTarget', async () => {
|
|
60
|
+
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
|
|
61
|
+
browserTarget: 'angular-cli:build-2',
|
|
62
|
+
compodoc: false,
|
|
63
|
+
});
|
|
64
|
+
const output = await run.result;
|
|
65
|
+
await run.stop();
|
|
66
|
+
expect(output.success).toBeTruthy();
|
|
67
|
+
expect(mockRunScript).not.toHaveBeenCalledWith();
|
|
68
|
+
expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
69
|
+
angularBrowserTarget: 'angular-cli:build-2',
|
|
70
|
+
angularBuilderContext: expect.any(Object),
|
|
71
|
+
configDir: '.storybook',
|
|
72
|
+
loglevel: undefined,
|
|
73
|
+
quiet: false,
|
|
74
|
+
disableTelemetry: undefined,
|
|
75
|
+
outputDir: 'storybook-static',
|
|
76
|
+
packageJson: expect.any(Object),
|
|
77
|
+
mode: 'static',
|
|
78
|
+
tsConfig: './storybook/tsconfig.ts',
|
|
79
|
+
statsJson: false,
|
|
80
|
+
}));
|
|
81
|
+
});
|
|
82
|
+
it('should start storybook with tsConfig', async () => {
|
|
83
|
+
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
|
|
84
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
85
|
+
compodoc: false,
|
|
86
|
+
});
|
|
87
|
+
const output = await run.result;
|
|
88
|
+
await run.stop();
|
|
89
|
+
expect(output.success).toBeTruthy();
|
|
90
|
+
expect(mockRunScript).not.toHaveBeenCalledWith();
|
|
91
|
+
expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
92
|
+
angularBrowserTarget: null,
|
|
93
|
+
angularBuilderContext: expect.any(Object),
|
|
94
|
+
configDir: '.storybook',
|
|
95
|
+
loglevel: undefined,
|
|
96
|
+
quiet: false,
|
|
97
|
+
disableTelemetry: undefined,
|
|
98
|
+
outputDir: 'storybook-static',
|
|
99
|
+
packageJson: expect.any(Object),
|
|
100
|
+
mode: 'static',
|
|
101
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
102
|
+
statsJson: false,
|
|
103
|
+
}));
|
|
104
|
+
});
|
|
105
|
+
it('should build storybook with webpack stats.json', async () => {
|
|
106
|
+
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
|
|
107
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
108
|
+
compodoc: false,
|
|
109
|
+
statsJson: true,
|
|
110
|
+
});
|
|
111
|
+
const output = await run.result;
|
|
112
|
+
await run.stop();
|
|
113
|
+
expect(output.success).toBeTruthy();
|
|
114
|
+
expect(mockRunScript).not.toHaveBeenCalledWith();
|
|
115
|
+
expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
116
|
+
angularBrowserTarget: null,
|
|
117
|
+
angularBuilderContext: expect.any(Object),
|
|
118
|
+
configDir: '.storybook',
|
|
119
|
+
loglevel: undefined,
|
|
120
|
+
quiet: false,
|
|
121
|
+
outputDir: 'storybook-static',
|
|
122
|
+
packageJson: expect.any(Object),
|
|
123
|
+
mode: 'static',
|
|
124
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
125
|
+
statsJson: true,
|
|
126
|
+
}));
|
|
127
|
+
});
|
|
128
|
+
it('should throw error', async () => {
|
|
129
|
+
buildStaticStandaloneMock.mockRejectedValue(true);
|
|
130
|
+
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
|
|
131
|
+
browserTarget: 'angular-cli:build-2',
|
|
132
|
+
compodoc: false,
|
|
133
|
+
});
|
|
134
|
+
try {
|
|
135
|
+
await run.result;
|
|
136
|
+
expect(false).toEqual('Throw expected');
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
expect(error).toEqual('Broken build, fix the error above.\nYou may need to refresh the browser.');
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
it('should run compodoc', async () => {
|
|
143
|
+
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
|
|
144
|
+
browserTarget: 'angular-cli:build-2',
|
|
145
|
+
});
|
|
146
|
+
const output = await run.result;
|
|
147
|
+
await run.stop();
|
|
148
|
+
expect(output.success).toBeTruthy();
|
|
149
|
+
expect(mockRunScript).toHaveBeenCalledWith('compodoc', ['-p', './storybook/tsconfig.ts', '-d', '.', '-e', 'json'], '');
|
|
150
|
+
expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
151
|
+
angularBrowserTarget: 'angular-cli:build-2',
|
|
152
|
+
angularBuilderContext: expect.any(Object),
|
|
153
|
+
configDir: '.storybook',
|
|
154
|
+
loglevel: undefined,
|
|
155
|
+
quiet: false,
|
|
156
|
+
outputDir: 'storybook-static',
|
|
157
|
+
packageJson: expect.any(Object),
|
|
158
|
+
mode: 'static',
|
|
159
|
+
tsConfig: './storybook/tsconfig.ts',
|
|
160
|
+
statsJson: false,
|
|
161
|
+
}));
|
|
162
|
+
});
|
|
163
|
+
it('should start storybook with styles options', async () => {
|
|
164
|
+
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
|
|
165
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
166
|
+
compodoc: false,
|
|
167
|
+
styles: ['style.scss'],
|
|
168
|
+
});
|
|
169
|
+
const output = await run.result;
|
|
170
|
+
await run.stop();
|
|
171
|
+
expect(output.success).toBeTruthy();
|
|
172
|
+
expect(mockRunScript).not.toHaveBeenCalledWith();
|
|
173
|
+
expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
174
|
+
angularBrowserTarget: null,
|
|
175
|
+
angularBuilderContext: expect.any(Object),
|
|
176
|
+
angularBuilderOptions: { assets: [], styles: ['style.scss'] },
|
|
177
|
+
configDir: '.storybook',
|
|
178
|
+
loglevel: undefined,
|
|
179
|
+
quiet: false,
|
|
180
|
+
outputDir: 'storybook-static',
|
|
181
|
+
packageJson: expect.any(Object),
|
|
182
|
+
mode: 'static',
|
|
183
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
184
|
+
statsJson: false,
|
|
185
|
+
}));
|
|
186
|
+
});
|
|
187
|
+
});
|
|
@@ -91,8 +91,7 @@
|
|
|
91
91
|
"description": "Global styles to be included in the build.",
|
|
92
92
|
"items": {
|
|
93
93
|
"$ref": "#/definitions/styleElement"
|
|
94
|
-
}
|
|
95
|
-
"default": ""
|
|
94
|
+
}
|
|
96
95
|
},
|
|
97
96
|
"stylePreprocessorOptions": {
|
|
98
97
|
"description": "Options to pass to style preprocessors.",
|
|
@@ -106,8 +105,7 @@
|
|
|
106
105
|
}
|
|
107
106
|
}
|
|
108
107
|
},
|
|
109
|
-
"additionalProperties": false
|
|
110
|
-
"default": ""
|
|
108
|
+
"additionalProperties": false
|
|
111
109
|
},
|
|
112
110
|
"assets": {
|
|
113
111
|
"type": "array",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CLIOptions } from 'storybook/internal/types';
|
|
2
|
-
import { BuilderOutput } from '@angular-devkit/architect';
|
|
2
|
+
import { BuilderOutput, Builder as DevkitBuilder } from '@angular-devkit/architect';
|
|
3
3
|
import { StylePreprocessorOptions } from '@angular-devkit/build-angular';
|
|
4
4
|
import { AssetPattern, SourceMapUnion, StyleElement } from '@angular-devkit/build-angular/src/builders/browser/schema';
|
|
5
5
|
import { JsonObject } from '@angular-devkit/core';
|
|
@@ -17,17 +17,5 @@ export type StorybookBuilderOptions = JsonObject & {
|
|
|
17
17
|
experimentalZoneless?: boolean;
|
|
18
18
|
} & Pick<CLIOptions, 'port' | 'host' | 'configDir' | 'https' | 'sslCa' | 'sslCert' | 'sslKey' | 'smokeTest' | 'ci' | 'quiet' | 'disableTelemetry' | 'initialPath' | 'open' | 'docs' | 'debugWebpack' | 'webpackStatsJson' | 'statsJson' | 'loglevel' | 'previewUrl'>;
|
|
19
19
|
export type StorybookBuilderOutput = JsonObject & BuilderOutput & {};
|
|
20
|
-
declare const _default:
|
|
21
|
-
browserTarget?: string | null;
|
|
22
|
-
tsConfig?: string;
|
|
23
|
-
compodoc: boolean;
|
|
24
|
-
compodocArgs: string[];
|
|
25
|
-
enableProdMode?: boolean;
|
|
26
|
-
styles?: StyleElement[];
|
|
27
|
-
stylePreprocessorOptions?: StylePreprocessorOptions;
|
|
28
|
-
assets?: AssetPattern[];
|
|
29
|
-
preserveSymlinks?: boolean;
|
|
30
|
-
sourceMap?: SourceMapUnion;
|
|
31
|
-
experimentalZoneless?: boolean;
|
|
32
|
-
} & Pick<CLIOptions, "docs" | "statsJson" | "configDir" | "loglevel" | "quiet" | "webpackStatsJson" | "disableTelemetry" | "debugWebpack" | "previewUrl" | "port" | "host" | "initialPath" | "https" | "sslCa" | "sslCert" | "sslKey" | "smokeTest" | "open" | "ci">>;
|
|
20
|
+
declare const _default: DevkitBuilder<StorybookBuilderOptions & JsonObject>;
|
|
33
21
|
export default _default;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { getEnvConfig, versions } from 'storybook/internal/common';
|
|
2
|
+
import { buildDevStandalone, withTelemetry } from 'storybook/internal/core-server';
|
|
3
|
+
import { addToGlobalContext } from 'storybook/internal/telemetry';
|
|
4
|
+
import { createBuilder, targetFromTargetString, } from '@angular-devkit/architect';
|
|
5
|
+
import { findPackageSync } from 'fd-package-json';
|
|
6
|
+
import { sync as findUpSync } from 'find-up';
|
|
7
|
+
import { Observable, from, of } from 'rxjs';
|
|
8
|
+
import { map, mapTo, switchMap } from 'rxjs/operators';
|
|
9
|
+
import { errorSummary, printErrorDetails } from '../utils/error-handler';
|
|
10
|
+
import { runCompodoc } from '../utils/run-compodoc';
|
|
11
|
+
addToGlobalContext('cliVersion', versions.storybook);
|
|
12
|
+
const commandBuilder = (options, context) => {
|
|
13
|
+
const builder = from(setup(options, context)).pipe(switchMap(({ tsConfig }) => {
|
|
14
|
+
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
|
|
15
|
+
const runCompodoc$ = options.compodoc
|
|
16
|
+
? runCompodoc({
|
|
17
|
+
compodocArgs: [...options.compodocArgs, ...(options.quiet ? ['--silent'] : [])],
|
|
18
|
+
tsconfig: docTSConfig ?? tsConfig,
|
|
19
|
+
}, context).pipe(mapTo({ tsConfig }))
|
|
20
|
+
: of({});
|
|
21
|
+
return runCompodoc$.pipe(mapTo({ tsConfig }));
|
|
22
|
+
}), map(({ tsConfig }) => {
|
|
23
|
+
getEnvConfig(options, {
|
|
24
|
+
port: 'SBCONFIG_PORT',
|
|
25
|
+
host: 'SBCONFIG_HOSTNAME',
|
|
26
|
+
staticDir: 'SBCONFIG_STATIC_DIR',
|
|
27
|
+
configDir: 'SBCONFIG_CONFIG_DIR',
|
|
28
|
+
ci: 'CI',
|
|
29
|
+
});
|
|
30
|
+
options.port = parseInt(`${options.port}`, 10);
|
|
31
|
+
const { browserTarget, stylePreprocessorOptions, styles, ci, configDir, docs, host, https, port, quiet, enableProdMode = false, smokeTest, sslCa, sslCert, sslKey, disableTelemetry, assets, initialPath, open, debugWebpack, loglevel, webpackStatsJson, statsJson, previewUrl, sourceMap = false, preserveSymlinks = false, experimentalZoneless = false, } = options;
|
|
32
|
+
const standaloneOptions = {
|
|
33
|
+
packageJson: findPackageSync(__dirname),
|
|
34
|
+
ci,
|
|
35
|
+
configDir,
|
|
36
|
+
...(docs ? { docs } : {}),
|
|
37
|
+
host,
|
|
38
|
+
https,
|
|
39
|
+
port,
|
|
40
|
+
quiet,
|
|
41
|
+
enableProdMode,
|
|
42
|
+
smokeTest,
|
|
43
|
+
sslCa,
|
|
44
|
+
sslCert,
|
|
45
|
+
sslKey,
|
|
46
|
+
disableTelemetry,
|
|
47
|
+
angularBrowserTarget: browserTarget,
|
|
48
|
+
angularBuilderContext: context,
|
|
49
|
+
angularBuilderOptions: {
|
|
50
|
+
...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
|
|
51
|
+
...(styles ? { styles } : {}),
|
|
52
|
+
...(assets ? { assets } : {}),
|
|
53
|
+
preserveSymlinks,
|
|
54
|
+
sourceMap,
|
|
55
|
+
experimentalZoneless,
|
|
56
|
+
},
|
|
57
|
+
tsConfig,
|
|
58
|
+
initialPath,
|
|
59
|
+
open,
|
|
60
|
+
debugWebpack,
|
|
61
|
+
webpackStatsJson,
|
|
62
|
+
statsJson,
|
|
63
|
+
loglevel,
|
|
64
|
+
previewUrl,
|
|
65
|
+
};
|
|
66
|
+
return standaloneOptions;
|
|
67
|
+
}), switchMap((standaloneOptions) => runInstance(standaloneOptions)), map((port) => {
|
|
68
|
+
return { success: true, info: { port } };
|
|
69
|
+
}));
|
|
70
|
+
return builder;
|
|
71
|
+
};
|
|
72
|
+
export default createBuilder(commandBuilder);
|
|
73
|
+
async function setup(options, context) {
|
|
74
|
+
let browserOptions;
|
|
75
|
+
let browserTarget;
|
|
76
|
+
if (options.browserTarget) {
|
|
77
|
+
browserTarget = targetFromTargetString(options.browserTarget);
|
|
78
|
+
browserOptions = await context.validateOptions(await context.getTargetOptions(browserTarget), await context.getBuilderNameForTarget(browserTarget));
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
tsConfig: options.tsConfig ??
|
|
82
|
+
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
|
83
|
+
browserOptions.tsConfig,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function runInstance(options) {
|
|
87
|
+
return new Observable((observer) => {
|
|
88
|
+
// This Observable intentionally never complete, leaving the process running ;)
|
|
89
|
+
withTelemetry('dev', {
|
|
90
|
+
cliOptions: options,
|
|
91
|
+
presetOptions: { ...options, corePresets: [], overridePresets: [] },
|
|
92
|
+
printError: printErrorDetails,
|
|
93
|
+
}, () => buildDevStandalone(options))
|
|
94
|
+
.then(({ port }) => observer.next(port))
|
|
95
|
+
.catch((error) => {
|
|
96
|
+
observer.error(errorSummary(error));
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { Architect, createBuilder } from '@angular-devkit/architect';
|
|
2
|
+
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
|
3
|
+
import { schema } from '@angular-devkit/core';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
+
const buildDevStandaloneMock = vi.fn();
|
|
7
|
+
const buildStaticStandaloneMock = vi.fn();
|
|
8
|
+
const buildMock = {
|
|
9
|
+
buildDevStandalone: buildDevStandaloneMock,
|
|
10
|
+
buildStaticStandalone: buildStaticStandaloneMock,
|
|
11
|
+
withTelemetry: (_, __, fn) => fn(),
|
|
12
|
+
};
|
|
13
|
+
vi.doMock('storybook/internal/core-server', () => buildMock);
|
|
14
|
+
vi.doMock('find-up', () => ({ sync: () => './storybook/tsconfig.ts' }));
|
|
15
|
+
const mockRunScript = vi.fn();
|
|
16
|
+
vi.mock('storybook/internal/common', () => ({
|
|
17
|
+
getEnvConfig: (options) => options,
|
|
18
|
+
versions: {
|
|
19
|
+
storybook: 'x.x.x',
|
|
20
|
+
},
|
|
21
|
+
JsPackageManagerFactory: {
|
|
22
|
+
getPackageManager: () => ({
|
|
23
|
+
runPackageCommand: mockRunScript,
|
|
24
|
+
}),
|
|
25
|
+
},
|
|
26
|
+
}));
|
|
27
|
+
// Randomly fails on CI. TODO: investigate why
|
|
28
|
+
describe.skip('Start Storybook Builder', () => {
|
|
29
|
+
let architect;
|
|
30
|
+
let architectHost;
|
|
31
|
+
beforeEach(async () => {
|
|
32
|
+
const registry = new schema.CoreSchemaRegistry();
|
|
33
|
+
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
|
34
|
+
architectHost = new TestingArchitectHost();
|
|
35
|
+
architect = new Architect(architectHost, registry);
|
|
36
|
+
architectHost.addBuilder('@angular-devkit/build-angular:browser', createBuilder(() => {
|
|
37
|
+
return { success: true };
|
|
38
|
+
}));
|
|
39
|
+
architectHost.addTarget({ project: 'angular-cli', target: 'build-2' }, '@angular-devkit/build-angular:browser', {
|
|
40
|
+
outputPath: 'dist/angular-cli',
|
|
41
|
+
index: 'src/index.html',
|
|
42
|
+
main: 'src/main.ts',
|
|
43
|
+
polyfills: 'src/polyfills.ts',
|
|
44
|
+
tsConfig: 'src/tsconfig.app.json',
|
|
45
|
+
assets: ['src/favicon.ico', 'src/assets'],
|
|
46
|
+
styles: ['src/styles.css'],
|
|
47
|
+
scripts: [],
|
|
48
|
+
});
|
|
49
|
+
// This will either take a Node package name, or a path to the directory
|
|
50
|
+
// for the package.json file.
|
|
51
|
+
await architectHost.addBuilderFromPackage(join(__dirname, '../../..'));
|
|
52
|
+
});
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
buildDevStandaloneMock.mockImplementation((_options) => Promise.resolve(_options));
|
|
55
|
+
});
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
vi.clearAllMocks();
|
|
58
|
+
});
|
|
59
|
+
it('should start storybook with angularBrowserTarget', async () => {
|
|
60
|
+
const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
|
|
61
|
+
browserTarget: 'angular-cli:build-2',
|
|
62
|
+
port: 4400,
|
|
63
|
+
compodoc: false,
|
|
64
|
+
});
|
|
65
|
+
const output = await run.result;
|
|
66
|
+
await run.stop();
|
|
67
|
+
expect(output.success).toBeTruthy();
|
|
68
|
+
expect(mockRunScript).not.toHaveBeenCalledWith();
|
|
69
|
+
expect(buildDevStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
70
|
+
angularBrowserTarget: 'angular-cli:build-2',
|
|
71
|
+
angularBuilderContext: expect.any(Object),
|
|
72
|
+
ci: false,
|
|
73
|
+
configDir: '.storybook',
|
|
74
|
+
disableTelemetry: undefined,
|
|
75
|
+
host: 'localhost',
|
|
76
|
+
https: false,
|
|
77
|
+
packageJson: expect.any(Object),
|
|
78
|
+
port: 4400,
|
|
79
|
+
quiet: false,
|
|
80
|
+
smokeTest: false,
|
|
81
|
+
sslCa: undefined,
|
|
82
|
+
sslCert: undefined,
|
|
83
|
+
sslKey: undefined,
|
|
84
|
+
tsConfig: './storybook/tsconfig.ts',
|
|
85
|
+
}));
|
|
86
|
+
});
|
|
87
|
+
it('should start storybook with tsConfig', async () => {
|
|
88
|
+
const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
|
|
89
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
90
|
+
port: 4400,
|
|
91
|
+
compodoc: false,
|
|
92
|
+
});
|
|
93
|
+
const output = await run.result;
|
|
94
|
+
await run.stop();
|
|
95
|
+
expect(output.success).toBeTruthy();
|
|
96
|
+
expect(mockRunScript).not.toHaveBeenCalledWith();
|
|
97
|
+
expect(buildDevStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
98
|
+
angularBrowserTarget: null,
|
|
99
|
+
angularBuilderContext: expect.any(Object),
|
|
100
|
+
ci: false,
|
|
101
|
+
configDir: '.storybook',
|
|
102
|
+
disableTelemetry: undefined,
|
|
103
|
+
host: 'localhost',
|
|
104
|
+
https: false,
|
|
105
|
+
packageJson: expect.any(Object),
|
|
106
|
+
port: 4400,
|
|
107
|
+
quiet: false,
|
|
108
|
+
smokeTest: false,
|
|
109
|
+
sslCa: undefined,
|
|
110
|
+
sslCert: undefined,
|
|
111
|
+
sslKey: undefined,
|
|
112
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
113
|
+
}));
|
|
114
|
+
});
|
|
115
|
+
it('should throw error', async () => {
|
|
116
|
+
buildDevStandaloneMock.mockRejectedValue(true);
|
|
117
|
+
const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
|
|
118
|
+
browserTarget: 'angular-cli:build-2',
|
|
119
|
+
port: 4400,
|
|
120
|
+
compodoc: false,
|
|
121
|
+
});
|
|
122
|
+
try {
|
|
123
|
+
await run.result;
|
|
124
|
+
expect(false).toEqual('Throw expected');
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
expect(error).toEqual('Broken build, fix the error above.\nYou may need to refresh the browser.');
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
it('should run compodoc', async () => {
|
|
131
|
+
const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
|
|
132
|
+
browserTarget: 'angular-cli:build-2',
|
|
133
|
+
});
|
|
134
|
+
const output = await run.result;
|
|
135
|
+
await run.stop();
|
|
136
|
+
expect(output.success).toBeTruthy();
|
|
137
|
+
expect(mockRunScript).toHaveBeenCalledWith('compodoc', ['-p', './storybook/tsconfig.ts', '-d', '.', '-e', 'json'], '');
|
|
138
|
+
expect(buildDevStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
139
|
+
angularBrowserTarget: 'angular-cli:build-2',
|
|
140
|
+
angularBuilderContext: expect.any(Object),
|
|
141
|
+
ci: false,
|
|
142
|
+
disableTelemetry: undefined,
|
|
143
|
+
configDir: '.storybook',
|
|
144
|
+
host: 'localhost',
|
|
145
|
+
https: false,
|
|
146
|
+
packageJson: expect.any(Object),
|
|
147
|
+
port: 9009,
|
|
148
|
+
quiet: false,
|
|
149
|
+
smokeTest: false,
|
|
150
|
+
sslCa: undefined,
|
|
151
|
+
sslCert: undefined,
|
|
152
|
+
sslKey: undefined,
|
|
153
|
+
tsConfig: './storybook/tsconfig.ts',
|
|
154
|
+
}));
|
|
155
|
+
});
|
|
156
|
+
it('should start storybook with styles options', async () => {
|
|
157
|
+
const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
|
|
158
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
159
|
+
port: 4400,
|
|
160
|
+
compodoc: false,
|
|
161
|
+
styles: ['src/styles.css'],
|
|
162
|
+
});
|
|
163
|
+
const output = await run.result;
|
|
164
|
+
await run.stop();
|
|
165
|
+
expect(output.success).toBeTruthy();
|
|
166
|
+
expect(mockRunScript).not.toHaveBeenCalledWith();
|
|
167
|
+
expect(buildDevStandaloneMock).toHaveBeenCalledWith({
|
|
168
|
+
angularBrowserTarget: null,
|
|
169
|
+
angularBuilderContext: expect.any(Object),
|
|
170
|
+
angularBuilderOptions: { assets: [], styles: ['src/styles.css'] },
|
|
171
|
+
disableTelemetry: undefined,
|
|
172
|
+
ci: false,
|
|
173
|
+
configDir: '.storybook',
|
|
174
|
+
host: 'localhost',
|
|
175
|
+
https: false,
|
|
176
|
+
port: 4400,
|
|
177
|
+
packageJson: expect.any(Object),
|
|
178
|
+
quiet: false,
|
|
179
|
+
smokeTest: false,
|
|
180
|
+
sslCa: undefined,
|
|
181
|
+
sslCert: undefined,
|
|
182
|
+
sslKey: undefined,
|
|
183
|
+
tsConfig: 'path/to/tsConfig.json',
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
"browserTarget": {
|
|
8
8
|
"type": "string",
|
|
9
9
|
"description": "Build target to be served in project-name:builder:config format. Should generally target on the builder: '@angular-devkit/build-angular:browser'. Useful for Storybook to use options (styles, assets, ...).",
|
|
10
|
-
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
|
|
11
|
-
"default": null
|
|
10
|
+
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
|
|
12
11
|
},
|
|
13
12
|
"debugWebpack": {
|
|
14
13
|
"type": "boolean",
|
|
@@ -104,8 +103,7 @@
|
|
|
104
103
|
"description": "Global styles to be included in the build.",
|
|
105
104
|
"items": {
|
|
106
105
|
"$ref": "#/definitions/styleElement"
|
|
107
|
-
}
|
|
108
|
-
"default": ""
|
|
106
|
+
}
|
|
109
107
|
},
|
|
110
108
|
"stylePreprocessorOptions": {
|
|
111
109
|
"description": "Options to pass to style preprocessors.",
|
|
@@ -119,8 +117,7 @@
|
|
|
119
117
|
}
|
|
120
118
|
}
|
|
121
119
|
},
|
|
122
|
-
"additionalProperties": false
|
|
123
|
-
"default": ""
|
|
120
|
+
"additionalProperties": false
|
|
124
121
|
},
|
|
125
122
|
"assets": {
|
|
126
123
|
"type": "array",
|