|
| 1 | +"""Tag index page generation.""" |
| 2 | + |
| 3 | +from pathlib import Path |
| 4 | + |
| 5 | +from jinja2 import Environment |
| 6 | + |
| 7 | +from rockgarden.content.models import Page |
| 8 | +from rockgarden.urls import get_tag_url, get_tags_root_url, get_url, normalize_tag |
| 9 | + |
| 10 | + |
| 11 | +def collect_tags(pages: list[Page]) -> dict[str, list[Page]]: |
| 12 | + """Return a mapping of normalized tag slug → list of pages with that tag. |
| 13 | +
|
| 14 | + Pages are included in the order they appear in the input list. Tags with |
| 15 | + no pages are not included. Result is sorted alphabetically by tag slug. |
| 16 | + """ |
| 17 | + tags: dict[str, list[Page]] = {} |
| 18 | + for page in pages: |
| 19 | + raw_tags = page.frontmatter.get("tags", []) |
| 20 | + if isinstance(raw_tags, str): |
| 21 | + raw_tags = [raw_tags] |
| 22 | + for tag in raw_tags: |
| 23 | + slug = normalize_tag(tag) |
| 24 | + if slug: |
| 25 | + tags.setdefault(slug, []).append(page) |
| 26 | + return dict(sorted(tags.items())) |
| 27 | + |
| 28 | + |
| 29 | +def build_tag_pages( |
| 30 | + tags: dict[str, list[Page]], |
| 31 | + env: Environment, |
| 32 | + site_config: dict, |
| 33 | + output: Path, |
| 34 | + clean_urls: bool = True, |
| 35 | +) -> None: |
| 36 | + """Generate /tags/<slug>/ and /tags/ pages in the output directory.""" |
| 37 | + tag_index_template = env.get_template("tag_index.html") |
| 38 | + tags_root_template = env.get_template("tags_root.html") |
| 39 | + |
| 40 | + for tag_slug, tagged_pages in tags.items(): |
| 41 | + page_entries = [ |
| 42 | + {"title": p.title, "url": get_url(p.slug, clean_urls)} |
| 43 | + for p in tagged_pages |
| 44 | + ] |
| 45 | + html = tag_index_template.render( |
| 46 | + tag=tag_slug, |
| 47 | + pages=page_entries, |
| 48 | + site=site_config, |
| 49 | + ) |
| 50 | + if clean_urls: |
| 51 | + out_file = output / "tags" / tag_slug / "index.html" |
| 52 | + else: |
| 53 | + out_file = output / "tags" / f"{tag_slug}.html" |
| 54 | + out_file.parent.mkdir(parents=True, exist_ok=True) |
| 55 | + out_file.write_text(html) |
| 56 | + |
| 57 | + tag_counts = {slug: len(pages) for slug, pages in tags.items()} |
| 58 | + html = tags_root_template.render( |
| 59 | + tags=tag_counts, |
| 60 | + site=site_config, |
| 61 | + ) |
| 62 | + out_file = output / "tags" / "index.html" |
| 63 | + out_file.parent.mkdir(parents=True, exist_ok=True) |
| 64 | + out_file.write_text(html) |
0 commit comments