UNPKG

@uiw/react-markdown-editor

Version:

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

317 lines (260 loc) β€’ 10.4 kB
<p align="center"> <a href="https://github.com/uiwjs/react-markdown-editor"> <img alt="React Markdown Editor logo" src="./website/logo.svg?sanitize=true"> </a> </p> <!--dividing--> <p align="center"> <a href="https://github.com/uiwjs/react-markdown-editor/actions"> <img alt="Build & Deploy" src="https://github.com/uiwjs/react-markdown-editor/actions/workflows/ci.yml/badge.svg"> </a> <a href="https://www.npmjs.com/package/@uiw/react-markdown-editor"> <img alt="NPM Download" src="https://img.shields.io/npm/dm/@uiw/react-markdown-editor.svg?style=flat"> </a> <a href="https://www.npmjs.com/package/@uiw/react-markdown-editor"> <img alt="npm version" src="https://img.shields.io/npm/v/@uiw/react-markdown-editor.svg"> </a> </p> <p align="center"> A markdown editor with preview, implemented with React.js and TypeScript. </p> <!--rehype:ignore:start--> [![React Markdown Editor](https://user-images.githubusercontent.com/1680273/186128463-5f819e3f-926b-4dea-b5d8-e9d1d1a8d72e.png)](https://uiwjs.github.io/react-markdown-editor/) <!--rehype:ignore:end--> > Migrate from @uiw/react-markdown-editor [4.x to 5.x.](https://github.com/uiwjs/react-markdown-editor/releases/tag/v5.0.0) ## Install ```bash npm i @uiw/react-markdown-editor ``` <!--rehype:ignore:start--> ## Document Official document [demo preview](https://uiwjs.github.io/react-markdown-editor/) ([πŸ‡¨πŸ‡³δΈ­ε›½ι•œεƒη½‘η«™](http://uiw.gitee.io/react-markdown-editor/)) <!--rehype:ignore:end--> ## Basic Usage ```jsx import MarkdownEditor from '@uiw/react-markdown-editor'; import React from 'react'; import ReactDOM from 'react-dom'; const Dome = () => ( <MarkdownEditor value={this.state.markdown} onChange={this.updateMarkdown} /> ); ReactDOM.render(<Dome />, document.getElementById('app')); ``` ## Controlled Usage [![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?logo=codesandbox)](https://codesandbox.io/embed/react-markdown-editor-ybpce?file=/src/App.js) ```jsx import MarkdownEditor from '@uiw/react-markdown-editor'; import { createRoot } from 'react-dom/client'; import React, { useState } from 'react'; function App() { const [markdown, setMarkdown] = useState(""); return ( <MarkdownEditor value="# This is a H1 \n## This is a H2 \n###### This is a H6" onChange={(value, viewUpdate) => setMarkdown(value)} /> ); } export default App; ``` ## Custom Toolbars [![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?logo=codesandbox)](https://codesandbox.io/embed/react-markdown-editorcustom-toolbars-forked-r9ocu?fontsize=14&hidenavigation=1&theme=dark) ```jsx import React from "react"; import ReactDOM from "react-dom"; 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!" toolbars={[ 'bold', 'italic', 'header', title2 ]} /> ); export default Dome; ``` ## Support Nextjs Use examples in [nextjs](https://nextjs.org/). [#52](https://github.com/uiwjs/react-md-editor/issues/52#issuecomment-848969341) [#224](https://github.com/uiwjs/react-md-editor/issues/224#issuecomment-901112079) [![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?logo=codesandbox)](https://codesandbox.io/embed/nextjs-example-react-markdown-editor-72s9d?fontsize=14&hidenavigation=1&theme=dark) ```bash npm install next-remove-imports npm install @uiw/react-markdown-editor ``` ```js // next.config.js const removeImports = require('next-remove-imports')(); module.exports = removeImports({}); ``` ```jsx 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`](https://github.com/jaywcjlove/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 <html data-color-mode="dark"> ``` ```js document.documentElement.setAttribute('data-color-mode', 'dark') document.documentElement.setAttribute('data-color-mode', 'light') ``` Inherit custom color variables by adding `.wmde-markdown-var` selector. ```jsx 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 - `previewProps` - [react-markdown options](https://github.com/uiwjs/react-markdown-preview/tree/v2.1.0#options-props) ```ts 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; /** Option to hide the tool bar. */ hideToolbar?: boolean; /** Tool display settings. */ toolbars?: IToolBarProps['toolbars']; /** Tool display settings. */ toolbarsMode?: IToolBarProps['toolbars']; /** Override the default preview component */ renderPreview?: (props: MarkdownPreviewProps, visible: boolean) => React.ReactNode; /** [@uiw/react-markdown-preview](https://github.com/uiwjs/react-markdown-preview#options-props) options */ previewProps?: MarkdownPreviewProps; } ``` ```ts import React from 'react'; import { ReactCodeMirrorRef } from '@uiw/react-codemirror'; import { MarkdownPreviewProps, MarkdownPreviewRef } from '@uiw/react-markdown-preview'; export interface ToolBarProps { editor?: ReactCodeMirrorRef; preview: React.RefObject<MarkdownPreviewRef>; container: React.RefObject<HTMLDivElement>; containerEditor: React.RefObject<HTMLDivElement>; editorProps: IMarkdownEditor; } export interface MarkdownEditorRef { editor: React.RefObject<ReactCodeMirrorRef> | null; preview?: React.RefObject<MarkdownPreviewRef> | null; } export interface IToolBarProps<T = keyof typeof defaultCommands | ICommand> extends ToolBarProps { className?: string; editorProps: IMarkdownEditor; mode?: boolean; prefixCls?: string; toolbars?: T[]; onClick?: (type: string) => void; } 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: { bold: ICommand; italic: ICommand; header: ICommand; strike: ICommand; underline: ICommand; olist: ICommand; ulist: ICommand; link: ICommand; todo: ICommand; image: ICommand; fullscreen: ICommand; preview: ICommand; }; export declare const getCommands: () => ICommand[]; export declare const getModeCommands: () => ICommand[]; ``` ### Development ```bash npm run watch # Listen create type and .tsx files. npm run start # Preview code example. npm run doc ``` ### Related - [@uiw/react-textarea-code-editor](https://github.com/uiwjs/react-textarea-code-editor): A simple code editor with syntax highlighting. - [@uiw/react-codemirror](https://github.com/uiwjs/react-codemirror): CodeMirror component for React. @codemirror - [@uiw/react-monacoeditor](https://github.com/jaywcjlove/react-monacoeditor): Monaco Editor component for React. - [@uiw/react-md-editor](https://github.com/uiwjs/react-md-editor): A simple markdown editor with preview, implemented with React.js and TypeScript. - [@uiw/react-markdown-preview](https://github.com/uiwjs/react-markdown-preview): React component preview markdown text in web browser. ## Contributors As always, thanks to our amazing contributors! <a href="https://github.com/uiwjs/react-markdown-editor/graphs/contributors"> <img src="https://uiwjs.github.io/react-markdown-editor/CONTRIBUTORS.svg" /> </a> Made with [action-contributors](https://github.com/jaywcjlove/github-action-contributors). ## License Licensed under the MIT License.