Extensible Markdown-to-Svelte transpiler.
For my blog I needed a Markdown-to-Svelte transpiler.
The most popular option was MDsveX,
but after failing to integrate with it various modern versions of plugins
from the Unified.js/Micromark/Remark/Rehype ecosystem,
I found this: https://github.com/pngwn/MDsveX/discussions/236#discussioncomment-672015 .
This is still an issue at the time of writing.
MDsveX also coupled my code base to a major version of Svelte that I was not using.
While trying to adapt it, I stumbled over approx. 19k LOC of its monorepo (as counted by cloc --vcs=git
).
All of this disqualified MDsveX for my purpose.
Thus this re-implementation of a Markdown-to-Svelte transpiler based on a few observations (see Rationale) that made it possible to achieve roughly the same in just over 120 lines of code.
Based on a Unified.js pipeline without parsing Svelte code. See Features section below.
The following basic observations allow an extremely lean Markdown-to-Svelte transformation pipeline:
It follows that the 'core feature' of md2sv
(and MDsveX
by extension) comes absolutely for free.
This is reflected in the fact that it is hard to tell if a source is 'Svelte in Markdown' or 'Markdown in Svelte'.
Both are valid Markdown or Svelte.
In other words, any Markdown-to-HTML transpiler already does 'MDX for Svelte', and a library is redundant.
Why, then, create a library anyway? See Features section.
{'{'}
and {'}'}
(even though they are rare in prose).md2sv
provides to to you a
Markdown Directive named raw
export
statements in Svelte's <script context="module">
.
This makes the keys defined in the frontmatter available as attributes of the Svelte component.For illustration, see the unit tests and the example, in particular the input and the output.
The following were intentionally not implemented; however, since md2sv is easy to extend,
the following functionality can easily be added by yourself if and wherever you need it using
rehypePlugins{Pre,Post}
and remarkPlugins{Pre,Post}
(see API).
For a rich example pipeline having all those features, see example.
md2sv
is a factory, taking an options object of type ProcessorOptions
;
it returns a pipeline of type Unified.js Processor
.
ProcessorOptions
Custom plugins can be injected at various locations:
remarkPluginsPre
: before md2sv's remark plugins
remarkPluginsPost
: after md2sv's remark plugins (just before rehype translation)
rehypePluginsPre
: before md2sv's rehype plugins (just after rehype translation)
rehypePluginsPost
: after md2sv's rehype plugins (just before HTML serialization)
Add the following preprocessor object to your svelte.config.js
:
{
name: 'md2sv',
markup: ({ content, filename }) => {
if (!['mdx', 'md'].includes(filename.split('.').pop())) return;
const file = new VFile({ path: filename, value: content });
md2sv().processSync(file);
return {
code: file.value,
data: file.data,
map: '',
};
},
}