storybook: Unable to embed mdx/md documents within mdx doc page stories

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:

  1. Use below code along with a markdown file within story
  2. Navigate to story
  3. Open docs page
  4. View error

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. image

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",

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 18
  • Comments: 37 (19 by maintainers)

Most upvoted comments

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.

Not sure if you guys have successfully used this feature. What I did to get my MD files to be embeded, is by doing the followings:

Storybook version: 6.1.21

.storybook/main.js

addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    // add the followings
    {
      name: "@storybook/addon-docs",
      options: { transcludeMarkdown: true },
    },
],

I followed the example from here https://github.com/storybookjs/storybook/pull/11334/files

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} />;
};

@darondel @atanasster I think the only concern is breaking compatibility with how storybook currently operates. We can:

  • Introduce a breaking change in 6.0
  • Introduce a breaking change in addon-docs which overwrites Storybook’s .md behavior
    • By default
    • As a flag on the preset
module.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?

Hi, we further researched the md transclusion and here is what we found:

  1. It works for .mdx files:
import Readme from 'readme.mdx`
<Readme />
  1. It does not currently work for .md files, because we use by default the raw-loader and really not sure we should break behavior. So this doesnt work:
import Readme from 'readme.md`
<Readme />
  1. There is an easy workaround for us to add a Markdown docs block
import { Meta, Markdown } from '@storybook/addon-docs/blocks';
import Readme from 'readme.md`

<Markdown>{Readme}</Markdown>
  1. My PR #8007 fix for the transclusion in csf files works:
import Readme from '../../README.md';

export const plainMD = () => <Readme />;

what do you think - renaming .md to .mdx or using a <Markdown> sounds sufficient?

@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.

@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.

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.

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

I wish this worked. bitmoji

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. 👍

Thanks @williamliangwl 🎉 🎉 That was smooth indeed. Not sure if that has any other hidden impacts but working so far.

// your-story.mdx

import ChangeLog from "./CHANGELOG.md";

<ChangeLog />

I’ve tried it in version 6.4.21. Build success, but it displays Cannot get / if I start Storybook server.

This code was working. After upgrading to Storybook 7 (I think that was the issue), this didn’t work anymore. Reading the Documentaiton, it seems like we need to use another approach.

This was my previous code: MarkdownToJS_Before

This change worked now: MarkdownToJS_Issue

Here is the link for the Storybook documentation: https://storybook.js.org/docs/react/api/doc-block-markdown

Thanks @williamliangwl 🎉 🎉

That was smooth indeed. Not sure if that has any other hidden impacts but working so far.


// your-story.mdx

import ChangeLog from "./CHANGELOG.md";

<ChangeLog />

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

¡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.

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>;

Thanks @williamliangwl 🎉 🎉

That was smooth indeed. Not sure if that has any other hidden impacts but working so far.

// your-story.mdx

import ChangeLog from "./CHANGELOG.md";

<ChangeLog />

I’ve tried it in version 6.4.21. Build success, but it displays Cannot get / if I start Storybook server.

Slotted for 6.0, hopefully in the next week or two

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- image

@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 😎