Skip to content

uiwjs/react-markdown-editor

Repository files navigation

React Markdown Editor logo

Build & Deploy NPM Download npm version

A markdown editor with preview, implemented with React.js and TypeScript.

React Markdown Editor

Migrate from @uiw/react-markdown-editor 4.x to 5.x.

Install

npm i @uiw/react-markdown-editor

Document

Official document demo preview (🇨🇳中国镜像网站)

Basic Usage

import React from 'react'; import MarkdownEditor from '@uiw/react-markdown-editor'; const mdStr = `# This is a H1 \n## This is a H2 \n###### This is a H6`; const Dome = () => { return ( <MarkdownEditor value={mdStr} onChange={(value, viewUpdate) => { }} /> ) }; export default Dome;

Controlled Usage

Open in CodeSandbox

import React, { useState } from 'react'; import MarkdownEditor from '@uiw/react-markdown-editor'; const mdStr = `# This is a H1 \n## This is a H2 \n###### This is a H6`; export default function App() { const [markdown, setMarkdown] = useState(mdStr); return ( <MarkdownEditor value={markdown} height="200px" onChange={(value, viewUpdate) => setMarkdown(value)} /> ); }

Only Markdown Preview

Open in CodeSandbox

This markdown preview sub-component is a direct export @uiw/react-markdown-preview component, API documentation, please check @uiw/react-markdown-preview.

import React from 'react'; import MarkdownEditor from '@uiw/react-markdown-editor'; const mdStr = `# This is a H1 \n## This is a H2 \n###### This is a H6`; function App() { return ( <MarkdownEditor.Markdown source={mdStr} height="200px" /> ); } export default App;

Custom Toolbars

Open in CodeSandbox

