mirror of
https://github.com/Swarsel/.dotfiles.git
synced 2026-04-14 13:19:09 +02:00
docs: improve docs page
This commit is contained in:
parent
5ff362e1ea
commit
98b2cb93e2
1 changed files with 743 additions and 539 deletions
|
|
@ -212,6 +212,117 @@ I also add this javascript to add header pinning functionality to the site, usin
|
||||||
const body = document.body;
|
const body = document.body;
|
||||||
|
|
||||||
if (!content || !pinnedList || !toggleBtn || !clearAllBtn || !toc) return;
|
if (!content || !pinnedList || !toggleBtn || !clearAllBtn || !toc) return;
|
||||||
|
function injectSearch() {
|
||||||
|
// Check if already injected
|
||||||
|
if (document.getElementById('toc-search-input')) return;
|
||||||
|
|
||||||
|
const searchContainer = document.createElement('div');
|
||||||
|
searchContainer.id = 'toc-search-container';
|
||||||
|
|
||||||
|
const searchInput = document.createElement('input');
|
||||||
|
searchInput.id = 'toc-search-input';
|
||||||
|
searchInput.type = 'text';
|
||||||
|
searchInput.placeholder = 'Search TOC...';
|
||||||
|
searchInput.autocomplete = 'off';
|
||||||
|
|
||||||
|
const clearBtn = document.createElement('button');
|
||||||
|
clearBtn.id = 'toc-search-clear';
|
||||||
|
clearBtn.type = 'button';
|
||||||
|
clearBtn.textContent = 'Clear';
|
||||||
|
|
||||||
|
searchContainer.appendChild(searchInput);
|
||||||
|
searchContainer.appendChild(clearBtn);
|
||||||
|
|
||||||
|
toc.insertBefore(searchContainer, toc.firstChild);
|
||||||
|
|
||||||
|
function filterTOC(term) {
|
||||||
|
const allLinks = toc.querySelectorAll('a');
|
||||||
|
|
||||||
|
allLinks.forEach(link => {
|
||||||
|
const li = link.closest('li');
|
||||||
|
if (!li) return;
|
||||||
|
|
||||||
|
const text = link.textContent.toLowerCase();
|
||||||
|
const matches = text.includes(term);
|
||||||
|
|
||||||
|
if (matches) {
|
||||||
|
li.classList.remove('hidden-by-search');
|
||||||
|
let parent = li.parentElement;
|
||||||
|
while (parent && parent !== toc) {
|
||||||
|
if (parent.tagName === 'UL') {
|
||||||
|
parent.style.display = '';
|
||||||
|
}
|
||||||
|
if (parent.tagName === 'LI') {
|
||||||
|
parent.classList.remove('hidden-by-search');
|
||||||
|
}
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
li.classList.add('hidden-by-search');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (term === '') {
|
||||||
|
const allLis = toc.querySelectorAll('li');
|
||||||
|
allLis.forEach(li => li.classList.remove('hidden-by-search'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchInput.addEventListener('input', function(e) {
|
||||||
|
const term = e.target.value.toLowerCase();
|
||||||
|
filterTOC(term);
|
||||||
|
});
|
||||||
|
|
||||||
|
clearBtn.addEventListener('click', function() {
|
||||||
|
searchInput.value = '';
|
||||||
|
filterTOC('');
|
||||||
|
searchInput.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
injectSearch();
|
||||||
|
function addHeadingLinks() {
|
||||||
|
const headers = content.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
||||||
|
headers.forEach(header => {
|
||||||
|
const id = header.getAttribute('id');
|
||||||
|
if (!id) return;
|
||||||
|
|
||||||
|
if (header.querySelector('.heading-link')) return;
|
||||||
|
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.className = 'heading-link';
|
||||||
|
link.href = '#' + id;
|
||||||
|
link.textContent = '#';
|
||||||
|
link.title = 'Copy link to this heading';
|
||||||
|
|
||||||
|
const pinBtn = header.querySelector('.toc-pin-btn');
|
||||||
|
if (pinBtn) {
|
||||||
|
header.insertBefore(link, pinBtn);
|
||||||
|
} else {
|
||||||
|
header.appendChild(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
link.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const url = window.location.origin + window.location.pathname + '#' + id;
|
||||||
|
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
navigator.clipboard.writeText(url).then(() => {
|
||||||
|
const originalText = link.textContent;
|
||||||
|
link.textContent = '✓';
|
||||||
|
setTimeout(() => {
|
||||||
|
link.textContent = originalText;
|
||||||
|
}, 1000);
|
||||||
|
}).catch(err => {
|
||||||
|
console.warn('Failed to copy to clipboard', err);
|
||||||
|
window.location.hash = id;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
window.location.hash = id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
addHeadingLinks();
|
||||||
|
|
||||||
let mobileTocBtn = document.getElementById('mobile-toc-toggle');
|
let mobileTocBtn = document.getElementById('mobile-toc-toggle');
|
||||||
if (!mobileTocBtn) {
|
if (!mobileTocBtn) {
|
||||||
|
|
@ -241,6 +352,31 @@ I also add this javascript to add header pinning functionality to the site, usin
|
||||||
else body.classList.remove('mobile-panel-open');
|
else body.classList.remove('mobile-panel-open');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
if (window.innerWidth > 1000) return;
|
||||||
|
|
||||||
|
if (!anyMobilePanelOpen()) return;
|
||||||
|
|
||||||
|
const clickedInsideToc = toc.contains(e.target);
|
||||||
|
const clickedInsidePinned = pinnedPanel.contains(e.target);
|
||||||
|
const clickedTocBtn = mobileTocBtn.contains(e.target);
|
||||||
|
const clickedPinnedBtn = mobilePinnedBtn.contains(e.target);
|
||||||
|
|
||||||
|
const clickedInteractive =
|
||||||
|
e.target.tagName === 'A' ||
|
||||||
|
e.target.tagName === 'BUTTON' ||
|
||||||
|
e.target.tagName === 'INPUT' ||
|
||||||
|
e.target.tagName === 'TEXTAREA' ||
|
||||||
|
e.target.closest('a') ||
|
||||||
|
e.target.closest('button');
|
||||||
|
|
||||||
|
if (!clickedInsideToc && !clickedInsidePinned && !clickedTocBtn && !clickedPinnedBtn && !clickedInteractive) {
|
||||||
|
toc.classList.remove('mobile-visible');
|
||||||
|
pinnedPanel.classList.remove('mobile-visible');
|
||||||
|
updateBodyMobilePanelState();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
mobileTocBtn.addEventListener('click', function() {
|
mobileTocBtn.addEventListener('click', function() {
|
||||||
const isOpen = toc.classList.toggle('mobile-visible');
|
const isOpen = toc.classList.toggle('mobile-visible');
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
|
|
@ -511,7 +647,7 @@ I also add this javascript to add header pinning functionality to the site, usin
|
||||||
showBtn = document.createElement('button');
|
showBtn = document.createElement('button');
|
||||||
showBtn.id = 'show-pinned-btn';
|
showBtn.id = 'show-pinned-btn';
|
||||||
showBtn.type = 'button';
|
showBtn.type = 'button';
|
||||||
showBtn.textContent = 'Show Pinned';
|
showBtn.textContent = 'Pinned';
|
||||||
document.body.appendChild(showBtn);
|
document.body.appendChild(showBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -725,7 +861,7 @@ I also add this javascript to add header pinning functionality to the site, usin
|
||||||
attachPinBehavior(pinBtn, href, text);
|
attachPinBehavior(pinBtn, href, text);
|
||||||
});
|
});
|
||||||
|
|
||||||
const headers = content.querySelectorAll('h2, h3, h4, h5');
|
const headers = content.querySelectorAll('h2, h3, h4, h5, h6');
|
||||||
headers.forEach(header => {
|
headers.forEach(header => {
|
||||||
const id = header.getAttribute('id');
|
const id = header.getAttribute('id');
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
|
|
@ -32296,12 +32432,67 @@ This is the stylesheet used by the [[#h:12880c64-229c-4063-9eea-387a97490676][HT
|
||||||
background-color: #232b32;
|
background-color: #232b32;
|
||||||
border-right: 1px solid #2f3b45;
|
border-right: 1px solid #2f3b45;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#table-of-contents h2 {
|
#table-of-contents h2 {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#toc-search-container {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background-color: #232b32;
|
||||||
|
z-index: 10;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toc-search-input {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background-color: #1d252c;
|
||||||
|
border: 1px solid #2f3b45;
|
||||||
|
color: #b7c5d3;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toc-search-input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #5ec4ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toc-search-clear {
|
||||||
|
padding: 0.5rem 0.7rem;
|
||||||
|
background-color: #2f3b45;
|
||||||
|
border: 1px solid #3a4a56;
|
||||||
|
color: #b7c5d3;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s, color 0.2s;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toc-search-clear:hover {
|
||||||
|
background-color: #3a4a56;
|
||||||
|
color: #ff6b6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-by-search {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#text-table-of-contents {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
#text-table-of-contents ul {
|
#text-table-of-contents ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
|
@ -32353,29 +32544,12 @@ This is the stylesheet used by the [[#h:12880c64-229c-4063-9eea-387a97490676][HT
|
||||||
margin-top: 2.2rem;
|
margin-top: 2.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 { font-size: 2rem; }
|
||||||
font-size: 2rem;
|
h2 { font-size: 1.6rem; }
|
||||||
}
|
h3 { font-size: 1.3rem; }
|
||||||
|
h4 { font-size: 1.2rem; }
|
||||||
h2 {
|
h5 { font-size: 1.1rem; }
|
||||||
font-size: 1.6rem;
|
h6 { font-size: 1.0rem; }
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: 1.0rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #5ec4ff;
|
color: #5ec4ff;
|
||||||
|
|
@ -32677,6 +32851,36 @@ This is the stylesheet used by the [[#h:12880c64-229c-4063-9eea-387a97490676][HT
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
padding: 1.5rem 1.25rem;
|
padding: 1.5rem 1.25rem;
|
||||||
}
|
}
|
||||||
|
#toc-search-container {
|
||||||
|
top: 3rem;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-link {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: opacity 0.2s, visibility 0.2s;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
color: #718ca1;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.8em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-link:hover {
|
||||||
|
color: #5ec4ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:hover .heading-link,
|
||||||
|
h2:hover .heading-link,
|
||||||
|
h3:hover .heading-link,
|
||||||
|
h4:hover .heading-link,
|
||||||
|
h5:hover .heading-link,
|
||||||
|
h6:hover .heading-link {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue