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

Source-loader: Handle template strings in CSF title #8995

Merged
merged 9 commits into from Dec 2, 2019
Expand Up @@ -3,8 +3,10 @@ import notes from '../notes/notes.md';
import mdxNotes from '../notes/notes.mdx';
import { DocgenButton } from '../../components/DocgenButton';

const docsTitle = title => `Docs/${title}`;

export default {
title: 'Addons/Docs/stories',
title: `Addons/${docsTitle('stories')}`,
component: DocgenButton,
};

Expand Down
Expand Up @@ -96,31 +96,40 @@ export function findExportsMap(ast) {
if (!titleProperty) {
return { addsMap, idsToFrameworks };
}
const title = titleProperty.value.value;

estraverse.traverse(ast, {
fallback: 'iteration',
enter: node => {
patchNode(node);
if (
node.type === 'ExportNamedDeclaration' &&
node.declaration &&
node.declaration.declarations &&
node.declaration.declarations.length === 1 &&
node.declaration.declarations[0].type === 'VariableDeclarator' &&
node.declaration.declarations[0].id &&
node.declaration.declarations[0].id.name &&
node.declaration.declarations[0].init &&
['CallExpression', 'ArrowFunctionExpression', 'FunctionExpression'].includes(
node.declaration.declarations[0].init.type
)
) {
const storyName = storyNameFromExport(node.declaration.declarations[0].id.name);
const toAdd = handleExportedName(title, storyName, node.declaration.declarations[0].init);
Object.assign(addsMap, toAdd);
}
},
});
const titleValue = titleProperty.value;
let title;
if (titleValue.type === 'TemplateLiteral' && titleValue.quasis.length > 0) {
// if a tagged template string.
title = titleValue.quasis[0].value.raw;
Copy link
Member

@ndelangen ndelangen Nov 29, 2019

Choose a reason for hiding this comment

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

I suppose the support is actually quite limited?

import mdxNotes from '../notes/notes.mdx';
import { DocgenButton } from '../../components/DocgenButton';


const stories = () => 'Stories';

export default {
  title: `Addons/Docs/${stories()}`,
  component: DocgenButton,
};

wouldn't actually work?

Copy link
Member Author

Choose a reason for hiding this comment

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

works, I tried the following more real-life examples:

const docsTitle = title => `Docs/${title}`;
export default {
  title: `Addons/${docsTitle('Stories')}`,
};

or

import { DocgenButton } from '../../components/DocgenButton';
export default {
  title: `Addons/Docs/${DocgenButton.displayName}`,
};

and similar.

For other cases like expressions, dynamic functions etc - I assume there is some library that does ast node value evaluation, but I couldn't find one.

I checked in a better example and made the behavior backwards compatible for non-strings

Copy link
Contributor

Choose a reason for hiding this comment

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

What about paths.macro? Can it evaluate that correctly?

import * as React from 'react'
import base from 'paths.macro'

export default {
  title: `${base}`
}

export const example = () => <div />

Copy link
Member Author

Choose a reason for hiding this comment

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

The evaluation itself works fine. However there are some rules for titles - it can not finish in /.

for example we have:
import base from 'paths.macro'

that evaluates to /stories/addon-docs/

In the case those will work:

title: `Docs${base}Story`,
title: `${base}Story`,

However currently this will not work directly (ends in /):
title: `Docs${base}`

} else {
// if title is string: 'StringLiteral'
title = titleProperty.value.value;
}
if (title) {
estraverse.traverse(ast, {
fallback: 'iteration',
enter: node => {
patchNode(node);
if (
node.type === 'ExportNamedDeclaration' &&
node.declaration &&
node.declaration.declarations &&
node.declaration.declarations.length === 1 &&
node.declaration.declarations[0].type === 'VariableDeclarator' &&
node.declaration.declarations[0].id &&
node.declaration.declarations[0].id.name &&
node.declaration.declarations[0].init &&
['CallExpression', 'ArrowFunctionExpression', 'FunctionExpression'].includes(
node.declaration.declarations[0].init.type
)
) {
const storyName = storyNameFromExport(node.declaration.declarations[0].id.name);
const toAdd = handleExportedName(title, storyName, node.declaration.declarations[0].init);
Object.assign(addsMap, toAdd);
}
},
});
}
return { addsMap, idsToFrameworks };
}

Expand Down