TLDR
Add this file to your project e.g. as libs/shiki.js
:
jsconst shiki = require('shiki'); module.exports = (eleventyConfig, options) => { // empty call to notify 11ty that we use this feature // eslint-disable-next-line no-empty-function eleventyConfig.amendLibrary('md', () => {}); eleventyConfig.on('eleventy.before', async () => { const highlighter = await shiki.getHighlighter(options); eleventyConfig.amendLibrary('md', (mdLib) => mdLib.set({ highlight: (code, lang) => highlighter.codeToHtml(code, { lang }), }) ); }); };
And then add it as a plugin to your eleventyConfig
:
jsmodule.exports = function(eleventyConfig) { eleventyConfig.addPlugin(require("libs/shiki.js"), { theme: "dark-plus" }); // [...] }
That's all? Those couple of lines to all the work?
Yep, that's all.
There is no hidden magic and everything that you can pass to shiki.getHighlighter()
you can pass as options to this plugin.
So if you're fine with the limitation that you can't add some fancy focus, highlight or diff markers, then this is already enough for you.
The not so short version
Let's start with an empty plugin:
jsmodule.exports = (eleventyConfig, options) => { };
eleventyConfig
is the current eleventyConfig like it's also passed into your .eleventy.js
(or similar) file. options
is just the second parameter you can add to your eleventyConfig.addPlugin(plugin, someOptions)
call. The options
just get passed through.
Since 11ty does not yet support async configuration functions, but shiki needs them, we need to do a small trick: 11ty hooks can be async. So let's piggyback off of the eleventy.before
event.
jsconst shiki = require('shiki'); module.exports = (eleventyConfig, options) => { eleventyConfig.on('eleventy.before', async () => { const highlighter = await shiki.getHighlighter(options); }); };
The eleventyConfig.amendLibrary()
function is new in 11ty 2.0. You can still work around this on <2.0 by pulling the highlighter variable into an outer scope and using the eleventyConfig.setLibrary()
function.
Now we just need to replace the default syntax highlighter of our markdown library with our custom one:
jsconst shiki = require('shiki'); module.exports = (eleventyConfig, options) => { eleventyConfig.on('eleventy.before', async () => { const highlighter = await shiki.getHighlighter(options); eleventyConfig.amendLibrary('md', (mdLib) => mdLib.set({ highlight: (code, lang) => highlighter.codeToHtml(code, { lang }), }) ); }); };
This is basically done, but we need to add one empty eleventyConfig.amendLibrary()
call, so eleventy knows that we want to change the library and actually calls our amend function:
jsconst shiki = require('shiki'); module.exports = (eleventyConfig, options) => { // empty call to notify 11ty that we use this feature // eslint-disable-next-line no-empty-function eleventyConfig.amendLibrary('md', () => {}); eleventyConfig.on('eleventy.before', async () => { const highlighter = await shiki.getHighlighter(options); eleventyConfig.amendLibrary('md', (mdLib) => mdLib.set({ highlight: (code, lang) => highlighter.codeToHtml(code, { lang }), }) ); }); };
If you now want to know where to look next, take a look at the shiki project page.
Since my last post about shiki was really long and described a really deep way on how to use and modify shiki, this is the complete opposite. This shows just short and simple how to use shiki in your eleventy (11ty) project.