[gatsby-plugin-mdx] `html` field doesn't render custom components when those components are provided in a layout file via`MDXProvider shortcodes`
See original GitHub issueDescription
I have created some custom components and I use them in my blogpost markdown files. These custom components render fine in the browser when they’re supplied to MDXProvider
via shortcodes
in my layout file. Unfortunately, these custom components are not rendered properly in the html
field that is used by gatsby-plugin-feed
when generating the RSS feed.
I’ve done some digging, and it seems that the custom component will be rendered correctly if the component has been imported directly into the .mdx
file, but the component will not be rendered correctly if it has been supplied via shortcodes
to MDXProvider
.
Here’s an example of one component, Caption
:
import React from "react"
const Caption = ({children}) => {
return(
<div style={{
fontSize:"14px",
textAlign:"center",
color:"grey",
marginTop:"-1rem",
marginBottom:"2rem"}}>
{children}
</div>
)
}
export default Caption
It gets supplied to the blogPost.js layout file via a shortcode given to MDXProvider
:
import React from 'react'
import { graphql } from 'gatsby'
import Caption from '../components/Caption'
import { MDXProvider } from "@mdx-js/react"
import { MDXRenderer } from "gatsby-plugin-mdx"
const shortcodes = { Caption }
export default function PageTemplate( { data, pageContext } ) {
const { mdx } = data
const title = mdx.frontmatter.title
const timeToRead = mdx.timeToRead
const relativeDate = mdx.frontmatter.date
return (
<div>
<div id='middle-column'>
<div>
<h1 style={{fontFamily:"Georgia", marginBottom:"8px"}}>{title}</h1>
</div>
<div className='blogpost'>
<MDXProvider components={shortcodes}>
<MDXRenderer>{mdx.body}</MDXRenderer>
</MDXProvider>
</div>
</div>
</div>
)
}
export const pageQuery = graphql`
query($pathSlug:String!){
mdx(fields: { slug: { eq: $pathSlug} }){
id
body
frontmatter {
title
date (fromNow: true)
}
timeToRead
}
}
`
Here’s my plugin config in gatsby-config.js
:
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `pages`,
path: `${__dirname}/src/pages`
}
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `content`,
path: `${__dirname}/content`
}
},
{
resolve: `gatsby-plugin-mdx`,
},
{
resolve:`gatsby-plugin-feed`,
options: {
query: `
{
site {
siteMetadata {
title
description
siteUrl
site_url: siteUrl
}
}
}
`,
feeds: [
{
serialize: ({ query: { site, allMdx } }) => {
return allMdx.edges.map(edge => {
const siteUrl = site.siteMetadata.siteUrl
const slug = siteUrl + edge.node.fields.slug
const frontmatter = edge.node.frontmatter
return Object.assign({}, edge.node.frontmatter, {
description: edge.node.excerpt,
date: frontmatter.date,
url: slug,
guid: slug,
custom_elements: [
{ "content:encoded": edge.node.html }
],
})
})
},
query: `
{
allMdx(
sort: { order: DESC, fields: [frontmatter___date] },
) {
edges {
node {
excerpt
html
fields { slug }
frontmatter {
title
date
}
}
}
}
}
`,
output: "/rss.xml",
title: "RSS Feed",
},
],
},
},
]
}
When the Caption component is imported directly into the Markdown file, i.e:
---
date: "2020-01-11"
title: "Blogpost test - title"
excerpt: "Excerpty text"
---
import Caption from "../../components/Caption"
## Something about this awesome image
Imagine an image goes here...
<Caption>A custom caption for my image!</Caption>
# And so it begins
Something or other about my blogpost.
the following is rendered in the allMdx.edges.node.html
field, and thus my RSS feed (as expected):
<div style="font-size: 14px; text-align: center; color: grey; margin-top: -1rem; margin-bottom: 2rem;">The moguls below the ski lifts</div>
When the Caption component is supplied to MDXProvider
via shortcodes
(i.e. not imported directly), it is rendered as a div with none of the styling of the custom Caption
component:
<div>The moguls below the ski lifts</div>
Additionally, I also get this error at gatsby build
time:
warn Component Caption was not imported, exported, or provided by MDXProvider as global scope
It could be that I just don’t know how to properly supply shortcodes in a way that the html
field knows about them. I’ve read the docs, but can’t find anyway of doing this.
Otherwise, it seems like a potential feature request to me.
Steps to reproduce
- Create a new gatsby project
- Install
gatsby-plugin-mdx
andgatsby-plugin-feed
- Create a custom layout file, and supply a custom to MDXProvider using shortcodes.
- Use createPages function in gatsby-node.js to generate pages using the above layout
gatsby build
– produces an warning in the console (see above), and the custom component styling isn’t applied to thehtml
field inallMdx.edges.node.mdx
Repo with two blogs is here: https://github.com/jjdevenny/gatsby-rss-shortcodes-bug
One blog imports the Caption directly and works (./src/pages/direct-import-test.mdx
), the other imports the caption via shortcodes and doesn’t work (./content/shortcodes-test.mdx
).
Expected result
The html
field supplied to gatsby-plugin-feed
should respect the custom components I’ve supplied to MDXProvider
via shortcodes
in my layout file. My RSS feed should include the custom component styling + layout.
Actual result
The html
field supplied to gatsby-plugin-feed
doesn’t include any of the custom components I have supplied via MDXProvider
in my layout file.
I also get an error in the console on gatsby build
:
warn Component Caption was not imported, exported, or provided by MDXProvider as global scope
Environment
System: OS: macOS 10.15.2 CPU: (12) x64 Intel® Core™ i9-8950HK CPU @ 2.90GHz Shell: 5.7.1 - /bin/zsh Binaries: Node: 13.6.0 - /usr/local/bin/node Yarn: 1.19.2 - /usr/local/bin/yarn npm: 6.13.4 - /usr/local/bin/npm Languages: Python: 2.7.16 - /usr/bin/python Browsers: Chrome: 79.0.3945.117 Safari: 13.0.4 npmPackages: gatsby: ^2.18.21 => 2.18.21 gatsby-cli: ^2.8.26 => 2.8.26 gatsby-plugin-feed: ^2.3.26 => 2.3.26 gatsby-plugin-mdx: ^1.0.67 => 1.0.67 gatsby-source-filesystem: ^2.1.46 => 2.1.46 npmGlobalPackages: gatsby-cli: 2.8.26 gatsby: 2.18.7
Issue Analytics
- State:
- Created 4 years ago
- Reactions:3
- Comments:13 (3 by maintainers)
Top GitHub Comments
Hi @jjdevenny. I just had a closer look at the
html
resolver, and it looks like you just need to put the<MDXProvider>
in wrapRootElement.I have this
.mdx
page:And this setup:
All of this results in this HTML (I’ve converted its encoding XML->JSON):
That’s basically what you’re trying to do, yeah?
+1, @Js-Brecht your solution worked for me too! Unlike @jjdevenny this was less about inline styles for me and more about correct semantic output; I had custom
Image
andLink
/a
components, for example, that were getting completely ignored/transformed into adiv
in RSS because of this issue.