Gatsby: [gatsby-plugin-mdx] Images within <figure> nested within <p> tags are invalid

Created on 31 Jul 2019  路  11Comments  路  Source: gatsbyjs/gatsby

Description

When using gatsby-plugin-mdx with gatsby-remark-images, images written in Markdown are being wrapped in a <p> tag, which fails React's DOM nesting validation because elements like <figure> and <figcaption> (which area generated by gatsby-remark-images) are not valid with <p> tags.

Steps to reproduce

Render a Markdown image:

![Alt text](image.png)

In a Gatsby site using gatsby-plugin-mdx and gatsby-remark-images.

Expected result

The image would not be nested within a paragraph tag.

Actual result

The image is nested within a <p> tag, which caused DOM validation to fail:

Screen Shot 2019-07-30 at 9 52 30 PM

Environment

  System:
    OS: macOS 10.14.5
    CPU: (8) x64 Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 10.15.1 - ~/.nvm/versions/node/v10.15.1/bin/node
    Yarn: 1.16.0 - ~/.yarn/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v10.15.1/bin/npm
  Languages:
    Python: 2.7.10 - /usr/bin/python
  Browsers:
    Chrome: 75.0.3770.142
    Firefox: 64.0
    Safari: 12.1.1
  npmPackages:
    gatsby: 2.8.6 => 2.8.6 
    gatsby-image: 2.1.2 => 2.1.2 
    gatsby-plugin-favicon: 3.1.6 => 3.1.6 
    gatsby-plugin-feed: 2.2.3 => 2.2.3 
    gatsby-plugin-layout: 1.0.15 => 1.0.15 
    gatsby-plugin-mdx: ^1.0.7 => 1.0.7 
    gatsby-plugin-page-creator: 2.0.13 => 2.0.13 
    gatsby-plugin-react-helmet: 3.0.12 => 3.0.12 
    gatsby-plugin-sharp: 2.1.3 => 2.1.3 
    gatsby-plugin-styled-components: 3.0.7 => 3.0.7 
    gatsby-plugin-twitter: 2.0.13 => 2.0.13 
    gatsby-remark-autolink-headers: 2.0.16 => 2.0.16 
    gatsby-remark-copy-linked-files: ^2.1.3 => 2.1.3 
    gatsby-remark-external-links: 0.0.4 => 0.0.4 
    gatsby-remark-images: 3.1.2 => 3.1.2 
    gatsby-source-airtable: 2.0.8 => 2.0.8 
    gatsby-source-filesystem: 2.0.38 => 2.0.38 
    gatsby-source-github: ^0.0.2 => 0.0.2 
    gatsby-source-wordpress: 3.0.64 => 3.0.64 
    gatsby-transformer-hjson: 2.1.8 => 2.1.8 
    gatsby-transformer-json: 2.1.11 => 2.1.11 
    gatsby-transformer-remark: 2.3.12 => 2.3.12 
    gatsby-transformer-sharp: 2.1.21 => 2.1.21 
  npmGlobalPackages:
    gatsby-cli: 2.6.5
not stale MDX

Most helpful comment

Found a workaround for the image issue, just add remark-unwrap-images:

const mdxImageWrapFix = {
  resolve: `gatsby-plugin-mdx`,
  options: {
    plugins: [`gatsby-remark-images`],
    remarkPlugins: [require('remark-unwrap-images')],
    gatsbyRemarkPlugins: [
      'gatsby-remark-images',
    ],
  },
},

I guess it should be easy to adapt this plugin to embedded video and others as well.

All 11 comments

cc @ChristopherBiscardi @johno

This might require making sure that gatsby-remark-images is configured to show captions under images.

I'm also experiencing this issue. Only when writing an alt text in Markdown like so:

![Alt text](image.png)

It seems like it doesn't matter if I configure showCaptions or markdownCaptions in my config, the alt text shows up anyway if it exists. But I suppose that is a separate issue!

I just stumbled over this too.

In my gatsby config i use the mdx plugin together with the remarkplugin like this:

    {
      resolve: 'gatsby-plugin-mdx',
      options: {
        defaultLayouts: {
          default: require.resolve(
            `${__dirname}/src/components/page/Layout.jsx`
          ),
        },
        extensions: ['.mdx', '.md'],
        gatsbyRemarkPlugins: [
          {
            resolve: 'gatsby-remark-images',
            options: {
              linkImagesToOriginal: false,
              showCaptions: true,
              withWebp: true,
            },
          },
        ],
        plugins: ['gatsby-remark-images'],
      },
    },

and my images are rendered with this error in the console:

