summaryrefslogtreecommitdiffstats
path: root/_shared/build.py
diff options
context:
space:
mode:
authorAhmed <git@gumx.cc>2026-06-14 16:30:47 +0300
committerAhmed <git@gumx.cc>2026-06-14 16:30:47 +0300
commit307ff4912bac1095ebf382d70241f19409b2f8b8 (patch)
treea2c3d36634fa86705e48db4fc797437ba816e5e0 /_shared/build.py
parentfa568e13d04c0aacdb29ca252b783f1dcdb6bf23 (diff)
add: templating
Diffstat (limited to '_shared/build.py')
-rw-r--r--_shared/build.py94
1 files changed, 94 insertions, 0 deletions
diff --git a/_shared/build.py b/_shared/build.py
new file mode 100644
index 0000000..935bf5c
--- /dev/null
+++ b/_shared/build.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python3
+"""Build sites from body.html + meta into index.html using shared templates."""
+import json
+import os
+import sys
+
+FAVICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1IDUiPjxyZWN0IHg9IjEiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiLz48cmVjdCB4PSIyIiB5PSIxIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIi8+PHJlY3QgeD0iMCIgeT0iMiIgd2lkdGg9IjEiIGhlaWdodD0iMSIvPjxyZWN0IHg9IjEiIHk9IjIiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiLz48cmVjdCB4PSIyIiB5PSIyIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIi8+PC9zdmc+"
+
+
+def render(title, breadcrumb, style, extra_css, body, footer):
+ css = style + ("\n" + extra_css if extra_css.strip() else "")
+ return f"""<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<link rel="icon" type="image/svg+xml" href="{FAVICON}">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>{title}</title>
+<style>
+{css}
+</style>
+</head>
+<body>
+<header>
+<h1><a href="https://gumx.cc">gumx</a> / {breadcrumb}</h1>
+</header>
+<main>
+{body}
+</main>
+{footer}
+</body>
+</html>
+"""
+
+
+def build_demo_body(demos_file):
+ demos = json.load(open(demos_file))
+ parts = []
+ for d in demos:
+ url = d.get("url", "#")
+ title = d.get("title", d.get("name", ""))
+ desc = d.get("description", "")
+ src = d.get("source", "")
+ src_link = f' / <a href="{src}">source</a>' if src else ""
+ parts.append(f'<p><a href="{url}">{title}</a>{src_link}</p>\n<p>{desc}</p>')
+ return "\n".join(parts)
+
+
+def build(sites_dir):
+ shared = os.path.join(sites_dir, "_shared")
+ style = open(os.path.join(shared, "style.css")).read()
+ footer = open(os.path.join(shared, "footer.html")).read()
+
+ for site in sorted(os.listdir(sites_dir)):
+ if site.startswith("_") or site == "fonts" or site == "hooks":
+ continue
+ site_dir = os.path.join(sites_dir, site)
+ if not os.path.isdir(site_dir):
+ continue
+
+ body_file = os.path.join(site_dir, "body.html")
+ demos_file = os.path.join(site_dir, "demos.json")
+
+ if site == "demo.gumx.cc" and os.path.exists(demos_file):
+ body = build_demo_body(demos_file)
+ elif os.path.exists(body_file):
+ body = open(body_file).read()
+ else:
+ continue
+
+ title = site
+ breadcrumb = site
+ meta_file = os.path.join(site_dir, "meta")
+ if os.path.exists(meta_file):
+ for line in open(meta_file):
+ k, _, v = line.strip().partition("=")
+ if k == "TITLE":
+ title = v.strip('"')
+ elif k == "BREADCRUMB":
+ breadcrumb = v.strip('"')
+
+ extra_css = ""
+ extra_file = os.path.join(site_dir, "extra.css")
+ if os.path.exists(extra_file):
+ extra_css = open(extra_file).read()
+
+ out = render(title, breadcrumb, style, extra_css, body, footer)
+ with open(os.path.join(site_dir, "index.html"), "w") as f:
+ f.write(out)
+ print(f"built: {site}")
+
+
+if __name__ == "__main__":
+ build(sys.argv[1] if len(sys.argv) > 1 else ".")