dd67d2c2ec
Весь контент перенесён в content/yasha/ (7 подразделов). Создан content/semen/ с подразделами: changelog, kb, diary. Навигация — dropdown в навбаре, двухуровневое меню в hugo.toml. Шаблоны, сайдбар, поиск обновлены под вложенные секции.
96 lines
3.3 KiB
JavaScript
96 lines
3.3 KiB
JavaScript
// Search functionality using Fuse.js
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const searchInput = document.getElementById('search-input');
|
|
const searchForm = document.querySelector('.search-form');
|
|
const searchResults = document.getElementById('search-results');
|
|
const resultsList = document.getElementById('results-list');
|
|
const closeSearch = document.getElementById('close-search');
|
|
|
|
if (!searchInput) return;
|
|
|
|
let fuse;
|
|
|
|
// Load search index
|
|
fetch('/index.json')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
fuse = new Fuse(data, {
|
|
keys: ['title', 'content', 'tags'],
|
|
includeScore: true,
|
|
threshold: 0.3,
|
|
ignoreLocation: true,
|
|
minMatchCharLength: 2
|
|
});
|
|
})
|
|
.catch(err => console.error('Failed to load search index:', err));
|
|
|
|
function performSearch(query) {
|
|
if (!fuse || !query.trim()) {
|
|
searchResults.style.display = 'none';
|
|
return;
|
|
}
|
|
|
|
const results = fuse.search(query, { limit: 10 });
|
|
|
|
if (results.length === 0) {
|
|
resultsList.innerHTML = '<li>Ничего не найдено</li>';
|
|
} else {
|
|
resultsList.innerHTML = results.map(result => {
|
|
const item = result.item;
|
|
const sectionLabels = {
|
|
'yasha/diary': 'Яша / Дневник',
|
|
'yasha/kb': 'Яша / База знаний',
|
|
'yasha/plans': 'Яша / Планы',
|
|
'yasha/guides': 'Яша / Инструкции',
|
|
'yasha/creds': 'Яша / Креды',
|
|
'yasha/leadera': 'Яша / Leadera',
|
|
'yasha/personal-site': 'Яша / Личный сайт',
|
|
'semen': 'Семен',
|
|
'semen/diary': 'Семен / Дневник',
|
|
'semen/kb': 'Семен / База знаний'
|
|
};
|
|
const label = sectionLabels[item.section] || item.section;
|
|
return `<li>
|
|
<a href="${item.url}">
|
|
<strong>${item.title}</strong>
|
|
<small class="text-muted d-block">${label}</small>
|
|
</a>
|
|
</li>`;
|
|
}).join('');
|
|
}
|
|
|
|
searchResults.style.display = 'block';
|
|
}
|
|
|
|
// Debounce function
|
|
let debounceTimer;
|
|
function debounce(func, delay) {
|
|
return function() {
|
|
const context = this;
|
|
const args = arguments;
|
|
clearTimeout(debounceTimer);
|
|
debounceTimer = setTimeout(() => func.apply(context, args), delay);
|
|
};
|
|
}
|
|
|
|
searchInput.addEventListener('input', debounce(function(e) {
|
|
performSearch(e.target.value);
|
|
}, 200));
|
|
|
|
searchForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
performSearch(searchInput.value);
|
|
});
|
|
|
|
closeSearch.addEventListener('click', function() {
|
|
searchResults.style.display = 'none';
|
|
});
|
|
|
|
// Close search when clicking outside
|
|
document.addEventListener('click', function(e) {
|
|
if (!searchForm.contains(e.target) && !searchResults.contains(e.target)) {
|
|
searchResults.style.display = 'none';
|
|
}
|
|
});
|
|
});
|