diff options
| author | grm <grm@eyesin.space> | 2026-09-18 19:17:17 +0300 |
|---|---|---|
| committer | grm <grm@eyesin.space> | 2026-09-18 19:17:17 +0300 |
| commit | b88a7d22c8d79b30de3403c631dd2c5f67669537 (patch) | |
| tree | 90fd4215595aedee86bfa4603b41e9f8bbfb04d2 /internal/web/theme.go | |
| parent | 7ac90f8e99dbf763b0fe04a17d7eef19dd22cae8 (diff) | |
| download | blogspace-b88a7d22c8d79b30de3403c631dd2c5f67669537.tar.gz blogspace-b88a7d22c8d79b30de3403c631dd2c5f67669537.tar.bz2 blogspace-b88a7d22c8d79b30de3403c631dd2c5f67669537.zip | |
Make the menu link styles switches that combine
The one "Link style" select (normal, uppercase, plain) could not give
uppercase links without the bold, or underlined bold links. Bold,
uppercase and the underline (never, on hover, always) are now separate
switches, drawn by blog.css from body classes (Theme.NavClass) so the
theme CSS only colours the links. A stored nav_style is mapped onto the
switches when the theme is read and dropped on the next save; themes
without either keep the bold, underline-on-hover look blog.css always had.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A
Diffstat (limited to 'internal/web/theme.go')
| -rw-r--r-- | internal/web/theme.go | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/internal/web/theme.go b/internal/web/theme.go index 0437f51..9eae856 100644 --- a/internal/web/theme.go +++ b/internal/web/theme.go @@ -43,10 +43,17 @@ type Theme struct { HeaderRule string `json:"header_rule"` // none | line | dots | stripes, drawn beside the title/logo modules in the header NavAlign string `json:"nav_align"` // left | center | right (header menu) - NavStyle string `json:"nav_style"` // normal | uppercase | plain (regular weight, underlined) - NavBg string `json:"nav_bg"` - NavText string `json:"nav_text"` - NavHover string `json:"nav_hover"` // "" = same as NavText + // The link styles are switches that combine; blog.css draws them from + // the body classes NavClass makes. NavStyle is the select they replaced + // (normal | uppercase | plain): still decoded from themes saved before, + // turned into the switches by ParseTheme and never written again. + NavStyle string `json:"nav_style,omitempty"` + NavBold bool `json:"nav_bold"` + NavUpper bool `json:"nav_upper"` // uppercase, letter-spaced + NavUnderline string `json:"nav_underline"` // hover | never | always + NavBg string `json:"nav_bg"` + NavText string `json:"nav_text"` + NavHover string `json:"nav_hover"` // "" = same as NavText ShowDates bool `json:"show_dates"` DateFormat string `json:"date_format"` // long | short | iso (rendered by i18n.FormatDate) @@ -108,7 +115,7 @@ func DefaultTheme() Theme { ContentStyle: "card", ContentPadding: "normal", Font: "sans", HeadingFont: "same", FontSize: "normal", HeaderImageHeight: "medium", HeaderAlign: "left", HeaderBg: "#2f3a4a", HeaderText: "#ffffff", TitleSize: "normal", HeaderRule: "none", - NavAlign: "left", NavStyle: "normal", NavBg: "#ffffff", NavText: "#222222", + NavAlign: "left", NavBold: true, NavUnderline: "hover", NavBg: "#ffffff", NavText: "#222222", ShowDates: true, DateFormat: "long", PostsPerPage: postsPerPageChoices[0], ListStyle: "full", PostImage: "top", TitleRule: "none", PostNotices: true, FooterBg: "#2f3a4a", FooterColor: "#d0d5dc", FooterAlign: "center", LogoSize: "medium", @@ -122,6 +129,15 @@ func ParseTheme(raw json.RawMessage) Theme { if len(raw) > 0 { _ = json.Unmarshal(raw, &t) } + // Themes saved with the old link-style select: it becomes the switches + // it stood for, and is dropped from the JSON on the next save. + switch t.NavStyle { + case "uppercase": + t.NavUpper = true + case "plain": + t.NavBold, t.NavUnderline = false, "always" + } + t.NavStyle = "" t.normalize() return t } @@ -190,7 +206,7 @@ func (t *Theme) normalize() { t.TitleSize = pick(t.TitleSize, "normal", "small", "large") t.HeaderRule = pick(t.HeaderRule, "none", "line", "dots", "stripes") t.NavAlign = pick(t.NavAlign, "left", "center", "right") - t.NavStyle = pick(t.NavStyle, "normal", "uppercase", "plain") + t.NavUnderline = pick(t.NavUnderline, "hover", "never", "always") t.NavBg = color(t.NavBg, d.NavBg) t.NavText = color(t.NavText, d.NavText) t.NavHover = optColor(t.NavHover) @@ -259,7 +275,9 @@ func ThemeFromForm(cur Theme, f url.Values) Theme { t.TitleSize = get("title_size") t.HeaderRule = get("header_rule") t.NavAlign = get("nav_align") - t.NavStyle = get("nav_style") + t.NavBold = on("nav_bold") + t.NavUpper = on("nav_upper") + t.NavUnderline = get("nav_underline") t.NavBg = get("nav_bg") t.NavText = get("nav_text") t.NavHover = hover("nav_hover") @@ -504,6 +522,19 @@ func (t Theme) RuleClass() string { return "ruled rule-" + t.HeaderRule } +// NavClass is the body classes blog.css draws the menu links from (weight, +// case, underline); the theme CSS only colours them. +func (t Theme) NavClass() string { + c := []string{"nav-ul-" + t.NavUnderline} + if t.NavBold { + c = append(c, "nav-bold") + } + if t.NavUpper { + c = append(c, "nav-upper") + } + return strings.Join(c, " ") +} + // TitleRuleClass is the body class blog.css draws the rule under page and // post titles from; the theme CSS only colours it. func (t Theme) TitleRuleClass() string { @@ -551,7 +582,7 @@ a:hover {{"{"}}{{if .LinkHover}} color:{{.LinkHover}};{{end}}{{if eq .LinkUnderl .header-image img { max-height:{{.HeaderImageMaxHeight}}; } .site-nav { background:{{.NavBg}}; } .nav-inner { text-align:{{.NavAlign}}; } -.site-nav a { color:{{.NavText}};{{if eq .NavStyle "uppercase"}} text-transform:uppercase; letter-spacing:0.05em; font-size:0.9em;{{else if eq .NavStyle "plain"}} font-weight:normal; text-decoration:underline;{{end}} } +.site-nav a { color:{{.NavText}}; } {{- if .NavHover}} .site-nav a:hover { color:{{.NavHover}}; } {{- end}} |
