diff --git a/packages/ui-default/build/config/webpack.js b/packages/ui-default/build/config/webpack.js index 6c29d4bfe..0be6cf76e 100644 --- a/packages/ui-default/build/config/webpack.js +++ b/packages/ui-default/build/config/webpack.js @@ -175,7 +175,7 @@ export default function (env = {}) { }), 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', 'julia'], + languages: ['markdown', 'yaml', 'cpp', 'csharp', 'java', 'javascript', 'python', 'rust', 'ruby', 'php', 'pascal', 'go', 'julia'], }), new StaticManifestPlugin({ fileName: 'static-manifest.json', diff --git a/packages/ui-default/components/discussion/CommentBox.js b/packages/ui-default/components/discussion/CommentBox.js index 82ed55aba..a2a85cc38 100644 --- a/packages/ui-default/components/discussion/CommentBox.js +++ b/packages/ui-default/components/discussion/CommentBox.js @@ -1,7 +1,7 @@ import _ from 'lodash'; import DOMAttachedObject from 'vj/components/DOMAttachedObject'; import request from 'vj/utils/request'; -import TextareaHandler from 'vj/components/cmeditor/textareaHandler'; +import TextareaHandler from 'vj/components/editor/textareaHandler'; import Notification from 'vj/components/notification'; let initialized = false; diff --git a/packages/ui-default/components/cmeditor/EditorComponent.jsx b/packages/ui-default/components/editor/EditorComponent.jsx similarity index 100% rename from packages/ui-default/components/cmeditor/EditorComponent.jsx rename to packages/ui-default/components/editor/EditorComponent.jsx diff --git a/packages/ui-default/components/cmeditor/cmeditor.page.js b/packages/ui-default/components/editor/cmeditor.page.js similarity index 100% rename from packages/ui-default/components/cmeditor/cmeditor.page.js rename to packages/ui-default/components/editor/cmeditor.page.js diff --git a/packages/ui-default/components/cmeditor/cmeditor.styl b/packages/ui-default/components/editor/cmeditor.styl similarity index 100% rename from packages/ui-default/components/cmeditor/cmeditor.styl rename to packages/ui-default/components/editor/cmeditor.styl diff --git a/packages/ui-default/components/cmeditor/index.js b/packages/ui-default/components/editor/index.js similarity index 54% rename from packages/ui-default/components/cmeditor/index.js rename to packages/ui-default/components/editor/index.js index 6edcf6caa..be461a9c4 100644 --- a/packages/ui-default/components/cmeditor/index.js +++ b/packages/ui-default/components/editor/index.js @@ -24,23 +24,62 @@ export const config = { }, }; -export default class CmEditor extends DOMAttachedObject { - static DOMAttachKey = 'vjCmEditorInstance'; +export default class Editor extends DOMAttachedObject { + static DOMAttachKey = 'vjEditorInstance'; constructor($dom, options = {}) { super($dom); this.options = options; - this.init(); + if (UserContext.preferredEditorType === 'monaco') this.initMonaco(); + else this.initVditor(); } - async init() { + async initMonaco() { + const monaco = await import('monaco-editor/esm/vs/editor/editor.api'); + const { $dom } = this; + const hasFocus = $dom.is(':focus'); + const origin = $dom.get(0); + const ele = document.createElement('div'); + $(ele).height(550); + $(ele).width('100%'); + $(ele).addClass('textbox'); + $dom.hide(); + origin.parentElement.appendChild(ele); + const value = $dom.val(); + const { + onChange, language = 'markdown', theme = 'vs-light', model = `file://model-${Math.random().toString(16)}`, + } = this.options; + this.model = monaco.editor.createModel(value, language, monaco.Uri.parse(model)); + this.editor = monaco.editor.create( + ele, + { + theme, + lineNumbers: true, + glyphMargin: true, + lightbulb: { + enabled: true, + }, + model: this.model, + } + ); + this._subscription = this.editor.onDidChangeModelContent(() => { + const val = this.editor.getValue(); + $dom.val(val); + $dom.text(val); + if (onChange) onChange(val); + }); + this.isValid = true; + if (hasFocus) this.editor.focus(); + } + + async initVditor() { const { default: Vditor } = await import('vditor'); const { $dom } = this; const hasFocus = $dom.is(':focus'); const origin = $dom.get(0); const ele = document.createElement('div'); const value = $dom.val(); - const onChange = this.options.onChange; + const { onChange } = this.options; await new Promise((resolve) => { this.editor = new Vditor(ele, { ...config, @@ -78,4 +117,4 @@ export default class CmEditor extends DOMAttachedObject { } } -_.assign(CmEditor, DOMAttachedObject); +_.assign(Editor, DOMAttachedObject); diff --git a/packages/ui-default/components/cmeditor/textareaHandler.js b/packages/ui-default/components/editor/textareaHandler.js similarity index 90% rename from packages/ui-default/components/cmeditor/textareaHandler.js rename to packages/ui-default/components/editor/textareaHandler.js index 572742180..90924319f 100644 --- a/packages/ui-default/components/cmeditor/textareaHandler.js +++ b/packages/ui-default/components/editor/textareaHandler.js @@ -1,12 +1,12 @@ import _ from 'lodash'; import DOMAttachedObject from 'vj/components/DOMAttachedObject'; -import CmEditor from './index'; +import Editor from './index'; export default class TextareaHandler extends DOMAttachedObject { static DOMAttachKey = 'vjTextareaHandlerInstance'; getCmEditor() { - return CmEditor.get(this.$dom); + return Editor.get(this.$dom); } isCmEditor() { diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 79ec75802..453034174 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.6.26", + "version": "4.6.27", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/pages/problem_edit.page.js b/packages/ui-default/pages/problem_edit.page.js index b49391166..13d247daf 100644 --- a/packages/ui-default/pages/problem_edit.page.js +++ b/packages/ui-default/pages/problem_edit.page.js @@ -5,7 +5,7 @@ import tpl from 'vj/utils/tpl'; import i18n from 'vj/utils/i18n'; import { ConfirmDialog } from 'vj/components/dialog'; import Dropdown from 'vj/components/dropdown/Dropdown'; -import CmEditor from 'vj/components/cmeditor/index'; +import Editor from 'vj/components/editor/index'; const categories = {}; const dirtyCategories = []; @@ -253,6 +253,6 @@ export default new NamedPage(['problem_create', 'problem_edit'], (pagename) => { else content[i] = val; $main.val(JSON.stringify(content)); } - CmEditor.getOrConstruct($dom, { upload, onChange }); + Editor.getOrConstruct($dom, { upload, onChange }); }); }); diff --git a/packages/ui-default/setting.yaml b/packages/ui-default/setting.yaml index accd561d4..e6655296e 100644 --- a/packages/ui-default/setting.yaml +++ b/packages/ui-default/setting.yaml @@ -86,6 +86,7 @@ preferredEditorType: wysiwyg: WYSIWYG ir: Instant Rendering sv: Split View + monaco: Monaco Editor family: markdown category: preference value: sv diff --git a/packages/ui-default/theme/98.js b/packages/ui-default/theme/98.js index f358ccdd0..26021b22d 100644 --- a/packages/ui-default/theme/98.js +++ b/packages/ui-default/theme/98.js @@ -16,7 +16,7 @@ import 'vj/misc/structure.styl'; import 'vj/misc/section.98.styl'; import 'vj/misc/nothing.styl'; -import 'vj/components/cmeditor/cmeditor.styl'; +import 'vj/components/editor/cmeditor.styl'; import 'vj/components/datepicker/datepicker.styl'; import 'vj/components/katex/katex.styl'; diff --git a/packages/ui-default/theme/default.js b/packages/ui-default/theme/default.js index 7623e0ea9..142b070c4 100644 --- a/packages/ui-default/theme/default.js +++ b/packages/ui-default/theme/default.js @@ -17,7 +17,7 @@ import 'vj/misc/structure.styl'; import 'vj/misc/section.styl'; import 'vj/misc/nothing.styl'; -import 'vj/components/cmeditor/cmeditor.styl'; +import 'vj/components/editor/cmeditor.styl'; import 'vj/components/datepicker/datepicker.styl'; import 'vj/components/katex/katex.styl';