Skip to content

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
vue
<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
vue
<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
vue
<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&Tab;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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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
vue
<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

NameDescriptionTypeDefault
srcMarkdown stringstring / number''
htmlWhether to parse HTML tags in Markdownbooleantrue
sanitizeWhether to sanitize HTML tags in the output. Accepts a boolean or DOMPurify optionsboolean / SanitizeOptionstrue
preset-nameMarkdown preset name'default' | 'commonmark' | 'zero'default
pluginsmarkdown-it pluginsPluginSimple / Array<PluginSimple | [PluginWithParams, ...any[]]>[]
inlineWhether to enable inline modebooleanfalse
xhtml-outWhether to generate XHTML-compliant outputbooleanfalse
breaksWhether to render \n as <br>booleanfalse
highlightWhether to enable syntax highlighting for code blocksboolean / (str: string, lang: string, attrs: string) => stringtrue
highlight-optionsSyntax highlighting options. Only effective when highlight is true. See highlight.js configurationHLJSOptions-
lang-prefixCSS class prefix for code blocksstringlanguage-
linkifyWhether to convert URL-like text into linksbooleanfalse
typographerWhether to replace certain text with common typographic symbolsbooleanfalse
quotesCustom quotation marks. Only effective when typographer is enabledstring / Array<string>“”‘’
emojiWhether to parse specific text into emojis. Accepts a boolean or markdown-it-emoji optionsboolean / EmojiOptionstrue
anchorHeading anchor configuration. Accepts a boolean, markdown-it-anchor options, or a functionboolean / AnchorOptions / (anchor: Anchor) => AnchorOptionstrue
permalinkWhether to enable permalinks. Only effective when anchor is truebooleantrue
markdown-classCustom Markdown CSS classstringmarkdown-body

Events

NameDescriptionArguments
env-changeTriggered when env in markdown-it changesvalue: {}

Expose

NameDescriptionType
mdInstanceGet the internal markdown-it instanceMarkdownIt
htmlStrGet the parsed HTML stringstring