Svelte 에서 highlight.js 연동하기

Svelte 를 공부하면서 코드를 웹페이지에 넣을 일이 많아지는데, <pre> 태그만 쓰자니 아쉬워서 highlight.js 라이브러리를 사용해보기로 했다. 공식문서만 보고 그냥 html 파일에 따라하는 것은 그렇게 어렵지 않았는데, 이걸 svelte 구조에 맞춰 처리하려니 생각보다 어려웠다. 2가지 방식만 정리해본다.

참고로, highlight.js 라이브러리는 줄번호, 줄강조 등의 기능이 없다. 만약 그런 기능을 원한다면 다른 라이브러리를 찾아 공부하시길 바란다. 이유는 아래와 같다고 한다.

* https://highlightjs.readthedocs.io/en/latest/line-numbers.html 페이지 일부 번역

처음부터 Highlight.js를 정의하는 디자인 원칙 중 하나는 단순함이었다. 코드의 단순함(사실, 그것은 꽤 복잡하다)이 아니라 사용의 단순성과 HTML 페이지에서 강조된 스니펫의 실제 모습. 내 생각에 많은 하이라이터는 모든 유형의 렉셈, 줄무늬 배경, 코드 블록 주변의 멋진 버튼 및 줄 번호에 대한 별도의 색상과 같은 것들로 그것을 과장하고 있다. 코드 주변에 더 멋진 것들이 있을수록 독자가 그것을 이해하는 것을 더 산만하게 한다.

1.Package Manager 로 설치하여 사용

npm 을 이용해서 패키지를 설치한다.

npm install highlight.js

필수로 import 해야하는 파일은 highlight.js 파일과 코드테마를 입힐 css 파일이다. 디폴트 스타일보다는 atom 스타일로 넣었고, 마지막으로 <code class="language-html"> 처럼 code 태그에도 꼭 프로그램 언어에 맞는 class 명을 정의해야 한다. [결과확인]

<script>
    import { onMount } from 'svelte';
    import hljs from 'highlight.js';
    import 'highlight.js/styles/atom-one-dark.min.css';

    const codeHtml = '<div class="row"><span>Hello World!</span></div>';

    onMount(() => {
        hljs.highlightAll(); // 모든 코드 블록을 강조 표시        
    });
</script>

<pre>
    <code class="language-html">{codeHtml}</code>
</pre>

onMount 없이 그냥 hljs.highlightAll(); 를 호출하면 아래와 같은 에러메시지를 볼 수 있다. onMount 는 HTML Document 로딩이 완료되었을때, 즉시 실행하고픈 함수를 예약할 수 있다. 보통 html body 태그내에 실행하는 javascript 함수들을 여기에 넣으면 된다.

ReferenceError: document is not defined
    at Object.highlightAll (/usr/src/app/node_modules/highlight.js/lib/core.js:2374:5)

2. CDN 링크를 이용

보면 알겠지만, import 를 가지고 내부 파일을 연결하는게 아니라, <svelte:head> 를 이용해서 외부링크를 연결하는 케이스 이다. [결과확인]

<script>
    import { onMount } from 'svelte';

    const codeHtml = '<div class="row"><span>Hello World!</span></div>';

    onMount(() => {
        hljs.highlightAll(); // 모든 코드 블록을 강조 표시        
    });
</script>

<svelte:head>
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
</svelte:head>

<pre>
    <code class="language-html">{codeHtml}</code>
</pre>

원하는 언어만 등록해서 적용하고 싶을때

사실 이것만으로도 highlight.js 의 기본적인 기능을 사용할 수 있게 되었다. 그런데, npm 으로 설치한 경우, import 를 하는 순간 프로그래밍 언어별로 하이라이트 할 수 있도록 언어별 js 파일을 읽어오는데, 192개 모두 불러온다.

import hljs from 'highlight.js';
console.log(hljs.listLanguages().length);
// --> 192 가 출력된다.

그리고 외부 cdn 주소를 사용하는 경우 36개 언어만 불러온다.

onMount(() => {
    hljs.highlightAll();
    console.log(hljs.listLanguages().length);
    // --> 36 이 출력된다.    
});

사실 보통 다루는 언어는 몇개 되지 않고, 그 중에서 내가 웹페이지에 표시할 만한 언어는 2~3개 밖에 되지 않는다면, 이건 불필요하니 일부 언어포맷만 등록해서 사용할 수 있도록 제한 할 수 있다. npm 설치버전에서만 가능하니 참고한다. [결과확인] 페이지에 가보면, 3개언어만 하이라이트가 되고 정의되지 않은 언어는 아무효과없이 출력된다.

import hljs from 'highlight.js/lib/core';
import javascript from 'highlight.js/lib/languages/javascript';
import julia from 'highlight.js/lib/languages/julia';
import go from 'highlight.js/lib/languages/go';

// 필요한 언어만 가져다가 바인딩 한다.
hljs.registerLanguage('go', go);
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('julia', julia);

console.log(hljs.listLanguages().length);
// --> 3 이 출력된다.

cdn 는 36개 언어를 불러오며, 거기에 없는 언어는 추가 js 파일을 넣으면 된다. [결과확인]

<svelte:head>
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <!-- julia 언어는 36개중에 없는 언어라 아래처럼 추가해야 한다. -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/julia.min.js"></script>
</svelte:head>

더 보면 좋을 글들