#Have all MDX files automatically import a specific component

10 messages · Page 1 of 1 (latest)

shy moth
#

I have blog post mdx files. I have a NewsletterSignup component for them that gets put in the mdx files like <NewsletterSignup /> and would like to have all of the mdx files automatically import the necessary component without me having to manually do it. Is this possible? The import statement would look like import NewsletterSignup from "./src/components/NewsletterSignup/NewsletterSignup"

I've tried writing a remark plugin (below), and it adds the import statement to the ast, but Astro throws an error that says "...you likely forgot to import...". If I manually type in the import statement in the mdx file it works just fine.

export default function remarkAddImport(options) {
  return (tree) => {
    // at the start of every mdx file, import necessary components
    tree.children.unshift({
      type: "import",
      value: `import NewsletterSignup from "./src/components/NewsletterSignup/NewsletterSignup"`,
    });
  };
}
solemn latchBOT
#
Still waiting for an answer?

It looks like no-one has responded to your question yet. People might not be available right now or don’t know how to answer your question. Want an answer while you wait? Try asking our experimental bot in #1095492539085230272.

shy moth
#

bump

stoic quartz
#

So you want to add the newsletter signup within the body of your posts (and not before or after the post yeah? Otherwise you could just add it to your singlepost.astro file that displays the rendered mdx yeah?)

// mySinglePost.astro

<h1>post.title}</h1>
<NewsletterSignup />
{
  post.Content ? (
    <>
      {/* @ts-ignore */}
      <post.Content />
    </>
  ) : (
    <Fragment set:html={post.content} />
  )
}
<NewsletterSignup />

I'm no wiz, but I'd assume the only option might be:

a) Add some type of marker in the mdx:


Hello mom!

??NewsletterFormHere??

## My other heading...

b) Intercept that post.Content in your mySinglePost.astro and modify it before it renders?

But then is ??NewsletterFormHere?? that much more of a burden than the official approach:

import NewsletterForm from 'path/to/component';
## My content...
<NewsletterForm />
## My other content...

?

OR, if you are asking how to bulk edit many mdx files, I wonder if this might be helpful? https://stackoverflow.com/questions/64148177/can-i-bulk-edit-multiple-file-with-vs-code

(OR I could be missing something!)

shy moth
#

@stoic quartz Thanks for the reply. I got it working with the below code after finding someone in another thread with a similar problem.

So I couldn't get the astro-auto-import to work, but I did get a custom remark plugin to work. Perhaps there's something out there that automatically does this, but here's what I did:

import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkMdx from "remark-mdx";

const code = `import NewsletterSignup from "../../components/NewsletterSignup/NewsletterSignup.tsx";
  `;

// note that the below code DOES NOT WORK. It works in dev but not when built. Relative paths are necessary
// const code = `import NewsletterSignup from "./src/components/NewsletterSignup/NewsletterSignup.tsx";
//   `;

const ast = unified().use(remarkParse).use(remarkMdx).parse(code);

export default function remarkAddImport(options) {
  return (tree) => {
    // at the start of every mdx file, import necessary components
    tree.children.unshift(ast);
    // console.log(JSON.stringify(tree, null, 4));
  };
}

Then in astro.config.mjs, import your remark plugin and add it to the mdx remark plugins in integrations

integrations: [
  tailwind(),
  react(),
  mdx({
    remarkPlugins: [remarkAddImports],
  }),
],
stoic quartz
#

Great. So I'm curious (as I consider how I use common components across many mdx files), the end result =

a) Every mdx file automatically has: import NewsletterSignup from "../../components/NewsletterSignup/NewsletterSignup.tsx"

b) You then manually add <NewsletterSignup /> wherever you want in the mdx file.

Yeah?

shy moth
#

Yep you got it. The reasoning is that with the CMS setup I have it puts in <NewsletterSignup /> but doesn't put in the import statement. The integration astro-auto-import should do that but I couldn't get it to work. Going to try and make a simple project to replicate that and post it as an issue for that integration.

stoic quartz
#

Thanks @shy moth, makes sense. Follow up Q if you don't mind: re: CMS + Astro: And preferences re: git-based CMSes like Tina etc vs hosted CMSes like Storyblok, Contentful etc... vs other? home grown? (yeah, 'it depends on use case' I'm sure, but curious if you had any thoughts to share since you've been there, done that.) Thanks!

shy moth
#

I did a quick test with Sanity to see how that worked and it was pretty easy. It's mostly pay as you go. Making a project with Tina CMS right now for something free (for 2 people). Wanted to keep everything in git as this won't be a huge site, and wanted to optimize images. So I'm really just using Tina to add and edit github files (markdown, mdx, json, images) and then using astro content collections for the experimental image optimization. Just using SSG. Run into a number of quirks just due to how Tina CMS inputs data into files (like not putting the import statement). However Tina has a query feature so you could use that instead of content collections and it would probably be easier.

#

One I want to try later is Decap (formerly Netlify CMS). Since all I want to do is edit files in the github repo. I also plan to learn WordPress basics and how to use it Headless for freelancing purposes.