-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate_site.py
More file actions
132 lines (103 loc) · 3.83 KB
/
generate_site.py
File metadata and controls
132 lines (103 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python3
"""
Static site generator for podcast episodes.
Reads episode metadata from local JSON files and generates a Hebrew RTL website.
"""
import json
import re
import shutil
from datetime import datetime
from html import escape
from pathlib import Path
AUDIO_BASE_URL = "https://rgw.rke2.hasadna.org.il/podcasts/"
METADATA_DIR = Path("metadata")
OUTPUT_DIR = Path("site")
TEMPLATES_DIR = Path("templates")
def parse_date(date_str: str) -> datetime:
"""Parse RFC 2822 date format."""
# Example: "Fri, 29 Jun 2018 08:01:05 +0000"
try:
# Remove timezone for parsing
date_str_clean = re.sub(r"\s*[+-]\d{4}$", "", date_str)
return datetime.strptime(date_str_clean, "%a, %d %b %Y %H:%M:%S")
except ValueError:
return datetime.now()
def format_date_hebrew(dt: datetime) -> str:
"""Format date in Hebrew style."""
months = [
"ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני",
"יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"
]
return f"{dt.day} {months[dt.month - 1]} {dt.year}"
def load_template(name: str) -> str:
"""Load a template file."""
return (TEMPLATES_DIR / name).read_text(encoding="utf-8")
def render_template(template: str, **kwargs) -> str:
"""Simple template rendering with {{variable}} placeholders."""
result = template
for key, value in kwargs.items():
result = result.replace(f"{{{{{key}}}}}", str(value))
return result
def load_episodes() -> list[dict]:
"""Load episode metadata from local JSON files."""
episodes = []
json_files = list(METADATA_DIR.glob("*.json"))
print(f"Found {len(json_files)} episodes")
for json_file in json_files:
print(f" Loading: {json_file.name}")
try:
metadata = json.loads(json_file.read_text(encoding="utf-8"))
dt = parse_date(metadata.get("pubDate", ""))
episodes.append({
"guid": metadata.get("guid", json_file.stem),
"title": metadata.get("title", "Untitled"),
"description": metadata.get("description", ""),
"date": dt,
"date_formatted": format_date_hebrew(dt),
})
except Exception as e:
print(f" Error: {e}")
return episodes
def generate_html(episodes: list[dict]) -> str:
"""Generate the HTML page."""
# Sort episodes by date (newest first)
episodes.sort(key=lambda e: e["date"], reverse=True)
# Load templates
index_template = load_template("index.html")
episode_template = load_template("episode.html")
# Render episodes
episodes_html = ""
for ep in episodes:
mp3_url = AUDIO_BASE_URL + ep["guid"] + ".mp3"
description = ep.get("description", "")
# Clean HTML tags from description for preview
description_text = re.sub(r"<[^>]+>", "", description)
episodes_html += render_template(
episode_template,
guid=ep["guid"],
title=escape(ep["title"]),
date=ep["date_formatted"],
description=escape(description_text),
audio_url=escape(mp3_url),
)
# Render main page
return render_template(
index_template,
episode_count=len(episodes),
episodes=episodes_html,
)
def main():
print("Loading episodes...")
episodes = load_episodes()
print("Generating HTML...")
html = generate_html(episodes)
# Create output directory
OUTPUT_DIR.mkdir(exist_ok=True)
# Write HTML file
output_file = OUTPUT_DIR / "index.html"
output_file.write_text(html, encoding="utf-8")
# Copy CSS file
shutil.copy(TEMPLATES_DIR / "style.css", OUTPUT_DIR / "style.css")
print(f"Done! Files saved to: {OUTPUT_DIR}/")
if __name__ == "__main__":
main()