프로그래밍/Javascript

[ReactJS] code highlight editor (feat. highlight.js)

Beginner:) 2024. 8. 24.
320x100

1. 실행 결과

 

2. 원리

먼저 highlight.js는 텍스트에 style을 입혀주는 기능을 할 뿐이다. 

 

즉 엘리먼트들을 사용한다는 것인데, textarea나 MUI의 TextField에서는 적용이 불가능하다.

 

예로 들어 C언어에서 "int num = 5;"라는 code는 "<span class="hljs-type">int</span> num = <span class="hljs-number">5</span>"라는 html코드로 되어있다. 

 

int는 type이니까 hljs-type의 class이름으로 css를 입힌다... 이런 식인데

 

textarea와 같은 컴포넌트들은 HTML 코드가 아니니 innerHTML도 불가능하고, css도 입히지 못하는 것이다.

 

그러면 어떻게 TextEditor를 만드냐면 

 

textarea와 pre&code를 겹치는 것이다. (여기서 pre&code는 hightlight.js 적용방법이다)

 

둘을 겹치되, textarea는 z-index를 높여 앞으로 나오게 하고, text color와 background color를 tansparent로 설정한다.

 

혹여나 teatarea 전체를 opacity: 0으로 설정하면 안 되냐? 할 수 있지만 그러면 cursor까지 안 보인다. 

 

그러니 textarea와 pre&code를 font설정도 같이, padding, margin 등도 똑같이 설정해줘야 한다.

 

이렇게 되면 입력창은 살아있되 보여지는 텍스트는 highlight.js의 style을 먹은 pre&code가 보여지는 것이다.

 

 

3. 코드

먼저 code를 입력하는 form부터.

참고로 React용 highlight.js가 있었으나, 무슨 이유인지 설치가 안되어서 native js로...

 

javascript

(handleKeyDown은 Tab을 눌렀을 때 \t를 주려고 만들었으나, 아직 구현하진 않음)

<div className="code-editor-wrapper">
    <textarea
        value={code}
        onChange={(e)=>{setCode(e.target.value)}}
        // onKeyDown={handleKeyDown}
        className="code-input"
        spellCheck={false}
    />
    <pre className="code-output">
        <code ref={codeRef} className={`language-${language}`} />
    </pre>
</div>

 

 

css

.code-editor-wrapper {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    position: relative;
    width: 100%;
    height: 100%;
    font-family: 'Courier New', monospace;
}

.code-input,
.code-output {
    grid-column: 1 / 2;
    grid-row: 1 / 2;
    width: calc(100% - 20px);
    height: 100%;
    padding: 10px;
    margin: 0;
    font-family: inherit;
    font-size: 16px;
    line-height: 1.5;
    letter-spacing: 0px;
    tab-size: 4;
}

.code-input {
    color: transparent;
    background-color: transparent;
    border: none;
    resize: none;
    caret-color: black;
    white-space: pre-wrap;
    overflow: hidden;
    z-index: 1;
}

.code-output {
    background-color: #f5f5f5;
    border: 1px solid #000000;
    pointer-events: none;
    white-space: pre-wrap;
    word-wrap: break-word;
    z-index: 0;
    overflow: auto;
}

 

 

이러면 입력창은 완료하였고, 다음은 highlight.js를 입히는 코드

 

javascript

// 라이브러리 import
import hljs from 'highlight.js';
import 'highlight.js/styles/docco.min.css';
import cLang from 'highlight.js/lib/languages/c';

// c언어 등록
hljs.registerLanguage('language-c', cLang);

// textarea가 변경될 때 마다 highligh.js 를 적용하여 pre&code에 innerHTML로 입력
React.useEffect(() => {
    if ( codeRef.current ) {
        codeRef.current.innerHTML = hljs.highlight(`language-c`, code).value;
    }
}, [code]);

 

 

새로운 언어에 대한 code style을 바꾸고 싶다면 아래 링크로...

 

2024.08.24 - [프로그래밍/Javascript] - [ReactJS] highlight.js 커스텀 language 추가

 

[ReactJS] highlight.js 커스텀 language 추가

1. 기존의 언어 추가먼저 highlight.js를 보면 기존의 language들이 있다.   예를 들어 c언어를 추가하고 싶다면 아래와 같이 c언어의 라이브러리를 불러와 언어를 등록해 주면 된다import hljs from 'highli

park-duck.tistory.com

 

반응형

댓글