Create a struct with all of Hugo's config options

Primary motivation is documentation, but it will also hopefully simplify the code.

Also,

* Lower case the default output format names; this is in line with the custom ones (map keys) and how
it's treated all the places. This avoids doing `stringds.EqualFold` everywhere.

Closes #10896
Closes #10620
This commit is contained in:
Bjørn Erik Pedersen 2023-01-04 18:24:36 +01:00
parent 6aededf6b4
commit 241b21b0fd
337 changed files with 13377 additions and 14898 deletions

View file

@ -1,4 +1,4 @@
// Copyright 2019 The Hugo Authors. All rights reserved.
// Copyright 2023 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package resources
package resources_test
import (
"context"
@ -25,11 +25,12 @@ import (
"testing"
"github.com/gohugoio/hugo/htesting"
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources/images"
"github.com/gohugoio/hugo/resources/internal"
@ -46,20 +47,21 @@ const gopher = `iVBORw0KGgoAAAANSUhEUgAAAEsAAAA8CAAAAAALAhhPAAAFfUlEQVRYw62XeWwU
func gopherPNG() io.Reader { return base64.NewDecoder(base64.StdEncoding, strings.NewReader(gopher)) }
func TestTransform(t *testing.T) {
c := qt.New(t)
createTransformer := func(spec *Spec, filename, content string) Transformer {
createTransformer := func(c *qt.C, spec *resources.Spec, filename, content string) resources.Transformer {
filename = filepath.FromSlash(filename)
fs := spec.Fs.Source
afero.WriteFile(fs, filename, []byte(content), 0777)
r, _ := spec.New(ResourceSourceDescriptor{Fs: fs, SourceFilename: filename})
return r.(Transformer)
err := afero.WriteFile(spec.Fs.Source, filepath.Join("assets", filename), []byte(content), 0777)
c.Assert(err, qt.IsNil)
r, err := spec.New(resources.ResourceSourceDescriptor{Fs: spec.BaseFs.Assets.Fs, SourceFilename: filename})
c.Assert(err, qt.IsNil)
c.Assert(r, qt.Not(qt.IsNil), qt.Commentf(filename))
return r.(resources.Transformer)
}
createContentReplacer := func(name, old, new string) ResourceTransformation {
createContentReplacer := func(name, old, new string) resources.ResourceTransformation {
return &testTransformation{
name: name,
transform: func(ctx *ResourceTransformationCtx) error {
transform: func(ctx *resources.ResourceTransformationCtx) error {
in := helpers.ReaderToString(ctx.From)
in = strings.Replace(in, old, new, 1)
ctx.AddOutPathIdentifier("." + name)
@ -70,7 +72,7 @@ func TestTransform(t *testing.T) {
}
// Verify that we publish the same file once only.
assertNoDuplicateWrites := func(c *qt.C, spec *Spec) {
assertNoDuplicateWrites := func(c *qt.C, spec *resources.Spec) {
c.Helper()
hugofs.WalkFilesystems(spec.Fs.PublishDir, func(fs afero.Fs) bool {
if dfs, ok := fs.(hugofs.DuplicatesReporter); ok {
@ -80,12 +82,14 @@ func TestTransform(t *testing.T) {
})
}
assertShouldExist := func(c *qt.C, spec *Spec, filename string, should bool) {
assertShouldExist := func(c *qt.C, spec *resources.Spec, filename string, should bool) {
c.Helper()
exists, _ := helpers.Exists(filepath.FromSlash(filename), spec.Fs.WorkingDirReadOnly)
c.Assert(exists, qt.Equals, should)
}
c := qt.New(t)
c.Run("All values", func(c *qt.C) {
c.Parallel()
@ -93,14 +97,14 @@ func TestTransform(t *testing.T) {
transformation := &testTransformation{
name: "test",
transform: func(ctx *ResourceTransformationCtx) error {
transform: func(ctx *resources.ResourceTransformationCtx) error {
// Content
in := helpers.ReaderToString(ctx.From)
in = strings.Replace(in, "blue", "green", 1)
fmt.Fprint(ctx.To, in)
// Media type
ctx.OutMediaType = media.CSVType
ctx.OutMediaType = media.Builtin.CSVType
// Change target
ctx.ReplaceOutPathExtension(".csv")
@ -112,7 +116,7 @@ func TestTransform(t *testing.T) {
},
}
r := createTransformer(spec, "f1.txt", "color is blue")
r := createTransformer(c, spec, "f1.txt", "color is blue")
tr, err := r.Transform(transformation)
c.Assert(err, qt.IsNil)
@ -120,7 +124,7 @@ func TestTransform(t *testing.T) {
c.Assert(err, qt.IsNil)
c.Assert(content, qt.Equals, "color is green")
c.Assert(tr.MediaType(), eq, media.CSVType)
c.Assert(tr.MediaType(), eq, media.Builtin.CSVType)
c.Assert(tr.RelPermalink(), qt.Equals, "/f1.csv")
assertShouldExist(c, spec, "public/f1.csv", true)
@ -137,16 +141,16 @@ func TestTransform(t *testing.T) {
transformation := &testTransformation{
name: "test",
transform: func(ctx *ResourceTransformationCtx) error {
transform: func(ctx *resources.ResourceTransformationCtx) error {
// Change media type only
ctx.OutMediaType = media.CSVType
ctx.OutMediaType = media.Builtin.CSVType
ctx.ReplaceOutPathExtension(".csv")
return nil
},
}
r := createTransformer(spec, "f1.txt", "color is blue")
r := createTransformer(c, spec, "f1.txt", "color is blue")
tr, err := r.Transform(transformation)
c.Assert(err, qt.IsNil)
@ -154,7 +158,7 @@ func TestTransform(t *testing.T) {
c.Assert(err, qt.IsNil)
c.Assert(content, qt.Equals, "color is blue")
c.Assert(tr.MediaType(), eq, media.CSVType)
c.Assert(tr.MediaType(), eq, media.Builtin.CSVType)
// The transformed file should only be published if RelPermalink
// or Permalink is called.
@ -182,8 +186,8 @@ func TestTransform(t *testing.T) {
t1 := createContentReplacer("t1", "blue", "green")
t2 := createContentReplacer("t1", "color", "car")
for i, transformation := range []ResourceTransformation{t1, t2} {
r := createTransformer(spec, "f1.txt", "color is blue")
for i, transformation := range []resources.ResourceTransformation{t1, t2} {
r := createTransformer(c, spec, "f1.txt", "color is blue")
tr, _ := r.Transform(transformation)
content, err := tr.(resource.ContentProvider).Content(context.Background())
c.Assert(err, qt.IsNil)
@ -203,20 +207,20 @@ func TestTransform(t *testing.T) {
for i := 0; i < 2; i++ {
spec := newTestResourceSpec(specDescriptor{c: c, fs: fs})
r := createTransformer(spec, "f1.txt", "color is blue")
r := createTransformer(c, spec, "f1.txt", "color is blue")
var transformation ResourceTransformation
var transformation resources.ResourceTransformation
if i == 0 {
// There is currently a hardcoded list of transformations that we
// persist to disk (tocss, postcss).
transformation = &testTransformation{
name: "tocss",
transform: func(ctx *ResourceTransformationCtx) error {
transform: func(ctx *resources.ResourceTransformationCtx) error {
in := helpers.ReaderToString(ctx.From)
in = strings.Replace(in, "blue", "green", 1)
ctx.AddOutPathIdentifier("." + "cached")
ctx.OutMediaType = media.CSVType
ctx.OutMediaType = media.Builtin.CSVType
ctx.Data = map[string]any{
"Hugo": "Rocks!",
}
@ -228,7 +232,7 @@ func TestTransform(t *testing.T) {
// Force read from file cache.
transformation = &testTransformation{
name: "tocss",
transform: func(ctx *ResourceTransformationCtx) error {
transform: func(ctx *resources.ResourceTransformationCtx) error {
return herrors.ErrFeatureNotAvailable
},
}
@ -241,7 +245,7 @@ func TestTransform(t *testing.T) {
content, err := tr.(resource.ContentProvider).Content(context.Background())
c.Assert(err, qt.IsNil)
c.Assert(content, qt.Equals, "color is green", msg)
c.Assert(tr.MediaType(), eq, media.CSVType)
c.Assert(tr.MediaType(), eq, media.Builtin.CSVType)
c.Assert(tr.Data(), qt.DeepEquals, map[string]any{
"Hugo": "Rocks!",
})
@ -259,7 +263,7 @@ func TestTransform(t *testing.T) {
t1 := createContentReplacer("t1", "blue", "green")
r := createTransformer(spec, "f1.txt", "color is blue")
r := createTransformer(c, spec, "f1.txt", "color is blue")
tr, _ := r.Transform(t1)
@ -270,7 +274,7 @@ func TestTransform(t *testing.T) {
c.Assert(relPermalink, qt.Equals, "/f1.t1.txt")
c.Assert(content, qt.Equals, "color is green")
c.Assert(tr.MediaType(), eq, media.TextType)
c.Assert(tr.MediaType(), eq, media.Builtin.TextType)
assertNoDuplicateWrites(c, spec)
assertShouldExist(c, spec, "public/f1.t1.txt", true)
@ -284,14 +288,14 @@ func TestTransform(t *testing.T) {
t1 := createContentReplacer("t1", "blue", "green")
t2 := createContentReplacer("t1", "color", "car")
r := createTransformer(spec, "f1.txt", "color is blue")
r := createTransformer(c, spec, "f1.txt", "color is blue")
tr, _ := r.Transform(t1, t2)
content, err := tr.(resource.ContentProvider).Content(context.Background())
c.Assert(err, qt.IsNil)
c.Assert(content, qt.Equals, "car is green")
c.Assert(tr.MediaType(), eq, media.TextType)
c.Assert(tr.MediaType(), eq, media.Builtin.TextType)
assertNoDuplicateWrites(c, spec)
})
@ -304,7 +308,7 @@ func TestTransform(t *testing.T) {
t1 := createContentReplacer("t1", "blue", "green")
t2 := createContentReplacer("t2", "color", "car")
r := createTransformer(spec, "f1.txt", "color is blue")
r := createTransformer(c, spec, "f1.txt", "color is blue")
tr1, _ := r.Transform(t1)
tr2, _ := tr1.Transform(t2)
@ -327,7 +331,7 @@ func TestTransform(t *testing.T) {
const count = 26 // A-Z
transformations := make([]ResourceTransformation, count)
transformations := make([]resources.ResourceTransformation, count)
for i := 0; i < count; i++ {
transformations[i] = createContentReplacer(fmt.Sprintf("t%d", i), fmt.Sprint(i), string(rune(i+65)))
}
@ -337,7 +341,7 @@ func TestTransform(t *testing.T) {
countstr.WriteString(fmt.Sprint(i))
}
r := createTransformer(spec, "f1.txt", countstr.String())
r := createTransformer(c, spec, "f1.txt", countstr.String())
tr, _ := r.Transform(transformations...)
content, err := tr.(resource.ContentProvider).Content(context.Background())
@ -355,17 +359,17 @@ func TestTransform(t *testing.T) {
transformation := &testTransformation{
name: "test",
transform: func(ctx *ResourceTransformationCtx) error {
transform: func(ctx *resources.ResourceTransformationCtx) error {
ctx.AddOutPathIdentifier(".changed")
return nil
},
}
r := createTransformer(spec, "gopher.png", helpers.ReaderToString(gopherPNG()))
r := createTransformer(c, spec, "gopher.png", helpers.ReaderToString(gopherPNG()))
tr, err := r.Transform(transformation)
c.Assert(err, qt.IsNil)
c.Assert(tr.MediaType(), eq, media.PNGType)
c.Assert(tr.MediaType(), eq, media.Builtin.PNGType)
img, ok := tr.(images.ImageResource)
c.Assert(ok, qt.Equals, true)
@ -400,11 +404,11 @@ func TestTransform(t *testing.T) {
c.Run("Concurrent", func(c *qt.C) {
spec := newTestResourceSpec(specDescriptor{c: c})
transformers := make([]Transformer, 10)
transformations := make([]ResourceTransformation, 10)
transformers := make([]resources.Transformer, 10)
transformations := make([]resources.ResourceTransformation, 10)
for i := 0; i < 10; i++ {
transformers[i] = createTransformer(spec, fmt.Sprintf("f%d.txt", i), fmt.Sprintf("color is %d", i))
transformers[i] = createTransformer(c, spec, fmt.Sprintf("f%d.txt", i), fmt.Sprintf("color is %d", i))
transformations[i] = createContentReplacer("test", strconv.Itoa(i), "blue")
}
@ -433,13 +437,13 @@ func TestTransform(t *testing.T) {
type testTransformation struct {
name string
transform func(ctx *ResourceTransformationCtx) error
transform func(ctx *resources.ResourceTransformationCtx) error
}
func (t *testTransformation) Key() internal.ResourceTransformationKey {
return internal.NewResourceTransformationKey(t.name)
}
func (t *testTransformation) Transform(ctx *ResourceTransformationCtx) error {
func (t *testTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
return t.transform(ctx)
}