diff --git a/website/build.py b/website/build.py index c204cbeb..7e87dcbd 100644 --- a/website/build.py +++ b/website/build.py @@ -39,6 +39,24 @@ class StarData(TypedDict): GITHUB_REPO_URL_RE = re.compile(r"^https?://github\.com/([^/]+/[^/]+?)(?:\.git)?/?$") +SOURCE_TYPE_DOMAINS = { + "docs.python.org": "stdlib", + "gitlab.com": "GitLab", + "bitbucket.org": "Bitbucket", +} + + +def detect_source_type(url: str) -> str | None: + """Detect source type from URL domain. Returns None for GitHub URLs.""" + if GITHUB_REPO_URL_RE.match(url): + return None + for domain, source_type in SOURCE_TYPE_DOMAINS.items(): + if domain in url: + return source_type + if "github.com" not in url: + return "External" + return None + def extract_github_repo(url: str) -> str | None: """Extract owner/repo from a GitHub repo URL. Returns None for non-GitHub URLs.""" @@ -57,14 +75,19 @@ def load_stars(path: Path) -> dict[str, StarData]: def sort_entries(entries: list[dict]) -> list[dict]: - """Sort entries by stars descending, then name ascending. No-star entries go last.""" + """Sort entries by stars descending, then name ascending. + + Three tiers: starred entries first, stdlib second, other non-starred last. + """ def sort_key(entry: dict) -> tuple[int, int, str]: stars = entry["stars"] name = entry["name"].lower() - if stars is None: + if stars is not None: + return (0, -stars, name) + if entry.get("source_type") == "stdlib": return (1, 0, name) - return (0, -stars, name) + return (2, 0, name) return sorted(entries, key=sort_key) @@ -105,6 +128,7 @@ def extract_entries( "stars": None, "owner": None, "last_commit_at": None, + "source_type": detect_source_type(url), "also_see": entry["also_see"], } seen[url] = merged diff --git a/website/static/style.css b/website/static/style.css index 8f86f881..da7652f4 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -334,6 +334,19 @@ th[data-sort].sort-asc::after { text-align: right; } +/* === Source Badges === */ +.source-badge { + display: inline-block; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.03em; + color: var(--text-muted); + background: var(--bg-input); + padding: 0.15rem 0.45rem; + border-radius: 3px; + white-space: nowrap; +} + /* === Arrow Column === */ .col-arrow { width: 2.5rem; diff --git a/website/templates/index.html b/website/templates/index.html index 9e8b25d1..dc5fd55a 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -98,6 +98,7 @@ {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{% + elif entry.source_type %}{{ entry.source_type }}{% else %}—{% endif %}