Warning: validateDOMNesting(...): <figure> cannot appear as a descendant of <p>.
    in figure (created by MDXCreateElement)

It renders but the error is of course annoying, is there anything I can do to get this fixed?

Maybe related to this? https://github.com/gatsbyjs/gatsby/issues/15486
I think the issue is with the plugin handling itself as discussed in the above issue. Hopefully a fix will come soon!

I am having this same issue but with the gatsby embed video or gatsby responsive iframe, one of them creates a <div>which goes inside the <p> tag for markdown. Any updates? Thanks. Can add more info if needed but essentially the same problem.

Found a workaround for the image issue, just add remark-unwrap-images:

const mdxImageWrapFix = {
  resolve: `gatsby-plugin-mdx`,
  options: {
    plugins: [`gatsby-remark-images`],
    remarkPlugins: [require('remark-unwrap-images')],
    gatsbyRemarkPlugins: [
      'gatsby-remark-images',
    ],
  },
},

I guess it should be easy to adapt this plugin to embedded video and others as well.

Is there an official fix coming for this yet? I have the same problem.

{
      resolve: `gatsby-plugin-mdx`,
      options: {
        extensions: [`.mdx`, `.md`],
        gatsbyRemarkPlugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 756,
              showCaptions: true,
              quality: 80,
            },
          },
        ],
      },
    },
Warning: validateDOMNesting(...): <figure> cannot appear as a descendant of <p>.

thanks for the tip @muuvmuuv worked for me once I removed the markdownCaptions option from my gatsby-remark-images options.

I am having this same issue but with the gatsby embed video or gatsby responsive iframe, one of them creates a <div>which goes inside the <p> tag for markdown. Any updates? Thanks. Can add more info if needed but essentially the same problem.

Issue with embedding video that gives <div> cannot appear as a descendant of <p>

Here are the current dependency line up I used to reproduce this issue:

    "@mdx-js/mdx": "1.6.5",
    "@mdx-js/react": "1.6.5",
    "gatsby": "2.23.3",
    "gatsby-plugin-mdx": "1.2.15",
    "gatsby-remark-images": "3.3.10",
    "remark-unwrap-images": "2.0.0",

I can also verify there is an issue @onadeem1 pointed out when MDX wraps HTML markup tags coming from gatsby-remark-embed-video with gatsby-remark-responsive-iframe. The resulting HTML becomes

<p>
  <undefined>
      <div class="gatsby-resp-iframe-wrapper" style="...">
          <div class="embedVideo-container">
              <iframe src="..." class="embedVideo-iframe" allowfullscreen="" style="...">...</iframe>
          </div>
      </div>
  </undefined>
</p>

along with the following error on the console

Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
    in div (created by MDXCreateElement)
    in MDXCreateElement (created by MDXContent)
    in div (created by MDXCreateElement)
    in MDXCreateElement (created by MDXContent)
    in undefined (created by MDXCreateElement)
    in MDXCreateElement (created by MDXContent)
    in p (created by MDXCreateElement)
    in MDXCreateElement (created by MDXContent)
    in wrapper (created by MDXCreateElement)
    in MDXCreateElement (created by MDXContent)
    in MDXContent (created by MDXRenderer)
    in MDXRenderer (at Bodytext.js:20)
    ...

What should have been rendered?

If I were to use the regular .md markup with gatsby-transformer-remark without MDX support, the HTML markup does not wrap <div> within <p>

<div class="gatsby-resp-iframe-wrapper" style="...">
  <div class="embedVideo-container">
    <iframe src="..." class="embedVideo-iframe" allowfullscreen="" style="...">...</iframe>
  </div>
</div>

Workaround with remark-unwrap-images does not solve the markup wrapping issue from embedded video

Tried adding remark-unwrap-images as suggested by @muuvmuuv which workaround the issue Images within <figure> nested within <p> tags are invalid by unwrapping image from gatsby-remark-images. However, it does not help with the issue from gatsby-remark-embed-video as pointed out above.

Curious if remark-unwrap-images could be extended to help solve the issue with embedded video? Perhaps the official solution should really be coming out from gatsby-plugin-mdx without the need for these workarounds. Would love to help, but not sure where to start, any pointers would be grateful!

Running into a similar issue with gatsby-remark-embed-gist and gatsby-plugin-mdx

Using the config https://github.com/weirdpattern/gatsby-remark-embed-gist/issues/12 gives these errors:

Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
The tag <undefined> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ferMartz picture ferMartz  路  3Comments

KyleAMathews picture KyleAMathews  路  3Comments

3CordGuy picture 3CordGuy  路  3Comments

timbrandin picture timbrandin  路  3Comments

theduke picture theduke  路  3Comments