While migrating my blog from Zola to Astro, I ran into an issue with RouterOS syntax highlighting. Astro uses Shiki for code highlighting, and Shiki doesn't include RouterOS out of the box. Here's how I solved it.

The problem#

When building the Astro site, I saw warnings like:

[Shiki] The language "routeros" doesn't exist, falling back to "plaintext".

My posts about MikroTik configuration were losing their syntax highlighting.

Finding a grammar#

Shiki uses TextMate grammars (.tmLanguage.json format). I found an Atom package with a RouterOS grammar in CSON format:

https://github.com/ofstudio/atom-language-routeros-script

CSON (CoffeeScript Object Notation) is essentially a more readable JSON, so conversion is straightforward.

Converting CSON to JSON#

First, create the grammars directory and download the grammar:

mkdir -p src/grammars
wget -q https://raw.githubusercontent.com/ofstudio/atom-language-routeros-script/master/grammars/routeros.cson

Then convert using npx cson:

npx cson routeros.cson src/grammars/routeros.tmLanguage.json
rm routeros.cson

Or use some other way to convert, should be straightforward.

Loading the grammar in Astro#

Update astro.config.mjs:

import { defineConfig } from "astro/config"
import { readFileSync } from "fs"

const routerosGrammar = JSON.parse(
  readFileSync("./src/grammars/routeros.tmLanguage.json", "utf-8")
)

export default defineConfig({
  site: "https://peterbabic.dev",
  markdown: {
    shikiConfig: {
      theme: "github-dark",
      langs: [
        {
          ...routerosGrammar,
          aliases: ["routeros"],
        },
      ],
    },
  },
})

Result#

Now RouterOS code blocks render with proper highlighting:

/system routerboard mode-button
set enabled=yes on-event=dark-mode

/ip firewall filter
add chain=input action=accept protocol=icmp
add chain=input action=drop

The same approach works for any language that has an Atom or TextMate grammar available but isn't included in Shiki by default. Enjoy!