Will
Posted on September 3, 2022
The Svelte Markdown tutorials I've seen out there assume that you have access to a .md
file or are writing Markdown directly in a preprocessed file.
What if you wanted to render a raw string that contains Markdown? Example use-case: You want the flexibility of being able to serve Markdown content from a CMS (such as Strapi) without having to make changes to a .md
file.
There are a few ways you can achieve this, in this solution we'll be using mdsvex
to convert the Markdown into HTML format, then rendering that HTML. mdsvex
is a Markdown preprocessor which is essentially a wrapper for MDX, making it compatible for Svelte.
Installation
If you're not using SvelteKit, check out the MDsveX docs for alternative installations, if you are:
Start by installing it as a dev-dependency.
npm i --save-dev mdsvex
or...
yarn add --dev mdsvex
Then update the Svelte configuration to include an extensions
array:
(We'll just be using a .svelte
file, but you can also include extensions such as .svx
if you plan on using those file types)
svelte.config.js
export default {
preprocess: [
// your existing config
],
extensions: ['.svelte'], // Add this
kit: {
// your existing config...
}
};
That's all the configuration we need for now. ☑️
Passing the compiled string to the component
Let's set up a route loader that simulates fetching data from an API:
+page.server.ts
import type { Load } from '@sveltejs/kit';
const MOCK_RESPONSE_FROM_API = `
## Lorem
Lorem is currently extended with the following plugins.
Instructions on how to use them in your application are linked below.
| Plugin | README |
| ------ | ------ |
| Dropbox | [plugins/dropbox/README.md](Link) |
| Medium | [plugins/medium/README.md](Link) |
| Google Analytics | [plugins/googleanalytics/README.md](Link) |
`;
export const load: Load = async () => {
const response = MOCK_RESPONSE_FROM_API; // Get data with eg. `fetch`
return response;
};
Next, we can import the compile
function from mdsvex
, declare a variable passing the (mock) response
into it, and return it so it's available in our component. We'll also log it to see what gets returned from compile
:
+page.server.ts
import { compile } from 'mdsvex';
// ...
const compiledResponse = await compile(response);
console.log('compiledResponse is: ', compiledResponse);
return compiledResponse;
// ...
console output (Given this is being run server side, it's viewable on the terminal, not the browser console)
As you can see, the Markdown has been compiled into what looks like HTML string format, appended together with the +
operator, under the key of code
.
So we can update the return statement to only include what we need:
+page.server.ts
export const load: Load = async () => {
const res = MOCK_RESPONSE_FROM_API; // Get data with eg. `fetch`
const compiledResponse = await compile(res);
return { content: compiledResponse?.code };
};
Rendering the HTML directly into the component
Now from our component, all we need to do is receive the data
through export let
, and render it.
Usually, strings are inserted as plain text, meaning that characters like < and > have no special meaning. So given we've now got HTML that we want to render directly, we can use HTML tags:
<p>{@html string}</p>
so in our case...
+page.svelte
<script lang="ts">
export let data = {
content: ''
};
</script>
<div>{@html data.content}</div>
Which gives us our rendered Markdown 🪄:
Note from the docs:
Svelte does not sanitise expressions before injecting HTML. If the data comes from an untrusted source, you must sanitise it, or you are exposing your users to an XSS vulnerability.
Further Customisation
The compile
method accepts a second parameter, options
:
interface MdsvexOptions {
extensions: string[];
smartypants: boolean | smartypantsOptions;
layout: string | { [name: string]: string };
remarkPlugins: Array<plugin> | Array<[plugin, plugin_options]>;
rehypePlugins: Array<plugin> | Array<[plugin, plugin_options]>;
highlight: { highlighter: Function, alias: { [alias]: lang } };
frontmatter: { parse: Function; marker: string };
}
This means that you can transform your HTML with tools like rehype or remark. You can find out more about the available options here.
That's it! 👨💻
If you need any further information on the above or anything else related - check out the SvelteKit docs, the MDX docs or the official Svelte discord.
Posted on September 3, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.