티스토리 뷰

Tistory

tistory 블로그에 toc 추가

pwnbit 2020. 5. 3. 23:28

toc란

toc는 table of contents를 의미하고, markdown으로 작성한 글의 header를 모아서 보여주는 용도로 사용됩니다.

우연히 python 관련 글을 보다가 tistory 블로그임에도 toc가 붙어있는 것을 보고 작성자분께 양해를 구하고 코드를 가져와서 나름대로 적용을 해 봤습니다.

제가 적용한 toc는 tocbot이고, 깔끔한 스타일이라 마음에 들었습니다.
toc를 적용한 덕분에 오랜만에 블로그에, 그것도 tistory에서 markdown으로 글을 써보네요.

toc code

적용 방법

당연히 tistory skin을 html로 수정을 해야하기 때문에 약간의(?) html, javascript 개발에 대한 지식이 필요합니다.
아래 각 부분을 위치에 맞게만 넣고, javascript 부분만 조금 수정을 하면 크게 문제 없이 적용 가능할 것 같습니다.
이 외에도 toc에 제목을 넣어주기 위해 tistory 기본 스킨 부분을 수정한 것도 있고, 브라우저 개발자 도구로 하나씩 찾아가면서 뜯어 고친 부분도 몇 있습니다.

head 부분

head 태그 안에 넣습니다.

<!-- tocbot -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.css">
<!-- tocbot -->

body 부분

본문이 시작되는 부분에 넣습니다.
제가 쓰는 스킨의 경우는 <div id=dkContent...> 바로 아래에 넣었습니다.

<div class='toc toc-fixed'></div>

script 부분

body 가장 마지막에 넣습니다.

<script>
    // toc
    // set heading id
    function makeHeading(headings){
        Array.prototype.forEach.call(headings, function (heading) {
            var id = heading.id ? heading.id : heading.textContent.trim().toLowerCase()
                    .split(' ').join('-').replace(/[\!\@\#\$\%\^\&\*\(\)\:]/ig, '')
            headingMap[id] = !isNaN(headingMap[id]) ? ++headingMap[id] : 0;
            if (headingMap[id]) {
                heading.id = id + '-' + headingMap[id];
            } else {
                heading.id = id;
            }
        });
    }
    var headingMap = {};
    var headings = document.querySelector('.area_title').querySelectorAll('h1, h2, h3');
    makeHeading(headings);
    var headings = document.querySelector('.area_view').querySelectorAll('h1, h2, h3');
    makeHeading(headings);

    // toc addon
    tocbot.init({
        // Where to render the table of contents.
        tocSelector: '.toc',
        // Where to grab the headings to build the table of contents.
        contentSelector: '.skin_view',
        // Which headings to grab inside of the contentSelector element.
        headingSelector: 'h1, h2, h3',
        // For headings inside relative or absolute positioned containers within content.
        hasInnerContainers: false
    });

    $(window).scroll(function() {
    if (Math.round( $(window).scrollTop()) > $(document).height() - $(window).height() - 500) {
        $("div.toc.toc-fixed").hide(250);
        } else {
            $("div.toc.toc-fixed").show(250);
        }
    });
</script>

CSS 부분

/* tocbot */
.toc-absolute {
    position: absolute;
    margin-top: 165px;
}

.toc-fixed {
    position: fixed;
    top: 165px;
}

.toc {
    left: calc((100% - 720px) / 2 - 300px);
    width: 250px;
    padding: 10px;
    box-sizing: border-box;
}

.toc-list {
    margin-top: 10px !important;
    font-size: 0.9em;
}

.toc > .toc-list li {
    margin-bottom: 10px;
}

.toc > .toc-list li:last-child {
    margin-bottom: 0;
}

.toc > .toc-list li a {
    text-decoration: none;
}

글이 너무 짧은 경우 스크롤 부분에 -500을 해놔서 이상하게 동작하고 조금 뜯어고치다 보니 손 볼데가 있어 보이긴 하지만,
개발을 배운적이 없어 javascript의 Array.prototype... 부분과 같이 동작 방식이 이해가 가지 않는 부분은 건드리지도 못 하네요..
다른 부분들 수정하면서 prototype 부분도 같이 공부 해봐야겠습니다.

댓글
댓글쓰기 폼