How to assign class names to inline code elements in Markdown

  • astro
  • markdown
  • remark

Hunor Márton Borbély on

Many blogs use inline code blocks to highlight keywords. In Markdown, the styling of these inline code blocks is limited. They all look the same. In this article, I will show you how to write a plugin that lets you assign different class names to inline code elements in Markdown.

On SVG-Tutorial.com, the elements are highlighted in green, the properties are highlighted in purple, and the values are highlighted in blue.

How to draw a Circle in SVG

For today’s example, we draw a simple Christmas ornament. Here, we only use simple shapes: two circles and a rectangle.

To define a circle we need to set the following properties:

  • We set its center position with the cx and cy properties.
  • We set the radius with the r.

We define the main part of the Christmas ornament as a circle. We set its center position on the x-axis to the middle at 100 and on the y-axis, slightly below the middle at 120. We set a large radius and set its fill color. Hover over the element to see how it is positioned.

Read more

To achieve this, we need to have a custom Markdown processor. If you are using Astro, you can customize the Markdown processor with Remark plugins.

What is Remark?

Remark is a Markdown processor powered by plugins. With Remark, you can transform your Markdown content into HTML, React, or any other format you need.

The example above uses a custom Markdown annotation for inline code elements. It defines the inline code elements with a class name:

### How to draw a Circle in SVG
For today's example, we draw a simple Christmas ornament. Here, we only use simple shapes: two circles and a rectangle.
To define a `element:circle` we need to set the following properties:
- We set its center position with the `property:cx` and `property:cy` properties.
- We set the radius with the `property:r`.
We define the main part of the Christmas ornament as a circle. We set its center position on the x-axis to the middle at `value:100` and on the y-axis, slightly below the middle at `value:120`. We set a large radius and set its fill color. Hover over the element to see how it is positioned.

By default, the Markdown above would render into HTML as follows:

How to draw a Circle in SVG

For today’s example, we draw a simple Christmas ornament. Here, we only use simple shapes: two circles and a rectangle.

To define a element:circle we need to set the following properties:

  • We set its center position with the property:cx and property:cy properties.
  • We set the radius with the property:r.

We define the main part of the Christmas ornament as a circle. We set its center position on the x-axis to the middle at value:100 and on the y-axis, slightly below the middle at value:120. We set a large radius and set its fill color. Hover over the element to see how it is positioned.

We can write a Remark plugin that replaces the inline code elements in Markdown with HTML snippets that contain the class names. This way, we can style the different inline code elements separately by this class name:

### How to draw a Circle in SVG
For today's example, we draw a simple Christmas ornament. Here, we only use simple shapes: two circles and a rectangle.
To define a <code class="element">circle</code> we need to set the following properties:
- We set its center position with the <code class="property">cx</code> and <code class="property">cy</code> properties.
- We set the radius with the <code class="property">r</code>.
We define the main part of the Christmas ornament as a circle. We set its center position on the x-axis to the middle at <code class="property">100</code> and on the y-axis, slightly below the middle at <code class="property">120</code>. We set a large radius and set its fill color. Hover over the element to see how it is positioned.

Writing a Remark Plugin

We write a Remark plugin that replaces the inline code elements in Markdown with HTML snippets that contain the class names.

We use unist-util-visit package to visit every inline code element. Then, we use a regular expression to break down the content into a class name and a value. We replace the inline code element with an HTML element with the class name.

First, install the unist-util-visit package. The following example uses TypeScript. If we want to use TypeScript, we also need to install the types for unist.

Terminal window
npm install unist-util-visit @types/unist

The plugin uses the visit function to visit every inline code element in Markdown. Then, it checks the content of the inline code elements against a regular expression.

The regular expression breaks down the content into a capturing group for the class name and a capturing group for the value. The class name group will contain every character before the separator string, and the value group will contain every character after it.

The separator string is customizable with the separator option. By default, it is set to :.

If the content matches the regular expression, it replaces the inline code element with an HTML element. If the content doesn’t match the regular expression, it leaves the inline code element as it is.

remark-inline-code-class.ts
import { visit } from "unist-util-visit";
import { Node, Literal, Parent } from "unist";
type Options = Partial<{
separator: string;
}>;
export default function remarkInlineCodeClass(options?: Options) {
const separator = options?.separator || ":";
return (tree: Node) => {
visit(
tree,
"inlineCode",
(node: Literal, index: number, parent: Parent) => {
if (typeof node.value !== "string") return;
// Break down the content into class name and value
const regex = new RegExp(`^([^${separator}]+)${separator}(.+)$`);
const match = regex.exec(node.value);
if (match) {
const [, className, codeValue] = match;
const codeNode = {
type: "html",
value: `<code class="${className}">${codeValue}</code>`,
};
// Replace node with HTML snippet
parent.children.splice(index, 1, codeNode);
}
}
);
};
}

Configuring Astro

Now that we have our plugin, we can extend our Astro config to make use of it. This will automatically process every markdown file and replace the inline code elements with the new HTML elements.

import { defineConfig } from "astro/config";
import remarkInlineCodeClass from "./remark-inline-code-class.ts";
// https://astro.build/config
export default defineConfig({
markdown: {
remarkPlugins: [remarkInlineCodeClass],
},
});

Styling the Classes

Now, you can style the different classes in your global CSS file. For example, you can highlight the element class in green, the property class in purple, and the value class in blue.

code {
padding: 2px 5px;
border-radius: 2px;
border: 1px solid;
}
code.element {
border-color: rgb(133, 232, 157, 1);
background-color: rgb(133, 232, 157, 0.1);
}
code.property {
border-color: rgb(179, 146, 240, 1);
background-color: rgb(179, 146, 240, 0.1);
}
code.value {
border-color: rgb(158, 203, 255, 1);
background-color: rgb(158, 203, 255, 0.1);
}

Use an NPM package

If you don’t want to write the plugin yourself, I created an NPM package that does exactly this. It is called remark-inline-code-class. You can use it with Astro or any other Markdown processor that supports Remark plugins.

Install the package remark-inline-code-class to your project:

Terminal window
npm install remark-inline-code-class

Extend your Astro config file:

import { defineConfig } from "astro/config";
import remarkInlineCodeClass from "remark-inline-code-class";
// https://astro.build/config
export default defineConfig({
markdown: {
remarkPlugins: [remarkInlineCodeClass],
},
});

Then, you can use the new annotation in your Markdown files as follows:

The `element:circle` element has a radius `property:r` property.

This plugin doesn’t do any styling on its own. You have to define the styles for your class names in a global CSS file.

Custom Separator

The plugin lets you override the separator string that separates the class name from the value. You can set it in the Astro config file:

import { defineConfig } from "astro/config";
import remarkInlineCodeClass from "remark-inline-code-class";
// https://astro.build/config
export default defineConfig({
markdown: {
remarkPlugins: [[remarkInlineCodeClass, { separator: "|" }]],
},
});