TCP 서버 모드 추가
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import React, { useEffect, useRef, memo } from 'react';
|
||||
import * as monaco from 'monaco-editor';
|
||||
|
||||
const MonacoEditor = memo(({
|
||||
id,
|
||||
value = '',
|
||||
language = 'javascript',
|
||||
readOnly = false,
|
||||
height = '64',
|
||||
onChange = () => {}
|
||||
}) => {
|
||||
const editorRef = useRef(null);
|
||||
const containerRef = useRef(null);
|
||||
const subscriptionRef = useRef(null);
|
||||
|
||||
// Configure editor options based on language
|
||||
const getEditorOptions = (lang) => {
|
||||
const baseOptions = {
|
||||
automaticLayout: true,
|
||||
theme: 'vs-light',
|
||||
minimap: { enabled: false },
|
||||
readOnly,
|
||||
scrollBeyondLastLine: false,
|
||||
fontSize: 14,
|
||||
lineHeight: 21,
|
||||
padding: { top: 8, bottom: 8 },
|
||||
tabSize: 2,
|
||||
scrollbar: {
|
||||
vertical: 'auto',
|
||||
horizontal: 'auto'
|
||||
}
|
||||
};
|
||||
|
||||
// Language-specific options
|
||||
switch (lang) {
|
||||
case 'json':
|
||||
return {
|
||||
...baseOptions,
|
||||
formatOnPaste: true,
|
||||
formatOnType: true,
|
||||
autoClosingBrackets: 'always',
|
||||
autoClosingQuotes: 'always',
|
||||
bracketPairColorization: { enabled: true }
|
||||
};
|
||||
case 'xml':
|
||||
return {
|
||||
...baseOptions,
|
||||
formatOnType: true,
|
||||
autoClosingTags: true,
|
||||
autoClosingBrackets: 'always',
|
||||
autoClosingQuotes: 'always'
|
||||
};
|
||||
default:
|
||||
return baseOptions;
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize or update editor
|
||||
const setupEditor = () => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
// Dispose existing editor if it exists
|
||||
if (editorRef.current) {
|
||||
editorRef.current.dispose();
|
||||
}
|
||||
|
||||
// Create new editor with language-specific options
|
||||
const options = getEditorOptions(language);
|
||||
editorRef.current = monaco.editor.create(containerRef.current, {
|
||||
value,
|
||||
language,
|
||||
...options
|
||||
});
|
||||
|
||||
// Set up change event handler
|
||||
if (subscriptionRef.current) {
|
||||
subscriptionRef.current.dispose();
|
||||
}
|
||||
|
||||
subscriptionRef.current = editorRef.current.onDidChangeModelContent(() => {
|
||||
const newValue = editorRef.current.getValue();
|
||||
onChange(newValue);
|
||||
});
|
||||
|
||||
// Format document if it's JSON
|
||||
if (language === 'json' && value) {
|
||||
try {
|
||||
const modelUri = monaco.Uri.parse(`inmemory://model-${id}.json`);
|
||||
const model = monaco.editor.createModel(value, 'json', modelUri);
|
||||
setTimeout(() => {
|
||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||
validate: true,
|
||||
allowComments: false,
|
||||
schemas: []
|
||||
});
|
||||
editorRef.current.setModel(model);
|
||||
}, 100);
|
||||
} catch (e) {
|
||||
console.warn('Failed to format JSON:', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initial setup
|
||||
useEffect(() => {
|
||||
setupEditor();
|
||||
|
||||
// Set up resize observer
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
if (editorRef.current) {
|
||||
editorRef.current.layout();
|
||||
}
|
||||
});
|
||||
|
||||
if (containerRef.current) {
|
||||
resizeObserver.observe(containerRef.current);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
if (subscriptionRef.current) {
|
||||
subscriptionRef.current.dispose();
|
||||
}
|
||||
if (editorRef.current) {
|
||||
editorRef.current.dispose();
|
||||
}
|
||||
};
|
||||
}, [language]); // Reinitialize when language changes
|
||||
|
||||
// Update value if it changes externally
|
||||
useEffect(() => {
|
||||
if (editorRef.current && value !== editorRef.current.getValue()) {
|
||||
editorRef.current.setValue(value);
|
||||
|
||||
// Add formatting for JSON
|
||||
if (language === 'json' && value) {
|
||||
try {
|
||||
const action = editorRef.current.getAction('editor.action.formatDocument');
|
||||
if (action) {
|
||||
action.run();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to format JSON:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [value, language]);
|
||||
|
||||
return (
|
||||
<div
|
||||
id={id}
|
||||
ref={containerRef}
|
||||
className={`h-${height} border mt-2`}
|
||||
style={{ minHeight: '100px' }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
MonacoEditor.displayName = 'MonacoEditor';
|
||||
|
||||
export default MonacoEditor;
|
||||
Reference in New Issue
Block a user