Codemirror Component for React.js

Last update: May 4, 2022

Codemirror

The excellent CodeMirror editor as a React.js component.

Demo & Examples

Live demo: JedWatson.github.io/react-codemirror

To build the examples locally, run:

npm install
npm start

Then open localhost:8000 in a browser.

Installation

The easiest way to use codemirror is to install it from NPM and include it in your own React build process (using Browserify, Webpack, etc).

You can also use the standalone build by including dist/react-codemirror.js in your page. If you use this, make sure you have already included React, and it is available as a global variable.

npm install react-codemirror --save

Usage

Require the CodeMirror component and render it with JSX:

var React = require('react');
var CodeMirror = require('react-codemirror');

var App = React.createClass({
	getInitialState: function() {
		return {
			code: "// Code",
		};
	},
	updateCode: function(newCode) {
		this.setState({
			code: newCode,
		});
	},
	render: function() {
		var options = {
			lineNumbers: true,
		};
		return <CodeMirror value={this.state.code} onChange={this.updateCode} options={options} />
	}
});

React.render(<App />, document.getElementById('app'));

Include the CSS

Ensure that CodeMirror's stylesheet codemirror.css is loaded.

If you're using LESS (similar for Sass) you can import the css directly from the codemirror package, as shown in example.less:

@import (inline) "./node_modules/codemirror/lib/codemirror.css";

If you're using Webpack with the css loader, you can require the codemirror css in your application instead:

require('codemirror/lib/codemirror.css');

Alternatively, you can explicitly link the codemirror.css file from the CodeMirror project in your index.html file, e.g <link href="css/codemirror.css" rel="stylesheet">.

Methods

  • focus focuses the CodeMirror instance
  • getCodeMirror returns the CodeMirror instance, available .

You can interact with the CodeMirror instance using a ref and the getCodeMirror() method after the componentDidMount lifecycle event has fired (including inside the componentDidMount event in a parent Component).

Properties

  • autoFocus Boolean automatically focuses the editor when it is mounted (default false)
  • autoSave Boolean automatically persist changes to underlying textarea (default false)
  • className String adds a custom css class to the editor
  • codeMirrorInstance Function provides a specific CodeMirror instance (defaults to require('codemirror'))
  • defaultValue String provides a default (not change tracked) value to the editor
  • name String sets the name of the editor input field
  • options Object options passed to the CodeMirror instance
  • onChange Function (newValue) called when a change is made
  • onCursorActivity Function (codemirror) called when the cursor is moved
  • onFocusChange Function (focused) called when the editor is focused or loses focus
  • onScroll Function (scrollInfo) called when the editor is scrolled
  • preserveScrollPosition Boolean=false preserve previous scroll position after updating value
  • value String the editor value

See the CodeMirror API Docs for the available options.

Using Language Modes

Several language modes are included with CodeMirror for syntax highlighting.

By default (to optimise bundle size) all modes are not included. To enable syntax highlighting:

  • install the codemirror package dependency (in addition to react-codemirror)
  • require the language modes you wish to make available after you require react-codemirror itself
  • set the mode option in the options object
var React = require('react');
var CodeMirror = require('react-codemirror');
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/xml/xml');
require('codemirror/mode/markdown/markdown');

<CodeMirror ... options={{
	mode: 'javascript',
}} />

See the example source for a reference implementation including JavaScript and markdown syntax highlighting.

License

Copyright (c) 2016 Jed Watson. MIT Licensed.

GitHub

