gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.28k stars 10.31k forks source link

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

Closed chasemccoy closed 2 years ago

chasemccoy commented 5 years ago

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
chasemccoy commented 5 years ago

cc @ChristopherBiscardi @johno

chasemccoy commented 5 years ago

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

RobertBroersma commented 5 years ago

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!

rejas commented 4 years ago

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?

muuvmuuv commented 4 years ago

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!

onadeem1 commented 4 years ago

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.

muuvmuuv commented 4 years ago

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.

mmgolden commented 4 years ago

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>.
rejas commented 4 years ago

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

joyfulelement commented 4 years ago

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!

ghost commented 4 years ago

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.
coldice commented 3 years ago

Be careful, everything might appear to be working, however when running the production build and reloading a page where this error is thrown, a bunch of other elements are blown by this. When navigating away and back, all looks good so this only triggers on first load / forced reload.

Using the unwrap plugin, you can actually enable the image captions and everything works fine. I followed this approach: https://github.com/gatsbyjs/gatsby/issues/24832#issuecomment-642649433

On the issue with the video component, I have now resorted to write my own wrapper component, which bypasses all the markdown nesting issues and allows better control of the settings (like using nocookie). There is a lovely samplecode at https://www.gatsbyjs.com/docs/how-to/images-and-media/working-with-video/

kimbaudi commented 3 years ago

similar issue. gatsby-plugin-mdx with gatsby-remark-embed-snippet is throwing validateDOMNesting warning:

Warning: validateDOMNesting(...): <pre> cannot appear as a descendant of <p>.

LekoArts commented 2 years ago

Hi!

I'm closing this as a stale issue as in the meantime Gatsby 4 and related packages were released. You can check our Framework Version Support Page to see which versions currently receive active support.

Please try the mentioned issue on the latest version (using the next tag) and if you still see this problem, open a new bug report. It must include a minimal reproduction.

Thanks!

dinhanhthi commented 2 years ago

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.

I got this error

Error: [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/thi/git/dat-5/node_modules/remark-unwrap-images/index.js
  require() of ES modules is not supported.
  require() of /Users/thi/git/dat-5/node_modules/remark-unwrap-images/index.js from /Users/thi/git/dat-5/gatsby-config.js is an ES module file as it is a .js file whose nearest parent packa
  ge.json contains "type": "module" which defines all .js files in that package scope as ES modules.
  Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /Users/thi/git/dat-5/node_modules/remark-unwrap-images/package.json.