"""Keep one gallery highlight link per name and capture year.""" from datetime import datetime, timezone import json from pathlib import Path import re def field(content, name): match = re.search(rf"^{re.escape(name)}: (.+)$", content.split("---", 2)[1], re.MULTILINE) if not match: return None value = match.group(1).strip() return json.loads(value) if value.startswith('"') else value def normalize_highlights(art): """Place each link on the newest photo in its named, dated group.""" groups = {} for path in Path(art).glob("*.md"): content = path.read_text() name = field(content, "highlight_name") or field(content, "anchor") date = field(content, "date") if not name or not date: continue taken = datetime.fromisoformat(str(date)) if taken.tzinfo is None: taken = taken.replace(tzinfo=timezone.utc) groups.setdefault((name, taken.year), []).append((taken, path, content)) changed = [] for (name, _), entries in groups.items(): # An old single anchor is already the only link; a newer named photo # moves the link without changing any photo's capture date or position. newest = max(entries, key=lambda entry: (entry[0], entry[1].name))[1] if len(entries) == 1 and field(entries[0][2], "anchor") == name: continue for _, path, content in entries: old = content had_anchor = field(content, "anchor") is not None if (path == newest and had_anchor and all(field(other[2], "anchor") is None for other in entries if other[1] != path)): continue if had_anchor: content = re.sub(r"^anchor: .+\n", "", content, count=1, flags=re.MULTILINE) if path == newest: content = content.replace("categories: art\n", "categories: art\n" + f"anchor: {json.dumps(name, ensure_ascii=False)}\n", 1) elif had_anchor: title = field(content, "title") if title and title.startswith("photo-") and f'id="{title}"' not in content: content = content.replace("---\n\n", f'---\n\n
\n\n', 1) if content != old: path.write_text(content) changed.append(path) return changed