Compile Markdown to Vue component.
- 📚 Use Markdown as Vue components.
- 💚 Use Vue components in Markdown.
- 🔌 Supports Vite, Webpack, Vue CLI and more, powered by unplugin.
- ⚡️ The same transformation as VitePress.
npm i unplugin-vue-markdown
Vite
// vite.config.ts import Vue from '@vitejs/plugin-vue' import Markdown from 'unplugin-vue-markdown/vite' export default defineConfig({ plugins: [ Vue({ include: [/\.vue$/, /\.md$/], // <-- allows Vue to compile Markdown files }), Markdown({ /* options */ }), ], })
Example: examples/vite
Webpack
// webpack.config.js const Markdown = require('unplugin-vue-markdown/webpack') const { VueLoaderPlugin } = require('vue-loader') module.exports = { /* ... */ module: { rules: [ // ... other rules { test: /\.(vue|md)$/, loader: 'vue-loader' } ] }, plugins: [ new VueLoaderPlugin(), Markdown({ /* options */ }) ] }
Vue CLI
// vue.config.js const Markdown = require('unplugin-vue-markdown/webpack') module.exports = { parallel: false, // Disable thread-loader which will cause errors, we are still investigating the root cause chainWebpack: (config) => { config.module .rule('vue') .test(/\.(vue|md)$/) // <-- allows Vue to compile Markdown files config .plugin('markdown') .use(Markdown({ markdownItUses: [ prism, ], })) }, }
Example: examples/vue-cli
<template> <HelloWorld /> </template> <script> import HelloWorld from './README.md' export default { components: { HelloWorld, }, } </script>
You can even use Vue components inside your markdown, for example
<Counter :init='5'/>
Note you can either register the components globally, or use the <script setup>
tag to register them locally.
import { createApp } from 'vue' import App from './App.vue' import Counter from './Counter.vue' const app = createApp(App) // register global app.component('Counter', Counter) // <-- app.mount()
<script setup> import { Counter } from './Counter.vue' </script> <Counter :init='5'/>
Or you can use unplugin-vue-components
for auto components registration.
Frontmatter will be parsed and inject into Vue's instance data frontmatter
field.
For example:
--- name: My Cool App --- # Hello World This is {{frontmatter.name}}
Will be rendered as
<h1>Hello World</h1> <p>This is My Cool App</p>
It will also be passed to the wrapper component's props if you have set wrapperComponent
option.
To manage document head and meta, you would need to install @unhead/vue
and do some setup.
npm i @unhead/vue
// vite.config.js import Vue from '@vitejs/plugin-vue' import Markdown from 'unplugin-vue-markdown/vite' export default { plugins: [ Vue({ include: [/\.vue$/, /\.md$/], }), Markdown({ headEnabled: true // <-- }) ] }
// src/main.js import { createHead } from '@unhead/vue/client' // <-- import { createApp } from 'vue' const app = createApp(App) const head = createHead() // <-- app.use(head) // <--
Then you can use frontmatter to control the head. For example:
--- title: My Cool App meta: - name: description content: Hello World ---
For more options available, please refer to @unhead/vue
's docs.
unplugin-vue-markdown
uses markdown-it
under the hood, see markdown-it
's docs for more details
// vite.config.js import MarkdownItAnchor from 'markdown-it-anchor' import MarkdownItPrism from 'markdown-it-prism' import Markdown from 'unplugin-vue-markdown/vite' export default { plugins: [ Markdown({ // default options passed to markdown-it // see: https://markdown-it.github.io/markdown-it/ markdownItOptions: { html: true, linkify: true, typographer: true, }, // A function providing the Markdown It instance gets the ability to apply custom settings/plugins markdownItSetup(md) { // for example md.use(MarkdownItAnchor) md.use(MarkdownItPrism) }, // Class names for the wrapper div wrapperClasses: 'markdown-body' }) ], }
See the tsdoc for more advanced options
See the /examples.
Or the pre-configured Markdown template Vitesse.
Work with vite-plugin-pages
import Vue from '@vitejs/plugin-vue' import Markdown from 'unplugin-vue-markdown/vite' import Pages from 'vite-plugin-pages' export default { plugins: [ Vue({ include: [/\.vue$/, /\.md$/], }), Pages({ extensions: ['vue', 'md'], }), Markdown() ], }
Put your markdown under ./src/pages/xx.md
, then you can access the page via route /xx
.
Work with unplugin-vue-components
unplugin-vue-components
allows you to do on-demand components auto-importing without worrying about registration.
import Vue from '@vitejs/plugin-vue' import Components from 'unplugin-vue-components/vite' import Markdown from 'unplugin-vue-markdown/vite' export default { plugins: [ Vue({ include: [/\.vue$/, /\.md$/], }), Markdown(), // should be placed after `Markdown()` Components({ // allow auto load markdown components under `./src/components/` extensions: ['vue', 'md'], // allow auto import and register components used in markdown include: [/\.vue$/, /\.vue\?vue/, /\.md$/], }) ], }
Components under ./src/components
can be directly used in markdown components, and markdown components can also be put under ./src/components
to be auto imported.
declare module '*.vue' { import type { ComponentOptions } from 'vue' const Component: ComponentOptions export default Component } declare module '*.md' { import type { ComponentOptions } from 'vue' const Component: ComponentOptions export default Component }
MIT License © 2020-PRESENT Anthony Fu