JSPM

  • Created
  • Published
  • Downloads 1047128
  • Score
    100M100P100Q207564F
  • License MIT

CodeMirror component for React.

Package Exports

    Readme

    react-codemirror logo

    react-codemirror

    Buy me a coffee NPM Downloads Build & Deploy Open in unpkg npm version Coverage Status Open in Gitpod

    CodeMirror component for React. Demo Preview: @uiwjs.github.io/react-codemirror

    Features:

    🚀 Quickly and easily configure the API.
    🌱 Versions after @uiw/react-codemirror@v4 use codemirror 6. #88.
    ⚛️ Support the features of React Hook(requires React 16.8+).
    📚 Use Typescript to write, better code hints.
    🌐 The bundled version supports use directly in the browser #267.
    🌎 There are better sample previews.
    🎨 Support theme customization, provide theme editor.

    Install

    Not dependent on uiw.

    npm install @uiw/react-codemirror --save

    All Packages

    Name NPM Version
    @uiw/react-codemirror npm version NPM Downloads
    react-codemirror-merge npm version NPM Downloads
    @uiw/codemirror-extensions-basic-setup npm version NPM Downloads
    @uiw/codemirror-extensions-color npm version NPM Downloads
    @uiw/codemirror-extensions-classname npm version NPM Downloads
    @uiw/codemirror-extensions-events npm version NPM Downloads
    @uiw/codemirror-extensions-hyper-link npm version NPM Downloads
    @uiw/codemirror-extensions-langs npm version NPM Downloads
    @uiw/codemirror-extensions-line-numbers-relative npm version NPM Downloads
    @uiw/codemirror-extensions-mentions npm version NPM Downloads
    @uiw/codemirror-extensions-zebra-stripes npm version NPM Downloads
    @uiw/codemirror-themes npm version NPM Downloads
    Name NPM Version
    @uiw/codemirror-themes-all npm version NPM Downloads
    @uiw/codemirror-theme-abcdef npm version NPM Downloads
    @uiw/codemirror-theme-abyss npm version NPM Downloads
    @uiw/codemirror-theme-androidstudio npm version NPM Downloads
    @uiw/codemirror-theme-andromeda npm version NPM Downloads
    @uiw/codemirror-theme-atomone npm version NPM Downloads
    @uiw/codemirror-theme-aura npm version NPM Downloads
    @uiw/codemirror-theme-basic npm version NPM Downloads
    @uiw/codemirror-theme-bbedit npm version NPM Downloads
    @uiw/codemirror-theme-bespin npm version NPM Downloads
    @uiw/codemirror-theme-console npm version NPM Downloads
    @uiw/codemirror-theme-copilot npm version NPM Downloads
    @uiw/codemirror-theme-duotone npm version NPM Downloads
    @uiw/codemirror-theme-dracula npm version NPM Downloads
    @uiw/codemirror-theme-darcula npm version NPM Downloads
    @uiw/codemirror-theme-eclipse npm version NPM Downloads
    @uiw/codemirror-theme-github npm version NPM Downloads
    @uiw/codemirror-theme-gruvbox-dark npm version NPM Downloads
    @uiw/codemirror-theme-kimbie npm version NPM Downloads
    @uiw/codemirror-theme-kimbie npm version NPM Downloads
    @uiw/codemirror-theme-material npm version NPM Downloads
    @uiw/codemirror-theme-monokai npm version NPM Downloads
    @uiw/codemirror-theme-noctis-lilac npm version NPM Downloads
    @uiw/codemirror-theme-nord npm version NPM Downloads
    @uiw/codemirror-theme-okaidia npm version NPM Downloads
    @uiw/codemirror-theme-quietlight npm version NPM Downloads
    @uiw/codemirror-theme-red npm version NPM Downloads
    @uiw/codemirror-theme-solarized npm version NPM Downloads
    @uiw/codemirror-theme-sublime npm version NPM Downloads
    @uiw/codemirror-theme-tokyo-night npm version NPM Downloads
    @uiw/codemirror-theme-tokyo-night-storm npm version NPM Downloads
    @uiw/codemirror-theme-tokyo-night-day npm version NPM Downloads
    @uiw/codemirror-theme-vscode npm version NPM Downloads
    @uiw/codemirror-theme-white npm version NPM Downloads
    @uiw/codemirror-theme-tomorrow-night-blue npm version NPM Downloads
    @uiw/codemirror-theme-xcode npm version NPM Downloads

    Usage

    Open in CodeSandbox

    import React from 'react';
    import CodeMirror from '@uiw/react-codemirror';
    import { javascript } from '@codemirror/lang-javascript';
    
    function App() {
      const [value, setValue] = React.useState("console.log('hello world!');");
      const onChange = React.useCallback((val, viewUpdate) => {
        console.log('val:', val);
        setValue(val);
      }, []);
      return <CodeMirror value={value} height="200px" extensions={[javascript({ jsx: true })]} onChange={onChange} />;
    }
    export default App;

    Support Language

    Open in CodeSandbox

    import CodeMirror from '@uiw/react-codemirror';
    import { StreamLanguage } from '@codemirror/language';
    import { go } from '@codemirror/legacy-modes/mode/go';
    
    const goLang = `package main
    import "fmt"
    
    func main() {
      fmt.Println("Hello, 世界")
    }`;
    
    export default function App() {
      return <CodeMirror value={goLang} height="200px" extensions={[StreamLanguage.define(go)]} />;
    }

    Markdown Example

    Markdown language code is automatically highlighted.

    Open in CodeSandbox

    import CodeMirror from '@uiw/react-codemirror';
    import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
    import { languages } from '@codemirror/language-data';
    
    const code = `## Title
    
    \`\`\`jsx
    function Demo() {
      return <div>demo</div>
    }
    \`\`\`
    
    \`\`\`bash
    # Not dependent on uiw.
    npm install @codemirror/lang-markdown --save
    npm install @codemirror/language-data --save
    \`\`\`
    
    [weisit ulr](https://uiwjs.github.io/react-codemirror/)
    
    \`\`\`go
    package main
    import "fmt"
    func main() {
      fmt.Println("Hello, 世界")
    }
    \`\`\`
    `;
    
    export default function App() {
      return <CodeMirror value={code} extensions={[markdown({ base: markdownLanguage, codeLanguages: languages })]} />;
    }

    Codemirror Merge

    A component that highlights the changes between two versions of a file in a side-by-side view, highlighting added, modified, or deleted lines of code.

    npm install react-codemirror-merge  --save
    import CodeMirrorMerge from 'react-codemirror-merge';
    import { EditorView } from 'codemirror';
    import { EditorState } from '@codemirror/state';
    
    const Original = CodeMirrorMerge.Original;
    const Modified = CodeMirrorMerge.Modified;
    let doc = `one
    two
    three
    four
    five`;
    
    export const Example = () => {
      return (
        <CodeMirrorMerge>
          <Original value={doc} />
          <Modified
            value={doc.replace(/t/g, 'T') + 'Six'}
            extensions={[EditorView.editable.of(false), EditorState.readOnly.of(true)]}
          />
        </CodeMirrorMerge>
      );
    };

    Support Hook

    Open in CodeSandbox

    import { useEffect, useMemo, useRef } from 'react';
    import { useCodeMirror } from '@uiw/react-codemirror';
    import { javascript } from '@codemirror/lang-javascript';
    
    const code = "console.log('hello world!');\n\n\n";
    // Define the extensions outside the component for the best performance.
    // If you need dynamic extensions, use React.useMemo to minimize reference changes
    // which cause costly re-renders.
    const extensions = [javascript()];
    
    export default function App() {
      const editor = useRef();
      const { setContainer } = useCodeMirror({
        container: editor.current,
        extensions,
        value: code,
      });
    
      useEffect(() => {
        if (editor.current) {
          setContainer(editor.current);
        }
      }, [editor.current]);
    
      return <div ref={editor} />;
    }

    Using Theme

    We have created a theme editor where you can define your own theme. We have also defined some themes ourselves, which can be installed and used directly. Below is a usage example:

    import CodeMirror from '@uiw/react-codemirror';
    import { javascript } from '@codemirror/lang-javascript';
    import { okaidia } from '@uiw/codemirror-theme-okaidia';
    
    const extensions = [javascript({ jsx: true })];
    
    export default function App() {
      return <CodeMirror value="console.log('hello world!');" height="200px" theme={okaidia} extensions={extensions} />;
    }

    Using custom theme

    import CodeMirror from '@uiw/react-codemirror';
    import { createTheme } from '@uiw/codemirror-themes';
    import { javascript } from '@codemirror/lang-javascript';
    import { tags as t } from '@lezer/highlight';
    
    const myTheme = createTheme({
      theme: 'light',
      settings: {
        background: '#ffffff',
        backgroundImage: '',
        foreground: '#75baff',
        caret: '#5d00ff',
        selection: '#036dd626',
        selectionMatch: '#036dd626',
        lineHighlight: '#8a91991a',
        gutterBackground: '#fff',
        gutterForeground: '#8a919966',
      },
      styles: [
        { tag: t.comment, color: '#787b8099' },
        { tag: t.variableName, color: '#0080ff' },
        { tag: [t.string, t.special(t.brace)], color: '#5c6166' },
        { tag: t.number, color: '#5c6166' },
        { tag: t.bool, color: '#5c6166' },
        { tag: t.null, color: '#5c6166' },
        { tag: t.keyword, color: '#5c6166' },
        { tag: t.operator, color: '#5c6166' },
        { tag: t.className, color: '#5c6166' },
        { tag: t.definition(t.typeName), color: '#5c6166' },
        { tag: t.typeName, color: '#5c6166' },
        { tag: t.angleBracket, color: '#5c6166' },
        { tag: t.tagName, color: '#5c6166' },
        { tag: t.attributeName, color: '#5c6166' },
      ],
    });
    const extensions = [javascript({ jsx: true })];
    
    export default function App() {
      const onChange = React.useCallback((value, viewUpdate) => {
        console.log('value:', value);
      }, []);
      return (
        <CodeMirror
          value="console.log('hello world!');"
          height="200px"
          theme={myTheme}
          extensions={extensions}
          onChange={onChange}
        />
      );
    }

    Use initialState to restore state from JSON-serialized representation

    CodeMirror allows to serialize editor state to JSON representation with toJSON function for persistency or other needs. This JSON representation can be later used to recreate ReactCodeMirror component with the same internal state.

    For example, this is how undo history can be saved in the local storage, so that it remains after the page reloads

    import CodeMirror from '@uiw/react-codemirror';
    import { historyField } from '@codemirror/commands';
    
    // When custom fields should be serialized, you can pass them in as an object mapping property names to fields.
    // See [toJSON](https://codemirror.net/docs/ref/#state.EditorState.toJSON) documentation for more details
    const stateFields = { history: historyField };
    
    export function EditorWithInitialState() {
      const serializedState = localStorage.getItem('myEditorState');
      const value = localStorage.getItem('myValue') || '';
    
      return (
        <CodeMirror
          value={value}
          initialState={
            serializedState
              ? {
                  json: JSON.parse(serializedState || ''),
                  fields: stateFields,
                }
              : undefined
          }
          onChange={(value, viewUpdate) => {
            localStorage.setItem('myValue', value);
    
            const state = viewUpdate.state.toJSON(stateFields);
            localStorage.setItem('myEditorState', JSON.stringify(state));
          }}
        />
      );
    }

    Props

    • value?: string value of the auto created model in the editor.
    • width?: string width of editor. Defaults to auto.
    • height?: string height of editor. Defaults to auto.
    • theme?: 'light' / 'dark' / Extension Defaults to 'light'.
    import React from 'react';
    import { EditorState, EditorStateConfig, Extension } from '@codemirror/state';
    import { EditorView, ViewUpdate } from '@codemirror/view';
    export * from '@codemirror/view';
    export * from '@codemirror/basic-setup';
    export * from '@codemirror/state';
    export interface UseCodeMirror extends ReactCodeMirrorProps {
      container?: HTMLDivElement | null;
    }
    export declare function useCodeMirror(props: UseCodeMirror): {
      state: EditorState | undefined;
      setState: import('react').Dispatch<import('react').SetStateAction<EditorState | undefined>>;
      view: EditorView | undefined;
      setView: import('react').Dispatch<import('react').SetStateAction<EditorView | undefined>>;
      container: HTMLDivElement | null | undefined;
      setContainer: import('react').Dispatch<import('react').SetStateAction<HTMLDivElement | null | undefined>>;
    };
    export interface ReactCodeMirrorProps
      extends Omit<EditorStateConfig, 'doc' | 'extensions'>,
        Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'placeholder'> {
      /** value of the auto created model in the editor. */
      value?: string;
      height?: string;
      minHeight?: string;
      maxHeight?: string;
      width?: string;
      minWidth?: string;
      maxWidth?: string;
      /** focus on the editor. */
      autoFocus?: boolean;
      /** Enables a placeholder—a piece of example content to show when the editor is empty. */
      placeholder?: string | HTMLElement;
      /**
       * `light` / `dark` / `Extension` Defaults to `light`.
       * @default light
       */
      theme?: 'light' | 'dark' | Extension;
      /**
       * Whether to optional basicSetup by default
       * @default true
       */
      basicSetup?: boolean | BasicSetupOptions;
      /**
       * This disables editing of the editor content by the user.
       * @default true
       */
      editable?: boolean;
      /**
       * This disables editing of the editor content by the user.
       * @default false
       */
      readOnly?: boolean;
      /**
       * Controls whether pressing the `Tab` key inserts a tab character and indents the text (`true`)
       * or behaves according to the browser's default behavior (`false`).
       * @default true
       */
      indentWithTab?: boolean;
      /** Fired whenever a change occurs to the document. */
      onChange?(value: string, viewUpdate: ViewUpdate): void;
      /** Some data on the statistics editor. */
      onStatistics?(data: Statistics): void;
      /** The first time the editor executes the event. */
      onCreateEditor?(view: EditorView, state: EditorState): void;
      /** Fired whenever any state change occurs within the editor, including non-document changes like lint results. */
      onUpdate?(viewUpdate: ViewUpdate): void;
      /**
       * Extension values can be [provided](https://codemirror.net/6/docs/ref/#state.EditorStateConfig.extensions) when creating a state to attach various kinds of configuration and behavior information.
       * They can either be built-in extension-providing objects,
       * such as [state fields](https://codemirror.net/6/docs/ref/#state.StateField) or [facet providers](https://codemirror.net/6/docs/ref/#state.Facet.of),
       * or objects with an extension in its `extension` property. Extensions can be nested in arrays arbitrarily deep—they will be flattened when processed.
       */
      extensions?: Extension[];
      /**
       * If the view is going to be mounted in a shadow root or document other than the one held by the global variable document (the default), you should pass it here.
       * Originally from the [config of EditorView](https://codemirror.net/6/docs/ref/#view.EditorView.constructor%5Econfig.root)
       */
      root?: ShadowRoot | Document;
      /**
       * Create a state from its JSON representation serialized with [toJSON](https://codemirror.net/docs/ref/#state.EditorState.toJSON) function
       */
      initialState?: {
        json: any;
        fields?: Record<'string', StateField<any>>;
      };
    }
    export interface ReactCodeMirrorRef {
      editor?: HTMLDivElement | null;
      state?: EditorState;
      view?: EditorView;
    }
    declare const ReactCodeMirror: React.ForwardRefExoticComponent<
      ReactCodeMirrorProps & React.RefAttributes<ReactCodeMirrorRef>
    >;
    export default ReactCodeMirror;
    export interface BasicSetupOptions {
      lineNumbers?: boolean;
      highlightActiveLineGutter?: boolean;
      highlightSpecialChars?: boolean;
      history?: boolean;
      foldGutter?: boolean;
      drawSelection?: boolean;
      dropCursor?: boolean;
      allowMultipleSelections?: boolean;
      indentOnInput?: boolean;
      syntaxHighlighting?: boolean;
      bracketMatching?: boolean;
      closeBrackets?: boolean;
      autocompletion?: boolean;
      rectangularSelection?: boolean;
      crosshairCursor?: boolean;
      highlightActiveLine?: boolean;
      highlightSelectionMatches?: boolean;
      closeBracketsKeymap?: boolean;
      defaultKeymap?: boolean;
      searchKeymap?: boolean;
      historyKeymap?: boolean;
      foldKeymap?: boolean;
      completionKeymap?: boolean;
      lintKeymap?: boolean;
    }
    import { EditorSelection, SelectionRange } from '@codemirror/state';
    import { ViewUpdate } from '@codemirror/view';
    export interface Statistics {
      /** Get the number of lines in the editor. */
      lineCount: number;
      /** total length of the document */
      length: number;
      /** Get the proper [line-break](https://codemirror.net/docs/ref/#state.EditorState^lineSeparator) string for this state. */
      lineBreak: string;
      /** Returns true when the editor is [configured](https://codemirror.net/6/docs/ref/#state.EditorState^readOnly) to be read-only. */
      readOnly: boolean;
      /** The size (in columns) of a tab in the document, determined by the [`tabSize`](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize) facet. */
      tabSize: number;
      /** Cursor Position */
      selection: EditorSelection;
      /** Make sure the selection only has one range. */
      selectionAsSingle: SelectionRange;
      /** Retrieves a list of all current selections. */
      ranges: readonly SelectionRange[];
      /** Get the currently selected code. */
      selectionCode: string;
      /**
       * The length of the given array should be the same as the number of active selections.
       * Replaces the content of the selections with the strings in the array.
       */
      selections: string[];
      /** Return true if any text is selected. */
      selectedText: boolean;
    }
    export declare const getStatistics: (view: ViewUpdate) => Statistics;

    Development

    1. Install dependencies
    $ npm install       # Installation dependencies
    $ npm run build     # Compile all package
    1. Development @uiw/react-codemirror package:
    $ cd core
    # listen to the component compile and output the .js file
    # listen for compilation output type .d.ts file
    $ npm run watch # Monitor the compiled package `@uiw/react-codemirror`
    1. Launch documentation site
    npm run start

    Contributors

    As always, thanks to our amazing contributors!

    Made with contributors.

    License

    Licensed under the MIT License.