react-md-editor

授权协议 MIT License
开发语言 JavaScript
所属分类 应用工具、 文档/文本编辑
软件类型 开源软件
地区 不详
投 递 者 卓嘉良
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

react-md-editor logo

Build & Deploy

A simple markdown editor with preview, implemented with React.js and TypeScript. This React Component aims to provide a simple Markdown editor with syntax highlighting support. This is based on textarea encapsulation, so it does not depend on any modern code editors such as Acs, CodeMirror, Monaco etc.

Features

  • �� Indent line or selected text by pressing tab key, with customizable indentation.
  • ♻️ Based on textarea encapsulation, does not depend on any modern code editors.
  • �� Does not depend on the uiw component library.
  • �� Automatic list on new lines.
  • �� GitHub flavored markdown support.
  • �� Support next.js, Use examples in next.js.

Quick Start

npm i @uiw/react-md-editor

Using

import React from "react";
import ReactDOM from "react-dom";
import MDEditor from '@uiw/react-md-editor';

export default function App() {
  const [value, setValue] = React.useState("**Hello world!!!**");
  return (
    <div className="container">
      <MDEditor
        value={value}
        onChange={setValue}
      />
      <MDEditor.Markdown source={value} />
    </div>
  );
}

Custom Toolbars

import React from "react";
import ReactDOM from "react-dom";
import MDEditor, { commands, ICommand, TextState, TextAreaTextApi } from '@uiw/react-md-editor';

const title3: ICommand = {
  name: 'title3',
  keyCommand: 'title3',
  buttonProps: { 'aria-label': 'Insert title3' },
  icon: (
    <svg width="12" height="12" viewBox="0 0 520 520">
      <path fill="currentColor" d="M15.7083333,468 C7.03242448,468 0,462.030833 0,454.666667 L0,421.333333 C0,413.969167 7.03242448,408 15.7083333,408 L361.291667,408 C369.967576,408 377,413.969167 377,421.333333 L377,454.666667 C377,462.030833 369.967576,468 361.291667,468 L15.7083333,468 Z M21.6666667,366 C9.69989583,366 0,359.831861 0,352.222222 L0,317.777778 C0,310.168139 9.69989583,304 21.6666667,304 L498.333333,304 C510.300104,304 520,310.168139 520,317.777778 L520,352.222222 C520,359.831861 510.300104,366 498.333333,366 L21.6666667,366 Z M136.835938,64 L136.835937,126 L107.25,126 L107.25,251 L40.75,251 L40.75,126 L-5.68434189e-14,126 L-5.68434189e-14,64 L136.835938,64 Z M212,64 L212,251 L161.648438,251 L161.648438,64 L212,64 Z M378,64 L378,126 L343.25,126 L343.25,251 L281.75,251 L281.75,126 L238,126 L238,64 L378,64 Z M449.047619,189.550781 L520,189.550781 L520,251 L405,251 L405,64 L449.047619,64 L449.047619,189.550781 Z" />
    </svg>
  ),
  execute: (state: TextState, api: TextAreaTextApi) => {
    let modifyText = `### ${state.selectedText}\n`;
    if (!state.selectedText) {
      modifyText = `### `;
    }
    api.replaceSelection(modifyText);
  },
};

export default function App() {
  const [value, setValue] = React.useState("**Hello world!!!**");
  return (
    <div className="container">
      <MDEditor
        value="Hello Markdown!"
        onChange={(val) => {
          setValue(val!);
        }}
        commands={[
          // Custom Toolbars
          title3,
          commands.group([commands.title1, commands.title2, commands.title3, commands.title4, commands.title5, commands.title6], {
            name: 'title',
            groupName: 'title',
            buttonProps: { 'aria-label': 'Insert title'}
          }),
          commands.divider,
          commands.group([], {
            name: 'update',
            groupName: 'update',
            icon: (
              <svg viewBox="0 0 1024 1024" width="12" height="12">
                <path fill="currentColor" d="M716.8 921.6a51.2 51.2 0 1 1 0 102.4H307.2a51.2 51.2 0 1 1 0-102.4h409.6zM475.8016 382.1568a51.2 51.2 0 0 1 72.3968 0l144.8448 144.8448a51.2 51.2 0 0 1-72.448 72.3968L563.2 541.952V768a51.2 51.2 0 0 1-45.2096 50.8416L512 819.2a51.2 51.2 0 0 1-51.2-51.2v-226.048l-57.3952 57.4464a51.2 51.2 0 0 1-67.584 4.2496l-4.864-4.2496a51.2 51.2 0 0 1 0-72.3968zM512 0c138.6496 0 253.4912 102.144 277.1456 236.288l10.752 0.3072C924.928 242.688 1024 348.0576 1024 476.5696 1024 608.9728 918.8352 716.8 788.48 716.8a51.2 51.2 0 1 1 0-102.4l8.3968-0.256C866.2016 609.6384 921.6 550.0416 921.6 476.5696c0-76.4416-59.904-137.8816-133.12-137.8816h-97.28v-51.2C691.2 184.9856 610.6624 102.4 512 102.4S332.8 184.9856 332.8 287.488v51.2H235.52c-73.216 0-133.12 61.44-133.12 137.8816C102.4 552.96 162.304 614.4 235.52 614.4l5.9904 0.3584A51.2 51.2 0 0 1 235.52 716.8C105.1648 716.8 0 608.9728 0 476.5696c0-132.1984 104.8064-239.872 234.8544-240.2816C258.5088 102.144 373.3504 0 512 0z" />
              </svg>
            ),
            children: ({ close, execute, getState, textApi }) => {
              return (
                <div style={{ width: 120, padding: 10 }}>
                  <div>My Custom Toolbar</div>
                  <button type="button" onClick={() => console.log('> execute: >>>>>', getState!())}>State</button>
                  <button type="button" onClick={() => close()}>Close</button>
                  <button type="button" onClick={() => execute()}>Execute</button>
                </div>
              );
            },
            execute: (state: TextState, api: TextAreaTextApi)  => {
              console.log('>>>>>>update>>>>>', state)
            },
            buttonProps: { 'aria-label': 'Insert title'}
          }),
        ]}
      />
    </div>
  );
}

