Initial version of build.py
This commit is contained in:
parent
5a1477fe19
commit
c61c050dc2
|
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Static site generator for evo-edu framework.
|
||||
|
||||
Two modes:
|
||||
1. --init : Prompt user for site config and save to site.json
|
||||
2. --config <file> --output <dir> : Render templates using config
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
|
||||
# Template directory (relative to this script)
|
||||
TEMPLATE_DIR = Path(__file__).parent / "templates"
|
||||
|
||||
def prompt_for_config():
|
||||
"""Prompt user for site configuration."""
|
||||
print("=== evo-edu Framework Site Config ===")
|
||||
config = {
|
||||
"lang": input("Language code (e.g., 'en'): ") or "en",
|
||||
"title": input("Page title (e.g., 'Notebook On Evolution'): ") or "Notebook On Evolution",
|
||||
"site_title": input("Site name (e.g., 'evo-edu.org'): ") or "evo-edu.org",
|
||||
"license": input("License text (e.g., 'CC BY-SA 4.0'): ") or "CC BY-SA 4.0",
|
||||
"github_url": input("GitHub URL: ") or "https://github.com/evo-edu",
|
||||
"contact_email": input("Contact email: ") or "admin@evo-edu.org",
|
||||
"languages": []
|
||||
}
|
||||
|
||||
# Language options
|
||||
print("\nLanguage switcher options (e.g., en:English, es:Español):")
|
||||
lang_input = input("Enter as 'code:name' pairs (comma-separated): ") or "en:English"
|
||||
for pair in lang_input.split(','):
|
||||
code, name = pair.strip().split(':', 1)
|
||||
config["languages"].append({"code": code, "name": name})
|
||||
lang_options = "\n".join([
|
||||
f'<option value="{lang["code"]}" {"selected" if lang["code"] == config["lang"] else ""}>{lang["name"]}</option>'
|
||||
for lang in config["languages"]
|
||||
])
|
||||
result = result.replace("{{language_options}}", lang_options)
|
||||
# Save
|
||||
out_file = input("\nSave config as (default: site.json): ") or "site.json"
|
||||
with open(out_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
print(f"✅ Config saved to {out_file}")
|
||||
|
||||
def render_template(template_text, config):
|
||||
"""Replace {{key}} and {{#each}} blocks with config values."""
|
||||
result = template_text
|
||||
|
||||
# Simple key replacements
|
||||
for key, value in config.items():
|
||||
if key != "languages":
|
||||
result = result.replace("{{" + key + "}}", str(value))
|
||||
|
||||
# Handle {{#each languages}}...{{/each}}
|
||||
if "{{#each languages}}" in result:
|
||||
lang_block_start = result.find("{{#each languages}}")
|
||||
lang_block_end = result.find("{{/each}}", lang_block_start)
|
||||
if lang_block_end != -1:
|
||||
block = result[lang_block_start + len("{{#each languages}}"):lang_block_end]
|
||||
rendered_langs = []
|
||||
for lang in config.get("languages", []):
|
||||
lang_item = block
|
||||
lang_item = lang_item.replace("{{code}}", lang["code"])
|
||||
lang_item = lang_item.replace("{{name}}", lang["name"])
|
||||
# Handle {{#if (eq code ../lang)}}
|
||||
if f'{{{{lang}}}}' in result:
|
||||
selected = 'selected' if lang["code"] == config.get("lang", "") else ''
|
||||
lang_item = lang_item.replace("{{selected_attr}}", f'selected="{selected}"' if selected else '')
|
||||
else:
|
||||
lang_item = lang_item.replace("{{selected_attr}}", "")
|
||||
rendered_langs.append(lang_item)
|
||||
result = result[:lang_block_start] + "".join(rendered_langs) + result[lang_block_end + len("{{/each}}"):]
|
||||
|
||||
return result
|
||||
|
||||
def build_site(config_file, output_dir):
|
||||
"""Render all templates using config."""
|
||||
with open(config_file, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
|
||||
out_path = Path(output_dir)
|
||||
out_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Copy theme assets
|
||||
theme_src = Path(__file__).parent / "theme"
|
||||
for asset in ["style.css", "main.js"]:
|
||||
shutil.copy(theme_src / asset, out_path / asset)
|
||||
|
||||
# Render base.html → index.html (example)
|
||||
with open(theme_src / "base.html", 'r', encoding='utf-8') as f:
|
||||
template = f.read()
|
||||
|
||||
rendered = render_template(template, config)
|
||||
with open(out_path / "index.html", 'w', encoding='utf-8') as f:
|
||||
f.write(rendered)
|
||||
|
||||
print(f"✅ Site built in {output_dir}")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--init", action="store_true", help="Create site config interactively")
|
||||
parser.add_argument("--config", help="Path to site.json")
|
||||
parser.add_argument("--output", help="Output directory for built site")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.init:
|
||||
prompt_for_config()
|
||||
elif args.config and args.output:
|
||||
build_site(args.config, args.output)
|
||||
else:
|
||||
print("Usage:")
|
||||
print(" python build.py --init")
|
||||
print(" python build.py --config site.json --output ../content/en/")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue