将monaco-editor作为在线IDE编辑器

This commit is contained in:
masnn committed 2020-04-09 18:57:42 +08:00
1 parent 4c53fc8146
commit 53a6dbeb1a
9 files changed
+79 -132

No files matched your search

+1 -4
View File
@@ -44,10 +44,7 @@ MIDDLEWARE(async (ctx, next) => {
} }
} }
}; };
ctx.back = () => { ctx.back = () => ctx.redirect(ctx.request.headers.referer || '/');
console.log(122143);
ctx.redirect(ctx.request.headers.referer || '/');
};
ctx.csrf_token = await token.add(token.TYPE_CSRF_TOKEN, 600, ctx.path); ctx.csrf_token = await token.add(token.TYPE_CSRF_TOKEN, 600, ctx.path);
await next(); await next();
if (ctx.session.sid) if (ctx.session.sid)
@@ -100,16 +100,12 @@
{% if pdoc['psdoc']['status'] %} {% if pdoc['psdoc']['status'] %}
<span class="icon record-status--icon {{ builtin.STATUS_CODES[pdoc['psdoc']['status']] }}"></span> <span class="icon record-status--icon {{ builtin.STATUS_CODES[pdoc['psdoc']['status']] }}"></span>
<a href="/r/{{ pdoc['psdoc']['rid'] }}" class="record-status--text {{ builtin.STATUS_CODES[pdoc['psdoc']['status']] }}"> <a href="/r/{{ pdoc['psdoc']['rid'] }}" class="record-status--text {{ builtin.STATUS_CODES[pdoc['psdoc']['status']] }}">
{{ status.STATUS_TEXTS[pdoc['psdoc']['status']] }} {{ builtin.STATUS_TEXTS[pdoc['psdoc']['status']] }}
</a> </a>
{% else %} {% else %}
{{ _('(None)') }} {{ _('(None)') }}
{% endif %} {% endif %}
</dd> </dd>
{% if pdoc['ac_msg'] and pdoc['psdoc']['status'] == status.STATUS_ACCEPTED %}
<dt>{{ _('AC Message') }}</dt>
<dd>{{ pdoc['ac_msg'] }}</dd>
{% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}
<dt>{{ _('Difficulty') }}</dt> <dt>{{ _('Difficulty') }}</dt>
+3 -3
View File
@@ -4,9 +4,9 @@
<script> <script>
var Context = { var Context = {
'problemId': "{{ pdoc.pid }}", 'problemId': "{{ pdoc.pid }}",
'postSubmitUrl': "/p/{{ pdoc.pid }}", 'postSubmitUrl': "/p/{{ pdoc.pid }}/submit",
'getSubmissionsUrl': "/p/{{ pdoc.pid }}", 'getSubmissionsUrl': "/p/{{ pdoc.pid }}/submit",
'getRecordDetailUrl': "/r/{{ rid }}", 'getRecordDetailUrl': "/r/{rid}",
'code_lang': "{{ handler.user.codeLang }}", 'code_lang': "{{ handler.user.codeLang }}",
'code_template': "{{ handler.user.codeTemplate }}", 'code_template': "{{ handler.user.codeTemplate }}",
}; };
+5 -3
View File
@@ -4,6 +4,7 @@ import _ from 'lodash';
import webpack from 'webpack'; import webpack from 'webpack';
import fs from 'fs-extra'; import fs from 'fs-extra';
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin'; import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin'; import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin'; import ExtractTextPlugin from 'extract-text-webpack-plugin';
@@ -183,9 +184,10 @@ export default function (env = {}) {
// don't include momentjs locale files // don't include momentjs locale files
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// don't include timeago.js locale files new MonacoWebpackPlugin({
// no use. FIXME. // available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
// new webpack.IgnorePlugin(/locales\//, /timeago/), languages: ['cpp', 'csharp', 'java', 'javascript', 'python', 'rust', 'ruby', 'php', 'pascal', 'go']
}),
// extract stylesheets into a standalone file // extract stylesheets into a standalone file
env.watch env.watch
@@ -1,26 +1,12 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import CodeMirror from 'react-codemirror'; import MonacoEditor from 'react-monaco-editor';
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 * as languageEnum from 'vj/constant/language'; import * as languageEnum from 'vj/constant/language';
const getOptions = lang => ({ const getOptions = lang => ({
lineNumbers: true, lineNumbers: true,
tabSize: 4, mode: languageEnum.LANG_MONACO_MODES[lang],
indentUnit: 4,
indentWithTabs: true,
mode: languageEnum.LANG_CODEMIRROR_MODES[lang],
}); });
const mapStateToProps = state => ({ const mapStateToProps = state => ({
@@ -39,17 +25,15 @@ const mapDispatchToProps = dispatch => ({
@connect(mapStateToProps, mapDispatchToProps) @connect(mapStateToProps, mapDispatchToProps)
export default class ScratchpadEditorContainer extends React.PureComponent { export default class ScratchpadEditorContainer extends React.PureComponent {
componentDidMount() {
this.refs.editor.getCodeMirror().setOption('theme', 'vjcm');
}
render() { render() {
return ( return (
<CodeMirror <MonacoEditor
language={languageEnum.LANG_MONACO_MODES[this.props.lang]}
theme="vs-dark"
value={this.props.code} value={this.props.code}
onChange={code => this.props.handleUpdateCode(code)}
options={getOptions(this.props.lang)} options={getOptions(this.props.lang)}
ref="editor" ref="editor"
onChange={code => this.props.handleUpdateCode(code)}
/> />
); );
} }
+14 -15
View File
@@ -32,19 +32,18 @@ export const LANG_HIGHLIGHT_ID = {
rb: 'ruby', rb: 'ruby',
}; };
export const LANG_CODEMIRROR_MODES = { export const LANG_MONACO_MODES = {
c: 'text/x-csrc', c: 'cpp',
cc: 'text/x-c++src', cc: 'cpp',
cs: 'text/x-csharp', cs: 'csharp',
pas: 'text/x-pascal', pas: 'pascal',
java: 'text/x-java', java: 'java',
py: 'text/x-python', py: 'python',
py3: 'text/x-python', py3: 'python',
php: 'text/x-php', php: 'php',
rs: 'text/x-rustsrc', rs: 'rust',
hs: 'text/x-haskell', hs: 'haskell',
js: 'text/javascript', js: 'javascript',
go: 'text/x-go', go: 'go',
rb: 'text/x-ruby', rb: 'ruby',
}; };
attachObjectMeta(LANG_CODEMIRROR_MODES, 'exportToPython', false);
+2
View File
@@ -51,6 +51,7 @@
"imports-loader": "^0.8.0", "imports-loader": "^0.8.0",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"monaco-editor-webpack-plugin": "^1.9.0",
"optimize-css-assets-webpack-plugin": "^3.2.0", "optimize-css-assets-webpack-plugin": "^3.2.0",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"rupture": "^0.7.1", "rupture": "^0.7.1",
@@ -89,6 +90,7 @@
"react": "^15.6.1", "react": "^15.6.1",
"react-codemirror": "^1.0.0", "react-codemirror": "^1.0.0",
"react-dom": "^15.6.1", "react-dom": "^15.6.1",
"react-monaco-editor": "^0.35.0",
"react-redux": "^5.0.6", "react-redux": "^5.0.6",
"react-split-pane": "^0.1.65", "react-split-pane": "^0.1.65",
"redux": "^3.7.2", "redux": "^3.7.2",
+7 -79
View File
@@ -1,13 +1,8 @@
import Tether from 'tether'; import Tether from 'tether';
import { NamedPage } from 'vj/misc/PageLoader'; import { NamedPage } from 'vj/misc/PageLoader';
import Navigation from 'vj/components/navigation'; 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 loadReactRedux from 'vj/utils/loadReactRedux';
import delay from 'vj/utils/delay'; import delay from 'vj/utils/delay';
import request from 'vj/utils/request';
import i18n from 'vj/utils/i18n';
class ProblemPageExtender { class ProblemPageExtender {
constructor() { constructor() {
@@ -19,12 +14,8 @@ class ProblemPageExtender {
} }
async extend() { async extend() {
if (this.inProgress) { if (this.inProgress) return;
return; if (this.isExtended) return;
}
if (this.isExtended) {
return;
}
this.inProgress = true; this.inProgress = true;
const bound = this.$contentBound const bound = this.$contentBound
@@ -38,7 +29,6 @@ class ProblemPageExtender {
Navigation.instance.logoVisible.set('scratchpad', true); Navigation.instance.logoVisible.set('scratchpad', true);
Navigation.instance.expanded.set('scratchpad', true); Navigation.instance.expanded.set('scratchpad', true);
$('body').addClass('header--collapsed mode--scratchpad'); $('body').addClass('header--collapsed mode--scratchpad');
await this.$scratchpadContainer await this.$scratchpadContainer
.css({ .css({
left: bound.left, left: bound.left,
@@ -67,12 +57,8 @@ class ProblemPageExtender {
} }
async collapse() { async collapse() {
if (this.inProgress) { if (this.inProgress) return;
return; if (!this.isExtended) return;
}
if (!this.isExtended) {
return;
}
this.inProgress = true; this.inProgress = true;
$(window).scrollTop(0); $(window).scrollTop(0);
@@ -109,11 +95,8 @@ class ProblemPageExtender {
} }
toggle() { toggle() {
if (this.isExtended) { if (this.isExtended) this.collapse();
this.collapse(); else this.extend();
} else {
this.extend();
}
} }
} }
@@ -174,10 +157,7 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
} }
async function loadReact() { async function loadReact() {
if (reactLoaded) { if (reactLoaded) return;
return;
}
$('.loader-container').show(); $('.loader-container').show();
const SockJs = await import('sockjs-client'); const SockJs = await import('sockjs-client');
@@ -204,61 +184,13 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
$('#scratchpad').get(0), $('#scratchpad').get(0),
); );
}; };
unmountReact = () => { unmountReact = () => {
unmountComponentAtNode($('#scratchpad').get(0)); unmountComponentAtNode($('#scratchpad').get(0));
}; };
reactLoaded = true; reactLoaded = true;
$('.loader-container').hide(); $('.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() { async function enterScratchpadMode() {
await extender.extend(); await extender.extend();
await loadReact(); await loadReact();
@@ -284,10 +216,6 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
leaveScratchpadMode(); leaveScratchpadMode();
ev.preventDefault(); ev.preventDefault();
}); });
$(document).on('click', '[name="problem-sidebar__copy-to"]', (ev) => {
handleClickCopyProblem();
ev.preventDefault();
});
$(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => { $(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => {
$(ev.currentTarget).hide(); $(ev.currentTarget).hide();
$('[name="problem-sidebar__categories"]').show(); $('[name="problem-sidebar__categories"]').show();
+40 -1
View File
@@ -1000,11 +1000,24 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ== 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": "@types/q@^1.5.1":
version "1.5.2" version "1.5.2"
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== 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: a-sync-waterfall@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" 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" clap "^1.0.9"
source-map "^0.5.3" 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: cubic2quad@^1.0.0:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/cubic2quad/-/cubic2quad-1.1.1.tgz#69b19c61a3f5b41ecf2f1d5fae8fb03415aa8b15" 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" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== 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" version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== 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" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== 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: move-concurrently@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" 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" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== 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: react-redux@^5.0.6:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57"