프로젝트에 새로운 Json Editor를 도입하는 임무를 맡게 되어서, 여러 라이브러리들을 검색하던 중 vue-codemirror(https://github.com/surmon-china/vue-codemirror#readme)라는 라이브러리를 찾게 되었다.
다른 후보군으로는 vue-prism-editor나 vue2-ace-editor도 있었는데, 전자는 훨씬 크기가 크고 후자는 문서화가 잘 안되어있고 업데이트도 안되는 것 같아 모든 면에서 더 나은 vue-codemirror를 선택하였다.
vue-codemirror를 설치하기 위해 우선 아래의 명령어를 실행한다.
npm install vue-codemirror --save
그리고 main.ts에 아래와 같이 명시한다.
import Codemirror from 'vue-codemirror';
import 'codemirror/lib/codemirror.css';
...
(생략)
...
Vue.use(Codemirror);
이제 프로젝트 내에서 Codemirror를 사용할 수 있다.
다만 진행중인 프로젝트의 컨벤션 상 라이브러리를 그대로 쓰지 않고 컴포넌트로 wrapping해야 하기 때문에 아래와 같이 html 코드를 작성한다. 이 부분은 프로젝트마다 다를 수 있다.
<template>
<div class="p-text-editor">
<codemirror
ref="editor"
v-model="proxyCode"
:options="options"
:mode="mode"
/>
</div>
</template>
그리고 typescript 영역에는,
import {
onMounted, reactive, toRefs, watch,
} from '@vue/composition-api';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/addon/lint/json-lint';
import 'codemirror/addon/fold/brace-fold';
import 'codemirror/addon/fold/comment-fold';
import 'codemirror/addon/fold/foldcode';
import 'codemirror/addon/fold/foldgutter';
import 'codemirror/addon/fold/indent-fold';
import 'codemirror/addon/fold/markdown-fold';
import 'codemirror/addon/fold/xml-fold';
import 'codemirror/addon/edit/closebrackets';
import 'codemirror/addon/edit/closetag';
이렇게 필요한 addon을 공식 문서(https://codemirror.net/doc/manual.html#addons)에서 찾아 추가해준다. 진행중인 프로젝트의 요구사항은 1 depth 이상 들어가는 json은 모두 folding 해주어야 하고, json 형태로 보여주어야 하는 것이기에 위와 같이 추가하였다.
그리고 나서, 아래와 같이 props를 정의했다.
export default {
name: 'PTextEditor',
components: { },
props: {
code: {
type: String,
default: '',
required: true,
},
options: {
type: Object,
default: () => ({
tabSize: 4,
styleActiveLine: true,
lineNumbers: true,
line: true,
mode: 'application/json',
lineWrapping: true,
theme: 'ayu-mirage',
matchBrackets: true,
autoCloseBrackets: true,
autoCloseTags: true,
foldGutter: true,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
}),
},
mode: {
type: String,
default: 'edit',
required: true,
},
},
프로젝트마다 props에 필요한 것들이나, 이 컴포넌트를 사용하는 쪽에서 json에 입력한 input(위의 코드에서는 code)을 정의하는 방식이 다르기 때문에 options 위주로 참고해주세요. 🙂
options에 정의한 내용들은 위에서 codemirror에 바인딩되는 codemirror 에디터 자체의 옵션들이다.
tab size, line 넘버 표기, json 형태, editor 테마, 괄호 자동 닫기, code Folding 기능 등을 명시하였다. 공식 문서에 더 자세한 옵션들이 존재한다.
중요한 점은 위와 같은 옵션을 사용하기 위해선 해당하는 addon을 import해야 한다는 것이다.
이 다음 setup()부터 return까지는 각 프로젝트마다 로직이 다르기 때문에 생략한다.
다만 이 때 중요한 점은, props로 받아온 값(여기서는 code)을 그대로 사용할 수 없기 때문에 getter와 setter를 만들어(props를 get해주고, update를 emit하는 set..) 바인딩해주어야 하는 것이다.
사용하는 쪽에선 .sync를 통해 데이터를 바인딩한다.
그리고 혹시라도 공식문서에 나와있는 것처럼 dom에 접근하는 action을 활용하고 싶을 때는,
const cm = editor.codemirror;
이런 식으로 ref에 접근한 후 해당 ref 안에 있는 codemirror를 사용하면 된다. (ex. cm.operation...)
사실 codemirror의 문서가 그다지 친절하진 않아서 해당 객체가 어떤 속성을 가지고 있는 지 debugger를 통해 모두 뜯어보기도 했는데, 힘들었지만 좋은 경험(삽질)이었던 것 같다.
로직을 다 작성한 후에는 이제 스타일링이 남았다.
<style lang="postcss">
@import 'codemirror/theme/ayu-mirage.css';
@import 'codemirror/addon/lint/lint.css';
@import 'codemirror/lib/codemirror.css';
@import 'codemirror/addon/fold/foldgutter.css';
.p-text-editor {
height: 100%;
min-height: 5rem;
.CodeMirror {
font-family: Inconsolata, monospace;
line-height: 1.5;
height: fit-content;
padding: 1rem;
}
}
</style>
진행중인 프로젝트에서는 postcss-easy-import라는 플러그인을 사용하기 때문에 위와 같이 import해주었고, 일반적인 방식으로 import해도 똑같이 동작한다.
테마나 린트, codemirror 자체 css 등을 import해준다.
그 후 editor를 스타일링 할 때는 .CodeMirror 클래스를 직접 접근해서 수정해주면 된다.
이렇게 프로젝트에 code mirror 적용을 할 수 있다. 😁 아래는 적용한 code mirror editor의 모습이다.