ui: preferredEditor: monaco

This commit is contained in:
undefined committed 2021-05-04 14:01:45 +08:00
1 parent b82a26c903
commit f29dc43fec
12 files changed
+55 -15

No files matched your search

@@ -0,0 +1,38 @@
import React from 'react';
import Vditor from 'vditor';
import { config } from './index';
export default class MarkdownEditor extends React.PureComponent {
constructor(props) {
super(props);
this.ref = React.createRef();
}
async componentDidMount() {
await new Promise((resolve) => {
this.editor = new Vditor(this.ref.current, {
...config,
after: resolve,
input(value) { this.props.onChange(value); },
cache: { id: Math.random().toString() },
});
});
}
componentWillUnmount() {
this.editor.destory();
this.editor.detach();
}
value() {
return this.editor.getValue();
}
focus() {
return this.editor.focus();
}
render() {
return <div ref={this.ref}></div>;
}
}
@@ -0,0 +1,20 @@
import { AutoloadPage } from 'vj/misc/Page';
import delay from 'vj/utils/delay';
import CmEditor from '.';
function runSubstitute($container) {
const selector = ['textarea[data-markdown]'];
$container.find(selector.join(', ')).get().forEach((element) => {
CmEditor.getOrConstruct($(element));
});
}
const cmEditorPage = new AutoloadPage('cmEditorPage', () => {
runSubstitute($('body'));
$(document).on('vjContentNew', async (e) => {
await delay(0);
runSubstitute($(e.target));
});
});
export default cmEditorPage;
@@ -0,0 +1,8 @@
.vditor
margin-bottom: rem(10px)
.vditor-preview__action
display: none
.vditor ol
list-style: decimal
@@ -0,0 +1,120 @@
import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
export const config = {
toolbar: [
'emoji', 'headings', 'bold', 'italic', 'strike', 'link', '|',
'list', 'ordered-list', 'check', 'outdent', 'indent', '|',
'quote', 'line', 'code', 'inline-code', 'table', '|',
'upload', 'edit-mode', 'fullscreen', 'export',
],
mode: UserContext.preferredEditorType || 'sv',
toolbarConfig: {
pin: true,
},
cdn: `${UiContext.cdn_prefix}vditor`,
counter: {
enable: true,
max: 65536,
},
preview: {
math: {
inlineDigit: true,
},
},
};
export default class Editor extends DOMAttachedObject {
static DOMAttachKey = 'vjEditorInstance';
constructor($dom, options = {}) {
super($dom);
this.options = options;
if (UserContext.preferredEditorType === 'monaco') this.initMonaco();
else this.initVditor();
}
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;
await new Promise((resolve) => {
this.editor = new Vditor(ele, {
...config,
...this.options,
after: resolve,
input(v) {
$dom.val(v);
$dom.text(v);
if (onChange) onChange(v);
},
value,
cache: { id: Math.random().toString() },
});
});
$(ele).addClass('textbox');
$dom.hide();
origin.parentElement.appendChild(ele);
this.isValid = true;
if (hasFocus) this.focus();
}
ensureValid() {
if (!this.isValid) throw new Error('Editor is not loaded');
}
value(val) {
this.ensureValid();
if (val) return this.editor.setValue(val);
return this.editor.getValue();
}
focus() {
this.ensureValid();
this.editor.focus();
}
}
_.assign(Editor, DOMAttachedObject);
@@ -0,0 +1,32 @@
import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import Editor from './index';
export default class TextareaHandler extends DOMAttachedObject {
static DOMAttachKey = 'vjTextareaHandlerInstance';
getCmEditor() {
return Editor.get(this.$dom);
}
isCmEditor() {
const editor = this.getCmEditor();
return !!(editor && editor.isValid);
}
val(...argv) {
if (this.isCmEditor()) {
return this.getCmEditor().value(...argv);
}
return this.$dom.val(...argv);
}
focus() {
if (this.isCmEditor()) {
this.getCmEditor().focus();
}
this.$dom.focus();
}
}
_.assign(TextareaHandler, DOMAttachedObject);