Skip to content

Commit

Permalink
templates: support the more extended information for themes
Browse files Browse the repository at this point in the history
  • Loading branch information
Wessie committed Jan 5, 2025
1 parent e5a3e8a commit 3088ca3
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 19 deletions.
8 changes: 4 additions & 4 deletions radio.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,10 @@ type ThemeName string

// Theme is a website theme
type Theme struct {
Name ThemeName
DisplayName string
Description string
Author string
Name ThemeName `toml:"-"`
DisplayName string `toml:"DisplayName"`
Description string `toml:"Description"`
Author string `toml:"Author"`
}

type SongInfo struct {
Expand Down
4 changes: 2 additions & 2 deletions templates/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ var defaultFunctions = map[string]any{
"AllUserPermissions": radio.AllUserPermissions,
"HasField": HasField,
"SongPair": SongPair,
publicThemeNameFn: func() []radio.ThemeName { return nil }, // placeholder
adminThemeNameFn: func() []radio.ThemeName { return nil }, // placeholder
publicThemeNameFn: func() []radio.Theme { return nil }, // placeholder
adminThemeNameFn: func() []radio.Theme { return nil }, // placeholder
}

type SongPairing struct {
Expand Down
78 changes: 65 additions & 13 deletions templates/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"html/template"
"io/fs"
"log"
"os"
"path"
"path/filepath"
Expand All @@ -16,6 +17,7 @@ import (

"maps"

"github.com/BurntSushi/toml"
radio "github.com/R-a-dio/valkyrie"
"github.com/R-a-dio/valkyrie/errors"
"github.com/R-a-dio/valkyrie/util"
Expand All @@ -24,6 +26,8 @@ import (
const (
// the extension used for template files
TEMPLATE_EXT = ".tmpl"
// the filename to be used for extra theme information
INFORMATION_FILE = "info.toml"
// the directory for static assets
ASSETS_DIR = "assets"
// the directory name used for partial templates, these are under <theme>/partials
Expand Down Expand Up @@ -54,13 +58,15 @@ type Site struct {
}

const (
adminThemeNameFn = "AdminThemeNames"
publicThemeNameFn = "PublicThemeNames"
adminThemeNameFn = "AdminThemes"
publicThemeNameFn = "PublicThemes"
)

type themeNames struct {
public []radio.ThemeName
admin []radio.ThemeName
publicNames []radio.ThemeName
publicThemes []radio.Theme
adminNames []radio.ThemeName
adminThemes []radio.Theme
}

type cacheKey string
Expand Down Expand Up @@ -103,23 +109,34 @@ func (s *Site) Executor() Executor {

func (s *Site) populateNames(themes Themes) {
var names themeNames

for _, name := range slices.Sorted(maps.Keys(themes)) {
if IsAdminTheme(name) {
names.admin = append(names.admin, name)
names.adminNames = append(names.adminNames, name)
names.adminThemes = append(names.adminThemes, themes[name].Theme)
} else {
names.public = append(names.public, name)
names.publicNames = append(names.publicNames, name)
names.publicThemes = append(names.publicThemes, themes[name].Theme)
}
}

s.names.Store(names)
}

func (s *Site) ThemeNames() []radio.ThemeName {
return s.names.Load().public
return s.names.Load().publicNames
}

func (s *Site) ThemeNamesAdmin() []radio.ThemeName {
return s.names.Load().admin
return s.names.Load().adminNames
}

func (s *Site) Themes() []radio.Theme {
return s.names.Load().publicThemes
}

func (s *Site) ThemesAdmin() []radio.Theme {
return s.names.Load().adminThemes
}

// Template returns a Template associated with the theme and page name given.
Expand Down Expand Up @@ -229,8 +246,8 @@ func FromFS(fsys fs.FS, state *StatefulFuncs) (*Site, error) {
}

// add our theme name functions before loading the files
fnMap[publicThemeNameFn] = tmpl.ThemeNames
fnMap[adminThemeNameFn] = tmpl.ThemeNamesAdmin
fnMap[publicThemeNameFn] = tmpl.Themes
fnMap[adminThemeNameFn] = tmpl.ThemesAdmin

if err = tmpl.load(); err != nil {
return nil, errors.E(op, err)
Expand Down Expand Up @@ -326,7 +343,7 @@ type Themes map[radio.ThemeName]ThemeBundle

// ThemeBundle contains the pages that construct a specific theme as a set of TemplateBundle's
type ThemeBundle struct {
name radio.ThemeName
radio.Theme
pages map[string]*TemplateBundle
assets fs.FS
}
Expand Down Expand Up @@ -456,8 +473,19 @@ func (ls *loadState) loadThemes(themes Themes, defaultDir string, dirs []string)
return errors.E(op, err)
}

info, err := ls.loadThemeInformation(defaultDir)
if err != nil {
// this isn't a fatal error, just print a warning
// FIXME: use proper logger(?)
log.Println("failed to load theme information file:", err)
}

// construct the bundle for the default
themes[radio.ThemeName(defaultDir)] = ThemeBundle{radio.ThemeName(defaultDir), defaults.bundle, assetsFs}
themes[radio.ThemeName(defaultDir)] = ThemeBundle{
Theme: info,
pages: defaults.bundle,
assets: assetsFs,
}

// and now we have to do it for all the leftover directories
for _, dir := range dirs {
Expand All @@ -476,11 +504,35 @@ func (ls *loadState) loadThemes(themes Themes, defaultDir string, dirs []string)
return errors.E(op, err)
}

themes[radio.ThemeName(dir)] = ThemeBundle{radio.ThemeName(dir), bundle, assetsFs}
info, err := ls.loadThemeInformation(dir)
if err != nil {
// this isn't a fatal error, just print a warning
// FIXME: use proper logger(?)
log.Println("failed to load theme information file:", err)
}

themes[radio.ThemeName(dir)] = ThemeBundle{
Theme: info,
pages: bundle,
assets: assetsFs,
}
}
return nil
}

func (ls *loadState) loadThemeInformation(dir string) (radio.Theme, error) {
const op errors.Op = "templates/loadState.loadThemeInformation"

var theme radio.Theme
theme.Name = radio.ThemeName(dir)

_, err := toml.DecodeFS(ls.fs, path.Join(dir, INFORMATION_FILE), &theme)
if err != nil {
return theme, errors.E(op, err)
}
return theme, nil
}

// loadSubDir searches a subdirectory of the FS used in the creation of the loader.
//
// it looks for `*.tmpl` files in this subdirectory and in a `partials/` subdirectory
Expand Down

0 comments on commit 3088ca3

Please sign in to comment.