레이블이 목차만들기인 게시물을 표시합니다. 모든 게시물 표시
레이블이 목차만들기인 게시물을 표시합니다. 모든 게시물 표시

2025년 11월 22일 토요일

블로그스팟 - 목차 만들기(+Blogger 테마에 자동 목차 생성,JavaScript 위젯 프로그램)

블로그스팟 - 목차 만들기(+Blogger 테마에 자동 목차 생성,JavaScript 위젯 프로그램)

Blogger 테마에 자동 목차 생성 기능을 추가하기 위한 JavaScript 위젯 프로그램입니다.

이 코드는 게시물 본문 내의 H2, H3, H4 태그를 자동으로 스캔하여 클릭 가능한 목차(Table of Contents)를 생성하고, 이를 게시물 제목 아래에 삽입합니다.

구현 난이도 '상'을 포함하는 이유는, 이 코드를 Blogger 테마의 HTML 편집 영역에 직접 삽입하고, 사용자의 테마 구조에 따라 특정 CSS 선택자(postBody 변수)를 조정해야 할 수도 있기 때문입니다.

아래 파일을 다운로드하여 내용을 복사한 후, Blogger 대시보드 -> 테마 -> HTML 편집으로 이동하여 </body> 닫는 태그 바로 위에 붙여넣으시면 됩니다.


<!--============================================================
Blogger 자동 목차 생성 위젯 (Automatic Table of Contents Widget)
============================================================
[사용 방법]
1. 이 전체 코드를 복사합니다.
2. Blogger 대시보드에서 [테마] -> [HTML 편집]으로 이동합니다.
3. </body> 닫는 태그 바로 위에 이 코드를 붙여넣습니다.
4. (선택 사항) 사용 중인 테마에 따라 '.post-body' 선택자가 다를 수 있습니다.
   만약 목차가 생성되지 않으면 JavaScript 코드 내의 'postBody' 변수 설정을
   게시물 본문 영역의 정확한 CSS 선택자로 변경해야 합니다.-->
<style>
/* ============================================================
목차 위젯 기본 스타일 (Custom Styles)
============================================================
*/
#auto-toc-container {
    border: 1px solid #e0e0e0;
    padding: 15px;
    margin: 20px 0;
    border-radius: 8px;
    background-color: #f9f9f9;
    font-family: 'Noto Sans', sans-serif;
}

#auto-toc-container h2 {
    font-size: 1.3em;
    color: #333;
    margin-top: 0;
    margin-bottom: 10px;
    border-bottom: 2px solid #ddd;
    padding-bottom: 5px;
    font-weight: 700;
}

#auto-toc-container ol {
    list-style-type: decimal; /* 숫자 목록 */
    padding-left: 20px;
    margin: 0;
}

#auto-toc-container ol li {
    margin-bottom: 5px;
    line-height: 1.5;
}

#auto-toc-container a {
    text-decoration: none;
    color: #007bff; /* 링크 색상 */
    transition: color 0.2s;
}

#auto-toc-container a:hover {
    color: #0056b3; /* 호버 색상 */
    text-decoration: underline;
}

/* 계층별 들여쓰기 */
.toc-list-level-2 {
    padding-left: 25px; /* H3는 더 깊게 들여쓰기 */
}
.toc-list-level-3 {
    padding-left: 45px; /* H4는 더 깊게 들여쓰기 */
}
</style>

