summaryrefslogtreecommitdiffstats
path: root/tpl
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-05-03 09:16:58 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-07-24 09:35:53 +0200
commit9f5a92078a3f388b52d597b5a59af5c933a112d2 (patch)
tree0b2b07e5b3a3f21877bc5585a4bdd76306a09dde /tpl
parent47953148b6121441d0147c960a99829c53b5a5ba (diff)
Add Hugo Modules
This commit implements Hugo Modules. This is a broad subject, but some keywords include: * A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project. * A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects. * Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running. * Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions. * A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`. All of the above is backed by Go Modules. Fixes #5973 Fixes #5996 Fixes #6010 Fixes #5911 Fixes #5940 Fixes #6074 Fixes #6082 Fixes #6092
Diffstat (limited to 'tpl')
-rw-r--r--tpl/cast/docshelper.go10
-rw-r--r--tpl/data/init_test.go2
-rw-r--r--tpl/data/resources_test.go17
-rw-r--r--tpl/hugo/init_test.go8
-rw-r--r--tpl/os/os.go25
-rw-r--r--tpl/site/init_test.go8
-rw-r--r--tpl/template.go7
-rw-r--r--tpl/tplimpl/embedded/templates.autogen.go3
-rw-r--r--tpl/tplimpl/template.go6
-rw-r--r--tpl/tplimpl/template_funcs_test.go14
10 files changed, 69 insertions, 31 deletions
diff --git a/tpl/cast/docshelper.go b/tpl/cast/docshelper.go
index 6fc35f3c7..1ee614b10 100644
--- a/tpl/cast/docshelper.go
+++ b/tpl/cast/docshelper.go
@@ -17,7 +17,7 @@ import (
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/docshelper"
- "github.com/gohugoio/hugo/htesting"
+ "github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/tpl/internal"
"github.com/spf13/viper"
)
@@ -30,7 +30,7 @@ func init() {
Cfg: viper.New(),
Log: loggers.NewErrorLogger(),
BuildStartListeners: &deps.Listeners{},
- Site: htesting.NewTestHugoSite(),
+ Site: page.NewDummyHugoSite(newTestConfig()),
}
var namespaces internal.TemplateFuncsNamespaces
@@ -47,3 +47,9 @@ func init() {
docshelper.AddDocProvider("tpl", docsProvider)
}
+
+func newTestConfig() *viper.Viper {
+ v := viper.New()
+ v.Set("contentDir", "content")
+ return v
+}
diff --git a/tpl/data/init_test.go b/tpl/data/init_test.go
index c4751e892..94c8408ea 100644
--- a/tpl/data/init_test.go
+++ b/tpl/data/init_test.go
@@ -16,6 +16,7 @@ package data
import (
"testing"
+ "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/tpl/internal"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
@@ -27,6 +28,7 @@ func TestInit(t *testing.T) {
v := viper.New()
v.Set("contentDir", "content")
+ langs.LoadLanguageSettings(v, nil)
for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
ns = nsf(newDeps(v))
diff --git a/tpl/data/resources_test.go b/tpl/data/resources_test.go
index a42232f94..39cf6bfa9 100644
--- a/tpl/data/resources_test.go
+++ b/tpl/data/resources_test.go
@@ -23,6 +23,8 @@ import (
"testing"
"time"
+ "github.com/gohugoio/hugo/modules"
+
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/cache/filecache"
@@ -87,7 +89,7 @@ func getTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*httpt
func TestScpGetRemote(t *testing.T) {
t.Parallel()
fs := new(afero.MemMapFs)
- cache := filecache.NewCache(fs, 100)
+ cache := filecache.NewCache(fs, 100, "")
tests := []struct {
path string
@@ -186,14 +188,19 @@ func newDeps(cfg config.Provider) *deps.Deps {
cfg.Set("layoutDir", "layouts")
cfg.Set("archetypeDir", "archetypes")
- l := langs.NewLanguage("en", cfg)
- l.Set("i18nDir", "i18n")
- cs, err := helpers.NewContentSpec(l)
+ langs.LoadLanguageSettings(cfg, nil)
+ mod, err := modules.CreateProjectModule(cfg)
+ if err != nil {
+ panic(err)
+ }
+ cfg.Set("allModules", modules.Modules{mod})
+
+ cs, err := helpers.NewContentSpec(cfg)
if err != nil {
panic(err)
}
- fs := hugofs.NewMem(l)
+ fs := hugofs.NewMem(cfg)
logger := loggers.NewErrorLogger()
p, err := helpers.NewPathSpec(fs, cfg)
diff --git a/tpl/hugo/init_test.go b/tpl/hugo/init_test.go
index 128f6fc19..f4e31f622 100644
--- a/tpl/hugo/init_test.go
+++ b/tpl/hugo/init_test.go
@@ -16,17 +16,19 @@ package hugo
import (
"testing"
- "github.com/gohugoio/hugo/htesting"
-
"github.com/gohugoio/hugo/deps"
+ "github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/tpl/internal"
+ "github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func TestInit(t *testing.T) {
var found bool
var ns *internal.TemplateFuncsNamespace
- s := htesting.NewTestHugoSite()
+ v := viper.New()
+ v.Set("contentDir", "content")
+ s := page.NewDummyHugoSite(v)
for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
ns = nsf(&deps.Deps{Site: s})
diff --git a/tpl/os/os.go b/tpl/os/os.go
index 2dab5c490..eb31498af 100644
--- a/tpl/os/os.go
+++ b/tpl/os/os.go
@@ -18,6 +18,7 @@ package os
import (
"errors"
"fmt"
+ "os"
_os "os"
"github.com/gohugoio/hugo/deps"
@@ -26,23 +27,20 @@ import (
)
// New returns a new instance of the os-namespaced template functions.
-func New(deps *deps.Deps) *Namespace {
+func New(d *deps.Deps) *Namespace {
- // Since Hugo 0.38 we can have multiple content dirs. This can make it hard to
- // reason about where the file is placed relative to the project root.
- // To make the {{ readFile .Filename }} variant just work, we create a composite
- // filesystem that first checks the work dir fs and then the content fs.
var rfs afero.Fs
- if deps.Fs != nil {
- rfs = deps.Fs.WorkingDir
- if deps.PathSpec != nil && deps.PathSpec.BaseFs != nil {
- rfs = afero.NewReadOnlyFs(afero.NewCopyOnWriteFs(deps.PathSpec.BaseFs.Content.Fs, deps.Fs.WorkingDir))
+ if d.Fs != nil {
+ rfs = d.Fs.WorkingDir
+ if d.PathSpec != nil && d.PathSpec.BaseFs != nil {
+ rfs = afero.NewReadOnlyFs(afero.NewCopyOnWriteFs(d.PathSpec.BaseFs.Content.Fs, d.Fs.WorkingDir))
}
+
}
return &Namespace{
readFileFs: rfs,
- deps: deps,
+ deps: d,
}
}
@@ -76,6 +74,9 @@ func readFile(fs afero.Fs, filename string) (string, error) {
return "", fmt.Errorf("file %q is too big", filename)
}
} else {
+ if os.IsNotExist(err) {
+ return "", fmt.Errorf("file %q does not exist", filename)
+ }
return "", err
}
b, err := afero.ReadFile(fs, filename)
@@ -96,6 +97,10 @@ func (ns *Namespace) ReadFile(i interface{}) (string, error) {
return "", err
}
+ if ns.deps.PathSpec != nil {
+ s = ns.deps.PathSpec.RelPathify(s)
+ }
+
return readFile(ns.readFileFs, s)
}
diff --git a/tpl/site/init_test.go b/tpl/site/init_test.go
index 00704d943..5ef885677 100644
--- a/tpl/site/init_test.go
+++ b/tpl/site/init_test.go
@@ -16,8 +16,10 @@ package site
import (
"testing"
+ "github.com/spf13/viper"
+
"github.com/gohugoio/hugo/deps"
- "github.com/gohugoio/hugo/htesting"
+ "github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/tpl/internal"
"github.com/stretchr/testify/require"
)
@@ -25,7 +27,9 @@ import (
func TestInit(t *testing.T) {
var found bool
var ns *internal.TemplateFuncsNamespace
- s := htesting.NewTestHugoSite()
+ v := viper.New()
+ v.Set("contentDir", "content")
+ s := page.NewDummyHugoSite(v)
for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
ns = nsf(&deps.Deps{Site: s})
diff --git a/tpl/template.go b/tpl/template.go
index 935771364..cd00d8061 100644
--- a/tpl/template.go
+++ b/tpl/template.go
@@ -252,12 +252,15 @@ func (t *TemplateAdapter) fileAndFilename(name string) (afero.File, string, erro
if err != nil {
return nil, "", err
}
- f, err := fs.Open(filename)
+ fim := fi.(hugofs.FileMetaInfo)
+ meta := fim.Meta()
+
+ f, err := meta.Open()
if err != nil {
return nil, "", errors.Wrapf(err, "failed to open template file %q:", filename)
}
- return f, fi.(hugofs.RealFilenameInfo).RealFilename(), nil
+ return f, meta.Filename(), nil
}
// ExecuteToString executes the current template and returns the result as a
diff --git a/tpl/tplimpl/embedded/templates.autogen.go b/tpl/tplimpl/embedded/templates.autogen.go
index bdbc84222..b2c97de6a 100644
--- a/tpl/tplimpl/embedded/templates.autogen.go
+++ b/tpl/tplimpl/embedded/templates.autogen.go
@@ -268,8 +268,7 @@ if (!doNotTrack) {
</li>
{{ end }}
</ul>
-{{ end }}
-`},
+{{ end }}`},
{`schema.html`, `<meta itemprop="name" content="{{ .Title }}">
<meta itemprop="description" content="{{ with .Description }}{{ . }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ else }}{{ with .Site.Params.description }}{{ . }}{{ end }}{{ end }}{{ end }}">
diff --git a/tpl/tplimpl/template.go b/tpl/tplimpl/template.go
index f0d3066e2..cce867ac2 100644
--- a/tpl/tplimpl/template.go
+++ b/tpl/tplimpl/template.go
@@ -711,7 +711,7 @@ func (t *templateHandler) RebuildClone() {
func (t *templateHandler) loadTemplates(prefix string) error {
- walker := func(path string, fi os.FileInfo, err error) error {
+ walker := func(path string, fi hugofs.FileMetaInfo, err error) error {
if err != nil || fi.IsDir() {
return err
}
@@ -928,8 +928,8 @@ func (t *templateHandler) addTemplateFile(name, baseTemplatePath, path string) e
realFilename := filename
if fi, err := fs.Stat(filename); err == nil {
- if fir, ok := fi.(hugofs.RealFilenameInfo); ok {
- realFilename = fir.RealFilename()
+ if fim, ok := fi.(hugofs.FileMetaInfo); ok {
+ realFilename = fim.Meta().Filename()
}
}
diff --git a/tpl/tplimpl/template_funcs_test.go b/tpl/tplimpl/template_funcs_test.go
index 449d20fd4..faf5b01fe 100644
--- a/tpl/tplimpl/template_funcs_test.go
+++ b/tpl/tplimpl/template_funcs_test.go
@@ -21,7 +21,9 @@ import (
"testing"
"time"
- "github.com/gohugoio/hugo/htesting"
+ "github.com/gohugoio/hugo/modules"
+
+ "github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers"
@@ -52,6 +54,14 @@ func newTestConfig() config.Provider {
v.Set("assetDir", "assets")
v.Set("resourceDir", "resources")
v.Set("publishDir", "public")
+
+ langs.LoadLanguageSettings(v, nil)
+ mod, err := modules.CreateProjectModule(v)
+ if err != nil {
+ panic(err)
+ }
+ v.Set("allModules", modules.Modules{mod})
+
return v
}
@@ -59,7 +69,7 @@ func newDepsConfig(cfg config.Provider) deps.DepsCfg {
l := langs.NewLanguage("en", cfg)
return deps.DepsCfg{
Language: l,
- Site: htesting.NewTestHugoSite(),
+ Site: page.NewDummyHugoSite(cfg),
Cfg: cfg,
Fs: hugofs.NewMem(l),
Logger: logger,