function loadResource(type, attributes) { if (type === 'style') { const style = document.createElement('style'); style.textContent = attributes.css; document.head.appendChild(style); } } function createTOC() { const tocElement = document.createElement('div'); tocElement.className = 'toc'; const contentContainer = document.querySelector('.markdown-body'); contentContainer.appendChild(tocElement); const headings = contentContainer.querySelectorAll('h1, h2, h3, h4, h5, h6'); headings.forEach(heading => { if (!heading.id) { heading.id = heading.textContent.trim().replace(/\s+/g, '-').toLowerCase(); } const link = document.createElement('a'); link.href = '#' + heading.id; link.textContent = heading.textContent; link.className = 'toc-link'; link.style.paddingLeft = `${(parseInt(heading.tagName.charAt(1)) - 1) * 10}px`; tocElement.appendChild(link); }); } function toggleTOC() { const tocElement = document.querySelector('.toc'); const tocIcon = document.querySelector('.toc-icon'); if (tocElement) { tocElement.classList.toggle('show'); tocIcon.classList.toggle('active'); tocIcon.textContent = tocElement.classList.contains('show') ? '✖' : '☰'; } } document.addEventListener("DOMContentLoaded", function() { createTOC(); const css = ` :root { --toc-bg: #fff; --toc-border: #e1e4e8; --toc-text: #24292e; --toc-hover: #f6f8fa; --toc-icon-bg: #fff; --toc-icon-color: #ad6598; --toc-icon-active-bg: #813c85; --toc-icon-active-color: #fff; } @media (prefers-color-scheme: dark) { :root { --toc-bg: #2d333b; --toc-border: #444c56; --toc-text: #adbac7; --toc-hover: #373e47; --toc-icon-bg: #22272e; --toc-icon-color: #ad6598; --toc-icon-active-bg: #813c85; --toc-icon-active-color: #adbac7; } } .toc { position: fixed; bottom: 60px; right: 20px; width: 250px; max-height: 70vh; background-color: var(--toc-bg); border: 1px solid var(--toc-border); border-radius: 6px; padding: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); overflow-y: auto; z-index: 1000; opacity: 0; visibility: hidden; transform: translateY(20px) scale(0.9); transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s; } .toc.show { opacity: 1; visibility: visible; transform: translateY(0) scale(1); } .toc a { display: block; color: var(--toc-text); text-decoration: none; padding: 5px 0; font-size: 14px; line-height: 1.5; border-bottom: 1px solid var(--toc-border); transition: background-color 0.2s ease, padding-left 0.2s ease; } .toc a:last-child { border-bottom: none; } .toc a:hover { background-color: var(--toc-hover); padding-left: 5px; } .toc-icon { position: fixed; bottom: 20px; right: 20px; cursor: pointer; font-size: 24px; background-color: var(--toc-icon-bg); color: var(--toc-icon-color); border: 2px solid var(--toc-icon-color); border-radius: 50%; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; box-shadow: 0 1px 3px rgba(0,0,0,0.12); z-index: 1001; transition: all 0.3s ease; user-select: none; -webkit-tap-highlight-color: transparent; outline: none; } .toc-icon:hover { transform: scale(1.1); } .toc-icon:active { transform: scale(0.9); } .toc-icon.active { background-color: var(--toc-icon-active-bg); color: var(--toc-icon-active-color); border-color: var(--toc-icon-active-bg); transform: rotate(90deg); } `; loadResource('style', {css: css}); const tocIcon = document.createElement('div'); tocIcon.className = 'toc-icon'; tocIcon.textContent = '☰'; tocIcon.onclick = (e) => { e.stopPropagation(); toggleTOC(); }; document.body.appendChild(tocIcon); document.addEventListener('click', (e) => { const tocElement = document.querySelector('.toc'); if (tocElement && tocElement.classList.contains('show') && !tocElement.contains(e.target) && !e.target.classList.contains('toc-icon')) { toggleTOC(); } }); });