Astro 7 · Sätteri

The plugins Sätteri left behind

Eight ports of the remark and rehype plugins that stop working when Astro 7 switches to Sätteri — each one demonstrated, and the whole page snapshot-tested in CI.

Astro 7 compiles Markdown with Sätteri, a Rust engine that does not run remark or rehype plugins. Everything below is a port that restores one of them.

This page is the proof. It is built by real Astro with all eight plugins enabled, and its HTML is asserted in CI, so nothing here can rot without the build going red.

Note that satteri-breaks is enabled, which turns every single newline into a break. Paragraphs in this document’s source are therefore written on one line each, except where the break is the point.

Package Replaces Shown under
satteri-slug rehype-slug Headings and anchors
satteri-autolink-headings rehype-autolink-headings Headings and anchors
satteri-katex rehype-katex Maths
satteri-mathjax rehype-mathjax Maths
satteri-breaks remark-breaks Line breaks
satteri-github remark-github GitHub references
satteri-sanitize rehype-sanitize Untrusted HTML
satteri-mdx-frontmatter remark-mdx-frontmatter the MDX page

Headings and anchors

satteri-slug gives every heading an id; satteri-autolink-headings adds the # you see on hover. Order matters: slug has to run first, and both have to run before Astro’s own heading pass.

Duplicate

Repeated headings are numbered rather than colliding. This one is duplicate.

Duplicate

This one is duplicate-1.

Punctuation, symbols & casing!

Punctuation is stripped and the text lowercased, exactly as rehype-slug did.

Maths

Sätteri parses maths but renders none of it, so without a plugin the expressions below reach the page as inert code blocks.

Inline maths flows with the text: the Pythagorean identity a2+b2=c2a^2 + b^2 = c^2a2+b2=c2 sits inside this sentence, as does Euler’s eiπ+1=0e^{i\pi} + 1 = 0e+1=0.

Display maths gets its own block:

ex2dx=π\int_{-\infty}^{\infty} e^{-x^2} \, dx = \sqrt{\pi}ex2dx=π tΨ(x,t)=i2m2Ψ(x,t)\frac{\partial}{\partial t} \Psi(x, t) = \frac{i\hbar}{2m} \nabla^2 \Psi(x, t)tΨ(x,t)=2mi2Ψ(x,t)

satteri-katex and satteri-mathjax are interchangeable and consume the same nodes, so exactly one can run. CI builds this page twice, once with each, and asserts both.

Maths that does not parse

A broken expression does not break the build. This one, \frac{a}, is left in place and flagged.

Line breaks

satteri-breaks turns a single newline into a break, so this address
stays on three lines
instead of collapsing into one.

GitHub references

satteri-github autolinks against this repo: #1 links to the first issue, @Ashish-CodeJourney links to a profile, and a1b2c3d links to a commit with the text abbreviated.

Untrusted HTML

satteri-sanitize runs last, so it sees every other plugin’s output as well as the document’s own HTML. Sätteri passes raw HTML straight through unparsed, which makes this the one plugin here that is load-bearing for security rather than convenience.

The block below contains a script, an event handler and a javascript: link. None survive.

a link that loses its href bold survives

Ampersands the author already encoded, like AT&T, stay encoded rather than being escaped a second time.

satteri-validate-links checks every link against something real. This page deliberately contains one that is not: a link to a heading that does not exist. The banner above the article is the plugin’s own output, read back from this page’s frontmatter.

It is a report, not a failure. Whether a broken link should stop your build is your decision, and this site chooses to show them rather than fall over.

Links to routes are skipped through the ignore option. Astro maps ./mdx to a page, but there is no ./mdx on disk, so checking the filesystem for it would report a link that works.

Built into Sätteri

These need no plugin. Porting them would have been wasted work.

Feature Syntax Enabled by
Tables this table gfm, on by default
Strikethrough like this gfm, on by default
Task lists see below gfm, on by default
Footnotes like this1 gfm, on by default
Maths parsing $x$ features.math
  • Tables, strikethrough and task lists
  • Footnotes
  • Anything needing remark-gfm

Code blocks are Astro’s own highlighter, untouched by any of this. Only language-math blocks are claimed by the maths plugins.

const { html } = markdownToHtml("## Hello", {
  mdastPlugins: [satteriBreaks(), satteriGithub(), satteriKatex()],
  hastPlugins: [satteriSlug(), satteriAutolinkHeadings(), satteriSanitize()],
});

Footnotes

  1. Footnotes are part of GFM, which Sätteri enables by default.