feat: Monaco editor for StringEditor
- Install monaco-editor + @guolao/vue-monaco-editor - main.ts: loader.config + MonacoEnvironment worker setup - StringEditor.vue: replace textarea with Monaco editor - JSON syntax highlighting, folding, word wrap - Read-only mode when not editing, auto-detect JSON - Theme follows app theme (vs-dark/vs) - Font size follows app settings
This commit is contained in:
@@ -1,17 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
// src/renderer/src/components/StringEditor.vue
|
||||
import { ref, watch } from 'vue'
|
||||
// src/components/StringEditor.vue
|
||||
import { ref, watch, computed } from 'vue'
|
||||
import { VueMonacoEditor } from '@guolao/vue-monaco-editor'
|
||||
import { useKeyStore } from '@renderer/stores/key'
|
||||
import { useConnectionStore } from '@renderer/stores/connection'
|
||||
import { useAppStore } from '@renderer/stores/app'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const keyStore = useKeyStore()
|
||||
const connStore = useConnectionStore()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const editedValue = ref('')
|
||||
const isJson = ref(false)
|
||||
const isEditing = ref(false)
|
||||
|
||||
const monacoTheme = computed(() => {
|
||||
if (appStore.theme === 'light') return 'vs'
|
||||
if (appStore.theme === 'dark') return 'vs-dark'
|
||||
return 'vs-dark' // system default (will be refined)
|
||||
})
|
||||
|
||||
function formatValue(val: string | null) {
|
||||
if (val === null) return ''
|
||||
try {
|
||||
@@ -35,6 +44,25 @@ watch(
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const editorOptions = computed(() => ({
|
||||
readOnly: !isEditing.value,
|
||||
minimap: { enabled: false },
|
||||
fontSize: appStore.fontSize,
|
||||
wordWrap: 'on' as const,
|
||||
scrollBeyondLastLine: false,
|
||||
automaticLayout: true,
|
||||
tabSize: 2,
|
||||
lineNumbers: 'on' as const,
|
||||
folding: true,
|
||||
renderWhitespace: 'none',
|
||||
scrollbar: {
|
||||
vertical: 'auto' as const,
|
||||
horizontal: 'auto' as const,
|
||||
verticalScrollbarSize: 6,
|
||||
horizontalScrollbarSize: 6,
|
||||
},
|
||||
}))
|
||||
|
||||
async function save() {
|
||||
if (!connStore.activeId || !keyStore.selectedKey) return
|
||||
try {
|
||||
@@ -59,14 +87,12 @@ async function save() {
|
||||
</template>
|
||||
</div>
|
||||
<div class="editor-content">
|
||||
<el-input
|
||||
v-model="editedValue"
|
||||
type="textarea"
|
||||
:rows="12"
|
||||
:disabled="!isEditing"
|
||||
:class="{ json: isJson }"
|
||||
spellcheck="false"
|
||||
class="editor-textarea"
|
||||
<vue-monaco-editor
|
||||
v-model:value="editedValue"
|
||||
:theme="monacoTheme"
|
||||
:language="isJson ? 'json' : 'plaintext'"
|
||||
:options="editorOptions"
|
||||
height="100%"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,17 +126,6 @@ async function save() {
|
||||
|
||||
.editor-content {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.editor-textarea :deep(.el-textarea__inner) {
|
||||
background: var(--bg-primary);
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-primary);
|
||||
font-family: 'Cascadia Code', 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
resize: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
+15
@@ -4,9 +4,24 @@ import { createPinia } from 'pinia'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import { loader } from '@guolao/vue-monaco-editor'
|
||||
import * as monaco from 'monaco-editor'
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
||||
import App from './App.vue'
|
||||
import './styles/global.css'
|
||||
|
||||
// Monaco worker setup for Vite
|
||||
self.MonacoEnvironment = {
|
||||
getWorker(_, label) {
|
||||
if (label === 'json') return new jsonWorker()
|
||||
return new editorWorker()
|
||||
},
|
||||
}
|
||||
|
||||
// Use local monaco-editor
|
||||
loader.config({ monaco })
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(createPinia())
|
||||
app.use(ElementPlus, { size: 'small' })
|
||||
|
||||
Reference in New Issue
Block a user