TIL/2025

Tistory 코드 블럭 highlighting & 복사 버튼 추가하기

고무 오리 2025. 4. 21. 18:30
728x90
📢 Tistory blog의 Code block은 예쁘지 않아요. Tistory의 plugin 기능으로 Highlight 할 수 있지만 line number, copy button 등이 없죠. 그래서 highlight.js, clipboard.js CDN을 이용해서 Code block을 예쁘게 바꿔봤어요.

 

아래 순서대로 적용하면 끝!

 

패키지 추가

기능 구현을 위해 필요한 패키지들의 CDN을 <head>...</head> 태그에 추가해요

  • highlight.js : Syntax highlight, line number 표시를 위한 패키지와 플러그인
  • clipboard.js : 코드 클립보드 복사 기능을 위한 패키지
<head>
  ...
  <!-- highlight.js 스타일 (github 밝은 테마) -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
  <!-- highlight.js 본체 -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
  <!-- highlight.js Line number 플러그인 -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>
  <!-- 복사 기능용 clipboard.js -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script>
</head>

 

 

기능 추가

<body>...</body> 밑에 아래 코드(<script>...</script>)추가

  • highlight.js 적용을 위해 Tistory 기본 에디터로 작성한 code block tag 정보를 수정 해줌
  • copy button 추가 및 버튼 동작 추가
<script>
/* code block with highlight.js & clipboard.js */
document.addEventListener('DOMContentLoaded', function () {
  document.querySelectorAll('pre[data-ke-language]').forEach((preBlock, index) => {
    const lang = preBlock.getAttribute('data-ke-language') || 'plaintext';
    const rawText = preBlock.textContent;

    // code 태그 생성
    const code = document.createElement('code');
    code.className = 'hljs language-' + lang;
    code.textContent = rawText;
    const codeId = `code-${index}`;
    code.setAttribute('id', codeId);

    // pre 태그 구성
    preBlock.classList.add('hljs', 'line-numbers');
    preBlock.innerHTML = '';
    preBlock.appendChild(code);

    // 복사 버튼 생성
    const button = document.createElement('button');
    button.innerText = '📋 Copy';
    button.className = 'copy-button';
    button.setAttribute('data-clipboard-target', `#${codeId}`);
    preBlock.appendChild(button);
  });

  // 하이라이트 및 라인 넘버 적용
  document.querySelectorAll('pre code').forEach(block => {
    hljs.highlightElement(block);
  });
  hljs.initLineNumbersOnLoad();

  // 복사 기능 활성화
  const clipboard = new ClipboardJS('.copy-button');
  clipboard.on('success', function (e) {
    const button = e.trigger;
    const originalText = button.innerText;

    button.innerText = '✅ Copied!';
    button.classList.add('copied');

    setTimeout(() => {
      button.innerText = originalText;
      button.classList.remove('copied');
    }, 1500);
  });
});
</script>

 

 

Style 추가

copy button, code block style 내 입맛에 맞게 변경

  • 제일 하단에 추가해야 내가 원하는 style이 잘 적용 됨
/* code block with highlight.js & clipboard.js */
.copy-button {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 4px 4px;
  font-size: 12px;
  background: #eee;
  border: 1px solid #ccc;
  border-radius: 4px;
  cursor: pointer;
  z-index: 1;
}

.copy-button:hover {
  background: #d0d0d0;
  color: #000;
}

/* 복사 후 상태 */
.copy-button.copied {
  background: #4caf50;
  color: #fff;
  border-color: #4caf50;
}

#article-view code.hljs table td {
  padding: 0px 8px;
  font-size: 12px;
}

#article-view pre code.hljs {
  font-family: 'D2Coding';
  padding: 36px 20px 16px 20px;
}

pre.line-numbers {
  position: relative;
  overflow-x: auto; /* 가로 스크롤 */
  white-space: pre; /* 줄바꿈 유지 + 줄 전체 보여주기 */
}

 

 

 

이제 예쁜 코드 블럭, 복사 버튼과 함께 포스팅을 할 수 있어요!

728x90