Astro - markdown content

How to grab markdown file content in Astro

//TODO: This post needs a revision to a recent Astro version.

//TODO: Accompanying demo material for this article has been deleted as it did not work with Astro V1+.

Intro

We want to access “compiled” markdown content from our .md files.

In Astro, working with markdown files .md is very easy, and for most of your tasks you rely on the file’s frontmatter. There are a lot of use-cases where this is sufficient.

But there are some use-cases, where you need the actual content of your markdown, and getting to it has proven difficult.

After a few failed attempts, I now have the secret formula for grabbing the markdown content without resorting to something like node:fs and doing a custom implementation.

Krabby Patty secret-formula

Kudos to clarkio on the Astro Discord for figuring it out!
The thread

Formula

Using Astro.glob(); and import.meta.globEager() for non-Astro pages.

From Non-HTML Pages

For this scenario, we’ll use import.meta.globEager('./blog/*.md').

//-- /src/pages/exportSearchIndexWithContent.json.js
export async function get() {
  let posts = await import.meta.globEager(`./blog/*.md`);
  let ary = [];
  for (let postkey in posts) {
    if (posts[postkey].frontmatter.published && posts[postkey].frontmatter.title) {
      let post = posts[postkey];
      let awaitedPost = await post.default(); //1//
      ary.push({
        title: post.frontmatter.title,
        summary: post.frontmatter.summary,
        tags: post.frontmatter.tags.join(' '),
        appCode: 'roc',
        published: post.frontmatter.published,
        slug: post.url,
        image: post.frontmatter.og.basic.image,
        content: awaitedPost.metadata.source  //2//
      });
      
    }
  }
  let body = { entries: ary };
  return {
    body: JSON.stringify(body, false, 2)
  };
};

The snippet contains a full operational non-HTML page, and you can view the results in the following link:

View result

The relevant/key lines on the above snippet I have commented with (1) and (2).

Another unlocked property is html which contains compiled markdown, except for parts where AstroComponents are used, which cannot be compiled during markdown and require an extra step.

From Astro Components

Using Markdown Component

For this scenario, we’ll use the available Astro.glob('./blog/*.md').

//-- /src/pages/blog/samples/astro-md-content/using-markdown.astro
---
import { Markdown } from 'astro/components';

let posts = await Astro.glob('./sample-md.md');
let post = posts[0];
let awaitedContent = await post.default(); //1//
---
<Markdown>
{awaitedContent.metadata.source} //2//
</Markdown>

View result

The relevant/key lines on the above snippet I have commented with (1) and (2).

Using straight post.Content

A variant pointed out by clarkio is achieved by:

//-- /src/pages/blog/samples/astro-md-content/using-content.astro
---
let posts = await Astro.glob('./sample-md.md');
let post = posts[0];
---
<post.Content />

View result

Turns out the Content property is an AstroComponent and will take care of outputting the compiled markdown.

Conclusion

The markdown content is “hidden” away behind an async default() method, and found at .metadata.source.

It makes sense that it is not readily available as it could fill someone’s memory resources if the amount of files is considerably large.

Perhaps we will see an official way to obtain this content in the near future when the documentation reaches a more stable state.



Back to Post List
ok!