jonschlinkert / gray-matter

Smarter YAML front matter parser, used by metalsmith, Gatsby, Netlify, Assemble, mapbox-gl, phenomic, vuejs vitepress, TinaCMS, Shopify Polaris, Ant Design, Astro, hashicorp, garden, slidev, saber, sourcegraph, and many others. Simple to use, and battle tested. Parses YAML by default but can also parse JSON Front Matter, Coffee Front Matter, TOML Front Matter, and has support for custom parsers. Please follow gray-matter's author: https://github.com/jonschlinkert
https://github.com/jonschlinkert
MIT License
3.97k stars 138 forks source link

Stale cache item is returned if matter(...) is subsequently called with the same "content", but different "data" (i.e. front matter) #129

Closed MikeM2343 closed 3 years ago

MikeM2343 commented 3 years ago

Steps to reproduce:

  1. Call matter(str) with an input string containing front matter and content
  2. Modify the input string so that the front matter is changed, but the content after the front matter is not
  3. Call matter(str) again with the modified input string
  4. A stale cache item is returned. The data property indicates the value that was in the original input string, and not the modified input string.

I believe this is caused because the cache is based on the "content" portion of the input string and not based on the entire input string.

arakelian commented 3 years ago

@MikeM2343 I believe that I experienced this same issue. My workaround was not to mutate the returned data object, at which point things worked fine.

MikeM2343 commented 3 years ago

@arakelian Thank you for the feedback, Greg.

You are correct that you should not modify the data object that is returned from the matter call. After some digging, I found that by modifying the data object, you are in fact modifying the data object in the cache for the mdx content string that you requested. If you then request that same string to be converted again, it will return the modified data object, which is why it looks like stale data.

I ended up fixing my problem by disabling the cache as follows:

const mdx = matter(str, {})

Please note that stringify(content, data) will also cache data because before it stringify's the content and the front matter, it calls matter(content) to get a file object, which it in turn passes to the internal stringify function. To disable caching there, you also need to pass in options like so:

const str = stringify(mdxContent, mdxData, {})

In my case it made sense to completely disable the cache because in an mdx editor situation, you would end up caching every single character edit of all files until the page is refreshed.

Although this is a bit of a gotcha for people using the library, it appears to be by design, so I'm closing the issue.