Allow themes to define output formats, media types and params

This allows a `config.toml` (or `yaml`, ´yml`, or `json`)  in the theme to set:

1) `params` (but cannot override params in project. Will also get its own "namespace", i.e. `{{ .Site.Params.mytheme.my_param }}` will be the same as `{{ .Site.Params.my_param }}` providing that the main project does not define a param with that key.
2) `menu` -- but cannot redefine/add menus in the project. Must create its own menus with its own identifiers.
3) `languages` -- only `params` and `menu`. Same rules as above.
4) **new** `outputFormats`
5) **new** `mediaTypes`

This should help with the "theme portability" issue and people having to copy and paste lots of setting into their projects.

Fixes #4490
This commit is contained in:
Bjørn Erik Pedersen
2018-03-18 11:07:24 +01:00
parent 3d1a6e109c
commit e9c7b6205f
12 changed files with 796 additions and 218 deletions

View File

@@ -10,6 +10,8 @@ import (
"strings"
"text/template"
"github.com/sanity-io/litter"
jww "github.com/spf13/jwalterweatherman"
"github.com/gohugoio/hugo/config"
@@ -37,11 +39,15 @@ type sitesBuilder struct {
Fs *hugofs.Fs
T testing.TB
dumper litter.Options
// Aka the Hugo server mode.
running bool
H *HugoSites
theme string
// Default toml
configFormat string
@@ -63,7 +69,13 @@ func newTestSitesBuilder(t testing.TB) *sitesBuilder {
v := viper.New()
fs := hugofs.NewMem(v)
return &sitesBuilder{T: t, Fs: fs, configFormat: "toml"}
litterOptions := litter.Options{
HidePrivateFields: true,
StripPackageNames: true,
Separator: " ",
}
return &sitesBuilder{T: t, Fs: fs, configFormat: "toml", dumper: litterOptions}
}
func (s *sitesBuilder) Running() *sitesBuilder {
@@ -97,6 +109,15 @@ func (s *sitesBuilder) WithConfigFile(format, conf string) *sitesBuilder {
return s
}
func (s *sitesBuilder) WithThemeConfigFile(format, conf string) *sitesBuilder {
if s.theme == "" {
s.theme = "test-theme"
}
filename := filepath.Join("themes", s.theme, "config."+format)
writeSource(s.T, s.Fs, filename, conf)
return s
}
func (s *sitesBuilder) WithSimpleConfigFile() *sitesBuilder {
var config = `
baseURL = "http://example.com/"
@@ -229,10 +250,15 @@ func (s *sitesBuilder) CreateSites() *sitesBuilder {
s.writeFilePairs("i18n", s.i18nFilePairsAdded)
if s.Cfg == nil {
cfg, err := LoadConfig(ConfigSourceDescriptor{Fs: s.Fs.Source, Name: "config." + s.configFormat})
cfg, configFiles, err := LoadConfig(ConfigSourceDescriptor{Fs: s.Fs.Source, Filename: "config." + s.configFormat})
if err != nil {
s.Fatalf("Failed to load config: %s", err)
}
expectedConfigs := 1
if s.theme != "" {
expectedConfigs = 2
}
require.Equal(s.T, expectedConfigs, len(configFiles), fmt.Sprintf("Configs: %v", configFiles))
s.Cfg = cfg
}
@@ -345,6 +371,17 @@ func (s *sitesBuilder) AssertFileContent(filename string, matches ...string) {
}
}
func (s *sitesBuilder) AssertObject(expected string, object interface{}) {
got := s.dumper.Sdump(object)
expected = strings.TrimSpace(expected)
if expected != got {
fmt.Println(got)
diff := helpers.DiffStrings(expected, got)
s.Fatalf("diff:\n%s\nexpected\n%s\ngot\n%s", diff, expected, got)
}
}
func (s *sitesBuilder) AssertFileContentRe(filename string, matches ...string) {
content := readDestination(s.T, s.Fs, filename)
for _, match := range matches {