mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
将monaco-editor作为在线IDE编辑器
This commit is contained in:
1 parent
4c53fc8146
commit
53a6dbeb1a
9 files changed
+81
-134
No files matched your search
@@ -4,6 +4,7 @@ import _ from 'lodash';
|
||||
import webpack from 'webpack';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
|
||||
import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
|
||||
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
|
||||
import ExtractTextPlugin from 'extract-text-webpack-plugin';
|
||||
@@ -183,9 +184,10 @@ export default function (env = {}) {
|
||||
// don't include momentjs locale files
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
|
||||
// don't include timeago.js locale files
|
||||
// no use. FIXME.
|
||||
// new webpack.IgnorePlugin(/locales\//, /timeago/),
|
||||
new MonacoWebpackPlugin({
|
||||
// available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
|
||||
languages: ['cpp', 'csharp', 'java', 'javascript', 'python', 'rust', 'ruby', 'php', 'pascal', 'go']
|
||||
}),
|
||||
|
||||
// extract stylesheets into a standalone file
|
||||
env.watch
|
||||
|
||||
@@ -1,26 +1,12 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import CodeMirror from 'react-codemirror';
|
||||
|
||||
import 'codemirror/addon/edit/matchbrackets';
|
||||
import 'codemirror/mode/clike/clike';
|
||||
import 'codemirror/mode/pascal/pascal';
|
||||
import 'codemirror/mode/python/python';
|
||||
import 'codemirror/mode/php/php';
|
||||
import 'codemirror/mode/rust/rust';
|
||||
import 'codemirror/mode/haskell/haskell';
|
||||
import 'codemirror/mode/javascript/javascript';
|
||||
import 'codemirror/mode/go/go';
|
||||
import 'codemirror/mode/ruby/ruby';
|
||||
import MonacoEditor from 'react-monaco-editor';
|
||||
|
||||
import * as languageEnum from 'vj/constant/language';
|
||||
|
||||
const getOptions = lang => ({
|
||||
lineNumbers: true,
|
||||
tabSize: 4,
|
||||
indentUnit: 4,
|
||||
indentWithTabs: true,
|
||||
mode: languageEnum.LANG_CODEMIRROR_MODES[lang],
|
||||
mode: languageEnum.LANG_MONACO_MODES[lang],
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
@@ -39,17 +25,15 @@ const mapDispatchToProps = dispatch => ({
|
||||
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
export default class ScratchpadEditorContainer extends React.PureComponent {
|
||||
componentDidMount() {
|
||||
this.refs.editor.getCodeMirror().setOption('theme', 'vjcm');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<CodeMirror
|
||||
<MonacoEditor
|
||||
language={languageEnum.LANG_MONACO_MODES[this.props.lang]}
|
||||
theme="vs-dark"
|
||||
value={this.props.code}
|
||||
onChange={code => this.props.handleUpdateCode(code)}
|
||||
options={getOptions(this.props.lang)}
|
||||
ref="editor"
|
||||
onChange={code => this.props.handleUpdateCode(code)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+14
-15
@@ -32,19 +32,18 @@ export const LANG_HIGHLIGHT_ID = {
|
||||
rb: 'ruby',
|
||||
};
|
||||
|
||||
export const LANG_CODEMIRROR_MODES = {
|
||||
c: 'text/x-csrc',
|
||||
cc: 'text/x-c++src',
|
||||
cs: 'text/x-csharp',
|
||||
pas: 'text/x-pascal',
|
||||
java: 'text/x-java',
|
||||
py: 'text/x-python',
|
||||
py3: 'text/x-python',
|
||||
php: 'text/x-php',
|
||||
rs: 'text/x-rustsrc',
|
||||
hs: 'text/x-haskell',
|
||||
js: 'text/javascript',
|
||||
go: 'text/x-go',
|
||||
rb: 'text/x-ruby',
|
||||
export const LANG_MONACO_MODES = {
|
||||
c: 'cpp',
|
||||
cc: 'cpp',
|
||||
cs: 'csharp',
|
||||
pas: 'pascal',
|
||||
java: 'java',
|
||||
py: 'python',
|
||||
py3: 'python',
|
||||
php: 'php',
|
||||
rs: 'rust',
|
||||
hs: 'haskell',
|
||||
js: 'javascript',
|
||||
go: 'go',
|
||||
rb: 'ruby',
|
||||
};
|
||||
attachObjectMeta(LANG_CODEMIRROR_MODES, 'exportToPython', false);
|
||||
@@ -51,6 +51,7 @@
|
||||
"imports-loader": "^0.8.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"json-loader": "^0.5.7",
|
||||
"monaco-editor-webpack-plugin": "^1.9.0",
|
||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"rupture": "^0.7.1",
|
||||
@@ -89,6 +90,7 @@
|
||||
"react": "^15.6.1",
|
||||
"react-codemirror": "^1.0.0",
|
||||
"react-dom": "^15.6.1",
|
||||
"react-monaco-editor": "^0.35.0",
|
||||
"react-redux": "^5.0.6",
|
||||
"react-split-pane": "^0.1.65",
|
||||
"redux": "^3.7.2",
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import Tether from 'tether';
|
||||
import { NamedPage } from 'vj/misc/PageLoader';
|
||||
import Navigation from 'vj/components/navigation';
|
||||
import Notification from 'vj/components/notification';
|
||||
import { ActionDialog } from 'vj/components/dialog';
|
||||
import DomainSelectAutoComplete from 'vj/components/autocomplete/DomainSelectAutoComplete';
|
||||
import loadReactRedux from 'vj/utils/loadReactRedux';
|
||||
import delay from 'vj/utils/delay';
|
||||
import request from 'vj/utils/request';
|
||||
import i18n from 'vj/utils/i18n';
|
||||
|
||||
class ProblemPageExtender {
|
||||
constructor() {
|
||||
@@ -19,12 +14,8 @@ class ProblemPageExtender {
|
||||
}
|
||||
|
||||
async extend() {
|
||||
if (this.inProgress) {
|
||||
return;
|
||||
}
|
||||
if (this.isExtended) {
|
||||
return;
|
||||
}
|
||||
if (this.inProgress) return;
|
||||
if (this.isExtended) return;
|
||||
this.inProgress = true;
|
||||
|
||||
const bound = this.$contentBound
|
||||
@@ -38,7 +29,6 @@ class ProblemPageExtender {
|
||||
Navigation.instance.logoVisible.set('scratchpad', true);
|
||||
Navigation.instance.expanded.set('scratchpad', true);
|
||||
$('body').addClass('header--collapsed mode--scratchpad');
|
||||
|
||||
await this.$scratchpadContainer
|
||||
.css({
|
||||
left: bound.left,
|
||||
@@ -67,12 +57,8 @@ class ProblemPageExtender {
|
||||
}
|
||||
|
||||
async collapse() {
|
||||
if (this.inProgress) {
|
||||
return;
|
||||
}
|
||||
if (!this.isExtended) {
|
||||
return;
|
||||
}
|
||||
if (this.inProgress) return;
|
||||
if (!this.isExtended) return;
|
||||
this.inProgress = true;
|
||||
|
||||
$(window).scrollTop(0);
|
||||
@@ -109,11 +95,8 @@ class ProblemPageExtender {
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this.isExtended) {
|
||||
this.collapse();
|
||||
} else {
|
||||
this.extend();
|
||||
}
|
||||
if (this.isExtended) this.collapse();
|
||||
else this.extend();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,10 +157,7 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
|
||||
}
|
||||
|
||||
async function loadReact() {
|
||||
if (reactLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reactLoaded) return;
|
||||
$('.loader-container').show();
|
||||
|
||||
const SockJs = await import('sockjs-client');
|
||||
@@ -204,61 +184,13 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
|
||||
$('#scratchpad').get(0),
|
||||
);
|
||||
};
|
||||
|
||||
unmountReact = () => {
|
||||
unmountComponentAtNode($('#scratchpad').get(0));
|
||||
};
|
||||
|
||||
reactLoaded = true;
|
||||
|
||||
$('.loader-container').hide();
|
||||
}
|
||||
|
||||
const domainSelector = DomainSelectAutoComplete.getOrConstruct($('.dialog__body--copy-to [name="domain_id"]'));
|
||||
const copyProblemToDialog = new ActionDialog({
|
||||
$body: $('.dialog__body--copy-to > div'),
|
||||
onDispatch(action) {
|
||||
if (action === 'ok' && domainSelector.value() === null) {
|
||||
domainSelector.focus();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
});
|
||||
copyProblemToDialog.clear = function () {
|
||||
domainSelector.clear();
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
async function handleClickCopyProblem() {
|
||||
const action = await copyProblemToDialog.clear().open();
|
||||
if (action !== 'ok') {
|
||||
return;
|
||||
}
|
||||
const domainId = copyProblemToDialog.$dom.find('[name="domain_id"]').val();
|
||||
const useNumericId = copyProblemToDialog.$dom.find('[name="numeric_pid"]').prop('checked');
|
||||
const isHidden = copyProblemToDialog.$dom.find('[name="hidden"]').prop('checked');
|
||||
const payload = {
|
||||
operation: 'copy_to_domain',
|
||||
dest_domain_id: domainId,
|
||||
};
|
||||
if (useNumericId) {
|
||||
payload.numeric_pid = 'on';
|
||||
}
|
||||
if (isHidden) {
|
||||
payload.hidden = 'on';
|
||||
}
|
||||
try {
|
||||
const data = await request.post('', payload);
|
||||
Notification.success(i18n('Problem is successfully copied.'));
|
||||
await delay(1000);
|
||||
window.location.href = data.new_problem_url;
|
||||
} catch (error) {
|
||||
Notification.error(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function enterScratchpadMode() {
|
||||
await extender.extend();
|
||||
await loadReact();
|
||||
@@ -284,10 +216,6 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
|
||||
leaveScratchpadMode();
|
||||
ev.preventDefault();
|
||||
});
|
||||
$(document).on('click', '[name="problem-sidebar__copy-to"]', (ev) => {
|
||||
handleClickCopyProblem();
|
||||
ev.preventDefault();
|
||||
});
|
||||
$(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => {
|
||||
$(ev.currentTarget).hide();
|
||||
$('[name="problem-sidebar__categories"]').show();
|
||||
|
||||
+40
-1
@@ -1000,11 +1000,24 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
|
||||
integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
||||
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
|
||||
|
||||
"@types/q@^1.5.1":
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
|
||||
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
|
||||
|
||||
"@types/react@^15.x || ^16.x":
|
||||
version "16.9.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.33.tgz#a5274520f0d28cbbb73c8652ddd48646fd4bcae5"
|
||||
integrity sha512-ovgoy7p9999HDzwv8Sewhl8GJjn/r0GRsFrM9UMwp1uodh0kQ0pwIHLQ6LNfqGSyjNzJ8II/HIg0BL7Yn/B9yA==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^2.2.0"
|
||||
|
||||
a-sync-waterfall@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7"
|
||||
@@ -2705,6 +2718,11 @@ csso@~2.3.1:
|
||||
clap "^1.0.9"
|
||||
source-map "^0.5.3"
|
||||
|
||||
csstype@^2.2.0:
|
||||
version "2.6.10"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
|
||||
integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==
|
||||
|
||||
cubic2quad@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/cubic2quad/-/cubic2quad-1.1.1.tgz#69b19c61a3f5b41ecf2f1d5fae8fb03415aa8b15"
|
||||
@@ -5360,7 +5378,7 @@ loader-runner@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
||||
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
|
||||
|
||||
loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.4.0:
|
||||
loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
|
||||
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
|
||||
@@ -5818,6 +5836,18 @@ moment@^2.24.0:
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
|
||||
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
|
||||
|
||||
monaco-editor-webpack-plugin@^1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.9.0.tgz#5b547281b9f404057dc5d8c5722390df9ac90be6"
|
||||
integrity sha512-tOiiToc94E1sb50BgZ8q8WK/bxus77SRrwCqIpAB5er3cpX78SULbEBY4YPOB8kDolOzKRt30WIHG/D6gz69Ww==
|
||||
dependencies:
|
||||
loader-utils "^1.2.3"
|
||||
|
||||
monaco-editor@*:
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
|
||||
integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
|
||||
|
||||
move-concurrently@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
||||
@@ -7493,6 +7523,15 @@ react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-monaco-editor@^0.35.0:
|
||||
version "0.35.0"
|
||||
resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.35.0.tgz#ceaaca4f292571e95957871145bd7c5f76a4fd33"
|
||||
integrity sha512-iQbJykYPgKko0yqphTVWi1vHFokFShv5qpWnFV2TvtliKG45x2LVF4/HC06MDVK4fBfp2lCrun+NUcEYMzAnNQ==
|
||||
dependencies:
|
||||
"@types/react" "^15.x || ^16.x"
|
||||
monaco-editor "*"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-redux@^5.0.6:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57"
|
||||
|
||||
Reference in new issue
Block a user