Describe the bug
An error is received when attempting to embed markdown documents within a doc page story (mdx file). Error states Failed to execute 'createElement' on 'Document': The tag name provided ('# Markdown File....
To Reproduce
Steps to reproduce the behavior:
Expected behavior
I would expect the content of the markdown file to be embedded within the mdx file content.
Screenshots
If applicable, add screenshots to help explain your problem.
Code snippets
Sample Content of my mdx file
import { moduleMetadata } from '@storybook/angular';
import { Story, Meta } from '@storybook/addon-docs/blocks';
import { MatCardModule } from '@angular/material/card';
import Overview from './docs/overview.md';
<Meta
title="Experience/Components"
decorators={
[
moduleMetadata(
{
imports: [
MatCardModule,
],
}
),
]
}
/>
<Overview />
<Story name="Card">
{{
template: `
<div style="padding: 10px">
<mat-card>Simple card</mat-card>
</div>
`,
}}
</Story>
Sample Content of my md file
# Markdown File
This is a markdown file...
System:
Environment Info:
System:
OS: Windows 10
CPU: (8) x64 Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
Binaries:
Node: 10.15.1 - C:\Program Files\nodejs\node.EXE
Yarn: 1.16.0 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
npm: 6.9.0 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: 41.16299.1004.0
"@storybook/addon-a11y": "5.2.0-beta.18",
"@storybook/addon-actions": "5.2.0-beta.18",
"@storybook/addon-docs": "5.2.0-beta.18",
"@storybook/addon-knobs": "5.2.0-beta.18",
"@storybook/addon-links": "5.2.0-beta.18",
"@storybook/addon-notes": "5.2.0-beta.18",
"@storybook/addon-viewport": "5.2.0-beta.18",
"@storybook/addons": "5.2.0-beta.18",
"@storybook/angular": "5.2.0-beta.18",
@rkara Thanks for filing this. As you pointed out in Discord, transclusion is supported by MDX but it's not currently supported by Storybook. I'll see what I can do to make this work. It's a little complicated because Storybook already has a defined behavior for .md
specifically and I think it's inconsistent with MDX. However, transcluding .mdx
should be possible. 馃槶
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!
Hey! In my project, we use StencilJS to develop Web Components and generate associated readme files (with the .md
format). Would be nice to have this feature. 馃憤
Hi @darondel , having a few flights to catch up and not sure about a final solution, but here is something that you can try in the meantime:
import { Description } from '@storybook/addon-docs/blocks';
import readme from '../../README.md';
export const plainMD = () => {
return <Description markdown={readme} />;
};
another workaround that will just render the markdown, it will not keep the storybooks styling for h1 etc elements.
import Markdown from 'markdown-to-jsx';
import readme from '../../README.md';
....
export const markdownToJsx = () => <Markdown>{readme}</Markdown>;
Hi, we further researched the md transclusion and here is what we found:
import Readme from 'readme.mdx`
<Readme />
import Readme from 'readme.md`
<Readme />
import { Meta, Markdown } from '@storybook/addon-docs/blocks';
import Readme from 'readme.md`
<Markdown>{Readme}</Markdown>
import Readme from '../../README.md';
export const plainMD = () => <Readme />;
what do you think - renaming .md to .mdx or using a <Markdown>
sounds sufficient?
Hey!
In my case, StencilJS generates a readme using the MD format. As far as I know, we cannot use another extension for this behavior. The workarounds that you propose are completely suitable for me, either:
<Description>
from @storybook/addon-docs/blocks
package.<Markdown>
from markdown-to-jsx
.In the long run, I think that supporting the import of MD files into MDX would be more intuitive and respect the MDX specification, though it will require to rethink the way you load files.
Great to hear the workarounds are workable. I think we can close this as an issue.
Just for completeness sake, you can also add a rule to the webpack config (as long as it doesn't conflict with another loader as in the case with raw-loader
:
{
test: /\.md$/, // or any other extension we would like to import
use: ['babel-loader', '@mdx-js/loader'],
},
@darondel @atanasster I think the only concern is breaking compatibility with how storybook currently operates. We can:
addon-docs
which overwrites Storybook's .md
behaviormodule.exports = [
{
name: '@storybook/addon-docs/react/preset'
options: {
transcludeMarkdown: true
}
}
]
Now that I'm writing it out, I think the best solution is to add it as an option on the preset and then make that the default in 6.0 (possibly with an overhaul of how SB treats MD across the board).
What do you think?
@shilman thats sounds a really good solution, without a breaking change.
I wish this worked.
Hi I'm also interested into this feature.
If I've understood correctly we can transclude only mdx file for the moment. If that is right, could you please provide a simplified example for this?
Because using the following example it will throw an error:
table.mdx
### This is a table in an mdx
| Prop | Type | Default | Note |
|:------|:------:|:---------:|:------|
|a | a | a | a |
doc.mdx
import { Meta } from "@storybook/addon-docs/blocks";
import MyTable from './table.mdx'
<Meta title="my title" />
# A good title
A nice description
<MyTable />
It will throw an error saying:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `MDXCreateElement`.
Hello there,
I was also stuck on this problem for a while, until I found something that works for me:
test.md
:
# Test
This is just an example of a Markdown for my first ever Github comment.
I hope it can help some people.
test.stories.mdx
:
import { Meta, Description } from '@storybook/addon-docs/blocks';
import test from './test.md';
<Meta title="Test"/>
<Description>{test}</Description>
I hope this is helps.
Thanks @Hicksmix! Was just about to try this on a project and really glad to hear that it works.
Great to hear the workarounds are workable. I think we can close this as an issue.
Just for completeness sake, you can also add a rule to the webpack config (as long as it doesn't conflict with another loader as in the case with
raw-loader
:{ test: /\.md$/, // or any other extension we would like to import use: ['babel-loader', '@mdx-js/loader'], },
Building up on this, if you want to import .md
files in the MDX loader by adding a rule to your webpackFile
export in main.js
, you'll need to filter out the original rule for .md
files, like so:
webpackFinal: async config => {
config.module.rules = [ {
test: /\.md$/,
use: ['babel-loader', '@mdx-js/loader'],
}, ...config.module.rules.filter(rule => rule.test.source !== '\\.md$')]
return config
},
Note that importing .md
files and rendering them as MDX seems to be the only way to have coloured source code blocks in Storybook. Using <Description ... />
or <Markdown>...</Markdown>
will result in unstyled source code blocks.
@Sidnioulz what about Source
blocks?
@shilman the issue with those is that I'd need to take the string from the raw-loader
and manually extract code blocks from my Markdown. I did this at some point and loaded my code samples into CodeOrSourceMdx blocks, but I couldn't find how to display my mixed Markdown and JSX content.
I could've insisted and found some way to export my content but it felt silly that I had to parse MD manually when the MDX loader does such a great job of turning MD content into JSX.
I tried to use the workaround mentioned by @atanasster
import { Meta, Markdown } from '@storybook/addon-docs/blocks';
import Readme from '../../README.md';
<Meta title="General|Introduction" />
<Markdown>{Readme}</Markdown>
But i always get this error when trying to serve storybook:
ERROR in ./README.md 1:0
Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> # WIP: Introduction to the IBE UI Library
|
| This library projects purpose is to consolitate generic, reusable components in one project for better maintainability and provide them as NPM package to be imported and used through all IBE projects/mono-repos.
@ ./src/storybook/introduction.stories.mdx 10:0-37 34:5-11
@ ./src/storybook sync nonrecursive ^\.\/(?:(?:introduction\.stories\.mdx)$)$
@ ./config/storybook/generated-entry.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./node_modules/@storybook/addon-docs/dist/frameworks/common/config.js ./node_modules/@storybook/addon-docs/dist/frameworks/vue/config.js ./node_modules/@storybook/addon-knobs/dist/preset/addDecorator.js ./config/storybook/generated-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=true
Shouldn't storybook out of the box be able to load those .md files?
I installed Storybook via vue-cli-plugin-storybook
cc @mrmckeb
This is not only a problem in mdx files this seems to be also a problem for CSF Format files. Here i get the same error while trying to import an .md file! So it seems that the preconfigured loader for normal markdown files does not do it's job
@awacode21 the preconfigured loader for markdown files probably needs to be updated. But we have not done that because it's a breaking change and we haven't done a major release since this issue was filed. However, we're working on a major release right now (6.0) so it's finally a good time to update it.
@Sidnioulz
Building up on this, if you want to import
.md
files in the MDX loader by adding a rule to yourwebpackFile
export inmain.js
, you'll need to filter out the original rule for.md
files, like so:webpackFinal: async config => { config.module.rules = [ { test: /\.md$/, use: ['babel-loader', '@mdx-js/loader'], }, ...config.module.rules.filter(rule => rule.test.source !== '\\.md$')] return config },
Note that importing
.md
files and rendering them as MDX seems to be the only way to have coloured source code blocks in Storybook. Using<Description ... />
or<Markdown>...</Markdown>
will result in unstyled source code blocks.
I tried this, but I'm getting an error while building, when importing an MD file:
ERROR in ./README.md 10:9
Module parse failed: Unexpected token (10:9)
File was processed with these loaders:
* ./node_modules/@mdx-js/loader/index.js
You may need an additional loader to handle the result of these loaders.
| const makeShortcode = name => function MDXDefaultShortcode(props) {
| console.warn("Component " + name + " was not imported, exported, or provided by MDXProvider as global scope")
> return <div {...props}/>
| };
|
So how do you get it to work? It seems a slight bit more configuration is needed in order for this to work properly. I'm on SB 5.3.14, btw. I'll try updating to latest, but I doubt this will fix it.
/edit: And indeed updating does not fix this.
@thany below is my whole Webpack config, as you can see, nothing else than what I've posted should be involved when it comes to loading MD files. I'm using @mdx-js/loader
and @mdx-js/mdx
1.5.5 and 1.5.7 according to my yarn.lock (not sure which version is used, thus). My SB is 5.3.10.
const webpackConfig = require('../webpack.config')
...
webpackFinal: async config => {
config.resolve.extensions = Array.from(
new Set([...config.resolve.extensions, ...webpackConfig.resolve.extensions])
)
config.resolve.modules = Array.from(new Set([...config.resolve.modules, ...webpackConfig.resolve.modules]))
config.module.rules = [
{
test: /\.md$/,
use: ['babel-loader', '@mdx-js/loader'],
},
...config.module.rules.filter(rule => rule.test.source !== '\\.md$'),
]
return config
},
Also, my MD files actually refer to documentation without stories. They are pure Markdown content. Is that the case for you too?
@Sidnioulz
Your config is a bit off as compared to the documentation, but functionally yours and mine are the same. But no worries, after some more digging, I found this documentation on MDX in Webpack, saying that it also requires some presets to be added in the .babelrc
, which I didn't have yet.
So my .babelrc is now:
{
"presets": ["@babel/env", "@babel/react"],
"plugins": [
"babel-plugin-styled-components"
]
}
And that makes it work!
Thanks for the help 馃憤馃徎
This seems like a fine workaround until SB 6.0 is released 馃槑
Good job @thany, I'd forgotten about that! I also use those two presets.
I am unable to get any of the above solutions to work in my angular storybook 6.0.0-beta.16
. Has anyone got something workable within an angular storybook?
When I try to do installation using- https://github.com/storybookjs/storybook/tree/master/addons/docs#installation on a react project, I get error as-
any update on the issue?
Slotted for 6.0, hopefully in the next week or two
隆Ay Caramba!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.38 containing PR #11333 that references this issue. Upgrade today to try it out!
You can find this prerelease on the @next
NPM tag.
Closing this issue. Please re-open if you think there's still more to do.
Can you clarify what the expected Api is here for Storybook 6? Do I need to add the extra opts in the main.js
file to get the markdown transcluded?
Reading through the code I would have thought that .md
could now be imported with zero-config, but not sure where I am going wrong.
Here's an example of a docs-only component from a create-react-app
that was initialized with npx sb init
import Welcome from "../README.md";
import { Meta, Markdown, Description } from "@storybook/addon-docs/blocks";
<Meta title="Welcome to the Docs" />
<h1>As a component</h1>
<Welcome/> //=> Does not load
<h1>Markdown</h1>
{Welcome} //=> Renders directly without interpolation (e.g. shows as {Welcome})
<h1>Not markdown</h1>
<Description>{Welcome}</Description> //=> Works
@shilman Thank you for your work on this, I also have the same question as @nrakochy, what does usage with the new change in storyboard 6.0 look like? I wasn't able to find any documentation when searching for transcludeMarkdown
.
Most helpful comment
Hello there,
I was also stuck on this problem for a while, until I found something that works for me:
test.md
:test.stories.mdx
:I hope this is helps.