diff options
| author | grm <grm@eyesin.space> | 2026-09-13 00:38:24 +0300 |
|---|---|---|
| committer | grm <grm@eyesin.space> | 2026-09-13 00:38:24 +0300 |
| commit | d11e4c9544f544b3a024c7ac705a674b4096cf50 (patch) | |
| tree | a60be98a37b764dfcb655b2738c8a991a248103b /internal/web/templates/layouts/blog.html | |
| parent | e974eb6f3feb06c8951f85c1d34161938905f807 (diff) | |
| download | blogspace-d11e4c9544f544b3a024c7ac705a674b4096cf50.tar.gz blogspace-d11e4c9544f544b3a024c7ac705a674b4096cf50.tar.bz2 blogspace-d11e4c9544f544b3a024c7ac705a674b4096cf50.zip | |
Add the Layout tab: five areas with modules, columns and a menu editor
A blog page is now header, left column, main content, right column and
footer, each holding an ordered list of modules (blog title, logo, menu,
archive by year/month, recent posts, custom HTML, footer text, RSS link,
site map). Side columns have percentage widths, can be hidden, and can
keep their space when empty; on phones they stack under the posts. The
menu becomes its own ordered list mixing pages and outside links.
Announcements are placed per column at its top or bottom.
Modules and menu items get tables; the migration derives them from each
blog's old theme (nav position, footer text, show-in-nav pages) so
existing blogs look the same. Custom HTML is deliberately stored and
served as-is (owner's decision; see AGENTS.md for why the blast radius
is the blogger's own origin).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A
Diffstat (limited to 'internal/web/templates/layouts/blog.html')
| -rw-r--r-- | internal/web/templates/layouts/blog.html | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/internal/web/templates/layouts/blog.html b/internal/web/templates/layouts/blog.html index 3447e1f..deaaa75 100644 --- a/internal/web/templates/layouts/blog.html +++ b/internal/web/templates/layouts/blog.html @@ -11,30 +11,35 @@ {{end}}<link rel="stylesheet" href="/static/blog.css"> <style>{{css .Data.css}}</style> </head> -<body class="nav-{{.Data.theme.NavPosition}}"> -{{if eq .Data.theme.NavPosition "top-bar"}}{{template "blognav" .}}{{end}} -<div class="site-header"> +{{$l := .Data.layout}} +<body class="{{if $l.HasLeft}}has-left {{end}}{{if $l.HasRight}}has-right{{end}}"> +{{if or $l.Header .Data.theme.HeaderImage}}{{if .Data.theme.HeaderOn}}<div class="site-header"> {{if .Data.theme.HeaderImage}}<div class="header-image"><a href="/"><img src="/media/{{.Data.theme.HeaderImage}}" alt=""></a></div>{{end}} - {{if .Data.theme.HeaderShowTitle}}<div class="wrap header-text"> - <h1 class="site-title"><a href="/">{{.Blog.Title}}</a></h1> - {{if .Blog.Tagline}}<p class="tagline">{{.Blog.Tagline}}</p>{{end}} - </div>{{end}} -</div> -{{if eq .Data.theme.NavPosition "below-header"}}{{template "blognav" .}}{{end}} -<div class="wrap body-wrap"> - {{if eq .Data.theme.NavPosition "left-sidebar"}}{{template "blognav" .}}{{if .Data.sidebar}}<div class="sidebar-notices">{{template "notices" .Data.sidebar}}</div>{{end}}{{end}} - <div class="content"> - {{template "notices" .Data.above}} + {{range $l.Header}}{{template "module" (dict "m" . "root" $)}}{{end}} +</div>{{end}}{{end}} +<div class="wrap body-wrap cols"> + {{$n := .Data.notices}} + <div class="col col-main"><div class="content"> + {{template "notices" (index $n "main-top")}} + {{range $l.Above}}{{template "module" (dict "m" . "root" $)}}{{end}} {{template "content" .}} - {{template "notices" .Data.below}} - </div> -</div> -<div class="site-footer"> - <div class="wrap footer-inner"> - {{if .Data.theme.FooterText}}<p>{{.Data.theme.FooterText}}</p>{{end}} - <p class="small">{{if .Data.theme.FooterShowRSS}}<a href="/feed.xml">RSS</a> · {{end}}{{.Blog.Title}}</p> - </div> + {{range $l.Below}}{{template "module" (dict "m" . "root" $)}}{{end}} + {{template "notices" (index $n "main-bottom")}} + </div></div> + {{if $l.HasLeft}}<div class="col col-left{{if and (not $l.Left) (not (index $n "left-top")) (not (index $n "left-bottom"))}} col-empty{{end}}"> + {{template "notices" (index $n "left-top")}} + {{range $l.Left}}{{template "module" (dict "m" . "root" $)}}{{end}} + {{template "notices" (index $n "left-bottom")}} + </div>{{end}} + {{if $l.HasRight}}<div class="col col-right{{if and (not $l.Right) (not (index $n "right-top")) (not (index $n "right-bottom"))}} col-empty{{end}}"> + {{template "notices" (index $n "right-top")}} + {{range $l.Right}}{{template "module" (dict "m" . "root" $)}}{{end}} + {{template "notices" (index $n "right-bottom")}} + </div>{{end}} </div> +{{if $l.Footer}}<div class="site-footer"><div class="wrap footer-inner"> + {{range $l.Footer}}{{template "module" (dict "m" . "root" $)}}{{end}} +</div></div>{{end}} </body> </html>{{end}} @@ -44,6 +49,37 @@ </aside> {{end}}{{end}} -{{define "blognav"}}<div class="site-nav"><div class="wrap nav-inner"> -{{range .Data.nav}}<a href="{{if .IsHome}}/{{else}}/{{.Slug}}{{end}}"{{if and $.Data.page (eq $.Data.page.ID .ID)}} class="active"{{end}}>{{.Title}}</a> -{{end}}</div></div>{{end}} +{{/* One layout module. .m is the store.Module, .root the page data; the same + kind renders differently in the header (big blocks) and elsewhere (boxes). */}} +{{define "module"}}{{$m := .m}}{{$r := .root}}{{$t := $r.Data.theme}} +{{- if eq $m.Kind "title"}}<div class="wrap header-text"> + <h1 class="site-title"><a href="/">{{$r.Blog.Title}}</a></h1> + {{if $r.Blog.Tagline}}<p class="tagline">{{$r.Blog.Tagline}}</p>{{end}} +</div> +{{- else if eq $m.Kind "logo"}}{{if $t.Logo}}{{if eq $m.Area "header"}}<div class="wrap header-logo"><a href="/"><img class="logo" src="/media/{{$t.Logo}}" alt="{{$r.Blog.Title}}"></a></div> +{{else}}<div class="mod mod-logo"><a href="/"><img class="logo" src="/media/{{$t.Logo}}" alt="{{$r.Blog.Title}}"></a></div>{{end}}{{end}} +{{- else if eq $m.Kind "menu"}}{{if eq $m.Area "header"}}<div class="site-nav"><div class="wrap nav-inner">{{template "menulinks" $r}}</div></div> +{{else}}<div class="mod site-nav mod-menu">{{template "modtitle" $m}}<div class="nav-inner">{{template "menulinks" $r}}</div></div>{{end}} +{{- else if eq $m.Kind "recent"}}<div class="mod mod-recent">{{template "modtitle" $m}} + <ul>{{range $i, $p := $r.Data.recent}}{{if lt $i $m.Count}}<li><a href="/{{$p.PageSlug}}/{{$p.Slug}}">{{$p.Title}}</a></li>{{end}}{{end}}</ul> +</div> +{{- else if eq $m.Kind "archive"}}<div class="mod mod-archive">{{template "modtitle" $m}} + {{range $i, $y := $r.Data.archive}}<details{{if eq $i 0}} open{{end}}><summary>{{$y.Year}} <span class="muted">({{$y.Count}})</span></summary> + {{range $y.Months}}<details><summary>{{.Name}} <span class="muted">({{len .Posts}})</span></summary> + <ul>{{range .Posts}}<li><a href="/{{.PageSlug}}/{{.Slug}}">{{.Title}}</a></li>{{end}}</ul> + </details>{{end}} + </details>{{else}}<p class="muted">No posts yet.</p>{{end}} +</div> +{{- else if eq $m.Kind "html"}}{{if not $m.Body}}{{else if or (eq $m.Area "above") (eq $m.Area "below")}}<div class="custom-html custom-html-{{$m.Area}}">{{html $m.Body}}</div> +{{else}}<div class="mod mod-html">{{template "modtitle" $m}}{{html $m.Body}}</div>{{end}} +{{- else if eq $m.Kind "rss"}}<p class="mod mod-rss small"><a href="/feed.xml">RSS feed</a></p> +{{- else if eq $m.Kind "text"}}{{if $m.Body}}<div class="mod mod-text">{{range split $m.Body "\n"}}{{if .}}<p>{{.}}</p>{{end}}{{end}}</div>{{end}} +{{- else if eq $m.Kind "sitemap"}}<div class="mod mod-sitemap">{{template "modtitle" $m}} + <ul>{{range $r.Data.pages}}<li><a href="{{if .IsHome}}/{{else}}/{{.Slug}}{{end}}">{{.Title}}</a></li>{{end}}</ul> +</div> +{{- end}}{{end}} + +{{define "modtitle"}}{{if .Title}}<h3 class="mod-title">{{.Title}}</h3>{{end}}{{end}} + +{{define "menulinks"}}{{range .Data.menu}}<a href="{{.Href}}"{{if and .PageID $.Data.page (eq $.Data.page.ID (deref64 .PageID))}} class="active"{{end}}>{{.Text}}</a> +{{end}}{{end}} |
