Markdown

Read and write Markdown with v-model, commands and the official @tiptap/markdown parser.

The Markdown extension wraps the official @tiptap/markdown package (MarkedJS under the hood) for bidirectional Markdown support.

Markdown as v-model

<script setup lang="ts">
import { ref } from 'vue'
import { EchoEditor, BaseKit, History, Heading, Bold, Italic, Link, BulletList, OrderedList, TaskList, CodeBlock, Markdown } from 'vue-echo-editor'

const markdown = ref('# Hello\n\nThis is **Markdown**.')

const extensions = [BaseKit, History, Heading, Bold, Italic, Link, BulletList, OrderedList, TaskList, CodeBlock, Markdown]
</script>

<template>
  <EchoEditor v-model="markdown" output="markdown" :extensions="extensions" />
</template>

With output="markdown", the initial modelValue is parsed as Markdown and every update emits Markdown.

Commands & API

// Serialise
const md = editor.getMarkdown()

// Replace the document with Markdown
editor.commands.setContent('## New content', { contentType: 'markdown' })

// Insert Markdown at the cursor
editor.commands.insertContent('- item 1\n- item 2', { contentType: 'markdown' })

Supported syntax

Headings, paragraphs, bold, italic, strikethrough, inline code, links, images, blockquotes, bullet / ordered / task lists, horizontal rules, fenced code blocks (with language) and tables. Unknown HTML embedded in Markdown is parsed with the regular HTML rules.

Custom syntax

Every Tiptap node or mark can define parseMarkdown and renderMarkdown. For example, the built-in CodeBlock does:

CodeBlock.extend({
  markdownTokenName: 'code',
  parseMarkdown: token => ({ type: 'codeBlock', attrs: { language: token.lang, code: token.text } }),
  renderMarkdown: node => '```' + node.attrs.language + '\n' + node.attrs.code + '\n```',
})

See the Tiptap docs on custom Markdown tokenizers for advanced cases.