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 e9c7b62
Show file tree
Hide file tree
Showing 12 changed files with 794 additions and 216 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"
177 changes: 171 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,22 @@ 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

// We can do this only once.
fsCreate sync.Once

serverPorts []int
languages helpers.Languages

Expand Down Expand Up @@ -65,16 +88,158 @@ 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 {

if c.DepsCfg == nil {
c.DepsCfg = &deps.DepsCfg{}
}

cfg := c.DepsCfg
c.configured = false
cfg.Running = running

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

var sourceFs afero.Fs = hugofs.Os
if c.DepsCfg.Fs != nil {
sourceFs = c.DepsCfg.Fs.Source
}

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

c.Cfg = config
c.configFiles = configFiles

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

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

if l, ok := cfg.Cfg.Get("languagesSorted").(helpers.Languages); ok {
languages = l
if baseURL != "" {
config.Set("baseURL", baseURL)
}

c := &commandeer{DepsCfg: cfg, languages: languages, visitedURLs: types.NewEvictingStringQueue(10)}
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)
}

createMemFs := config.GetBool("renderToMemory")

if createMemFs {
// Rendering to memoryFS, publish to Root regardless of publishDir.
config.Set("publishDir", "/")
}

c.fsCreate.Do(func() {
fs := hugofs.NewFrom(sourceFs, config)

// Hugo writes the output to memory instead of the disk.
if createMemFs {
fs.Destination = new(afero.MemMapFs)
}

err = c.initFs(fs)
})

if err != nil {
return err
}

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

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

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

themeVersionMismatch, minVersion := c.isThemeVsHugoVersionMismatch(sourceFs)

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 e9c7b62

Please sign in to comment.