Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions admin/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ var settingGroups = []settingGroupDef{
{Key: "favicon", Label: "Favicon", Help: "Icon shown in the browser tab."},
{Key: "custom_header_code", Label: "Custom header code", Help: "HTML added to the <head> of every page."},
{Key: "custom_footer_code", Label: "Custom footer code", Help: "HTML added before </body> on every page."},
{Key: "show_powered_by", Label: "Show \"Powered by goblog\"", Help: "Credit line with a link to goblog.live in the footer."},
}},
{ID: "comments", Title: "Comments", Settings: []settingMeta{
{Key: "comments_require_login", Label: "Require login to comment", Help: "When off, anyone can leave a comment."},
Expand Down
2 changes: 1 addition & 1 deletion admin/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var seededSettings = map[string]string{
"landing_page_image": "file", "favicon": "file", "custom_header_code": "textarea", "custom_footer_code": "textarea",
"theme": "text", "robots_tag": "text", "site_url": "text", "comments_require_login": "checkbox",
"plugin_directory_url": "text", "theme_directory_url": "text",
"site_description": "textarea", "site_image": "file",
"site_description": "textarea", "site_image": "file", "show_powered_by": "checkbox",
}

func seededSettingMap() map[string]blog.Setting {
Expand Down
2 changes: 1 addition & 1 deletion plugins/docs/content/writing-a-theme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This page is about the templates: how they are loaded, what data they get, how t

At startup, and again whenever the `theme` setting changes, goblog builds one Go [`html/template`](https://pkg.go.dev/html/template) set in three layers, each parsed on top of the last:

1. **Shared:** `templates/shared/*.html` — partials goblog owns because they carry behaviour rather than look. `_head.html` defines `_head`, the `<head>` every page starts with (meta tags, the CDN stylesheets, `/theme/css/goblog.css`, the `custom_header_code` setting and the plugins' head HTML). `_search_results.html` defines `_search_results`, the search page's result list: the count, the no-results message, and one entry per result — posts and whatever installed plugins contribute (the plugin and theme directories, the docs). A theme includes it from `search.html` and never needs to know which kinds of result exist; a release that adds a new kind shows up on every theme.
1. **Shared:** `templates/shared/*.html` — partials goblog owns because they carry behaviour rather than look. `_head.html` defines `_head`, the `<head>` every page starts with (meta tags, the CDN stylesheets, `/theme/css/goblog.css`, the `custom_header_code` setting and the plugins' head HTML). `_search_results.html` defines `_search_results`, the search page's result list: the count, the no-results message, and one entry per result — posts and whatever installed plugins contribute (the plugin and theme directories, the docs). A theme includes it from `search.html` and never needs to know which kinds of result exist; a release that adds a new kind shows up on every theme. `_powered_by.html` defines `_powered_by`, the "Powered by goblog" credit: a `<span class="powered-by">` holding the text and the link, or nothing when the site has switched the `show_powered_by` setting off. Include it from your `footer.html` inside the element you style the line with, rather than writing the link yourself, so the setting works on your theme too.
2. **Default:** `themes/default/templates/*.html`.
3. **Yours:** `<theme>/templates/*.html`.

Expand Down
2 changes: 1 addition & 1 deletion plugins/docs/content_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func knownIdentifiers() map[string]bool {
// Setting keys seeded in tools/migrate.go and read via
// blog.SettingValue / ctx.Settings elsewhere.
"plugin_directory_url", "theme_directory_url", "refresh_minutes", "github_token",
"site_url", "site_description", "site_image", "custom_header_code", "custom_footer_code",
"site_url", "site_description", "site_image", "custom_header_code", "custom_footer_code", "show_powered_by",

// comments_require_login is both a template data key (blog/blog.go
// post.html render calls) and the setting blog.CommentsRequireLogin
Expand Down
11 changes: 11 additions & 0 deletions templates/shared/_powered_by.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{/*
_powered_by renders the "Powered by goblog" credit, unless the
show_powered_by setting is off. A theme's footer includes it with
{{ template "_powered_by" . }} inside whatever element it styles the line
with, so the link and the setting live here rather than in every theme.
The wizard pages have no settings yet and always show it.
*/}}
{{ define "_powered_by" -}}
{{ $show := true }}{{ with .settings }}{{ if eq (index . "show_powered_by").Value "false" }}{{ $show = false }}{{ end }}{{ end -}}
{{ if $show }}<span class="powered-by">Powered by <a href="https://www.goblog.live" target="goblog {{ .version }}">goblog {{ .version }}</a></span>{{ end }}
{{- end }}
53 changes: 53 additions & 0 deletions templates_powered_by_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"bytes"
"strings"
"testing"

"github.com/gin-gonic/gin"
"goblog/blog"
"goblog/theme"
)

// TestPoweredBy: the shared _powered_by partial shows the credit unless the
// show_powered_by setting is "false" — including before the setting exists
// (an upgraded site, the wizard pages).
func TestPoweredBy(t *testing.T) {
tmpl, _, err := theme.Load(theme.DefaultName, theme.FuncMap())
if err != nil {
t.Fatalf("load default theme: %v", err)
}
setting := func(v string) map[string]blog.Setting {
return map[string]blog.Setting{"show_powered_by": {Key: "show_powered_by", Type: "checkbox", Value: v}}
}
for name, tc := range map[string]struct {
data gin.H
want bool
}{
"no settings (wizard)": {gin.H{"version": "v1"}, true},
"setting not seeded": {gin.H{"version": "v1", "settings": map[string]blog.Setting{}}, true},
"on": {gin.H{"version": "v1", "settings": setting("true")}, true},
"off": {gin.H{"version": "v1", "settings": setting("false")}, false},
} {
var out bytes.Buffer
if err := tmpl.ExecuteTemplate(&out, "_powered_by", tc.data); err != nil {
t.Fatalf("%s: %v", name, err)
}
got := strings.Contains(out.String(), `Powered by <a href="https://www.goblog.live"`)
if got != tc.want {
t.Errorf("%s: credit shown = %v, want %v (output %q)", name, got, tc.want, out.String())
}
if !tc.want && strings.TrimSpace(out.String()) != "" {
t.Errorf("%s: expected no output, got %q", name, out.String())
}
}
// footer.html must go through the partial, or the setting does nothing.
var out bytes.Buffer
if err := tmpl.ExecuteTemplate(&out, "footer.html", gin.H{"version": "v1", "settings": setting("false"), "recent": blog.Post{}}); err != nil {
t.Fatalf("footer.html: %v", err)
}
if strings.Contains(out.String(), "Powered by") {
t.Error("footer.html shows the credit with show_powered_by off")
}
}
2 changes: 1 addition & 1 deletion themes/default/templates/footer.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div id="footer" class="text-center">
<div class="footer"></div>
<div class="spacer version">Powered by <a href="https://github.com/compscidr/goblog" target="goblog {{ .version }}">goblog {{ .version }}</a></div>
<div class="spacer version">{{ template "_powered_by" . }}</div>
</div>
</div> <!-- / wrapper -->
<div class="bottom bottom-0">
Expand Down
2 changes: 1 addition & 1 deletion themes/default/templates/wizard_auth.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h5>Create Admin Account</h5>
<i class="fab fa-github fa-1x"></i> Sign in with GitHub
</button>
</form>
<div class="version text-center">Powered by <a href="https://github.com/compscidr/goblog" target="goblog {{ .version }}">goblog {{ .version }}</a></div>
<div class="version text-center">{{ template "_powered_by" . }}</div>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion themes/default/templates/wizard_db.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ <h5>Database:</h5>
<i class="bi bi-database-gear"></i> Test Database
</a>
</form>
<div class="version text-center">Powered by <a href="https://github.com/compscidr/goblog" target="goblog {{ .version }}">goblog {{ .version }}</a></div>
<div class="version text-center">{{ template "_powered_by" . }}</div>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion themes/default/templates/wizard_settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ <h5>Socials: (leave blank if you don't want to display)</h5>
Save Settings
</a>
</form>
<div class="version text-center">Powered by <a href="https://github.com/compscidr/goblog" target="goblog {{ .version }}">goblog {{ .version }}</a></div>
<div class="version text-center">{{ template "_powered_by" . }}</div>
</div>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions tools/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ func seedDefaultSettings(db *gorm.DB) {
{Key: "favicon", Type: "file", Value: "/img/favicon.ico"},
{Key: "custom_header_code", Type: "textarea", Value: ""},
{Key: "custom_footer_code", Type: "textarea", Value: ""},
{Key: "show_powered_by", Type: "checkbox", Value: "true"},
{Key: "theme", Type: "text", Value: "default"},
{Key: "robots_tag", Type: "text", Value: "index, follow"},
{Key: "site_url", Type: "text", Value: "https://www.example.com"},
Expand Down
Loading