원 저자에 대한 알림
본 스크립트를 제작한 사람은 별도로 존재하며, 이 글은 국내에서도 이 스크립트를 사용하는 데 어려움이 없도록 단순히 기능을 설명하기 위함이니 제작자에게 관심이 있다면 아래 링크를 방문 바랍니다(단, 일본어라 번역기능이 필요합니다).
여는 글
Table Of Contents 즉, 목차는 긴 글에 들어가기에 앞서 글의 내용을 미리 이해하는데 도움을 줍니다. 아울러 가독성을 향상시키고, 글 자체가 정보의 나열이 아닌 정돈되어있다는 인상을 심어주는 효과가 있죠.
목차가 있는 글들을 보며, 부지런하다라고 생각했는데, 알고보니 이거 스크립트만 넣으면 자동으로 생성되는 것이었더군요. 스크립트를 쓰려면 어렵진 않을까 고민했는데, 다행히도 TOC를 생성할 수 있도록 많은 선지자분들께서 이미 스크립트를 만들어 두셨습니다.
오늘 소개할 TOC 생성 스크립트는 그러한 코드 중 하나이며, 이 TOC 스크립트가 제공하는 기능은 아래와 같습니다.
- 포스트로 작성되어있는 모든 글에 목차를 자동으로 생성
- 타 스크립트와 달리 태그를 직접 사용하여 위치를 지정하지 않음(첫 제목의 상단/하단 및 기사 상단으로 지정만 가능함)
- 마우스를 올렸을때 선택된 목차 부분을 강조표시함
- ★ 제목 태그(h1, h2 등)가 특정 개수 이상일 때에만 목차를 생성하도록 설정할 수 있음
4번째에 기재한, 제목이 특정 개수 이상일 때에만 목차를 생성하는 기능이 아주 유용합니다. 토막글에 일일이 목차가 달리면 오히려 가독성이 떨어져서 별로인데, 그렇다고 매번 글마다 목차 삽입여부를 결정하는것도 머리아프거든요.
제목 태그가 3개 이상일때 목차를 생성하는 조건을 달아두면, 모든 글에 목차를 넣지는 않으면서도 매번 목차를 넣느라 머리 아플 필요가 없어 매우 편리했습니다.
참고로 이 스크립트는 구글블로그와 티스토리에 모두 적용가능합니다.
적용방법
- 최하단의 TOC 생성기 코드를 전체 복사하여, 블로그 html 편집에서
</head>
태그 앞에 붙여넣습니다.- (티스토리 블로그의 경우) <script> ~ </script> 사이에서 postBodySelector의 값을 ".article-view"로 변경해줍니다.
- (티스토리 블로그의 경우) 붙여넣은 부분 중, <style type='text/css'> ~ </style> 부분은 잘라내어 CSS에 붙여넣는다. 이때, <style type='text/css'>와 > </style>은 삭제하여야 정상작동합니다(내부 본문만 붙여넣을 것).
- 붙여넣은 태그에서 각주의 설명을 참고하여 개인의 입맛에 맞게 커스텀합니다.
- 기존 글들에도 모두 한 번에 적용되므로, 적용된 글들에 문제가 있지는 않은지 확인합니다.
주로 발생하는 오류① - 목차의 순서가 맞지 않음
목차의 순서가 맞지 않는 경우는 불필요한<div> </div>
가 본문에 존재하여 구역 분배를 깨뜨리기 때문입니다. 이 경우 목차 뿐 아니라 사이드바도 엉뚱한 곳에 위치하는 등 오류가 발생하므로, 중간에 아무런 내용이나 스타일 지정 없이 방치된 div가 있다면 쌍을 맞춰 삭제해줍시다.
주로 발생하는 오류② - 비어있는 목차 발생
비어있는 목차가 발생하는 경우는 스타일이 적용된 채로 줄바꿈이 된 부분이 존재할 때 입니다. 특히, 스타일을 지정한 후 부제목 상단이나 하단에 빈칸을 추가했을 때 이러한 현상이 나타납니다. 포스터 수정을 통해 불필요한 h2, h3 태그를 직접 찾아서 삭제해 주어야 합니다.
주로 수정하는 부분(코드 커스텀하기)
- 상단 script 변수부분
- target: 타겟이 될 태그로 h1, h2 등 제목 태그와 title을 지정가능
- autoNumber: 목차에 자동으로 숫자를 붙임
- condTargetCount: 목차를 표시할 '최상위 제목’의 수를 지정. 예를 들어 2로 지정하면 target옵션으로 지정한 최상위 제목이 두 개 이상 있을 때 목차가 표시됨. 따라서, 목차를 적용하고 싶지 않은 글이 있다면 부제목의 수를 제한하면 된다.
- insertPosition: 목차가 표시되는 위치를 결정. 첫 제목을 기준으로, 제목 앞에 목차 입력(firstHeadBefore), 제목 뒤에 목차 입력(firstHeadAfter), 기사의 상단에 표시(top)의 3가지 옵션을 선택 가능하다. 그러나, top는 몇몇 블로그에서는 정상작동하지 않는 듯 하니, 적용해보고 작동이 안된다 싶으면 firstHeadBefore를 사용하고, 차라리 첫 줄에 ‘여는 글’ 등의 제목을 하나 달기를 권장한다.
- showToc: 목차 표기여부 결정
- indent: 하위 목차를 표기할 때, 상위 목차 대비 들여쓰기를 얼마나 할 것인지를 기록한다
- 하단 CSS 부분
- b-toc-container: 목차 창 전체에 대한 세팅
- b-toc-container p span:nth-of-type(1): 목차 상단의 ‘목차’ 글씨에 대한 세팅
- b-toc-container ul li a : 목차에 포함된 각 제목에 대한 세팅
- b-toc-container ul li a:hover : 목차에 포함된 각 제목에 마우스를 올렸을때 나타나는 효과 설정
- b-toc-container p a : 숨기기 버튼에 대한 서식
TOC 생성기 코드
<!-- 자동목차 생성기 (원본 링크 : https://www.sukerou.com/2018/10/blogger-table-of-contents-javascript.html) -->
<script>
//<![CDATA[
var toc_options = {
target: ["h2", "h3"], // 타겟이 될 태그로 h1, h2 등 제목 태그와 title을 지정가능하다.
autoNumber: true, // 자동으로 숫자를 붙인다.
condTargetCount: 3, // 목차를 표시할 '최상위 제목'의 수를 지정한다.
// 예를 들어 2로 지정하면 target옵션으로 지정한 최상위 제목이 두 개 이상 있을 때 목차가 표시됨
insertPosition: "firstHeadBefore", // firstHeadBefore, firstHeadAfter, Top중 택1
// 각각 첫제목 전, 후 및 기사상단을 의미함. 단, top는 블로그에 따라 종종 잘 작동하지 않는 것으로 보임
showToc: true, // 목차의 표기여부 결정(true = 표기, false = 표기안함)
width: "100%",
marginTop: "2em",
marginBottom: "3em",
indent: "2", // 하위 목차에 들여쓰기를 넣을것인지 여부. (0: 넣지않음, 1~ : 숫자만큼 띄어쓰기)
postBodySelector: ".widget.Blog"
};
//(/script)까지는 변수 등 작동방식에 관련된 부분이므로 편집하면 작동에 문제가 발생할 수 있음
(function(i){var j=0;document.addEventListener("DOMContentLoaded",function(){var p=document.querySelector(toc_options.postBodySelector);if(p==null||typeof p==="undefined"){reutrn}if(toc_options.target.length==0){return}rootContent=h(toc_options,p);if(rootContent.children.length>=toc_options.condTargetCount){var q=c(rootContent);o(q)}});function h(q,p){var u=q.target.length;var t=function(E,D,w){var z=q.target[E];var x=E<u-1?q.target[E+1]:"";var y="toc_"+(++j);var F=g(z,m(D),E+1,y);w.children.push(F);D.id=y;var A=f(D);if(x==""){return}while(true){if(A==null||typeof A==="undefined"){break}if(b(A)==z){break}if(b(A)==x){t(E+1,A,F)}else{var B=A.getElementsByTagName(x);for(var C=0;C<B.length;C++){t(E+1,B[C],F)}}var A=f(A)}};var r=g("ROOT","",0);var v=p.getElementsByTagName(q.target[0]);for(var s=0;s<v.length;s++){t(0,v[s],r,"")}return r}function c(s){var r=document.createElement("div");r.classList.add("b-toc-container");r.style.marginTop=toc_options.marginTop;r.style.marginBottom=toc_options.marginBottom;if(toc_options.width=="100%"){r.style.display="block"}else{r.style.width=toc_options.width}var q=document.createElement("p");var w=document.createElement("span");var v=document.createElement("span");var u=document.createElement("span");v.classList.add("b-toc-show-wrap");u.classList.add("b-toc-show-wrap");var y=document.createElement("a");w.innerText="목차";v.innerText=" [";u.innerText="]";y.href="javascript:void(0);";q.appendChild(w);q.appendChild(v);q.appendChild(y);q.appendChild(u);var t=function(z){var p=typeof z==="boolean"?z:e(r,"hide");if(p){y.innerText="숨기기";r.classList.remove("hide")}else{y.innerText="표시";r.classList.add("hide")}};y.addEventListener("click",t);t(toc_options.showToc);var x=document.createElement("ul");s.children.forEach(function(z,p){n(x,z,(p+1)+"")});r.appendChild(q);r.appendChild(x);return r}function n(s,u,w){var p=document.createElement("li");var q=document.createElement("a");p.style.paddingLeft=toc_options.indent;q.href="#"+u.id;if(toc_options.autoNumber){var t=document.createElement("span");t.classList.add("toc-number");t.innerText=w}var v=document.createElement("span");v.classList.add("toc-text");v.innerText=u.text;if(toc_options.autoNumber){q.appendChild(t)}q.appendChild(v);p.appendChild(q);s.appendChild(p);if(u.children.length>0){var r=document.createElement("ul");p.appendChild(r);u.children.forEach(function(y,x){n(r,y,w+"-"+(x+1))})}}function o(q){var r=null;var p=document.querySelector(toc_options.postBodySelector);if(toc_options.insertPosition=="firstHeadBefore"||toc_options.insertPosition=="firstHeadAfter"){r=p.querySelector(toc_options.target[0])}else{if(toc_options.insertPosition=="top"){r=p}}if(r==null){return}if(toc_options.insertPosition=="firstHeadBefore"){k(r,q)}else{if(toc_options.insertPosition=="firstHeadAfter"){a(r,q)}else{if(toc_options.insertPosition=="top"){k(r,q)}}}}function g(q,r,p,s){return{tagName:q,text:r,children:[],nestLevel:p,id:s}}function m(p){return p.innerText}function f(p){return p.nextElementSibling}function d(p){return p.previousElementSibling}function b(p){return p.tagName.toLowerCase()}function e(p,q){return p.classList.contains(q)}function l(p){return p.parentNode}function a(q,s){var r=l(q);var p=f(q);if(r!=null&&p!=null){r.insertBefore(s,p)}}function k(p,r){var q=l(p);if(q!=null){q.insertBefore(r,p)}}})(window);
//]]>
</script>
<style type='text/css'>
.b-toc-container {
position: relative;
background:#fff; // 목차 창의 배경색상(기본: 흰색(#fff))
border:1px solid #eee;
border-radius:8px;
display: table;
padding:1.5em;
margin-right: auto;
margin-left: auto;
box-shadow:10px 10px 15px -10px #aaa;
width:80%;
}
.b-toc-container p {
text-align:center;
margin:0;
padding:0;
}
.b-toc-container p span:nth-of-type(1) { // 목차 상단에 표기되는 '목차' 글씨의 조정
font-weight:bold;
font-size:1.3em;
font-family:arial;
color:#555; // '목차' 글씨의 색상(기본: 연회색(#555))
}
.b-toc-container ul {
list-style-type:none;
list-style:none;
margin:0;
padding:0;
}
.b-toc-container > ul {
margin:15px 0 0;
}
.b-toc-container.hide > ul {
display:none;
}
.b-toc-container ul li {
margin:0;
padding:0 0 0 10px;
list-style:none;
line-height:1.7em;
}
.toc-number {
font-weight:bold;
padding-left: 5px;
}
.toc-number:after {
content:"\002E";
}
.b-toc-container ul li a {
color:#42a5f5; // 기본 목차 내용물의 색상 (미지정시 블로그의 Link 색상을 사용함)
display: flex;
align-items: flex-start;
flex-wrap: nowrap;
}
.b-toc-container ul li .toc-number {
margin:0 5px 0 0;
white-space: nowrap;
}
.b-toc-container ul li a:hover {
color: #fff!important;
text-decoration: none!important;
background: #6495ed; // 마우스를 올렸을 때 나타나는 문단 배경 색상
}
.b-toc-container p a { // 목차 우측 상단에 숨기기 버튼을 표기하는 부분
display:none; // 숨기기 버튼 표시여부 (none: 미표시, 공란: 표시)
position: absolute;
right: 10px;
top: 10px;
font-size: .7em;
color: #111!important; // 숨기기 버튼의 글씨 색상 지정
line-height: 1.8em;
text-decoration: none!important;
padding: 0 5px;
background: #62e5c9; // 숨기기 버튼 배경 색상 지정
border-radius: 2px;
opacity: .8;
}
.b-toc-show-wrap {
display: none;
}
.b-toc-container p a:hover {
opacity: 1;
color: #333!important;
}
</style>
<!--자동목차 생성기 종료-->
'컴퓨터 & 코딩 공부 > 웹 & 코딩 기초지식 정리' 카테고리의 다른 글
API, 라이브러리, 프레임워크 및 유사 용어 (0) | 2024.08.16 |
---|---|
구글블로그에 올린 글에 방문객(유입)이 0인 이유 - 샌드박스 기간 (1) | 2024.04.23 |
블로그 특정 요소의 CSS가 어디있는지 빠르게 찾는 방법 : 개발자 도구 활용하기 (0) | 2024.04.23 |
구글 블로그 기본 템플릿에서 우선 수정할 사항 : 인기글 위젯 요약문 글자수, 사진크기, 빈 사진 띄우기 등 (0) | 2024.04.23 |
구글 블로그 기본 템플릿에서 우선 수정할 사항 : 코딩에 서식 적용 (0) | 2024.04.23 |