ChristopherBiscardi / gatsby-mdx

Gatsby+MDX • Transformers, CMS UI Extensions, and Ecosystem Components for ambitious projects
https://gatsby-mdx.netlify.com/
715 stars 100 forks source link

gatsby-remark-* plugin support #10

Closed KyleAMathews closed 6 years ago

KyleAMathews commented 6 years ago

It'd be awesome if it could support gatsby-remark-* plugins so it instantly has image support, etc. Not 100% sure if possible so if not, reimplement a similar API.

LekoArts commented 6 years ago

Would also be interested in that so that people can use my plugin with their React components: https://github.com/LeKoArts/gatsby-remark-design-system

youngboy commented 6 years ago

haven't try with gatsby-remark-image plugin, but I just play a bit with gatsby-mdx image support, and only found out two ways to add image to mdx for now

  1. use webpack loader
    
    import pic from './pic.jpg'
12
2. use page query to query image processed by sharp relate plugin
ideally we should map each `img` tag with `StaticQuery` component, but unfortunately it is not support query variables, but maybe we can have it later ? see https://github.com/gatsbyjs/gatsby/issues/6596

so as a workaround I use `PageQuery` together with React Context
```jsx
// layout
export const ImageContext = React.createContext('images');
import { ImageContext } from './Layout'

const Mdxayout = (props) => {
  const { data,  children } = props
  return (
        <ImageContext.Provider value={data}>
          {children}
        </ImageContext.Provider>
  )

// mdx
import Layout from '../components/Layout'
import Img from 'gatsby-image'

export default Layout

export const query = graphql`
query CollectionPic {
  file(relativePath: { eq: "pic.jpg" }) {
    childImageSharp{
      fluid(maxWidth: 320) {
        ...GatsbyImageSharpFluid
      }
    }
  }
}
`
  <ImageContext.Consumer>
    {data => {
      return <Img fluid={data.file.childImageSharp.fluid} alt='pic-alt' />
    }}
  </ImageContext.Consumer>
jquense commented 6 years ago

MDX works out of the box with remark plugins, I think the best strategy would be to try and write the gatsby remark plugins as plain remark plugins? I know that doesn't really work, but maybe there is a way to do both, e.g. wrap in gatsby plugin for the gatsby specific work and move the remark ast stuff to proper plugins?

In that case both gatsby-remark, and gatsby-mdx could implement the same convention for consuming sub-plugins? Or maybe gatsby-mdx could be handed directly to the gatsby remark-plugin

ChristopherBiscardi commented 6 years ago

@jquense there are a few classes of plugins right now.

  1. remark, rehype, and anything else supported directly in mdx can be passed in as the typical options, which get passed through directly:
    {
    ...
    mdPlugins: [],
    hastPlugins: []
    ...
    }
  2. gatsby-plugins that use setParserPlugins. These can be added to the mdPlugins array following similar syntax to the way the remark-transformer does it code in PR.
    // extend-node-type
    options.mdPlugins.push(parserPlugin);
  3. gatsby plugins that mutateSource. This is where it starts to get tricky because we're passing in the full markdown node, all of the files sourced by gatsby, the getNode function and the cache. Which means there's a potentially huge surface area for people to depend on the structure of the markdownNode, any given file, any? node. I haven't seen a plugin that implements mutateSource yet though so need someone to point one out if they're aware of one.
  4. Pretty much the same as 3, except it calling the required module directly with slightly different argument

TBD on how many plugins we can support by passing in the AST at the right stage in the pipeline, but that's the current approach I'm taking for full gatsby-remark-* support.

jquense commented 6 years ago

nice breakdown :thumbsup: its mainly 3 i think we can consolidate or make compatible i think. Ideally (i think we'd agree) i't be great if all the gatsby remark prism, image, etc plugins worked interchangably between gatsby-transformer-remark and gatsby-mdx, I think @KyleAMathews would agree that we can make neded changes upstream in gatsby to facilitate that, but the question is what is the best strategy for doing so. I think that moving as much of the gatsby plugin logic into real remark plugins (as is possible) is a good first step.

On top of that it may make sense to build hooks into the remark transformer so that mdx can be a child plugin, or maybe just a common set of conventions so all the existing child remark gatsby plugins (prism, images, etc) could be added to gatsby-mdx same as they are to the transformer

ChristopherBiscardi commented 6 years ago

I worked out support for item 4 today in https://github.com/ChristopherBiscardi/gatsby-mdx/pull/68 on the stream today by basically using a closure to encapsulate the scope and apply a new programmatically created remark plugin for each gatsby-remark plugin.

The problems are no longer the differing interfaces, but rather the interface between the plugins and the mdx parser. For example, gatsby-remark-prismjs outputs html into the tree but mdx isn't escaping it at that point in the pipeline so we need to apply a new remark plugin to convert html into jsx for html nodes. (otherwise mdx will choke on things like <span>{</span> which are valid html but indicate an opening of a code expression for jsx)

ChristopherBiscardi commented 6 years ago

Basically, now we just need to work out the kinks and see what plugins cause what edge cases

ChristopherBiscardi commented 6 years ago

gatsby-remark-* plugin support was released in 0.1.1.

Anyone who has custom plugins or uses gatsby-remark-* plugins can test it out by following the config shown in the custom-remark-plugins example.

As we discover edge cases for plugins, they should go into their own issues so we can knock them down one by one. I expect that there will be issues as we get through the long-tail of plugin compatibility and I know of at least one instance of the autolink header misapplying styles because it uses class and not className. By contrast, the prism and katex plugins seem to be fully operational.

We also need to follow up with mdx-js and push some parsing changes upstream so we can get them out of gatsby-mdx and into core mdx.

alexchantastic commented 6 years ago

@youngboy's method (https://github.com/ChristopherBiscardi/gatsby-mdx/issues/10#issuecomment-409606726) no longer seems to work (v0.1.4).

import pic from './pic.jpg'

<img src={pic} alt='12' />

Has this method been deprecated in favor of using gatsby-remark-images?

ChristopherBiscardi commented 6 years ago

@alexchantastic Assuming you set up the proper webpack loader importing files like that should still work since it doesn't really depend on mdx, but you can use the gatsby-mdx docs to set up gatsby-remark-images.

alexchantastic commented 6 years ago

@ChristopherBiscardi thanks for the prompt reply. I did a little bit more digging and this might be an issue with mdx-js itself in that inline JSX doesn't seem to work properly.

This:

import image from './my-image.png;

<img src={image} />
<img src={`http://www.my-website.com/my-image.png`} />
<img src="http://www.my-website.com/my-image.png" />

Outputs this:

<img src="{image}">
<img src="{`http://www.my-website.com/my-image.png`}">
<img src="http://www.my-website.com/my-image.png">

These seem to be the relevant issues in mdx-js: https://github.com/mdx-js/mdx/issues/246 https://github.com/mdx-js/mdx/issues/222