storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84k stars 9.23k forks source link

[addon-docs] Add support for providing remark plugins in docs #9483

Open kevin940726 opened 4 years ago

kevin940726 commented 4 years ago

Is your feature request related to a problem? Please describe. See the twitter discussion I had with @shilman.

Currently if the user wants to add new remark plugins to docs, they have to manually create the loader in conjunction with createCompiler, as seen in the doc.

const createCompiler = require('@storybook/addon-docs/mdx-compiler-plugin');
const emoji = require("remark-emoji");

{
  loader: "@mdx-js/loader",
  options: {
    compilers: [createCompiler({})],
    remarkPlugins: [emoji] // <--
  }
}

Describe the solution you'd like We can add a new option in addon-docs to add the remarkPlugins (and other loader options) to the mdx loader, called mdxLoaderOptions.

const emoji = require("remark-emoji");

module.exports = {
  addons: [
    {
      name: "@storybook/addon-docs",
      options: {
        mdxLoaderOptions: {
          remarkPlugins: [emoji] // <--
        }
      }
    }
  ]
};

Currently we already have 2 default remark plugins. We can just simply override the options and expect the users to add them back if they still want those plugins.

Describe alternatives you've considered We could dedup the provided plugins, but that might be a bad idea.

Are you able to assist bring the feature to reality? Sure! :) Any heads-up for where to look into?

shilman commented 4 years ago

I think adding an mdxLoaderOptions to the docs preset would be 💯! cc @patricklafrance

patricklafrance commented 4 years ago

Oh yeah, sorry I was to suppose to had this, i've been lazy ;) @shilman

patricklafrance commented 4 years ago

Not sure though about just overriding the existing remark plugins since MDX linking depends on remark-slug.

Still it would be nice if someone could somehow opt out of remark-external-links.

Maybe we could offer an array that contains all the default remark plugins? I believe react-docgen is using a similar approach to configure handlers and resolvers.

patricklafrance commented 4 years ago

If this issue https://github.com/storybookjs/storybook/issues/9329 is tackled, it would also work and we could then override all the existing remark plugins

kevin940726 commented 4 years ago

@patricklafrance That's a fairly good point, I didn't know that we actually depends on remark-slug.

While #9339 is still on-going, and also I think we can't be sure that we won't have any other dependency plugins in the future, we can somehow provide the users a list of the default plugins.

What I'd propose is to make the config a function, and we can call our default settings in the first argument. So if the user pass in an object, we can just override the whole options as is, we expect the user to also provide the necessary plugin (remark-slug for example). If the user pass in a function then we call it with our defaults and use the return value as the result. Something like this

// Replace and override all the options with what users provided
mdxLoaderOptions: {
  remarkPlugins: [slug, emoji]
}

// Call the function with our default options and expect the users to merge them somehow
mdxLoaderOptions: (defaultOptions) => ({
  ...defaultOptions,
  remarkPlugins: [...defaultOptions.remarkPlugins, emoji]
})

I wonder if this makes sense? Does it overly complicate things? What are other alternatives?

shilman commented 4 years ago

I really don't like the merge version 😉

@patricklafrance any chance you can knock out #9329 and unblock this?

kevin940726 commented 4 years ago

@shilman Fair enough! I'm hesitant about that either.

I can help with #9329 if @patricklafrance hasn't got time with it 😉

patricklafrance commented 4 years ago

Still too busy but i'll be happy to participate to the review if you want to do this @kevin940726

frassinier commented 3 years ago

And FWIW there is a simple workaround for now https://twitter.com/frassinier/status/1381581824699273222

nerdyman commented 1 year ago

It looks like the Webpack config has changed so the snippet from the Tweet above didn't work for me. I did the following to get Remark working with Storybook 6.5.12 & MDX v1:

{
  webpackFinal: (config) => {
    const mdxConfig = config.module.rules
      .find((rule) => rule?.test?.test?.('story.mdx') && !rule?.exclude?.test?.('story.mdx'))
      ?.use?.find?.((use) => use.loader.includes('@storybook/mdx1-csf'))
     ;

    console.debug('using MDX config', mdxConfig);

    mdxConfig.options = mdxConfig.options || {};
    mdxConfig.options.remarkPlugins = mdxConfig.options.remarkPlugins || [];
    mdxConfig.options.remarkPlugins.push([your_remark_plugin, { /* your remark config */ } ]);

    return config;
  }
}

There's a working config using the Codesandbox Remark plugin here https://github.com/nerdyman/react-compare-slider/blob/ce05fffc2e54d2424e50a4b00a9d4577db5abf3c/.storybook/main.ts#L32