vue-modern-monaco-mdc

Vue 3 composables and components for modern-monaco editor with MDC support
573
Install
npm install vue-modern-monaco-mdc
Latest Version:0.2.1
Vue:3
License:MIT
Last Updated:Oct 17, 2026
Links: npm
Maintainer: manutopik

vue-modern-monaco-mdc

npm version License: MIT

Vue 3 composables and components for modern-monaco editor, with optional MDC (Markdown Components) support.

Features

  • Vue 3 Components — Ready-to-use <MonacoEditor> and <MonacoDiffEditor> components
  • Composables — Flexible useMonaco(), useMonacoDiff(), and useMonacoOptions() composables
  • Themes — Built-in dark and light themes (Vitesse)
  • Syntax Highlighting — Powered by Shiki via modern-monaco
  • MDC Support — Optional Markdown Components support with autocomplete (tree-shakable)
  • Reactive — Full Vue reactivity support with v-model
  • TypeScript — Full TypeScript support

Installation

npm install vue-modern-monaco-mdc
# or
pnpm add vue-modern-monaco-mdc
# or
yarn add vue-modern-monaco-mdc

Monaco itself is loaded from the CDN at runtime. For its TypeScript types (editor instance, events…), also install modern-monaco as a dev dependency:

pnpm add -D modern-monaco

Quick Start

Using Components

<template>
  <MonacoEditor v-model="code" language="typescript" theme="vitesse-dark" style="height: 400px" />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { MonacoEditor } from "vue-modern-monaco-mdc";

const code = ref(`function hello() {
  console.log('Hello, World!')
}`);
</script>

Using Composables

For more control over the editor lifecycle:

<template>
  <div ref="container" style="height: 400px" />
</template>

<script setup lang="ts">
import { ref, shallowRef } from "vue";
import { useMonaco } from "vue-modern-monaco-mdc";

const container = shallowRef<HTMLElement | null>(null);
const content = ref('const hello = "world"');

const { editor, isReady } = useMonaco({
  container,
  content,
  language: "typescript",
  theme: "vitesse-dark",
  onChange: (value) => console.log("Content changed:", value),
});
</script>

Examples

Diff Editor

Compare two versions of code side-by-side:

<template>
  <MonacoDiffEditor
    :original="originalCode"
    v-model:modified="modifiedCode"
    language="typescript"
    theme="vitesse-dark"
    style="height: 400px"
  />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { MonacoDiffEditor } from "vue-modern-monaco-mdc";

const originalCode = ref(`function add(a: number, b: number): number {
  return a + b
}`);

const modifiedCode = ref(`function add(a: number, b: number): number {
  // Add two numbers together
  const result = a + b
  return result
}`);
</script>

Accessing the Editor Instance

<template>
  <div>
    <button @click="formatCode">Format Code</button>
    <MonacoEditor ref="editorRef" v-model="code" language="typescript" style="height: 400px" />
  </div>
</template>

<script setup lang="ts">
import { ref, shallowRef } from "vue";
import { MonacoEditor } from "vue-modern-monaco-mdc";

const code = ref(`function example() {
return "unformatted code"
}`);

const editorRef = shallowRef<InstanceType<typeof MonacoEditor> | null>(null);

async function formatCode() {
  const editor = editorRef.value?.editor;
  await editor?.getAction("editor.action.formatDocument")?.run();
}
</script>

MDC (Markdown Components) Support

MDC support is optional and tree-shakable. Import from the /mdc subpath to avoid bundling it when not needed.

<template>
  <MonacoEditor
    v-model="code"
    language="mdc"
    theme="vitesse-dark"
    :on-setup="setupMDC"
    style="height: 400px"
  />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { MonacoEditor } from "vue-modern-monaco-mdc";
import { registerMdcLanguage, setupSuggestion } from "vue-modern-monaco-mdc/mdc";
import type { Monaco } from "vue-modern-monaco-mdc";
import type { ComponentMeta, TreeItem } from "vue-modern-monaco-mdc/mdc";

const code = ref(`# My Document\n\n::my-component{prop="value"}\nContent here\n::`);

const componentsMeta: ComponentMeta[] = [
  {
    name: "my-component",
    path: "/components/MyComponent.vue",
    meta: {
      props: [{ name: "prop", type: "string", required: false }],
      slots: [{ name: "default", description: "Default slot content" }],
    },
  },
];

const mediaTree: TreeItem[] = [{ name: "image.png", fsPath: "/images/image.png", type: "file" }];

function setupMDC(monaco: Monaco) {
  registerMdcLanguage(monaco);
  setupSuggestion(monaco, componentsMeta, mediaTree, (key, defaultVal) => defaultVal || key);
}
</script>

Markdown Toolbar

The /mdc subpath exports formatting utilities for building toolbar buttons:

<template>
  <div class="toolbar">
    <button @click="toggleBold(editor)">Bold</button>
    <button @click="toggleItalic(editor)">Italic</button>
    <button @click="onHeading(editor)">Heading</button>
    <button @click="onUnorderedList(editor)">List</button>
    <button @click="onLink(editor)">Link</button>
  </div>
</template>

<script setup lang="ts">
import type { MonacoEditorInstance } from "vue-modern-monaco-mdc";
import {
  toggleBold,
  toggleItalic,
  onHeading,
  onUnorderedList,
  onLink,
} from "vue-modern-monaco-mdc/mdc";

const props = defineProps<{ editor: MonacoEditorInstance }>();
</script>

API Reference

Components

