Nuxt MDC
MDC supercharges regular Markdown to write documents interacting deeply with any Vue component. MDC stands for MarkDown Components.
Features
- Mix Markdown syntax with HTML tags or Vue components
- Unwrap any generated content (ex:
<p>
added by each Markdown paragraph) - Use Vue components with named slots
- Support inline components
- Add attributes and classes to inline HTML tags
Learn more about the MDC syntax on https://content.nuxtjs.org/guide/writing/mdc
Install
npm install --save-dev @nuxtjs/mdc
yarn add --dev @nuxtjs/mdc
pnpm add --dev @nuxtjs/mdc
Then, add @nuxtjs/mdc
to the modules section of your nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/mdc']
})
That's it! You can start writing and rendering markdown files ✨
Rendering
@nuxtjs/mdc
exposes three components to render markdown files.
<MDC>
Using <MDC>
, you can parse and render markdown contents right inside your components/pages. This component takes raw markdown, parses it using the parseMarkdown
function, and then renders it with <MDCRenderer>
.
<script setup lang="ts">
const md = `
::alert
Hello MDC
::
`
</script>
<template>
<MDC :value="md" tag="article" />
</template>
Note that ::alert
will use the components/global/Alert.vue
component.
<MDCRenderer>
This component will take the result of parseMarkdown
function and render the contents. For example, this is an extended version of the sample code in the Browser section which uses MDCRenderer
to render the parsed markdown.
<script setup lang="ts">
import { parseMarkdown } from '@nuxtjs/mdc/runtime'
const ast = await useAsyncData('markdown', () => parseMarkdown('::alert\nMissing markdown input\n::'))
</script>
<template>
<MDCRenderer :body="ast.body" :data="ast.data" />
</template>
<MDCSlot>
This component is a replacement for Vue's <slot/>
component, specifically designed for MDC. Using this component, you can render a component's children while removing one or multiple wrapping elements. In the below example, the Alert component receives text and its default slot (children). But if the component renders this slot using the normal <slot/>
, it will render a <p>
element around the text.
::alert
This is an Alert
::
<template>
<div class="alert">
<slot />
</div>
</template>
It is the default behavior of markdown to wrap every text inside a paragraph. MDC didn't come to break markdown behavior; instead, the goal of MDC is to make markdown powerful. In this example and all similar situations, you can use <MDCSlot />
to remove unwanted wrappers.
<template>
<div class="alert">
<MDCSlot unwrap="p" />
</div>
</template>
Prose Components
Prose components are a list of components that will be rendered instead of regular HTML tags. For example, instead of rendering a <p>
tag, @nuxtjs/mdc
renders a <ProseP>
component. This is useful when you want to add extra features to your markdown files. For example, you can add a copy
button to your code blocks.
You can disable prose components by setting the prose
option to false
in nuxt.config.ts
. Or extend the map of prose components to add your own components.
export default defineNuxtConfig({
modules: ['@nuxtjs/mdc'],
mdc: {
components: {
prose: false,
map: {
p: 'MyCustomPComponent'
}
}
}
})
Here is the list of available prose components:
Parsing Markdown
Nuxt MDC exposes a handy helper to parse MDC files. You can import the parseMarkdown
function from @nuxtjs/mdc/runtime
and use it to parse markdown files written with MDC syntax.
Node.js
import { parseMarkdown } from '@nuxtjs/mdc/runtime'
export default eventHandler(async () => {
const mdc = [
'# Hello MDC',
'',
'::alert',
'This is an Alert',
'::'
].join('\n')
const ast = await parseMarkdown(mdc)
return ast
})
Browser
The parseMarkdown
function is a universal helper, and you can also use it in the browser, for example inside a Vue component.
<script setup lang="ts">
import { parseMarkdown } from '@nuxtjs/mdc/runtime'
const ast = await useAsyncData('markdown', () => parseMarkdown('::alert\nMissing markdown input\n::'))
</script>
<template>
<MDCRenderer :body="ast.body" :data="ast.data" />
</template>
Options
The parseMarkdown
helper also accepts options as the second argument to control the parser's behavior. (Checkout MDCParseOptions
interface↗︎).
Name | Default | Description |
---|
remark.plugins | {} | Register / Configure parser's remark plugins. |
rehype.options | {} | Configure remark-rehype options. |
rehype.plugins | {} | Register / Configure parser's rehype plugins. |
highlight | false | Control whether code blocks should highlight or not. You can also provide a custom highlighter. |
toc.depth | 2 | Maximum heading depth to include in the table of contents. |
toc.searchDepth | 2 | Maximum depth of nested tags to search for heading. |
Checkout MDCParseOptions
types↗︎.
Configurations
You can configure the module by providing the mdc
property in your nuxt.config.js
; here are the default options:
import { defineNuxtConfig } from 'nuxt/config'
export default defineNuxtConfig({
modules: ['@nuxtjs/mdc'],
mdc: {
remarkPlugins: {
plugins: {
}
},
rehypePlugins: {
options: {
},
plugins: {
}
},
headings: {
anchorLinks: {
}
},
highlight: false,
components: {
prose: false,
map: {
}
}
}
})
Checkout ModuleOptions
types↗︎.
Contributing
You can contribute to this module online with CodeSandbox:
Or locally:
- Clone this repository
- Install dependencies using
pnpm install
- Start the development server using
pnpm dev
License
MIT License
Copyright (c) NuxtLabs