Replace hidden attribute on filter-bar with opacity/transform transition
driven by a .visible class, allowing smooth fade-in/slide-down when a
filter is active. Add staggered hero-in keyframe animations to the page
title, subtitle, action buttons, and search box. Polish sortable table
headers with color transition on hover and active states.
Co-Authored-By: Claude <noreply@anthropic.com>
Previously used right: max(1.5rem, calc(50vw - 700px + 0.5rem)) which
caused the button to overlap content at certain viewport widths. Switch
to left: 50% with margin-left: -2rem to keep it centered relative to
the viewport without interfering with sidebar or content layout.
Co-Authored-By: Claude <noreply@anthropic.com>
Adds a fixed-position button that fades in after scrolling 600px and
smoothly scrolls back to the top on click. Hidden by default via the
HTML hidden attribute so noscript users never see it.
Co-Authored-By: Claude <noreply@anthropic.com>
Within the same star count, built-in (stdlib) entries were interleaved
with third-party entries. Add a builtin tier to the sort key so stdlib
entries always rank below non-stdlib entries at equal star counts.
Co-Authored-By: Claude <noreply@anthropic.com>
Stdlib entries now show a "Built-in" tag alongside their regular
category tag. The tag is clickable and filters to all 17 stdlib
entries. Added to data-cats attribute so existing filter logic works.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entries with source_type 'Built-in' have no extractable GitHub repo key
from their URL, so they never received star/metadata enrichment. Fall
back to python/cpython for these entries so the star count and related
data are populated correctly.
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, two entries sharing the same URL but different names would be
collapsed into one. Using a composite (url, name) key preserves distinct
entries while still merging true duplicates.
Co-Authored-By: Claude <noreply@anthropic.com>
Detect the hosting source (stdlib, GitLab, Bitbucket, External) from
the entry URL and surface it as a small badge in the stars column where
a star count would otherwise show an em dash.
Stdlib entries also get their own sort tier — between starred entries
and other no-star entries — so the standard library is not buried at
the bottom of each category.
Co-Authored-By: Claude <noreply@anthropic.com>
Several sections were removed in recent cleanup commits, so the previous
floor of 76 was no longer accurate.
Co-Authored-By: Claude <noreply@anthropic.com>
now_iso and total_batches were recomputed on every iteration. Moving them
above the loop makes intent clearer and avoids redundant work. Also
simplifies cache dict construction with dict unpacking.
Co-Authored-By: Claude <noreply@anthropic.com>
Calling getSortValue inside the comparator ran DOM queries on every
comparison (O(n log n) reads). Hoisting into a forEach beforehand reduces
that to O(n). Batching row appends through a DocumentFragment also avoids
repeated reflows during table reorder.
Co-Authored-By: Claude <noreply@anthropic.com>
Entry was dead code with no callers. Switching from shutil.copy to
write_text uses the already-loaded readme_text variable directly instead
of re-reading the file from disk.
Co-Authored-By: Claude <noreply@anthropic.com>
The website builder previously relied on a hardcoded SECTION_GROUPS list in
build.py to organize categories into thematic groups. This was fragile: any
rename or addition to README.md required a matching code change.
Replace this with a parser-driven approach:
- readme_parser.py now detects bold-only paragraphs (**Group Name**) as
group boundary markers and groups H2 categories beneath them into
ParsedGroup structs.
- build.py drops SECTION_GROUPS entirely; group_categories() now just
passes parsed groups through and appends the Resources group.
- sort.py is removed as it relied on the old flat section model.
- Tests updated throughout to reflect the new (groups, resources) return
shape and to cover the new grouping logic.
Co-Authored-By: Claude <noreply@anthropic.com>
Entries appearing in more than one category were previously emitted as
separate rows. They are now deduplicated in build.py by URL, collecting
all category and group names into lists.
The template encodes those lists as pipe-delimited data attributes
(data-cats, data-groups) and renders a tag button per category.
The JS filter is updated to split on '||' and check for membership,
so clicking any category tag correctly shows the merged row.
Co-Authored-By: Claude <noreply@anthropic.com>
Add active-state press feedback (scale transform) to buttons, filter clear,
and tags. Add moz-osx-font-smoothing for consistent antialiasing on Firefox/Mac.
Apply text-wrap: balance to headings and text-wrap: pretty to body text and
expanded row descriptions. Add text-underline-offset to links and highlight
active table rows with bg-hover.
Co-Authored-By: Claude <noreply@anthropic.com>
- Relocate group tag from expand row to category column so it appears inline beside the category tag
- Add margin between stacked tags with .col-cat .tag + .tag spacing rule
- Remove fixed width from .col-cat; narrow .col-name from 35% to 30% to give category column room
- Hide .tag-group on screens ≤900px and widen .col-name to 50% to reclaim space
Co-Authored-By: Claude <noreply@anthropic.com>
Switch table-layout back to auto on mobile to let columns size naturally,
add uniform cell padding overrides, shrink num/arrow columns further,
pin stars column width, reduce edge padding, and left-align the number
column to avoid awkward right-aligned single digits.
Co-Authored-By: Claude <noreply@anthropic.com>
AI & ML: AI and Agents, Machine Learning, Deep Learning, Computer Vision,
Natural Language Processing, Recommender Systems, Robotics.
Data & Science: Data Analysis, Data Validation, Data Visualization,
Geolocation, Science, Quantum Computing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the Specialized catchall group. Redistribute its categories:
- Web & API: Admin Panels, CMS, Email, Static Site Generator, URL Manipulation
- AI & Data: Geolocation, Robotics
- Content & Media: Game Development, Internationalization
- System & Runtime: Date and Time, Hardware, Microsoft Windows
- Development Tools: Algorithms and Design Patterns
Only Miscellaneous remains ungrouped (falls into Other).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace 'Curated by @vinta since 2014' with 'Maintained by @vinta
and @JinyangWang27' to reflect the new co-maintainer
- Increase .hero-sub font size from --text-sm to --text-base for
better readability
Co-Authored-By: Claude <noreply@anthropic.com>
Introduce CACHE_MAX_AGE_HOURS (12 h) and filter current_repos before
the fetch loop so repos that were updated recently are not re-requested.
Prints a breakdown of fetched vs cached count.
Co-Authored-By: Claude <noreply@anthropic.com>
Replace the separate fetch-github-stars.yml workflow (which committed
star data back to git) with an inline fetch step in deploy-website.yml.
Star data is now stored in Actions cache between runs, eliminating the
workflow_run trigger chain and the need to track github_stars.json in
the repository.
Co-Authored-By: Claude <noreply@anthropic.com>
Rename the Makefile target from fetch_stats to fetch_github_stars to
match the script name. Remove CACHE_MAX_AGE_DAYS and the staleness
check so every run fetches all repos unconditionally.
Co-Authored-By: Claude <noreply@anthropic.com>
Reformats dict and list literals to trailing-comma multiline style
throughout. Also copies README.md to llms.txt in the site output so
LLM crawlers can discover the full content.
Co-Authored-By: Claude <noreply@anthropic.com>
Switch readme_parser.py from regex-based parsing to markdown-it-py for
more robust and maintainable Markdown AST traversal. Update build pipeline,
templates, styles, and JS to support the new parser output. Refresh GitHub
stars data and update tests to match new parser behavior.
Co-Authored-By: Claude <noreply@anthropic.com>
- Add sr-only headings for search/filter and results regions
- Add role=region and aria-label to .table-wrap for landmark navigation
- Add tabindex=0 and focus outline to .table-wrap for keyboard reachability
- Add sr-only text to empty Details column header
- Add role=button to expandable rows
- Add .expand-tags-mobile to show category/group tags in expand row on mobile
- Show .expand-tags-mobile via media query at <=900px breakpoint
Co-Authored-By: Claude <noreply@anthropic.com>
Replace two-column footer (links left, attribution right) with a
single inline row of slash-separated items. Update attribution text
to 'Made by Vinta' with a link to vinta.ws, align footer links to
match standard anchor color/hover behavior.
Co-Authored-By: Claude <noreply@anthropic.com>
Replace the inline data-URI emoji favicon with a proper Python-logo SVG
served from /static/favicon.svg. Avoids repeated base64 encoding overhead
and allows the icon to be cached and updated independently.
Co-Authored-By: Claude <noreply@anthropic.com>
Rename site_* targets to bare names (install, fetch_stats, build,
preview). Replace the static preview target with a watchmedo-driven
live-reload loop so file changes trigger automatic rebuilds. Make
the output directory creation idempotent (exist_ok=True) and static
copy incremental (dirs_exist_ok=True) so repeated builds don't wipe
output on each run.
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove `_has_description` which duplicated `_extract_description` logic;
use truthiness of the description string instead
- Remove unused `resources` parameter from `extract_entries`
- Merge two sequential loops in `parse_readme` into a single pass over
children to find hr, Resources, and Contributing indices
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
load_cache was a duplicate of logic now living in build.load_stars.
Switch the call site to the shared helper and remove the redundant
local function and its tests.
Co-Authored-By: Claude <noreply@anthropic.com>
slugify, parse_readme, count_entries, extract_preview, render_content_html,
and related helpers are moved to a dedicated readme_parser module.
build.py now imports from readme_parser rather than defining these inline.
Tests for the removed functions are dropped from test_build.py since they
now live with the module they test.
Co-Authored-By: Claude <noreply@anthropic.com>
Replace the _render_section_html stub with a working implementation that
converts parsed bullet-list nodes into classed div elements (entry,
entry-sub, subcat). Add _render_bullet_list_html to handle nested
structure and XSS escaping. Cover all cases with a new
TestRenderSectionHtml suite.
Co-Authored-By: Claude <noreply@anthropic.com>
Replace _parse_section_entries stub with full implementation that walks
bullet_list AST nodes to extract ParsedEntry records, including support
for subcategory labels (text-only list items) and also_see nested links.
Add _parse_list_entries, helper finders (_find_inline, _find_first_link,
_find_child), and _extract_description_html with separator stripping.
Extend test suite with TestParseSectionEntries covering flat entries,
link-only entries, subcategorized entries, also_see, entry_count, preview
first-four, and XSS escaping in description HTML.
Co-Authored-By: Claude <noreply@anthropic.com>
Introduce parse_readme() which uses MarkdownIt to build a full AST
instead of line-by-line regex matching. The function splits the document
at the thematic break, groups nodes by h2 heading, extracts category
descriptions from leading italic paragraphs, and separates the
Categories, Resources, and Contributing sections cleanly.
Add markdown-it-py==4.0.0 (+ mdurl) as a runtime dependency to support
the new parser.
Tests cover section counts, names, slugs, descriptions, content
presence, boundary conditions (no separator, no description), and mixed
description markup.
Co-Authored-By: Claude <noreply@anthropic.com>
Introduce readme_parser.py which parses README.md into structured
section data using the markdown-it-py AST. Includes TypedDicts for
ParsedEntry/ParsedSection, slugify(), render_inline_html(), and
render_inline_text(). Add test_readme_parser.py covering HTML escaping,
link rendering, emphasis, strong, and code_inline for both renderers.
Co-Authored-By: Claude <noreply@anthropic.com>
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>