How can I filter frontmatter in a remark plugin?

136 Views Asked by At

In an AstroJS site, I've set up a remark plugin to apply a default layout to .md(x) documents if one is not explicitly set. The code comes from the RFC in issue #397 and works well. I'd now like to use the <Content/> component to break large documents down into fragments.

I can get the content component to work, however each fragment has a default layout applied to it, so I have full pages nested within full pages! One solution is to apply layout: "" to my fragments, but I am also building a site search index which these need to be excluded from (since the full page will be returned as a result). This means that custom frontmatter like fragment: true is preferable because it's definition is more explicit.

Here's the code I currently have set up:

export default function defaultLayoutPlugin() {
  return function (tree, file) {
      console.log(file?.data?.astro?.frontmatter);
      const hasLayout = file?.data?.astro?.frontmatter?.layout;
      const isFragment = file?.data?.astro?.frontmatter?.fragment ? true : false;
      if (hasLayout) {
        return;
      }
      if (isFragment) {
        return;
      }
      // do default layout stuff
   }
}

The console.log line simply returns undefined for every page, despite them all having at least title and description attributes, if not also a layout. With that said, pages that have explicit layouts are not having the default one applied, so the frontmatter is being picked up somewhere, but I cannot log it. For reasons unknown, isFragment is always false, even when it's explicitly set to true.

  • What could be causing the frontmatter not to be logged?
  • How can I properly debug (custom) frontmatter inside remark plugins and then do something with the values?

Thank you

1

There are 1 best solutions below

0
On
  • The way you used the frontmatter is correct as of Astro version 2.0.0-beta.1 I used for a test example and I got this working. The only slight difference is the named export, and your config file which is not provided.

  • if you have injected frontmatter with another plugin, then see the breaking changes since Astro release 2.0.0-beta.0 that states the injectedFrontmatter property has been renamed to remarkPluginFrontmatter

reference https://github.com/withastro/astro/releases/tag/astro%402.0.0-beta.0

  • In general, you can debug remark by placing dummy plugins for checking before and after your plugin under test

Test

I tested your code with files how have and do not have a Layout with this plugin, similar to yours just adjusted to log your boolean variables and to fint my named export import.

function remarkLayoutCheck() {
  return function transformer(syntaxTree,file) {
    console.log("   ---   remark Layout Check   ---")
    console.log(file?.data?.astro?.frontmatter);
    const hasLayout = file?.data?.astro?.frontmatter?.layout;
    const isFragment = file?.data?.astro?.frontmatter?.fragment ? true : false;
    console.log(`hasLayout = ${hasLayout}`)
    console.log(`isFragment = ${isFragment}`)

    return syntaxTree;
  };
}

export{
  remarkLayoutCheck
}

this is the output

   ---   remark Layout Check   ---
{ title: 'Testing Layout', layout: '../src/layouts/Layout.astro' }
hasLayout = ../src/layouts/Layout.astro
isFragment = false
   ---   remark Layout Check   ---
{ title: 'Testing No Layout' }
hasLayout = undefined
isFragment = false

Example

https://github.com/MicroWebStacks/astro-examples/blob/2bc0c72c99419d5af85feaa142ea5f23e5249525/22_mdx-svg/remark/remark-layout-check.js#L8