[Javascript] 웹 사이트나 블로그등에 소스 코드 보기(highlightjs.min.js)
안녕하세요. 명월입니다.
이 글은 Javascript를 이용해서 웹 사이트나 블로그등에 소스 코드 보기(highlightjs.min.js)에 대한 글입니다.
우리가 프로그램 관련된 블로그를 작성하거나(저처럼..) 웹 사이트를 작성한다고 한다고 하면 프로그램 소스 보기가 필요합니다. 이 소스 보기는 단순히 메모장처럼 소스를 라인별로 보이는 것이 중요한 것이 아니라 IDE 툴처럼 함수나 클래스 등에 색깔을 달리해서 가독성을 높이는 게 중요하겠네요.
이런 가독성을 높이기 위한 라이브러리를 보통 소스 코드 하이라이트(highlight) 라이브러리라고 이야기하는데 종류가 굉장히 많이 있습니다.
저는 그 중에서 highlightjs를 사용하고 있습니다.
일단 사이트에 가면 정말 친절하게 사용법을 자세하게 소개하고 있으나 여기서는 간단하게 구현하는 방법과 결과를 확인하겠습니다.
<!DOCTYPE html>
<html>
<!-- 헤더 라인 -->
<head>
<!-- 타이틀 -->
<title>Source highlight test</title>
<!-- 하이라이트 rainbow 스타일 라이브러리 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/rainbow.min.css">
</head>
<!-- 바디 라인 -->
<body>
<!-- 소스 표시 영역 -->
<pre>
<!-- code 태그에 class에 표시할 언어를 설정한다. -->
<!-- code 태그 안에 소스 코드를 입력합니다만, 스페이스와 탭 영역을 주의해서 입력한다. -->
<code class="javascript">function test() {
alert('hello world');
}</code>
</pre>
<!-- 하이라이트 라이브러리 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
<!-- 하이라이트 라이브러리 실행 -->
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>
먼저 저는 로컬에서 테스트를 했기 때문에 CDN에 프로토콜(https)를 붙였습니다.
저는 rainbow 스타일을 썻습니다. rainbow 스타일은 기본적으로 어두운 색 계열에 문자가 밝게 표시하는 스타일입니다. 각 스타일은 홈페이지에서 확인이 가능합니다.
홈페이지에서 language와 style부분을 클릭하면 변경되는데 이런저런 스타일을 확인할 수 있습니다.
작성이 되었으면 확인해 보겠습니다.
일단 어두운 색에서 키워드나 함수 색이 확실히 구분되었습니다.
그러나 지금 제가 사용하는 블로그와는 차이가 있네요.. 먼저 줄(라인) 넘버가 표시되지 않네요.
이 라인 넘버는 이 홈페이지에서 제공하지 않고 다른 분이 많든 것 같습니다.
링크 - https://github.com/wcoder/highlightjs-line-numbers.js/
라인 넘버를 추가하는 방법은 라이브러리를 추가하고 hljs.initLineNumbersOnLoad()함수를 호출하는 것으로 실행이 됩니다.
<!DOCTYPE html>
<html>
<!-- 헤더 라인 -->
<head>
<!-- 타이틀 -->
<title>Source highlight test</title>
<!-- 하이라이트 rainbow 스타일 라이브러리 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/rainbow.min.css">
<!-- 하이라이트 줄 넘버 스타일-->
<style>
/* 숫자 스타일 */
.hljs-ln-numbers {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* 가운데 정렬 */
text-align: center;
/* 글자 색 설정 */
color: #ccc;
/* 오른쪽 선 설정 */
border-right: 1px solid #CCC;
/* 세로 정렬 */
vertical-align: top;
/* 오른쪽 여백 */
padding-right: 10px !important;
/* 글자 사이즈 */
font-size: 10pt;
/* 라인 높이 */
line-height: 15px;
}
/* 코드 스타일 */
.hljs-ln-code {
/* 왼쪽 여백 */
padding-left: 10px !important;
/* 글자 사이즈 */
font-size: 10pt;
/* 공백 설정 */
white-space: pre-wrap;
/* 라인 높이 */
line-height: 15px;
}
</style>
</head>
<!-- 바디 라인 -->
<body>
<!-- 소스 표시 영역 -->
<pre>
<!-- code 태그에 class에 표시할 언어를 설정한다. -->
<!-- code 태그 안에 소스 코드를 입력합니다만, 스페이스와 탭 영역을 주의해서 입력한다. -->
<code class="javascript">function test() {
alert('hello world');
}</code>
</pre>
<!-- 하이라이트 라이브러리 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
<!-- 줄(라인) 넘버 라이브러리 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>
<!-- 하이라이트 라이브러리 실행 -->
<script>hljs.initHighlightingOnLoad();</script>
<!-- 줄(라인) 넘버 라이브러리 실행 -->
<script>hljs.initLineNumbersOnLoad();</script>
</body>
</html>
소스 하이라이트에 줄 넘버까지 표시가 되었습니다.
그런데 제 블로그에 있는 화면과는 또 약간의 차이가 있습니다. 나머지는 제가 작성한 부분입니다.
테두리를 만들고 메테리얼 스타일을 적용하고 collapse 기능(접기, 펼치기 기능) 추가하고 소스를 복사할 수 있는 기능을 추가했습니다.
<!DOCTYPE html>
<html>
<!-- 헤더 라인 -->
<head>
<!-- 타이틀 -->
<title>Source highlight test</title>
<!-- 하이라이트 rainbow 스타일 라이브러리 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/rainbow.min.css">
<!-- 메시지 알람 라이브러리 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css">
<!-- 아이콘 라이브러리 -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<!-- 하이라이트 줄 넘버 스타일-->
<style>
/* 숫자 스타일 */
.hljs-ln-numbers {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* 가운데 정렬 */
text-align: center;
/* 글자 색 설정 */
color: #ccc;
/* 오른쪽 선 설정 */
border-right: 1px solid #CCC;
/* 세로 정렬 */
vertical-align: top;
/* 오른쪽 여백 */
padding-right: 10px !important;
/* 글자 사이즈 */
font-size: 10pt;
/* 라인 높이 */
line-height: 15px;
}
/* 코드 스타일 */
.hljs-ln-code {
/* 왼쪽 여백 */
padding-left: 10px !important;
/* 글자 사이즈 */
font-size: 10pt;
/* 공백 설정 */
white-space: pre-wrap;
/* 라인 높이 */
line-height: 15px;
}
</style>
<style>
/* pre 태그 스타일*/
pre {
/* 화면*/
display: block;
/* 글자 크기 */
font-size: 13px;
/* 라인*/
line-height: 1.42857143;
/* 글자 크기 */
color: #333;
/* 글자가 테이블을 넘어서면 자르기 */
word-break: break-all;
word-wrap: break-word;
/* 테두리 색깔 설정 */
background-color: #f5f5f5;
/* 테두리 색깔 설정 */
border: 1px solid #ccc;
/* 선 모서리 스타일 */
border-radius: 4px;
/* 여백 */
margin: 10px 0px;
/* 여백 */
padding: 0px;
/* 메테리얼 스타일 (그림자 설정) */
box-shadow: 1px 2px 4px;
}
/* 타이틀 스타일 */
.code-title {
/* 배경색 설정 */
background-color: #e9e9e9;
/* 왼쪽 오른쪽 여백*/
padding-left: 10px;
padding-top: 5px;
/* 글자 색 */
color:black;
/* 글자 두께*/
font-weight: 800;
}
/* 접기 했을 때 스타일 */
pre.code-view-disabled code{
/* 화면에서 없애기 */
display: none;
height: 0px;
}
/* copy 버튼 스타일*/
.code-copy {
/* 오른쪽 정렬 */
float: right;
/* 상대적 위치 설정 */
position: relative;
/* 오른쪾에서의 위치 */
right: 10px;
/* 위쪽 여백 설정 */
padding-top: 2px;
/* 글자 색깔 */
color: #337ab7;
/* 텍스트 밑줄 없애기 */
text-decoration: none;
/* 배경 색깔*/
background-color: transparent;
}
</style>
</head>
<!-- 바디 라인 -->
<body>
<!-- 소스 표시 영역 -->
<!-- code 태그에 class에 표시할 언어를 설정한다. -->
<!-- code 태그 안에 소스 코드를 입력합니다만, 스페이스와 탭 영역을 주의해서 입력한다. -->
<!-- data-type은 타이틀 제목이다. -->
<pre><code class="javascript" data-type="test">function test() {
alert('hello world');
}</code></pre>
<!-- Jquery 추가 -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!-- 메시지 라이브러리 추가 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
<!-- 하이라이트 라이브러리 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
<!-- 줄(라인) 넘버 라이브러리 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>
<!-- 하이라이트 라이브러리 실행 -->
<script>hljs.initHighlightingOnLoad();</script>
<!-- 줄(라인) 넘버 라이브러리 실행 -->
<script>hljs.initLineNumbersOnLoad();</script>
<script>
/* 실행 함수 */
(function (obj) {
/* 페이지 로드 완료되면 실행*/
$(obj.onLoad);
})({
onLoad: function () {
/* 하이라이트 코드 스타일 설정 */
$("pre code.hljs").each(function () {
/* copy 버튼 만들기 */
$(this).before($("<a href='javascript:void(0);' class='code-copy'><i class='fa fa-copy'></i>Copy!</a>"));
/* 타이틀 만들기 */
$(this).before($("<div class='code-title'></div>")
.append($("<i class='fa fa-minus-square code-collapse' style='margin-right:10px;'></i>"))
.append(" [소스 보기] " + $(this).data("type")));
/* 클래스 추가 */
$(this).parent().addClass("code-view");
});
/* 타이틀을 클릭 했을 때*/
$(document).on("click", ".code-title", function () {
$this = $(this);
/* collapse 효과 만들기 */
$i = $this.find("i.code-collapse");
/* + 버튼일때*/
if ($i.hasClass("fa-plus-square")) {
/* 버튼을 -로 교체 */
$i.removeClass("fa-plus-square");
$i.addClass("fa-minus-square");
/* 코드 클래스를 제거함으로 표시한다. */
$this.parent().removeClass("code-view-disabled");
} else {
/* 버튼을 +로 교체*/
$i.removeClass("fa-minus-square");
$i.addClass("fa-plus-square");
/* 코드 클래스를 추가함으로 화면에서 없앤다. */
$this.parent().addClass("code-view-disabled");
}
});
/* copy 버튼을 클릭했을 경우 */
$(document).on("click",'.code-copy', function(){
/* escape 문자 치환하기 */
function escapeHTML(str) {
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\"").replace(/'/g, "'");
}
/* code-view 클래스를 찾는다. */
$parent = $(this).closest(".code-view");
/* collapse로 코드 화면이 닫겨져 있을 때*/
if($parent.hasClass("code-view-disabled")){
/* 펼친다. */
$i = $parent.find("i.code-collapse");
/* -에서 + 버튼으로 교체*/
$i.removeClass("fa-plus-square");
$i.addClass("fa-minus-square");
/* 화면 표시*/
$parent.removeClass("code-view-disabled");
}
/* 메시지 표시*/
toastr.success(null,"소스가 복사되었습니다.", {timeOut: 700});
/* code 태그를 찾는다. */
var code_element = $(this).closest("pre").find("code")[0];
/* 연속 개행일 경우 수정한다. */
var value = code_element.innerText.replace(/\n\n/ig, '\n').replace(/\n\n\n/ig, '').replace(' \n','').replace(/\t/ig, '');
/* 셀렉션 취득 */
var selection = window.getSelection();
/* body 태그 찾는다. */
var body_element = document.getElementsByTagName('body')[0];
/* div 태그 생성*/
var newdiv = document.createElement('div');
/* 절대 위치로 브라우져에 보이지 않는 곳에 생성*/
newdiv.style.position = 'absolute';
newdiv.style.left = '-10000px';
newdiv.style.top = '-10000px';
/* body 태그에 div 태그 추가 */
body_element.appendChild(newdiv);
/* 복사해 온 값을 표시한다. */
newdiv.innerHTML = "<pre>" + escapeHTML(value) + "</pre>";
/* 선택한다.*/
selection.selectAllChildren(newdiv);
/* 10초 후에 div 태그 삭제한다.*/
setTimeout(function(){
newdiv.remove();
},10000);
/* 복사한다.*/
document.execCommand('copy');
});
}
});
</script>
</body>
</html>
제 블로그에 있는 오브젝트와 똑같이 만들어 졌습니다.
접기, 펼치기 테스트를 해보겠습니다.
정상적으로 작동되네요.
이번에는 copy 버튼을 테스트를 해보겠습니다.
소스 복사되었다고 메시지가 표시됩니다.
소스 복사도 문제없이 돌아갑니다.
이 소스는 무단으로 가져다가 쓰셔도 되고 마구마구 수정하셔서 사용해도 괜찮습니다.
출처를 안남겨도 상관 없습니다만, 가능하면 남겨주세요.
여기까지 Javascript를 이용해서 웹 사이트나 블로그등에 소스 코드 보기(highlightjs.min.js)에 대한 글이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.
'Development note > Javascript, JQuery, CSS' 카테고리의 다른 글
[Html] video와 audio 태그 (0) | 2020.03.05 |
---|---|
[Jquery] ajax 전역 이벤트를 사용하는 방법 (0) | 2019.11.27 |
[Javascript] Html태그로 파일 다운로드(base64)를 하는 방법 (0) | 2019.11.23 |
[Javascript] 서명 마크(sign)를 만드는 방법(canvas태크) (4) | 2019.11.14 |
[Jquery] $.cookie 사용법 (0) | 2019.11.12 |
[CSS] 반응형 웹을 만들기 위한 브라우저 사이즈별 css 적용 방법 (0) | 2019.11.05 |
[Javascript] 팝업 라이브러리(bootbox) (0) | 2019.11.04 |
[Javascript] 접속 브라우져를 확인하는 방법 (0) | 2019.11.02 |