Supercharged syntax highlighting with Astro & Rehype Pretty Code
Want to add next level syntax highlighting to your Astro blog? We take a look at Rehype Pretty Code - a simple way to add beautifully highlighted code to your website.
Astro is great for building content focussed websites, in particular developer blogs. When it comes to displaying code, the built-in Shiki highlighter does a good job at displaying your code nicely. But what if you crave some next-level features that go beyond simply highlighting keywords? Thatâs where Rehype Pretty Code comes in. You get all these awesome features in your code blocks:
- Line numbers
- Word & line highlighting
- Titles
- Captions
- Light & dark themes
Letâs take a look at getting it working in an Astro blog.
Setup
Firstly, initialise a new Astro website (jump to here if you have an Astro project already).
yarn create astro Call your project whatever you want, but be sure to select a blog template to get things going quickly. Select the defaults for the rest of the setup and then open up the project in your IDE of choice.
Install additional dependencies
Weâre going to need to install a few more dependencies. Run this command in your terminal:
yarn add rehype-pretty-code shiki RPC is a rehype plugin powered by Shiki to highlight code blocks. It also has the additional benefit of running at build time so you get all these fancy features without any extra Javascript added to your pages. That keeps things moving pretty fast! đđžââď¸đ¨
Modify Astro config
With all our dependencies installed, we can now modify our Astro config to include the new rehype plugin:
import { defineConfig } from "astro/config";
import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
import rehypePrettyCode from "rehype-pretty-code";
// https://astro.build/config
export default defineConfig({
site: "https://example.com",
integrations: [mdx(), sitemap()],
markdown: {
rehypePlugins: [rehypePrettyCode],
},
}); If you run yarn dev now in your terminal and navigate to the âMarkdown Style Guideâ page youâll see some beautifully styled code blocks, but weâre not quite there yet. As I mentioned earlier, Astro has built in syntax highlighting that we need to disable in order to get to the new stuff, so letâs go ahead and disable that:
export default defineConfig({
site: "https://example.com",
integrations: [mdx(), sitemap()],
markdown: {
rehypePlugins: [rehypePrettyCode],
+ syntaxHighlight: false,
},
}); Now the setup is complete, weâre ready to take our code blocks to the next level! (I think thatâs the nerdiest sentence Iâve ever written in my life.)
Using our new powers đڏââď¸
RPC uses meta strings to configure the code blocks to add in details like titles, captions, highlighted lines etc. The syntax (for want of a better phrase) is very simple, and full details can be found on their website. Weâll just go over some basics here. Feel free to add these examples to the same âMarkdown Style Guideâ page we viewed earlier to see them in action.
```js title="/src/app/fetchMovie.js"
const movies = await fetchMovies();
``` Adding a title
```js caption="Fetch movies from our server"
export async function fetchMovies() {
const response = await fetch("http://example.com/movies.json");
return await response.json();
}
``` Adding a caption
```js {2-4}
const movies = await fetchMovies();
movies.map((movie, i) => {
console.log(movie.title);
});
``` Adding highlighted lines
```js /movie.title/
const movies = await fetchMovies();
movies.map((movie, i) => {
console.log(movie.title);
});
``` Highlight specific words & phrases (uses regex)
```js showLineNumbers
const movies = await fetchMovies();
movies.map((movie, i) => {
console.log(movie.title);
});
``` Adding line numbers
Adding styles
Now if you head over to the markdown style guide page, you might not notice much difference. Thatâs because RPC doesnât add styles to these âsuperchargedâ elements. Thatâs for you to do, so you remain in full control and can apply whatever styles you want. We can target all these elements using the attributes added to our code blocks.
Letâs make a new posts.css file in the styles directory of our project. Itâs good to separate so weâre not clogging up other pages with unnecessary CSS. Weâll need to import this into our blog post [slug] page as well.
import "../../styles/posts.css"; /* Styling titles */
[data-rehype-pretty-code-title] {
background-color: #6f4870;
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
color: #eee;
margin-bottom: -1.5rem;
padding: 0.5rem;
text-align: center;
}
/* Styling captions */
[data-rehype-pretty-code-caption] {
text-align: center;
font-size: 1rem;
line-height: 1.25rem;
}
/* Styling highlighted blocks */
[data-highlighted-line],
[data-highlighted-chars] {
background-color: rgba(49, 173, 113, 0.4);
}
[data-highlighted-line] {
border-left-width: 4px;
border-left-style: solid;
border-left-color: #6f4870;
}
/* Styling line numbers */
[data-rehype-pretty-code-fragment] pre > code {
display: grid;
counter-reset: line;
}
[data-line-numbers] > [data-line]::before {
counter-increment: line;
content: counter(line);
display: inline-block;
width: 1rem;
margin-right: 2rem;
text-align: right;
color: gray;
} Almost there! Finally, letâs add some base styles to get everything looking a bit neater.
/* Neaten everything up */
[data-rehype-pretty-code-fragment] pre {
padding-left: 0;
padding-right: 0;
overflow-x: scroll;
}
[data-line] {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
[data-rehype-pretty-code-title] + pre {
border-top-right-radius: 0px;
border-top-left-radius: 0px;
} Nice. Weâve added a lot of stuff already and now our code blocks are looking great. But what about if youâve got a site that supports multiple themes?
Light & dark themes
RPC makes it easy to configure separate light and dark themes. It requires a minor change in our Astro config and a little more CSS. Add the following underneath your imports in the Astro config file:
/** @type {import('rehype-pretty-code').Options} */
const options = {
// https://rehype-pretty-code.netlify.app
theme: {
dark: "slack-dark",
light: "slack-ochin",
},
}; And make the following edit where youâve included the rehype plugin:
markdown: {
- rehypePlugins: [rehypePrettyCode],
+ rehypePlugins: [[rehypePrettyCode, options]],
syntaxHighlight: false,
remarkPlugins: [a11yEmoji],
}, Finally, we just need to add this CSS to hide/show the appropriate theme depending on the system settings:
/* Light/dark themes*/
@media (prefers-color-scheme: dark) {
*[data-theme="light"] {
display: none;
}
}
@media (prefers-color-scheme: light) {
*[data-theme="dark"] {
display: none;
}
}
.slack-ochin {
background-color: #eee !important;
} Alternatives
Not gonna lie, thatâs a lot of effort to get decent syntax highlighting working on our website, but now we can reap the benefits! đŞđž You might prefer another integration, however. Expressive Code essentially does the same thing and it even has support for copying code blocks to your clipboard, but no light/dark mode toggling baked in. I also had to use the remark plugin rather than the Astro one in order to get it working. Your mileage may vary!
Thereâs also Prism which shares a lot of the same features, but will add some Javascript bulk to your pages. And thatâs before youâve even added more plugins for line-highlighting and other features!
If youâve got any other suggestions, Iâd love to hear it!