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

Autodocs: Fix docs pages ignoring meta.id when calculating their ID #23520

Merged
merged 10 commits into from
Aug 1, 2023
88 changes: 88 additions & 0 deletions code/lib/core-server/src/utils/StoryIndexGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,47 @@ describe('StoryIndexGenerator', () => {
}
`);
});

it('prioritizes using the component id over meta.title for generating its id, if provided. (autodocs)', async () => {
const csfSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./docs-id-generation/A.stories.jsx',
options
);

const generator = new StoryIndexGenerator([csfSpecifier], autodocsOptions);
await generator.initialize();

expect(await generator.getIndex()).toMatchInlineSnapshot(`
Object {
"entries": Object {
"my-component-a--docs": Object {
"id": "my-component-a--docs",
"importPath": "./docs-id-generation/A.stories.jsx",
"name": "docs",
"storiesImports": Array [],
"tags": Array [
"autodocs",
"docs",
],
"title": "A",
"type": "docs",
},
"my-component-a--story-one": Object {
"id": "my-component-a--story-one",
"importPath": "./docs-id-generation/A.stories.jsx",
"name": "Story One",
"tags": Array [
"autodocs",
"story",
],
"title": "A",
"type": "story",
},
},
"v": 4,
}
`);
});
});

describe('docs specifier', () => {
Expand Down Expand Up @@ -1016,6 +1057,53 @@ describe('StoryIndexGenerator', () => {
}
`);
});

it('prioritizes using the component id over meta.title for generating its id, if provided. (mdx docs)', async () => {
const csfSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./docs-id-generation/B.stories.jsx',
options
);

const docsSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./docs-id-generation/B.docs.mdx',
options
);

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

expect(await generator.getIndex()).toMatchInlineSnapshot(`
Object {
"entries": Object {
"my-component-b--docs": Object {
"id": "my-component-b--docs",
"importPath": "./docs-id-generation/B.docs.mdx",
"name": "docs",
"storiesImports": Array [
"./docs-id-generation/B.stories.jsx",
],
"tags": Array [
"attached-mdx",
"docs",
],
"title": "B",
"type": "docs",
},
"my-component-b--story-one": Object {
"id": "my-component-b--story-one",
"importPath": "./docs-id-generation/B.stories.jsx",
"name": "Story One",
"tags": Array [
"story",
],
"title": "B",
"type": "story",
},
},
"v": 4,
}
`);
});
});

describe('errors', () => {
Expand Down
27 changes: 22 additions & 5 deletions code/lib/core-server/src/utils/StoryIndexGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type ErrorEntry = {
};
type CacheEntry = false | StoriesCacheEntry | DocsCacheEntry | ErrorEntry;
type SpecifierStoriesCache = Record<Path, CacheEntry>;
// Extended type to keep track of the csf meta so we know the component id when referencing docs in `extractDocs`
type StoryIndexEntryWithMeta = StoryIndexEntry & { meta?: any };
sookmax marked this conversation as resolved.
Show resolved Hide resolved

export const AUTODOCS_TAG = 'autodocs';
export const STORIES_MDX_TAG = 'stories-mdx';
Expand Down Expand Up @@ -217,7 +219,13 @@ export class StoryIndexGenerator {
if (!entry) return [];
if (entry.type === 'docs') return [entry];
if (entry.type === 'error') return [entry];
return entry.entries;

return entry.entries.map((item) => {
if (item.type === 'docs') return item;
// Drop the meta as it isn't part of the index, we just used it for record keeping in `extractDocs`
const { meta, ...existing } = item as StoryIndexEntryWithMeta;
return existing;
});
});
});
}
Expand Down Expand Up @@ -260,7 +268,16 @@ export class StoryIndexGenerator {
csf.stories.forEach(({ id, name, tags: storyTags, parameters }) => {
if (!parameters?.docsOnly) {
const tags = [...(storyTags || componentTags), 'story'];
entries.push({ id, title: csf.meta.title, name, importPath, tags, type: 'story' });
entries.push({
id,
title: csf.meta.title,
name,
importPath,
tags,
type: 'story',
// We need to keep track of the csf meta so we know the component id when referencing docs below in `extractDocs`
meta: csf.meta,
sookmax marked this conversation as resolved.
Show resolved Hide resolved
} as StoryIndexEntryWithMeta);
}
});

Expand All @@ -273,7 +290,7 @@ export class StoryIndexGenerator {
// b) we have docs page enabled for this file
if (componentTags.includes(STORIES_MDX_TAG) || autodocsOptedIn) {
const name = this.options.docs.defaultName;
const id = toId(csf.meta.title, name);
const id = toId(csf.meta.id || csf.meta.title, name);
entries.unshift({
id,
title: csf.meta.title,
Expand Down Expand Up @@ -332,7 +349,7 @@ export class StoryIndexGenerator {

// Also, if `result.of` is set, it means that we're using the `<Meta of={XStories} />` syntax,
// so find the `title` defined the file that `meta` points to.
let csfEntry: StoryIndexEntry;
let csfEntry: StoryIndexEntryWithMeta;
if (result.of) {
const absoluteOf = makeAbsolute(result.of, normalizedPath, this.options.workingDir);
dependencies.forEach((dep) => {
Expand Down Expand Up @@ -373,7 +390,7 @@ export class StoryIndexGenerator {
const name =
result.name ||
(csfEntry ? autoName(importPath, csfEntry.importPath, defaultName) : defaultName);
const id = toId(title, name);
const id = toId(csfEntry?.meta?.id || title, name);

const docsEntry: DocsCacheEntry = {
id,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Stories for a component with meta.id
const component = {};
export default {
id: 'my-component-A',
component,
tags: ['autodocs'],
};

export const StoryOne = {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as Stories from './B.stories';

<Meta of={Stories} />

# Docs with of

hello docs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Stories for a component with meta.id
const component = {};
export default {
id: 'my-component-B',
component,
};

export const StoryOne = {};
2 changes: 1 addition & 1 deletion code/lib/types/src/modules/storyIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface IndexedStory {
parameters?: Parameters;
}
export interface IndexedCSFFile {
meta: { title?: string; tags?: Tag[] };
meta: { id?: string; title?: string; tags?: Tag[] };
stories: IndexedStory[];
}

Expand Down