Skip to content

remarkablejames/extended-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.

About

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

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 93.4%
  • Less 5.5%
  • HTML 1.1%