import React from "react"; import MarkdownEditor from '@uiw/react-markdown-editor'; const title2 = { name: 'title2', keyCommand: 'title2', button: { 'aria-label': 'Add title text' }, icon: ( <svg width="12" height="12" viewBox="0 0 512 512"> <path fill="currentColor" d="M496 80V48c0-8.837-7.163-16-16-16H320c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h37.621v128H154.379V96H192c8.837 0 16-7.163 16-16V48c0-8.837-7.163-16-16-16H32c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h37.275v320H32c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h160c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-37.621V288H357.62v128H320c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h160c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-37.275V96H480c8.837 0 16-7.163 16-16z" /> </svg> ), execute: ({ state, view }) => { if (!state || !view) return; const lineInfo = view.state.doc.lineAt(view.state.selection.main.from); let mark = '#'; const matchMark = lineInfo.text.match(/^#+/) if (matchMark && matchMark[0]) { const txt = matchMark[0]; if (txt.length < 6) { mark = txt + '#'; } } if (mark.length > 6) { mark = '#'; } const title = lineInfo.text.replace(/^#+/, '') view.dispatch({ changes: { from: lineInfo.from, to: lineInfo.to, insert: `${mark} ${title}` }, // selection: EditorSelection.range(lineInfo.from + mark.length, lineInfo.to), selection: { anchor: lineInfo.from + mark.length }, }); }, }; const Dome = () => ( <MarkdownEditor value="Hello Markdown!" height="200px" toolbars={[ 'bold', title2 ]} /> ); export default Dome;

Disable preview feature

Open in CodeSandbox

import React from "react"; import MarkdownEditor from '@uiw/react-markdown-editor'; const Dome = () => ( <MarkdownEditor value="Hello Markdown!" height="200px" enablePreview={false} /> ); export default Dome;

Support Nextjs

Use examples in nextjs.

Open in CodeSandbox #52 #224

npm install next-remove-imports npm install @uiw/react-markdown-editor
// next.config.js const removeImports = require('next-remove-imports')(); module.exports = removeImports({});
import dynamic from 'next/dynamic'; import '@uiw/react-markdown-editor/markdown-editor.css'; import '@uiw/react-markdown-preview/markdown.css'; const MarkdownEditor = dynamic( () => import("@uiw/react-markdown-editor").then((mod) => mod.default), { ssr: false } ); function HomePage() { return ( <div> <MarkdownEditor value="Hello Markdown!" /> </div> ); } export default HomePage;

Support dark-mode/night-mode

By default, the dark-mode is automatically switched according to the system. If you need to switch manually, just set the data-color-mode="dark" parameter for html Element.

<html data-color-mode="dark">
document.documentElement.setAttribute('data-color-mode', 'dark') document.documentElement.setAttribute('data-color-mode', 'light')

Inherit custom color variables by adding .wmde-markdown-var selector.

const Demo = () => { return ( <div> <div className="wmde-markdown-var"> </div> <MarkdownEditor value="Hello Markdown!" /> </div> ) }

Props

  • value (string) - the raw markdown that will be converted to html (required)
  • visible?: boolean - Shows a preview that will be converted to html.
  • toolbars?: ICommand[] | string[] - Tool display settings.
  • toolbarsMode?: ICommand[] | string[] - Tool display settings.
  • onChange?:function(editor: IInstance, data: CodeMirror.EditorChange, value: string) - called when a change is made
  • onBlur?: function(editor: IInstance, event: Event) - event occurs when an object loses focus
  • onPreviewMode?: (isHide: boolean) => void - Edit mode and preview mode switching event
  • previewProps - react-markdown options
import { ReactCodeMirrorProps } from '@uiw/react-codemirror'; export interface IMarkdownEditor extends ReactCodeMirrorProps { className?: string; prefixCls?: string; /** The raw markdown that will be converted to html (**required**) */ value?: string; /** Shows a preview that will be converted to html. */ visible?: boolean; visibleEditor?: boolean; /** Override the default preview component */ renderPreview?: (props: MarkdownPreviewProps, initVisible: boolean) => React.ReactNode; /** Preview expanded width @default `50%` */ previewWidth?: string; /** Whether to enable preview function @default `true` */ enablePreview?: boolean; /** Whether to enable scrolling */ enableScroll?: boolean; /** Tool display settings. */ toolbars?: Commands[]; /** The tool on the right shows the settings. */ toolbarsMode?: Commands[]; /** Tool display filter settings. */ toolbarsFilter?: (tool: Commands, idx: number) => boolean; /** Toolbar on bottom */ toolbarBottom?: boolean; /** Option to hide the tool bar. @deprecated The next major version will be deprecated. Please use `showToolbar`. */ hideToolbar?: boolean; /** Option to hide the tool bar. */ showToolbar?: boolean; /** [@uiw/react-markdown-preview](https://github.com/uiwjs/react-markdown-preview#options-props) options */ previewProps?: MarkdownPreviewProps; /** replace the default `extensions` */ reExtensions?: ReactCodeMirrorProps['extensions']; /** Edit mode and preview mode switching event */ onPreviewMode?: (isHide: boolean) => void; }
import React from 'react'; import { ReactCodeMirrorRef } from '@uiw/react-codemirror'; import { MarkdownPreviewProps, MarkdownPreviewRef } from '@uiw/react-markdown-preview'; export * from '@uiw/react-markdown-preview'; export interface ToolBarProps { editor: React.RefObject<ReactCodeMirrorRef>; preview: React.RefObject<HTMLDivElement>; container: React.RefObject<HTMLDivElement>; containerEditor: React.RefObject<HTMLDivElement>; editorProps: IMarkdownEditor; } export interface MarkdownEditorRef { editor: React.RefObject<ReactCodeMirrorRef> | null; preview?: React.RefObject<MarkdownPreviewRef> | null; } export declare type Commands = keyof typeof defaultCommands | ICommand; export interface IToolBarProps<T = Commands> extends ToolBarProps { className?: string; editorProps: IMarkdownEditor; mode?: boolean; prefixCls?: string; toolbars?: T[]; onClick?: (type: string) => void; } declare const MarkdownEditor: MarkdownEditorComponent; declare type MarkdownEditorComponent = React.FC<React.PropsWithRef<IMarkdownEditor>> & { Markdown: typeof MarkdownPreview; }; export default MarkdownEditor;
import { ReactCodeMirrorRef } from '@uiw/react-codemirror'; import { MarkdownPreviewProps, MarkdownPreviewRef } from '@uiw/react-markdown-preview'; export declare type ButtonHandle = (command: ICommand, props: IMarkdownEditor, options: ToolBarProps) => JSX.Element; export declare type ICommand = { icon?: React.ReactElement; name?: string; keyCommand?: string; button?: ButtonHandle | React.ButtonHTMLAttributes<HTMLButtonElement>; execute?: (editor: ReactCodeMirrorRef) => void; }; export declare const defaultCommands: { undo: ICommand; redo: ICommand; bold: ICommand; italic: ICommand; header: ICommand; strike: ICommand; underline: ICommand; quote: ICommand; olist: ICommand; ulist: ICommand; todo: ICommand; link: ICommand; image: ICommand; code: ICommand; codeBlock: ICommand; fullscreen: ICommand; preview: ICommand; }; export declare const getCommands: () => ICommand[]; export declare const getModeCommands: () => ICommand[]; export declare const defaultTheme: import("@codemirror/state").Extension;

Development

npm run watch # Listen create type and .tsx files. npm run start # Preview code example. npm run doc

Related

Contributors

As always, thanks to our amazing contributors!

Made with action-contributors.

License

Licensed under the MIT License.