Skip to content

Commit

Permalink
Allow themes to define output formats, media types and params
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bep committed Mar 21, 2018
1 parent 3d1a6e1 commit 7633294
Show file tree
Hide file tree
Showing 12 changed files with 740 additions and 186 deletions.
13 changes: 10 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,7 @@
name = "github.com/muesli/smartcrop"
branch = "master"


[[constraint]]
name = "github.com/sanity-io/litter"
version = "1.1.0"
163 changes: 157 additions & 6 deletions commands/commandeer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@
package commands

import (
"os"
"path/filepath"
"sync"

"github.com/spf13/cobra"

"github.com/gohugoio/hugo/utils"

"github.com/spf13/afero"

"github.com/gohugoio/hugo/hugolib"

"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
Expand All @@ -23,11 +35,21 @@ import (

type commandeer struct {
*deps.DepsCfg

subCmdVs []*cobra.Command

pathSpec *helpers.PathSpec
visitedURLs *types.EvictingStringQueue

staticDirsConfig []*src.Dirs

// We watch these for changes.
configFiles []string

doWithCommandeer func(c *commandeer) error
// Make sure we don't try to allocate server ports etc. twice.
doWithCommandeerInit sync.Once

serverPorts []int
languages helpers.Languages

Expand Down Expand Up @@ -65,16 +87,145 @@ func (c *commandeer) initFs(fs *hugofs.Fs) error {
return nil
}

func newCommandeer(cfg *deps.DepsCfg, running bool) (*commandeer, error) {
func newCommandeer(running bool, doWithCommandeer func(c *commandeer) error, subCmdVs ...*cobra.Command) (*commandeer, error) {

c := &commandeer{
doWithCommandeer: doWithCommandeer,
subCmdVs: append([]*cobra.Command{hugoCmdV}, subCmdVs...),
visitedURLs: types.NewEvictingStringQueue(10)}

return c, c.loadConfig(running)
}

func (c *commandeer) loadConfig(running bool) error {
cfg := &deps.DepsCfg{}
c.DepsCfg = cfg
c.configured = false
cfg.Running = running

var languages helpers.Languages
var dir string
if source != "" {
dir, _ = filepath.Abs(source)
} else {
dir, _ = os.Getwd()
}

sourceFs := hugofs.Os
config, configFiles, err := hugolib.LoadConfig(hugolib.ConfigSourceDescriptor{Fs: sourceFs, Path: source, WorkingDir: dir, Filename: cfgFile})
if err != nil {
return err
}

for _, cmdV := range c.subCmdVs {
c.initializeFlags(cmdV)
}

c.Cfg = config
c.configFiles = configFiles

if l, ok := c.Cfg.Get("languagesSorted").(helpers.Languages); ok {
c.languages = l
}

if baseURL != "" {
config.Set("baseURL", baseURL)
}

c.doWithCommandeerInit.Do(func() {
if c.doWithCommandeer != nil {
err = c.doWithCommandeer(c)
}
})

if err != nil {
return err
}

if len(disableKinds) > 0 {
c.Set("disableKinds", disableKinds)
}

logger, err := createLogger(cfg.Cfg)
if err != nil {
return err
}

cfg.Logger = logger

config.Set("logI18nWarnings", logI18nWarnings)

if theme != "" {
config.Set("theme", theme)
}

if themesDir != "" {
config.Set("themesDir", themesDir)
}

if destination != "" {
config.Set("publishDir", destination)
}

config.Set("workingDir", dir)

if contentDir != "" {
config.Set("contentDir", contentDir)
}

if layoutDir != "" {
config.Set("layoutDir", layoutDir)
}

if cacheDir != "" {
config.Set("cacheDir", cacheDir)
}

fs := hugofs.NewFrom(sourceFs, config)

// Hugo writes the output to memory instead of the disk.
// This is only used for benchmark testing. Cause the content is only visible
// in memory.
if config.GetBool("renderToMemory") {
fs.Destination = new(afero.MemMapFs)
// Rendering to memoryFS, publish to Root regardless of publishDir.
config.Set("publishDir", "/")
}

cacheDir = config.GetString("cacheDir")
if cacheDir != "" {
if helpers.FilePathSeparator != cacheDir[len(cacheDir)-1:] {
cacheDir = cacheDir + helpers.FilePathSeparator
}
isDir, err := helpers.DirExists(cacheDir, fs.Source)
utils.CheckErr(cfg.Logger, err)
if !isDir {
mkdir(cacheDir)
}
config.Set("cacheDir", cacheDir)
} else {
config.Set("cacheDir", helpers.GetTempDir("hugo_cache", fs.Source))
}

if l, ok := cfg.Cfg.Get("languagesSorted").(helpers.Languages); ok {
languages = l
if err := c.initFs(fs); err != nil {
return err
}

cfg.Logger.INFO.Println("Using config file:", config.ConfigFileUsed())

themeDir := c.PathSpec().GetThemeDir()
if themeDir != "" {
if _, err := cfg.Fs.Source.Stat(themeDir); os.IsNotExist(err) {
return newSystemError("Unable to find theme Directory:", themeDir)
}
}

c := &commandeer{DepsCfg: cfg, languages: languages, visitedURLs: types.NewEvictingStringQueue(10)}
themeVersionMismatch, minVersion := c.isThemeVsHugoVersionMismatch()

if themeVersionMismatch {
cfg.Logger.ERROR.Printf("Current theme does not support Hugo version %s. Minimum version required is %s\n",
helpers.CurrentHugoVersion.ReleaseVersion(), minVersion)
}

return nil

return c, nil
}
Loading

0 comments on commit 7633294

Please sign in to comment.