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

Core: Update index generation to use tags to detect MDX stories #19712

Merged
merged 10 commits into from
Nov 7, 2022
4 changes: 2 additions & 2 deletions code/addons/docs/jest-transform-mdx.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ const path = require('path');
const { ScriptTransformer } = require('@jest/transform');
const { dedent } = require('ts-dedent');

const { compileAsync } = require('@storybook/mdx2-csf');
const { compile } = require('@storybook/mdx2-csf');

module.exports = {
async processAsync(src, filename, config, { instrument }) {
const code = await compileAsync(src, { skipCsf: false });
const code = await compile(src, { skipCsf: false });
const result = dedent`
/* @jsx mdx */
import React from 'react'
Expand Down
4 changes: 1 addition & 3 deletions code/addons/docs/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,9 @@ export async function webpack(
return result;
}

export const storyIndexers = async (indexers: CoreCommon_StoryIndexer[] | null) => {
export const storyIndexers = (indexers: CoreCommon_StoryIndexer[] | null) => {
const mdxIndexer = async (fileName: string, opts: CoreCommon_IndexerOptions) => {
let code = (await fs.readFile(fileName, 'utf-8')).toString();
// @ts-expect-error (Converted from ts-ignore)
const { compile } = await import('@storybook/mdx2-csf');
code = await compile(code, {});
return loadCsf(code, { ...opts, fileName }).parse();
Expand All @@ -172,7 +171,6 @@ export const storyIndexers = async (indexers: CoreCommon_StoryIndexer[] | null)
{
test: /(stories|story)\.mdx$/,
indexer: mdxIndexer,
addDocsTemplate: true,
},
...(indexers || []),
];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Meta, Story, Canvas } from '@storybook/addon-docs';
import { Meta, Story, Canvas, ArgsTable } from '@storybook/addon-docs';
import globalThis from 'global';
import * as Csf from './csf-in-mdx.stories.js';

Expand Down
1 change: 0 additions & 1 deletion code/lib/builder-vite/src/plugins/mdx-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export function mdxPlugin(): Plugin {
async transform(src, id, options) {
if (!filter(id)) return undefined;

// @ts-expect-error typescript doesn't think compile exists, but it does.
const { compile } = await import('@storybook/mdx2-csf');

const mdxCode = String(await compile(src, { skipCsf: !isStorybookMdx(id) }));
Expand Down
3 changes: 1 addition & 2 deletions code/lib/client-api/src/StoryStoreFacade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ export class StoryStoreFacade<TFramework extends AnyFramework> {
docsOptions.docsPage === 'automatic' ||
(docsOptions.docsPage && componentTags.includes('docsPage'));
if (docsOptions.enabled && storyExports.length) {
// We will use tags soon and this crappy filename test will go away
if (fileName.match(/\.mdx$/) || docsPageOptedIn) {
if (componentTags.includes('mdx') || docsPageOptedIn) {
const name = docsOptions.defaultName;
const docsId = toId(componentId || title, name);
this.entries[docsId] = {
Expand Down
3 changes: 2 additions & 1 deletion code/lib/core-client/src/start.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ describe('start', () => {
'test',
makeRequireContext({
'./Introduction.stories.mdx': {
default: { title: 'Introduction' },
default: { title: 'Introduction', tags: ['mdx'] },
_Page: { name: 'Page', parameters: { docsOnly: true } },
},
})
Expand All @@ -979,6 +979,7 @@ describe('start', () => {
"standalone": false,
"storiesImports": Array [],
"tags": Array [
"mdx",
"docs",
],
"title": "Introduction",
Expand Down
55 changes: 34 additions & 21 deletions code/lib/core-server/src/utils/StoryIndexGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ jest.mock('@storybook/docs-mdx', async () => ({
const name = content.match(/name=['"](.*)['"]/)?.[1];
const ofMatch = content.match(/of=\{(.*)\}/)?.[1];
const isTemplate = content.match(/isTemplate/);
return { title, name, imports, of: ofMatch && imports.length && imports[0], isTemplate };
const tags = ['mdx'];
return { title, name, tags, imports, of: ofMatch && imports.length && imports[0], isTemplate };
},
}));

Expand All @@ -50,12 +51,20 @@ const csfIndexer = async (fileName: string, opts: any) => {
return loadCsf(code, { ...opts, fileName }).parse();
};

const storiesMdxIndexer = async (fileName: string, opts: any) => {
let code = (await fs.readFile(fileName, 'utf-8')).toString();
const { compile } = await import('@storybook/mdx2-csf');
code = await compile(code, {});
return loadCsf(code, { ...opts, fileName }).parse();
};

const options = {
configDir: path.join(__dirname, '__mockdata__'),
workingDir: path.join(__dirname, '__mockdata__'),
storyIndexers: [
{ test: /\.stories\..*$/, indexer: csfIndexer as any as CoreCommon_StoryIndexer['indexer'] },
],
{ test: /\.stories\.mdx$/, indexer: storiesMdxIndexer },
{ test: /\.stories\.(js|ts)x?$/, indexer: csfIndexer },
] as CoreCommon_StoryIndexer[],
storiesV2Compatibility: false,
storyStoreV7: true,
docs: { enabled: true, defaultName: 'docs', docsPage: false },
Expand Down Expand Up @@ -232,47 +241,43 @@ describe('StoryIndexGenerator', () => {
});
});

describe('addDocsTemplate indexer', () => {
const templateIndexer = { ...options.storyIndexers[0], addDocsTemplate: true };

describe('mdx tagged components', () => {
it('adds docs entry with docs enabled', async () => {
const specifier: CoreCommon_NormalizedStoriesSpecifier = normalizeStoriesEntry(
'./src/A.stories.js',
'./src/nested/Page.stories.mdx',
options
);

const generator = new StoryIndexGenerator([specifier], {
...options,
storyIndexers: [templateIndexer],
});
await generator.initialize();

expect(await generator.getIndex()).toMatchInlineSnapshot(`
Object {
"entries": Object {
"a--docs": Object {
"id": "a--docs",
"importPath": "./src/A.stories.js",
"page--docs": Object {
"id": "page--docs",
"importPath": "./src/nested/Page.stories.mdx",
"name": "docs",
"standalone": false,
"storiesImports": Array [],
"tags": Array [
"component-tag",
"docsPage",
"mdx",
"docs",
],
"title": "A",
"title": "Page",
"type": "docs",
},
"a--story-one": Object {
"id": "a--story-one",
"importPath": "./src/A.stories.js",
"name": "Story One",
"page--story-one": Object {
"id": "page--story-one",
"importPath": "./src/nested/Page.stories.mdx",
"name": "StoryOne",
"tags": Array [
"story-tag",
"mdx",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just confirming that the mdx tag here means that the story was generated from MDX. Do we want that? It could be confusing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was intentional on my part anyway. Happy to change the tag from mdx if it is confusing that a story can be "mdx". To me it makes sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WFM after letting it settle in

"story",
],
"title": "A",
"title": "Page",
"type": "story",
},
},
Expand All @@ -288,7 +293,6 @@ describe('StoryIndexGenerator', () => {

const generator = new StoryIndexGenerator([specifier], {
...options,
storyIndexers: [templateIndexer],
docs: { enabled: false },
});
await generator.initialize();
Expand Down Expand Up @@ -500,6 +504,7 @@ describe('StoryIndexGenerator', () => {
"./src/A.stories.js",
],
"tags": Array [
"mdx",
"docs",
],
"title": "A",
Expand Down Expand Up @@ -613,6 +618,7 @@ describe('StoryIndexGenerator', () => {
"./src/A.stories.js",
],
"tags": Array [
"mdx",
"docs",
],
"title": "A",
Expand All @@ -627,6 +633,7 @@ describe('StoryIndexGenerator', () => {
"./src/A.stories.js",
],
"tags": Array [
"mdx",
"docs",
],
"title": "A",
Expand All @@ -650,6 +657,7 @@ describe('StoryIndexGenerator', () => {
"standalone": true,
"storiesImports": Array [],
"tags": Array [
"mdx",
"docs",
],
"title": "docs2/Yabbadabbadooo",
Expand All @@ -662,6 +670,7 @@ describe('StoryIndexGenerator', () => {
"standalone": true,
"storiesImports": Array [],
"tags": Array [
"mdx",
"docs",
],
"title": "NoTitle",
Expand Down Expand Up @@ -752,6 +761,7 @@ describe('StoryIndexGenerator', () => {
"./src/A.stories.js",
],
"tags": Array [
"mdx",
"docs",
],
"title": "A",
Expand All @@ -766,6 +776,7 @@ describe('StoryIndexGenerator', () => {
"./src/A.stories.js",
],
"tags": Array [
"mdx",
"docs",
],
"title": "A",
Expand All @@ -789,6 +800,7 @@ describe('StoryIndexGenerator', () => {
"standalone": true,
"storiesImports": Array [],
"tags": Array [
"mdx",
"docs",
],
"title": "docs2/Yabbadabbadooo",
Expand All @@ -801,6 +813,7 @@ describe('StoryIndexGenerator', () => {
"standalone": true,
"storiesImports": Array [],
"tags": Array [
"mdx",
"docs",
],
"title": "NoTitle",
Expand Down
7 changes: 4 additions & 3 deletions code/lib/core-server/src/utils/StoryIndexGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,10 @@ export class StoryIndexGenerator {
const { docsPage } = this.options.docs;
const docsPageOptedIn =
docsPage === 'automatic' || (docsPage && componentTags.includes('docsPage'));
// We always add a template for *.stories.mdx, but only if docs page is enabled for
// regular CSF files
if (storyIndexer.addDocsTemplate || docsPageOptedIn) {
// We need a docs entry attached to the CSF file if either:
// a) it is a stories.mdx transpiled to CSF, OR
// b) we have docs page enabled for this file
if (componentTags.includes('mdx') || docsPageOptedIn) {
const name = this.options.docs.defaultName;
const id = toId(csf.meta.title, name);
entries.unshift({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Meta, Story } from '@storybook/addon-docs';

<Meta component={{}} />;
<Meta component={{}} />

<Story name="StoryOne" />
Loading