Wysimark-lite

August 31, 2026 · View on GitHub

A modern and clean rich text editor for React, supporting CommonMark and GFM Markdown spec.

wysimark ( https://github.com/portive/wysimark ) is a modern and clean rich text editor for React, supporting CommonMark and GFM Markdown spec. It is a fork of wysimark with some modifications to make it more lightweight and easier to use.

Thanks to the original author of wysimark, portive m(_ _)m

日本語版 README はこちら

Demo

You can try out the editor using storybook in the following link: https://takeshy.github.io/wysimark-lite

Wysimark-lite editor screenshot

Usage

As React Component

npm install wysimark-lite
import { Editable, useEditor } from "wysimark-lite";
import React from "react";

const Editor: React.FC = () => {
  const [value, setValue] = React.useState("");
  const editor = useEditor({});

  return (
    <div style={{ width: "800px" }}>
      <Editable editor={editor} value={value} onChange={setValue} />
    </div>
  );
};

Editor Options

The useEditor hook accepts the following options:

const editor = useEditor({
  // Enable raw markdown editing mode (default: true = disabled)
  disableRawMode: false,

  // Enable highlight mark feature (default: true = disabled)
  disableHighlight: false,

  // Disable task list / checklist (default: false)
  disableTaskList: true,

  // Disable code block (default: false)
  disableCodeBlock: true,
});
OptionDefaultDescription
disableRawModetrueWhen false, shows a toggle button to switch between WYSIWYG and raw Markdown editing
disableHighlighttrueWhen false, shows a highlight button in the toolbar. Highlight is saved as <mark>text</mark> in Markdown
disableTaskListfalseWhen true, hides the task list (checklist) button from the toolbar
disableCodeBlockfalseWhen true, hides the code block button from the toolbar

Hosts can also provide onFileSelect for the image dialog's Select tab and onLinkSelect for a picker button in the internal-link tab. Both callbacks return a selected URL/path or null when cancelled. resolveImageSrc can asynchronously map a stored relative image URL to a display URL without changing the Markdown that is serialized.

With Image Upload

You can enable image file upload by providing the onImageChange callback:

import { Editable, useEditor } from "wysimark-lite";
import React from "react";

const Editor: React.FC = () => {
  const [value, setValue] = React.useState("");
  const editor = useEditor({});

  const handleImageUpload = async (file: File): Promise<string> => {
    // Upload file to your server and return the URL
    const formData = new FormData();
    formData.append("image", file);
    const response = await fetch("/api/upload", { method: "POST", body: formData });
    const { url } = await response.json();
    return url;
  };

  return (
    <div style={{ width: "800px" }}>
      <Editable
        editor={editor}
        value={value}
        onChange={setValue}
        onImageChange={handleImageUpload}
      />
    </div>
  );
};

When onImageChange is provided:

  • The image dialog shows a radio button to switch between URL input and file upload
  • Drag and drop image files directly into the editor to insert them at the cursor position

Direct Initialization

You can also initialize the editor directly on an HTML element:

you use rails importmap, add the following line to your importmap.rb

※ @latest is the latest version of wysimark-lite. If you want to specify a version, replace @latest with the version you want to use.

pin 'wysimark-lite', to: 'https://esm.sh/wysimark-lite@latest?deps=react@19.2.0,react-dom@19.2.0'
<div id="editor"></div>
<script type="module">
  import { createWysimark } from "wysimark-lite";

  const editor = createWysimark(document.getElementById("editor"), {
    initialMarkdown: "# Hello Wysimark\n\nStart typing here...",
    onChange: (markdown) => {
      console.log("Markdown changed:", markdown);
    },
  });
</script>

Features

  • Modern Design: Clean and contemporary interface that integrates seamlessly with React applications
  • Raw Markdown Mode: Switch between WYSIWYG and raw Markdown editing modes (enable with disableRawMode: false)
  • Highlight Support: Highlight text with <mark> tags (enable with disableHighlight: false)
  • Image Upload Support: Upload images via file picker or drag and drop when onImageChange callback is provided
  • Code Block with Custom Language: Click on the language label to enter any language name
  • User-Friendly Interface:
    • Simplified toolbar with toggle buttons (click to activate/deactivate formatting)
    • Markdown shortcuts (e.g., ** for bold, # for heading)
    • Keyboard shortcuts (e.g., Ctrl/Cmd + B for bold)
    • Japanese localized UI (toolbar and menu items in Japanese)
  • Enhanced Link Editing:
    • Edit link text and tooltip directly in the link dialog
    • Both insert and edit dialogs support text and tooltip fields
  • Enhanced List Support:
    • Nested lists support (create hierarchical lists with multiple levels)
    • Mix different list types in the hierarchy
  • Enhanced Table Editing:
    • Press Enter in a table cell to insert a line break (soft break)
    • Press Shift+Enter to move to the next cell
    • Press Tab in the last cell to exit the table and create a new paragraph
  • Smart Block Splitting: When applying heading/paragraph styles to multi-line blocks, only the selected lines are converted
  • Cursor Position Preservation: Cursor position is maintained after element type conversion (e.g., paragraph to heading)

Browser Support

  • Google Chrome
  • Apple Safari
  • Microsoft Edge
  • Firefox

Requirements

  • React >= 17.x
  • React DOM >= 17.x

Development

Lint

Run ESLint for TypeScript/TSX sources with:

npm run lint

License

MIT