mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Prevent resource publishing for transformed inline resources
That is, if only `.Content` is accessed. This means that, for a transformed resource to be published to `/public`, you need to access either `.RelPermalink` or `Permalink`. Fixes #4944
This commit is contained in:
parent
1021714449
commit
43f9df0194
2 changed files with 91 additions and 20 deletions
|
@ -168,6 +168,8 @@ T1: {{ $r.Content }}
|
||||||
func TestResourceChain(t *testing.T) {
|
func TestResourceChain(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := require.New(t)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
shouldRun func() bool
|
shouldRun func() bool
|
||||||
|
@ -199,7 +201,7 @@ T6: {{ $bundle1.Permalink }}
|
||||||
b.AssertFileContent("public/index.html", `T5 RelPermalink: /sass/styles3.css|`)
|
b.AssertFileContent("public/index.html", `T5 RelPermalink: /sass/styles3.css|`)
|
||||||
b.AssertFileContent("public/index.html", `T6: http://example.com/styles/bundle1.css`)
|
b.AssertFileContent("public/index.html", `T6: http://example.com/styles/bundle1.css`)
|
||||||
|
|
||||||
b.AssertFileContent("public/styles/templ.min.css", `.home{color:blue}`)
|
assert.False(b.CheckExists("public/styles/templ.min.css"))
|
||||||
b.AssertFileContent("public/styles/bundle1.css", `.home{color:blue}body{color:#333}`)
|
b.AssertFileContent("public/styles/bundle1.css", `.home{color:blue}body{color:#333}`)
|
||||||
|
|
||||||
}},
|
}},
|
||||||
|
@ -313,6 +315,30 @@ T1: {{ $r1.Permalink }}|{{ $r1.RelPermalink }}
|
||||||
|
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
// https://github.com/gohugoio/hugo/issues/4944
|
||||||
|
{"Prevent resource publish on .Content only", func() bool { return true }, func(b *sitesBuilder) {
|
||||||
|
b.WithTemplates("home.html", `
|
||||||
|
{{ $cssInline := "body { color: green; }" | resources.FromString "inline.css" | minify }}
|
||||||
|
{{ $cssPublish1 := "body { color: blue; }" | resources.FromString "external1.css" | minify }}
|
||||||
|
{{ $cssPublish2 := "body { color: orange; }" | resources.FromString "external2.css" | minify }}
|
||||||
|
|
||||||
|
Inline: {{ $cssInline.Content }}
|
||||||
|
Publish 1: {{ $cssPublish1.Content }} {{ $cssPublish1.RelPermalink }}
|
||||||
|
Publish 2: {{ $cssPublish2.Permalink }}
|
||||||
|
`)
|
||||||
|
|
||||||
|
}, func(b *sitesBuilder) {
|
||||||
|
b.AssertFileContent("public/index.html",
|
||||||
|
`Inline: body{color:green}`,
|
||||||
|
"Publish 1: body{color:blue} /external1.min.css",
|
||||||
|
"Publish 2: http://example.com/external2.min.css",
|
||||||
|
)
|
||||||
|
assert.True(b.CheckExists("public/external2.min.css"), "Referenced content should be copied to /public")
|
||||||
|
assert.True(b.CheckExists("public/external1.min.css"), "Referenced content should be copied to /public")
|
||||||
|
|
||||||
|
assert.False(b.CheckExists("public/inline.min.css"), "Inline content should not be copied to /public")
|
||||||
|
}},
|
||||||
|
|
||||||
{"template", func() bool { return true }, func(b *sitesBuilder) {}, func(b *sitesBuilder) {
|
{"template", func() bool { return true }, func(b *sitesBuilder) {}, func(b *sitesBuilder) {
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,11 @@ type transformedResource struct {
|
||||||
transformInit sync.Once
|
transformInit sync.Once
|
||||||
transformErr error
|
transformErr error
|
||||||
|
|
||||||
|
// We delay publishing until either .RelPermalink or .Permalink
|
||||||
|
// is invoked.
|
||||||
|
publishInit sync.Once
|
||||||
|
published bool
|
||||||
|
|
||||||
// The transformed values
|
// The transformed values
|
||||||
content string
|
content string
|
||||||
contentInit sync.Once
|
contentInit sync.Once
|
||||||
|
@ -220,7 +225,7 @@ func (r *transformedResource) tryTransformedFileCache(key string) io.ReadCloser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *transformedResource) Content() (interface{}, error) {
|
func (r *transformedResource) Content() (interface{}, error) {
|
||||||
if err := r.initTransform(true); err != nil {
|
if err := r.initTransform(true, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := r.initContent(); err != nil {
|
if err := r.initContent(); err != nil {
|
||||||
|
@ -230,14 +235,14 @@ func (r *transformedResource) Content() (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *transformedResource) Data() interface{} {
|
func (r *transformedResource) Data() interface{} {
|
||||||
if err := r.initTransform(false); err != nil {
|
if err := r.initTransform(false, false); err != nil {
|
||||||
return noData
|
return noData
|
||||||
}
|
}
|
||||||
return r.MetaData
|
return r.MetaData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *transformedResource) MediaType() media.Type {
|
func (r *transformedResource) MediaType() media.Type {
|
||||||
if err := r.initTransform(false); err != nil {
|
if err := r.initTransform(false, false); err != nil {
|
||||||
return media.Type{}
|
return media.Type{}
|
||||||
}
|
}
|
||||||
m, _ := r.cache.rs.MediaTypes.GetByType(r.MediaTypeV)
|
m, _ := r.cache.rs.MediaTypes.GetByType(r.MediaTypeV)
|
||||||
|
@ -245,14 +250,14 @@ func (r *transformedResource) MediaType() media.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *transformedResource) Permalink() string {
|
func (r *transformedResource) Permalink() string {
|
||||||
if err := r.initTransform(false); err != nil {
|
if err := r.initTransform(false, true); err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return r.linker.permalinkFor(r.Target)
|
return r.linker.permalinkFor(r.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *transformedResource) RelPermalink() string {
|
func (r *transformedResource) RelPermalink() string {
|
||||||
if err := r.initTransform(false); err != nil {
|
if err := r.initTransform(false, true); err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return r.linker.relPermalinkFor(r.Target)
|
return r.linker.relPermalinkFor(r.Target)
|
||||||
|
@ -271,11 +276,11 @@ func (r *transformedResource) initContent() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *transformedResource) transform(setContent bool) (err error) {
|
func (r *transformedResource) openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error) {
|
||||||
|
return helpers.OpenFilesForWriting(r.cache.rs.PublishFs, r.linker.relTargetPathsFor(relTargetPath)...)
|
||||||
|
}
|
||||||
|
|
||||||
openPublishFileForWriting := func(relTargetPath string) (io.WriteCloser, error) {
|
func (r *transformedResource) transform(setContent, publish bool) (err error) {
|
||||||
return helpers.OpenFilesForWriting(r.cache.rs.PublishFs, r.linker.relTargetPathsFor(relTargetPath)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can be the last resource in a chain.
|
// This can be the last resource in a chain.
|
||||||
// Rewind and create a processing chain.
|
// Rewind and create a processing chain.
|
||||||
|
@ -345,7 +350,7 @@ func (r *transformedResource) transform(setContent bool) (err error) {
|
||||||
|
|
||||||
tctx := &ResourceTransformationCtx{
|
tctx := &ResourceTransformationCtx{
|
||||||
Data: r.transformedResourceMetadata.MetaData,
|
Data: r.transformedResourceMetadata.MetaData,
|
||||||
OpenResourcePublisher: openPublishFileForWriting,
|
OpenResourcePublisher: r.openPublishFileForWriting,
|
||||||
}
|
}
|
||||||
|
|
||||||
tctx.InMediaType = first.MediaType()
|
tctx.InMediaType = first.MediaType()
|
||||||
|
@ -426,14 +431,18 @@ func (r *transformedResource) transform(setContent bool) (err error) {
|
||||||
r.MediaTypeV = tctx.OutMediaType.Type()
|
r.MediaTypeV = tctx.OutMediaType.Type()
|
||||||
}
|
}
|
||||||
|
|
||||||
publicw, err := openPublishFileForWriting(r.Target)
|
var publishwriters []io.WriteCloser
|
||||||
if err != nil {
|
|
||||||
r.transformErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer publicw.Close()
|
|
||||||
|
|
||||||
publishwriters := []io.WriteCloser{publicw}
|
if publish {
|
||||||
|
publicw, err := r.openPublishFileForWriting(r.Target)
|
||||||
|
if err != nil {
|
||||||
|
r.transformErr = err
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer publicw.Close()
|
||||||
|
|
||||||
|
publishwriters = append(publishwriters, publicw)
|
||||||
|
}
|
||||||
|
|
||||||
if transformedContentr == nil {
|
if transformedContentr == nil {
|
||||||
// Also write it to the cache
|
// Also write it to the cache
|
||||||
|
@ -474,13 +483,49 @@ func (r *transformedResource) transform(setContent bool) (err error) {
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
func (r *transformedResource) initTransform(setContent bool) error {
|
func (r *transformedResource) initTransform(setContent, publish bool) error {
|
||||||
r.transformInit.Do(func() {
|
r.transformInit.Do(func() {
|
||||||
if err := r.transform(setContent); err != nil {
|
r.published = publish
|
||||||
|
if err := r.transform(setContent, publish); err != nil {
|
||||||
r.transformErr = err
|
r.transformErr = err
|
||||||
r.cache.rs.Logger.ERROR.Println("error: failed to transform resource:", err)
|
r.cache.rs.Logger.ERROR.Println("error: failed to transform resource:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if !publish {
|
||||||
|
return r.transformErr
|
||||||
|
}
|
||||||
|
|
||||||
|
r.publishInit.Do(func() {
|
||||||
|
if r.published {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r.published = true
|
||||||
|
|
||||||
|
// Copy the file from cache to /public
|
||||||
|
_, src, err := r.cache.fileCache.Get(r.sourceFilename)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
var dst io.WriteCloser
|
||||||
|
dst, err = r.openPublishFileForWriting(r.Target)
|
||||||
|
if err == nil {
|
||||||
|
defer dst.Close()
|
||||||
|
io.Copy(dst, src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
r.transformErr = err
|
||||||
|
r.cache.rs.Logger.ERROR.Println("error: failed to publish resource:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
return r.transformErr
|
return r.transformErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue