No results

For AI agents and crawlers: a structured index of this site is available at https://danny.is/llms.txt.

Upgrading to Astro 7 and switching to Sätteri

I’ve just upgraded this site to Astro 7, including the switch from remark to the new Astro default, Sätteri.

The actual Astro upgrade was fairly painless since I did it before swapping out the markdown parser. The switch to Sätteri was a little more complex because I had a bunch of remark and rehype plugins which needed migrating to the MDAST or HAST plugins Sätteri uses.

MDAST Plugins

I now have the following MDAST plugins on this site, which work on the markdown syntax tree.

  • Reading time. satteriReadingTime injects minutesRead into the frontmatter for articles. It’s registered first so it measures the document before any ESM injection.
  • Footnotes. satteriFootnoteDetector detects whether content contains footnotes and adds hasFootnotes if it does. I use this to conditionally inject styling and javascript for showing inline footnotes on pages where it’s needed.
  • Auto-import MDX components. satteriMdxImports injects imports for all my MDX components (things like <Callout>) into every mdx file, replacing the astro-auto-import plugin I wrote about before. It also auto-applies MDX_COMPONENT_REMAPPING to any MDX pages using Page.astro.
  • Markdown Preview & FileTrees. satteriMarkdownPreview and satteriTreeBlock transform fenced code blocks for markdown previews and file trees into their respective components.

HAST Plugins

These work on the HTML syntax tree and to transform the HTML after Sätteri has done its stuff.

  • Heading ID Links. satteriAutolinkHeadings appends a # link to headings in content pages so it’s easy for folks to copy a URL to any heading.
  • Image Unwrapper. I have a <BasicImage> component which accepts a bunch of props to control how images are displayed and wraps Astro’s Picture component, often rendering a <figure> with a caption. Markdown image tags are remapped to use this automatically and since I often use markdown images inside other MDX components like <Grid>, I ended up with a bunch of issues where the image tags were getting wrapped in <p>s and then hoisted out by Astro’s HTML parser leaving lots of empty <p></p> elements within wrappers like Grid. This broke a lot of layout stuff, so satteriUnwrapImages strips the wrapping <p> from any paragraph whose only content is images, so the img → BasicImage remapping produces clean, directly-nested <figure>s.
  • Image Captions. satteriImageCaption lets me use CommonMark’s title attribute: ![alt](./image.jpg "This caption") injects This caption as BasicImage’s caption prop if present.
  • External links. External links in MDX files already render a SmartLink component which adds target="_blank" rel="noopener noreferrer" to external links. satteriExternalLinks does this for links in plain markdown files.
  • List density. satteriListDensity adds a long-list-items class to HTML lists where the list items are more like paragraphs than short bullet lists. I use this to increase the space between list items.
  • Mermaid diagrams. satteriMermaid renders mermaid fenced code blocks to inline SVGs at build time via mermaid-isomorphic. The colours from src/config/mermaid.js are rewritten to --mermaid-* CSS variables which use light-dark() so the SVGs respond to changes in theme.

I didn’t take any measurements but it feels like switching to Astro 7, Sätteri and Vite 8 has sped up my builds a little, and the process of rewriting the plugins above definitely helped to clean up and simplify the codebase a little.