This commit is contained in:
2025-05-04 14:16:29 +02:00
parent 92d272b36e
commit eb2d05f082
11 changed files with 202 additions and 38 deletions

View File

@@ -74,7 +74,7 @@ func main() {
http.NotFound(w, r)
return
}
if err := tplList.ExecuteTemplate(w, "base", articles); err != nil {
if err := tplList.ExecuteTemplate(w, "layout", articles); err != nil {
http.Error(w, err.Error(), 500)
}
})
@@ -83,7 +83,7 @@ func main() {
slug := strings.TrimPrefix(r.URL.Path, "/post/")
for _, a := range articles {
if a.Slug == slug {
if err := tplArticle.ExecuteTemplate(w, "base", a); err != nil {
if err := tplArticle.ExecuteTemplate(w, "layout", a); err != nil {
http.Error(w, err.Error(), 500)
}
return

3
content/2025/demo.md Normal file
View File

@@ -0,0 +1,3 @@
<!--{"title": "ChatGPT + Go: So geht's", "date": "2025-05-04", "slug": "chatgpt-go", "cover": ""}-->
# Hello Gophers 🤖
*(MarkdownInhalt)*

View File

@@ -1,4 +1,4 @@
<!-- { "title": "Mein erster MarkdownPost", "date": "20250504", "slug": "mein-erster-markdown-post" } -->
<!--{"title": "Mein erster MarkdownPost", "date": "2025-05-04", "slug": "mein-erster-markdown-post", "cover": "/static/img/placeholder.png"}-->
# Hello Markdown 🌟

View File

@@ -26,7 +26,6 @@ func LoadDir(root string) ([]Article, error) {
// gültige ExtensionMaske
exts := parser.CommonExtensions | parser.AutoHeadingIDs | parser.DefinitionLists
mdParser := parser.NewWithExtensions(exts)
mdRenderer := html.NewRenderer(html.RendererOptions{
Flags: html.CommonFlags | html.HrefTargetBlank,
})
@@ -57,6 +56,7 @@ func LoadDir(root string) ([]Article, error) {
Title string `json:"title"`
Date string `json:"date"`
Slug string `json:"slug"`
Cover string `json:"cover"` // NEW
}
clean := strings.TrimSpace(string(headerLine))
@@ -80,14 +80,19 @@ func LoadDir(root string) ([]Article, error) {
htmlBody := bodyBytes
if ext == ".md" {
mdParser := parser.NewWithExtensions(exts)
htmlBody = md.ToHTML(bodyBytes, mdParser, mdRenderer)
}
date, _ := time.Parse("2006-01-02", meta.Date)
date, err := time.Parse("2006-01-02", meta.Date)
if err != nil {
fmt.Println("Time", err, date)
}
out = append(out, Article{
Title: meta.Title,
Slug: meta.Slug,
Date: date,
Cover: meta.Cover, // NEW
Body: template.HTML(htmlBody),
})
return nil

View File

@@ -10,5 +10,6 @@ type Article struct {
Title string
Slug string
Date time.Time
Cover string //  NEW
Body template.HTML // already trusted
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 MiB

View File

@@ -0,0 +1,133 @@
/* ---------- Farbpalette (Feelfree to tune) ---------- */
:root {
--bg: #0d1117;
--bgalt: #161b22;
--text: #c9d1d9;
--textmuted: #8b949e;
--accent: #3b82f6; /* Blau */
--accentlight:#60a5fa;
--codebg: #1e242c;
--codeborder: #30363d;
--radius: 0.6rem;
--gap: 1.5rem;
fontsize: 16px;
fontfamily: systemui, "Segoe UI", Roboto, sansserif;
colorscheme: dark;
}
/* ---------- Globale Elemente ---------- */
* { boxsizing: borderbox; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
lineheight: 1.6;
}
a {
color: var(--accent);
textdecoration: none;
}
a:hover { textdecoration: underline; }
/* ---------- Layout ---------- */
.wrapper {
maxwidth: 768px;
margin: 0 auto;
padding: var(--gap);
}
header, footer {
display: flex;
alignitems: center;
justifycontent: space-between;
background: var(--bgalt);
padding: 1rem var(--gap);
borderbottom: 1px solid var(--codeborder);
}
header h1 {
margin: 0;
fontsize: 1.4rem;
letterspacing: 0.5px;
}
header a { color: var(--text); }
footer {
bordertop: 1px solid var(--codeborder);
fontsize: 0.9rem;
color: var(--textmuted);
}
/* ---------- Artikelliste ---------- */
.postlist li {
margin: 0;
padding: 1rem 0;
borderbottom: 1px solid var(--codeborder);
}
.postlist li:lastchild { borderbottom: none; }
.postlist time { color: var(--textmuted); fontsize: 0.9rem; }
/* ---------- Einzelartikel ---------- */
article h1 { margintop: 0; fontsize: 2rem; }
article time { color: var(--textmuted); fontsize: 0.9rem; }
article img, article video {
maxwidth: 100%; height: auto; borderradius: var(--radius);
}
article pre, article code {
fontfamily: "Fira Code", Consolas, monospace;
}
article pre {
background: var(--codebg);
border: 1px solid var(--codeborder);
padding: 1rem;
borderradius: var(--radius);
overflow: auto;
}
article blockquote {
margin: 1rem 0;
padding: 0.5rem 1rem;
borderleft: 4px solid var(--accentlight);
background: var(--bgalt);
color: var(--textmuted);
}
/* ---------- KartenLayout für Artikelliste ---------- */
.card {
display: grid;
grid-template-columns: 160px 1fr;
gap: 1rem;
padding: 1rem;
border: 1px solid var(--code-border);
border-radius: var(--radius);
background: var(--bg-alt);
transition: transform .15s ease, border-color .15s ease;
}
.card:hover {
transform: translateY(-4px);
border-color: var(--accent);
}
.card img {
width: 160px;
height: 100px;
object-fit: cover;
border-radius: var(--radius);
}
.card h2 {
margin: 0 0 .4rem;
font-size: 1.2rem;
}
.card time { color: var(--text-muted); font-size: .9rem; }
/* ---------- HeroBild im Artikel ---------- */
.hero {
width: 100%;
max-height: 340px;
object-fit: cover;
border-radius: var(--radius);
margin-bottom: 1rem;
}
/* ---------- Responsive ---------- */
@media (maxwidth: 600px) {
:root { fontsize: 15px; }
header, footer { flexdirection: column; gap: 0.5rem; }
}

View File

@@ -1,20 +1,20 @@
{{ define "article" }}
{{ template "base.html" . }}
{{ end }}
{{ define "title" }}{{ .Title }}  B1tsblog{{ end }}
{{ define "title" }}{{ .Title }}  B1tsblog{{ end }}
{{ define "body" }}
<article class="article">
<header>
<h1>{{ .Title }}</h1>
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "02.01.2006" }}</time>
</header>
<article>
{{ if .Cover }}
<img class="hero" src="{{ .Cover }}" alt="">
{{ end }}
<h1>{{ .Title }}</h1>
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "02.01.2006" }}</time>
<div class="article-content">
{{ .Body }}
</div>
<p><a href="/"> Alle Artikel</a></p>
<p><a href="/">Zurück zur Übersicht</a></p>
</article>
{{ end }}
{{ define "article" }}{{ template "layout" . }}{{ end }}

View File

@@ -1,15 +1,30 @@
<!DOCTYPE html><html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>{{ block "title" . }}B1tsblog{{ end }}</title>
<link rel="stylesheet" href="/static/main.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<!-- MonospaceFont für Code (optional) -->
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
</head>
<body>
<header><h1><a href="/">B1tsblog</a></h1></header>
<main>{{ block "body" . }}{{ end }}</main>
<footer>© {{ now.Year }}</footer>
</body></html>
{{ define "layout" }}
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>{{ block "title" . }}B1tsblog{{ end }}</title>
<link rel="stylesheet" href="/static/main.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<!-- MonospaceFont für Code (optional) -->
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
</head>
<body>
<header>
<h1><a href="/">B1tsblog</a></h1>
<nav>
<!-- Platz für spätere Links -->
</nav>
</header>
<main class="wrapper">
{{ template "body" . }}
</main>
<footer class="wrapper">
© {{ now.Year }} · Powered by Go
</footer>
</body>
</html>
{{ end }}

View File

@@ -1,16 +1,23 @@
{{ define "list" }} {{/* ausführbarer EntryPoint */}}
{{ template "base.html" . }} {{/* ruft das Layout auf */}}
{{ end }}
{{ define "title" }}Alle Artikel{{ end }}
{{ define "body" }}
<ul>
<ul class="post-list" style="list-style:none; padding:0; display:grid; gap:var(--gap);">
{{ range . }}
<li>
<a href="/post/{{ .Slug }}">{{ .Title }}</a>
{{ .Date.Format "02.01.2006" }}
<a class="card" href="/post/{{ .Slug }}">
{{ if .Cover }}
<img src="{{ .Cover }}" alt="">
{{ else }}
<img src="/static/img/placeholder.png" alt="">
{{ end }}
<div>
<h2>{{ .Title }}</h2>
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "02.01.2006" }}</time>
</div>
</a>
</li>
{{ end }}
</ul>
{{ end }}
{{ define "list" }}{{ template "layout" . }}{{ end }}