Preview Markdown

import React from "react";
import ReactDOM from "react-dom";
import MDEditor from '@uiw/react-md-editor';

export default function App() {
  return (
    <div className="container">
      <MDEditor.Markdown source="Hello Markdown!" />
    </div>
  );
}

Support Custom KaTeX Preview

KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web, We perform math rendering through KaTeX.

The following example is preview in CodeSandbox.

⚠️ Upgrade v2 to v3 d025430

npm install katex
import React from "react";
import ReactDOM from "react-dom";
import MDEditor from '@uiw/react-md-editor';
import katex from 'katex';
import 'katex/dist/katex.css';

const mdKaTeX = `This is to display the 
\`\$\$\c = \\pm\\sqrt{a^2 + b^2}\$\$\`
 in one line

\`\`\`KaTeX
c = \\pm\\sqrt{a^2 + b^2}
\`\`\`
`;

export default function App() {
  return (
    <MDEditor
      value={mdKaTeX}
      previewOptions={{
        components: {
          code: ({ inline, children, className, ...props }) => {
            const txt = children[0] || '';
            if (inline) {
              if (typeof txt === 'string' && /^\$\$(.*)\$\$/.test(txt)) {
                const html = katex.renderToString(txt.replace(/^\$\$(.*)\$\$/, '$1'), {
                  throwOnError: false,
                });
                return <code dangerouslySetInnerHTML={{ __html: html }} />;
              }
              return <code>{txt}</code>;
            }
            if (
              typeof txt === 'string' &&
              typeof className === 'string' &&
              /^language-katex/.test(className.toLocaleLowerCase())
            ) {
              const html = katex.renderToString(txt, {
                throwOnError: false,
              });
              return <code dangerouslySetInnerHTML={{ __html: html }} />;
            }
            return <code className={String(className)}>{txt}</code>;
          },
        },
      }}
    />
  );
}

Markdown text to Imgage

import React from "react";
import MDEditor, { commands, ICommand, TextState, TextAreaTextApi } from "@uiw/react-md-editor";
import domToImage from "dom-to-image";

const textToImage: ICommand = {
  name: "Text To Image",
  keyCommand: "text2image",
  buttonProps: { "aria-label": "Insert title3" },
  icon: (
    <svg width="12" height="12" viewBox="0 0 20 20">
      <path fill="currentColor" d="M15 9c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4-7H1c-.55 0-1 .45-1 1v14c0 .55.45 1 1 1h18c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 13l-6-5-2 2-4-5-4 8V4h16v11z" ></path>
    </svg>
  ),
  execute: (state: TextState, api: TextAreaTextApi) => {
    const dom = document.getElementsByClassName("w-md-editor")[0];
    if (dom) {
      domToImage.toJpeg(dom, {}).then((dataUrl) => {
        const link = document.createElement("a");
        link.download = "image.jpg";
        link.href = dataUrl;
        link.click();
      });
    }
  }
};

export default function App() {
  return (
    <div className="container">
      <MDEditor
        value="**Hello world!!!**"
        commands={[
          textToImage,
          commands.divider
        ]}
      />
    </div>
  );
}

Support Custom Mermaid Preview

Using mermaid to generation of diagram and flowchart from text in a similar manner as markdown

