update
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
build_locations.py — Location page generator for floorithardwoodfloors.com
|
||||
Reads data/locations.json + locations/_template.html
|
||||
Outputs flat .html files: locations/{slug}.html
|
||||
|
||||
Usage:
|
||||
python3 build_locations.py
|
||||
python3 build_locations.py --slug buffalo # rebuild one city only
|
||||
python3 build_locations.py --list # list all cities in database
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
SITE_ROOT = Path(__file__).parent
|
||||
DATA_FILE = SITE_ROOT / "data" / "locations.json"
|
||||
TEMPLATE_FILE = SITE_ROOT / "locations" / "_template.html"
|
||||
OUTPUT_DIR = SITE_ROOT / "locations"
|
||||
|
||||
|
||||
def build_faq_html(faqs: list) -> str:
|
||||
"""Render FAQ list to HTML accordion items."""
|
||||
items = []
|
||||
for faq in faqs:
|
||||
items.append(f""" <div class="faq-item">
|
||||
<div class="faq-question">
|
||||
<h4>{faq['q']}</h4>
|
||||
<div class="faq-icon" aria-hidden="true"></div>
|
||||
</div>
|
||||
<div class="faq-answer">
|
||||
<div class="faq-answer-inner">{faq['a']}</div>
|
||||
</div>
|
||||
</div>""")
|
||||
return "\n".join(items)
|
||||
|
||||
|
||||
def render_page(location: dict, template: str) -> str:
|
||||
"""Stamp all {{variable}} placeholders in template with location data."""
|
||||
html = template
|
||||
|
||||
# Render complex fields first
|
||||
html = html.replace("{{faq_items}}", build_faq_html(location.get("faqs", [])))
|
||||
|
||||
# Stamp all scalar fields
|
||||
for key, value in location.items():
|
||||
if isinstance(value, str):
|
||||
html = html.replace(f"{{{{{key}}}}}", value)
|
||||
|
||||
return html
|
||||
|
||||
|
||||
def build_one(location: dict, template: str, verbose: bool = True) -> Path:
|
||||
"""Generate one location page. Returns output path."""
|
||||
slug = location["slug"]
|
||||
city = location.get("city", slug)
|
||||
output_path = OUTPUT_DIR / f"{slug}.html"
|
||||
|
||||
html = render_page(location, template)
|
||||
output_path.write_text(html, encoding="utf-8")
|
||||
|
||||
if verbose:
|
||||
print(f" Built: locations/{slug}.html ({city}, {location.get('state','NY')})")
|
||||
|
||||
return output_path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Build flat location HTML pages from JSON database.")
|
||||
parser.add_argument("--slug", help="Build a single city by slug (e.g. buffalo)")
|
||||
parser.add_argument("--list", action="store_true", help="List all cities in database")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validate paths
|
||||
if not DATA_FILE.exists():
|
||||
print(f"ERROR: data file not found: {DATA_FILE}")
|
||||
sys.exit(1)
|
||||
if not TEMPLATE_FILE.exists():
|
||||
print(f"ERROR: template not found: {TEMPLATE_FILE}")
|
||||
sys.exit(1)
|
||||
|
||||
locations = json.loads(DATA_FILE.read_text(encoding="utf-8"))
|
||||
template = TEMPLATE_FILE.read_text(encoding="utf-8")
|
||||
|
||||
if args.list:
|
||||
print(f"\nLocations in database ({len(locations)} total):")
|
||||
for loc in locations:
|
||||
print(f" {loc['slug']:20s} {loc.get('city','')}, {loc.get('state','NY')}")
|
||||
return
|
||||
|
||||
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if args.slug:
|
||||
matches = [l for l in locations if l["slug"] == args.slug]
|
||||
if not matches:
|
||||
print(f"ERROR: slug '{args.slug}' not found in database.")
|
||||
sys.exit(1)
|
||||
print(f"\nBuilding single location: {args.slug}")
|
||||
build_one(matches[0], template)
|
||||
else:
|
||||
print(f"\nBuilding {len(locations)} location pages...")
|
||||
built = []
|
||||
for loc in locations:
|
||||
path = build_one(loc, template)
|
||||
built.append(path)
|
||||
print(f"\nDone. {len(built)} pages written to locations/")
|
||||
|
||||
print(f"Completed at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user