├── .gitignore
├── LICENSE
├── README.md
├── build.js
├── example
├── browserify
│ ├── app.js
│ ├── index.html
│ ├── index.js
│ └── server.js
└── standalone
│ ├── app.js
│ └── index.html
├── index.js
├── package.json
└── standalone.js
/.gitignore:
--------------------------------------------------------------------------------
1 | lib-cov
2 | *.seed
3 | *.log
4 | *.csv
5 | *.dat
6 | *.out
7 | *.pid
8 | *.gz
9 | pids
10 | logs
11 | results
12 | npm-debug.log
13 | node_modules
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Forbes Lindesay
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-code-mirror
2 |
3 | Deprecated. Use https://github.com/scniro/react-codemirror2
4 |
5 | ## Installation
6 |
7 | npm install react-code-mirror
8 |
9 | If you're not using browserify/node you can also just load the standalone.js file (having first loaded CodeMirror and React.
10 |
11 | ## Usage
12 |
13 | See example folder
14 |
15 | It can also render server side, providing you don't `require('codemirror')` anywhere on the server. If you render server side it will just render the mobile view (i.e. a textarea) that will get upgraded to the full CodeMirror editor on the client.
16 |
17 | ## License
18 |
19 | MIT
20 |
--------------------------------------------------------------------------------
/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 |
5 | var src = fs.readFileSync(__dirname + '/index.js', 'utf8');
6 |
7 | src = src.replace(/^(.)/gm, ' $1');
8 | src = 'CodeMirrorEditor = (function (require, module) {\n' + src + '\n return module.exports;\n}(function (id) {\n' +
9 | ' if (id === "react") return React;\n' +
10 | ' else if (id === "codemirror") return CodeMirror;\n' +
11 | ' else throw new Error("Unexpected require of " + id);' +
12 | '\n}, {exports: {}}));';
13 | src = '// auto-generated from index.js via build.js, do not edit directly\n' + src;
14 |
15 | fs.writeFileSync(__dirname + '/standalone.js', src);
16 |
--------------------------------------------------------------------------------
/example/browserify/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react');
4 | var CodeMirror = React.createFactory(require('../../'));
5 |
6 | var div = React.createFactory('div');
7 | var h1 = React.createFactory('h1');
8 | var p = React.createFactory('p');
9 | var pre = React.createFactory('pre');
10 | var code = React.createFactory('code');
11 |
12 | module.exports = React.createClass({
13 | getInitialState: function () {
14 | return {
15 | src: 'function add(a, b) {\n' +
16 | ' return a + b;\n' +
17 | '}'
18 | };
19 | },
20 | render: function () {
21 | return div({},
22 | h1({}, 'Using "defaultValue"'),
23 | p({}, 'This creates an editable code mirror editor, as you would expect. ' +
24 | 'Note that it will not respond to changes in the model though.'),
25 | CodeMirror({
26 | style: {border: '1px solid black'},
27 | textAreaClassName: ['form-control'],
28 | textAreaStyle: {minHeight: '10em'},
29 | defaultValue: this.state.src,
30 | mode: 'javascript',
31 | theme: 'solarized',
32 | lineNumbers: true
33 | }),
34 | h1({}, 'Using "value" and no "onChange"'),
35 | p({}, 'This creates a read only code mirror editor that responds to changes.'),
36 | CodeMirror({
37 | style: {border: '1px solid black'},
38 | textAreaClassName: ['form-control'],
39 | textAreaStyle: {minHeight: '10em'},
40 | value: this.state.src,
41 | mode: 'javascript',
42 | theme: 'solarized',
43 | lineNumbers: true,
44 | readOnly: true
45 | }),
46 | h1({}, 'Using "value" with "onChange"'),
47 | p({}, 'This creates a typical, editable code mirror editor that responds to changes.'),
48 | CodeMirror({
49 | style: {border: '1px solid black'},
50 | textAreaClassName: ['form-control'],
51 | textAreaStyle: {minHeight: '10em'},
52 | value: this.state.src,
53 | mode: 'javascript',
54 | theme: 'solarized',
55 | lineNumbers: true,
56 | onChange: function (e) {
57 | this.setState({src: e.target.value});
58 | }.bind(this)
59 | }),
60 | h1({}, 'Using the forceTextArea option'),
61 | p({}, 'This is the default fallback option for mobile browsers and works seamlessly.'),
62 | CodeMirror({
63 | forceTextArea: true,
64 | textAreaClassName: ['form-control'],
65 | textAreaStyle: {minHeight: '10em'},
66 | value: this.state.src,
67 | mode: 'javascript',
68 | theme: 'solarized',
69 | lineNumbers: true,
70 | onChange: function (e) {
71 | this.setState({src: e.target.value});
72 | }.bind(this)
73 | }),
74 | h1({}, 'Just a pre/code'),
75 | p({}, 'Just so you can see the output.'),
76 | pre({}, code({}, this.state.src))
77 | );
78 | }
79 | });
80 |
--------------------------------------------------------------------------------
/example/browserify/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/browserify/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react');
4 | var ReactDOM = require('react-dom');
5 | var Application = require('./app.js');
6 | require('codemirror/mode/javascript/javascript');
7 |
8 | ReactDOM.render(React.createElement(Application), document.getElementById('container'));
9 |
--------------------------------------------------------------------------------
/example/browserify/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var assert = require('assert');
4 | var fs = require('fs');
5 | var React = require('react');
6 | var ReactDOMServer = require('react-dom/server');
7 | var express = require('express');
8 | var browserify = require('browserify-middleware');
9 | var Application = require('./app');
10 |
11 | var app = express();
12 |
13 | app.get('/', function (req, res) {
14 | var html = fs.readFileSync(__dirname + '/index.html', 'utf8');
15 | html = html.replace('{{component}}', ReactDOMServer.renderToString(React.createElement(Application)));
16 | res.send(html);
17 | });
18 | app.get('/index.js', browserify(__dirname + '/index.js'));
19 | app.get('/codemirror.css', function (req, res) {
20 | res.sendFile(require.resolve('codemirror/lib/codemirror.css'));
21 | });
22 | app.get('/codemirror/theme/:theme.css', function (req, res) {
23 | assert(/^[a-z0-9\-]+$/.test(req.params.theme));
24 | res.sendFile(require.resolve('codemirror/theme/' + req.params.theme + '.css'));
25 | });
26 |
27 | app.listen(3000);
28 |
--------------------------------------------------------------------------------
/example/standalone/app.js:
--------------------------------------------------------------------------------
1 | ;(function () {
2 | 'use strict';
3 |
4 | var CodeMirror = React.createFactory(CodeMirrorEditor);
5 | var div = React.createFactory('div');
6 | var h1 = React.createFactory('h1');
7 | var p = React.createFactory('p');
8 | var pre = React.createFactory('pre');
9 | var code = React.createFactory('code');
10 |
11 | var Application = React.createClass({
12 | getInitialState: function () {
13 | return {
14 | src: 'function add(a, b) {\n' +
15 | ' return a + b;\n' +
16 | '}'
17 | };
18 | },
19 | render: function () {
20 | return div({},
21 | h1({}, 'Using "defaultValue"'),
22 | p({}, 'This creates an editable code mirror editor, as you would expect. ' +
23 | 'Note that it will not respond to changes in the model though.'),
24 | CodeMirror({
25 | style: {border: '1px solid black'},
26 | textAreaClassName: ['form-control'],
27 | textAreaStyle: {minHeight: '10em'},
28 | defaultValue: this.state.src,
29 | mode: 'javascript',
30 | theme: 'solarized',
31 | lineNumbers: true
32 | }),
33 | h1({}, 'Using "value" and no "onChange"'),
34 | p({}, 'This creates a read only code mirror editor that responds to changes.'),
35 | CodeMirror({
36 | style: {border: '1px solid black'},
37 | textAreaClassName: ['form-control'],
38 | textAreaStyle: {minHeight: '10em'},
39 | value: this.state.src,
40 | mode: 'javascript',
41 | theme: 'solarized',
42 | lineNumbers: true,
43 | readOnly: true
44 | }),
45 | h1({}, 'Using "value" with "onChange"'),
46 | p({}, 'This creates a typical, editable code mirror editor that responds to changes.'),
47 | CodeMirror({
48 | style: {border: '1px solid black'},
49 | textAreaClassName: ['form-control'],
50 | textAreaStyle: {minHeight: '10em'},
51 | value: this.state.src,
52 | mode: 'javascript',
53 | theme: 'solarized',
54 | lineNumbers: true,
55 | onChange: function (e) {
56 | this.setState({src: e.target.value});
57 | }.bind(this)
58 | }),
59 | h1({}, 'Using the forceTextArea option'),
60 | p({}, 'This is the default fallback option for mobile browsers and works seamlessly.'),
61 | CodeMirror({
62 | forceTextArea: true,
63 | textAreaClassName: ['form-control'],
64 | textAreaStyle: {minHeight: '10em'},
65 | value: this.state.src,
66 | mode: 'javascript',
67 | theme: 'solarized',
68 | lineNumbers: true,
69 | onChange: function (e) {
70 | this.setState({src: e.target.value});
71 | }.bind(this)
72 | }),
73 | h1({}, 'Just a pre/code'),
74 | p({}, 'Just so you can see the output.'),
75 | pre({}, code({}, this.state.src))
76 | );
77 | }
78 | });
79 |
80 | React.render(React.createElement(Application), document.getElementById('container'));
81 | }());
82 |
--------------------------------------------------------------------------------
/example/standalone/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react');
4 | var CodeMirror;
5 |
6 | // adapted from:
7 | // https://github.com/facebook/react/blob/master/docs/_js/live_editor.js#L16
8 |
9 | // also used as an example:
10 | // https://github.com/facebook/react/blob/master/src/browser/ui/dom/components/ReactDOMInput.js
11 |
12 | var IS_MOBILE = typeof navigator === 'undefined' || (
13 | navigator.userAgent.match(/Android/i)
14 | || navigator.userAgent.match(/webOS/i)
15 | || navigator.userAgent.match(/iPhone/i)
16 | || navigator.userAgent.match(/iPad/i)
17 | || navigator.userAgent.match(/iPod/i)
18 | || navigator.userAgent.match(/BlackBerry/i)
19 | || navigator.userAgent.match(/Windows Phone/i)
20 | );
21 |
22 | if (!IS_MOBILE) {
23 | CodeMirror = require('codemirror');
24 | }
25 |
26 | var CodeMirrorEditor = React.createClass({
27 | getInitialState: function() {
28 | return { isControlled: this.props.value != null };
29 | },
30 |
31 | propTypes: {
32 | value: React.PropTypes.string,
33 | defaultValue: React.PropTypes.string,
34 | style: React.PropTypes.object,
35 | className: React.PropTypes.string,
36 | onChange: React.PropTypes.func
37 | },
38 |
39 | componentDidMount: function() {
40 | var isTextArea = this.props.forceTextArea || IS_MOBILE;
41 | if (!isTextArea) {
42 | var editor = this.refs.editor;
43 | if (!editor.getAttribute) editor = editor.getDOMNode();
44 | this.editor = CodeMirror.fromTextArea(editor, this.props);
45 | this.editor.on('change', this.handleChange);
46 | }
47 | },
48 |
49 | componentDidUpdate: function() {
50 | if (this.editor) {
51 | if (this.props.value != null) {
52 | if (this.editor.getValue() !== this.props.value) {
53 | this.editor.setValue(this.props.value);
54 | }
55 | }
56 | }
57 | },
58 |
59 | handleChange: function() {
60 | if (this.editor) {
61 | var value = this.editor.getValue();
62 | if (value !== this.props.value) {
63 | this.props.onChange && this.props.onChange({target: {value: value}});
64 | if (this.editor.getValue() !== this.props.value) {
65 | if (this.state.isControlled) {
66 | this.editor.setValue(this.props.value);
67 | } else {
68 | this.props.value = value;
69 | }
70 | }
71 | }
72 | }
73 | },
74 |
75 | render: function() {
76 | var editor = React.createElement('textarea', {
77 | ref: 'editor',
78 | value: this.props.value,
79 | readOnly: this.props.readOnly,
80 | defaultValue: this.props.defaultValue,
81 | onChange: this.props.onChange,
82 | style: this.props.textAreaStyle,
83 | className: this.props.textAreaClassName || this.props.textAreaClass
84 | });
85 |
86 | return React.createElement('div', {style: this.props.style, className: this.props.className}, editor);
87 | }
88 | });
89 |
90 | module.exports = CodeMirrorEditor;
91 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-code-mirror",
3 | "version": "3.1.0",
4 | "description": "CodeMirror component for Facebook React",
5 | "keywords": [
6 | "react",
7 | "react-component"
8 | ],
9 | "peerDependencies": {
10 | "codemirror": ">=4.6.0 <6.0.0",
11 | "react": ">=0.12.0 <16.0.0"
12 | },
13 | "devDependencies": {
14 | "browserify-middleware": "^3.0.1",
15 | "codemirror": "^5.18.2",
16 | "express": "^4.9.5",
17 | "react": "^15.3.1",
18 | "react-dom": "^15.3.1",
19 | "umd": "^2.1.0"
20 | },
21 | "scripts": {
22 | "prepublish": "node build"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/ForbesLindesay/react-code-mirror.git"
27 | },
28 | "author": "ForbesLindesay",
29 | "license": "MIT"
30 | }
--------------------------------------------------------------------------------
/standalone.js:
--------------------------------------------------------------------------------
1 | // auto-generated from index.js via build.js, do not edit directly
2 | CodeMirrorEditor = (function (require, module) {
3 | 'use strict';
4 |
5 | var React = require('react');
6 | var CodeMirror;
7 |
8 | // adapted from:
9 | // https://github.com/facebook/react/blob/master/docs/_js/live_editor.js#L16
10 |
11 | // also used as an example:
12 | // https://github.com/facebook/react/blob/master/src/browser/ui/dom/components/ReactDOMInput.js
13 |
14 | var IS_MOBILE = typeof navigator === 'undefined' || (
15 | navigator.userAgent.match(/Android/i)
16 | || navigator.userAgent.match(/webOS/i)
17 | || navigator.userAgent.match(/iPhone/i)
18 | || navigator.userAgent.match(/iPad/i)
19 | || navigator.userAgent.match(/iPod/i)
20 | || navigator.userAgent.match(/BlackBerry/i)
21 | || navigator.userAgent.match(/Windows Phone/i)
22 | );
23 |
24 | if (!IS_MOBILE) {
25 | CodeMirror = require('codemirror');
26 | }
27 |
28 | var CodeMirrorEditor = React.createClass({
29 | getInitialState: function() {
30 | return { isControlled: this.props.value != null };
31 | },
32 |
33 | propTypes: {
34 | value: React.PropTypes.string,
35 | defaultValue: React.PropTypes.string,
36 | style: React.PropTypes.object,
37 | className: React.PropTypes.string,
38 | onChange: React.PropTypes.func
39 | },
40 |
41 | componentDidMount: function() {
42 | var isTextArea = this.props.forceTextArea || IS_MOBILE;
43 | if (!isTextArea) {
44 | var editor = this.refs.editor;
45 | if (!editor.getAttribute) editor = editor.getDOMNode();
46 | this.editor = CodeMirror.fromTextArea(editor, this.props);
47 | this.editor.on('change', this.handleChange);
48 | }
49 | },
50 |
51 | componentDidUpdate: function() {
52 | if (this.editor) {
53 | if (this.props.value != null) {
54 | if (this.editor.getValue() !== this.props.value) {
55 | this.editor.setValue(this.props.value);
56 | }
57 | }
58 | }
59 | },
60 |
61 | handleChange: function() {
62 | if (this.editor) {
63 | var value = this.editor.getValue();
64 | if (value !== this.props.value) {
65 | this.props.onChange && this.props.onChange({target: {value: value}});
66 | if (this.editor.getValue() !== this.props.value) {
67 | if (this.state.isControlled) {
68 | this.editor.setValue(this.props.value);
69 | } else {
70 | this.props.value = value;
71 | }
72 | }
73 | }
74 | }
75 | },
76 |
77 | render: function() {
78 | var editor = React.createElement('textarea', {
79 | ref: 'editor',
80 | value: this.props.value,
81 | readOnly: this.props.readOnly,
82 | defaultValue: this.props.defaultValue,
83 | onChange: this.props.onChange,
84 | style: this.props.textAreaStyle,
85 | className: this.props.textAreaClassName || this.props.textAreaClass
86 | });
87 |
88 | return React.createElement('div', {style: this.props.style, className: this.props.className}, editor);
89 | }
90 | });
91 |
92 | module.exports = CodeMirrorEditor;
93 |
94 | return module.exports;
95 | }(function (id) {
96 | if (id === "react") return React;
97 | else if (id === "codemirror") return CodeMirror;
98 | else throw new Error("Unexpected require of " + id);
99 | }, {exports: {}}));
--------------------------------------------------------------------------------