This will describe how to do the following in Sveltekit:
- Pull markdown content from a CMS;
- Render it in a Svelte Component styled with Tailwind;
- Add syntax highlighting to code blocks.
Setup
Install Tailwind:
1
npx svelte-add@latest
Install tailwind typgography:
1
2
3
4
5
6
7
8
npm install -D @tailwindcss/typography
add to plugins in tailwind.config.js:
plugins: [
require('@tailwindcss/typography'),
// ...
],
Install markdown-it:
1
npm i markdown-it
Install highlight.js:
1
npm i highlight.js
Install graphql-request
1
npm add graphql-request graphql
Steps
In +page.server.js we get the markdown from a graphql query and we render the markdown using markdown-it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
---
/routes/blog/[slug]/+page.server.js
---
import { request, gql } from 'graphql-request'
import MarkdownIt from 'markdown-it/lib';
import hljs from 'highlight.js';
export async function load({ params }) {
const slug = params.slug;
const query = gql`
{
bookmarks(filter: {slug: {_eq: "${slug}"}}) {
id
title
md
}
}
`
const response = await request(
'http://127.0.0.1:8055/graphql',
query,
)
console.log(response);
const markdown = response.bookmarks[0].md;
const md = new MarkdownIt({
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (e) {
// eslint-disable-next-line no-console
console.error('Failed to highlight string');
}
}
return ''; // use external default escaping
}
});
const rendered = md.render(markdown);
return {
rendered
};
}
In +page.svelte we read in the rendered data, we import the css styling for highlight.js, we wrap it in the typography prose class from tailwind, and we render the rendered html!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
/routes/blog/[slug]/+page.svelte
---
<script>
import Hello from "../../../lib/components/Hello.svelte";
import MarkdownIt from 'markdown-it/lib';
import 'highlight.js/styles/a11y-light.css'
export let data;
</script>
<article class="prose lg:prose-xl">
{ @html data.rendered }
</article>
Now when we go tto localhost:5173/blog/first-post (where first-post is the slug we set in directus on the item which contains the markdown we want to render), we will see a nice looking page!
If you want greater customisation that the typography plugin, you can style things locally within svelte. You can create a class within which you can then style things. Or you could just affect all h1, h2 etc tags within your file.
1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="md">
<h1>Hello I am green</h1>
</div>
<h1>
I am another one but I am not green.
</h1>
<style>
.md h1 {
@apply text-green-700 text-3xl underline italic;
}
</style>
You can also (and this is probably the best option), use a combination of typography + custom styles so that you get sane defaults from typography but can override things if you want. What is nice is that it adds on top of typography. So if you only wanted to change the colour to green, but keep everything else you got from typography, that’s fine.
1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="prose md container mx-auto pt-10">
<h1>Hello</h1>
</div>
<h1>
I am another one
</h1>
<style>
.md h1 {
@apply text-green-700 text-3xl underline italic;
}
</style>
