gatsbyjs / gatsby

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

gatsby-remark-images error if using markdownCaptions: true #16703

Closed hendra-go closed 5 years ago

hendra-go commented 5 years ago

Description

gatsby-remark-images produces and error if using markdownCaptions: true in gatsby-config.js

Steps to reproduce

  1. Create a new Gatsby site using the gatsby-starter-blog (e.g gatsby new my-themed-blog https://github.com/gatsbyjs/gatsby-starter-blog-theme)
  2. Change gatsby-config.js to add option markdownCaptions: true on gatsby-remark-images block
  3. Run yarn develop

Expected result

The page content should be generated and the development site should be available.

Actual result

Errors on terminal

UNHANDLED REJECTION Cannot read property 'contentDigest' of undefined

  TypeError: Cannot read property 'contentDigest' of undefined

  - extend-node-type.js:57 htmlCacheKey
    [test]/[gatsby-transformer-remark]/extend-node-type.js:57:80

  - extend-node-type.js:337 Object.getHTML [as generateHTML]
    [test]/[gatsby-transformer-remark]/extend-node-type.js:337:42

  - index.js:150 getImageCaption
    [test]/[gatsby-remark-images]/index.js:150:21

  - index.js:306 _callee$
    [test]/[gatsby-remark-images]/index.js:306:54

Environment

System: OS: Windows 10 CPU: (8) x64 Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz Binaries: Yarn: 1.17.3 npm: 6.10.3 Languages: Python: 3.7.1 Browsers: Edge: 44.18362.267.0 npmPackages: gatsby: ^2.13.67 => 2.13.67 gatsby-image: ^2.2.8 => 2.2.8 gatsby-plugin-feed: ^2.3.6 => 2.3.6 gatsby-plugin-google-analytics: ^2.1.7 => 2.1.7 gatsby-plugin-manifest: ^2.2.5 => 2.2.5 gatsby-plugin-offline: ^2.2.6 => 2.2.6 gatsby-plugin-react-helmet: ^3.1.3 => 3.1.3 gatsby-plugin-sharp: ^2.2.12 => 2.2.12 gatsby-plugin-typography: ^2.3.2 => 2.3.2 gatsby-remark-copy-linked-files: ^2.1.6 => 2.1.6 gatsby-remark-images: ^3.1.12 => 3.1.12 gatsby-remark-prismjs: ^3.3.5 => 3.3.5 gatsby-remark-responsive-iframe: ^2.2.4 => 2.2.4 gatsby-remark-smartypants: ^2.1.2 => 2.1.2 gatsby-source-filesystem: ^2.1.9 => 2.1.9 gatsby-transformer-remark: ^2.6.14 => 2.6.14 gatsby-transformer-sharp: ^2.2.6 => 2.2.6

More info

It looks like the gatsby-remark-images generate caption from markdown getHTML function from gatsby-transform-remark. I guess The "markdownnode" of the image caption does not have node.internal.contentDigest

gatsbot[bot] commented 5 years ago

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 💪💜

gatsbot[bot] commented 5 years ago

Hey again!

It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.

Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks again for being part of the Gatsby community!

denisnazarov commented 5 years ago

Having same issue.

ornotandrew commented 5 years ago

Having the same issue. Has anyone found a workaround for this in the meantime?

denisnazarov commented 5 years ago

@LekoArts possible to reopen this issue?

LekoArts commented 5 years ago

Yeah, can reproduce it.

ornotandrew commented 5 years ago

So I've done a bit of digging, and it seems there is a test for this case which is passing.

However, the test is set up differently to how this plugin is used in practice. The test uses the hast util directly, while in practice it seems this function is being used.

It looks like there's some extra caching etc going on, which relies on the missing node.internal.contentDigest field.

Hopefully this helps. I'd like to submit a PR for this, but I'm not very familiar with the code - perhaps @mathieudutour might have a better idea, since they submitted the oringinal PR.

To be honest, I'm not even sure if my setup is correct - maybe someone can point out my mistake if there's something wrong with my gatsby-config?

{
  resolve: 'gatsby-transformer-remark',
  options: {
    plugins: [
      {
        resolve: 'gatsby-remark-images',
        options: {
          showCaptions: ['title'],
          markdownCaptions: true
        },
      }
    ],
  },
},
mathieudutour commented 5 years ago

Ah right, might need to change https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-transformer-remark/src/extend-node-type.js#L333-L345 to

const shouldCache = !!markdownNode && !!markdownNode.internal
const cachedHTML = shouldCache && await cache.get(htmlCacheKey(markdownNode))
if (cachedHTML) {
  return cachedHTML
} else {
  const ast = await getHTMLAst(markdownNode)
  // Save new HTML to cache and return
  const html = hastToHTML(ast, {
    allowDangerousHTML: true,
  })

  if (shouldCache) {
    // Save new HTML to cache and return
    cache.set(htmlCacheKey(markdownNode), html)
  }
  return html
}
hendra-go commented 5 years ago

Hi all, A couple weeks ago actually i already made a personal workaround for my personal use case regarding this bug, but i haven't share it because i thought my use case is to spesific that nobody except me will use it. Now i think i have to share it and hopefully it would be useful.

I cloned gatsby-remark-images source and modified it and put it in my-personal-project's plugins folder.

Before i share the code, let me explain what i am trying to achieve: Basically i want to have figcaption that has a title :

<figcaption class="gatsby-resp-image-figcaption">
    <p class="figcaption-title">The Image Caption Title</p>
    <p>Longer text about the image details</p>
</figcaption>

Notice that I don't use heading for the caption title because i am not so sure if heading (h1-h6) is semantically allowed inside figcaption.

This is how i insert image and the caption in markdown:

![Img Alt](./image.jpg 'The Image Caption Title|Longer text about the **Image details** bla bla')

the idea is the caption title and caption content is split by | (Notice that i want to bold the **Image details**)

So in gatsby-remark-images/index.js i made this modification:

before:

...
    const captionString = getCaptionString()

    if (!options.markdownCaptions || !compiler) {
      return _.escape(captionString)
    }

    return compiler.generateHTML(compiler.parseString(captionString))
...

after:

...
    const captionString = getCaptionString()

    if (!options.markdownCaptions || !compiler) {
      return _.escape(captionString)
    }

    return `
            <p class="figcaption-title">${captionString.split(` | `)[0]}</p>
            ${
              captionString.split(` | `)[1]
                ? hastToHTML(
                    toHAST(compiler.parseString(captionString.split(` | `)[1]), {
                      allowDangerousHTML: true,
                    }),
                    { allowDangerousHTML: true }
                  )
                : ``
            }
...

And so far works fine in my personal project. I hope this could shed some light.

O ya, probably i should mention that compiler.generateHTML and compiler.parseString are found in gatsby-transformer-remark/extend-node-type.js

hendra-go commented 5 years ago

Ah right, might need to change https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-transformer-remark/src/extend-node-type.js#L333 to

const cachedHTML = markdownNode && markdownNode.internal && await cache.get(htmlCacheKey(markdownNode))

@mathieudutour : ah this could work. Thanks Mathieu