npm install mermaid
import React from "react";
import ReactDOM from "react-dom";
import MDEditor from "@uiw/react-md-editor";
import mermaid from "mermaid";

const mdMermaid = `The following are some examples of the diagrams, charts and graphs that can be made using Mermaid and the Markdown-inspired text specific to it. 

\`\`\`mermaid
graph TD
A[Hard] -->|Text| B(Round)
B --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]
\`\`\`

\`\`\`mermaid
sequenceDiagram
Alice->>John: Hello John, how are you?
loop Healthcheck
    John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
\`\`\`
`;

export default function App() {
  return (
    <MDEditor
      height={500}
      value={mdMermaid || ""}
      previewOptions={{
        components: {
          code: ({ inline, children, className, ...props }) => {
            const txt = children[0] || '';
            if (
              typeof txt === 'string' &&
              typeof className === 'string' &&
              /^language-mermaid/.test(className.toLocaleLowerCase())
            ) {
              const Elm = document.createElement("div");
              Elm.id = "demo";
              const svg = mermaid.render("demo", txt);
              return <code dangerouslySetInnerHTML={{ __html: svg }} />
            }
            return <code className={String(className)}>{txt}</code>;
          },
        },
      }}
    />
  );
}

ReactDOM.render(<App />, document.getElementById("container"));

Support Nextjs

Use examples in nextjs. #52 #224

npm install next-remove-imports
npm install @uiw/react-md-editor@v3.6.0
// next.config.js
const removeImports = require('next-remove-imports')();
module.exports = removeImports({});
import "@uiw/react-md-editor/markdown-editor.css";
import "@uiw/react-markdown-preview/markdown.css";
import dynamic from "next/dynamic";
import { useState } from "react";

const MDEditor = dynamic(
  () => import("@uiw/react-md-editor").then((mod) => mod.default),
  { ssr: false }
);

function HomePage() {
  const [value, setValue] = useState("**Hello world!!!**");
  return (
    <div>
      <MDEditor value={value} onChange={setValue} />
    </div>
  );
}

export default HomePage;

Props

  • value: string: The Markdown value.
  • onChange?: (value: string): Event handler for the onChange event.
  • commands?: ICommand[]: An array of ICommand, which, each one, contain a commands property. If no commands are specified, the default will be used. Commands are explained in more details below.
  • extraCommands?: ICommand[]: Displayed on the right side of the toolbar.
  • autoFocus?: true: Can be used to make Markdown Editor focus itself on initialization.
  • previewOptions?: ReactMarkdown.ReactMarkdownProps: This is reset @uiw/react-markdown-preview settings.
  • textareaProps?: TextareaHTMLAttributes: Set the textarea related props.
  • renderTextarea?: (props, opts) => JSX.Element;: Use div to replace TextArea or re-render TextArea. #193
  • height?: number=200: The height of the editor.
  • visiableDragbar?: boolean=true: Show drag and drop tool. Set the height of the editor.
  • highlightEnable?: boolean=true: Disable editing area code highlighting. The value is false, which increases the editing speed.
  • fullscreen?: boolean=false: Show markdown preview.
  • preview?: 'live' | 'edit' | 'preview': Default value live, Show markdown preview.
  • maxHeight?: number=1200: Maximum drag height. The visiableDragbar=true value is valid.
  • minHeights?: number=100: Minimum drag height. The visiableDragbar=true value is valid.
  • tabSize?: number=2: The number of characters to insert when pressing tab key. Default 2 spaces.
  • hideToolbar?: boolean=false: Option to hide the tool bar.
  • enableScroll?: boolean=true: Whether to enable scrolling.

Development

npm run watch     # Listen create type and .tsx files.
npm run css:watch # listen to the component compile and output the .css file
npm run start  # Preview code example.

Related

License

