mirror of
https://github.com/vinta/awesome-python.git
synced 2026-03-23 05:03:45 +08:00
feat(website): add social proof line to hero with star count and build date
Display the awesome-python repo's star count (formatted as '230k+') and the last data refresh date below the hero CTA. Fetches the self-repo star count by always including vinta/awesome-python in the stars fetch. Also removes the footer date stamp, which is now surfaced in the hero. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1
Makefile
1
Makefile
@@ -14,7 +14,6 @@ build:
|
|||||||
uv run python website/build.py
|
uv run python website/build.py
|
||||||
|
|
||||||
preview: build
|
preview: build
|
||||||
@echo "Check the website on http://localhost:8000"
|
|
||||||
uv run watchmedo shell-command \
|
uv run watchmedo shell-command \
|
||||||
--patterns='*.md;*.html;*.css;*.js;*.py' \
|
--patterns='*.md;*.html;*.css;*.js;*.py' \
|
||||||
--recursive \
|
--recursive \
|
||||||
|
|||||||
@@ -126,6 +126,13 @@ def extract_entries(
|
|||||||
return entries
|
return entries
|
||||||
|
|
||||||
|
|
||||||
|
def format_stars_short(stars: int) -> str:
|
||||||
|
"""Format star count as compact string like '230k'."""
|
||||||
|
if stars >= 1000:
|
||||||
|
return f"{stars // 1000}k"
|
||||||
|
return str(stars)
|
||||||
|
|
||||||
|
|
||||||
def build(repo_root: str) -> None:
|
def build(repo_root: str) -> None:
|
||||||
"""Main build: parse README, render single-page HTML via Jinja2 templates."""
|
"""Main build: parse README, render single-page HTML via Jinja2 templates."""
|
||||||
repo = Path(repo_root)
|
repo = Path(repo_root)
|
||||||
@@ -146,6 +153,10 @@ def build(repo_root: str) -> None:
|
|||||||
entries = extract_entries(categories, parsed_groups)
|
entries = extract_entries(categories, parsed_groups)
|
||||||
|
|
||||||
stars_data = load_stars(website / "data" / "github_stars.json")
|
stars_data = load_stars(website / "data" / "github_stars.json")
|
||||||
|
|
||||||
|
repo_self = stars_data.get("vinta/awesome-python", {})
|
||||||
|
repo_stars = format_stars_short(repo_self["stars"]) if "stars" in repo_self else None
|
||||||
|
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
repo_key = extract_github_repo(entry["url"])
|
repo_key = extract_github_repo(entry["url"])
|
||||||
if not repo_key and entry.get("source_type") == "Built-in":
|
if not repo_key and entry.get("source_type") == "Built-in":
|
||||||
@@ -176,6 +187,7 @@ def build(repo_root: str) -> None:
|
|||||||
entries=entries,
|
entries=entries,
|
||||||
total_entries=total_entries,
|
total_entries=total_entries,
|
||||||
total_categories=len(categories),
|
total_categories=len(categories),
|
||||||
|
repo_stars=repo_stars,
|
||||||
build_date=datetime.now(timezone.utc).strftime("%B %d, %Y"),
|
build_date=datetime.now(timezone.utc).strftime("%B %d, %Y"),
|
||||||
),
|
),
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ def main() -> None:
|
|||||||
|
|
||||||
readme_text = README_PATH.read_text(encoding="utf-8")
|
readme_text = README_PATH.read_text(encoding="utf-8")
|
||||||
current_repos = extract_github_repos(readme_text)
|
current_repos = extract_github_repos(readme_text)
|
||||||
|
current_repos.add("vinta/awesome-python")
|
||||||
print(f"Found {len(current_repos)} GitHub repos in README.md")
|
print(f"Found {len(current_repos)} GitHub repos in README.md")
|
||||||
|
|
||||||
cache = load_stars(CACHE_FILE)
|
cache = load_stars(CACHE_FILE)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
--footer-text: oklch(72% 0.02 75);
|
--footer-text: oklch(72% 0.02 75);
|
||||||
--footer-link: oklch(82% 0.02 75);
|
--footer-link: oklch(82% 0.02 75);
|
||||||
--footer-link-hover: oklch(95% 0.01 80);
|
--footer-link-hover: oklch(95% 0.01 80);
|
||||||
--footer-muted: oklch(50% 0.02 55);
|
|
||||||
--footer-sep: oklch(55% 0.02 55);
|
--footer-sep: oklch(55% 0.02 55);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,6 +304,13 @@ kbd {
|
|||||||
margin-top: 1.75rem;
|
margin-top: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hero-proof {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
color: oklch(68% 0.02 72);
|
||||||
|
font-size: var(--text-sm);
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
.hero-action {
|
.hero-action {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -896,11 +903,6 @@ th[data-sort].sort-asc::after {
|
|||||||
color: var(--footer-link);
|
color: var(--footer-link);
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-date {
|
|
||||||
font-size: var(--text-xs);
|
|
||||||
color: var(--footer-muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-links {
|
.footer-links {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|||||||
@@ -55,7 +55,6 @@
|
|||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="footer-left">
|
<div class="footer-left">
|
||||||
<span class="footer-brand">Awesome Python</span>
|
<span class="footer-brand">Awesome Python</span>
|
||||||
{% if build_date %}<span class="footer-date">Data refreshed {{ build_date }}</span>{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -47,6 +47,14 @@
|
|||||||
>View on GitHub</a
|
>View on GitHub</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if repo_stars or build_date %}
|
||||||
|
<p class="hero-proof">
|
||||||
|
{% if repo_stars %}{{ repo_stars }}+ stars on GitHub{% endif %}
|
||||||
|
{% if repo_stars and build_date %}/{% endif %}
|
||||||
|
{% if build_date %}Updated {{ build_date }}{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -160,7 +160,13 @@ class TestMainSkipsFreshCache:
|
|||||||
"owner": "psf",
|
"owner": "psf",
|
||||||
"last_commit_at": "2025-01-01T00:00:00+00:00",
|
"last_commit_at": "2025-01-01T00:00:00+00:00",
|
||||||
"fetched_at": (now - timedelta(hours=1)).isoformat(),
|
"fetched_at": (now - timedelta(hours=1)).isoformat(),
|
||||||
}
|
},
|
||||||
|
"vinta/awesome-python": {
|
||||||
|
"stars": 230000,
|
||||||
|
"owner": "vinta",
|
||||||
|
"last_commit_at": "2025-01-01T00:00:00+00:00",
|
||||||
|
"fetched_at": (now - timedelta(hours=1)).isoformat(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
cache_file.write_text(json.dumps(fresh_cache), encoding="utf-8")
|
cache_file.write_text(json.dumps(fresh_cache), encoding="utf-8")
|
||||||
monkeypatch.setattr("fetch_github_stars.CACHE_FILE", cache_file)
|
monkeypatch.setattr("fetch_github_stars.CACHE_FILE", cache_file)
|
||||||
@@ -195,7 +201,13 @@ class TestMainSkipsFreshCache:
|
|||||||
"owner": "psf",
|
"owner": "psf",
|
||||||
"last_commit_at": "2025-01-01T00:00:00+00:00",
|
"last_commit_at": "2025-01-01T00:00:00+00:00",
|
||||||
"fetched_at": (now - timedelta(hours=24)).isoformat(),
|
"fetched_at": (now - timedelta(hours=24)).isoformat(),
|
||||||
}
|
},
|
||||||
|
"vinta/awesome-python": {
|
||||||
|
"stars": 230000,
|
||||||
|
"owner": "vinta",
|
||||||
|
"last_commit_at": "2025-01-01T00:00:00+00:00",
|
||||||
|
"fetched_at": (now - timedelta(hours=24)).isoformat(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
cache_file.write_text(json.dumps(stale_cache), encoding="utf-8")
|
cache_file.write_text(json.dumps(stale_cache), encoding="utf-8")
|
||||||
monkeypatch.setattr("fetch_github_stars.CACHE_FILE", cache_file)
|
monkeypatch.setattr("fetch_github_stars.CACHE_FILE", cache_file)
|
||||||
@@ -210,7 +222,12 @@ class TestMainSkipsFreshCache:
|
|||||||
"stargazerCount": 53000,
|
"stargazerCount": 53000,
|
||||||
"owner": {"login": "psf"},
|
"owner": {"login": "psf"},
|
||||||
"defaultBranchRef": {"target": {"committedDate": "2025-06-01T00:00:00Z"}},
|
"defaultBranchRef": {"target": {"committedDate": "2025-06-01T00:00:00Z"}},
|
||||||
}
|
},
|
||||||
|
"repo_1": {
|
||||||
|
"stargazerCount": 231000,
|
||||||
|
"owner": {"login": "vinta"},
|
||||||
|
"defaultBranchRef": {"target": {"committedDate": "2025-06-01T00:00:00Z"}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mock_response.raise_for_status = MagicMock()
|
mock_response.raise_for_status = MagicMock()
|
||||||
@@ -223,6 +240,6 @@ class TestMainSkipsFreshCache:
|
|||||||
main()
|
main()
|
||||||
|
|
||||||
output = capsys.readouterr().out
|
output = capsys.readouterr().out
|
||||||
assert "1 repos to fetch" in output
|
assert "2 repos to fetch" in output
|
||||||
assert "Done. Fetched 1 repos" in output
|
assert "Done. Fetched 2 repos" in output
|
||||||
mock_client.post.assert_called_once()
|
mock_client.post.assert_called_once()
|
||||||
|
|||||||
Reference in New Issue
Block a user