Skip to content
Permalink
Browse files

Image resource refactor

This commit pulls most of the image related logic into its own package, to make it easier to reason about and extend.

This is also a rewrite of the transformation logic used in Hugo Pipes, mostly to allow constructs like the one below:

    {{ ($myimg | fingerprint ).Width }}

Fixes gohugoio#5903
Fixes gohugoio#6234
Fixes gohugoio#6266
  • Loading branch information...
bep committed Aug 18, 2019
1 parent ad1d6d6 commit 8ef5d8006c025d0be167318c70f8d209111b13a0
Showing with 2,581 additions and 1,477 deletions.
  1. +1 −0 common/herrors/errors.go
  2. +19 −0 htesting/test_helpers.go
  3. BIN hugolib/assets/images/sunset.jpg
  4. +4 −6 hugolib/pagebundler_test.go
  5. +64 −3 hugolib/resource_chain_test.go
  6. +1 −0 hugolib/testhelpers_test.go
  7. +80 −426 resources/image.go
  8. +28 −35 resources/image_cache.go
  9. +57 −132 resources/image_test.go
  10. +276 −0 resources/images/config.go
  11. +125 −0 resources/images/config_test.go
  12. +170 −0 resources/images/image.go
  13. +7 −9 resources/{ → images}/smartcrop.go
  14. +61 −0 resources/internal/key.go
  15. +36 −0 resources/internal/key_test.go
  16. +352 −475 resources/resource.go
  17. +19 −1 resources/resource/resourcetypes.go
  18. +1 −1 resources/resource_cache.go
  19. +16 −4 resources/resource_metadata.go
  20. +1 −1 resources/resource_metadata_test.go
  21. +304 −0 resources/resource_spec.go
  22. +10 −15 resources/resource_test.go
  23. +80 −0 resources/resource_transformers/htesting/testhelpers.go
  24. +17 −8 resources/resource_transformers/integrity/integrity.go
  25. +24 −0 resources/resource_transformers/integrity/integrity_test.go
  26. +9 −9 resources/resource_transformers/minifier/minify.go
  27. +43 −0 resources/resource_transformers/minifier/minify_test.go
  28. +5 −7 resources/resource_transformers/postcss/postcss.go
  29. +10 −12 resources/resource_transformers/templates/execute_as_template.go
  30. +5 −7 resources/resource_transformers/tocss/scss/client.go
  31. +31 −13 resources/testhelpers_test.go
  32. +297 −291 resources/transform.go
  33. +416 −12 resources/transform_test.go
  34. +12 −10 tpl/resources/resources.go
@@ -52,6 +52,7 @@ func FprintStackTrace(w io.Writer, err error) {
// defer herrors.Recover()
func Recover(args ...interface{}) {
if r := recover(); r != nil {
fmt.Println("ERR:", r)
args = append(args, "stacktrace from panic: \n"+string(debug.Stack()), "\n")
fmt.Println(args...)
}
@@ -14,8 +14,10 @@
package htesting

import (
"math/rand"
"runtime"
"strings"
"time"

"github.com/spf13/afero"
)
@@ -37,3 +39,20 @@ func CreateTempDir(fs afero.Fs, prefix string) (string, func(), error) {
}
return tempDir, func() { fs.RemoveAll(tempDir) }, nil
}

// BailOut panics with a stack trace after the given duration. Useful for
// hanging tests.
func BailOut(after time.Duration) {
time.AfterFunc(after, func() {
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
panic(string(buf))
})

}

var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))

func RandIntn(n int) int {
return rnd.Intn(n)
}
Binary file not shown.
@@ -42,8 +42,7 @@ import (
)

