2016-06-27 22:03:22 +02:00
import React , { PropTypes } from 'react' ;
2016-06-24 00:29:55 +02:00
import CodeMirror from 'codemirror' ;
import 'codemirror/mode/javascript/javascript' ;
2016-07-14 01:52:50 +02:00
import 'codemirror/mode/css/css' ;
import 'codemirror/mode/htmlmixed/htmlmixed' ;
2016-06-24 00:29:55 +02:00
import 'codemirror/addon/selection/active-line' ;
2016-07-12 23:38:24 +02:00
import 'codemirror/addon/lint/lint' ;
import 'codemirror/addon/lint/javascript-lint' ;
2016-07-14 01:52:50 +02:00
import 'codemirror/addon/lint/css-lint' ;
import 'codemirror/addon/lint/html-lint' ;
2016-07-21 20:33:23 +02:00
import 'codemirror/addon/comment/comment' ;
import 'codemirror/keymap/sublime' ;
2016-08-05 22:58:59 +02:00
import 'codemirror/addon/search/jump-to-line' ;
2016-07-12 23:38:24 +02:00
import { JSHINT } from 'jshint' ;
window . JSHINT = JSHINT ;
2016-07-14 01:52:50 +02:00
import { CSSLint } from 'csslint' ;
window . CSSLint = CSSLint ;
import { HTMLHint } from 'htmlhint' ;
window . HTMLHint = HTMLHint ;
2016-06-24 00:29:55 +02:00
2016-07-14 03:50:59 +02:00
import { debounce } from 'throttle-debounce' ;
2016-06-24 00:29:55 +02:00
class Editor extends React . Component {
componentDidMount ( ) {
this . _cm = CodeMirror ( this . refs . container , { // eslint-disable-line
theme : 'p5-widget' ,
2016-07-08 21:58:49 +02:00
value : this . props . file . content ,
2016-06-24 00:29:55 +02:00
lineNumbers : true ,
styleActiveLine : true ,
2016-07-13 17:59:47 +02:00
inputStyle : 'contenteditable' ,
2016-07-12 21:58:11 +02:00
mode : 'javascript' ,
2016-07-12 23:38:24 +02:00
lineWrapping : true ,
gutters : [ 'CodeMirror-lint-markers' ] ,
2016-07-21 20:33:23 +02:00
lint : true ,
2016-08-05 22:58:59 +02:00
keyMap : 'sublime' ,
lint : {
onUpdateLinting : ( annotations ) => {
document . getElementById ( 'editor-lintmessages' ) . innerHTML = '' ;
annotations . forEach ( function ( x ) {
document . getElementById ( 'editor-lintmessages' ) . innerHTML += ( x . severity + ' in line number ' + ( x . from . line + 1 ) + ' : ' + x . message ) ; } ) ; // eslint-disable-line
}
}
2016-06-24 00:29:55 +02:00
} ) ;
2016-07-14 03:50:59 +02:00
this . _cm . on ( 'change' , debounce ( 200 , ( ) => {
2016-07-08 21:58:49 +02:00
this . props . updateFileContent ( this . props . file . name , this . _cm . getValue ( ) ) ;
2016-07-14 03:50:59 +02:00
} ) ) ;
2016-08-05 22:58:59 +02:00
this . _cm . on ( 'keyup' , ( ) => {
document . getElementById ( 'editor-linenumber' ) . innerHTML = parseInt ( ( this . _cm . getCursor ( ) . line ) + 1 , 10 ) ;
} ) ;
2016-07-14 03:50:59 +02:00
// this._cm.on('change', () => { // eslint-disable-line
// // this.props.updateFileContent('sketch.js', this._cm.getValue());
// throttle(1000, () => console.log('debounce is working!'));
// this.props.updateFileContent(this.props.file.name, this._cm.getValue());
// });
2016-06-24 00:29:55 +02:00
this . _cm . getWrapperElement ( ) . style [ 'font-size' ] = ` ${ this . props . fontSize } px ` ;
2016-07-11 05:11:06 +02:00
this . _cm . setOption ( 'indentWithTabs' , this . props . isTabIndent ) ;
2016-07-11 15:00:44 +02:00
this . _cm . setOption ( 'tabSize' , this . props . indentationAmount ) ;
2016-06-24 00:29:55 +02:00
}
componentDidUpdate ( prevProps ) {
2016-08-05 22:58:59 +02:00
const annotations = this . _cm . state . lint . marked ;
annotations . forEach ( function ( x ) { console . log ( x . _ _annotation . severity + ' in line number ' + ( x . _ _annotation . from . line + 1 ) + ' : ' + x . _ _annotation . message ) ; } ) ; // eslint-disable-line
2016-07-08 21:58:49 +02:00
if ( this . props . file . content !== prevProps . file . content &&
this . props . file . content !== this . _cm . getValue ( ) ) {
this . _cm . setValue ( this . props . file . content ) ; // eslint-disable-line no-underscore-dangle
2016-06-24 00:29:55 +02:00
}
if ( this . props . fontSize !== prevProps . fontSize ) {
this . _cm . getWrapperElement ( ) . style [ 'font-size' ] = ` ${ this . props . fontSize } px ` ;
}
2016-07-06 17:27:39 +02:00
if ( this . props . indentationAmount !== prevProps . indentationAmount ) {
this . _cm . setOption ( 'tabSize' , this . props . indentationAmount ) ;
}
2016-07-11 05:11:06 +02:00
if ( this . props . isTabIndent !== prevProps . isTabIndent ) {
this . _cm . setOption ( 'indentWithTabs' , this . props . isTabIndent ) ;
}
2016-07-14 01:52:50 +02:00
if ( this . props . file . name !== prevProps . name ) {
if ( this . props . file . name . match ( /.+\.js$/ ) ) {
this . _cm . setOption ( 'mode' , 'javascript' ) ;
} else if ( this . props . file . name . match ( /.+\.css$/ ) ) {
this . _cm . setOption ( 'mode' , 'css' ) ;
} else if ( this . props . file . name . match ( /.+\.html$/ ) ) {
this . _cm . setOption ( 'mode' , 'htmlmixed' ) ;
}
}
2016-06-24 00:29:55 +02:00
}
componentWillUnmount ( ) {
this . _cm = null ;
}
_cm : CodeMirror . Editor
render ( ) {
2016-08-05 22:58:59 +02:00
return (
< div ref = "container" className = "editor-holder" tabIndex = "0" title = "code editor" role = "region" >
< / d i v >
) ;
2016-06-24 00:29:55 +02:00
}
}
2016-06-27 22:03:22 +02:00
Editor . propTypes = {
2016-07-11 04:52:48 +02:00
indentationAmount : PropTypes . number . isRequired ,
2016-07-12 05:40:30 +02:00
isTabIndent : PropTypes . bool . isRequired ,
updateFileContent : PropTypes . func . isRequired ,
fontSize : PropTypes . number . isRequired ,
2016-07-08 21:58:49 +02:00
file : PropTypes . shape ( {
name : PropTypes . string . isRequired ,
content : PropTypes . string . isRequired
2016-07-12 05:40:30 +02:00
} )
2016-06-27 22:03:22 +02:00
} ;
2016-06-24 00:29:55 +02:00
export default Editor ;