diff --git a/.DS_Store b/.DS_Store
index f912345..336b29d 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/cms.py b/cms.py
index 61612d3..3edc84d 100755
--- a/cms.py
+++ b/cms.py
@@ -31,7 +31,8 @@ for d in (MD_DIR, TPL_DIR, CSS_DIR, OUT_DIR):
SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9_-]*$", re.IGNORECASE)
START_PAGE = "startseite"
-FOOTER_PAGE = "footer" # Baustein: wird in jede Seite eingefuegt, nicht eigenstaendig exportiert
+HEADER_PAGE = "header" # Baustein: wird ueber den Inhalt jeder Seite gesetzt
+FOOTER_PAGE = "footer" # Baustein: wird unter den Inhalt jeder Seite gesetzt
# ---------------------------------------------------------------- markdown
@@ -174,7 +175,7 @@ def md_path(slug):
def list_pages():
pages = []
for f in sorted(os.listdir(MD_DIR)):
- if f.endswith(".md") and f[:-3] != FOOTER_PAGE:
+ if f.endswith(".md") and f[:-3] not in (HEADER_PAGE, FOOTER_PAGE):
pages.append(f[:-3])
return pages
@@ -197,12 +198,26 @@ def delete_page(slug):
# ------------------------------------------------------------------ export
-def render_page(raw, template, footer_html=""):
+def block_html(slug):
+ """Rendert einen Baustein (header/footer) als HTML, leer wenn nicht vorhanden."""
+ if os.path.exists(md_path(slug)):
+ _, body = parse_md(load_page(slug))
+ return md_to_html(body)
+ return ""
+
+
+def render_page(raw, template, header_html="", footer_html=""):
meta, body = parse_md(raw)
html = md_to_html(body)
page = (template
.replace("{{titel}}", _escape(meta.get("titel", "")))
.replace("{{inhalt}}", html))
+ if "{{header}}" in template:
+ page = page.replace("{{header}}", header_html)
+ elif header_html and "
" in page:
+ # Template ohne {{header}}-Platzhalter: Baustein automatisch setzen
+ idx = page.index("") + len("")
+ page = page[:idx] + "\n\n" + page[idx:]
if "{{footer}}" in template:
page = page.replace("{{footer}}", footer_html)
elif footer_html and "" in page:
@@ -232,14 +247,12 @@ def export_site():
if f.endswith(".css"):
shutil.copy2(os.path.join(CSS_DIR, f), os.path.join(OUT_DIR, "css", f))
- footer_html = ""
- if os.path.exists(md_path(FOOTER_PAGE)):
- _, fbody = parse_md(load_page(FOOTER_PAGE))
- footer_html = md_to_html(fbody)
+ footer_html = block_html(FOOTER_PAGE)
+ header_html = block_html(HEADER_PAGE)
exported = []
for slug in list_pages():
- page, _ = render_page(load_page(slug), template, footer_html)
+ page, _ = render_page(load_page(slug), template, header_html, footer_html)
# startseite.md wird zur index.html
out_name = "index.html" if slug == START_PAGE else slug + ".html"
with open(os.path.join(OUT_DIR, out_name), "w", encoding="utf-8") as fh:
@@ -276,10 +289,11 @@ class Handler(BaseHTTPRequestHandler):
self._send(200, ADMIN_HTML, "text/html; charset=utf-8")
elif path == "/api/pages":
self._json({"pages": list_pages(), "start": START_PAGE,
+ "header": os.path.exists(md_path(HEADER_PAGE)),
"footer": os.path.exists(md_path(FOOTER_PAGE))})
elif path.startswith("/api/page/"):
slug = unquote(path[len("/api/page/"):])
- if slug == FOOTER_PAGE or slug in list_pages():
+ if slug in (HEADER_PAGE, FOOTER_PAGE) or slug in list_pages():
self._json({"slug": slug, "raw": load_page(slug)})
else:
self._json({"error": "Seite nicht gefunden"}, 404)
@@ -304,10 +318,10 @@ class Handler(BaseHTTPRequestHandler):
self._json({"ok": True, "slug": slug})
elif path == "/api/delete":
slug = data.get("slug", "")
- if slug != FOOTER_PAGE and slug not in list_pages():
+ if slug not in (HEADER_PAGE, FOOTER_PAGE) and slug not in list_pages():
return self._json({"error": "Seite nicht gefunden"}, 404)
- if slug in (START_PAGE, FOOTER_PAGE):
- return self._json({"error": "Startseite und Footer-Baustein koennen nicht geloescht werden."}, 400)
+ if slug in (START_PAGE, HEADER_PAGE, FOOTER_PAGE):
+ return self._json({"error": "Startseite und Bausteine koennen nicht geloescht werden."}, 400)
delete_page(slug)
self._json({"ok": True})
elif path == "/api/preview":
@@ -384,12 +398,14 @@ async function loadPages() {
if (p === current) a.className = "active";
$("pages").appendChild(a);
}
- if (d.footer) {
- const a = document.createElement("a");
- a.textContent = "footer (Baustein)";
- a.onclick = () => openPage("footer");
- if (current === "footer") a.className = "active";
- $("pages").appendChild(a);
+ for (const b of [["header", d.header], ["footer", d.footer]]) {
+ if (b[1]) {
+ const a = document.createElement("a");
+ a.textContent = b[0] + " (Baustein)";
+ a.onclick = () => openPage(b[0]);
+ if (current === b[0]) a.className = "active";
+ $("pages").appendChild(a);
+ }
}
}
diff --git a/images/hfglogo.png b/images/hfglogo.png
new file mode 100644
index 0000000..84161e7
Binary files /dev/null and b/images/hfglogo.png differ
diff --git a/md/header.md b/md/header.md
new file mode 100644
index 0000000..71ee792
--- /dev/null
+++ b/md/header.md
@@ -0,0 +1,9 @@
+---
+titel: Header
+---
+
+# Meine Website
+
+Dieser Header-Baustein wird automatisch ueber den Inhalt **aller** Seiten gesetzt.
+
+- [Startseite](index.html)
diff --git a/output/index.html b/output/index.html
index 8c182bd..c7efd00 100644
--- a/output/index.html
+++ b/output/index.html
@@ -8,9 +8,14 @@
+ startseite
Neue Seite. hier kommen alle inhalte hin.