Skip to content

Commit 01ab895

Browse files
Merge pull request kailong321200875#467 from lt5227/feat/CodeEditor
feat: Add a new component CodeEditor (kailong321200875#466)
2 parents 3d1c8a8 + 00989b7 commit 01ab895

File tree

9 files changed

+422
-3
lines changed

9 files changed

+422
-3
lines changed

mock/role/index.mock.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@ const adminList = [
202202
meta: {
203203
title: 'router.jsonEditor'
204204
}
205+
},
206+
{
207+
path: 'code-editor',
208+
component: 'views/Components/Editor/CodeEditor',
209+
name: 'CodeEditor',
210+
meta: {
211+
title: 'router.codeEditor'
212+
}
205213
}
206214
]
207215
},
@@ -687,6 +695,7 @@ const testList: string[] = [
687695
'/components/editor-demo',
688696
'/components/editor-demo/editor',
689697
'/components/editor-demo/json-editor',
698+
'/components/editor-demo/code-editor',
690699
'/components/search',
691700
'/components/descriptions',
692701
'/components/image-viewer',

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
"vue-json-pretty": "^2.4.0",
5656
"vue-router": "^4.3.0",
5757
"vue-types": "^5.1.1",
58-
"xgplayer": "^3.0.14"
58+
"xgplayer": "^3.0.14",
59+
"monaco-editor": "^0.48.0"
5960
},
6061
"devDependencies": {
6162
"@commitlint/cli": "^19.2.1",

src/components/CodeEditor/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import CodeEditor from './src/CodeEditor.vue'
2+
3+
export { CodeEditor }
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<script setup lang="tsx">
2+
import { useMonacoEditor } from '@/hooks/web/useMonacoEditor'
3+
import { onMounted, computed, watch, ref } from 'vue'
4+
import { ElSelect, ElOption, ElFormItem, ElForm } from 'element-plus'
5+
import { languageOptions, themeOptions } from './config/config'
6+
7+
const props = withDefaults(
8+
defineProps<{
9+
width?: string | number
10+
height?: string | number
11+
languageSelector?: boolean
12+
language?: string
13+
themeSelector?: boolean
14+
theme?: string
15+
editorOption?: Object
16+
modelValue: string
17+
}>(),
18+
{
19+
width: '100%',
20+
height: '100%',
21+
languageSelector: true,
22+
language: 'javascript',
23+
themeSelector: true,
24+
theme: 'vs-dark',
25+
editorOption: () => ({}),
26+
modelValue: ''
27+
}
28+
)
29+
30+
const emits = defineEmits<{
31+
(e: 'blur'): void
32+
(e: 'update:modelValue', val: string): void
33+
}>()
34+
35+
const monacoEditorStyle = computed(() => {
36+
return {
37+
width: typeof props.width === 'string' ? props.width : props.width + 'px',
38+
height: typeof props.height === 'string' ? props.height : props.height + 'px'
39+
}
40+
})
41+
42+
const {
43+
monacoEditorRef,
44+
createEditor,
45+
updateVal,
46+
updateOptions,
47+
getEditor,
48+
changeLanguage,
49+
changeTheme
50+
} = useMonacoEditor(props.language)
51+
52+
onMounted(() => {
53+
const monacoEditor = createEditor(props.editorOption)
54+
updateMonacoVal(props.modelValue)
55+
monacoEditor?.onDidChangeModelContent(() => {
56+
emits('update:modelValue', monacoEditor!.getValue())
57+
})
58+
monacoEditor?.onDidBlurEditorText(() => {
59+
emits('blur')
60+
})
61+
})
62+
63+
watch(
64+
() => props.modelValue,
65+
() => {
66+
updateMonacoVal(props.modelValue)
67+
}
68+
)
69+
70+
const localLanguage = ref(props.language)
71+
72+
watch(localLanguage, (newLanguage) => {
73+
changeLanguage(newLanguage)
74+
})
75+
76+
const localTheme = ref(props.theme)
77+
watch(localTheme, (newTheme) => {
78+
changeTheme(newTheme)
79+
})
80+
81+
function updateMonacoVal(val: string) {
82+
if (val !== getEditor()?.getValue()) {
83+
updateVal(val)
84+
}
85+
}
86+
87+
defineExpose({ updateOptions })
88+
</script>
89+
90+
<template>
91+
<ElForm :inline="true">
92+
<ElFormItem v-if="languageSelector" label="language" class="w-30% mb-5px!">
93+
<ElSelect
94+
v-model="localLanguage"
95+
placeholder="Please select language"
96+
size="small"
97+
filterable
98+
>
99+
<ElOption
100+
v-for="item in languageOptions"
101+
:key="item.value"
102+
:label="item.label"
103+
:value="item.value"
104+
/>
105+
</ElSelect>
106+
</ElFormItem>
107+
<ElFormItem v-if="themeSelector" label="theme" class="w-30% mb-5px!">
108+
<ElSelect v-model="localTheme" placeholder="Please select language" size="small" filterable>
109+
<ElOption
110+
v-for="item in themeOptions"
111+
:key="item.value"
112+
:label="item.label"
113+
:value="item.value"
114+
/>
115+
</ElSelect>
116+
</ElFormItem>
117+
</ElForm>
118+
<div ref="monacoEditorRef" :style="monacoEditorStyle"></div>
119+
</template>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
export const languageOptions = [
2+
{ label: 'plaintext', value: 'plaintext' },
3+
{ label: 'abap', value: 'abap' },
4+
{ label: 'apex', value: 'apex' },
5+
{ label: 'azcli', value: 'azcli' },
6+
{ label: 'bat', value: 'bat' },
7+
{ label: 'bicep', value: 'bicep' },
8+
{ label: 'cameligo', value: 'cameligo' },
9+
{ label: 'clojure', value: 'clojure' },
10+
{ label: 'coffeescript', value: 'coffeescript' },
11+
{ label: 'c', value: 'c' },
12+
{ label: 'cpp', value: 'cpp' },
13+
{ label: 'csharp', value: 'csharp' },
14+
{ label: 'csp', value: 'csp' },
15+
{ label: 'css', value: 'css' },
16+
{ label: 'cypher', value: 'cypher' },
17+
{ label: 'dart', value: 'dart' },
18+
{ label: 'dockerfile', value: 'dockerfile' },
19+
{ label: 'ecl', value: 'ecl' },
20+
{ label: 'elixir', value: 'elixir' },
21+
{ label: 'flow9', value: 'flow9' },
22+
{ label: 'fsharp', value: 'fsharp' },
23+
{ label: 'freemarker2', value: 'freemarker2' },
24+
{
25+
label: 'freemarker2.tag-angle.interpolation-dollar',
26+
value: 'freemarker2.tag-angle.interpolation-dollar'
27+
},
28+
{
29+
label: 'freemarker2.tag-bracket.interpolation-dollar',
30+
value: 'freemarker2.tag-bracket.interpolation-dollar'
31+
},
32+
{
33+
label: 'freemarker2.tag-angle.interpolation-bracket',
34+
value: 'freemarker2.tag-angle.interpolation-bracket'
35+
},
36+
{
37+
label: 'freemarker2.tag-bracket.interpolation-bracket',
38+
value: 'freemarker2.tag-bracket.interpolation-bracket'
39+
},
40+
{
41+
label: 'freemarker2.tag-auto.interpolation-dollar',
42+
value: 'freemarker2.tag-auto.interpolation-dollar'
43+
},
44+
{
45+
label: 'freemarker2.tag-auto.interpolation-bracket',
46+
value: 'freemarker2.tag-auto.interpolation-bracket'
47+
},
48+
{ label: 'go', value: 'go' },
49+
{ label: 'graphql', value: 'graphql' },
50+
{ label: 'handlebars', value: 'handlebars' },
51+
{ label: 'hcl', value: 'hcl' },
52+
{ label: 'html', value: 'html' },
53+
{ label: 'ini', value: 'ini' },
54+
{ label: 'java', value: 'java' },
55+
{ label: 'javascript', value: 'javascript' },
56+
{ label: 'julia', value: 'julia' },
57+
{ label: 'kotlin', value: 'kotlin' },
58+
{ label: 'less', value: 'less' },
59+
{ label: 'lexon', value: 'lexon' },
60+
{ label: 'lua', value: 'lua' },
61+
{ label: 'liquid', value: 'liquid' },
62+
{ label: 'm3', value: 'm3' },
63+
{ label: 'markdown', value: 'markdown' },
64+
{ label: 'mdx', value: 'mdx' },
65+
{ label: 'mips', value: 'mips' },
66+
{ label: 'msdax', value: 'msdax' },
67+
{ label: 'mysql', value: 'mysql' },
68+
{ label: 'objective-c', value: 'objective-c' },
69+
{ label: 'pascal', value: 'pascal' },
70+
{ label: 'pascaligo', value: 'pascaligo' },
71+
{ label: 'perl', value: 'perl' },
72+
{ label: 'pgsql', value: 'pgsql' },
73+
{ label: 'php', value: 'php' },
74+
{ label: 'pla', value: 'pla' },
75+
{ label: 'postiats', value: 'postiats' },
76+
{ label: 'powerquery', value: 'powerquery' },
77+
{ label: 'powershell', value: 'powershell' },
78+
{ label: 'proto', value: 'proto' },
79+
{ label: 'pug', value: 'pug' },
80+
{ label: 'python', value: 'python' },
81+
{ label: 'qsharp', value: 'qsharp' },
82+
{ label: 'r', value: 'r' },
83+
{ label: 'razor', value: 'razor' },
84+
{ label: 'redis', value: 'redis' },
85+
{ label: 'redshift', value: 'redshift' },
86+
{ label: 'restructuredtext', value: 'restructuredtext' },
87+
{ label: 'ruby', value: 'ruby' },
88+
{ label: 'rust', value: 'rust' },
89+
{ label: 'sb', value: 'sb' },
90+
{ label: 'scala', value: 'scala' },
91+
{ label: 'scheme', value: 'scheme' },
92+
{ label: 'scss', value: 'scss' },
93+
{ label: 'shell', value: 'shell' },
94+
{ label: 'sol', value: 'sol' },
95+
{ label: 'aes', value: 'aes' },
96+
{ label: 'sparql', value: 'sparql' },
97+
{ label: 'sql', value: 'sql' },
98+
{ label: 'st', value: 'st' },
99+
{ label: 'swift', value: 'swift' },
100+
{ label: 'systemverilog', value: 'systemverilog' },
101+
{ label: 'verilog', value: 'verilog' },
102+
{ label: 'tcl', value: 'tcl' },
103+
{ label: 'twig', value: 'twig' },
104+
{ label: 'typescript', value: 'typescript' },
105+
{ label: 'vb', value: 'vb' },
106+
{ label: 'wgsl', value: 'wgsl' },
107+
{ label: 'xml', value: 'xml' },
108+
{ label: 'yaml', value: 'yaml' },
109+
{ label: 'json', value: 'json' }
110+
]
111+
112+
export const themeOptions = [
113+
{
114+
label: 'vs',
115+
value: 'vs'
116+
},
117+
{
118+
label: 'vs-dark',
119+
value: 'vs-dark'
120+
},
121+
{
122+
label: 'hc-black',
123+
value: 'hc-black'
124+
},
125+
{
126+
label: 'hc-light',
127+
value: 'hc-light'
128+
}
129+
]

0 commit comments

Comments
 (0)