mirror of
https://github.com/vinta/awesome-python.git
synced 2026-05-09 22:53:49 +08:00
feat(website): mirror index layout on category pages
Add search input, filter chips, no-results block, and back-to-top button to category/group/subcategory pages. Pass filter_urls_json to all page types so tag-chip navigation works site-wide. Fix JS so filter-clear and no-results-clear redirect to / on non-index pages instead of trying to filter a non-existent local table. Remove the now-redundant .category-results CSS overrides. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+6
-1
@@ -339,6 +339,8 @@ def build(repo_root: Path) -> None:
|
|||||||
shutil.rmtree(site_dir)
|
shutil.rmtree(site_dir)
|
||||||
site_dir.mkdir(parents=True)
|
site_dir.mkdir(parents=True)
|
||||||
|
|
||||||
|
filter_urls_json = json.dumps(filter_urls, sort_keys=True, ensure_ascii=False).replace("</", "<\\/")
|
||||||
|
|
||||||
tpl_index = env.get_template("index.html")
|
tpl_index = env.get_template("index.html")
|
||||||
(site_dir / "index.html").write_text(
|
(site_dir / "index.html").write_text(
|
||||||
tpl_index.render(
|
tpl_index.render(
|
||||||
@@ -351,7 +353,7 @@ def build(repo_root: Path) -> None:
|
|||||||
build_date=build_date.strftime("%B %d, %Y"),
|
build_date=build_date.strftime("%B %d, %Y"),
|
||||||
sponsors=sponsors,
|
sponsors=sponsors,
|
||||||
category_urls=category_urls,
|
category_urls=category_urls,
|
||||||
filter_urls_json=json.dumps(filter_urls, sort_keys=True, ensure_ascii=False).replace("</", "<\\/"),
|
filter_urls_json=filter_urls_json,
|
||||||
),
|
),
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
@@ -371,6 +373,7 @@ def build(repo_root: Path) -> None:
|
|||||||
page_kind="category",
|
page_kind="category",
|
||||||
category_urls=category_urls,
|
category_urls=category_urls,
|
||||||
current_path=category_path(category),
|
current_path=category_path(category),
|
||||||
|
filter_urls_json=filter_urls_json,
|
||||||
),
|
),
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
@@ -394,6 +397,7 @@ def build(repo_root: Path) -> None:
|
|||||||
page_kind="group",
|
page_kind="group",
|
||||||
category_urls=category_urls,
|
category_urls=category_urls,
|
||||||
current_path=group_path(group["slug"]),
|
current_path=group_path(group["slug"]),
|
||||||
|
filter_urls_json=filter_urls_json,
|
||||||
),
|
),
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
@@ -431,6 +435,7 @@ def build(repo_root: Path) -> None:
|
|||||||
parent_category=category,
|
parent_category=category,
|
||||||
category_urls=category_urls,
|
category_urls=category_urls,
|
||||||
current_path=subcategory_path(category["slug"], sub["slug"]),
|
current_path=subcategory_path(category["slug"], sub["slug"]),
|
||||||
|
filter_urls_json=filter_urls_json,
|
||||||
),
|
),
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|||||||
+10
-4
@@ -341,6 +341,10 @@ tags.forEach(function (tag) {
|
|||||||
|
|
||||||
if (filterClear) {
|
if (filterClear) {
|
||||||
filterClear.addEventListener("click", function () {
|
filterClear.addEventListener("click", function () {
|
||||||
|
if (!isIndexPage()) {
|
||||||
|
window.location.href = "/";
|
||||||
|
return;
|
||||||
|
}
|
||||||
activeFilter = null;
|
activeFilter = null;
|
||||||
applyFilters();
|
applyFilters();
|
||||||
});
|
});
|
||||||
@@ -349,6 +353,10 @@ if (filterClear) {
|
|||||||
const noResultsClear = document.querySelector(".no-results-clear");
|
const noResultsClear = document.querySelector(".no-results-clear");
|
||||||
if (noResultsClear) {
|
if (noResultsClear) {
|
||||||
noResultsClear.addEventListener("click", function () {
|
noResultsClear.addEventListener("click", function () {
|
||||||
|
if (!isIndexPage()) {
|
||||||
|
window.location.href = "/";
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (searchInput) searchInput.value = "";
|
if (searchInput) searchInput.value = "";
|
||||||
activeFilter = null;
|
activeFilter = null;
|
||||||
applyFilters();
|
applyFilters();
|
||||||
@@ -451,10 +459,8 @@ if (backToTop) {
|
|||||||
) {
|
) {
|
||||||
activeSort = { col: sort, order: order };
|
activeSort = { col: sort, order: order };
|
||||||
}
|
}
|
||||||
if (isIndexPage()) {
|
const matched = urlToFilter[location.pathname];
|
||||||
const matched = urlToFilter[location.pathname];
|
if (matched) activeFilter = matched;
|
||||||
if (matched) activeFilter = matched;
|
|
||||||
}
|
|
||||||
if (q || activeFilter || sort) {
|
if (q || activeFilter || sort) {
|
||||||
sortRows();
|
sortRows();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ kbd {
|
|||||||
.tag:focus-visible,
|
.tag:focus-visible,
|
||||||
.back-to-top:focus-visible,
|
.back-to-top:focus-visible,
|
||||||
.no-results-clear:focus-visible,
|
.no-results-clear:focus-visible,
|
||||||
.category-table a:focus-visible,
|
.table a:focus-visible,
|
||||||
.footer a:focus-visible,
|
.footer a:focus-visible,
|
||||||
.sort-btn:focus-visible {
|
.sort-btn:focus-visible {
|
||||||
outline: 2px solid var(--accent);
|
outline: 2px solid var(--accent);
|
||||||
@@ -498,19 +498,6 @@ kbd {
|
|||||||
text-decoration-color: oklch(100% 0 0 / 0.7);
|
text-decoration-color: oklch(100% 0 0 / 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-results {
|
|
||||||
padding-top: clamp(2.5rem, 5vw, 3.75rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-results .results-intro {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 0.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-results .results-intro .results-note {
|
|
||||||
justify-self: start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sponsor-band {
|
.sponsor-band {
|
||||||
padding-block: clamp(2.5rem, 5.5vw, 4rem);
|
padding-block: clamp(2.5rem, 5.5vw, 4rem);
|
||||||
background:
|
background:
|
||||||
|
|||||||
@@ -38,24 +38,58 @@
|
|||||||
</header>
|
</header>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="results-section category-results" id="category-index">
|
<script type="application/json" id="filter-urls">{{ filter_urls_json | safe }}</script>
|
||||||
|
<section class="results-section" id="library-index">
|
||||||
<div class="results-intro section-shell" data-reveal>
|
<div class="results-intro section-shell" data-reveal>
|
||||||
<div>
|
<div>
|
||||||
<h2>Python Projects in {{ category.name }}</h2>
|
<h2>Search every project in one place</h2>
|
||||||
</div>
|
</div>
|
||||||
<p class="results-note">
|
<p class="results-note">
|
||||||
Sorted by GitHub stars when available. Click any row for details.
|
Press <kbd>/</kbd> to search. Tap a tag to filter. Click any row for
|
||||||
|
details.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="sr-only">{{ category.name }} results</h2>
|
<div class="controls section-shell" data-reveal>
|
||||||
|
<h2 class="sr-only">Search and filter</h2>
|
||||||
|
<div class="search-wrap">
|
||||||
|
<svg
|
||||||
|
class="search-icon"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<circle cx="11" cy="11" r="8" />
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
class="search"
|
||||||
|
placeholder="Search {{ entries | length }} projects in {{ category.name }}..."
|
||||||
|
aria-label="Search projects"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="filter-bar" aria-live="polite">
|
||||||
|
<span>Filtering for <strong class="filter-value"></strong></span>
|
||||||
|
<button class="filter-clear" aria-label="Clear filter">
|
||||||
|
Clear filter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="sr-only">Results</h2>
|
||||||
<div
|
<div
|
||||||
class="table-wrap"
|
class="table-wrap"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="region"
|
role="region"
|
||||||
aria-label="{{ category.name }} libraries table"
|
aria-label="Libraries table"
|
||||||
>
|
>
|
||||||
<table class="table category-table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="col-num"><span class="sr-only">Row number</span></th>
|
<th class="col-num"><span class="sr-only">Row number</span></th>
|
||||||
@@ -69,7 +103,11 @@
|
|||||||
<button type="button" class="sort-btn">Last Commit</button>
|
<button type="button" class="sort-btn">Last Commit</button>
|
||||||
</th>
|
</th>
|
||||||
<th class="col-cat">Tags</th>
|
<th class="col-cat">Tags</th>
|
||||||
<th class="col-arrow"><span class="sr-only">Details</span></th>
|
<th class="col-arrow">
|
||||||
|
<button class="back-to-top" aria-label="Back to top">
|
||||||
|
Top ↑
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -79,7 +117,7 @@
|
|||||||
data-tags="{{ entry.categories | join('||') }}{% if entry.subcategories %}||{{ entry.subcategories | map(attribute='value') | join('||') }}{% endif %}||{{ entry.groups | join('||') }}{% if entry.source_type == 'Built-in' %}||Built-in{% endif %}"
|
data-tags="{{ entry.categories | join('||') }}{% if entry.subcategories %}||{{ entry.subcategories | map(attribute='value') | join('||') }}{% endif %}||{{ entry.groups | join('||') }}{% if entry.source_type == 'Built-in' %}||Built-in{% endif %}"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="category-expand-{{ loop.index }}"
|
aria-controls="expand-{{ loop.index }}"
|
||||||
>
|
>
|
||||||
<td class="col-num">{{ loop.index }}</td>
|
<td class="col-num">{{ loop.index }}</td>
|
||||||
<td class="col-name">
|
<td class="col-name">
|
||||||
@@ -145,7 +183,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="col-arrow"><span class="arrow">→</span></td>
|
<td class="col-arrow"><span class="arrow">→</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="expand-row" id="category-expand-{{ loop.index }}">
|
<tr class="expand-row" id="expand-{{ loop.index }}">
|
||||||
<td></td>
|
<td></td>
|
||||||
<td colspan="4">
|
<td colspan="4">
|
||||||
<div class="expand-content">
|
<div class="expand-content">
|
||||||
@@ -188,6 +226,14 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="no-results" hidden>
|
||||||
|
<p>No projects match your search or filter.</p>
|
||||||
|
<p class="no-results-hint">
|
||||||
|
Try a broader term, or
|
||||||
|
<button class="no-results-clear">browse all projects</button>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="final-cta" data-reveal>
|
<section class="final-cta" data-reveal>
|
||||||
@@ -203,7 +249,13 @@
|
|||||||
rel="noopener"
|
rel="noopener"
|
||||||
>Submit a project</a
|
>Submit a project</a
|
||||||
>
|
>
|
||||||
<a href="/" class="hero-action hero-action-secondary">Browse all</a>
|
<a
|
||||||
|
href="https://github.com/vinta/awesome-python"
|
||||||
|
class="hero-action hero-action-secondary"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>Star the repository</a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ class TestBuild:
|
|||||||
assert 'href="https://example.com/w1"' in category_html
|
assert 'href="https://example.com/w1"' in category_html
|
||||||
assert "A widget." in category_html
|
assert "A widget." in category_html
|
||||||
assert 'href="https://github.com/owner/w2"' in category_html
|
assert 'href="https://github.com/owner/w2"' in category_html
|
||||||
assert '<table class="table category-table">' in category_html
|
assert '<table class="table">' in category_html
|
||||||
assert "42" in category_html
|
assert "42" in category_html
|
||||||
assert "2026-01-01T00:00:00+00:00" in category_html
|
assert "2026-01-01T00:00:00+00:00" in category_html
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user