Render
Parses Markdown text in real-time and renders it into safe, polished HTML.
Basic Usage
Use src to pass a Markdown string and render the corresponding HTML output.
View Source
<template>
<vmd-render :src="md" />
</template>
<script setup>
const md = `
# h1 Heading 8-)
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
## Horizontal Rules
___
---
***
## Emphasis
**This is bold text**
__This is bold text__
*This is italic text*
_This is italic text_
~~Strikethrough~~
## Blockquotes
> Blockquotes can also be nested...
>> ...by using additional greater-than signs right next to each other...
> > > ...or with spaces between arrows.
## Lists
Unordered
+ Create a list by starting a line with \`+\`, \`-\`, or \`*\`
+ Sub-lists are made by indenting 2 spaces:
- Marker character change forces new list start:
* Ac tristique libero volutpat at
+ Facilisis in pretium nisl aliquet
- Nulla volutpat aliquam velit
+ Very easy!
Ordered
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
3. Integer molestie lorem at massa
1. You can use sequential numbers...
1. ...or keep all the numbers as \`1.\`
Start numbering with offset:
57. foo
1. bar
## Tables
| Option | Description |
| ------ | ----------- |
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
Right aligned columns
| Option | Description |
| ------:| -----------:|
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
`
</script>Parse HTML Tags
Use html to control whether HTML tags inside Markdown are parsed.
View Source
<template>
<div>
<p>
<label>
<input v-model="html" name="checkbox" type="checkbox" />
Enable html
</label>
</p>
<vmd-render :src="md" :html="html" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const html = ref(true)
const md = `
# Lorem ipsum
<p style="background: rgba(9, 105, 218, 0.14); padding: 10px">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi maximus elit fermentum pellentesque vehicula. Suspendisse potenti. Donec iaculis consectetur erat nec placerat. Suspendisse facilisis justo sit amet hendrerit sollicitudin. Suspendisse commodo malesuada massa, ac elementum risus. Ut eu facilisis neque. Fusce tincidunt, ligula vitae eleifend venenatis, purus purus ultrices purus, nec maximus tellus lectus nec leo. Sed auctor magna sed quam dapibus dapibus. Nullam ornare ultricies sem, a iaculis sapien volutpat euismod. Sed ac dictum nulla. Duis euismod tellus vitae diam hendrerit, sit amet vestibulum mauris rhoncus.
</p>
`
</script>Sanitize HTML Tags
Use sanitize to sanitize HTML tags in the output to prevent XSS and other web attacks. Enabling sanitize may affect how some HTML tags are rendered. If the result is not what you expect and your security requirements are low, you can try disabling sanitize, but this is extremely risky. If you have strict security requirements, consider disabling html instead.
View Source
<template>
<div>
<h4>Markdown:</h4>
<pre style="background: #fff; overflow: auto"><code>{{ md }}</code></pre>
<h4>Output:</h4>
<vmd-render :src="md" />
</div>
</template>
<script setup>
const md = `
<p style="background: rgba(9, 105, 218, 0.14); padding: 10px">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<iframe//src=jAva	script:alert(3)>def
</p>
`
</script>Preset Name
Use preset-name to quickly switch Markdown syntax rules. Three commonly used presets are built-in: default (similar to GFM), commonmark (see CommonMark), and zero (disables all syntax rules).
TIP
Compared to markdown-it's default preset, the html option is enabled by default here.
View Source
<template>
<div>
<p>
<label>
Select a preset:
<select v-model="presetName" name="select">
<option v-for="item in options" :key="item" :value="item">{{ item }}</option>
</select>
</label>
</p>
<template v-for="item in options" :key="item">
<vmd-render v-if="item === presetName" :src="md" :preset-name="item" />
</template>
</div>
</template>
<script setup>
import { ref } from 'vue'
const options = ['default', 'commonmark', 'zero']
const presetName = ref('default')
const md = `
| Preset Name | Description |
| ----------------------------------------------------------------------------------------------- | ----------------------------------------- |
| [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.mjs) | Similar to GFM |
| [commonmark](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.mjs) | See [CommonMark](https://commonmark.org/) |
| [zero](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.mjs) | Disables all syntax rules |
`
</script>markdown-it Plugins
Use plugins to pass markdown-it plugins. Two forms are supported: pass a single plugin directly, or pass an array of plugins where each item can be a plugin or a plugin-with-params tuple (e.g., [plugin, [plugin, param1, param2, ...], ...]).
View Source
<template>
<vmd-render :src="md" :plugins="plugins" />
</template>
<script setup>
// npm i markdown-it-container
import container from 'markdown-it-container'
const md = `
# Lorem ipsum
::: example
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi maximus elit fermentum pellentesque vehicula. Suspendisse potenti. Donec iaculis consectetur erat nec placerat. Suspendisse facilisis justo sit amet hendrerit sollicitudin. Suspendisse commodo malesuada massa, ac elementum risus. Ut eu facilisis neque. Fusce tincidunt, ligula vitae eleifend venenatis, purus purus ultrices purus, nec maximus tellus lectus nec leo. Sed auctor magna sed quam dapibus dapibus. Nullam ornare ultricies sem, a iaculis sapien volutpat euismod. Sed ac dictum nulla. Duis euismod tellus vitae diam hendrerit, sit amet vestibulum mauris rhoncus.
:::
`
const plugins = [
[
container,
'example',
{
render: (tokens, idx) => {
return tokens[idx].nesting === 1 ? '<details><summary>Expand</summary>\n' : '</details>\n'
}
}
]
]
</script>Inline
Use inline to skip block rules parsing and render output without a <p> wrapper.
View Source
<template>
<div>
<p>
<label>
<input v-model="inline" name="checkbox" type="checkbox" />
Enable inline
</label>
</p>
<vmd-render :src="md" :inline="inline" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const inline = ref(true)
const md = `
# Lorem ipsum
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi maximus elit fermentum pellentesque vehicula. Suspendisse potenti. Donec iaculis consectetur erat nec placerat. Suspendisse facilisis justo sit amet hendrerit sollicitudin. Suspendisse commodo malesuada massa, ac elementum risus. Ut eu facilisis neque. Fusce tincidunt, ligula vitae eleifend venenatis, purus purus ultrices purus, nec maximus tellus lectus nec leo. Sed auctor magna sed quam dapibus dapibus. Nullam ornare ultricies sem, a iaculis sapien volutpat euismod. Sed ac dictum nulla. Duis euismod tellus vitae diam hendrerit, sit amet vestibulum mauris rhoncus.
`
</script>XHTML
Use xhtml-out to generate XHTML-compliant output.
View Source
<template>
<div>
<p>
<label>
<input v-model="xhtmlOut" name="checkbox" type="checkbox" />
Enable xhtml-out
</label>
</p>
<h4>Parsed:</h4>
<div style="background: #fff; padding: 32px">
{{ renderRef?.htmlStr }}
</div>
<h4>Rendered:</h4>
<vmd-render ref="renderRef" :src="md" :xhtml-out="xhtmlOut" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const renderRef = ref(null)
const xhtmlOut = ref(true)
const md = `
---
`
</script>Breaks
Use breaks to render \n in Markdown as <br>.
View Source
<template>
<div>
<p>
<label>
<input v-model="breaks" name="checkbox" type="checkbox" />
Enable breaks
</label>
</p>
<h4>Parsed:</h4>
<div style="background: #fff; padding: 32px">
{{ renderRef?.htmlStr }}
</div>
<h4>Rendered:</h4>
<vmd-render ref="renderRef" :src="md" :breaks="breaks" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const renderRef = ref(null)
const breaks = ref(true)
const md = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nMorbi maximus elit fermentum pellentesque vehicula.
`
</script>Syntax Highlighting
Use highlight to syntax-highlight fenced code blocks based on their language. When a boolean is provided, highlight.js is used as the syntax highlighter and can be configured via highlight-options (see highlight.js configuration). If the default highlighting is not enough, highlight also supports providing a function to customize highlighting.
View Source
<template>
<div>
<p>
<label>
<input v-model="highlight" name="checkbox" type="checkbox" />
Enable highlight
</label>
</p>
<h4>Boolean:</h4>
<vmd-render :src="md" :highlight="highlight" />
<h4>Function:</h4>
<vmd-render :src="md" :highlight="highlight && customHighlight" />
</div>
</template>
<script setup>
// npm i highlight.js
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css'
import { ref } from 'vue'
const highlight = ref(true)
const customHighlight = (str, language) => {
return hljs.highlight(str, { language }).value
}
const md = `
\`\`\` js
var foo = function (bar) {
return bar++;
};
console.log(foo(5));
\`\`\`
`
</script>Custom Highlight Class
Use lang-prefix to change the CSS class prefix used for code blocks, so you can customize highlight styles.
View Source
<template>
<div>
<p>
<label>
Select class prefix:
<select v-model="langPrefix" name="select">
<option value="custom-">Custom prefix: custom-</option>
<option value="language-">Default prefix: language-</option>
</select>
</label>
</p>
<vmd-render :src="md" :lang-prefix="langPrefix" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const langPrefix = ref('custom-')
const md = `
\`\`\` js
var foo = function (bar) {
return bar++;
};
console.log(foo(5));
\`\`\`
`
</script>
<style>
.custom-js {
color: #666666 !important;
}
.custom-js .hljs-keyword {
color: #ab5959 !important;
}
.custom-js .hljs-title {
color: #59873a !important;
}
.custom-js .hljs-variable,
.custom-js .hljs-params {
color: #b07d48 !important;
}
.custom-js .hljs-string {
color: #b56959 !important;
}
</style>Linkify
Use linkify to automatically convert URL-like text in Markdown into links.
View Source
<template>
<div>
<p>
<label>
<input v-model="linkify" name="checkbox" type="checkbox" />
Enable linkify
</label>
</p>
<vmd-render :src="md" :linkify="linkify" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const linkify = ref(true)
const md = `
Link: [https://www.example.com](https://www.example.com)
URL-like text: https://www.example.com
`
</script>Typographer
Use typographer to replace certain text in Markdown with typographic symbols. When typographer is enabled, you can also customize quotation marks via quotes, which is useful in multilingual environments.
View Source
<template>
<div>
<p>
<label>
<input v-model="typographer" name="checkbox" type="checkbox" />
Enable typographer
</label>
</p>
<p>
<label>
Enter quotes:
<input
v-for="(item, index) in quotes"
:key="item"
v-model="quotes[index]"
name="text"
style="width: 2em; margin: 4px"
/>
</label>
</p>
<vmd-render :src="md" :typographer="typographer" :quotes="[...quotes]" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const typographer = ref(true)
const quotes = ref(['«', '»', '‹', '›'])
const md = `
Copyright symbol: (c)
Trademark: (tm)
Registered trademark: (r)
"This is a double-quote demo"
'This is a single-quote demo'
`
</script>Emoji
Use emoji to parse specific text in Markdown into emoji. In addition to boolean values, you can also pass an options object (see markdown-it-emoji options).
View Source
<template>
<vmd-render :src="md" :emoji="emoji" />
</template>
<script setup>
const emoji = {
shortcuts: {
smiley: ':-)',
frowning: ':-(',
sunglasses: '8-)',
wink: ';)'
}
}
const md = `
Classic emojis: :wink: :cry: :laughing: :yum:
Custom shortcuts: :-) :-( 8-) ;)
`
</script>Heading Anchors
Use anchor to add unique IDs to all headings. This helps navigation components (such as Toc) perform anchor scrolling. When anchor is enabled, permalinks are enabled by default for all headings; you can toggle them with permalink. anchor also supports passing an options object or a function to customize heading rendering (see markdown-it-anchor options).
View Source
<template>
<div>
<h4>Default heading rendering:</h4>
<p>
<label>
<input v-model="permalink" name="checkbox" type="checkbox" />
Enable permalink (hover the heading to show the permalink symbol)
</label>
</p>
<vmd-render :src="md" :permalink="permalink" />
<h4>Custom heading rendering:</h4>
<vmd-render :src="md" :anchor="anchorOptions" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const permalink = ref(true)
const anchorOptions = (anchor) => ({
permalink: anchor.permalink.headerLink()
})
const md = `
# Lorem ipsum
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi maximus elit fermentum pellentesque vehicula. Suspendisse potenti. Donec iaculis consectetur erat nec placerat. Suspendisse facilisis justo sit amet hendrerit sollicitudin. Suspendisse commodo malesuada massa, ac elementum risus. Ut eu facilisis neque. Fusce tincidunt, ligula vitae eleifend venenatis, purus purus ultrices purus, nec maximus tellus lectus nec leo. Sed auctor magna sed quam dapibus dapibus. Nullam ornare ultricies sem, a iaculis sapien volutpat euismod. Sed ac dictum nulla. Duis euismod tellus vitae diam hendrerit, sit amet vestibulum mauris rhoncus.
`
</script>Custom Styles
By default, github-markdown-css is used to style the rendered output. You can also provide your own styles via markdown-class.
View Source
<template>
<div>
<p>
<label>
Select a class name:
<select v-model="markdownClass" name="select">
<option value="custom-theme">Custom: custom-theme</option>
<option value="markdown-body">Default: markdown-body</option>
<option value="">No theme</option>
</select>
</label>
</p>
<vmd-render :src="md" :markdown-class="markdownClass" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const markdownClass = ref('custom-theme')
const md = `
# Lorem ipsum
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi maximus elit fermentum pellentesque vehicula. Suspendisse potenti. Donec iaculis consectetur erat nec placerat. Suspendisse facilisis justo sit amet hendrerit sollicitudin. Suspendisse commodo malesuada massa, ac elementum risus. Ut eu facilisis neque. Fusce tincidunt, ligula vitae eleifend venenatis, purus purus ultrices purus, nec maximus tellus lectus nec leo. Sed auctor magna sed quam dapibus dapibus. Nullam ornare ultricies sem, a iaculis sapien volutpat euismod. Sed ac dictum nulla. Duis euismod tellus vitae diam hendrerit, sit amet vestibulum mauris rhoncus.
`
</script>
<style>
.custom-theme {
background: #fffffd;
}
.custom-theme * {
margin: 0;
}
.custom-theme h1 {
font-size: 2.4em;
padding-bottom: 0.3em;
border-bottom: 3px double #eee;
margin-bottom: 0.6em;
line-height: 1.35;
font-weight: bolder;
color: #456688;
}
.custom-theme p {
margin-bottom: 1.2em;
color: #383838;
}
.custom-theme a {
color: #456688;
text-decoration: none;
}
</style>API
Props
| Name | Description | Type | Default |
|---|---|---|---|
| src | Markdown string | string / number | '' |
| html | Whether to parse HTML tags in Markdown | boolean | true |
| sanitize | Whether to sanitize HTML tags in the output. Accepts a boolean or DOMPurify options | boolean / SanitizeOptions | true |
| preset-name | Markdown preset name | 'default' | 'commonmark' | 'zero' | default |
| plugins | markdown-it plugins | PluginSimple / Array<PluginSimple | [PluginWithParams, ...any[]]> | [] |
| inline | Whether to enable inline mode | boolean | false |
| xhtml-out | Whether to generate XHTML-compliant output | boolean | false |
| breaks | Whether to render \n as <br> | boolean | false |
| highlight | Whether to enable syntax highlighting for code blocks | boolean / (str: string, lang: string, attrs: string) => string | true |
| highlight-options | Syntax highlighting options. Only effective when highlight is true. See highlight.js configuration | HLJSOptions | - |
| lang-prefix | CSS class prefix for code blocks | string | language- |
| linkify | Whether to convert URL-like text into links | boolean | false |
| typographer | Whether to replace certain text with common typographic symbols | boolean | false |
| quotes | Custom quotation marks. Only effective when typographer is enabled | string / Array<string> | “”‘’ |
| emoji | Whether to parse specific text into emojis. Accepts a boolean or markdown-it-emoji options | boolean / EmojiOptions | true |
| anchor | Heading anchor configuration. Accepts a boolean, markdown-it-anchor options, or a function | boolean / AnchorOptions / (anchor: Anchor) => AnchorOptions | true |
| permalink | Whether to enable permalinks. Only effective when anchor is true | boolean | true |
| markdown-class | Custom Markdown CSS class | string | markdown-body |
Events
| Name | Description | Arguments |
|---|---|---|
| env-change | Triggered when env in markdown-it changes | value: {} |
Expose
| Name | Description | Type |
|---|---|---|
| mdInstance | Get the internal markdown-it instance | MarkdownIt |
| htmlStr | Get the parsed HTML string | string |