https://github.com/JedWatson/react-codemirror
Comments
  • 1. Make debounce specific to the instance

    Solution to #47, ensures that the debounce is applied at the instance level. The way it is currently written, all instances of this component are sharing the same debounce so only one instance will update when multiple instances on a page are supposed to update simultaneously. This is an issue for things like drag & drop sorting of codemirror content blocks.

    Reviewed by sslotsky at 2016-05-02 13:43
  • 2. Line Numbers not rendering to gutter correctly.

    Using Browserify.

    If I toggle the included css being pointed to the numbers display correctly.

    snapshot

    Like this: .CodeMirror-gutter-elt {left: -29px !important}

    The line numbers display correctly, after I include the above line of css.

    Possibly related areas of code: https://github.com/JedWatson/react-codemirror/blob/master/lib/Codemirror.js#L23 https://github.com/JedWatson/react-codemirror/blob/master/dist/react-codemirror.js#L677-L678 https://github.com/JedWatson/react-codemirror/blob/master/dist/react-codemirror.js#L1052-L1063

    I was also having difficulties with getting extra themes to work as well, since the className was not being appended to the correct elements.

    var Editor         = require('./codeeditorview/CodeMirror')
        editorConfig: {
            'mode': 'javascript',
            'theme': 'cm-s-monokai',
            'lineNumbers': true,
        },
    <Editor config={ this.items.editorConfig }/>
    

    ./codeeditorview/CodeMirror':

    'use strict';
    var Codemirror = require('react-codemirror');
    var Editor = React.createClass({
        getInitialState: function() {
            return {
                code: 'function add(a, b) {\n' +
                      '  return a + b;\n' +
                      '}'
            };
        },
        updateCode: function(newCode) {
            console.log('From the editor',newCode)
            this.setState({
                code: newCode
            });
        },
        render: function() {
          var options = this.props.config
          return (
              <Codemirror value={this.state.code} onChange={this.updateCode} options={options} />
          )
        }
      });
    
    // React.render(<App />, document.getElementById('app'));
    module.exports = Editor
    
    Reviewed by ghost at 2015-06-22 21:06
  • 3. Fixed React 15.5 deprecation warnings

    For your consideration.

    1. Replaced React.PropTypes with prop-types module. See React 15.5 release notes.
    2. Replaced React.createClass with create-react-class module. See React 15.5 release notes.

    This commit changes the peer dependency requirement to 15.3+ in order to avoid introducing the following new warning:

    Warning: You are manually calling a React.PropTypes validation function for the className prop on <<anonymous>>. This is deprecated and will not work in production with the next major version. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details.

    Reviewed by bvaughn at 2017-04-09 18:10
  • 4. lint addon is not working

    I've been trying to add javascript-lint gutter markers to my code editor and I haven't been getting anywhere. I am importing the lint.js and javascript-lint.js files from codemirror like I assume I am supposed to do. I have also added the lint and gutter options to my options object like I've also seen. I am getting everything to work properly except the lint gutter markers. Below is the code I am using to make the code editor and the result after I have bundled the code and am running it on my website. Am I doing something wrong? Help is much appreciated, thanks!

    Javascipt File

    import React from 'react';
    import CodeMirror from 'react-codemirror';
    const isBrowser = typeof window !== 'undefined';
    isBrowser ? function(){
      require('codemirror/mode/javascript/javascript');
      require('codemirror/addon/lint/lint');
      require('codemirror/addon/lint/javascript-lint');
    }() : undefined;
    
    import _ from 'underscore';
    
    class CodeEditor extends React.Component{
      constructor(props){
        super(props);
        
        this.state = {
          code: this.props.children,
          output: "",
          theme: 'tomorrow-night-bright',
          error: ""
        };
      }
      updateCode(e) {
        this.setState({
          code: e
        });
      }
      toggleTheme() {
        let newTheme = this.state.theme == 'tomorrow-night-bright' ? 'default' : 'tomorrow-night-bright';
        this.setState({
          theme: newTheme
        });
      }
      evalCode() {
        let newOutput = "";
        let code = this.state.code.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$|(<script>)|eval|XMLHttpRequest|document\.write/gm,"");
        try{
          newOutput = (() => {return eval(code)})();
        } catch(e) {
          newOutput = "";
        }
        let error = "";
        if(this.props.test) {
          let include = this.props.test.include;
          let notInclude = this.props.test.notInclude || [];
          let expectedOutput = this.props.test.output;
          include = include.map(item => code.indexOf(item).toString());
          notInclude = notInclude.map(item => code.indexOf(item).toString());
          
          if(include.indexOf("-1") != -1) {
            console.log("You did not use the necessary items in this exercise.");
            error = <div className="editorError">You did not use the necessary items in this exercise.</div>;
          } else if(notInclude.indexOf("-1") == -1) {
            console.log("You still have some of following keywords in your program: " + notInclude);
            error = <div className="editorError">You still have some of following keywords in your program: {notInclude}</div>;
          } else if(_.isEqual(newOutput,expectedOutput) === false) {
            console.log("Oops, it looks like your output does not match expected output.");
            error = <div className="editorError">Oops, it looks like your output does not match expected output.</div>;
          } else {
            error = <div className="editorSuccess">Good Job!</div>;
          }
        }
        this.setState({
          output: newOutput,
          error: error
        });
      }
      render() {
        let outputClass = 'editorOutput';
        let buttonsClass = 'editorButtons';
        if(this.state.theme == 'default'){
          outputClass = 'editorOutput lightEditorOutput';
          buttonsClass = 'editorButtons lightEditorButtons';
        }
        
        let options = {
          lineNumbers: true,
          mode: 'javascript',
          theme: this.state.theme,
          scrollbarStyle: 'null',
          lineWrapping: true,
          lint: true,
          gutters: [
            'CodeMirror-lint-markers',
          ]
          
        };
        return (
          <div className="editorContainer">
          <div className={buttonsClass}>
            <button onClick={this.evalCode.bind(this)}>Run</button>
            <button onClick={this.toggleTheme.bind(this)}>Toggle Light/Dark</button>
            {this.state.error}
          </div>
          <CodeMirror ref="editor" className="editor" value={this.state.code} onChange={this.updateCode.bind(this)} options={options}/>
          <div className={outputClass}>
            <small style={{color: "red",fontSize: "10px"}}>Output</small><br/>{JSON.stringify(this.state.output)}
          </div>
          </div>
        );
      }
    }
    
    export default CodeEditor;
    

    Result Editor image

    Reviewed by edwin0258 at 2017-02-16 21:37
  • 5. Re-setting options on an existing instance can have side effects

    I've found that react-codemirror seems incompatible with proper usage of the lint add-on to CodeMirror.

    The way to activate linting is to set it as an option, e.g.

    CodeMirror.fromTextArea([…], {
      lint: {
        predef: ["window"]
      }
    });
    

    lint's default behavior is to respond to onChange events (debounced and on a 500ms delay), but when it's first initialized, it runs immediately on the current editor value. react-codemirror's approach to setting all of the options whenever the component updates effectively causes lint to fire on every editor change (with no delay) because setting the lint option re-initializes it, even if the option provided is the same.

    I have a proof-of-concept that addresses this problem by comparing the editor's existing option values to the new option values on each update, and only setting each option if it's different. But, I'm waiting to hear about #49 because the underlying bug behind that pull request prevents options from being applied correctly to multiple instances of CodeMirror.

    The approach I had in mind is a bit of a kludge, but I think JSON.stringify would suffice as a way to compare option values quickly:

    setCodeMirrorOptionIfChanged: function(optionName, newValue) {
        var oldValue = this.codeMirror.getOption(optionName);
        if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) {
            this.codeMirror.setOption(optionName, newValue);
        }
    },
    
    Reviewed by attaboy at 2016-06-08 02:45
  • 6. Server-Side Rendering?

    Any thoughts on how we could integrate this with server-side rendering?

    React-code-mirror has a nice approach of simply generating a textarea with the content and then having codemirror hot-load over it once on the client.

    Reviewed by isTravis at 2015-11-11 00:02
  • 7. Make debounce specific to the instance

    Resubmission of #49

    Elected to resubmit rather than rebase because

    1. Code was extremely stale
    2. Easier to undo my changes to the lib folder, which I assume you don't want

    Also noticed that #66 proposes the same change as this does, but it also needs rebasing. @JedWatson I'll leave it up to you which one you prefer, but assuming you use this one, let's get it before it goes stale again!

    Reviewed by sslotsky at 2016-09-20 18:29
  • 8. ES6 compatibility

    I'm trying to use react-codemirror in my ES6 project but it fails.

    Importing it that way:

    import CodeMirror from 'react-codemirror';
    

    Getting the following error:

    [0] ./~/react-codemirror/src/codemirror.js
    [0] Module parse failed: app/node_modules/react-codemirror/src/codemirror.js Unexpected token (76:3)
    [0] You may need an appropriate loader to handle this file type.
    [0] SyntaxError: Unexpected token (76:3)
    ...
    [0]  @ ./~/react-codemirror/lib/Codemirror.js 20:42-63
    

    Am I doing something wrong or is the project not compatible yet?

    Reviewed by jgautheron at 2016-05-22 22:12
  • 9. Set new options only if their values are different from the old ones

    This patch makes it possible to use react-codemirror with codemirror's lint plugin, which otherwise doesn't work (see #89 and #53). It does this by only re-setting options on the codemirror instance when the values differ from those already set. I added a set of basic "deep equal" tools to ensure that this works correctly.

    Reviewed by attaboy at 2017-03-15 15:07
  • 10. When multiple Codemirror components exist on a page, only one can change the language

    I have a page that renders multiple instances of this component:

    import React, { PropTypes, Component } from 'react'
    import CodeMirror from 'react-codemirror'
    import 'codemirror/mode/jsx/jsx'
    import 'codemirror/mode/javascript/javascript'
    import 'codemirror/mode/ruby/ruby'
    
    export class Snippet extends Component {
      static propTypes = {
        language: PropTypes.object,
        text: PropTypes.object
      }
    
      handleChange(text) {
        this.props.text.onChange(text)
      }
    
      changeLanguage(e) {
        this.props.language.onChange(e.target.value)
      }
    
      render() {
        return (
          <div>
            <select value={this.props.language.value} onChange={::this.changeLanguage}>
              <option value='jsx'>JSX</option>
              <option value='javascript'>JavaScript</option>
              <option value='ruby'>Ruby</option>
            </select>
            <CodeMirror options={{ mode: this.props.language.value, theme: 'erlang-dark' }} value={this.props.text.value} onChange={::this.handleChange} />
          </div>
        )
      }
    }
    

    It renders one for each entry in an array. The very bottom instance works perfectly. When I change my selection in the language dropdown, I can see the highlighting change as I expect. But all instances above the bottom instance reflect no change when I change their corresponding dropdown select.

    There are no errors whatsoever. The CodeMirror instances seem to just be quietly ignoring the language change.

    Reviewed by sslotsky at 2016-04-28 03:19
  • 11. Allow code mirror instance to be set via prop

    This change allows react-codemirror to use codemirror instances that are extended with addons such as matchbrackets and comment. This also addresses issue #30.

    Reviewed by stuhlmueller at 2016-01-27 22:36
  • 12. Support React 17

    Overview

    Hello! I was curious if React 17 support was on the roadmap to be added to react-codemirror? Thanks!

    Package versions

    react-codemirror version: @latest

    Reviewed by chrisgbaker at 2021-12-03 15:42
  • 13. Codemirror syntax highlighting works in preview but not when published

    This plugin looks really great but I can seem to get it to appear correct when published. I have checked through the settings and see nothing that can help me. Appreciate any help, thank you

    syntax not highlighting syntax highlighting

    Reviewed by resassured at 2021-02-06 17:58
  • 14. New project with react-codemirror on typescript

    Guys, it seems that this project is not being developed anymore. That's why for my needs I made a new one: https://github.com/atassis/react-codemirror-ts If you see any issues or features to be done- call me out.

    Reviewed by atassis at 2020-12-09 07:16
  • 15. lineNumbers show in preview codemirror

    Hi, First of all, thank you. I when enable lineNumbers: true in code, line numbers showing to output. Please see screenshot https://imgur.com/nGfIqcy

    thx

    Reviewed by itroz at 2020-05-30 17:14
✏️ A very simple but useful Markdown Previewer and Markdown Editor with CodeMirror, Markedjs, and Create-react-app

Markdown Editor A very simple but useful Markdown Previewer and Markdown Editor with CodeMirror, Markedjs and Create-react-app Preview Markdown Editor

Apr 7, 2022
Codemirror integrated components for React

react-codemirror2 demo @ scniro.github.io/react-codemirror2 Install npm install react-codemirror2 codemirror --save react-codemirror2 ships with the n

May 9, 2022
Official CKEditor 4 React component.
Official CKEditor 4 React component.

CKEditor 4 WYSIWYG editor component for React Official CKEditor 4 WYSIWYG editor component for React. We are looking forward to your feedback! You can

May 13, 2022
Official CKEditor 5 React component.

CKEditor 5 rich text editor component for React Official CKEditor 5 rich text editor component for React. Developer Documentation ?? See the "Rich tex

May 16, 2022
React Ace Component

React-Ace A set of react components for Ace NOTE FOR VERSION 8! : We have stopped support for Brace and now use Ace-builds. Please read the documentat

May 12, 2022
React component for a div with editable contents

react-contenteditable React component for a div with editable contents Install npm install react-contenteditable Usage import React from 'react' impor

May 13, 2022
A Quill component for React.

ReactQuill A Quill component for React. See a live demo or Codepen. Quick Start With webpack or create-react-app With the browser bundle Usage Control

May 15, 2022
Drag-n-Drop Email Editor Component for React.js
Drag-n-Drop Email Editor Component for React.js

The excellent drag-n-drop email editor by Unlayer as a React.js wrapper component. This is the most powerful and developer friendly visual email builder for your app.

May 13, 2022
Monaco Editor component for React.
Monaco Editor component for React.

Monaco Editor component for React.

May 10, 2022
The react-web-editor is a WYSIWYG editor library. you can resize and drag your component. It also has simple rich text editor
The react-web-editor is a WYSIWYG editor library. you can resize and drag your component. It also has simple rich text editor

react-web-editor A Simple WYSIWYG editor for react users You can make your own editor using our library You can explore various features on the websit

May 9, 2022
Editable Text Component for React Apps
Editable Text Component for React Apps

react-editext Editable Text Component for React Applications This project is generated from react-typescript-library template. Install npm install --s

May 1, 2022
⚛️📝The unofficial editor-js component for React
⚛️📝The unofficial editor-js component for React

?? DEMO CodeSandbox ?? Supported Official Plugin Paragraph (default) Embed Table List Warning Code Link Image Raw Header Quote Marker CheckList Delimi

May 13, 2022
A React component to make correcting automated transcriptions of audio and video easier and faster. By BBC News Labs. - Work in progress

React Transcript Editor A React component to make transcribing audio and video easier and faster. The project uses [this github project boards to orga

Apr 21, 2022
A ubb editor component based on react

react-ubb-editor A ubb editor based on react See more at https://asukasong.github.io/react-ubb-editor/ Install with yarn yarn add @cc98/react-ubb-edit

Sep 14, 2020
React component for Froala WYSIWYG HTML Rich Text Editor.

React JS Froala WYSIWYG Editor react-froala-wyswiyg provides React bindings to the Froala WYSIWYG editor VERSION 3. Installation npm install react-fro

May 12, 2022
Teselagen's Open Source Vector/Plasmid Editor Component
 Teselagen's Open Source Vector/Plasmid Editor Component

Congrats, you've made it to the repo for Teselagen's Open Source Vector Editor Component Built With React & Redux Built for easy extensibility + embed

Apr 30, 2022
Monaco Editor for React - use the monaco-editor in any React application

Monaco Editor for React - use the monaco-editor in any React application without needing to use webpack (or rollup/parcel/etc) configuration files / plugins

May 11, 2022
React Trix rich text editor is react wrapper built for the Trix editor
React Trix rich text editor is react wrapper built for the Trix editor

React wrapper for Trix rich text editor created by Basecamp

Apr 4, 2022
A React framework for building text editors.
A React framework for building text editors.

Draft.js Draft.js is a JavaScript rich text editor framework, built for React and backed by an immutable model. Extensible and Customizable: We provid

May 15, 2022