mirror of
https://github.com/vinta/awesome-python.git
synced 2026-03-24 01:24:43 +08:00
Replaces MkDocs with a bespoke Python site generator using Jinja2 templates and Markdown. Adds uv for dependency management, GitHub Actions workflow for deployment, and Makefile targets for local development (fetch_stars, build, preview, deploy). Co-Authored-By: Claude <noreply@anthropic.com>
155 lines
4.3 KiB
JavaScript
155 lines
4.3 KiB
JavaScript
// State
|
|
var activeFilter = null; // { type: "cat"|"group", value: "..." }
|
|
var searchInput = document.querySelector('.search');
|
|
var filterBar = document.querySelector('.filter-bar');
|
|
var filterValue = document.querySelector('.filter-value');
|
|
var filterClear = document.querySelector('.filter-clear');
|
|
var noResults = document.querySelector('.no-results');
|
|
var countEl = document.querySelector('.count');
|
|
var rows = document.querySelectorAll('.table tbody tr.row');
|
|
var tags = document.querySelectorAll('.tag');
|
|
var tbody = document.querySelector('.table tbody');
|
|
|
|
function collapseAll() {
|
|
var openRows = document.querySelectorAll('.table tbody tr.row.open');
|
|
openRows.forEach(function (row) {
|
|
row.classList.remove('open');
|
|
row.setAttribute('aria-expanded', 'false');
|
|
});
|
|
}
|
|
|
|
function applyFilters() {
|
|
var query = searchInput ? searchInput.value.toLowerCase().trim() : '';
|
|
var visibleCount = 0;
|
|
|
|
// Collapse all expanded rows on filter/search change
|
|
collapseAll();
|
|
|
|
rows.forEach(function (row) {
|
|
var show = true;
|
|
|
|
// Category/group filter
|
|
if (activeFilter) {
|
|
show = row.dataset[activeFilter.type] === activeFilter.value;
|
|
}
|
|
|
|
// Text search
|
|
if (show && query) {
|
|
if (!row._searchText) {
|
|
var text = row.textContent.toLowerCase();
|
|
var next = row.nextElementSibling;
|
|
if (next && next.classList.contains('expand-row')) {
|
|
text += ' ' + next.textContent.toLowerCase();
|
|
}
|
|
row._searchText = text;
|
|
}
|
|
show = row._searchText.includes(query);
|
|
}
|
|
|
|
row.hidden = !show;
|
|
|
|
if (show) {
|
|
visibleCount++;
|
|
row.querySelector('.col-num').textContent = String(visibleCount);
|
|
}
|
|
});
|
|
|
|
if (noResults) noResults.hidden = visibleCount > 0;
|
|
if (countEl) countEl.textContent = visibleCount;
|
|
|
|
// Update tag highlights
|
|
tags.forEach(function (tag) {
|
|
var isActive = activeFilter
|
|
&& tag.dataset.type === activeFilter.type
|
|
&& tag.dataset.value === activeFilter.value;
|
|
tag.classList.toggle('active', isActive);
|
|
});
|
|
|
|
// Filter bar
|
|
if (filterBar) {
|
|
if (activeFilter) {
|
|
filterBar.hidden = false;
|
|
if (filterValue) filterValue.textContent = activeFilter.value;
|
|
} else {
|
|
filterBar.hidden = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Expand/collapse: event delegation on tbody
|
|
if (tbody) {
|
|
tbody.addEventListener('click', function (e) {
|
|
// Don't toggle if clicking a link or tag button
|
|
if (e.target.closest('a') || e.target.closest('.tag')) return;
|
|
|
|
var row = e.target.closest('tr.row');
|
|
if (!row) return;
|
|
|
|
var isOpen = row.classList.contains('open');
|
|
if (isOpen) {
|
|
row.classList.remove('open');
|
|
row.setAttribute('aria-expanded', 'false');
|
|
} else {
|
|
row.classList.add('open');
|
|
row.setAttribute('aria-expanded', 'true');
|
|
}
|
|
});
|
|
|
|
// Keyboard: Enter or Space on focused .row toggles expand
|
|
tbody.addEventListener('keydown', function (e) {
|
|
if (e.key !== 'Enter' && e.key !== ' ') return;
|
|
var row = e.target.closest('tr.row');
|
|
if (!row) return;
|
|
e.preventDefault();
|
|
row.click();
|
|
});
|
|
}
|
|
|
|
// Tag click: filter by category or group
|
|
tags.forEach(function (tag) {
|
|
tag.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
var type = tag.dataset.type;
|
|
var value = tag.dataset.value;
|
|
|
|
// Toggle: click same filter again to clear
|
|
if (activeFilter && activeFilter.type === type && activeFilter.value === value) {
|
|
activeFilter = null;
|
|
} else {
|
|
activeFilter = { type: type, value: value };
|
|
}
|
|
applyFilters();
|
|
});
|
|
});
|
|
|
|
// Clear filter
|
|
if (filterClear) {
|
|
filterClear.addEventListener('click', function () {
|
|
activeFilter = null;
|
|
applyFilters();
|
|
});
|
|
}
|
|
|
|
// Search input
|
|
if (searchInput) {
|
|
var searchTimer;
|
|
searchInput.addEventListener('input', function () {
|
|
clearTimeout(searchTimer);
|
|
searchTimer = setTimeout(applyFilters, 150);
|
|
});
|
|
|
|
// Keyboard shortcuts
|
|
document.addEventListener('keydown', function (e) {
|
|
if (e.key === '/' && !['INPUT', 'TEXTAREA', 'SELECT'].includes(document.activeElement.tagName) && !e.ctrlKey && !e.metaKey) {
|
|
e.preventDefault();
|
|
searchInput.focus();
|
|
}
|
|
if (e.key === 'Escape' && document.activeElement === searchInput) {
|
|
searchInput.value = '';
|
|
activeFilter = null;
|
|
applyFilters();
|
|
searchInput.blur();
|
|
}
|
|
});
|
|
}
|