MDXRenderer: components available globally as shortcodes not working
See original GitHub issueDescription
I am trying to get JSX components to work globally in my markdown files for my blog as per the documentation: Importing and Using Components in MDX
The proper html is not being rendered from my custom component inthe markdown, Rather I get a plain <div> tag with the attributes set in the custom component.
When I import my custom component into a .mdx file in src/pages and import the component from within the .md file as per import-components-for-use-from-another-library the proper html is rendered:
<blockquote class='sc-bdVaJa jKmSoD'>
<p>
<small>
This is a foobar<cite>by some genius</cite>
</small>
</p>
</blockquote>
I have simplified my test to putting a <MDXRenderer>
right in the blog.js
file which resides in src/pages
to rule out any issues with pathing and createPages
in gatsby-node.js
The contents of my blog.js is:
import Bio from "../components/bio"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm } from "../utils/typography"
import Button from "../components/button"
import { MDXRenderer } from "gatsby-plugin-mdx"
import { ImgCaption } from "../components/ImgCaption"
class Blog extends React.Component {
render() {
const { data } = this.props
const siteTitle = data.site.siteMetadata.title
const posts = data.allMdx.edges
const shortcodes = { ImgCaption }
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO title="All posts" />
<Bio />
<div style={{ margin: "40px 0 40px" }}>
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<React.Fragment>
<div key={node.fields.slug} style={{paddingLeft: '15px'}}>
<MDXRenderer
components={shortcodes}
>
{node.body}
</MDXRenderer>
<h3
style={{
marginBottom: rhythm(1 / 8),
}}
>
<Link
style={{ boxShadow: `none` }}
to={`blog${node.fields.slug}`}
>
{title}
</Link>
</h3>
<small>{node.frontmatter.date}</small>
<p
style={{
marginBottom: rhythm(1 / 2),
marginTop: rhythm(1 / 4)
}}
dangerouslySetInnerHTML={{
__html: node.frontmatter.description || node.excerpt,
}}
/>
</div>
<hr style={{borderTop: '1px solid #bbb', margin: '0 0 15px'}} />
</React.Fragment>
)
})}
</div>
<Link to="/">
<Button marginTop="85px">Go Home</Button>
</Link>
</Layout>
)
}
}
export default Blog
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
allMdx(sort: { fields: [frontmatter___date], order: DESC } filter: {fileAbsolutePath: {regex: "/content/blog/"}}) {
edges {
node {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
}
body
}
}
}
}
`
My custom component is here: src/components/ImgCaption.js
and looks like this:
import React from 'react'
import styled from 'styled-components'
import colors from '../../content/assets/style/colors.scss'
export const ImgCaption = ({description, citation}) => {
return (
<Container>
<p>
<small>
{description}
<cite>
{citation}
</cite>
</small>
</p>
</Container>
)
}
const Container = styled.blockquote`
border-left: 1px solid ${colors.charm_pink};
padding-left: .35em !important;
p {
small {
font-size: 65%;
cite {
font-size: xx-small;
}
}
}
`
My gatsby-config.js
looks like this:
module.exports = {
siteMetadata: {
// edit below
title: `blah`,
author: `blah bah`,
description: `blah blah blah blah blah`,
siteUrl: `https://blah.com/`,
social: {
twitter: `blahblah`,
},
},
plugins: [
{
resolve:`gatsby-source-filesystem`, // this entry has to be the first or will not work as per FAQ
options:{
path:`${__dirname}/static/assets`,
name:`assets`
}
},
`gatsby-plugin-sass`,
`gatsby-plugin-netlify-cms`,
`gatsby-plugin-styled-components`,
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
`gatsby-plugin-offline`,
`gatsby-plugin-react-helmet`,
`gatsby-plugin-feed-mdx`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content/blog`,
name: `blog`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content/data`,
name: `content`,
},
},
{
resolve: `gatsby-plugin-mdx`,
options: {
extensions: [".mdx", ".md"],
gatsbyRemarkPlugins: [
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 590,
},
},
{
resolve: "gatsby-remark-external-links",
options: {
target: "_blank",
rel: "nofollow"
}
},
{
resolve: `gatsby-remark-responsive-iframe`,
options: {
wrapperStyle: `margin-bottom: 1.0725rem`,
},
},
{
resolve: `gatsby-remark-vscode`,
},
{
resolve: `gatsby-remark-copy-linked-files`,
},
{
resolve: `gatsby-remark-smartypants`,
},
],
},
},
{
resolve: `gatsby-plugin-google-analytics`,
options: {
// edit below
// trackingId: `ADD YOUR TRACKING ID HERE`,
},
},
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `blah`,
short_name: `blah`,
start_url: `/`,
background_color: `#ffffff`,
theme_color: `#663399`,
display: `minimal-ui`,
// edit below
icon: `content/assets/gatsby-icon.png`,
},
},
/*{
resolve: `gatsby-plugin-typography`,
options: {
pathToConfigModule: `src/utils/typography`,
},
},*/
],
}
Steps to reproduce
- Place a file named
test.md
in/content/assets/blog
- Ensure that
test.md
contains the following content:
---
path: 03-10-20-1
date: 2020-13-10T16:51:48.059Z
title: this is a test
description: 'testing a possible bug'
---
This is regular content
<ImgCaption description='This is a foobar' citation='by some genius' />
This is more regular content
Expected result
The following html should be rendered from the custom component:
<blockquote class='sc-bdVaJa jKmSoD'>
<p>
<small>
This is a foobar<cite>by some genius</cite>
</small>
</p>
</blockquote>
Actual result
The following html is rendered for the html component:
<div description="This is a foobar" citation="by some genius"></div>
Environment
System: OS: Windows 10 10.0.18362 CPU: (8) x64 Intel® Core™ i7-6700HQ CPU @ 2.60GHz Binaries: Node: 12.4.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.19.1 - ~\AppData\Roaming\npm\yarn.CMD npm: 6.13.2 - C:\Program Files\nodejs\npm.CMD Languages: Python: 2.7.16 - /c/Python27/python Browsers: Edge: 44.18362.449.0 npmPackages: gatsby: ^2.3.25 => 2.19.34 gatsby-image: ^2.0.39 => 2.2.43 gatsby-plugin-feed-mdx: ^1.0.0 => 1.0.1 gatsby-plugin-google-analytics: ^2.0.18 => 2.1.37 gatsby-plugin-manifest: ^2.0.29 => 2.2.45 gatsby-plugin-mdx: ^1.0.52 => 1.0.78 gatsby-plugin-netlify-cms: ^4.0.0 => 4.1.41 gatsby-plugin-offline: ^2.0.25 => 2.2.10 gatsby-plugin-react-helmet: ^3.0.12 => 3.1.23 gatsby-plugin-sass: ^2.1.30 => 2.1.30 gatsby-plugin-sharp: ^2.0.35 => 2.4.8 gatsby-plugin-styled-components: ^3.0.7 => 3.1.20 gatsby-plugin-typography: ^2.2.13 => 2.3.24 gatsby-remark-copy-linked-files: ^2.0.11 => 2.1.39 gatsby-remark-external-links: ^0.0.4 => 0.0.4 gatsby-remark-images: ^2.0.6 => 2.0.6 gatsby-remark-responsive-iframe: ^2.1.1 => 2.2.33 gatsby-remark-smartypants: ^2.0.9 => 2.1.22 gatsby-remark-vscode: ^1.0.4 => 1.4.0 gatsby-source-filesystem: ^2.0.29 => 2.1.51 gatsby-transformer-sharp: ^2.1.18 => 2.3.17
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (4 by maintainers)
Looks like everyone here gets it, but I’ll just post this for the next soul trying to use it with MDXRenderer. You want your MDXProvider to wrap your MDXRenderer. Then you will have access to all your components
To expand on @flikteoh’s comment…
In your code, you are passing your components to
MDXRenderer
. Instead, you should pass custom component toMDXProvider
.From the docs:
The
MDXProvider
in this example is in a layout component that wraps all MDX pages, you can read about this pattern in the layout section of the gatsby-plugin-mdx README.You can specify the default layout component for different types of mdx pages in the plugin options.