From 3556d00584d7186a22ade76efcb57eb4424df5fd Mon Sep 17 00:00:00 2001 From: Bori-github Date: Tue, 4 Nov 2025 14:52:04 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EB=8B=A8=EC=B6=95=ED=82=A4?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=ED=95=B4=20prettier=20=ED=8F=AC=EB=A7=B7?= =?UTF-8?q?=ED=8C=85=20=EC=A7=80=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/widgets/code-editor/code-editor.tsx | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/apps/executeJS/src/widgets/code-editor/code-editor.tsx b/apps/executeJS/src/widgets/code-editor/code-editor.tsx index 7845edc..7618b82 100644 --- a/apps/executeJS/src/widgets/code-editor/code-editor.tsx +++ b/apps/executeJS/src/widgets/code-editor/code-editor.tsx @@ -1,5 +1,10 @@ import React, { useRef } from 'react'; + import { Editor, EditorProps } from '@monaco-editor/react'; +import prettier from 'prettier/standalone'; +import babel from 'prettier/plugins/babel'; +import estree from 'prettier/plugins/estree'; + import type { CodeEditorProps } from '../../shared/types'; export const CodeEditor: React.FC = ({ @@ -16,12 +21,51 @@ export const CodeEditor: React.FC = ({ try { editorRef.current = editor; - // Cmd+Enter 키바인딩 추가 + // Prettier 포맷터 등록 + monaco.languages.registerDocumentFormattingEditProvider(language, { + async provideDocumentFormattingEdits(model) { + const text = model.getValue(); + + try { + const formatted = await prettier.format(text, { + parser: 'babel', + plugins: [babel, estree], + semi: true, + trailingComma: 'es5', + singleQuote: true, + printWidth: 80, + tabWidth: 2, + useTabs: false, + }); + + return [ + { + range: model.getFullModelRange(), + text: formatted, + }, + ]; + } catch (error) { + console.error('Prettier formatting error:', error); + return []; + } + }, + }); + + // 단축키 바인딩 if (monaco && monaco.KeyMod && monaco.KeyCode) { + // Cmd+Enter 코드 실행 editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { const currentValue = editor.getValue(); onExecute?.(currentValue); }); + + // Cmd+Shift+F prettier 포맷 실행 + editor.addCommand( + monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KeyF, + () => { + editor.getAction('editor.action.formatDocument')?.run(); + } + ); } // 에디터 포커스 From ffff45726ce400c0e0702f53931062042e112cc7 Mon Sep 17 00:00:00 2001 From: Bori-github Date: Tue, 4 Nov 2025 19:20:35 +0900 Subject: [PATCH 2/5] fix: format check --- docs/docs/dev/_meta.json | 5 +---- docs/docs/guide/_meta.json | 6 +----- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/docs/docs/dev/_meta.json b/docs/docs/dev/_meta.json index 7b4cfd1..56bfa59 100644 --- a/docs/docs/dev/_meta.json +++ b/docs/docs/dev/_meta.json @@ -1,4 +1 @@ -[ - "development", - "commands" -] +["development", "commands"] diff --git a/docs/docs/guide/_meta.json b/docs/docs/guide/_meta.json index 209ca5f..a80008f 100644 --- a/docs/docs/guide/_meta.json +++ b/docs/docs/guide/_meta.json @@ -1,5 +1 @@ -[ - "getting-started", - "npm-modules", - "live-demo" -] +["getting-started", "npm-modules", "live-demo"] From e0b0f08cadea38230be8b22838b8121fecf7e7bb Mon Sep 17 00:00:00 2001 From: Bori-github Date: Tue, 4 Nov 2025 19:38:26 +0900 Subject: [PATCH 3/5] =?UTF-8?q?chore:=20javascript/typescript=20=ED=8F=AC?= =?UTF-8?q?=EB=A7=B7=ED=84=B0=20=EB=93=B1=EB=A1=9D=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/widgets/code-editor/code-editor.tsx | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/apps/executeJS/src/widgets/code-editor/code-editor.tsx b/apps/executeJS/src/widgets/code-editor/code-editor.tsx index 7618b82..c1fa170 100644 --- a/apps/executeJS/src/widgets/code-editor/code-editor.tsx +++ b/apps/executeJS/src/widgets/code-editor/code-editor.tsx @@ -1,12 +1,23 @@ import React, { useRef } from 'react'; import { Editor, EditorProps } from '@monaco-editor/react'; +import type { Options as PrettierOptions } from 'prettier'; import prettier from 'prettier/standalone'; import babel from 'prettier/plugins/babel'; import estree from 'prettier/plugins/estree'; +import typescript from 'prettier/plugins/typescript'; import type { CodeEditorProps } from '../../shared/types'; +const prettierOptions: PrettierOptions = { + semi: true, + trailingComma: 'es5', + singleQuote: true, + printWidth: 80, + tabWidth: 2, + useTabs: false, +}; + export const CodeEditor: React.FC = ({ value, onChange, @@ -21,21 +32,41 @@ export const CodeEditor: React.FC = ({ try { editorRef.current = editor; - // Prettier 포맷터 등록 - monaco.languages.registerDocumentFormattingEditProvider(language, { + // JavaScript 포맷터 등록 + monaco.languages.registerDocumentFormattingEditProvider('javascript', { async provideDocumentFormattingEdits(model) { const text = model.getValue(); try { const formatted = await prettier.format(text, { + ...prettierOptions, parser: 'babel', plugins: [babel, estree], - semi: true, - trailingComma: 'es5', - singleQuote: true, - printWidth: 80, - tabWidth: 2, - useTabs: false, + }); + + return [ + { + range: model.getFullModelRange(), + text: formatted, + }, + ]; + } catch (error) { + console.error('Prettier formatting error:', error); + return []; + } + }, + }); + + // TypeScript 포맷터 등록 + monaco.languages.registerDocumentFormattingEditProvider('typescript', { + async provideDocumentFormattingEdits(model) { + const text = model.getValue(); + + try { + const formatted = await prettier.format(text, { + ...prettierOptions, + parser: 'typescript', + plugins: [typescript, estree], }); return [ From 1735759f00cfae2941701b1d2e611386463c088c Mon Sep 17 00:00:00 2001 From: Bori-github Date: Wed, 5 Nov 2025 14:03:58 +0900 Subject: [PATCH 4/5] =?UTF-8?q?chore:=20=EB=93=B1=EB=A1=9D=EB=90=9C=20?= =?UTF-8?q?=ED=8F=AC=EB=A7=B7=ED=84=B0=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=96=B8=EB=A7=88=EC=9A=B4=ED=8A=B8=20=EC=8B=9C=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C=ED=95=98=EC=97=AC=20clean=20up=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/widgets/code-editor/code-editor.tsx | 112 ++++++++++-------- 1 file changed, 65 insertions(+), 47 deletions(-) diff --git a/apps/executeJS/src/widgets/code-editor/code-editor.tsx b/apps/executeJS/src/widgets/code-editor/code-editor.tsx index c1fa170..d7ffb42 100644 --- a/apps/executeJS/src/widgets/code-editor/code-editor.tsx +++ b/apps/executeJS/src/widgets/code-editor/code-editor.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from 'react'; +import React, { useEffect, useRef } from 'react'; import { Editor, EditorProps } from '@monaco-editor/react'; import type { Options as PrettierOptions } from 'prettier'; @@ -26,6 +26,7 @@ export const CodeEditor: React.FC = ({ theme = 'vs-dark', }) => { const editorRef = useRef(null); + const disposablesRef = useRef>([]); // Monaco Editor 설정 const handleEditorDidMount: EditorProps['onMount'] = (editor, monaco) => { @@ -33,54 +34,59 @@ export const CodeEditor: React.FC = ({ editorRef.current = editor; // JavaScript 포맷터 등록 - monaco.languages.registerDocumentFormattingEditProvider('javascript', { - async provideDocumentFormattingEdits(model) { - const text = model.getValue(); - - try { - const formatted = await prettier.format(text, { - ...prettierOptions, - parser: 'babel', - plugins: [babel, estree], - }); - - return [ - { - range: model.getFullModelRange(), - text: formatted, - }, - ]; - } catch (error) { - console.error('Prettier formatting error:', error); - return []; - } - }, - }); + const jsDisposable = + monaco.languages.registerDocumentFormattingEditProvider('javascript', { + async provideDocumentFormattingEdits(model) { + const text = model.getValue(); + + try { + const formatted = await prettier.format(text, { + ...prettierOptions, + parser: 'babel', + plugins: [babel, estree], + }); + + return [ + { + range: model.getFullModelRange(), + text: formatted, + }, + ]; + } catch (error) { + console.error('Prettier formatting error:', error); + return []; + } + }, + }); // TypeScript 포맷터 등록 - monaco.languages.registerDocumentFormattingEditProvider('typescript', { - async provideDocumentFormattingEdits(model) { - const text = model.getValue(); - - try { - const formatted = await prettier.format(text, { - ...prettierOptions, - parser: 'typescript', - plugins: [typescript, estree], - }); - - return [ - { - range: model.getFullModelRange(), - text: formatted, - }, - ]; - } catch (error) { - console.error('Prettier formatting error:', error); - return []; - } - }, - }); + const tsDisposable = + monaco.languages.registerDocumentFormattingEditProvider('typescript', { + async provideDocumentFormattingEdits(model) { + const text = model.getValue(); + + try { + const formatted = await prettier.format(text, { + ...prettierOptions, + parser: 'typescript', + plugins: [typescript, estree], + }); + + return [ + { + range: model.getFullModelRange(), + text: formatted, + }, + ]; + } catch (error) { + console.error('Prettier formatting error:', error); + return []; + } + }, + }); + + // Disposable들을 ref에 저장 + disposablesRef.current = [jsDisposable, tsDisposable]; // 단축키 바인딩 if (monaco && monaco.KeyMod && monaco.KeyCode) { @@ -148,6 +154,18 @@ export const CodeEditor: React.FC = ({ acceptSuggestionOnEnter: 'off' as const, }; + // Cleanup: unmount 시 포맷터 등록 해제 + useEffect(() => { + return () => { + // 모든 disposable 해제 + disposablesRef.current.forEach((disposable) => { + disposable.dispose(); + }); + + disposablesRef.current = []; + }; + }, []); + return (
Date: Wed, 5 Nov 2025 14:20:09 +0900 Subject: [PATCH 5/5] =?UTF-8?q?chore:=20=EC=9D=B4=EC=A0=84=EC=97=90=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=EB=90=9C=20=ED=8F=AC=EB=A7=B7=ED=84=B0?= =?UTF-8?q?=EA=B0=80=20=EB=82=A8=EC=95=84=EC=9E=88=EB=8A=94=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0,=20=EB=A8=BC=EC=A0=80=20=ED=95=B4=EC=A0=9C=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=BD=94=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/executeJS/src/widgets/code-editor/code-editor.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/executeJS/src/widgets/code-editor/code-editor.tsx b/apps/executeJS/src/widgets/code-editor/code-editor.tsx index d7ffb42..b0388ab 100644 --- a/apps/executeJS/src/widgets/code-editor/code-editor.tsx +++ b/apps/executeJS/src/widgets/code-editor/code-editor.tsx @@ -33,6 +33,14 @@ export const CodeEditor: React.FC = ({ try { editorRef.current = editor; + // 이전 등록된 포맷터가 남아있는 경우, 먼저 해제 + if (disposablesRef.current.length > 0) { + disposablesRef.current.forEach((disposable) => { + disposable.dispose(); + }); + disposablesRef.current = []; + } + // JavaScript 포맷터 등록 const jsDisposable = monaco.languages.registerDocumentFormattingEditProvider('javascript', { @@ -161,7 +169,6 @@ export const CodeEditor: React.FC = ({ disposablesRef.current.forEach((disposable) => { disposable.dispose(); }); - disposablesRef.current = []; }; }, []);