Integrating Expressive Code in My Existing Astro JS Website

Tags: Astro JS, MDX

Context or Problem

For those who want to do it on your site just open their official docs and do it on your own.

Anyways, I just want to write the next episode from my last journal about encountering expressive code after take lot of time configuring another tools for it which is not bad, because I really learn much new things especially in CSS selector that using data[blabla] and rehype ecosystem.

For today challenge this may be just another refactoring things but I believe this is worth the time investment on it while I have too much free time too LOL.

Let’s see how I can integrate astro-expressive-code to my existing Astro JS website that fortunately not really have much articles or components yet so it shouldn’t be that hard.

Experiment

I start by writing this artile and make sure I have journal on everything I do in my daily random debugging time.

First I will just install astro-expressive-code and see if it conflicted with my existing spaghetti codebase.

npx astro add astro-expressive-code

Then try to run the project but I got this error message:

Incorrect integration order: To allow code blocks on MDX pages to use astro-expressive-code, please move astroExpressiveCode() before mdx() in the “integrations” array of your Astro config file.

So I tried to just comments all existing rehype-pretty-code part while following that info to see if it will works or not.

And everything works as I expected with default theme. Now I can just maybe steal my configuration from my testing project available on my other repo to be like this.

astro.config.mjs
// @ts-check
import { defineConfig } from "astro/config";
import tailwindcss from "@tailwindcss/vite";
import expressiveCode, { ExpressiveCodeTheme } from "astro-expressive-code";
import mdx from "@astrojs/mdx";
// @ts-ignore
import fs from "node:fs";
// Load your saved theme JSONC file here and create a theme from it
const jsoncString = fs.readFileSync(
new URL(`./beautiful-dracula.json`, import.meta.url),
"utf-8",
);
const beautifulDracula = ExpressiveCodeTheme.fromJSONString(jsoncString);
// https://astro.build/config
export default defineConfig({
vite: {
plugins: [tailwindcss()],
},
integrations: [
expressiveCode({
themes: [beautifulDracula],
}),
mdx(),
],
});

But it took long time to see the refreshed page. So I just restart the npm run dev command and see what will happen.

Well now it works! guess maybe my intel celeron devices can’t handle that config reload that fast haha.

Now I need to see my other published journal and make some, wait better I get rid of the custom css that I placed before to style rehype-pretty-code.

Now that everything works fine and my Tailwind CSS configuration simplified it’s a great time to rewrite some of my published journal .mdx file to make sure it didn’t break and also applied some features offered by expressive code to it.

I notice a little breaking changes, for inline code like

`let data = []{:js}` or `<Tag>{:html}`

Using rehype-pretty-code will have syntax highlighting too like this

a screenshot showcasing rehype-pretty-code in Astro JS that highlighting inline code

but, when I am using astro-expressive-code it didn’t work.

a screenshot showcasing expressive-code in Astro JS with it's default configuration that just works without any CSS tweaking

I will look if it can be styled by expressive code or I need to write custom css only for that inline code.

After doing some research (googling) I found, that feature is not available right now but still have posibility to come in future.

https://github.com/expressive-code/expressive-code/issues/250

So yeah I will just create custom CSS for it. The best thing I can do for it is just using the same background as the VSCode theme. I also need to get rid of tailwind typography prose css that automatically adding backticks tag on after:: and before::. End result was something like this

styles/global.css
/* Using direct rsms css file to have curly quotes etc, google font suck */
@import url("https://rsms.me/inter/inter.css");
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@theme {
--font-sans:
"Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/*"liga" 1, "calt" 1 used to fix for Chrome */
--font-sans--font-feature-settings: "liga" 1, "calt" 1, "ss02", "ss08";
}
.prose code {
@apply bg-[#1e1e2f] font-mono text-sm text-[#c1c1cb];
margin-block: -0.125rem;
padding: 0.125rem 0.375rem;
}

Adjusting the tailwind prose to not show additional backticks on inline code. Dunno if this is the correct way to do it but it works.

ProseContainer.astro
<article
class="mx-auto w-full max-w-3xl rounded-lg p-6 text-neutral-200 shadow prose-headings:text-neutral-300 prose-code:before:hidden prose-code:after:hidden">
<!-- Contents -->
</article>

Other things to consider is by default expressive code doesn’t have showLineNumbers except using a plugin but for now it was fine. Line number still usefull in future or in specific learning materials for student I bet, but for my journaling use cases it should be enough.

I also encountering stupid bug on my codebase (of course) that cause wrapped codeblock to just always make it overflowing inline in long text inside a codeblock even if it’s already have wrap tag.

I thought it was an issue on astro-expressive-code, but turn out it because my old custom component code for rehype-pretty-code which is CodeBlock.astro and mapped to <Content components={MDXComponentMapping} /> tag are the main problem. I spend that night and this morning, even reinstalling everything on this project LOL.

So I just remove it and not use any custom mdx component for code and pre at all and now everything works fine!

Outcome

Working fine codeblock highlighted with my favorite VSCode theme. Altought is not works on inline code like this it’s fine. It already have copy to clipboard button for some lazy people out there (like me).

Possible Next Steps

Keep writing and have muscle memory on using it on future journals.

References