func TestPageBundlerSiteRegular(t *testing.T) {
t.Parallel()

c := qt.New(t)
baseBaseURL := "https://example.com"

for _, baseURLPath := range []string{"", "/hugo"} {
@@ -55,15 +54,14 @@ func TestPageBundlerSiteRegular(t *testing.T) {
}
ugly := ugly
canonify := canonify
t.Run(fmt.Sprintf("ugly=%t,canonify=%t,path=%s", ugly, canonify, baseURLPathId),
func(t *testing.T) {
t.Parallel()
c.Run(fmt.Sprintf("ugly=%t,canonify=%t,path=%s", ugly, canonify, baseURLPathId),
func(c *qt.C) {
c.Parallel()
baseURL := baseBaseURL + baseURLPath
relURLBase := baseURLPath
if canonify {
relURLBase = ""
}
c := qt.New(t)
fs, cfg := newTestBundleSources(t)
cfg.Set("baseURL", baseURL)
cfg.Set("canonifyURLs", canonify)
@@ -14,6 +14,7 @@
package hugolib

import (
"io"
"os"
"path/filepath"
"testing"
@@ -167,6 +168,64 @@ T1: {{ $r.Content }}

}

func TestResourceChainBasic(t *testing.T) {
t.Parallel()

b := newTestSitesBuilder(t)
b.WithTemplatesAdded("index.html", `
{{ $hello := "<h1> Hello World! </h1>" | resources.FromString "hello.html" | fingerprint "sha512" | minify | fingerprint }}
HELLO: {{ $hello.Name }}|{{ $hello.RelPermalink }}|{{ $hello.Content | safeHTML }}
{{ $img := resources.Get "images/sunset.jpg" }}
{{ $fit := $img.Fit "200x200" }}
{{ $fit2 := $fit.Fit "100x200" }}
{{ $img = $img | fingerprint }}
SUNSET: {{ $img.Name }}|{{ $img.RelPermalink }}|{{ $img.Width }}|{{ len $img.Content }}
FIT: {{ $fit.Name }}|{{ $fit.RelPermalink }}|{{ $fit.Width }}
`)

fs := b.Fs.Source

imageDir := filepath.Join("assets", "images")
b.Assert(os.MkdirAll(imageDir, 0777), qt.IsNil)
src, err := os.Open("testdata/sunset.jpg")
b.Assert(err, qt.IsNil)
out, err := fs.Create(filepath.Join(imageDir, "sunset.jpg"))
b.Assert(err, qt.IsNil)
_, err = io.Copy(out, src)
b.Assert(err, qt.IsNil)
out.Close()

b.Running()

for i := 0; i < 2; i++ {

b.Build(BuildCfg{})

b.AssertFileContent("public/index.html",
`
SUNSET: images/sunset.jpg|/images/sunset.jpg|900|90587
FIT: images/sunset.jpg|/images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x200_fit_q75_box.jpg|200
`)

b.EditFiles("page1.md", `
---
title: "Page 1 edit"
summary: "Edited summary"
---
Edited content.
`)

b.Assert(b.Fs.Destination.Remove("public"), qt.IsNil)
b.H.ResourceSpec.ClearCaches()

}
}

func TestResourceChain(t *testing.T) {
t.Parallel()

@@ -353,9 +412,11 @@ Publish 2: {{ $cssPublish2.Permalink }}
"Publish 1: body{color:blue} /external1.min.css",
"Publish 2: http://example.com/external2.min.css",
)
c.Assert(b.CheckExists("public/external2.min.css"), qt.Equals, true)
c.Assert(b.CheckExists("public/external1.min.css"), qt.Equals, true)
c.Assert(b.CheckExists("public/inline.min.css"), qt.Equals, false)
b.Assert(b.CheckExists("public/external2.css"), qt.Equals, false)
b.Assert(b.CheckExists("public/external1.css"), qt.Equals, false)
b.Assert(b.CheckExists("public/external2.min.css"), qt.Equals, true)
b.Assert(b.CheckExists("public/external1.min.css"), qt.Equals, true)
b.Assert(b.CheckExists("public/inline.min.css"), qt.Equals, false)
}},

{"unmarshal", func() bool { return true }, func(b *sitesBuilder) {
@@ -536,6 +536,7 @@ func (s *sitesBuilder) changeEvents() []fsnotify.Event {
}

func (s *sitesBuilder) build(cfg BuildCfg, shouldFail bool) *sitesBuilder {
s.Helper()
defer func() {
s.changedFiles = nil
}()

0 comments on commit 8ef5d80

Please sign in to comment.
You can’t perform that action at this time.