Browse Source

Finish monaco editor

pull/6/head
Menci 6 years ago
parent
commit
89660b162b
  1. 18
      language-config.json
  2. 332
      static/self/monaco-editor-tomorrow.js
  3. 107
      static/self/monaco-editor.css
  4. 1024
      static/self/monaco-editor.js
  5. 8
      views/admin_raw.ejs
  6. 28
      views/article.ejs
  7. 54
      views/article_edit.ejs
  8. 41
      views/contest_edit.ejs
  9. 1
      views/header.ejs
  10. 31
      views/monaco-editor.ejs
  11. 22
      views/problem.ejs
  12. 88
      views/problem_edit.ejs
  13. 31
      views/user_edit.ejs

18
language-config.json

@ -3,63 +3,63 @@
"show": "C++", "show": "C++",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 8.2.0", "version": "GCC 8.2.0",
"editor": "c_cpp", "editor": "cpp",
"format": "cpp" "format": "cpp"
}, },
"cpp11": { "cpp11": {
"show": "C++ 11", "show": "C++ 11",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 8.2.0", "version": "GCC 8.2.0",
"editor": "c_cpp", "editor": "cpp",
"format": "cpp" "format": "cpp"
}, },
"cpp17": { "cpp17": {
"show": "C++ 17", "show": "C++ 17",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 8.2.0", "version": "GCC 8.2.0",
"editor": "c_cpp", "editor": "cpp",
"format": "cpp" "format": "cpp"
}, },
"cpp-noilinux": { "cpp-noilinux": {
"show": "C++ (NOI)", "show": "C++ (NOI)",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 4.8.4 (NOILinux 1.4.1)", "version": "GCC 4.8.4 (NOILinux 1.4.1)",
"editor": "c_cpp", "editor": "cpp",
"format": "cpp" "format": "cpp"
}, },
"cpp11-noilinux": { "cpp11-noilinux": {
"show": "C++ 11 (NOI)", "show": "C++ 11 (NOI)",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 4.8.4 (NOILinux 1.4.1)", "version": "GCC 4.8.4 (NOILinux 1.4.1)",
"editor": "c_cpp", "editor": "cpp",
"format": "cpp" "format": "cpp"
}, },
"cpp11-clang": { "cpp11-clang": {
"show": "C++ 11 (Clang)", "show": "C++ 11 (Clang)",
"highlight": "cpp", "highlight": "cpp",
"version": "Clang 7.0.1", "version": "Clang 7.0.1",
"editor": "c_cpp", "editor": "cpp",
"format": "cpp" "format": "cpp"
}, },
"cpp17-clang": { "cpp17-clang": {
"show": "C++ 17 (Clang)", "show": "C++ 17 (Clang)",
"highlight": "cpp", "highlight": "cpp",
"version": "Clang 7.0.1", "version": "Clang 7.0.1",
"editor": "c_cpp", "editor": "cpp",
"format": "cpp" "format": "cpp"
}, },
"c": { "c": {
"show": "C", "show": "C",
"highlight": "c", "highlight": "c",
"version": "Clang 7.0.1", "version": "Clang 7.0.1",
"editor": "c_cpp", "editor": "c",
"format": "c" "format": "c"
}, },
"c-noilinux": { "c-noilinux": {
"show": "C (NOI)", "show": "C (NOI)",
"highlight": "c", "highlight": "c",
"version": "GCC 4.8.4 (NOILinux 1.4.1)", "version": "GCC 4.8.4 (NOILinux 1.4.1)",
"editor": "c_cpp", "editor": "c",
"format": "c" "format": "c"
}, },
"csharp": { "csharp": {

332
static/self/monaco-editor-tomorrow.js

@ -1,167 +1,167 @@
monaco.editor.defineTheme('tomorrow', { monaco.editor.defineTheme('tomorrow', {
"base": "vs", "base": "vs",
"inherit": true, "inherit": true,
"rules": [ "rules": [
{ {
"foreground": "8e908c", "foreground": "8e908c",
"token": "comment" "token": "comment"
}, },
{ {
"foreground": "666969", "foreground": "666969",
"token": "keyword.operator.class" "token": "keyword.operator.class"
}, },
{ {
"foreground": "666969", "foreground": "666969",
"token": "constant.other" "token": "constant.other"
}, },
{ {
"foreground": "666969", "foreground": "666969",
"token": "source.php.embedded.line" "token": "source.php.embedded.line"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "variable" "token": "variable"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "support.other.variable" "token": "support.other.variable"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "string.other.link" "token": "string.other.link"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "string.regexp" "token": "string.regexp"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "entity.name.tag" "token": "entity.name.tag"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "entity.other.attribute-name" "token": "entity.other.attribute-name"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "meta.tag" "token": "meta.tag"
}, },
{ {
"foreground": "c82829", "foreground": "c82829",
"token": "declaration.tag" "token": "declaration.tag"
}, },
{ {
"foreground": "f5871f", "foreground": "f5871f",
"token": "constant.numeric" "token": "constant.numeric"
}, },
{ {
"foreground": "f5871f", "foreground": "f5871f",
"token": "constant.language" "token": "constant.language"
}, },
{ {
"foreground": "f5871f", "foreground": "f5871f",
"token": "support.constant" "token": "support.constant"
}, },
{ {
"foreground": "f5871f", "foreground": "f5871f",
"token": "constant.character" "token": "constant.character"
}, },
{ {
"foreground": "f5871f", "foreground": "f5871f",
"token": "variable.parameter" "token": "variable.parameter"
}, },
{ {
"foreground": "f5871f", "foreground": "f5871f",
"token": "punctuation.section.embedded" "token": "punctuation.section.embedded"
}, },
{ {
"foreground": "f5871f", "foreground": "f5871f",
"token": "keyword.other.unit" "token": "keyword.other.unit"
}, },
{ {
"foreground": "c99e00", "foreground": "c99e00",
"token": "entity.name.class" "token": "entity.name.class"
}, },
{ {
"foreground": "c99e00", "foreground": "c99e00",
"token": "entity.name.type.class" "token": "entity.name.type.class"
}, },
{ {
"foreground": "c99e00", "foreground": "c99e00",
"token": "support.type" "token": "support.type"
}, },
{ {
"foreground": "c99e00", "foreground": "c99e00",
"token": "support.class" "token": "support.class"
}, },
{ {
"foreground": "718c00", "foreground": "718c00",
"token": "string" "token": "string"
}, },
{ {
"foreground": "718c00", "foreground": "718c00",
"token": "constant.other.symbol" "token": "constant.other.symbol"
}, },
{ {
"foreground": "718c00", "foreground": "718c00",
"token": "entity.other.inherited-class" "token": "entity.other.inherited-class"
}, },
{ {
"foreground": "718c00", "foreground": "718c00",
"token": "markup.heading" "token": "markup.heading"
}, },
{ {
"foreground": "3e999f", "foreground": "3e999f",
"token": "keyword.operator" "token": "keyword.operator"
}, },
{ {
"foreground": "3e999f", "foreground": "3e999f",
"token": "constant.other.color" "token": "constant.other.color"
}, },
{ {
"foreground": "4271ae", "foreground": "4271ae",
"token": "entity.name.function" "token": "entity.name.function"
}, },
{ {
"foreground": "4271ae", "foreground": "4271ae",
"token": "meta.function-call" "token": "meta.function-call"
}, },
{ {
"foreground": "4271ae", "foreground": "4271ae",
"token": "support.function" "token": "support.function"
}, },
{ {
"foreground": "4271ae", "foreground": "4271ae",
"token": "keyword.other.special-method" "token": "keyword.other.special-method"
}, },
{ {
"foreground": "4271ae", "foreground": "4271ae",
"token": "meta.block-level" "token": "meta.block-level"
}, },
{ {
"foreground": "8959a8", "foreground": "8959a8",
"token": "keyword" "token": "keyword"
}, },
{ {
"foreground": "8959a8", "foreground": "8959a8",
"token": "storage" "token": "storage"
}, },
{ {
"foreground": "8959a8", "foreground": "8959a8",
"token": "storage.type" "token": "storage.type"
}, },
{ {
"foreground": "373b41", "foreground": "373b41",
"background": "e0e0e0", "background": "e0e0e0",
"token": "meta.separator" "token": "meta.separator"
} }
], ],
"colors": { "colors": {
"editor.foreground": "#4D4D4C", "editor.foreground": "#4D4D4C",
"editor.background": "#FFFFFF", "editor.background": "#FFFFFF",
"editor.selectionBackground": "#D6D6D6", "editor.selectionBackground": "#D6D6D6",
"editor.lineHighlightBackground": "#EFEFEF", "editor.lineHighlightBackground": "#EFEFEF",
"editorCursor.foreground": "#AEAFAD", "editorCursor.foreground": "#AEAFAD",
"editorWhitespace.foreground": "#D1D1D1" "editorWhitespace.foreground": "#D1D1D1"
} }
}); });

107
static/self/monaco-editor.css

@ -1,37 +1,70 @@
.editor { .editor {
background: #fff; background: #fff;
font-family: "Fira Mono", "Bitstream Vera Sans Mono", Menlo, Consolas, "Lucida Console", monospace; position: relative;
} border: 1px solid rgba(34, 36, 38, 0.15);
}
.monaco-editor .inputarea {
min-height: 0 !important; .editor.editor-with-border {
padding: 0 !important; border-radius: .28571429rem;
border: 0 !important; overflow: hidden;
color: rgba(0, 0, 0, 0) !important; outline: none;
} }
.monaco-editor-background.textAreaCover.line-numbers { .editor.editor-with-border:focus-within {
visibility: hidden; border-color: #85b7d9;
} }
.monaco-editor .selected-text, .monaco-editor .monaco-editor-background { .editor.editor-with-border .monaco-editor .margin {
border-radius: 0 !important; visibility: hidden;
} }
.monaco-editor .mtk1 { .editor.editor-with-border .monaco-editor .lines-content.monaco-editor-background {
color: #4d4d4c !important; margin-top: 9px;
} margin-left: 4px;
}
.monaco-editor .cursor {
color: #000 !important; .monaco-editor .inputarea {
border-color: #000 !important; min-height: 0 !important;
background-color: #000 !important; padding: 0 !important;
} border: 0 !important;
color: rgba(0, 0, 0, 0) !important;
.monaco-editor .line-numbers { }
color: #4d4d4c !important;
} .monaco-editor-background.textAreaCover.line-numbers {
visibility: hidden;
.monaco-editor .margin-view-overlays .current-line { }
background-color: #efefef !important;
} .monaco-editor .selected-text, .monaco-editor .monaco-editor-background {
border-radius: 0 !important;
}
.monaco-editor .mtk1 {
color: #4d4d4c !important;
}
.monaco-editor .cursor {
color: #000 !important;
border-color: #000 !important;
background-color: #000 !important;
}
.monaco-editor .line-numbers {
color: #575756 !important;
}
.monaco-editor .margin-view-overlays .current-line ~ .line-numbers {
color: #000 !important;
font-weight: 500;
}
.editor.editor-with-border .monaco-editor .monaco-scrollable-element .scrollbar.vertical {
background: rgba(0,0,0,.1);
border-radius: 0;
}
.editor.editor-with-border .monaco-editor .monaco-scrollable-element .scrollbar.vertical .slider {
border-radius: 5px;
background: rgba(0,0,0,.25);
-webkit-transition: color .2s ease;
transition: color .2s ease;
}

1024
static/self/monaco-editor.js

File diff suppressed because it is too large Load Diff

8
views/admin_raw.ejs

@ -2,10 +2,12 @@
<% include admin_header %> <% include admin_header %>
<form method="post"> <form method="post">
<div id="editor" class="editor" style="border: 1px solid #D4D4D5; height: 500px; margin-bottom: 20px; "></div> <% include monaco-editor %>
<div id="editor" class="editor" style="border: 1px solid #D4D4D5; height: 500px; margin-bottom: 20px; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="data"> <input type="hidden" name="data">
<% include monaco-editor %>
<script type="text/javascript"> <script type="text/javascript">
var originalData = <%- serializejs(data) %>; var originalData = <%- serializejs(data) %>;
var input = $('[name="data"]'); var input = $('[name="data"]');
@ -13,7 +15,7 @@ input.val(originalData);
window.onEditorLoaded(function () { window.onEditorLoaded(function () {
var editor; var editor;
window.editor = editor = window.createEditor(document.getElementById("editor"), "json", originalData); window.editor = editor = window.createCodeEditor(document.getElementById("editor"), "json", originalData);
$('form').on('submit', function () { $('form').on('submit', function () {
input.val(editor.getValue()); input.val(editor.getValue());
}); });

28
views/article.ejs

@ -94,17 +94,33 @@
<% include page %> <% include page %>
</div> </div>
<% } %> <% } %>
<% if (article.allowedComment) { %> <% if (article.allowedComment) { %>
<form class="ui reply form" method="post" action="<%= syzoj.utils.makeUrl(['article', article.id, 'comment']) %>"> <% include monaco-editor %>
<div class="field"> <form class="ui reply form" method="post" action="<%= syzoj.utils.makeUrl(['article', article.id, 'comment']) %>">
<textarea name="comment"></textarea> <div id="comment" class="editor editor-with-border" style="height: 200px; width: 100%; margin-bottom: 1em; ">
<%- this.showLoadingEditor(); %>
</div> </div>
<input type="hidden" name="comment">
<div style="text-align: center; "> <div style="text-align: center; ">
<button type="submit" class="ui labeled submit icon button"> <button type="submit" class="ui labeled submit icon button">
<i class="icon edit"></i> 回复 <i class="icon edit"></i> 回复
</button> </button>
</div> </div>
</form> </form>
<% } %> <script>
var editors = {
comment: { defaultValue: '' }
};
window.onEditorLoaded(function () {
for (var name in editors) {
var editor = editors[name];
var editorElement = document.getElementById(name);
var input = document.getElementsByName(name)[0];
editor.editor = window.createMarkdownEditor(editorElement, editor.defaultValue, input);
}
});
</script>
<% } %>
</div> </div>
<% include footer %> <% include footer %>

54
views/article_edit.ejs

@ -1,31 +1,39 @@
<% this.title = article.id ? '编辑帖子' : '发表帖子'; %> <% this.title = article.id ? '编辑帖子' : '发表帖子'; %>
<% include header %> <% include header %>
<% include monaco-editor %>
<style type="text/css"> <style type="text/css">
.am-panel-title{ .am-panel-title{
font-size: 1.6em; font-size: 1.6em;
} }
</style> </style>
<div class="padding"> <div class="padding">
<form class="ui form" method="post"> <form class="" method="post">
<div class="ui top attached tabular menu"> <div class="ui top attached tabular menu">
<a class="item active" data-tab="edit">编辑</a> <a class="item active" data-tab="edit">编辑</a>
<a class="item" data-tab="preview" id="preview_tab">预览</a> <a class="item" data-tab="preview" id="preview_tab">预览</a>
</div> </div>
<div class="ui bottom attached tab segment active" data-tab="edit"> <div class="ui bottom attached tab segment active" data-tab="edit">
<div class="field"> <div class="ui form">
<label for="title">标题</label> <div class="field">
<input type="text" id="title" name="title" value="<%= article.title %>"> <label for="title">标题</label>
<div style="margin-top: 15px; "></div> <input type="text" id="title" name="title" value="<%= article.title %>">
<label for="content">内容</label> </div>
<textarea rows="15" id="content" name="content" class="markdown-edit"><%= article.content %></textarea> <div class="field">
<% if (user && user.is_admin) { %> <label for="content">内容</label>
<div class="ui <% if (article.is_notice) { %>checked <% } %>checkbox" style="margin-top: 15px; "> </div>
<input <% if (article.is_notice) { %>checked=""<% } %> name="is_notice" type="checkbox">
<label><strong>公告</strong></label>
<p style="margin-top: 5px; ">选择后将显示在首页公告栏。</p>
</div>
<% } %>
</div> </div>
<div class="editor editor-with-border" id="content" style="width: 100%; height: 400px; margin-bottom: 1em; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="content">
<% if (user && user.is_admin) { %>
<div class="ui <% if (article.is_notice) { %>checked <% } %>checkbox" style="margin-top: 15px; ">
<input <% if (article.is_notice) { %>checked=""<% } %> name="is_notice" type="checkbox">
<label><strong>公告</strong></label>
<p style="margin-top: 5px; ">选择后将显示在首页公告栏。</p>
</div>
<% } %>
</div> </div>
<div class="ui bottom attached tab segment" data-tab="preview"> <div class="ui bottom attached tab segment" data-tab="preview">
<div class="ui header" id="pv-title"></div> <div class="ui header" id="pv-title"></div>
@ -40,17 +48,29 @@
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var editors = {
content: { defaultValue: <%- serializejs(article.content) %> },
};
window.onEditorLoaded(function () {
for (var name in editors) {
var editor = editors[name];
var editorElement = document.getElementById(name);
var input = document.getElementsByName(name)[0];
editor.editor = window.createMarkdownEditor(editorElement, editor.defaultValue, input);
}
});
$(function () { $(function () {
function render(output, input) { function render(output, input) {
$.post('/api/markdown', { s: input.val() }, function (s) { $.post('/api/markdown', { s: editors[input].editor.getValue() }, function (s) {
// console.log(s);
output.html(s); output.html(s);
}); });
} }
$("#preview_tab").click(function () { $("#preview_tab").click(function () {
$("#pv-title").text($("#title").val()); $("#pv-title").text($("#title").val());
$("#pv-content").text('Loading...'); $("#pv-content").text('Loading...');
render($("#pv-content"), $("#content")); render($("#pv-content"), "content");
}); });
$('.tabular.menu .item').tab(); $('.tabular.menu .item').tab();
}) })

41
views/contest_edit.ejs

@ -1,15 +1,22 @@
<% this.title = contest.id ? '编辑比赛' : '新建比赛' %> <% this.title = contest.id ? '编辑比赛' : '新建比赛' %>
<% include header %> <% include header %>
<% include monaco-editor %>
<div class="padding"> <div class="padding">
<form class="ui form" action="<%= syzoj.utils.makeUrl(['contest', contest.id, 'edit']) %>" method="post"> <form action="<%= syzoj.utils.makeUrl(['contest', contest.id, 'edit']) %>" method="post">
<div class="field"> <div class="ui form">
<div class="field">
<label>比赛名称</label> <label>比赛名称</label>
<input type="text" name="title" value="<%= contest.title %>"> <input type="text" name="title" value="<%= contest.title %>">
</div> </div>
<div class="field"> <div class="field">
<label>比赛描述</label> <label>比赛描述</label>
<input type="text" name="subtitle" class="markdown-edit" value="<%= contest.subtitle %>"> </div>
</div> </div>
<div id="subtitle" class="editor editor-with-border" style="height: 100px; width: 100%; margin-bottom: 1em; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="subtitle">
<div class="ui form">
<div class="field"> <div class="field">
<label>试题列表</label> <label>试题列表</label>
<select class="ui fluid search dropdown" multiple="" id="search_problems" name="problems"> <select class="ui fluid search dropdown" multiple="" id="search_problems" name="problems">
@ -53,8 +60,13 @@
</div> </div>
<div class="field"> <div class="field">
<label>比赛公告</label> <label>比赛公告</label>
<textarea class="" rows="5" id="doc-ta-1" name="information" class="markdown-edit"><%= contest.information %></textarea>
</div> </div>
</div>
<div id="information" class="editor editor-with-border" style="height: 100px; width: 100%; margin-bottom: 1em; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="information">
<div class="ui form">
<div class="field"> <div class="field">
<label>开始时间</label> <label>开始时间</label>
<input type="text" name="start_time" value="<%= syzoj.utils.formatDate(contest.start_time || syzoj.utils.getCurrentDate()) %>"> <input type="text" name="start_time" value="<%= syzoj.utils.formatDate(contest.start_time || syzoj.utils.getCurrentDate()) %>">
@ -78,8 +90,23 @@
</div> </div>
</div> </div>
<div style="text-align: center; "><button type="submit" class="ui labeled icon blue button"><i class="ui edit icon"></i>提交</button></div> <div style="text-align: center; "><button type="submit" class="ui labeled icon blue button"><i class="ui edit icon"></i>提交</button></div>
</div>
</form> </form>
<script> <script>
var editors = {
subtitle: { defaultValue: <%- serializejs(contest.subtitle) %> },
information: { defaultValue: <%- serializejs(contest.information) %> }
};
window.onEditorLoaded(function () {
for (var name in editors) {
var editor = editors[name];
var editorElement = document.getElementById(name);
var input = document.getElementsByName(name)[0];
editor.editor = window.createMarkdownEditor(editorElement, editor.defaultValue, input);
}
});
$(function () { $(function () {
$('#search_admins') $('#search_admins')
.dropdown({ .dropdown({

1
views/header.ejs

@ -11,7 +11,6 @@
<link href="<%- selfLib('math.css') %>" rel="stylesheet"> <link href="<%- selfLib('math.css') %>" rel="stylesheet">
<link href="<%- selfLib('style.css') %>?20181212" rel="stylesheet"> <link href="<%- selfLib('style.css') %>?20181212" rel="stylesheet">
<link href="<%- lib('morris.js/0.5.1/morris.css') %>" rel="stylesheet"> <link href="<%- lib('morris.js/0.5.1/morris.css') %>" rel="stylesheet">
<link href="<%- lib('monaco-editor/0.16.2/min/vs/editor/editor.main.css') %>" rel="stylesheet">
<% if (useLocalLibs || !syzoj.config.google_fonts || !syzoj.config.google_fonts.url || !['like-google-fonts', 'like-local'].includes(syzoj.config.google_fonts.type)) { %> <% if (useLocalLibs || !syzoj.config.google_fonts || !syzoj.config.google_fonts.url || !['like-google-fonts', 'like-local'].includes(syzoj.config.google_fonts.type)) { %>
<link href="<%- syzoj.utils.makeUrl(['google-fonts', 'fira-mono.css']) %>" rel="stylesheet"> <link href="<%- syzoj.utils.makeUrl(['google-fonts', 'fira-mono.css']) %>" rel="stylesheet">
<link href="<%- syzoj.utils.makeUrl(['google-fonts', 'lato.css']) %>" rel="stylesheet"> <link href="<%- syzoj.utils.makeUrl(['google-fonts', 'lato.css']) %>" rel="stylesheet">

31
views/monaco-editor.ejs

@ -1,8 +1,23 @@
<script> <script>
window.pathLib = "<%- lib('') %>"; window.pathLib = "<%- lib('') %>";
window.pathSelfLib = "<%- selfLib('') %>"; window.pathSelfLib = "<%- selfLib('') %>";
</script>
var originalConsoleWarn = console.warn;
<script src="<%- lib('monaco-editor/0.16.2/min/vs/loader.js') %>"></script> console.warn = function (message) {
<script src="<%- selfLib('monaco-editor.js') %>"></script> if (message.startsWith('Duplicate definition of module')) return;
<link rel="stylesheet" href="<%- selfLib('monaco-editor.css') %>"> originalConsoleWarn.apply(console, arguments);
};
</script>
<!-- Load monaco-editor -->
<script src="<%- lib('monaco-editor/0.16.2/min/vs/loader.js') %>"></script>
<script src="<%- selfLib('monaco-editor.js') %>"></script>
<link rel="stylesheet" href="<%- selfLib('monaco-editor.css') %>">
<%
this.showLoadingEditor = () => {
%>
<div class="ui active medium text loader">编辑器加载中 …</div>
<%
};
%>

22
views/problem.ejs

@ -241,15 +241,17 @@ if (contest) {
<div class="four wide column" style="margin-right: -25px; "> <div class="four wide column" style="margin-right: -25px; ">
<div class="ui attached vertical fluid pointing menu" id="testcase-menu" style="height: 370px; overflow-y: scroll; overflow-x: hidden; "> <div class="ui attached vertical fluid pointing menu" id="testcase-menu" style="height: 370px; overflow-y: scroll; overflow-x: hidden; ">
<% for (let i = 0; i < cases.length; i++) { %> <% for (let i = 0; i < cases.length; i++) { %>
<a class="item<%= i === 0 ? ' active' : '' %>" data-value="<%= i %>"> <a style="border-radius: 0; " class="item<%= i === 0 ? ' active' : '' %>" data-value="<%= i %>">
<%= cases[i] %> <%= cases[i] %>
</a> </a>
<% } %> <% } %>
</div> </div>
</div> </div>
<div class="twelve wide stretched column" style="position: relative; padding-left: 0; margin-left: calc(-1rem - 1px); width: calc(75% + 1rem + 12px) !important; "> <div class="twelve wide stretched column" style="position: relative; padding-left: 0; margin-left: calc(-1rem - 1px); width: calc(75% + 1rem + 13px) !important; ">
<% for (let i = 0; i < cases.length; i++) { %> <% for (let i = 0; i < cases.length; i++) { %>
<div id="editor-<%= i %>" class="editor" style="position: absolute; width: 100%; height: calc(100% - 28px); border: 1px solid #D4D4D5; <%= i === 0 ? '' : 'visibility: hidden; ' %>"></div> <div id="editor-<%= i %>" class="editor" style="position: absolute; width: 100%; height: calc(100% - 28px); border: 1px solid #D4D4D5; overflow: hidden; <%= i === 0 ? '' : 'visibility: hidden; ' %>">
<%- this.showLoadingEditor(); %>
</div>
<% } %> <% } %>
</div> </div>
<% } %> <% } %>
@ -258,7 +260,7 @@ if (contest) {
window.onEditorLoaded(function () { window.onEditorLoaded(function () {
window.editors = []; window.editors = [];
for (var i = 0; i < cases.length; i++) { for (var i = 0; i < cases.length; i++) {
var editor = window.createEditor(document.getElementById("editor-" + i)); var editor = window.createCodeEditor(document.getElementById("editor-" + i));
editors[i] = editor; editors[i] = editor;
} }
@ -305,15 +307,17 @@ if (contest) {
} else if (lastLanguage) language = lastLanguage; } else if (lastLanguage) language = lastLanguage;
%> %>
<% for (lang of syzoj.config.enabled_languages) { %> <% for (lang of syzoj.config.enabled_languages) { %>
<a class="item<%= lang === language ? ' active' : '' %>" data-value="<%= lang %>" data-mode="<%= syzoj.languages[lang].editor %>"> <a style="border-radius: 0; " class="item<%= lang === language ? ' active' : '' %>" data-value="<%= lang %>" data-mode="<%= syzoj.languages[lang].editor %>">
<%= syzoj.languages[lang].show %> <%= syzoj.languages[lang].show %>
<div class="ui right floated" style="opacity: 0.4; margin-top: 8px; font-size: 0.7em; "><%= syzoj.languages[lang].version %></div> <div class="ui right floated" style="opacity: 0.4; margin-top: 8px; font-size: 0.7em; "><%= syzoj.languages[lang].version %></div>
</a> </a>
<% } %> <% } %>
</div> </div>
</div> </div>
<div class="twelve wide stretched column" style="padding-left: 0; margin-left: calc(-1rem - 1px); width: calc(75% + 1rem + 1px + 25px) !important; "> <div class="twelve wide stretched column" style="position: relative; padding-left: 0; margin-left: calc(-1rem - 1px); width: calc(75% + 1rem + 13px) !important; ">
<div id="editor" style="border: 1px solid #D4D4D5; " class="editor"></div> <div id="editor" style="position: absolute; width: 100%; height: calc(100% - 28px); border: 1px solid #D4D4D5; overflow: hidden; " class="editor">
<%- this.showLoadingEditor(); %>
</div>
</div> </div>
<div class="ui form" style="width: 100%; "> <div class="ui form" style="width: 100%; ">
<div class="inline fields" style="width: 100%; "> <div class="inline fields" style="width: 100%; ">
@ -341,7 +345,7 @@ if (contest) {
var editorElement = document.getElementById('editor'); var editorElement = document.getElementById('editor');
var content = ''; var content = '';
<% if (state) { %>content = <%- serializejs(state.code) %>;<% } %> <% if (state) { %>content = <%- serializejs(state.code) %>;<% } %>
editor = window.createEditor(editorElement, 'ace_' + $('#languages-menu .item.active').data('mode'), content); editor = window.createCodeEditor(editorElement, $('#languages-menu .item.active').data('mode'), content);
window.editor = editor; window.editor = editor;
}); });
@ -366,7 +370,7 @@ if (contest) {
.not($(this)) .not($(this))
.removeClass('active') .removeClass('active')
; ;
monaco.editor.setModelLanguage(editor.getModel(), 'ace_' + $(this).data('mode')); monaco.editor.setModelLanguage(editor.getModel(), $(this).data('mode'));
}); });
}); });
</script> </script>

88
views/problem_edit.ejs

@ -5,14 +5,15 @@
text-align: center; text-align: center;
} }
</style> </style>
<% include monaco-editor %>
<div class="padding"> <div class="padding">
<form class="ui form" method="post" action="<%= syzoj.utils.makeUrl(['problem', req.params.id, 'edit']) %>"> <form method="post" action="<%= syzoj.utils.makeUrl(['problem', req.params.id, 'edit']) %>">
<div class="ui top attached tabular menu"> <div class="ui top attached tabular menu">
<a class="item active" data-tab="edit">编辑</a> <a class="item active" data-tab="edit">编辑</a>
<a class="item" data-tab="preview" id="preview_tab">预览</a> <a class="item" data-tab="preview" id="preview_tab">预览</a>
</div> </div>
<div class="ui bottom attached tab segment active" data-tab="edit"> <div class="ui bottom attached tab segment active" data-tab="edit">
<div class="field"> <div class="ui form"><div class="field">
<% if (problem.allowedManage) { %> <% if (problem.allowedManage) { %>
<label for="id"> <label for="id">
<% if (problem.new) { %> <% if (problem.new) { %>
@ -27,16 +28,47 @@
<% } %> <% } %>
<label for="title">题目名称</label> <label for="title">题目名称</label>
<input class="font-content" type="text" id="title" name="title" value="<%= problem.title %>"> <input class="font-content" type="text" id="title" name="title" value="<%= problem.title %>">
<label style="margin-top: 15px; " for="description">题目描述</label>
<textarea class="markdown-edit" rows="15" id="description" name="description"><%= problem.description %></textarea> <label style="margin-top: 15px; " for="description">题目描述</label>
<label style="margin-top: 15px; " for="input_format">输入格式</label> </div></div>
<textarea class="markdown-edit" rows="10" id="input" name="input_format"><%= problem.input_format %></textarea> <div class="editor editor-with-border" id="description" style="width: 100%; height: 300px; ">
<label style="margin-top: 15px; " for="output_format">输出格式</label> <%- this.showLoadingEditor(); %>
<textarea class="markdown-edit" rows="10" id="output" name="output_format"><%= problem.output_format %></textarea> </div>
<label style="margin-top: 15px; ">样例</label> <input type="hidden" name="description">
<textarea class="markdown-edit" rows="15" id="example" name="example"><%= problem.example %></textarea> <div class="ui form"><div class="field">
<label style="margin-top: 15px; ">数据范围与提示</label>
<textarea class="markdown-edit" rows="10" id="hint" name="limit_and_hint"><%= problem.limit_and_hint %></textarea> <label style="margin-top: 15px; " for="input_format">输入格式</label>
</div></div>
<div class="editor editor-with-border" id="input_format" style="width: 100%; height: 200px; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="input_format">
<div class="ui form"><div class="field">
<label style="margin-top: 15px; " for="output_format">输出格式</label>
</div></div>
<div class="editor editor-with-border" id="output_format" style="width: 100%; height: 200px; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="output_format">
<div class="ui form"><div class="field">
<label style="margin-top: 15px; " for="example">样例</label>
</div></div>
<div class="editor editor-with-border" id="example" style="width: 100%; height: 300px; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="example">
<div class="ui form"><div class="field">
<label style="margin-top: 15px; " for="limit_and_hint">数据范围与提示</label>
</div></div>
<div class="editor editor-with-border" id="limit_and_hint" style="width: 100%; height: 200px; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="limit_and_hint">
<div class="ui form"><div class="field">
<label style="margin-top: 15px; ">标签</label> <label style="margin-top: 15px; ">标签</label>
<select class="ui fluid search dropdown" multiple="" id="search_tags" name="tags"> <select class="ui fluid search dropdown" multiple="" id="search_tags" name="tags">
<% for (let tag of problem.tags) { %> <% for (let tag of problem.tags) { %>
@ -48,7 +80,7 @@
<label><strong>匿名上传</strong></label> <label><strong>匿名上传</strong></label>
<p style="margin-top: 5px; ">选择后,上传者的用户名将不在题目页面中显示。</p> <p style="margin-top: 5px; ">选择后,上传者的用户名将不在题目页面中显示。</p>
</div> </div>
</div> </div></div>
</div> </div>
<div class="ui bottom attached tab segment" data-tab="preview" id="preview"> <div class="ui bottom attached tab segment" data-tab="preview" id="preview">
<h1 class="ui header problem_header" id="pv-title"></h1> <h1 class="ui header problem_header" id="pv-title"></h1>
@ -73,21 +105,37 @@
</form> </form>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var editors = {
description: { defaultValue: <%- serializejs(problem.description) %> },
input_format: { defaultValue: <%- serializejs(problem.input_format) %> },
output_format: { defaultValue: <%- serializejs(problem.output_format) %> },
example: { defaultValue: <%- serializejs(problem.example) %> },
limit_and_hint: { defaultValue: <%- serializejs(problem.limit_and_hint) %> }
};
window.onEditorLoaded(function () {
for (var name in editors) {
var editor = editors[name];
var editorElement = document.getElementById(name);
var input = document.getElementsByName(name)[0];
editor.editor = window.createMarkdownEditor(editorElement, editor.defaultValue, input);
}
});
$(function () { $(function () {
function render(output, input) { function render(output, input) {
$.post('/api/markdown', { s: input.val() }, function (s) { $.post('/api/markdown', { s: editors[input].editor.getValue() }, function (s) {
// console.log(s);
output.html(s); output.html(s);
}); });
} }
$("#preview_tab").click(function () { $("#preview_tab").click(function () {
$("#pv-title").text($("#title").val()); $("#pv-title").text($("#title").val());
$("#pv-description, #pv-input, #pv-output, #pv-example, #pv-hint").text('Loading...'); $("#pv-description, #pv-input, #pv-output, #pv-example, #pv-hint").text('Loading...');
render($("#pv-description"), $("#description")); render($("#pv-description"), "description");
render($("#pv-input"), $("#input")); render($("#pv-input"), "input_format");
render($("#pv-output"), $("#output")); render($("#pv-output"), "output_format");
render($("#pv-example"), $("#example")); render($("#pv-example"), "example");
render($("#pv-hint"), $("#hint")); render($("#pv-hint"), "limit_and_hint");
}); });
$('.tabular.menu .item').tab(); $('.tabular.menu .item').tab();
}); });

31
views/user_edit.ejs

@ -1,5 +1,6 @@
<% this.title = '修改资料'; %> <% this.title = '修改资料'; %>
<% include header %> <% include header %>
<% include monaco-editor %>
<div class="padding"> <div class="padding">
<div class="ui <% if (error_info === '') { %>success<% } else { %>error<% } %> message" id="error" <% if (error_info === null) { %>hidden<% } %>> <div class="ui <% if (error_info === '') { %>success<% } else { %>error<% } %> message" id="error" <% if (error_info === null) { %>hidden<% } %>>
<% if (error_info !== null) { <% if (error_info !== null) {
@ -8,7 +9,8 @@
<p id="error_info"><%= error_info %></p> <p id="error_info"><%= error_info %></p>
<% } %> <% } %>
</div> </div>
<form id="form" class="ui form" action="<%= syzoj.utils.makeUrl(['user', edited_user.id, 'edit']) %>" method="post" onsubmit="return check()"> <form id="form" action="<%= syzoj.utils.makeUrl(['user', edited_user.id, 'edit']) %>" method="post" onsubmit="return check()">
<div class="ui form">
<div class="field"> <div class="field">
<label for="username">用户名</label> <label for="username">用户名</label>
<input type="text" id="username" name="username" value="<%= edited_user.username %>"<% if (!user.allowedManage) { %> readonly<% } %>> <input type="text" id="username" name="username" value="<%= edited_user.username %>"<% if (!user.allowedManage) { %> readonly<% } %>>
@ -40,9 +42,16 @@
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label for="information">个性签名</label> <label for="information">个性签名</label>
<textarea class="font-content" rows="5" id="information" name="information"><%= edited_user.information %></textarea> </div>
</div>
</div>
<div class="editor editor-with-border" id="information" style="width: 100%; height: 100px; margin-bottom: 1em; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="information">
<div class="ui form">
<div class="field"> <div class="field">
<label class="ui header">密码</label> <label class="ui header">密码</label>
<input type="password" placeholder="原密码(留空则不修改)" name="old_password" id="old_password"> <input type="password" placeholder="原密码(留空则不修改)" name="old_password" id="old_password">
@ -80,12 +89,26 @@
<div style="text-align: center; margin-top: 30px; "> <div style="text-align: center; margin-top: 30px; ">
<button type="submit" class="ui blue labeled icon button"><i class="ui icon edit"></i>修改</button> <button type="submit" class="ui blue labeled icon button"><i class="ui icon edit"></i>修改</button>
<a href="<%= syzoj.utils.makeUrl(['user', edited_user.id]) %>" class="ui labeled icon button"><i class="ui icon angle left"></i>返回</a> <a href="<%= syzoj.utils.makeUrl(['user', edited_user.id]) %>" class="ui labeled icon button"><i class="ui icon angle left"></i>返回</a>
</div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
<script src="<%- lib('blueimp-md5/2.10.0/js/md5.min.js') %>"></script> <script src="<%- lib('blueimp-md5/2.10.0/js/md5.min.js') %>"></script>
<script type="text/javascript"> <script type="text/javascript">
var editors = {
information: { defaultValue: <%- serializejs(edited_user.information) %> },
};
window.onEditorLoaded(function () {
for (var name in editors) {
var editor = editors[name];
var editorElement = document.getElementById(name);
var input = document.getElementsByName(name)[0];
editor.editor = window.createMarkdownEditor(editorElement, editor.defaultValue, input);
}
});
function make_md5(tag) { function make_md5(tag) {
if (tag.val()) { if (tag.val()) {
tag.val(md5(tag.val() + "syzoj2_xxx")); tag.val(md5(tag.val() + "syzoj2_xxx"));

Loading…
Cancel
Save