Shubham Verma Frontend engineer. Passionate about web performance, scalability, and how things work internally. Open source contributor | Anime lover | Stack Overflow contributor.

Comparing Milkdown with other WYSIWYG editors

8 min read 2347 105

Comparing Milkdown with other WYSIWYG editors

There are numerous WYSIWYG editors available, which makes it challenging to choose one. In this post, we’ll evaluate Milkdown, a new WYSIWYG editor against some of its top competitors. Here’s what we’ll cover:

What is Milkdown?

Milkdown is an open source, WYSIWYG Markdown editor. Its aim is to provide an editor component that is powerful, extensible, and can be used anywhere. It is:

  • Open source: You can read the code on GitHub and extend it according to your requirements
  • Lightweight: Minified, the library is around 125kb; minified and gzipped, it’s about 40kb [source]. These may change in the future, as the library is still in early development
  • Extensibility: It follows a plugin-based principle, so whatever features you require can either be added and installed using npm packages, or you can create your own to support your idea
  • Customizable: Milkdown lets you control styling
  • Reliable: Milkdown is based on ProseMirror and Remark, both of which already have large, supportive communities and are well-tested
  • Integration: It supports all popular frontend frameworks, including React, Vue, etc.

Milkdown is internally made up of two parts, according to the official site:

  1. A tiny core, which provides a plugin loader and all kinds of internal plugins
  2. Lots of plugins that provide syntax, commands, and components

The benefit of a plugin-based system is that you can easily enable and disable custom features. It will also help in making sure that you only ship the code you need to ship.

It also supports some cool features that are available via official and community plugins:

  1. Math: You can write your math docs inside the editor; it is supported via TeX
  2. Table: You can add tables inside the editor
  3. Slash command: You can use the slash command in a similar way to how it is implemented in apps like Notion, Slack, etc.
  4. Collaboration: Supported shared editing

Why Milkdown?

The Milkdown site explains it beautifully:

There are kinds of different markdown editors, such as Typora, tui, and Bear. They work pretty well for writing notes in Markdown on different platforms. So why bother making Milkdown?

Milkdown aims to provide a open source solution for developers to make their editors more powerful, attractive, and used everywhere.

Most editors don’t give you the full power to customize everything. Some are paid. Some are not as feature-rich as others. Milkdown takes a different approach by providing many features out of the box. If you’re not satisfied with the features available, you might be able to create the specific functionality you’re looking for with the help of its plugin-based system.

You can find official plugins on the Milkdown site and community plugins on GitHub.

Note: Since Milkdown is a wrapper for ProseMirror, you can use all of its functionality, too, such as collaboration, linters, etc.

Basic Milkdown example

Below is a basic example of using Milkdown with vanilla TypeScript. This example is inspired by the Milkdown docs:

// These two imports are important to render the editor
import { Editor, defaultValueCtx, rootCtx } from "@milkdown/core";
import { commonmark } from "@milkdown/preset-commonmark";

// Plugins: Use based on your requirement
import { gfm } from "@milkdown/preset-gfm";
import { nord } from "@milkdown/theme-nord";
import { menu } from "@milkdown/plugin-menu";