<script>
//<![CDATA[
// JavaScript를 이용한 자동 목차 생성 로직
function generateTOC() {
    // 1. 블로그 게시물 본문 요소를 찾습니다.
    // 대부분의 Blogger 테마에서 작동하는 일반적인 선택자입니다.
    // 만약 목차가 생성되지 않으면, 사용 중인 테마의 게시물 본문 영역 클래스로 변경해야 합니다.
    const postBody = document.querySelector('.post-body') || document.querySelector('.entry-content') || document.querySelector('.post-content');

    // 게시물 본문을 찾지 못하거나 목차 생성 제외 태그가 발견되면 종료
    if (!postBody) return;
    
    // 이 코드를 추가하여 목차 생성을 원하지 않는 글을 제외할 수 있습니다.
    // <div class="no-toc"></div>를 글 본문에 추가하면 목차가 생성되지 않습니다.
    if (postBody.querySelector('.no-toc')) return;


    // 2. H2, H3, H4 태그를 모두 찾습니다. (H1은 게시물 제목이므로 제외)
    const headings = postBody.querySelectorAll('h2, h3, h4');
    if (headings.length < 2) return; // 최소 두 개 이상의 제목이 있어야 목차를 생성합니다.

    // 3. 목차(TOC) 컨테이너 생성
    const tocContainer = document.createElement('div');
    tocContainer.id = 'auto-toc-container';
    tocContainer.innerHTML = '<h2>목차 (Contents)</h2>'; 

    // 최상위 리스트 (H2 레벨) 시작
    let tocList = document.createElement('ol'); 
    tocList.className = 'toc-list-level-1';
    tocContainer.appendChild(tocList);

    let currentList = tocList; // 현재 작업 중인 리스트 요소 (ol)
    let currentLevel = 2;      // 현재 H 태그 레벨 (H2로 시작)

    headings.forEach((heading, index) => {
        const level = parseInt(heading.tagName.substring(1)); // 2, 3, or 4
        
        // 4. 고유 ID 생성 및 할당 (앵커 링크 연결을 위해 필수)
        const headingId = 'toc-heading-' + (index + 1) + '-' + heading.textContent.replace(/[^a-z0-9]/gi, '').substring(0, 10).toLowerCase();
        heading.id = headingId;

        // 5. 계층 구조에 맞게 리스트 조정 (들여쓰기)
        while (currentLevel < level) {
            // 하위 레벨로 내려가기 (예: H2 -> H3)
            const newList = document.createElement('ol');
            newList.className = `toc-list-level-${level}`;
            if (currentList.lastChild) {
                currentList.lastChild.appendChild(newList);
            } else {
                 // H2가 바로 H4로 넘어가는 등 비정상적인 구조일 때 대비
                currentList.appendChild(document.createElement('li')).appendChild(newList);
            }
            currentList = newList;
            currentLevel++;
        }

        while (currentLevel > level) {
            // 상위 레벨로 올라가기 (예: H4 -> H2)
            currentList = currentList.parentNode.closest('ol');
            if (!currentList) {
                // 안전 장치: 최상위 리스트까지 올라왔다면 break
                currentList = tocList;
                break;
            }
            currentLevel--;
        }

        // 6. 목차 항목 (li) 생성 및 현재 리스트에 추가
        const listItem = document.createElement('li');
        const link = document.createElement('a');
        link.href = '#' + headingId;
        link.textContent = heading.textContent;
        listItem.appendChild(link);
        currentList.appendChild(listItem);
        currentLevel = level; // 현재 레벨 업데이트
    });

    // 7. 목차를 게시물 본문의 시작 부분에 삽입 (H1 바로 아래)
    postBody.insertBefore(tocContainer, postBody.firstChild);
}

// 페이지 로드 후 generateTOC 함수를 실행합니다.
// 앵커 링크 충돌을 막기 위해 DOMContentLoaded가 아닌 window.onload를 사용합니다.
window.onload = function() {
    // 딜레이를 주어 테마 로딩 완료 후 실행되도록 보장합니다.
    setTimeout(generateTOC, 500); 
};
//]]>
</script><br />

이 코드는 H2, H3, H4 태그의 들여쓰기를 정확히 반영하여 계층적인 목차를 생성해 독자가 글의 구조를 한눈에 파악할 수 있도록 돕습니다.

추가 팁:

  • 성능: window.onload 후 500ms의 딜레이(setTimeout)를 주어 다른 스크립트나 테마 요소가 먼저 로드된 후 목차를 생성하도록 하여 페이지 로딩 안정성을 높였습니다.

  • 제외 기능: 특정 글에 목차 생성을 원하지 않을 경우, 해당 글의 HTML 편집 모드에서 본문 아무 곳에 <div class="no-toc"></div> 태그를 삽입하면 목차 생성이 자동으로 건너뛰어집니다.