Licensed under the MIT License.

  • 开发中有从详情页返回列表页的需求,这样一来页面返回后使用react-router会直接刷新页面,导致页面中的分页和搜索条件全部丢失,用户体验不佳,所以就必须将列表页的状态进行缓存。 网上搜索大概有几种方法: 1、使用localStorage/sessionStorage进行页面的状态的保存,跳转页面后再进行获取,这种方法虽然可行,但是从根本来说还是从新向后台再一次请求了数据,不算最佳方案。 2、r

  •   1.定制模板   使用自定义模板,您可以从中选择一个模板来创建您的项目,同时仍保留Create React App的所有功能。 您会注意到,自定义模板始终以格式命名cra-template-[template-name],但是您只需[template-name]要向创建命令提供即可。 还支持作用域模板,名称为@[scope-name]/cra-template或@[scope-name]/cr

  • 不废话了,这次直接开干。也是我逐步的搭建过程。当手记了 总结看最后。 本次项目地址:https://github.com/ht-sauce/react-template 1、创建项目 这个没什么可以说的,就是一个命令:npm create 你的项目名称 附带官网地址:https://www.html.cn/create-react-app/docs/setting-up-your-editor/

  • 1. 创建项目 首先安装vscode插件prettier, stylelint, eslint, EditorConfig for VS Code 1.1 使用create-react-app创建项目 npx create-react-app demo --template typescript 1.2 添加eslint yarn add eslint --dev yarn run eslint

  • 配置时:先执行npm run eject, 这个是把隐藏的配置显示出来。 webpack.config.js 在配置CSS module时,我在规则里都加了modules:true, 导致CSSmodule和antd冲突,antd样式失效。 { test: /.(js|mjs)$/, exclude: /@babel(?:/|\{1,2})runtime/, loader: require.res

  • 1.分析需求 实现富文本编辑功能,通过与后台传输html字符串,实现保存、编辑、回显功能。 2.下载依赖 npm install 3.引入 import { Editor } from 'react-draft-wysiwyg'; import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'; import { EditorState, con

  • 1.父组件jsx文件引用下面的子组件jsx文件 2.父组件jsx文件具体使用:<Editor.EditorShow config={{ markdown: // testEditor.getMarkdown().replace(//g, '\\’) ## Test \`` console.log(‘what can i do for you’) ``` # 123123`

  • Getting Started ——创建一个React App的多种方式 Quick Start 三条指令快速创建一个项目并运行 npx create-react-app my-app cd my-app npm start !注意: 非全局安装create-react-app可以保证npx总是最新的版本。 Get Started Immediately 内置的环境工具如webpack和Babe

  • Bookmarks Bookmarks 书签栏 前端 JS 中级 ES6、ES7、ES8、ES9、ES10新特性1 ES6、ES7、ES8、ES9、ES10新特性2 函数继承 对象基本用法 数组操作方法 其他数据类型 正则教程 Ajax原理和几种工具类 数据结构与算法 Http缓存 Http 1.x 2.x区别 Https 浏览器存贮 前端XSS,CSRF,点击劫持攻击 高级 JS执行机制1 JS

  • 1、react-navigation 导航组件  参考链接:https://www.jianshu.com/p/2f575cc35780 https://blog.csdn.net/u013718120/article/details/72357698   2、native-base 自定义样式 参考链接:http://docs.nativebase.io/Components.html#Comp

 相关资料
  • md-editor 带有预览功能的简单 Markdown 编辑器,使用 React.js 和 TypeScript 实现。 提供具有语法突出显示,自动按需懒加载 prismjs 的 187 种语言高亮的简单 Markdown 编辑器。 这基于 textarea 封装,因此它不依赖于任何现代代码编辑器,如 Acs,CodeMirror,Monaco 等,同时支持工具栏高度定制。 特征 �� 通过按T

  • md

    微信 Markdown 编辑器 项目介绍 本项目基于 wechat-format 进行二次开发,感谢 lyricat 的创意和贡献! Markdown 文档自动即时渲染为微信图文,让你不再为微信文章排版而发愁!只要你会基本的 Markdown 语法,就能做出一篇样式简洁而又美观大方的微信图文。 在线编辑器地址 Netlify: https://mdhere.netlify.app Gitee Pa

  • markdown 博客 为小团队内部分享技术文档而生的一个 markdown 博客 在线编辑文档,提供实时预览的 markdown 编辑器 支持拖拽上传图片 采用 GFM 语法 支持离线缓存未发布的文档 像浏览个人博客一样的浏览团队文档     使用方法:https://github.com/hanxi/md-pages/blob/master/README.md     实现过程:http://

  • Thinker-md是什么 Thinker-md 是一个支持 Markdown 的在线文档编辑器。 在线演示:http://thinkermd.oschina.mopaas.com Thinker-md的特性 支持Markdown标准和Github风格; 编辑内容实时保存,刷新页面不会丢失; 支持实时预览、图片(跨域)上传; 支持MarkdownToHtml,HtmlToMarkdown双向解析;

  • md-cv A jekyll-based markdown CV, which currently looks something like this, see this blog post for details. Forked from the (great) markdown CV of elipapa. How to use To build, clone the repo and run

  • doocs-md 是一款高度简洁的微信 Markdown 编辑器:支持 Markdown 所有基础语法、色盘取色、一键复制并粘贴到公众号后台、多图上传、一键下载文档、自定义 CSS 样式、一键重置等特性。 Markdown 文档自动即时渲染为微信图文,让你不再为微信文章排版而发愁!只要你会基本的 Markdown 语法,就能做出一篇样式简洁而又美观大方的微信图文。 在线编辑器地址 Netlify: