Preprocess Markdoc files for use in Svelte Kit sites.
Add the .md
extension and the markdoc
preprocessor to your Svelte Kit configuration:
import { markdoc } from "markdoc-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
extensions: [".svelte", ".md"],
preprocess: [markdoc()],
};
Markdoc allows you to configure various options for parsing:
To include these options in your preprocessing, pass them in the configuration. You can do this in two ways:
- Pass each individually as an option.
- Create a schema directory to include files that define each option for you. Include that directory in the markdown-svelte configuration.
In each case, imports happen before bundling, so import files as relative paths to JavaScript files with the extension. Use JavaScript files or run Node.js with a tool such as tsx to use TypeScript.
Use Markdoc functions to transform content. Include them as a file or directory in your Markdoc schema directory or in the markdoc-svelte configuration.
import { markdoc } from "markdoc-svelte";
const uppercase = {
transform(parameters) {
const string = parameters[0];
return typeof string === "string" ? string.toUpperCase() : string;
},
};
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [
markdoc({
functions: { uppercase },
}),
],
};
Use Markdoc nodes to customize how standard Markdown elements are rendered. Include them as a file or directory in your Markdoc schema directory or in the markdoc-svelte configuration.
Imports happen before bundling, so import files as relative paths to JavaScript files with the extension.
import { markdoc } from "markdoc-svelte";
import { link } from "./markdown/link.js";
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [
markdoc({
nodes: { link },
}),
],
};
Use Markdoc partials to reuse blocks of content in various places. Include them in a directory in your Markdoc schema directory or define a partials directory as a relative path in the markdoc-svelte configuration.
import { markdoc } from "markdoc-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [
markdoc({
partials: "./markdoc/partials",
}),
],
};
Use Markdoc tags to extend Markdown elements to do more. Include them as a file or directory in your Markdoc schema directory or in the markdoc-svelte configuration.
Imports happen before bundling, so import files as relative paths to JavaScript files with the extension.
import { markdoc } from "markdoc-svelte";
import { button } from "./markdown/button.js";
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [
markdoc({
nodes: { button },
}),
],
};
Use Markdoc variables to customize content during the build. Include them as a file in your Markdoc schema directory or in the markdoc-svelte configuration.
import { markdoc } from "markdoc-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [
markdoc({
variables: { flags: { best_feature_flag: true } },
}),
],
};
Markdoc tags are processed as the first thing.
This allows you to do things like use Markdoc variables inside code blocks.
But sometimes you want to include text like {% %}
inside a code block.
To mark a single code block to not be processed for tags, add a attribute to the block:
```markdown {% process = false %}
Use variables in your code: `{% product_name %}`
```
To set this as the default option, create a custom fence
node and set a different default
(example).
Frontmatter added as YAML is automatically parsed. So you could add frontmatter like the following:
---
title: A great page
---
With great content
You can then access it in your layouts:
<script lang="ts">
let {
children,
title = '',
} = $props()
</script>
<h1>{ title }</h1>
<!-- Article content -->
{@render children?.()}
And in your content:
---
title: Using the Next.js plugin
description: Integrate Markdoc into your Next.js app
---
# {% $frontmatter.title %}
You can choose to customize how Markdoc files are processed.
This preprocessor validates whether the Markdoc is valid.
By default, it throws an error on files for errors at the error
or critical
level.
To debug, you can set the level to a lower level and it stops the build for any errors at that level or above.
Possible values in ascending order: debug
, info
, warning
, error
, critical
import { markdoc } from "markdoc-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
extensions: [".markdoc", ".md"],
preprocess: [
markdoc({
validationLevel: "info",
}),
],
};
By default, files ending in .markdoc
and .md
are preprocessed.
To use other extensions, add them to the extensions
array in the options:
import { markdoc } from "markdoc-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
extensions: [".svelte", ".markdoc", ".md"],
preprocess: [
markdoc({
extensions: [".svelte", ".markdoc", ".md"],
}),
],
};
To give your processed Markdoc a layout, pass the path to the layout file:
import { markdoc } from "markdoc-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
extensions: [".svelte", ".md"],
preprocess: [
markdoc({
layout: "/path/to/layout.svelte",
}),
],
};
Frontmatter in YAML format is automatically passed to your layout as props. The content is passed as children that can then be rendered.
<script lang="ts">
let {
children,
title = '',
} = $props()
</script>
<h1>{ title }</h1>
<!-- Article content -->
{@render children?.()}
To define Markdoc options, you can use a directory that holds multiple options.
You can define each option as a single file or a directory with an index.js
file that exports the option.
Except for partials, which is a directory holding Markdoc files.
Example structure:
markdoc
├── functions.js
├── nodes
│ ├── heading.js
│ ├── index.js
│ └── callout.js
├── partials
│ ├── content.markdoc
│ └── more-content.markdoc
├── tags.js
└── variables.js
By default, the preprocessor looks for your Markdoc schema definition in a ./markdoc
directory at the app root.
To use a different path, define the directory in the options as a relative path.
import { markdoc } from "markdoc-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [
markdoc({
schema: "./path/to/schema/directory",
}),
],
};
In addition to the option to include Markdoc configuration as a single directory, you can pass each option individually: