learning-website-framework1-3 Exercise 1: Read the Banner
===========================================================
Write parse_banner(text), which returns a dictionary describing a page from its
opening comment (or its
, for a full HTML page). It must cope with every
banner shape that really exists on this site.
Save as banner.py:
import json, os, re, sys
KEY = re.compile(r"^([A-Za-z][A-Za-z ]*?):\s*(.*)$")
DATES = re.compile(r"Date Created:\s*(\d{4}-\d{2}-\d{2})\s+Date Updated:\s*(\d{4}-\d{2}-\d{2})")
def parse_banner(text):
"""Return a dict describing the page, from its banner comment or ."""
if text.lstrip().lower().startswith("(.*?)", text, re.S)
return {"kind": "full-page", "title": m.group(1).strip() if m else None}
m = re.match(r"\s*", text, re.S)
if not m:
return {"kind": "no-banner"}
block = m.group(1)
info = {}
d = DATES.search(block)
if d:
info["created"], info["updated"] = d.group(1), d.group(2)
lines = [ln.strip().strip("=").strip() for ln in block.splitlines()]
lines = [ln for ln in lines if ln]
for ln in lines:
km = KEY.match(ln)
if not km:
continue
key, value = km.group(1).strip(), km.group(2).strip()
if key in ("Date Created", "Date Updated"):
continue
info.setdefault(key.lower(), value)
if "course" in info:
info["kind"] = "course-chapter"
elif "category" in info:
info["kind"] = "sidebar"
else:
# free-form banner such as "PYTHON LESSON: Boolean Logic ..."
headline = lines[0] if lines else ""
info["kind"] = "free-banner"
info["headline"] = headline
return info
if __name__ == "__main__":
root = sys.argv[1]
for rel in sys.argv[2:]:
with open(os.path.join(root, rel), encoding="utf-8") as fh:
head = fh.read(4000)
info = parse_banner(head)
info = {k: (v[:70] + "...") if isinstance(v, str) and len(v) > 70 else v
for k, v in info.items()}
print(rel)
print(" " + json.dumps(info, ensure_ascii=False))
Run it (the first argument is your content/ folder):
python banner.py "/claude-projects/website-content/content" hungary/hungarian-basic-3/hungarian_basic_conversation_3_1.html sidebar/programming/cheat_sheet_git_command_line.html ...
Output (checked by running it on real files):
hungary/hungarian-basic-3/hungarian_basic_conversation_3_1.html
{"created": "2026-10-05", "updated": "2026-10-05", "course": "Hungarian Basic Conversation 3", "chapter": "Buying Clothes: Sizes, Fit & Returns", "file": "hungarian_basic_conversation_3_1.html", "topic": "Buying clothes: clothes and colour words, sizes and fit, Felpróbálhato...", "level": "Elementary | Hungarian + English respelling", "kind": "course-chapter"}
sidebar/programming/cheat_sheet_git_command_line.html
{"created": "2026-10-06", "updated": "2026-10-06", "category": "Sidebar", "subcategory": "Programming", "chapter": "Git Command Line Cheat Sheet", "file": "cheat_sheet_git_command_line.html", "kind": "sidebar"}
web-servers/apache-in-depth/apache_in_depth_1_1.html
{"course": "Apache In Depth", "chapter": "Scope: What This Course Builds On, and Why It's Apache-Only", "file": "apache_in_depth_1_1.html", "topic": "Recapping exactly what Web Servers Fundamentals left deliberately shal...", "kind": "course-chapter"}
programming/general-purpose-languages/python/python-lessons/python_lesson_boolean_logic_truthy_falsy.html
{"created": "2026-08-16", "updated": "2026-08-16", "python lesson": "Boolean Logic — What Python Actually Considers True or False", "level": "Beginner Python / Experienced Programmer", "kind": "free-banner", "headline": "PYTHON LESSON: Boolean Logic — What Python Actually Considers True or ..."}
hungary/hungarian-lessons/hungarian_alphabet.html
{"level": "All levels (pronunciation guide & letter reference)", "focus": "All 44 Hungarian letters (14 vowels + 30 consonants/digraphs)", "kind": "free-banner", "headline": "HUNGARIAN ALPHABET REFERENCE"}
japan/japanese-language/reference-materials/kanji/kanji_上.html
{"kind": "full-page", "title": "上 | Kanji | osztromok.com"}
The shapes found
----------------
1. course-chapter: Course / Chapter / File / Topic (+ dates when present;
older courses such as Apache In Depth have none)
2. sidebar: Category / Subcategory / Chapter / File (+ dates)
3. free-banner: a headline such as "PYTHON LESSON: ..." with Level and dates
4. free-banner without a title: the Hungarian alphabet reference
5. full-page: a complete HTML page with no banner (the kanji pages), where the
title comes from
WHY THIS WORKS AS AN ANSWER
---------------------------
The site's files are the database. A parser that reads the banner gives the
build the same information a CMS would store in columns: the course, the
chapter title, the dates. Handling every shape up front (instead of assuming the
newest one) is what lets old and new content share one site. Returning a
"kind" lets later code decide how to treat each page, and returning only what is
actually present (note the Apache chapter has no dates) means missing data
shows up as missing rather than being invented.