<MonacoEditor>
Prop Type Default Description
modelValue string — Editor content (v-model)
language string 'plaintext' Language mode
theme string 'vitesse-dark' Theme name
options MonacoEditorOptions — Additional editor options
onSetup (monaco) => void — Callback when Monaco instance is ready

Events: update:modelValue, ready

Slots: loading — custom loading state

Exposed: editor, monaco, isReady

<MonacoDiffEditor>
Prop Type Default Description
original string — Original content (left side)
modified string — Modified content (v-model:modified)
language string 'plaintext' Language mode
theme string 'vitesse-dark' Theme name
options MonacoEditorOptions — Additional editor options

Events: update:modified, ready

Slots: loading

Composables

useMonaco(options)
const { editor, monaco, isReady, getValue, setValue, focus } = useMonaco({
  container: Ref<HTMLElement | null>,
  content: Ref<string>,
  language?: MaybeRef<string>,
  theme?: MaybeRef<string>,
  options?: MonacoEditorOptions,
  onChange?: (value: string) => void,
  onSetup?: (monaco: Monaco) => void,
})
useMonacoDiff(options)
const { editor, monaco, isReady, getModifiedValue, setModifiedValue } = useMonacoDiff({
  container: Ref<HTMLElement | null>,
  original: Ref<string>,
  modified: Ref<string>,
  language?: MaybeRef<string>,
  theme?: MaybeRef<string>,
  options?: MonacoEditorOptions,
  onChange?: (value: string) => void,
})
useMonacoOptions(editor, options?)

Reactive bindings for common editor settings. Changes to the returned refs are automatically applied to the editor.

const { lineNumbers, folding, wordWrap, minimap, scrollBeyondLastLine } = useMonacoOptions(
  editor: MonacoEditorInstance | MonacoDiffEditorInstance | null,
  options?: {
    defaults?: Partial<MonacoOptions> | Ref<Partial<MonacoOptions>>
  }
)

// Toggle options directly
lineNumbers.value = true
wordWrap.value = false

Themes

Built-in themes: vitesse-dark (default), vitesse-light

Register a custom theme:

import { getMonaco, registerCustomTheme } from "vue-modern-monaco-mdc";

const monaco = await getMonaco();
registerCustomTheme(monaco, "my-theme", {
  base: "vs-dark",
  inherit: true,
  rules: [],
  colors: { "editor.background": "#1a1a1a" },
});

Utilities

import { loadMonaco, getMonaco } from "vue-modern-monaco-mdc";

// Load Monaco with specific languages
const monaco = await loadMonaco({ theme: "vitesse-dark", langs: ["typescript", "javascript"] });

// Get the already-loaded Monaco instance
const monaco = await getMonaco();

MDC Functions (vue-modern-monaco-mdc/mdc)

Language Registration
Function Description
registerMdcLanguage(monaco) Register MDC syntax highlighting and code folding
mapLanguageToMdc(lang) Map 'markdown' → 'mdc', pass through others
Autocomplete
Function Description
setupSuggestion(monaco, meta, tree, t) Register MDC component/media completions
getMediasCompletionItems(monaco, range, trigger, tree) Get completion items for media files
Formatting Utilities
Function Description
onUndo(editor) Undo last action
onRedo(editor) Redo last action
onHeading(editor) Toggle heading on current line
toggleBold(editor) Toggle bold on selection
toggleItalic(editor) Toggle italic on selection
toggleStrikethrough(editor) Toggle strikethrough on selection
toggleCode(editor) Toggle inline code on selection
onLink(editor) Insert link (uses clipboard URL if available)
onImage(editor) Insert image (uses clipboard URL if image)
onBlockquote(editor) Toggle blockquote on selected lines
onCodeBlock(editor) Insert code block
onUnorderedList(editor) Toggle bullet list on selected lines
onOrderedList(editor) Toggle numbered list on selected lines
onTable(editor) Insert table template
onPrettify(editor) Clean up markdown formatting

TypeScript

import type {
  Monaco,
  MonacoEditor as MonacoEditorInstance,
  MonacoDiffEditor as MonacoDiffEditorInstance,
  MonacoEditorOptions,
  UseMonacoOptions,
  UseMonacoReturn,
  UseMonacoOptionsOptions,
} from "vue-modern-monaco-mdc";

import type { ComponentMeta, TreeItem } from "vue-modern-monaco-mdc/mdc";

Browser Support

Modern browsers with ES module support. Monaco Editor uses Web Workers — ensure your build tool handles them correctly.

Development

The project uses Vite+ (vp) and pnpm:

vp install     # dependencies
vp check       # format, lint and type check
vp test        # tests
vp pack        # build to dist/
pnpm playground

Release

pnpm release bumps the version, then commits, tags and pushes it. The v* tag runs the release workflow: CI, then the npm publish (trusted publishing, next dist-tag for a prerelease) and the GitHub release with its notes from the conventional commits.

License

MIT

Related Packages

vite-plugin-monaco-editor

A vite plugin for the Monaco Editor

8,962,220 234
@akrc/vite-plugin-monaco-editor

A vite plugin for the Monaco Editor

28,475 1
vite-plugin-monaco-editor-new

A vite plugin for the Monaco Editor

2,389 234
@stonecrop/code-editor

Monaco-based code editor component for Stonecrop

22,693 13
monaco-vue3-editor

monaco vue3 editor,集成了 monaco-promql,简单易用的代码编辑器。

1,568 8

Version History

Version Released Vue License
0.2.1 ^3.3.0 MIT
0.2.0 ^3.3.0 MIT
0.1.0 ^3.3.0 MIT