Skip to content

Commit

Permalink
Add docs option and use to drive the indexer
Browse files Browse the repository at this point in the history
  • Loading branch information
tmeasday committed Jun 26, 2022
1 parent d27c826 commit b0873ad
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 27 deletions.
13 changes: 11 additions & 2 deletions addons/docs/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import remarkSlug from 'remark-slug';
import remarkExternalLinks from 'remark-external-links';
import global from 'global';

import type { IndexerOptions, Options, StoryIndexer } from '@storybook/core-common';
import type { DocsOptions, IndexerOptions, Options, StoryIndexer } from '@storybook/core-common';
import { logger } from '@storybook/node-logger';
import { loadCsf } from '@storybook/csf-tools';

Expand Down Expand Up @@ -137,7 +137,7 @@ export async function webpack(
return result;
}

export const storyIndexers = async (indexers?: StoryIndexer[]) => {
export const storyIndexers = async (indexers: StoryIndexer[] | null) => {
const mdxIndexer = async (fileName: string, opts: IndexerOptions) => {
let code = (await fs.readFile(fileName, 'utf-8')).toString();
// @ts-ignore
Expand All @@ -155,3 +155,12 @@ export const storyIndexers = async (indexers?: StoryIndexer[]) => {
...(indexers || []),
];
};

export const docs = (docsOptions: DocsOptions) => {
return {
...docsOptions,
enabled: true,
defaultName: 'Docs',
docsPage: true,
};
};
5 changes: 5 additions & 0 deletions examples/react-ts/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const config: StorybookConfig = {
'@storybook/addon-storyshots',
'@storybook/addon-a11y',
],
docs: {
// enabled: false,
defaultName: 'Info',
// docsPage: false,
},
typescript: {
check: true,
checkOptions: {},
Expand Down
20 changes: 20 additions & 0 deletions lib/core-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,21 @@ export type Entry = string;

type StorybookRefs = Record<string, { title: string; url: string } | { disable: boolean }>;

export type DocsOptions = {
/**
* Should we generate docs entries at all under any circumstances? (i.e. can they be rendered)
*/
enabled?: boolean;
/**
* What should we call the generated docs entries?
*/
defaultName?: string;
/**
* Should we generate a docs entry per CSF file?
*/
docsPage?: boolean;
};

/**
* The interface for Storybook configuration in `main.ts` files.
*/
Expand Down Expand Up @@ -434,4 +449,9 @@ export interface StorybookConfig {
* Process CSF files for the story index.
*/
storyIndexers?: (indexers: StoryIndexer[], options: Options) => StoryIndexer[];

/**
* Docs related features in index generation
*/
docs?: DocsOptions;
}
3 changes: 3 additions & 0 deletions lib/core-server/src/build-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
Options,
StorybookConfig,
CoreConfig,
DocsOptions,
} from '@storybook/core-common';
import {
loadAllPresets,
Expand Down Expand Up @@ -128,10 +129,12 @@ export async function buildStaticStandalone(
};
const normalizedStories = normalizeStories(await presets.apply('stories'), directories);
const storyIndexers = await presets.apply('storyIndexers', []);
const docsOptions = await presets.apply<DocsOptions>('docs', {});

const generator = new StoryIndexGenerator(normalizedStories, {
...directories,
storyIndexers,
docs: docsOptions,
storiesV2Compatibility: !features?.breakingChangesV7 && !features?.storyStoreV7,
storyStoreV7: !!features?.storyStoreV7,
});
Expand Down
1 change: 0 additions & 1 deletion lib/core-server/src/core-presets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ describe.each([
['prod', buildStaticStandalone],
['dev', buildDevStandalone],
])('%s', async (mode, builder) => {
console.log('running for ', mode, builder);
const options = {
...baseOptions,
configDir: path.resolve(`${__dirname}/../../../examples/${example}/.storybook`),
Expand Down
12 changes: 10 additions & 2 deletions lib/core-server/src/dev-server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import express, { Router } from 'express';
import compression from 'compression';

import type { CoreConfig, Options, StorybookConfig } from '@storybook/core-common';
import { normalizeStories, logConfig } from '@storybook/core-common';
import {
CoreConfig,
DocsOptions,
Options,
StorybookConfig,
normalizeStories,
logConfig,
} from '@storybook/core-common';

import { telemetry } from '@storybook/telemetry';
import { getMiddleware } from './utils/middleware';
Expand Down Expand Up @@ -44,10 +50,12 @@ export async function storybookDevServer(options: Options) {
directories
);
const storyIndexers = await options.presets.apply('storyIndexers', []);
const docsOptions = await options.presets.apply<DocsOptions>('docs', {});

const generator = new StoryIndexGenerator(normalizedStories, {
...directories,
storyIndexers,
docs: docsOptions,
workingDir,
storiesV2Compatibility: !features?.breakingChangesV7 && !features?.storyStoreV7,
storyStoreV7: features?.storyStoreV7,
Expand Down
75 changes: 61 additions & 14 deletions lib/core-server/src/utils/StoryIndexGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const options = {
storyIndexers: [{ test: /\.stories\..*$/, indexer: csfIndexer }],
storiesV2Compatibility: false,
storyStoreV7: true,
docs: { enabled: true, defaultName: 'docs', docsPage: true },
};

describe('StoryIndexGenerator', () => {
Expand Down Expand Up @@ -175,16 +176,15 @@ describe('StoryIndexGenerator', () => {
});

describe('docs specifier', () => {
const storiesSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./src/A.stories.(ts|js|jsx)',
options
);
const docsSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./src/**/*.mdx',
options
);
it('extracts stories from the right files', async () => {
const storiesSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./src/A.stories.(ts|js|jsx)',
options
);
const docsSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./src/**/*.mdx',
options
);

const generator = new StoryIndexGenerator([storiesSpecifier, docsSpecifier], options);
await generator.initialize();

Expand Down Expand Up @@ -231,16 +231,63 @@ describe('StoryIndexGenerator', () => {
});

it('errors when docs dependencies are missing', async () => {
const docsSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./src/**/MetaOf.mdx',
options
);

const generator = new StoryIndexGenerator([docsSpecifier], options);
await expect(() => generator.initialize()).rejects.toThrowErrorMatchingInlineSnapshot(
`"Could not find \\"../A.stories\\" for docs file \\"src/docs2/MetaOf.mdx\\"."`
);
});

it('Allows you to override default name for docs files', async () => {
const generator = new StoryIndexGenerator([storiesSpecifier, docsSpecifier], {
...options,
docs: {
...options.docs,
defaultName: 'Info',
},
});
await generator.initialize();

expect(await generator.getIndex()).toMatchInlineSnapshot(`
Object {
"entries": Object {
"a--info": Object {
"id": "a--info",
"importPath": "./src/docs2/MetaOf.mdx",
"name": "Info",
"storiesImports": Array [
"./src/A.stories.js",
],
"title": "A",
"type": "docs",
},
"a--story-one": Object {
"id": "a--story-one",
"importPath": "./src/A.stories.js",
"name": "Story One",
"title": "A",
"type": "story",
},
"docs2-notitle--info": Object {
"id": "docs2-notitle--info",
"importPath": "./src/docs2/NoTitle.mdx",
"name": "Info",
"storiesImports": Array [],
"title": "docs2/NoTitle",
"type": "docs",
},
"docs2-yabbadabbadooo--info": Object {
"id": "docs2-yabbadabbadooo--info",
"importPath": "./src/docs2/Title.mdx",
"name": "Info",
"storiesImports": Array [],
"title": "docs2/Yabbadabbadooo",
"type": "docs",
},
},
"v": 4,
}
`);
});
});
});

Expand Down
25 changes: 17 additions & 8 deletions lib/core-server/src/utils/StoryIndexGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
StoryIndexer,
IndexerOptions,
NormalizedStoriesSpecifier,
DocsOptions,
} from '@storybook/core-common';
import { normalizeStoryPath } from '@storybook/core-common';
import { logger } from '@storybook/node-logger';
Expand Down Expand Up @@ -56,6 +57,7 @@ export class StoryIndexGenerator {
storiesV2Compatibility: boolean;
storyStoreV7: boolean;
storyIndexers: StoryIndexer[];
docs: DocsOptions;
}
) {
this.specifierToCache = new Map();
Expand Down Expand Up @@ -120,9 +122,12 @@ export class StoryIndexGenerator {
await this.updateExtracted(async (specifier, absolutePath) =>
this.isDocsMdx(absolutePath) ? false : this.extractStories(specifier, absolutePath)
);
await this.updateExtracted(async (specifier, absolutePath) =>
this.extractDocs(specifier, absolutePath)
);

if (this.options.docs.enabled) {
await this.updateExtracted(async (specifier, absolutePath) =>
this.extractDocs(specifier, absolutePath)
);
}

return this.specifiers.flatMap((specifier) => {
const cache = this.specifierToCache.get(specifier);
Expand Down Expand Up @@ -217,7 +222,7 @@ export class StoryIndexGenerator {
});

const title = userOrAutoTitleFromSpecifier(importPath, specifier, result.title || ofTitle);
const name = 'docs';
const name = this.options.docs.defaultName;
const id = toId(title, name);

const docsEntry: DocsCacheEntry = {
Expand Down Expand Up @@ -254,10 +259,14 @@ export class StoryIndexGenerator {
const csf = await this.index(absolutePath, { makeTitle });
csf.stories.forEach(({ id, name, parameters }) => {
const base = { id, title: csf.meta.title, name, importPath };
const entry: IndexEntry = parameters?.docsOnly
? { ...base, type: 'docs', storiesImports: [], legacy: true }
: { ...base, type: 'story' };
entries.push(entry);

if (parameters?.docsOnly) {
if (this.options.docs.enabled) {
entries.push({ ...base, type: 'docs', storiesImports: [], legacy: true });
}
} else {
entries.push({ ...base, type: 'story' });
}
});
} catch (err) {
if (err.name === 'NoMetaError') {
Expand Down
1 change: 1 addition & 0 deletions lib/core-server/src/utils/stories-json.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const getInitializedStoryIndexGenerator = async (
workingDir,
storiesV2Compatibility: false,
storyStoreV7: true,
docs: { enabled: true, defaultName: 'docs', docsPage: true },
...overrides,
});
await generator.initialize();
Expand Down

0 comments on commit b0873ad

Please sign in to comment.