You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
educoder/public/react/src/modules/page/component/monaco/TPIMonaco.js

535 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React, { Component } from 'react';
import Dialog, {
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from 'material-ui/Dialog';
import _ from 'lodash'
import Drawer from 'material-ui/Drawer';
import './TPIMonaco.css'
import TPICodeSetting from '../TPICodeSetting'
import * as monaco from 'monaco-editor'
import { fromStore, toStore } from 'educoder'
import './TPIMonacoConfig'
monaco.editor.defineTheme('myCoolTheme', {
base: 'vs-dark',
inherit: true,
rules: [
{ token: 'green', background: 'FF0000', foreground: '00FF00', fontStyle: 'italic'},
{ token: 'red', foreground: 'FF0000' , fontStyle: 'bold underline'},
{ background: '#121c23' },
// { foreground: 'FFFFFF' }
],
// editor_monaco._themeService._knownThemes.get('myCoolTheme')
colors: {
// 'editor.foreground': '#FFFFFF',
'editor.background': '#121c23',
// 'editor.selectionHighlightBorder': '#ffffff',
// 'input.border': '#ffffff',
'editor.lineHighlightBorder': '#222c34', // .current-line
}
});
const $ = window.$;
function loadMonacoResouce(callback) {
let _url_origin = ``;
let prefix = 'react/build'
if (window.location.port == 3007) {
prefix = ''
} else {
// _url_origin = `https://testeduplus2.educoder.net/`;
_url_origin = 'http://pre-newweb.educoder.net';
}
const $ = window.$;
if (!window['monaco']) {
// How to import this library in a create-react-app?
// https://github.com/Microsoft/monaco-editor/issues/82
// window.require = { paths: { 'vs': '../node_modules/monaco-editor/min/vs' } };
// window.require = { paths: { 'vs': `${_url_origin}${prefix}/js/monaco/vs` } };
// $('head').append($('<link rel="stylesheet" type="text/css" />')
// .attr('href', `${_url_origin}${prefix}/js/monaco/vs/editor/editor.main.css`));
// $.ajaxSetup({
// cache: true
// });
// $.when(
// // $.getScript( `${_url_origin}${prefix}/js/monaco/vs/language/typescript/tsMode.js` ),
// // $.getScript( `${_url_origin}${prefix}/js/monaco/vs/basic-languages/javascript/javascript.js` ),
// $.getScript( `${_url_origin}${prefix}/js/monaco/vs/basic-languages/python/python.js` ),
// // $.getScript( `${_url_origin}${prefix}/js/monaco/vs/language/typescript/tsWorker.js` ),
// $.getScript( `${_url_origin}${prefix}/js/monaco/vs/loader.js` ),
// $.getScript( `${_url_origin}${prefix}/js/monaco/vs/editor/editor.main.nls.js` ),
// $.getScript( `${_url_origin}${prefix}/js/monaco/vs/editor/editor.main.js` ),
// $.Deferred(function( deferred ){
// console.log('Deferred')
// // TODO 暂时放这里
// $( deferred.resolve );
// checkIfLoaded(callback);
// })
// ).done(function(){
// debugger;
// // TODO 没执行到这里
// console.log('done done done ')
// //place your code here, the scripts are all loaded
// // callback && callback()
// });
// require.config({ paths: { 'vs': `/monaco/vs` }});
// require(['/vs/editor/editor.main'], function() {
callback && callback()
var editor = monaco.editor.create(document.getElementById('container'), {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('\n'),
language: 'javascript'
});
// });
} else {
callback && callback()
}
}
function checkIfLoaded (callback) {
if (window.monaco && window.monaco.editor) {
$.ajaxSetup({
cache: false
});
callback && callback()
} else {
console.log('check again 2s later..')
setTimeout(() => {
checkIfLoaded(callback)
}, 2000);
}
}
/*
language
javascript css less scss html typescript
java ruby vb r python php perl go cpp csharp
sql pgsql mysql
swift objective-c
shell
redis
xml yaml
markdown
'JFinal': 'text/x-java',
'Java': 'text/x-java',
'Kotlin': 'text/x-kotlin',
'C/C++' : 'text/x-c++src',
'MachineLearning': {
name: "python",
version: 3,
singleLineStringErrors: false
},
'Python2.7': {
name: "python",
version: 3,
singleLineStringErrors: false
},
'Python3.6': {
name: "python",
version: 3,
singleLineStringErrors: false
},
*/
const mirror2LanguageMap = {
'JFinal': 'java',
'Java': 'java',
'JavaWeb': 'java',
'Kotlin': 'java',
'Html': 'html',
'Css': 'css',
'Javascript': 'javascript',
'JavaScript': 'javascript',
'C/C++': 'cpp',
'MachineLearning': 'python',
'Python2.7': 'python',
'Python3.6': 'python',
'C#': 'csharp',
'R': 'r'
}
function getLanguageByMirrorName(mirror_name) {
let lang = 'javascript'
if (mirror_name && mirror_name.length) {
// 需要倒着遍历, html、css的实训主评测语言环境是python小类别是html或css
// TODO http://localhost:3007/tasks/hmcwa3g8typ5?debug=t ["Python3.6", "VNC", "Html"]
for (let i = mirror_name.length - 1; i >= 0; i--) {
let languageVal = mirror2LanguageMap[mirror_name[i]];
if (languageVal) {
lang = languageVal;
break;
}
}
}
return lang;
}
let notCallCodeMirrorOnChangeFlag = false;
/**
props :
mirror_name 决定语言
isEditablePath
repositoryCode
codemirrorDidMount
shixun.forbid_copy
showSettingDrawer, settingDrawerOpen
*/
class TPIMonaco extends Component {
constructor(props) {
super(props)
loadMonacoResouce();
this.state = {
cmFontSize: fromStore('cmFontSize', 16),
autoCompleteSwitch: fromStore('autoCompleteSwitch', true),
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
const { mirror_name } = this.props
const editor_monaco = this.editor_monaco;
if (editor_monaco && !_.isEqual(prevProps.mirror_name, mirror_name)) {
// TODO 后期考虑加入根据文件类型的不同使用不同的lang
const lang = getLanguageByMirrorName(mirror_name);
// https://github.com/Microsoft/monaco-editor/issues/539
window.monaco.editor.setModelLanguage(editor_monaco.getModel(), lang)
} else if (prevProps.isEditablePath != this.props.isEditablePath) {
if (this.props.isEditablePath || this.props.shixun && this.props.shixun.code_edit_permission == true) {
editor_monaco.updateOptions({readOnly: false})
} else {
editor_monaco.updateOptions({readOnly: true})
}
} else if (editor_monaco && prevProps.codeLoading === true && this.props.codeLoading === false
) {
if (this.props.repositoryCode != editor_monaco.getValue()) {
// newProps.repositoryCode !== this.props.repositoryCode &&
notCallCodeMirrorOnChangeFlag = true;
// 重要setState(因获取代码、重置代码等接口引起的调用)调用引起的变化才需要setValue
editor_monaco.setValue(this.props.repositoryCode)
}
// 代码没变也需要layout可能从命令行自动切回了代码tab
editor_monaco.layout();
// Clears the editor's undo history.
// TODO
// extend_editor.clearHistory()
}
}
componentWillUnmount() {
this.editor_monaco && this.editor_monaco.dispose()
}
componentDidMount() {
checkIfLoaded(() => {
let value = [
'define([], function() {',
'\treturn ({p1, p2}) => {',
'\t\treturn Promise.resolve("Hello, World");',
'\t};',
'});'
].join('\n');
// value = [
// 'function x() {',
// '\tconsole.log("Hello world!");',
// '}'
// ].join('\n'),
value = "<h1>Hello</h1>↵<!-- ********* Begin ********* -->↵ ↵ ↵<!-- ********* End ********* -->"
value = this.props.repositoryCode
const height = $('#games_repository_contents').height() - 40
const width = $('#games_repository_contents').width()
$('#codetab_con_1').height(height)
const lang = getLanguageByMirrorName(this.props.mirror_name);
const editor = window.monaco.editor.create(document.getElementById('extend-challenge-file-edit'), {
value: value,
readOnly: !this.props.isEditablePath && this.props.shixun && this.props.shixun.code_edit_permission != true,
// 属性说明
// http://testeduplus2.educoder.net/react/build/static/node_modules/_monaco-editor@0.15.6@monaco-editor/esm/vs/editor/common/config/commonEditorConfig.js
// https://github.com/Microsoft/monaco-editor/issues/29
scrollBeyondLastLine: false,
language: lang,
// language: 'css',
// theme: "vs-dark",
theme: "myCoolTheme",
fontSize: this.state.cmFontSize
});
window.editor_monaco = editor;
this.editor_monaco = editor
// editor.setPosition({ lineNumber: 2, column: 30 });
// editor.model.onDidChangeContent((event) => {
// if (notCallCodeMirrorOnChangeFlag === true) {
// notCallCodeMirrorOnChangeFlag = false
// return;
// }
// this.props.onRepositoryCodeUpdate(editor.getValue())
// });
editor.onDidChangeModelContent((event) => {
if (notCallCodeMirrorOnChangeFlag === true) {
notCallCodeMirrorOnChangeFlag = false
return;
}
this.props.onRepositoryCodeUpdate && this.props.onRepositoryCodeUpdate(editor.getValue())
})
this.props.codemirrorDidMount && this.props.codemirrorDidMount()
if(this.props.shixun && this.props.shixun.forbid_copy == true) {
// 禁用粘贴
// https://github.com/Microsoft/monaco-editor/issues/100
window.editor_monaco.onDidPaste( (a, b, c) => { window.__pastePosition = a })
window.addEventListener('paste', (a, b, c) => {
const selection = window.editor_monaco.getSelection();
const range = new monaco.Range(
window.__pastePosition.startLineNumber || selection.endLineNumber,
window.__pastePosition.startColumn || selection.endColumn,
window.__pastePosition.endLineNumber || selection.endLineNumber,
window.__pastePosition.endColumn || selection.endColumn,);
window.editor_monaco.executeEdits('', [{range, text: ''}] )
})
// 禁用复制
window.editor_monaco.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_C, () => null);
window.editor_monaco.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_V, () => null);
}
setTimeout(() => {
editor.layout();
editor.focus();
}, 600)
window.editor_monaco.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, () => {
this.props.doFileUpdateRequestOnCodeMirrorBlur();
return false;
});
})
// window.document.onkeydown = (e) => {
// e = window.event || e;
// if(e.keyCode== 83 && e.ctrlKey){
// /*延迟兼容FF浏览器 */
// // setTimeout(function(){
// // alert('ctrl+s');
// // },1);
// this.props.doFileUpdateRequestOnCodeMirrorBlur();
// return false;
// }
// };
}
onFontSizeChange = (value) => {
toStore('cmFontSize', value)
this.editor_monaco.updateOptions({fontSize: value})
this.setState({ cmFontSize: value });
}
onAutoCompleteSwitchChange = () => {
}
render() {
const { repositoryCode, showSettingDrawer, settingDrawerOpen } = this.props;
const { cmFontSize } = this.state;
return (
<React.Fragment>
<Drawer
anchor="right"
className="settingDrawer"
width={260}
open={settingDrawerOpen}
onClose={() => showSettingDrawer( false )}
>
<TPICodeSetting {...this.props} {...this.state}
onFontSizeChange={this.onFontSizeChange}
onAutoCompleteSwitchChange={this.onAutoCompleteSwitchChange}
></TPICodeSetting>
</Drawer>
<div className = "" id="extend-challenge-file-edit" name="content"
style={{ width: '100%', height: '100%', border:'1px solid grey' }}></div>
</React.Fragment>
);
}
}
export default ( TPIMonaco ) ;
/**
// http://testeduplus2.educoder.net/react/build/static/node_modules/
_monaco-editor@0.15.6@monaco-editor/esm/vs/editor/common/config/editorOptions.js
export var EDITOR_DEFAULTS = {
inDiffEditor: false,
wordSeparators: USUAL_WORD_SEPARATORS,
lineNumbersMinChars: 5,
lineDecorationsWidth: 10,
readOnly: false,
mouseStyle: 'text',
disableLayerHinting: false,
automaticLayout: false,
wordWrap: 'off',
wordWrapColumn: 80,
wordWrapMinified: true,
wrappingIndent: 1
wordWrapBreakBeforeCharacters: '([{‘“〈《「『【〔([{「£¥$£¥+',
wordWrapBreakAfterCharacters: ' \t})]?|&,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー”〉》」』】〕)]}」',
wordWrapBreakObtrusiveCharacters: '.',
autoClosingBrackets: 'languageDefined',
autoClosingQuotes: 'languageDefined',
autoSurround: 'languageDefined',
autoIndent: true,
dragAndDrop: true,
emptySelectionClipboard: true,
copyWithSyntaxHighlighting: true,
useTabStops: true,
multiCursorModifier: 'altKey',
multiCursorMergeOverlapping: true,
accessibilitySupport: 'auto',
showUnused: true,
viewInfo: {
extraEditorClassName: '',
disableMonospaceOptimizations: false,
rulers: [],
ariaLabel: nls.localize('editorViewAccessibleLabel', "Editor content"),
renderLineNumbers: 1 // On ,
renderCustomLineNumbers: null,
selectOnLineNumbers: true,
glyphMargin: true,
revealHorizontalRightPadding: 30,
roundedSelection: true,
overviewRulerLanes: 2,
overviewRulerBorder: true,
cursorBlinking: 1 /* Blink ,
mouseWheelZoom: false,
cursorStyle: TextEditorCursorStyle.Line,
cursorWidth: 0,
hideCursorInOverviewRuler: false,
scrollBeyondLastLine: true,
scrollBeyondLastColumn: 5,
smoothScrolling: false,
stopRenderingLineAfter: 10000,
renderWhitespace: 'none',
renderControlCharacters: false,
fontLigatures: false,
renderIndentGuides: true,
highlightActiveIndentGuide: true,
renderLineHighlight: 'line',
scrollbar: {
vertical: 1 /* Auto ,
horizontal: 1 /* Auto ,
arrowSize: 11,
useShadows: true,
verticalHasArrows: false,
horizontalHasArrows: false,
horizontalScrollbarSize: 10,
horizontalSliderSize: 10,
verticalScrollbarSize: 14,
verticalSliderSize: 14,
handleMouseWheel: true,
mouseWheelScrollSensitivity: 1,
},
minimap: {
enabled: true,
side: 'right',
showSlider: 'mouseover',
renderCharacters: true,
maxColumn: 120
},
fixedOverflowWidgets: false,
},
contribInfo: {
selectionClipboard: true,
hover: {
enabled: true,
delay: 300,
sticky: true
},
links: true,
contextmenu: true,
quickSuggestions: { other: true, comments: false, strings: false },
quickSuggestionsDelay: 10,
parameterHints: {
enabled: true,
cycle: false
},
iconsInSuggestions: true,
formatOnType: false,
formatOnPaste: false,
suggestOnTriggerCharacters: true,
acceptSuggestionOnEnter: 'on',
acceptSuggestionOnCommitCharacter: true,
wordBasedSuggestions: true,
suggestSelection: 'recentlyUsed',
suggestFontSize: 0,
suggestLineHeight: 0,
tabCompletion: 'off',
suggest: {
filterGraceful: true,
snippets: 'inline',
snippetsPreventQuickSuggestions: true,
localityBonus: false
},
selectionHighlight: true,
occurrencesHighlight: true,
codeLens: true,
folding: true,
foldingStrategy: 'auto',
showFoldingControls: 'mouseover',
matchBrackets: true,
find: {
seedSearchStringFromSelection: true,
autoFindInSelection: false,
globalFindClipboard: false
},
colorDecorators: true,
lightbulbEnabled: true,
codeActionsOnSave: {},
codeActionsOnSaveTimeout: 750
},
};
*/