diff --git a/src/loaders/mdx-loader.ts b/src/loaders/mdx-loader.ts
index a8a8bc8bf..190b974b8 100644
--- a/src/loaders/mdx-loader.ts
+++ b/src/loaders/mdx-loader.ts
@@ -19,7 +19,7 @@ import { mdx } from '@mdx-js/react';
export default async function mdxLoader(this: Rsg.StyleguidistLoaderContext, content: string) {
const callback = this.async() || (() => '');
const { updateExample, context } = this._styleguidist;
- const { component } = loaderUtils.getOptions(this) || {};
+ const { component: componentPath } = loaderUtils.getOptions(this) || {};
let result;
try {
@@ -29,16 +29,13 @@ export default async function mdxLoader(this: Rsg.StyleguidistLoaderContext, con
addReact,
markStaticExamples,
addExampleIndicies,
- updateExamples({ updateExample, resourcePath: this.resourcePath }),
+ updateExamples({ updateExample, mdxDocumentPath: this.resourcePath }),
exportExamples,
// Sections don't have current components
- component && exportStories({ component, resourcePath: this.resourcePath }),
+ componentPath && exportStories({ componentPath, mdxDocumentPath: this.resourcePath }),
provideDocumentScope({ context }),
provideExampleScope,
- component && provideCurrentComponent({ component }),
- // TODO: Use smart (no-duplicates) insert instead of deduplication
- // TODO: Or better insert needed imports in front of each example
- // deduplicateImports,
+ componentPath && provideCurrentComponent({ componentPath }),
],
});
} catch (err) {
diff --git a/src/loaders/rehype/__tests__/exportStories.spec.ts b/src/loaders/rehype/__tests__/exportStories.spec.ts
index 45dfa1abf..d7736061a 100644
--- a/src/loaders/rehype/__tests__/exportStories.spec.ts
+++ b/src/loaders/rehype/__tests__/exportStories.spec.ts
@@ -15,7 +15,9 @@ const compile = async (mdxContent: string, storyContent: string) => {
vol.fromJSON({ '/Pizza/Pizza.stories.tsx': storyContent });
const result = await mdx(mdxContent, {
filepath: 'Pizza.md',
- rehypePlugins: [exportStories({ component: 'Pizza', resourcePath: '/Pizza/Pizza.md' })],
+ rehypePlugins: [
+ exportStories({ componentPath: './index.tsx', mdxDocumentPath: '/Pizza/Readme.md' }),
+ ],
});
// Strip repeated parts
@@ -182,6 +184,35 @@ export const basic = () =>
`);
});
+ test('skips current component (named import)', async () => {
+ const result = await compile(
+ `Henlo`,
+ `
+import { Pizza } from '.';
+import Container from './Container';
+export const basic = () =>
+`
+ );
+ expect(result).toMatchInlineSnapshot(`
+ "
+ import * as __story_import_0 from '.'
+ import * as __story_import_1 from './Container'
+ export const __namedExamples = {
+ 'basic': 'import Container from \\\\'./Container\\\\';\\\\n\\\\n'
+ };
+ export const __storiesScope = {
+ '.': __story_import_0,
+ './Container': __story_import_1
+ };
+
+ const layoutProps = {
+ __namedExamples,
+ __storiesScope
+ };
+ "
+ `);
+ });
+
test('includes the current component when it is not the only import', async () => {
const result = await compile(
`Henlo`,
diff --git a/src/loaders/rehype/exportStories.ts b/src/loaders/rehype/exportStories.ts
index fad94b166..61056fe28 100644
--- a/src/loaders/rehype/exportStories.ts
+++ b/src/loaders/rehype/exportStories.ts
@@ -21,6 +21,7 @@ import toAst from 'to-ast';
import { builders as b } from 'ast-types';
import getAst from '../utils/getAst';
import { ModuleMap } from './types';
+import getNameFromFilePath from '../utils/getNameFromFilePath';
// TODO: Hot reload
// TODO: Unindenting
@@ -209,12 +210,12 @@ const getExportCode = (node: Declaration, code: string) => {
const prependExampleWithDependencies = (
code: string,
dependencies: Dependency[],
- component: string
+ componentName: string
) => {
const usedDependencies = dependencies.filter(
(dependency) =>
// Ignore the current component import it it's the only import
- !(dependency.names.length === 1 && dependency.names[0] === component) &&
+ !(dependency.names.length === 1 && dependency.names[0] === componentName) &&
// Include imports when any of the names are present in the code
dependency.names.some((name) => code.match(new RegExp(`\\b${name}\\b`)))
);
@@ -229,7 +230,7 @@ const prependExampleWithDependencies = (
.join('\n\n');
};
-const getExports = (ast: Program, code: string, component: string) => {
+const getExports = (ast: Program, code: string, componentName: string) => {
const imports = getImportStatements(ast, code);
const variables = getVariableStatements(ast, code);
@@ -245,7 +246,7 @@ const getExports = (ast: Program, code: string, component: string) => {
exports[exportCode.name] = prependExampleWithDependencies(
exportCode.code,
[...imports, ...variables],
- component
+ componentName
);
}
}
@@ -275,12 +276,16 @@ const getExports = (ast: Program, code: string, component: string) => {
* './Button': __story_import_0
* }
*/
-export default ({ component, resourcePath }: { component: string; resourcePath: string }) => () => (
- treeRaw: MdxNode
-) => {
+export default ({
+ componentPath,
+ mdxDocumentPath,
+}: {
+ componentPath: string;
+ mdxDocumentPath: string;
+}) => () => (treeRaw: MdxNode) => {
const tree = treeRaw as Parent;
- const componentAbsolutePath = path.resolve(path.dirname(resourcePath), component);
+ const componentAbsolutePath = path.resolve(path.dirname(mdxDocumentPath), componentPath);
const storiesFile = getStoriesFile(componentAbsolutePath);
if (!storiesFile) {
return tree;
@@ -292,8 +297,10 @@ export default ({ component, resourcePath }: { component: string; resourcePath:
return tree;
}
+ const componentName = getNameFromFilePath(componentAbsolutePath);
+
// Generate export for named examples
- const exports = getExports(storiesAst, storiesCode, component);
+ const exports = getExports(storiesAst, storiesCode, componentName);
const examplesExportCode = `export const __namedExamples = ${generate(toAst(exports))}`;
tree.children.push({
type: 'export',
diff --git a/src/loaders/rehype/provideCurrentComponent.ts b/src/loaders/rehype/provideCurrentComponent.ts
index b61252b25..7dd4efed4 100644
--- a/src/loaders/rehype/provideCurrentComponent.ts
+++ b/src/loaders/rehype/provideCurrentComponent.ts
@@ -9,13 +9,13 @@ const getLocalName = () => `__ex_component`;
* import * as __ex_component from './Button'
* export const __currentComponent = __ex_component
*/
-export default ({ component }: { component: string }) => () => (treeRaw: Node) => {
+export default ({ componentPath }: { componentPath: string }) => () => (treeRaw: Node) => {
const tree = treeRaw as Parent;
// Generate import
tree.children.push({
type: 'import',
- value: `import * as ${getLocalName()} from '${component}'`,
+ value: `import * as ${getLocalName()} from '${componentPath}'`,
});
// Generate export
diff --git a/src/loaders/rehype/updateExamples.ts b/src/loaders/rehype/updateExamples.ts
index 9d217eee7..30a83d8d8 100644
--- a/src/loaders/rehype/updateExamples.ts
+++ b/src/loaders/rehype/updateExamples.ts
@@ -17,17 +17,17 @@ const getCode = (node: CodeNode): string =>
*/
export default ({
updateExample,
- resourcePath,
+ mdxDocumentPath,
}: {
updateExample: Rsg.SanitizedStyleguidistConfig['updateExample'];
- resourcePath: string;
+ mdxDocumentPath: string;
}) => () => (tree: Node) => {
visit(tree, { type: 'element', tagName: 'code' }, (node) => {
const content = getCode(node);
const lang = getCodeLang(node);
const { className, metastring, ...settings } = node.properties;
- const nextExample = updateExample({ content, lang, settings }, resourcePath);
+ const nextExample = updateExample({ content, lang, settings }, mdxDocumentPath);
// TODO: Update lang
node.children[0].value = nextExample.content.trim();