This repository has no description
1"""Pure formatting helpers: slugs, @handles, absolute URLs, RFC-3339 times.
2
3Per the contract: `owner` carries a leading `@`, repo URLs are absolute, and
4timestamps are machine-readable (the frontend humanizes them).
5"""
6
7from __future__ import annotations
8
9import re
10from datetime import datetime
11
12_SLUG_RE = re.compile(r"[^a-z0-9]+")
13
14
15def slugify(text: str) -> str:
16 return _SLUG_RE.sub("-", (text or "").strip().lower()).strip("-")
17
18
19def at_owner(handle: str) -> str:
20 handle = (handle or "").lstrip("@")
21 return f"@{handle}"
22
23
24def repo_url(web_base: str, handle: str, name: str) -> str:
25 return f"{web_base.rstrip('/')}/{at_owner(handle)}/{name}"
26
27
28def issue_list_url(web_base: str, handle: str, name: str) -> str:
29 return f"{repo_url(web_base, handle, name)}/issues"
30
31
32def to_rfc3339(value) -> str:
33 """datetime -> ISO-8601 string; pass through strings (already ISO from the
34 DB's record_raw); empty for None."""
35 if value is None:
36 return ""
37 if isinstance(value, datetime):
38 return value.isoformat()
39 return str(value)