· 4 min read
Astro + Rehype Pretty Code
![Applying Tailwind styles to your code snippets with light & dark modes.](/_astro/astro-rehype-pretty-code.DO23YQ-3_t2YWI.webp)
This an extension on this other guy’s post so read that first if you need to setup everything from scratch.
Background
Astro has been chugging along with new releases at quite a pace and with it came some changes in version 4 regarding plugins. I believe this is what killed my code snippet styling with additional factors from upgrade of shiki
to version 1.0 in the background behind rehype-pretty-code
so all of my original css has needed changing. This post documents the configuration changes needed to make it work again with the latest Astro 4, Tailwind and rehype-pretty-code
plugin.
Configuring Rehype Pretty Code Plugin
My webiste supports dark and light mode code snippets. The new way to support multiple themes is shown below with the imported themes I copied from their respective repo and copy/pasted into my project. Also, I had to update my Tailwind integration’s configuration shown below.
import dark_theme from './src/assets/themes/remedy-dark.json' assert { type: 'json' };
import light_theme from './src/assets/themes/remedy-light.json' assert { type: 'json' };
const prettyCodeOptions = {
theme: {
dark: dark_theme,
light: light_theme,
},
onVisitLine(node) {
// Prevent lines from collapsing in `display: grid` mode and allow empty lines
if (node.children.length === 0) {
node.children = [
{
type: 'text',
value: '',
},
];
}
},
...
}
export default defineConfig({
...
integrations: [
tailwind({
applyBaseStyles: false,
nesting: true,
}),
...
],
...
});
I also found I could remove my previous custom onVisitHightlightedLine
and onVisitHighlightedWord
hooks as this new Shiki version automatically adds data attributes for highlighted lines and characters which I now use in my new css selectors.
Styling Code Snippets with Tailwind
Dark Mode
Again, I followed this blog post becuase it was more clean than my original implementation so I won’t repeat everything but it lacked support for dark mode so I made a few customizations to fit my setup. Firstly, to get dark mode working I added the following to the bottom of my css for code snipets.
html pre span {
color: var(--shiki-light);
}
html.dark pre span {
color: var(--shiki-dark);
}
Hightlighted Lines
Tailwind adds the dark
class on the root html
element so this snippet changes the Shiki code theme when dark mode is active. There are a few ways to do this based on the shiki style guide but this works for me and we should not include the background-color: var(--shiki-foo)
as that will get in the way of the css that highlights lines of code. Oh, and with this implementation !important
is not required.
Making custom line hightlighting for dark mode is easy since we can still use the regular dark:
syntax.
pre {
@apply mx-auto overflow-auto p-4;
@apply scrollbar scrollbar-h-2 scrollbar-track-rounded-md scrollbar-thumb-rounded-sm scrollbar-thumb-slate-200 dark:scrollbar-thumb-slate-800;
[data-line] {
@apply mx-0 px-2 leading-tight;
}
[data-highlighted-line] {
@apply bg-orange/20 dark:bg-orange-500/10 border-l-orange-500 border-l-2 border-opacity-50;
}
[data-highlighted-chars] {
@apply rounded-md py-0 px-1.5 border-b-2 border-opacity-75 bg-opacity-30 dark:bg-opacity-20;
}
mark {
@apply text-inherit bg-orange-500 border-b-orange-500;
}
}
Background Color
Then I ran into trouble configuring a custom background color for code snippets in dark mode. Eventually, I realized because I’m using Tailwind’s typography plugin my code snippets are within the prose so the css defined by the prose
class which overwrites other background styles. So I added a line with prose-pre
classes to define and now we have our defined dark mode code snippet background.
[data-rehype-pretty-code-figure] {
@apply relative;
@apply rounded-lg bg-slate-200 dark:bg-slate-700;
@apply prose-pre:bg-slate-50 dark:prose-pre:bg-slate-900;
}
Group Highlighted Characters
This didn’t break but I wanted to add this as an addition to the aforementioned blog post for how to highlight custom colors based on characters with a specific ID.
[data-chars-id='1'] {
@apply bg-pink-500 border-b-pink-500;
}
[data-chars-id='2'] {
@apply bg-emerald-500 border-b-emerald-500;
}
[data-chars-id='3'] {
@apply bg-blue-500 border-b-blue-500;
}
In the previous section additional character highlighting styling is configured.
(Mostly) Complete CSS Demo
Besides the parts outside of base.css
mentioned earlier this is the majority of the css for my code snippet styling. It’s mostly specific style preferences I made for myself but I thought it was good to include the full context for this post.
[data-rehype-pretty-code-figure] {
@apply relative;
@apply rounded-lg bg-slate-200 dark:bg-slate-700;
@apply prose-pre:bg-slate-50 dark:prose-pre:bg-slate-900;
}
[data-rehype-pretty-code-title] {
@apply font-mono text-sm text-slate-900 dark:text-white ps-2 py-1;
}
[data-rehype-pretty-code-title] + pre {
@apply m-0 px-0 py-1 rounded-none rounded-b-lg;
}
pre {
@apply mx-auto overflow-auto p-4;
@apply scrollbar scrollbar-h-2 scrollbar-track-rounded-md scrollbar-thumb-rounded-sm scrollbar-thumb-slate-200 dark:scrollbar-thumb-slate-800;
[data-line] {
@apply mx-0 px-2 leading-tight;
}
[data-highlighted-line] {
@apply ps-1.5 bg-orange/20 dark:bg-orange-500/10 border-l-orange-500 border-l-2 border-opacity-50;
}
[data-highlighted-chars] {
@apply rounded-md py-0 px-1.5 border-b-2 border-opacity-75 bg-opacity-30 dark:bg-opacity-20;
}
mark {
@apply text-inherit bg-orange-500 border-b-orange-500;
}
}
[data-chars-id='1'] {
@apply bg-pink-500 border-b-pink-500;
}
[data-chars-id='2'] {
@apply bg-emerald-500 border-b-emerald-500;
}
[data-chars-id='3'] {
@apply bg-blue-500 border-b-blue-500;
}
[data-rehype-pretty-code-figure] code {
@apply grid gap-0 font-mono;
&[data-line-numbers] {
counter-reset: line;
> [data-line]::before {
counter-increment: line;
content: counter(line);
@apply ml-2 mr-4 inline-block w-4 text-right text-slate-400 dark:text-slate-700;
}
}
}
html pre span {
color: var(--shiki-light);
}
html.dark pre span {
color: var(--shiki-dark);
}
- astro
- tailwind