0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-24 22:52:40 +00:00
Files
homebrewery/shared/naturalcrit/codeEditor/codeEditor.jsx
2021-09-11 00:12:58 -05:00

187 lines
6.3 KiB
JavaScript

require('./codeEditor.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
let CodeMirror;
if(typeof navigator !== 'undefined'){
CodeMirror = require('codemirror');
//Language Modes
require('codemirror/mode/gfm/gfm.js'); //Github flavoured markdown
require('codemirror/mode/css/css.js');
require('codemirror/mode/javascript/javascript.js');
}
const CodeEditor = createClass({
getDefaultProps : function() {
return {
language : '',
value : '',
wrap : true,
onChange : ()=>{}
};
},
componentDidMount : function() {
this.buildEditor();
},
componentDidUpdate : function(prevProps) {
if(prevProps.language !== this.props.language){ //rebuild editor when switching tabs
this.buildEditor();
}
if(this.codeMirror && this.codeMirror.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside
this.codeMirror.setValue(this.props.value);
}
},
buildEditor : function() {
this.codeMirror = CodeMirror(this.refs.editor, {
value : this.props.value,
lineNumbers : true,
lineWrapping : this.props.wrap,
mode : this.props.language, //TODO: CSS MODE DOESN'T SEEM TO LOAD PROPERLY
indentWithTabs : true,
tabSize : 2,
extraKeys : {
'Ctrl-B' : this.makeBold,
'Cmd-B' : this.makeBold,
'Ctrl-I' : this.makeItalic,
'Cmd-I' : this.makeItalic,
'Ctrl-U' : this.makeUnderline,
'Cmd-U' : this.makeUnderline,
'Ctrl-.' : this.makeNbsp,
'Cmd-.' : this.makeNbsp,
'Shift-Ctrl-.' : this.makeSpace,
'Shift-Cmd-.' : this.makeSpace,
'Shift-Ctrl-,' : this.removeSpace,
'Shift-Cmd-,' : this.removeSpace,
'Shift-Ctrl-Enter' : this.newColumn,
'Shift-Cmd-Enter' : this.newColumn,
'Ctrl-Enter' : this.newPage,
'Cmd-Enter' : this.newPage,
'Ctrl-M' : this.makeSpan,
'Cmd-M' : this.makeSpan,
'Shift-Ctrl-M' : this.makeDiv,
'Shift-Cmd-M' : this.makeDiv,
'Ctrl-/' : this.makeComment,
'Cmd-/' : this.makeComment
}
});
// Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror. Either one works.
this.codeMirror.on('change', (cm)=>{this.props.onChange(cm.getValue());});
this.updateSize();
},
makeBold : function() {
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '**' && selection.slice(-2) === '**';
this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `**${selection}**`, 'around');
if(selection.length === 0){
const cursor = this.codeMirror.getCursor();
this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
}
},
makeItalic : function() {
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 1) === '*' && selection.slice(-1) === '*';
this.codeMirror.replaceSelection(t ? selection.slice(1, -1) : `*${selection}*`, 'around');
if(selection.length === 0){
const cursor = this.codeMirror.getCursor();
this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 1 });
}
},
makeNbsp : function() {
this.codeMirror.replaceSelection(' ', 'end');
},
makeSpace : function() {
const selection = this.codeMirror.getSelection();
const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}';
if(t){
const percent = parseInt(selection.slice(8, -4)) + 10;
this.codeMirror.replaceSelection(percent < 90 ? `{{width:${percent}% }}` : '{{width:100% }}', 'around');
} else {
this.codeMirror.replaceSelection(`{{width:10% }}`, 'around');
}
},
removeSpace : function() {
const selection = this.codeMirror.getSelection();
const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}';
if(t){
const percent = parseInt(selection.slice(8, -4)) - 10;
this.codeMirror.replaceSelection(percent > 10 ? `{{width:${percent}% }}` : '', 'around');
}
},
newColumn : function() {
this.codeMirror.replaceSelection('\n\\column\n\n', 'end');
},
newPage : function() {
this.codeMirror.replaceSelection('\n\\page\n\n', 'end');
},
makeUnderline : function() {
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 3) === '<u>' && selection.slice(-4) === '</u>';
this.codeMirror.replaceSelection(t ? selection.slice(3, -4) : `<u>${selection}</u>`, 'around');
if(selection.length === 0){
const cursor = this.codeMirror.getCursor();
this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 4 });
}
},
makeSpan : function() {
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `{{ ${selection}}}`, 'around');
if(selection.length === 0){
const cursor = this.codeMirror.getCursor();
this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
}
},
makeDiv : function() {
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `{{\n${selection}\n}}`, 'around');
if(selection.length === 0){
const cursor = this.codeMirror.getCursor();
this.codeMirror.setCursor({ line: cursor.line - 1, ch: cursor.ch }); // set to -2? if wanting to enter classes etc. if so, get rid of first \n when replacing selection
}
},
makeComment : function() {
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 4) === '<!--' && selection.slice(-3) === '-->';
this.codeMirror.replaceSelection(t ? selection.slice(4, -3) : `<!-- ${selection} -->`, 'around');
if(selection.length === 0){
const cursor = this.codeMirror.getCursor();
this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 4 });
}
},
//=-- Externally used -==//
setCursorPosition : function(line, char){
setTimeout(()=>{
this.codeMirror.focus();
this.codeMirror.doc.setCursor(line, char);
}, 10);
},
getCursorPosition : function(){
return this.codeMirror.getCursor();
},
updateSize : function(){
this.codeMirror.refresh();
},
//----------------------//
render : function(){
return <div className='codeEditor' ref='editor' />;
}
});
module.exports = CodeEditor;