Sorting an Astro GlobPublished July 1, 2022
Astro is a framework that lets you bring your own framework and ship your site as static html (or semi-static). It’s a great product that’s almost out of beta, and it’s what this blog is currently written in. You can read more about it in my Astro review. Today we’re going to look at a brief hiccup I had while migrating content from WordPress to Markdown: namely, sorting posts. WordPress returns all their posts already sorted by date, so the latest post is at the front of the returned array. Astro doesn’t do that out of the box (how can it?). But once I realized why my posts were out of order, it was easy enough to fix by sorting the array. Let’s take a look.
Getting the Content
First, let’s take a look at how we get the Markdown content:
const posts = await Astro.glob('../content/blog/**/*.md');
src folder (next to components and pages), I have a content folder that stores all my site’s content, including blog posts, code samples, etc. We can get that content via
Astro.glob(). The glob will return an array based on the markdown files in the specified location. On my machine at least, this returned them in alphabetical order based on the name of the file. But in a blog, you typically want to display them in order of most recently written.
Sorting the Content
Once we have the array returned from
Astro.glob(), it’s easy enough to sort by date assuming you have a date property specified in the markdown’s frontmatter. Here is the typical frontmatter data for one of my blog posts:
title: Sorting an Astro Glob slug: sort-astro-glob date: "2022-07-01" excerpt: "Astro is a framework that let's you bring your own framework, but when this blog was rebuilt to use Markdown, I ran into an expected hiccup: the content was not being returned in date order like it was from WordPress. How can we sort the blog posts by date order?"
If you’re not familiar with frontmatter, you can read more about frontmatter in Astro here.
Astro.glob() returns an array, all you have to do is call
.sort() in that array and sort it by whatever data you want: in our case, date.
const posts = await Astro.glob('../content/blog/**/*.md'); posts.sort((a, b) => Date.parse(b.frontmatter.date) - Date.parse(a.frontmatter.date));
posts contains all of the content from our
/content/blog folder, sorted by its published date.
A Note on Sorting
Sorting arrays is pretty interesting, and not always intuitive. Take the following code:
const array = [80, 9, 22, 3]; array.sort();
You would expect this to return
[3, 9, 22, 80] or
[22, 3, 80, 9]. This is because calling
.sort() without a
const array = [80, 9, 22, 3]; array.sort((a, b) => a - b);
This correctly returns
[3, 9, 22, 80]. If you wanted a descending sort to get
[80, 22, 9, 3], you’d need to flip
a - b to
b - a. You can read more about sorting on MDN.
However, we’re not working with simple numeric arrays, we’re working with an array of objects. So instead of just doing
a - b, we need to pick the value we want to sort:
a.date - b.date, for example. To complicate things further, we’re storing the date as a string, so we need to get a numeric representation of that date. Hence,
Date.parse(a.date), which transforms the date like
"2022-07-01" to the number of milliseconds since January 1, 1970. You can read more about Date.parse() on MDN.
There’s nothing too complicated here, but it was a very minor speed bump in my conversion from WordPress to Markdown. I never thought about ordering in WordPress because it was already done out-of-the-box. It’s also something I couldn’t find on the Internet, and figured it was worth writing up to help anyone who comes after me. It makes sense that Astro is not auto-sorting the results of
Astro.glob(). After all, that would require a lot of assumptions. Since the function returns an easy-to-work-with array, we can quickly sort it ourselves. The only thing I might change is how much you have to drill to get to it (e.g.
glob could come with its own sort parameter, that might be a nice improvement.