ui: quick emoji input support

This commit is contained in:
undefined committed 2021-09-13 21:07:16 +08:00
1 parent 402a58cd47
commit fae452cc94
6 files changed
+255 -108

No files matched your search

@@ -55,8 +55,7 @@ export default class Editor extends DOMAttachedObject {
// eslint-disable-next-line no-nested-ternary
this.model = typeof model === 'string'
? monaco.editor.getModel(monaco.Uri.parse(model))
? monaco.editor.getModel(monaco.Uri.parse(model))
: monaco.editor.createModel(value, language, monaco.Uri.parse(model))
|| monaco.editor.createModel(value, language, monaco.Uri.parse(model))
: model;
this.model.setValue(value);
this.model.updateOptions({ language });
@@ -111,6 +110,8 @@ export default class Editor extends DOMAttachedObject {
this.isValid = true;
if (hasFocus) this.focus();
if (autoResize) updateEditorHeight();
window.model = this.model;
window.editor = this.editor;
}
async initVditor() {
+3 -105
View File
@@ -1,111 +1,9 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import loadFormatter from 'vj/components/wastyle/index';
import Notification from 'vj/components/notification';
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false,
});
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES6,
allowNonTsExtensions: true,
});
const libSource = [
'declare function readline(): string;',
'declare function print(content: string): void;',
].join('\n');
const libUri = 'ts:filename/basic.d.ts';
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, libUri);
monaco.editor.createModel(libSource, 'typescript', monaco.Uri.parse(libUri));
/** @type {Record<string, import('json-schema').JSONSchema7Definition>} */
const problemConfigSchemaDef = {
cases: { type: 'array', items: { $ref: '#/def/case' } },
case: {
type: 'object',
properties: {
input: { type: 'string' },
output: { type: 'string' },
},
required: ['input'],
additionalProperties: false,
},
subtask: {
description: 'Subtask Info',
type: 'object',
properties: {
type: { enum: ['min', 'max', 'sum'] },
time: { $ref: '#/def/time' },
memory: { $ref: '#/def/memory' },
score: { $ref: '#/def/score', description: 'score' },
cases: { $ref: '#/def/cases' },
if: { type: 'array', items: { type: 'integer' } },
id: { type: 'integer' },
},
required: ['score'],
additionalProperties: false,
},
time: { type: 'string', pattern: '^([0-9]+(?:\\.[0-9]*)?)([mu]?)s?$' },
memory: { type: 'string', pattern: '^([0-9]+(?:\\.[0-9]*)?)([kmg])b?$' },
score: { type: 'integer', maximum: 100, minimum: 1 },
};
/** @type {import('json-schema').JSONSchema7Definition} */
const problemConfigSchema = {
type: 'object',
def: problemConfigSchemaDef,
properties: {
key: { type: 'string', pattern: '[0-9a-f]{32}' },
type: { enum: ['default', 'interactive', 'submit_answer', 'objective', 'remote_judge'] },
subType: { type: 'string' },
langs: { type: 'array', items: { type: 'string' } },
target: { type: 'string' },
checker_type: { enum: ['default', 'lemon', 'syzoj', 'hustoj', 'testlib', 'strict', 'qduoj'] },
checker: { type: 'string', pattern: '\\.' },
interactor: { type: 'string', pattern: '\\.' },
user_extra_files: { type: 'array', items: { type: 'string' } },
judge_extra_files: { type: 'array', items: { type: 'string' } },
cases: { $ref: '#/def/cases' },
subtasks: { type: 'array', items: { $ref: '#/def/subtask' } },
filename: { type: 'string' },
detail: { type: 'boolean' },
time: { $ref: '#/def/time' },
memory: { $ref: '#/def/memory' },
score: { $ref: '#/def/score' },
template: {
type: 'object',
patternProperties: {
'^.*$': {
type: 'array',
minLength: 2,
maxLength: 2,
items: { type: 'string' },
},
},
additionalProperties: false,
},
outputs: {
type: 'array',
minLength: 1,
},
},
additionalProperties: false,
};
monaco.languages.yaml.yamlDefaults.setDiagnosticsOptions({
validate: true,
enableSchemaRequest: true,
hover: true,
completion: true,
format: true,
schemas: [
{
uri: 'https://hydro.js.org/schema/problemConfig.json',
fileMatch: ['hydro://problem/file/config.yaml'],
schema: problemConfigSchema,
},
],
});
import './languages/markdown';
import './languages/typescript';
import './languages/yaml';
export default monaco;
@@ -0,0 +1,138 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import list from 'emojis-list';
import keyword from 'emojis-keywords';
const qqEmojies = [
'weixiao',
'piezui',
'se',
'fadai',
'deyi',
'liulei',
'haixiu',
'bizui',
'shui',
'daku',
'ganga',
'fanu',
'tiaopi',
'ciya',
'jingya',
'nanguo',
'ku',
'lenghan',
'zhuakuang',
'tu',
'touxiao',
'keai',
'baiyan',
'aoman',
'jie',
'kun',
'jingkong',
'liuhan',
'hanxiao',
'dabing',
'fendou',
'zhouma',
'yiwen',
'xu',
'yun',
'zhemo',
'shuai',
'kulou',
'qiaoda',
'zaijian',
'cahan',
'koubi',
'guzhang',
'qiudale',
'huaixiao',
'zuohengheng',
'youhengheng',
'haqian',
'bishi',
'weiqu',
'kuaikule',
'yinxian',
'qinqin',
'xia',
'kelian',
'caidao',
'xigua',
'pijiu',
'lanqiu',
'pingpang',
'kafei',
'fan',
'zhutou',
'meigui',
'diaoxie',
'shiai',
'aixin',
'xinsui',
'dangao',
'shandian',
'zhadan',
'dao',
'zuqiu',
'piaochong',
'bianbian',
'yueliang',
'taiyang',
'liwu',
'yongbao',
'qiang',
'ruo',
'woshou',
'shengli',
'baoquan',
'gouyin',
'quantou',
'chajin',
'aini',
'no',
'ok',
];
function emoji(range) {
return keyword.map((i, index) => ({
label: `${list[index]} ${i}`,
kind: monaco.languages.CompletionItemKind.Keyword,
documentation: i,
insertText: list[index],
range,
}));
}
function qqEmoji(range) {
return qqEmojies.map((i, index) => ({
label: `/${i}`,
kind: monaco.languages.CompletionItemKind.Keyword,
documentation: `/${i}`,
insertText: `![${i}](//qq-face.vercel.app/gif/s${index}.gif =32x32) `,
range,
}));
}
monaco.languages.registerCompletionItemProvider('markdown', {
provideCompletionItems(model, position) {
const word = model.getWordAtPosition(position);
const prefix = model.getValueInRange({
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: word.startColumn - 1,
endColumn: position.column - 1,
});
if (![':', '/'].includes(prefix)) return { suggestions: [] };
const range = {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: word.startColumn - 1,
endColumn: word.endColumn,
};
return {
suggestions: prefix === ':' ? emoji(range) : qqEmoji(range),
};
},
});
@@ -0,0 +1,17 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false,
});
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES2020,
allowNonTsExtensions: true,
});
const libSource = [
'declare function readline(): string;',
'declare function print(content: string): void;',
].join('\n');
const libUri = 'ts:filename/basic.d.ts';
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, libUri);
monaco.editor.createModel(libSource, 'typescript', monaco.Uri.parse(libUri));
@@ -0,0 +1,91 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
/** @type {Record<string, import('json-schema').JSONSchema7Definition>} */
const problemConfigSchemaDef = {
cases: { type: 'array', items: { $ref: '#/def/case' } },
case: {
type: 'object',
properties: {
input: { type: 'string' },
output: { type: 'string' },
},
required: ['input'],
additionalProperties: false,
},
subtask: {
description: 'Subtask Info',
type: 'object',
properties: {
type: { enum: ['min', 'max', 'sum'] },
time: { $ref: '#/def/time' },
memory: { $ref: '#/def/memory' },
score: { $ref: '#/def/score', description: 'score' },
cases: { $ref: '#/def/cases' },
if: { type: 'array', items: { type: 'integer' } },
id: { type: 'integer' },
},
required: ['score'],
additionalProperties: false,
},
time: { type: 'string', pattern: '^([0-9]+(?:\\.[0-9]*)?)([mu]?)s?$' },
memory: { type: 'string', pattern: '^([0-9]+(?:\\.[0-9]*)?)([kmg])b?$' },
score: { type: 'integer', maximum: 100, minimum: 1 },
};
/** @type {import('json-schema').JSONSchema7Definition} */
const problemConfigSchema = {
type: 'object',
def: problemConfigSchemaDef,
properties: {
key: { type: 'string', pattern: '[0-9a-f]{32}' },
type: { enum: ['default', 'interactive', 'submit_answer', 'objective', 'remote_judge'] },
subType: { type: 'string' },
langs: { type: 'array', items: { type: 'string' } },
target: { type: 'string' },
checker_type: { enum: ['default', 'lemon', 'syzoj', 'hustoj', 'testlib', 'strict', 'qduoj'] },
checker: { type: 'string', pattern: '\\.' },
interactor: { type: 'string', pattern: '\\.' },
user_extra_files: { type: 'array', items: { type: 'string' } },
judge_extra_files: { type: 'array', items: { type: 'string' } },
cases: { $ref: '#/def/cases' },
subtasks: { type: 'array', items: { $ref: '#/def/subtask' } },
filename: { type: 'string' },
detail: { type: 'boolean' },
time: { $ref: '#/def/time' },
memory: { $ref: '#/def/memory' },
score: { $ref: '#/def/score' },
template: {
type: 'object',
patternProperties: {
'^.*$': {
type: 'array',
minLength: 2,
maxLength: 2,
items: { type: 'string' },
},
},
additionalProperties: false,
},
outputs: {
type: 'array',
minLength: 1,
},
},
additionalProperties: false,
};
// @ts-ignore
monaco.languages.yaml.yamlDefaults.setDiagnosticsOptions({
validate: true,
enableSchemaRequest: true,
hover: true,
completion: true,
format: true,
schemas: [
{
uri: 'https://hydro.js.org/schema/problemConfig.json',
fileMatch: ['hydro://problem/file/config.yaml'],
schema: problemConfigSchema,
},
],
});
+3 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
"version": "4.20.1",
"version": "4.20.2",
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0",
"main": "hydro.js",
@@ -32,6 +32,8 @@
"diff-dom": "^4.2.2",
"echarts": "^5.2.0",
"emojify.js": "^1.1.0",
"emojis-keywords": "2.0.0",
"emojis-list": "2.1.0",
"esbuild-loader": "^2.15.1",
"eslint": "^7.32.0",
"eslint-config-airbnb": "^18.2.1",