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 #5903
Fixes #6234
Fixes #6266
  • Loading branch information...
bep committed Aug 18, 2019
1 parent 58d4c0a commit f9978ed16476ca6d233a89669c62c798cdf9db9d
Showing with 2,593 additions and 1,475 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. +309 −289 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.a9bf1d944e19c0f382e0d8f51de690f7d0bc8fa97390c4242a86c3e5c0737e71.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 f9978ed

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