Adding markdown with latex to svelte
Published at Apr 14, 2023
Preamble
The code from this post is based in large part on this guide but aims to extend it with proper support for some missing features. Its also moreso meant for people who maybe already have a working markdown blog but wish to add the full functionality you would expect from markdown.
So if you are just starting out I recommend you first go through the afroementioned guide and then come back here to add the final touches to get everything working.
Features
I’ll go through the list of features one by one and how to add them.
Full Syntax highlighting
There is the official way of extending the mdsvex options but as a fan of costumizability I really just preferred the more manual approach of just importing some nice PrismJS
themes from here. To use these themes I made a styles
folder in my src
directory then in the app.scss
at the top I just included the theme from the folder and it overwrites any theme.
app.scss
@import url(./styles/prism-synthwave84.css);
// other global styles
As a sidenote you don’t have to be using scss for this to work, it was just my preferred flavor of css.
To get the inline syntax highlighting to work you might have to extend the code stylesheet, since mdsvex renders inline code such as this
as <code>this</code>
so you should add the code
tag to the main styles block like this.
// for block style
code[class*="language-"],
pre[class*="language-"],
// for inline style
code,
// optionally if you want code inside liks for example
a > code {
// main code styles
...
}
Checkout this example if you are still a bit confused.
In the stylesheet you can also do things like add a nice rounded border and in general modify the sytax highlighting exactly to your liking.
Latex
One thing that was quite a struggle initally was getting latex working, the crux of the problem with latex is that svelte sees things inside braces { }
as JS expressions which can mess up rendering the latex, so we obviously need to escape them somehow before svelte tries treating the contents as code.
Luckily to do this you just need to surround whatever string you wish to render with the special {@html ""}
tag. Doing this manually everytime you want to write some latex is rather annoying but luckily someone already wrote a plugin
that wraps all math inside this tag. To use this plugin there are a few steps.
- Get katex
Include the required stylesheets and scripts in your app.html
header.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script>
- Install the required dependencies
pnpm i remark-math rehype-katex-svelte
- Costumize your
svelte.config.js
file
import preprocess from "svelte-preprocess";
import adapter from "@sveltejs/adapter-auto";
import remarkUnwrapImages from 'remark-unwrap-images'
import remarkToc from 'remark-toc'
import remarkMath from "remark-math";
import rehypeSlug from 'rehype-slug'
import rehypeKatexSvelte from "rehype-katex-svelte";
import { vitePreprocess } from "@sveltejs/kit/vite";
import { mdsvex } from 'mdsvex';
/** @type {import('mdsvex').MdsvexOptions} */
const mdsvexOptions = {
extensions: ['.md'],
remarkPlugins: [
remarkMath,
remarkUnwrapImages,
[remarkToc, { tight: true }],
],
// Render katex components inside @html blocks, aka {@html "<katex output html>"}
rehypePlugins: [
rehypeKatexSvelte,
rehypeSlug
],
}
/** @type {import('@sveltejs/kit').Config} */
const config = {
extensions: [".svelte", ...mdsvexOptions.extensions],
preprocess: [
vitePreprocess(),
mdsvex(mdsvexOptions),
preprocess({
scss: {
prependData: '@use "src/variables.scss" as *;',
},
})
],
kit: {
adapter: adapter(),
},
};
export default config;
Now you should be able to have both 🐈
And very cool looking block latex
with Katex. Checkout the katex docs for what is supported.
Final notes
If you have any recommendations for things to add feel free to open an issue or contact me dirctly and I will update this page.