This post is a continuation of my migration journey from WordPress to Astro. If you have not read the previous posts, you might want to start with Why I Switched from WordPress to Astro, How I Moved My Blog Content and how I am Replacing WordPress Plugins with Astro: Acronyms, Meta Tags & Tag Clouds.
In this post, I cover how I replaced the next set of WordPress plugins with equivalent functionality in Astro:
Enlighter
The Enlighter plugin provided syntax highlighting for code blocks in WordPress, allowing custom styles and line numbers.
Astro Implementation
I replaced Enlighter with Expressive Code
.
It is a powerful and flexible replacement for syntax highlighting in Astro.
Here’s how I set it up:
import { defineConfig } from "astro/config";import expressiveCode from "astro-expressive-code";
export default defineConfig({ integrations: [ expressiveCode({ plugins: [pluginLineNumbers()], defaultProps: { wrap: true, showLineNumbers: false, }, styleOverrides: { codeFontFamily: "var(--font-monospace)", codeFontSize: "0.78125rem", codeLineHeight: "1.6", uiFontSize: "0.78125rem",
lineNumbers: { highlightForeground: "#85c7ebb3", }, }, }), ],});
I configured it to wrap long lines by default and disabled line numbers unless explicitly enabled. Additionally, I set the font family, size, and other styles to match the styling of my blog.
Using My Visual Studio Code Theme
I prefer the syntax highlighting theme in Visual Studio Code over the default GitHub styling.
Expressive Code allows you to define custom themes based on VS Code exports. So, I exported my theme and applied it in Expressive Code!
{ "$schema": "vscode://schemas/color-theme", "type": "dark", "colors": { "actionBar.toggledBackground": "#383a49", "activityBar.activeBorder": "#0078d4", "activityBar.background": "#181818", ... }, "tokenColors": []}
Full VS Code theme available here: vscode-theme.jsonc
Because the theme file is a jsonc
file. I had to load it in a specific manner in the astro.config.mjs
file:
import { defineConfig } from "astro/config";import { readFileSync } from "fs";import expressiveCode, { ExpressiveCodeTheme } from "astro-expressive-code";
const jsoncString = readFileSync(new URL(`./src/config/vscode-theme.jsonc`, import.meta.url), 'utf-8')const vscodeTheme = ExpressiveCodeTheme.fromJSONString(jsoncString)
export default defineConfig({ integrations: [ expressiveCode({ ... themes: [vscodeTheme] }) ],})
As you can already see in all the code samples in my posts, the syntax highlighting is working beautifully.
Full implementation on GitHub: astro.config.mjs.
Recent Post Widget Extended
The Recent Post Widget Extended plugin displayed recent posts dynamically.
Astro Implementation
In Astro, I created a simple loop using Astro’s Content Collection API.
---import { getCollection } from 'astro:content';
const unsortedPosts = await getCollection('posts')const posts: { data: { permalink: string; title: string } }[] = sortedPosts(unsortedPosts);
Next, I render the recent posts in the sidebar while filtering out the current post (if applicable):
<aside id="recent-posts"> <h2>Recent Posts</h2> <div> <nav> <ol> { posts .slice(0, 6) .filter((p) => p.data.permalink !== Astro.url.pathname) .slice(0, 5) .map((post) => ( <li> <a href={post.data.permalink} target="_self"> {post.data.title} </a> </li> )) } </ol> </nav> </div></aside>
Full implementation on GitHub: Sidebar.astro.
WP External Links
The External Links plugin manages external links, adding icons and SEO attributes.
Astro Implementation
I replaced this with rehype-external-links,
configuring it in astro.config.mjs
:
import rehypeExternalLinks from "rehype-external-links";
export default defineConfig({ markdown: { rehypePlugins: [ [ rehypeExternalLinks, { content: {}, rel: ["noopener", "noreferrer", "external"], target: "_blank" } ] ], },});
Now every link that contains an external URL will open in a new tab with the noopener
, noreferrer
, and external
attributes.
Using CSS on a
tags where the rel
attribute contains external
, I added an external link icon:
a[rel~="external"] span { width: 10px; height: 10px; display: inline-block; margin-left: 0.3em; background-image: url(/icon-13.png);}
You can see this implementation in action with various external links on this page.
If you want to exclude certain domains from being treated as external links,
you can use a test
function in the configuration.
I used this to exclude LinkedIn links.
View the full code on GitHub: astro.config.mjs and global.css.
This was the next set of 3 plugins I replaced with Astro functionality.
In the next post, I will cover more plugins, including paging, related posts, and more.