import '@milkdown/theme-nord/style.css'
// Default value
const markdown = `
# Test demo.
- [x] Hello
- [ ] World
- [x] Testing
- Remirror
const new = 1
async function main() {
  await Editor.make()
    .config((ctx) => {
      // By default it set to `document.body`. In this case we want to load editor on dom with id app
      ctx.set(rootCtx, "#app");
      ctx.set(defaultValueCtx, markdown.trim());

You can play around with our example demo on StackBlitz and the official demo on the Milkdown site.

How Milkdown compares to Quill.js

Quill.js is a popular open-source JavaScript library for building rich text editors on the web .

It is lightweight, easy to use, and provides a powerful set of features alongside a wealth of resources and community support. It is suitable for basic text formatting and editing tasks, uses a modular design approach, and gives developers the flexibility to customize and extend the editor’s functionality. Quill.js is also well-supported across browsers.

Key features

Quill.js lets you customize the editor’s interface. By default, it supports a minimal plug-n-play interface and uses a semantic naming convention, so there’s no need to learn technical jargon to work with the editor, as there would be with something like ProseMirror.

Other features include:

  1. Support for common text formatting like bold, italics, and other industry-standard functions
  2. Ability to add custom plugins to editor functionality by adding or removing modules
  3. A simple-to-use API that allows developers to easily integrate the editor with their existing application workflow
  4. Speed and efficiency, which makes it a good choice for applications that need to handle large amounts of text from users
  5. Lightweight in size (minified: ~209kb, minified + gzipped: 45.2kb, source)
  6. All core features are included out of the box; no need to install extra plugins

Comparison with Milkdown

Overall, Quill.js has fewer features than Milkdown:

  1. No support for internationalization
  2. No support for drag-and-drop (there are community plugins for this, but you have to play around with them according to your requirements)
  3. No support for integrating frontend frameworks
  4. No support for advanced features, like graph or math, as part of its official plugin

This example is inspired by the Quill.js documentation:

    <title>Quilljs Example</title>
    <meta charset="UTF-8" />
    <!-- Include stylesheet -->
    <!-- Create the editor container -->
    <div id="editor">
      <p>Hello World!</p>
      <p>Some initial <strong>bold</strong> text</p>
      <p><br /></p>
    <!-- Include the Quill library -->
    <script src=""></script>
    <!-- Initialize Quill editor -->
      var quill = new Quill("#editor", {
        theme: "snow"

You can learn more about Quill.js on their website.

How Milkdown compares to ProseMirror

ProseMirror is also an open source JavaScript library built by the same author who built CodeMirror. It is also somewhat similar to Quill.js, in that it too provides a set of tools and concepts for building a rich text editor. It’s another highly customizable and extensible library with comprehensive documentation and a large community of users who have helped build a wide range of text-editing features.

It’s important to note here that Milkdown is built on top of ProseMirror. This means that whatever ProseMirror offers, you can also use in Milkdown.

Key features

  1. Support for collaborative editing
  2. Modular architecture: Maintenance and development is easy when compared to others
  3. Plugin-based system
  4. Provides a robust API for building custom plugins
  5. Extensible schemas: ProseMirror helps in editing documents with a custom structure, without needing to write your own editor from scratch. It has a better document model and is more flexible

Here is a basic example inspired by the ProseMirror docs:


More great articles from LogRocket:

import { EditorState } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { Schema, DOMParser } from "prosemirror-model";
import { schema } from "prosemirror-schema-basic";
import { addListNodes } from "prosemirror-schema-list";
import { exampleSetup } from "prosemirror-example-setup";
import "prosemirror-menu/style/menu.css";
// Mix the nodes from prosemirror-schema-list into the basic schema to
// create a schema with list support.
const mySchema = new Schema({
  nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"),
  marks: schema.spec.marks
window.view = new EditorView(document.querySelector("#editor"), {
  state: EditorState.create({
    doc: DOMParser.fromSchema(mySchema).parse(
    plugins: exampleSetup({ schema: mySchema })

How Milkdown compares to TinyMCE

TinyMCE is another Milkdown alternative. According to their GitHub page:

Used and trusted by millions of developers, TinyMCE is the world’s most customizable, scalable, and flexible rich text editor.

With more than 350M+ downloads every year, we’re also one of the most trusted enterprise-grade open source HTML editors on the internet. There’s currently more than 100M+ products worldwide, powered by Tiny. As a high powered WYSIWYG editor, TinyMCE is built to scale, designed to innovate, and thrives on delivering results to difficult edge-cases.

Key features

  1. You can use its CDN or self-host completely
  2. Similar to others, it also follows a plugin-based architecture, so you can extend the library according to your requirements
  3. Offers accessibility support
  4. Broken link check support
  5. Enhanced image editing

You can find the full list of features here.

Comparison with Milkdown

  1. TinyMCE is an advanced editor and supports a lot of features out of the box, while Milkdown only supports basic rich text editing features
  2. Accessibility support is available in TinyMCE
  3. TinyMCE offers advanced image support; you can edit the image within a TinyMCE editor, and it supports image responsiveness
  4. Lot of features, which can come handy in future. You do not need to think about creating features from scratch
  5. Better documentation and support than Milkdown

Basic example

The basic setup example is borrowed from TinyMCE’s documentation:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
        selector: "#mytextarea"
    <h1>TinyMCE Quick Start Guide</h1>
    <form method="post">
      <textarea id="mytextarea">Hello, World!</textarea>

How Milkdown compares to the Toast UI editor

Toast UI is another popular open source editor. It provides two editing modes: Markdown and WYSIWYG, which can be switched at any point of time. It follows CommonMark and GFM (GitHub-flavored Markdown) specifications, both of which are widely used in the software industry.

Key features

  1. Viewer: Supports a mode to display only Markdown data without an editing area
  2. Internationalization: Supports English, Dutch, Korean, Japanese, Chinese, Spanish, German, Russian, French, Ukrainian, Turkish, Finnish, Czech, Arabic, Polish, Galician, Swedish, Italian, Norwegian, and Croatian, but you can extend it to support any language
  3. Widget: This feature allows you to configure the rules that replace string matching to a specific RegExp with the widget node
  4. Custom block: Nodes not supported by Markdown can be defined through a custom block. You can display the node you want to by writing the parsing logic within the custom block

With the help of official plugins you can also extend editor functionality as well. Some extensions include:

  • Charts
  • Code syntax highlighting
  • Color-syntax
  • Table-merged-cell
  • UML

Comparison with Milkdown

Both libraries are a similar kind of editor, but Toast UI has been around in the market for a long time. It is well-tested and supported by the community.

  1. Its support for charts, with the help of a plugin, is a differentiator from Milkdown, which so far does not offer chart support
  2. It has advanced table support, also with the help of plugin
  3. The viewer mode allows you to only render Markdown content
  4. It supports a color picker! If you want to change the color of the text you’re editing, you can use its plugin to do it
  5. Despite support for some other important features, Milkdown has better graph support than Toast UI
  6. Both support internationalization, dark theme, code syntax highlight

Reason to use Toast UI

If your use case included a need for displaying an iframe, highlight text color, or some other special type of content during editing, Toast UI Editor can be very helpful because of its less complex API and ability to add custom functionality. The learning curve for creating widgets and plugins is less complex compare to other editors.

Basic example

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <div id="editor"></div>
    <script src="src/index.ts" type="module"></script>
import Editor from "@toast-ui/editor";
import "@toast-ui/editor/dist/toastui-editor.css";
const editor = new Editor({
  el: document.querySelector("#editor")


In this post, we’ve discussed Milkdown, a new-in-market editor with strong features. Its main drawback currently is that its community is not as strong as other editors: if an issue arises, you’ll probably end up spending extra time troubleshooting it. Therefore, use it at your own risk.

In the end, your choice of editor relies on your requirements. While other open source editors are better for basic applications, Toast UI and TinyMCE are ideal choices if you wanted to construct a complicated application with a lot of features. There isn’t a single editor that fits every need.

With the aid of plugins, free editors may perform just as well as those that cost money, especially when the communities are as robust as ProseMirror’s and Quill.js’s

Are you adding new JS libraries to improve performance or build new features? What if they’re doing the opposite?

There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.

LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.

LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.

Build confidently — .

Shubham Verma Frontend engineer. Passionate about web performance, scalability, and how things work internally. Open source contributor | Anime lover | Stack Overflow contributor.

One Reply to “Comparing Milkdown with other WYSIWYG editors”

  1. Suprising that this article pretends to be from 2023, when QuillJS that it mentions is dead for about 4 years now, no update since 2019 and thousand+ bugs reported in repo. Please do not promote dead and bugged software

Leave a Reply