resources: Move resource interfaces into its own package
8
deps/deps.go
vendored
|
@ -16,7 +16,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
"github.com/gohugoio/hugo/metrics"
|
"github.com/gohugoio/hugo/metrics"
|
||||||
"github.com/gohugoio/hugo/output"
|
"github.com/gohugoio/hugo/output"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
"github.com/gohugoio/hugo/source"
|
"github.com/gohugoio/hugo/source"
|
||||||
"github.com/gohugoio/hugo/tpl"
|
"github.com/gohugoio/hugo/tpl"
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
|
@ -52,7 +52,7 @@ type Deps struct {
|
||||||
SourceSpec *source.SourceSpec `json:"-"`
|
SourceSpec *source.SourceSpec `json:"-"`
|
||||||
|
|
||||||
// The Resource Spec to use
|
// The Resource Spec to use
|
||||||
ResourceSpec *resource.Spec
|
ResourceSpec *resources.Spec
|
||||||
|
|
||||||
// The configuration to use
|
// The configuration to use
|
||||||
Cfg config.Provider `json:"-"`
|
Cfg config.Provider `json:"-"`
|
||||||
|
@ -214,7 +214,7 @@ func New(cfg DepsCfg) (*Deps, error) {
|
||||||
return nil, errors.WithMessage(err, "failed to create file caches from configuration")
|
return nil, errors.WithMessage(err, "failed to create file caches from configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceSpec, err := resource.NewSpec(ps, fileCaches, logger, cfg.OutputFormats, cfg.MediaTypes)
|
resourceSpec, err := resources.NewSpec(ps, fileCaches, logger, cfg.OutputFormats, cfg.MediaTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ func (d Deps) ForLanguage(cfg DepsCfg, onCreated func(d *Deps) error) (*Deps, er
|
||||||
// The resource cache is global so reuse.
|
// The resource cache is global so reuse.
|
||||||
// TODO(bep) clean up these inits.
|
// TODO(bep) clean up these inits.
|
||||||
resourceCache := d.ResourceSpec.ResourceCache
|
resourceCache := d.ResourceSpec.ResourceCache
|
||||||
d.ResourceSpec, err = resource.NewSpec(d.PathSpec, d.ResourceSpec.FileCaches, d.Log, cfg.OutputFormats, cfg.MediaTypes)
|
d.ResourceSpec, err = resources.NewSpec(d.PathSpec, d.ResourceSpec.FileCaches, d.Log, cfg.OutputFormats, cfg.MediaTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ package hugolib
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/collections"
|
"github.com/gohugoio/hugo/common/collections"
|
||||||
)
|
)
|
||||||
|
|
|
@ -35,7 +35,7 @@ import (
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/hugolib/pagemeta"
|
"github.com/gohugoio/hugo/hugolib/pagemeta"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/output"
|
"github.com/gohugoio/hugo/output"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/tpl"
|
"github.com/gohugoio/hugo/tpl"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
package hugolib
|
package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -22,7 +22,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -255,7 +256,7 @@ func (c *contentHandlers) parsePage(h contentHandler) contentHandler {
|
||||||
|
|
||||||
// Assign metadata from front matter if set
|
// Assign metadata from front matter if set
|
||||||
if len(p.resourcesMetadata) > 0 {
|
if len(p.resourcesMetadata) > 0 {
|
||||||
resource.AssignMetadata(p.resourcesMetadata, p.Resources...)
|
resources.AssignMetadata(p.resourcesMetadata, p.Resources...)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -309,7 +310,7 @@ func (c *contentHandlers) createResource() contentHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource, err := c.s.ResourceSpec.New(
|
resource, err := c.s.ResourceSpec.New(
|
||||||
resource.ResourceSourceDescriptor{
|
resources.ResourceSourceDescriptor{
|
||||||
TargetPathBuilder: ctx.parentPage.subResourceTargetPathFactory,
|
TargetPathBuilder: ctx.parentPage.subResourceTargetPathFactory,
|
||||||
SourceFile: ctx.source,
|
SourceFile: ctx.source,
|
||||||
RelTargetFilename: ctx.target,
|
RelTargetFilename: ctx.target,
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/hugofs"
|
"github.com/gohugoio/hugo/hugofs"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/loggers"
|
"github.com/gohugoio/hugo/common/loggers"
|
||||||
"github.com/gohugoio/hugo/resource/resource_transformers/tocss/scss"
|
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSCSSWithIncludePaths(t *testing.T) {
|
func TestSCSSWithIncludePaths(t *testing.T) {
|
||||||
|
|
|
@ -39,7 +39,6 @@ import (
|
||||||
"github.com/gohugoio/hugo/common/hugo"
|
"github.com/gohugoio/hugo/common/hugo"
|
||||||
"github.com/gohugoio/hugo/common/maps"
|
"github.com/gohugoio/hugo/common/maps"
|
||||||
"github.com/gohugoio/hugo/publisher"
|
"github.com/gohugoio/hugo/publisher"
|
||||||
"github.com/gohugoio/hugo/resource"
|
|
||||||
_errors "github.com/pkg/errors"
|
_errors "github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/langs"
|
"github.com/gohugoio/hugo/langs"
|
||||||
|
@ -62,6 +61,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/hugolib/pagemeta"
|
"github.com/gohugoio/hugo/hugolib/pagemeta"
|
||||||
"github.com/gohugoio/hugo/output"
|
"github.com/gohugoio/hugo/output"
|
||||||
"github.com/gohugoio/hugo/related"
|
"github.com/gohugoio/hugo/related"
|
||||||
|
"github.com/gohugoio/hugo/resources"
|
||||||
"github.com/gohugoio/hugo/source"
|
"github.com/gohugoio/hugo/source"
|
||||||
"github.com/gohugoio/hugo/tpl"
|
"github.com/gohugoio/hugo/tpl"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
@ -760,7 +760,7 @@ func (s *Site) processPartial(events []fsnotify.Event) (whatChanged, error) {
|
||||||
cachePartitions := make([]string, len(events))
|
cachePartitions := make([]string, len(events))
|
||||||
|
|
||||||
for i, ev := range events {
|
for i, ev := range events {
|
||||||
cachePartitions[i] = resource.ResourceKeyPartition(ev.Name)
|
cachePartitions[i] = resources.ResourceKeyPartition(ev.Name)
|
||||||
|
|
||||||
if s.isContentDirEvent(ev) {
|
if s.isContentDirEvent(ev) {
|
||||||
logger.Println("Source changed", ev)
|
logger.Println("Source changed", ev)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -27,6 +27,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
_errors "github.com/pkg/errors"
|
_errors "github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/disintegration/imaging"
|
"github.com/disintegration/imaging"
|
||||||
|
@ -43,9 +45,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ Resource = (*Image)(nil)
|
_ resource.Resource = (*Image)(nil)
|
||||||
_ Source = (*Image)(nil)
|
_ resource.Source = (*Image)(nil)
|
||||||
_ Cloner = (*Image)(nil)
|
_ resource.Cloner = (*Image)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Imaging contains default image processing configuration. This will be fetched
|
// Imaging contains default image processing configuration. This will be fetched
|
||||||
|
@ -146,7 +148,7 @@ func (i *Image) Height() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithNewBase implements the Cloner interface.
|
// WithNewBase implements the Cloner interface.
|
||||||
func (i *Image) WithNewBase(base string) Resource {
|
func (i *Image) WithNewBase(base string) resource.Resource {
|
||||||
return &Image{
|
return &Image{
|
||||||
imaging: i.imaging,
|
imaging: i.imaging,
|
||||||
format: i.format,
|
format: i.format,
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
48
resources/internal/glob.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright 2019 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.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gobwas/glob"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
globCache = make(map[string]glob.Glob)
|
||||||
|
globMu sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetGlob(pattern string) (glob.Glob, error) {
|
||||||
|
var g glob.Glob
|
||||||
|
|
||||||
|
globMu.RLock()
|
||||||
|
g, found := globCache[pattern]
|
||||||
|
globMu.RUnlock()
|
||||||
|
if !found {
|
||||||
|
var err error
|
||||||
|
g, err = glob.Compile(strings.ToLower(pattern), '/')
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
globMu.Lock()
|
||||||
|
globCache[pattern] = g
|
||||||
|
globMu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return g, nil
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -24,6 +24,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/media"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/output"
|
"github.com/gohugoio/hugo/output"
|
||||||
"github.com/gohugoio/hugo/tpl"
|
"github.com/gohugoio/hugo/tpl"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -32,35 +34,28 @@ import (
|
||||||
"github.com/gohugoio/hugo/common/collections"
|
"github.com/gohugoio/hugo/common/collections"
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
"github.com/gohugoio/hugo/common/loggers"
|
"github.com/gohugoio/hugo/common/loggers"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
"github.com/gobwas/glob"
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/media"
|
|
||||||
"github.com/gohugoio/hugo/source"
|
"github.com/gohugoio/hugo/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ ContentResource = (*genericResource)(nil)
|
_ resource.ContentResource = (*genericResource)(nil)
|
||||||
_ ReadSeekCloserResource = (*genericResource)(nil)
|
_ resource.ReadSeekCloserResource = (*genericResource)(nil)
|
||||||
_ Resource = (*genericResource)(nil)
|
_ resource.Resource = (*genericResource)(nil)
|
||||||
_ Source = (*genericResource)(nil)
|
_ resource.Source = (*genericResource)(nil)
|
||||||
_ Cloner = (*genericResource)(nil)
|
_ resource.Cloner = (*genericResource)(nil)
|
||||||
_ ResourcesLanguageMerger = (*Resources)(nil)
|
_ resource.ResourcesLanguageMerger = (*resource.Resources)(nil)
|
||||||
_ permalinker = (*genericResource)(nil)
|
_ permalinker = (*genericResource)(nil)
|
||||||
_ collections.Slicer = (*genericResource)(nil)
|
_ collections.Slicer = (*genericResource)(nil)
|
||||||
_ Identifier = (*genericResource)(nil)
|
_ resource.Identifier = (*genericResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
var noData = make(map[string]interface{})
|
var noData = make(map[string]interface{})
|
||||||
|
|
||||||
// Source is an internal template and not meant for use in the templates. It
|
|
||||||
// may change without notice.
|
|
||||||
type Source interface {
|
|
||||||
Publish() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type permalinker interface {
|
type permalinker interface {
|
||||||
relPermalinkFor(target string) string
|
relPermalinkFor(target string) string
|
||||||
permalinkFor(target string) string
|
permalinkFor(target string) string
|
||||||
|
@ -69,215 +64,6 @@ type permalinker interface {
|
||||||
targetPath() string
|
targetPath() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cloner is an internal template and not meant for use in the templates. It
|
|
||||||
// may change without notice.
|
|
||||||
type Cloner interface {
|
|
||||||
WithNewBase(base string) Resource
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resource represents a linkable resource, i.e. a content page, image etc.
|
|
||||||
type Resource interface {
|
|
||||||
resourceBase
|
|
||||||
|
|
||||||
// Permalink represents the absolute link to this resource.
|
|
||||||
Permalink() string
|
|
||||||
|
|
||||||
// RelPermalink represents the host relative link to this resource.
|
|
||||||
RelPermalink() string
|
|
||||||
|
|
||||||
// ResourceType is the resource type. For most file types, this is the main
|
|
||||||
// part of the MIME type, e.g. "image", "application", "text" etc.
|
|
||||||
// For content pages, this value is "page".
|
|
||||||
ResourceType() string
|
|
||||||
|
|
||||||
// Name is the logical name of this resource. This can be set in the front matter
|
|
||||||
// metadata for this resource. If not set, Hugo will assign a value.
|
|
||||||
// This will in most cases be the base filename.
|
|
||||||
// So, for the image "/some/path/sunset.jpg" this will be "sunset.jpg".
|
|
||||||
// The value returned by this method will be used in the GetByPrefix and ByPrefix methods
|
|
||||||
// on Resources.
|
|
||||||
Name() string
|
|
||||||
|
|
||||||
// Title returns the title if set in front matter. For content pages, this will be the expected value.
|
|
||||||
Title() string
|
|
||||||
|
|
||||||
// Resource specific data set by Hugo.
|
|
||||||
// One example would be.Data.Digest for fingerprinted resources.
|
|
||||||
Data() interface{}
|
|
||||||
|
|
||||||
// Params set in front matter for this resource.
|
|
||||||
Params() map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resourceBase pulls out the minimal set of operations to define a Resource,
|
|
||||||
// to simplify testing etc.
|
|
||||||
type resourceBase interface {
|
|
||||||
// MediaType is this resource's MIME type.
|
|
||||||
MediaType() media.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResourcesLanguageMerger describes an interface for merging resources from a
|
|
||||||
// different language.
|
|
||||||
type ResourcesLanguageMerger interface {
|
|
||||||
MergeByLanguage(other Resources) Resources
|
|
||||||
// Needed for integration with the tpl package.
|
|
||||||
MergeByLanguageInterface(other interface{}) (interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type translatedResource interface {
|
|
||||||
TranslationKey() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identifier identifies a resource.
|
|
||||||
type Identifier interface {
|
|
||||||
Key() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContentResource represents a Resource that provides a way to get to its content.
|
|
||||||
// Most Resource types in Hugo implements this interface, including Page.
|
|
||||||
// This should be used with care, as it will read the file content into memory, but it
|
|
||||||
// should be cached as effectively as possible by the implementation.
|
|
||||||
type ContentResource interface {
|
|
||||||
resourceBase
|
|
||||||
|
|
||||||
// Content returns this resource's content. It will be equivalent to reading the content
|
|
||||||
// that RelPermalink points to in the published folder.
|
|
||||||
// The return type will be contextual, and should be what you would expect:
|
|
||||||
// * Page: template.HTML
|
|
||||||
// * JSON: String
|
|
||||||
// * Etc.
|
|
||||||
Content() (interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenReadSeekCloser allows setting some other way (than reading from a filesystem)
|
|
||||||
// to open or create a ReadSeekCloser.
|
|
||||||
type OpenReadSeekCloser func() (hugio.ReadSeekCloser, error)
|
|
||||||
|
|
||||||
// ReadSeekCloserResource is a Resource that supports loading its content.
|
|
||||||
type ReadSeekCloserResource interface {
|
|
||||||
resourceBase
|
|
||||||
ReadSeekCloser() (hugio.ReadSeekCloser, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resources represents a slice of resources, which can be a mix of different types.
|
|
||||||
// I.e. both pages and images etc.
|
|
||||||
type Resources []Resource
|
|
||||||
|
|
||||||
// ResourcesConverter converts a given slice of Resource objects to Resources.
|
|
||||||
type ResourcesConverter interface {
|
|
||||||
ToResources() Resources
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByType returns resources of a given resource type (ie. "image").
|
|
||||||
func (r Resources) ByType(tp string) Resources {
|
|
||||||
var filtered Resources
|
|
||||||
|
|
||||||
for _, resource := range r {
|
|
||||||
if resource.ResourceType() == tp {
|
|
||||||
filtered = append(filtered, resource)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filtered
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMatch finds the first Resource matching the given pattern, or nil if none found.
|
|
||||||
// See Match for a more complete explanation about the rules used.
|
|
||||||
func (r Resources) GetMatch(pattern string) Resource {
|
|
||||||
g, err := getGlob(pattern)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, resource := range r {
|
|
||||||
if g.Match(strings.ToLower(resource.Name())) {
|
|
||||||
return resource
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match gets all resources matching the given base filename prefix, e.g
|
|
||||||
// "*.png" will match all png files. The "*" does not match path delimiters (/),
|
|
||||||
// so if you organize your resources in sub-folders, you need to be explicit about it, e.g.:
|
|
||||||
// "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and
|
|
||||||
// to match all PNG images below the images folder, use "images/**.jpg".
|
|
||||||
// The matching is case insensitive.
|
|
||||||
// Match matches by using the value of Resource.Name, which, by default, is a filename with
|
|
||||||
// path relative to the bundle root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png".
|
|
||||||
// See https://github.com/gobwas/glob for the full rules set.
|
|
||||||
func (r Resources) Match(pattern string) Resources {
|
|
||||||
g, err := getGlob(pattern)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var matches Resources
|
|
||||||
for _, resource := range r {
|
|
||||||
if g.Match(strings.ToLower(resource.Name())) {
|
|
||||||
matches = append(matches, resource)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matches
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
globCache = make(map[string]glob.Glob)
|
|
||||||
globMu sync.RWMutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func getGlob(pattern string) (glob.Glob, error) {
|
|
||||||
var g glob.Glob
|
|
||||||
|
|
||||||
globMu.RLock()
|
|
||||||
g, found := globCache[pattern]
|
|
||||||
globMu.RUnlock()
|
|
||||||
if !found {
|
|
||||||
var err error
|
|
||||||
g, err = glob.Compile(strings.ToLower(pattern), '/')
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
globMu.Lock()
|
|
||||||
globCache[pattern] = g
|
|
||||||
globMu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
return g, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MergeByLanguage adds missing translations in r1 from r2.
|
|
||||||
func (r Resources) MergeByLanguage(r2 Resources) Resources {
|
|
||||||
result := append(Resources(nil), r...)
|
|
||||||
m := make(map[string]bool)
|
|
||||||
for _, rr := range r {
|
|
||||||
if translated, ok := rr.(translatedResource); ok {
|
|
||||||
m[translated.TranslationKey()] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rr := range r2 {
|
|
||||||
if translated, ok := rr.(translatedResource); ok {
|
|
||||||
if _, found := m[translated.TranslationKey()]; !found {
|
|
||||||
result = append(result, rr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// MergeByLanguageInterface is the generic version of MergeByLanguage. It
|
|
||||||
// is here just so it can be called from the tpl package.
|
|
||||||
func (r Resources) MergeByLanguageInterface(in interface{}) (interface{}, error) {
|
|
||||||
r2, ok := in.(Resources)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("%T cannot be merged by language", in)
|
|
||||||
}
|
|
||||||
return r.MergeByLanguage(r2), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Spec struct {
|
type Spec struct {
|
||||||
*helpers.PathSpec
|
*helpers.PathSpec
|
||||||
|
|
||||||
|
@ -336,7 +122,7 @@ type ResourceSourceDescriptor struct {
|
||||||
|
|
||||||
// Need one of these to load the resource content.
|
// Need one of these to load the resource content.
|
||||||
SourceFile source.File
|
SourceFile source.File
|
||||||
OpenReadSeekCloser OpenReadSeekCloser
|
OpenReadSeekCloser resource.OpenReadSeekCloser
|
||||||
|
|
||||||
// If OpenReadSeekerCloser is not set, we use this to open the file.
|
// If OpenReadSeekerCloser is not set, we use this to open the file.
|
||||||
SourceFilename string
|
SourceFilename string
|
||||||
|
@ -370,15 +156,15 @@ func (r *Spec) sourceFs() afero.Fs {
|
||||||
return r.PathSpec.BaseFs.Content.Fs
|
return r.PathSpec.BaseFs.Content.Fs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Spec) New(fd ResourceSourceDescriptor) (Resource, error) {
|
func (r *Spec) New(fd ResourceSourceDescriptor) (resource.Resource, error) {
|
||||||
return r.newResourceForFs(r.sourceFs(), fd)
|
return r.newResourceForFs(r.sourceFs(), fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Spec) NewForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (Resource, error) {
|
func (r *Spec) NewForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (resource.Resource, error) {
|
||||||
return r.newResourceForFs(sourceFs, fd)
|
return r.newResourceForFs(sourceFs, fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Spec) newResourceForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (Resource, error) {
|
func (r *Spec) newResourceForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (resource.Resource, error) {
|
||||||
if fd.OpenReadSeekCloser == nil {
|
if fd.OpenReadSeekCloser == nil {
|
||||||
if fd.SourceFile != nil && fd.SourceFilename != "" {
|
if fd.SourceFile != nil && fd.SourceFilename != "" {
|
||||||
return nil, errors.New("both SourceFile and AbsSourceFilename provided")
|
return nil, errors.New("both SourceFile and AbsSourceFilename provided")
|
||||||
|
@ -399,7 +185,7 @@ func (r *Spec) newResourceForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor)
|
||||||
return r.newResource(sourceFs, fd)
|
return r.newResource(sourceFs, fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Spec) newResource(sourceFs afero.Fs, fd ResourceSourceDescriptor) (Resource, error) {
|
func (r *Spec) newResource(sourceFs afero.Fs, fd ResourceSourceDescriptor) (resource.Resource, error) {
|
||||||
var fi os.FileInfo
|
var fi os.FileInfo
|
||||||
var sourceFilename string
|
var sourceFilename string
|
||||||
|
|
||||||
|
@ -551,7 +337,7 @@ type publishOnce struct {
|
||||||
logger *loggers.Logger
|
logger *loggers.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *publishOnce) publish(s Source) error {
|
func (l *publishOnce) publish(s resource.Source) error {
|
||||||
l.publisherInit.Do(func() {
|
l.publisherInit.Do(func() {
|
||||||
l.publisherErr = s.Publish()
|
l.publisherErr = s.Publish()
|
||||||
if l.publisherErr != nil {
|
if l.publisherErr != nil {
|
||||||
|
@ -577,7 +363,7 @@ type genericResource struct {
|
||||||
sourceFilename string
|
sourceFilename string
|
||||||
|
|
||||||
// Will be set if this resource is backed by something other than a file.
|
// Will be set if this resource is backed by something other than a file.
|
||||||
openReadSeekerCloser OpenReadSeekCloser
|
openReadSeekerCloser resource.OpenReadSeekCloser
|
||||||
|
|
||||||
// A hash of the source content. Is only calculated in caching situations.
|
// A hash of the source content. Is only calculated in caching situations.
|
||||||
*resourceHash
|
*resourceHash
|
||||||
|
@ -632,7 +418,7 @@ func (l *genericResource) MediaType() media.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement the Cloner interface.
|
// Implement the Cloner interface.
|
||||||
func (l genericResource) WithNewBase(base string) Resource {
|
func (l genericResource) WithNewBase(base string) resource.Resource {
|
||||||
l.baseOffset = base
|
l.baseOffset = base
|
||||||
l.resourceContent = &resourceContent{}
|
l.resourceContent = &resourceContent{}
|
||||||
return &l
|
return &l
|
||||||
|
@ -642,12 +428,12 @@ func (l genericResource) WithNewBase(base string) Resource {
|
||||||
// for the template functions. See collections.Slice.
|
// for the template functions. See collections.Slice.
|
||||||
func (commonResource) Slice(in interface{}) (interface{}, error) {
|
func (commonResource) Slice(in interface{}) (interface{}, error) {
|
||||||
switch items := in.(type) {
|
switch items := in.(type) {
|
||||||
case Resources:
|
case resource.Resources:
|
||||||
return items, nil
|
return items, nil
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
groups := make(Resources, len(items))
|
groups := make(resource.Resources, len(items))
|
||||||
for i, v := range items {
|
for i, v := range items {
|
||||||
g, ok := v.(Resource)
|
g, ok := v.(resource.Resource)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("type %T is not a Resource", v)
|
return nil, fmt.Errorf("type %T is not a Resource", v)
|
||||||
}
|
}
|
||||||
|
@ -903,7 +689,7 @@ func (r *Spec) newGenericResource(sourceFs afero.Fs,
|
||||||
func (r *Spec) newGenericResourceWithBase(
|
func (r *Spec) newGenericResourceWithBase(
|
||||||
sourceFs afero.Fs,
|
sourceFs afero.Fs,
|
||||||
lazyPublish bool,
|
lazyPublish bool,
|
||||||
openReadSeekerCloser OpenReadSeekCloser,
|
openReadSeekerCloser resource.OpenReadSeekCloser,
|
||||||
urlBaseDir string,
|
urlBaseDir string,
|
||||||
targetPathBaseDirs []string,
|
targetPathBaseDirs []string,
|
||||||
targetPathBuilder func(base string) string,
|
targetPathBuilder func(base string) string,
|
123
resources/resource/resources.go
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
// Copyright 2019 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.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/resources/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Resources represents a slice of resources, which can be a mix of different types.
|
||||||
|
// I.e. both pages and images etc.
|
||||||
|
type Resources []Resource
|
||||||
|
|
||||||
|
// ResourcesConverter converts a given slice of Resource objects to Resources.
|
||||||
|
type ResourcesConverter interface {
|
||||||
|
ToResources() Resources
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByType returns resources of a given resource type (ie. "image").
|
||||||
|
func (r Resources) ByType(tp string) Resources {
|
||||||
|
var filtered Resources
|
||||||
|
|
||||||
|
for _, resource := range r {
|
||||||
|
if resource.ResourceType() == tp {
|
||||||
|
filtered = append(filtered, resource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMatch finds the first Resource matching the given pattern, or nil if none found.
|
||||||
|
// See Match for a more complete explanation about the rules used.
|
||||||
|
func (r Resources) GetMatch(pattern string) Resource {
|
||||||
|
g, err := internal.GetGlob(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, resource := range r {
|
||||||
|
if g.Match(strings.ToLower(resource.Name())) {
|
||||||
|
return resource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match gets all resources matching the given base filename prefix, e.g
|
||||||
|
// "*.png" will match all png files. The "*" does not match path delimiters (/),
|
||||||
|
// so if you organize your resources in sub-folders, you need to be explicit about it, e.g.:
|
||||||
|
// "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and
|
||||||
|
// to match all PNG images below the images folder, use "images/**.jpg".
|
||||||
|
// The matching is case insensitive.
|
||||||
|
// Match matches by using the value of Resource.Name, which, by default, is a filename with
|
||||||
|
// path relative to the bundle root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png".
|
||||||
|
// See https://github.com/gobwas/glob for the full rules set.
|
||||||
|
func (r Resources) Match(pattern string) Resources {
|
||||||
|
g, err := internal.GetGlob(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var matches Resources
|
||||||
|
for _, resource := range r {
|
||||||
|
if g.Match(strings.ToLower(resource.Name())) {
|
||||||
|
matches = append(matches, resource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|
||||||
|
type translatedResource interface {
|
||||||
|
TranslationKey() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeByLanguage adds missing translations in r1 from r2.
|
||||||
|
func (r Resources) MergeByLanguage(r2 Resources) Resources {
|
||||||
|
result := append(Resources(nil), r...)
|
||||||
|
m := make(map[string]bool)
|
||||||
|
for _, rr := range r {
|
||||||
|
if translated, ok := rr.(translatedResource); ok {
|
||||||
|
m[translated.TranslationKey()] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rr := range r2 {
|
||||||
|
if translated, ok := rr.(translatedResource); ok {
|
||||||
|
if _, found := m[translated.TranslationKey()]; !found {
|
||||||
|
result = append(result, rr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeByLanguageInterface is the generic version of MergeByLanguage. It
|
||||||
|
// is here just so it can be called from the tpl package.
|
||||||
|
func (r Resources) MergeByLanguageInterface(in interface{}) (interface{}, error) {
|
||||||
|
r2, ok := in.(Resources)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%T cannot be merged by language", in)
|
||||||
|
}
|
||||||
|
return r.MergeByLanguage(r2), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source is an internal template and not meant for use in the templates. It
|
||||||
|
// may change without notice.
|
||||||
|
type Source interface {
|
||||||
|
Publish() error
|
||||||
|
}
|
106
resources/resource/resourcetypes.go
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright 2019 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.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gohugoio/hugo/media"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cloner is an internal template and not meant for use in the templates. It
|
||||||
|
// may change without notice.
|
||||||
|
type Cloner interface {
|
||||||
|
WithNewBase(base string) Resource
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resource represents a linkable resource, i.e. a content page, image etc.
|
||||||
|
type Resource interface {
|
||||||
|
resourceBase
|
||||||
|
|
||||||
|
// Permalink represents the absolute link to this resource.
|
||||||
|
Permalink() string
|
||||||
|
|
||||||
|
// RelPermalink represents the host relative link to this resource.
|
||||||
|
RelPermalink() string
|
||||||
|
|
||||||
|
// ResourceType is the resource type. For most file types, this is the main
|
||||||
|
// part of the MIME type, e.g. "image", "application", "text" etc.
|
||||||
|
// For content pages, this value is "page".
|
||||||
|
ResourceType() string
|
||||||
|
|
||||||
|
// Name is the logical name of this resource. This can be set in the front matter
|
||||||
|
// metadata for this resource. If not set, Hugo will assign a value.
|
||||||
|
// This will in most cases be the base filename.
|
||||||
|
// So, for the image "/some/path/sunset.jpg" this will be "sunset.jpg".
|
||||||
|
// The value returned by this method will be used in the GetByPrefix and ByPrefix methods
|
||||||
|
// on Resources.
|
||||||
|
Name() string
|
||||||
|
|
||||||
|
// Title returns the title if set in front matter. For content pages, this will be the expected value.
|
||||||
|
Title() string
|
||||||
|
|
||||||
|
// Resource specific data set by Hugo.
|
||||||
|
// One example would be.Data.Digest for fingerprinted resources.
|
||||||
|
Data() interface{}
|
||||||
|
|
||||||
|
// Params set in front matter for this resource.
|
||||||
|
Params() map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resourceBase pulls out the minimal set of operations to define a Resource,
|
||||||
|
// to simplify testing etc.
|
||||||
|
type resourceBase interface {
|
||||||
|
// MediaType is this resource's MIME type.
|
||||||
|
MediaType() media.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourcesLanguageMerger describes an interface for merging resources from a
|
||||||
|
// different language.
|
||||||
|
type ResourcesLanguageMerger interface {
|
||||||
|
MergeByLanguage(other Resources) Resources
|
||||||
|
// Needed for integration with the tpl package.
|
||||||
|
MergeByLanguageInterface(other interface{}) (interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identifier identifies a resource.
|
||||||
|
type Identifier interface {
|
||||||
|
Key() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentResource represents a Resource that provides a way to get to its content.
|
||||||
|
// Most Resource types in Hugo implements this interface, including Page.
|
||||||
|
// This should be used with care, as it will read the file content into memory, but it
|
||||||
|
// should be cached as effectively as possible by the implementation.
|
||||||
|
type ContentResource interface {
|
||||||
|
resourceBase
|
||||||
|
|
||||||
|
// Content returns this resource's content. It will be equivalent to reading the content
|
||||||
|
// that RelPermalink points to in the published folder.
|
||||||
|
// The return type will be contextual, and should be what you would expect:
|
||||||
|
// * Page: template.HTML
|
||||||
|
// * JSON: String
|
||||||
|
// * Etc.
|
||||||
|
Content() (interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenReadSeekCloser allows setting some other way (than reading from a filesystem)
|
||||||
|
// to open or create a ReadSeekCloser.
|
||||||
|
type OpenReadSeekCloser func() (hugio.ReadSeekCloser, error)
|
||||||
|
|
||||||
|
// ReadSeekCloserResource is a Resource that supports loading its content.
|
||||||
|
type ReadSeekCloserResource interface {
|
||||||
|
resourceBase
|
||||||
|
ReadSeekCloser() (hugio.ReadSeekCloser, error)
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -21,6 +21,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/cache/filecache"
|
"github.com/gohugoio/hugo/cache/filecache"
|
||||||
|
|
||||||
"github.com/BurntSushi/locker"
|
"github.com/BurntSushi/locker"
|
||||||
|
@ -35,7 +37,7 @@ type ResourceCache struct {
|
||||||
rs *Spec
|
rs *Spec
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
cache map[string]Resource
|
cache map[string]resource.Resource
|
||||||
|
|
||||||
fileCache *filecache.Cache
|
fileCache *filecache.Cache
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ func newResourceCache(rs *Spec) *ResourceCache {
|
||||||
return &ResourceCache{
|
return &ResourceCache{
|
||||||
rs: rs,
|
rs: rs,
|
||||||
fileCache: rs.FileCaches.AssetsCache(),
|
fileCache: rs.FileCaches.AssetsCache(),
|
||||||
cache: make(map[string]Resource),
|
cache: make(map[string]resource.Resource),
|
||||||
nlocker: locker.NewLocker(),
|
nlocker: locker.NewLocker(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +70,7 @@ func (c *ResourceCache) clear() {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
|
||||||
c.cache = make(map[string]Resource)
|
c.cache = make(map[string]resource.Resource)
|
||||||
c.nlocker = locker.NewLocker()
|
c.nlocker = locker.NewLocker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,14 +84,14 @@ func (c *ResourceCache) cleanKey(key string) string {
|
||||||
return strings.TrimPrefix(path.Clean(key), "/")
|
return strings.TrimPrefix(path.Clean(key), "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ResourceCache) get(key string) (Resource, bool) {
|
func (c *ResourceCache) get(key string) (resource.Resource, bool) {
|
||||||
c.RLock()
|
c.RLock()
|
||||||
defer c.RUnlock()
|
defer c.RUnlock()
|
||||||
r, found := c.cache[key]
|
r, found := c.cache[key]
|
||||||
return r, found
|
return r, found
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ResourceCache) GetOrCreate(partition, key string, f func() (Resource, error)) (Resource, error) {
|
func (c *ResourceCache) GetOrCreate(partition, key string, f func() (resource.Resource, error)) (resource.Resource, error) {
|
||||||
key = c.cleanKey(path.Join(partition, key))
|
key = c.cleanKey(path.Join(partition, key))
|
||||||
// First check in-memory cache.
|
// First check in-memory cache.
|
||||||
r, found := c.get(key)
|
r, found := c.get(key)
|
||||||
|
@ -172,7 +174,7 @@ func (c *ResourceCache) writeMeta(key string, meta transformedResourceMetadata)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ResourceCache) set(key string, r Resource) {
|
func (c *ResourceCache) set(key string, r resource.Resource) {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
c.cache[key] = r
|
c.cache[key] = r
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -21,17 +21,18 @@ import (
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client contains methods perform concatenation and other bundling related
|
// Client contains methods perform concatenation and other bundling related
|
||||||
// tasks to Resource objects.
|
// tasks to Resource objects.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Client with the given specification.
|
// New creates a new Client with the given specification.
|
||||||
func New(rs *resource.Spec) *Client {
|
func New(rs *resources.Spec) *Client {
|
||||||
return &Client{rs: rs}
|
return &Client{rs: rs}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,14 +63,14 @@ func (r *multiReadSeekCloser) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concat concatenates the list of Resource objects.
|
// Concat concatenates the list of Resource objects.
|
||||||
func (c *Client) Concat(targetPath string, resources resource.Resources) (resource.Resource, error) {
|
func (c *Client) Concat(targetPath string, r resource.Resources) (resource.Resource, error) {
|
||||||
// The CACHE_OTHER will make sure this will be re-created and published on rebuilds.
|
// The CACHE_OTHER will make sure this will be re-created and published on rebuilds.
|
||||||
return c.rs.ResourceCache.GetOrCreate(resource.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
|
return c.rs.ResourceCache.GetOrCreate(resources.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
|
||||||
var resolvedm media.Type
|
var resolvedm media.Type
|
||||||
|
|
||||||
// The given set of resources must be of the same Media Type.
|
// The given set of resources must be of the same Media Type.
|
||||||
// We may improve on that in the future, but then we need to know more.
|
// We may improve on that in the future, but then we need to know more.
|
||||||
for i, r := range resources {
|
for i, r := range r {
|
||||||
if i > 0 && r.MediaType().Type() != resolvedm.Type() {
|
if i > 0 && r.MediaType().Type() != resolvedm.Type() {
|
||||||
return nil, fmt.Errorf("resources in Concat must be of the same Media Type, got %q and %q", r.MediaType().Type(), resolvedm.Type())
|
return nil, fmt.Errorf("resources in Concat must be of the same Media Type, got %q and %q", r.MediaType().Type(), resolvedm.Type())
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ func (c *Client) Concat(targetPath string, resources resource.Resources) (resour
|
||||||
|
|
||||||
concatr := func() (hugio.ReadSeekCloser, error) {
|
concatr := func() (hugio.ReadSeekCloser, error) {
|
||||||
var rcsources []hugio.ReadSeekCloser
|
var rcsources []hugio.ReadSeekCloser
|
||||||
for _, s := range resources {
|
for _, s := range r {
|
||||||
rcr, ok := s.(resource.ReadSeekCloserResource)
|
rcr, ok := s.(resource.ReadSeekCloserResource)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("resource %T does not implement resource.ReadSeekerCloserResource", s)
|
return nil, fmt.Errorf("resource %T does not implement resource.ReadSeekerCloserResource", s)
|
||||||
|
@ -106,7 +107,7 @@ func (c *Client) Concat(targetPath string, resources resource.Resources) (resour
|
||||||
|
|
||||||
composite, err := c.rs.NewForFs(
|
composite, err := c.rs.NewForFs(
|
||||||
c.rs.FileCaches.AssetsCache().Fs,
|
c.rs.FileCaches.AssetsCache().Fs,
|
||||||
resource.ResourceSourceDescriptor{
|
resources.ResourceSourceDescriptor{
|
||||||
LazyPublish: true,
|
LazyPublish: true,
|
||||||
OpenReadSeekCloser: concatr,
|
OpenReadSeekCloser: concatr,
|
||||||
RelTargetFilename: filepath.Clean(targetPath)})
|
RelTargetFilename: filepath.Clean(targetPath)})
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -21,26 +21,27 @@ import (
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client contains methods to create Resource objects.
|
// Client contains methods to create Resource objects.
|
||||||
// tasks to Resource objects.
|
// tasks to Resource objects.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Client with the given specification.
|
// New creates a new Client with the given specification.
|
||||||
func New(rs *resource.Spec) *Client {
|
func New(rs *resources.Spec) *Client {
|
||||||
return &Client{rs: rs}
|
return &Client{rs: rs}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get creates a new Resource by opening the given filename in the given filesystem.
|
// Get creates a new Resource by opening the given filename in the given filesystem.
|
||||||
func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) {
|
func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) {
|
||||||
filename = filepath.Clean(filename)
|
filename = filepath.Clean(filename)
|
||||||
return c.rs.ResourceCache.GetOrCreate(resource.ResourceKeyPartition(filename), filename, func() (resource.Resource, error) {
|
return c.rs.ResourceCache.GetOrCreate(resources.ResourceKeyPartition(filename), filename, func() (resource.Resource, error) {
|
||||||
return c.rs.NewForFs(fs,
|
return c.rs.NewForFs(fs,
|
||||||
resource.ResourceSourceDescriptor{
|
resources.ResourceSourceDescriptor{
|
||||||
LazyPublish: true,
|
LazyPublish: true,
|
||||||
SourceFilename: filename})
|
SourceFilename: filename})
|
||||||
})
|
})
|
||||||
|
@ -49,10 +50,10 @@ func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) {
|
||||||
|
|
||||||
// FromString creates a new Resource from a string with the given relative target path.
|
// FromString creates a new Resource from a string with the given relative target path.
|
||||||
func (c *Client) FromString(targetPath, content string) (resource.Resource, error) {
|
func (c *Client) FromString(targetPath, content string) (resource.Resource, error) {
|
||||||
return c.rs.ResourceCache.GetOrCreate(resource.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
|
return c.rs.ResourceCache.GetOrCreate(resources.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
|
||||||
return c.rs.NewForFs(
|
return c.rs.NewForFs(
|
||||||
c.rs.FileCaches.AssetsCache().Fs,
|
c.rs.FileCaches.AssetsCache().Fs,
|
||||||
resource.ResourceSourceDescriptor{
|
resources.ResourceSourceDescriptor{
|
||||||
LazyPublish: true,
|
LazyPublish: true,
|
||||||
OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
|
OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
|
||||||
return hugio.NewReadSeekerNoOpCloserFromString(content), nil
|
return hugio.NewReadSeekerNoOpCloserFromString(content), nil
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -11,12 +11,15 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/resources/internal"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
|
|
||||||
|
@ -43,7 +46,7 @@ const counterPlaceHolder = ":counter"
|
||||||
// This assignment is additive, but the most specific match needs to be first.
|
// This assignment is additive, but the most specific match needs to be first.
|
||||||
// The `name` and `title` metadata field support shell-matched collection it got a match in.
|
// The `name` and `title` metadata field support shell-matched collection it got a match in.
|
||||||
// See https://golang.org/pkg/path/#Match
|
// See https://golang.org/pkg/path/#Match
|
||||||
func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) error {
|
func AssignMetadata(metadata []map[string]interface{}, resources ...resource.Resource) error {
|
||||||
|
|
||||||
counters := make(map[string]int)
|
counters := make(map[string]int)
|
||||||
|
|
||||||
|
@ -68,7 +71,7 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
|
||||||
|
|
||||||
srcKey := strings.ToLower(cast.ToString(src))
|
srcKey := strings.ToLower(cast.ToString(src))
|
||||||
|
|
||||||
glob, err := getGlob(srcKey)
|
glob, err := internal.GetGlob(srcKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to match resource with metadata")
|
return errors.Wrap(err, "failed to match resource with metadata")
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -11,12 +11,13 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -25,8 +26,8 @@ func TestAssignMetadata(t *testing.T) {
|
||||||
assert := require.New(t)
|
assert := require.New(t)
|
||||||
spec := newTestResourceSpec(assert)
|
spec := newTestResourceSpec(assert)
|
||||||
|
|
||||||
var foo1, foo2, foo3, logo1, logo2, logo3 Resource
|
var foo1, foo2, foo3, logo1, logo2, logo3 resource.Resource
|
||||||
var resources Resources
|
var resources resource.Resources
|
||||||
|
|
||||||
for _, this := range []struct {
|
for _, this := range []struct {
|
||||||
metaData []map[string]interface{}
|
metaData []map[string]interface{}
|
||||||
|
@ -215,7 +216,7 @@ func TestAssignMetadata(t *testing.T) {
|
||||||
foo3 = spec.newGenericResource(nil, nil, nil, "/b/foo3.css", "foo3.css", media.CSSType)
|
foo3 = spec.newGenericResource(nil, nil, nil, "/b/foo3.css", "foo3.css", media.CSSType)
|
||||||
logo3 = spec.newGenericResource(nil, nil, nil, "/b/logo3.png", "logo3.png", pngType)
|
logo3 = spec.newGenericResource(nil, nil, nil, "/b/logo3.png", "logo3.png", pngType)
|
||||||
|
|
||||||
resources = Resources{
|
resources = resource.Resources{
|
||||||
foo2,
|
foo2,
|
||||||
logo2,
|
logo2,
|
||||||
foo1,
|
foo1,
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -22,6 +22,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -75,7 +77,7 @@ func TestNewResourceFromFilename(t *testing.T) {
|
||||||
assert.NotNil(r)
|
assert.NotNil(r)
|
||||||
assert.Equal("json", r.ResourceType())
|
assert.Equal("json", r.ResourceType())
|
||||||
|
|
||||||
cloned := r.(Cloner).WithNewBase("aceof")
|
cloned := r.(resource.Cloner).WithNewBase("aceof")
|
||||||
assert.Equal(r.ResourceType(), cloned.ResourceType())
|
assert.Equal(r.ResourceType(), cloned.ResourceType())
|
||||||
assert.Equal("/aceof/a/b/data.json", cloned.RelPermalink())
|
assert.Equal("/aceof/a/b/data.json", cloned.RelPermalink())
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,7 @@ var pngType, _ = media.FromStringAndExt("image/png", "png")
|
||||||
func TestResourcesByType(t *testing.T) {
|
func TestResourcesByType(t *testing.T) {
|
||||||
assert := require.New(t)
|
assert := require.New(t)
|
||||||
spec := newTestResourceSpec(assert)
|
spec := newTestResourceSpec(assert)
|
||||||
resources := Resources{
|
resources := resource.Resources{
|
||||||
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
|
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
|
||||||
spec.newGenericResource(nil, nil, nil, "/a/logo.png", "logo.css", pngType),
|
spec.newGenericResource(nil, nil, nil, "/a/logo.png", "logo.css", pngType),
|
||||||
spec.newGenericResource(nil, nil, nil, "/a/foo2.css", "foo2.css", media.CSSType),
|
spec.newGenericResource(nil, nil, nil, "/a/foo2.css", "foo2.css", media.CSSType),
|
||||||
|
@ -117,7 +119,7 @@ func TestResourcesByType(t *testing.T) {
|
||||||
func TestResourcesGetByPrefix(t *testing.T) {
|
func TestResourcesGetByPrefix(t *testing.T) {
|
||||||
assert := require.New(t)
|
assert := require.New(t)
|
||||||
spec := newTestResourceSpec(assert)
|
spec := newTestResourceSpec(assert)
|
||||||
resources := Resources{
|
resources := resource.Resources{
|
||||||
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
|
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
|
||||||
spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType),
|
spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType),
|
||||||
spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType),
|
spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType),
|
||||||
|
@ -146,7 +148,7 @@ func TestResourcesGetByPrefix(t *testing.T) {
|
||||||
func TestResourcesGetMatch(t *testing.T) {
|
func TestResourcesGetMatch(t *testing.T) {
|
||||||
assert := require.New(t)
|
assert := require.New(t)
|
||||||
spec := newTestResourceSpec(assert)
|
spec := newTestResourceSpec(assert)
|
||||||
resources := Resources{
|
resources := resource.Resources{
|
||||||
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
|
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
|
||||||
spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType),
|
spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType),
|
||||||
spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType),
|
spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType),
|
||||||
|
@ -211,7 +213,7 @@ func BenchmarkResourcesMatchA100(b *testing.B) {
|
||||||
a100 := strings.Repeat("a", 100)
|
a100 := strings.Repeat("a", 100)
|
||||||
pattern := "a*a*a*a*a*a*a*a*b"
|
pattern := "a*a*a*a*a*a*a*a*b"
|
||||||
|
|
||||||
resources := Resources{spec.newGenericResource(nil, nil, nil, "/a/"+a100, a100, media.CSSType)}
|
resources := resource.Resources{spec.newGenericResource(nil, nil, nil, "/a/"+a100, a100, media.CSSType)}
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
@ -220,10 +222,10 @@ func BenchmarkResourcesMatchA100(b *testing.B) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func benchResources(b *testing.B) Resources {
|
func benchResources(b *testing.B) resource.Resources {
|
||||||
assert := require.New(b)
|
assert := require.New(b)
|
||||||
spec := newTestResourceSpec(assert)
|
spec := newTestResourceSpec(assert)
|
||||||
var resources Resources
|
var resources resource.Resources
|
||||||
|
|
||||||
for i := 0; i < 30; i++ {
|
for i := 0; i < 30; i++ {
|
||||||
name := fmt.Sprintf("abcde%d_%d.css", i%5, i)
|
name := fmt.Sprintf("abcde%d_%d.css", i%5, i)
|
||||||
|
@ -250,7 +252,7 @@ func BenchmarkAssignMetadata(b *testing.B) {
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
var resources Resources
|
var resources resource.Resources
|
||||||
var meta = []map[string]interface{}{
|
var meta = []map[string]interface{}{
|
||||||
{
|
{
|
||||||
"title": "Foo #:counter",
|
"title": "Foo #:counter",
|
|
@ -24,7 +24,8 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultHashAlgo = "sha256"
|
const defaultHashAlgo = "sha256"
|
||||||
|
@ -32,11 +33,11 @@ const defaultHashAlgo = "sha256"
|
||||||
// Client contains methods to fingerprint (cachebusting) and other integrity-related
|
// Client contains methods to fingerprint (cachebusting) and other integrity-related
|
||||||
// methods.
|
// methods.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Client with the given specification.
|
// New creates a new Client with the given specification.
|
||||||
func New(rs *resource.Spec) *Client {
|
func New(rs *resources.Spec) *Client {
|
||||||
return &Client{rs: rs}
|
return &Client{rs: rs}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,13 +45,13 @@ type fingerprintTransformation struct {
|
||||||
algo string
|
algo string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *fingerprintTransformation) Key() resource.ResourceTransformationKey {
|
func (t *fingerprintTransformation) Key() resources.ResourceTransformationKey {
|
||||||
return resource.NewResourceTransformationKey("fingerprint", t.algo)
|
return resources.NewResourceTransformationKey("fingerprint", t.algo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform creates a MD5 hash of the Resource content and inserts that hash before
|
// Transform creates a MD5 hash of the Resource content and inserts that hash before
|
||||||
// the extension in the filename.
|
// the extension in the filename.
|
||||||
func (t *fingerprintTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
|
func (t *fingerprintTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
|
||||||
algo := t.algo
|
algo := t.algo
|
||||||
|
|
||||||
var h hash.Hash
|
var h hash.Hash
|
|
@ -15,32 +15,33 @@ package minifier
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gohugoio/hugo/minifiers"
|
"github.com/gohugoio/hugo/minifiers"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client for minification of Resource objects. Supported minfiers are:
|
// Client for minification of Resource objects. Supported minfiers are:
|
||||||
// css, html, js, json, svg and xml.
|
// css, html, js, json, svg and xml.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
m minifiers.Client
|
m minifiers.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Client given a specification. Note that it is the media types
|
// New creates a new Client given a specification. Note that it is the media types
|
||||||
// configured for the site that is used to match files to the correct minifier.
|
// configured for the site that is used to match files to the correct minifier.
|
||||||
func New(rs *resource.Spec) *Client {
|
func New(rs *resources.Spec) *Client {
|
||||||
return &Client{rs: rs, m: minifiers.New(rs.MediaTypes, rs.OutputFormats)}
|
return &Client{rs: rs, m: minifiers.New(rs.MediaTypes, rs.OutputFormats)}
|
||||||
}
|
}
|
||||||
|
|
||||||
type minifyTransformation struct {
|
type minifyTransformation struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
m minifiers.Client
|
m minifiers.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *minifyTransformation) Key() resource.ResourceTransformationKey {
|
func (t *minifyTransformation) Key() resources.ResourceTransformationKey {
|
||||||
return resource.NewResourceTransformationKey("minify")
|
return resources.NewResourceTransformationKey("minify")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *minifyTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
|
func (t *minifyTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
|
||||||
if err := t.m.Minify(ctx.InMediaType, ctx.To, ctx.From); err != nil {
|
if err := t.m.Minify(ctx.InMediaType, ctx.To, ctx.From); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
|
@ -26,7 +26,8 @@ import (
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/herrors"
|
"github.com/gohugoio/hugo/common/herrors"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Some of the options from https://github.com/postcss/postcss-cli
|
// Some of the options from https://github.com/postcss/postcss-cli
|
||||||
|
@ -74,28 +75,28 @@ func (opts Options) toArgs() []string {
|
||||||
|
|
||||||
// Client is the client used to do PostCSS transformations.
|
// Client is the client used to do PostCSS transformations.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Client with the given specification.
|
// New creates a new Client with the given specification.
|
||||||
func New(rs *resource.Spec) *Client {
|
func New(rs *resources.Spec) *Client {
|
||||||
return &Client{rs: rs}
|
return &Client{rs: rs}
|
||||||
}
|
}
|
||||||
|
|
||||||
type postcssTransformation struct {
|
type postcssTransformation struct {
|
||||||
options Options
|
options Options
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *postcssTransformation) Key() resource.ResourceTransformationKey {
|
func (t *postcssTransformation) Key() resources.ResourceTransformationKey {
|
||||||
return resource.NewResourceTransformationKey("postcss", t.options)
|
return resources.NewResourceTransformationKey("postcss", t.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform shells out to postcss-cli to do the heavy lifting.
|
// Transform shells out to postcss-cli to do the heavy lifting.
|
||||||
// For this to work, you need some additional tools. To install them globally:
|
// For this to work, you need some additional tools. To install them globally:
|
||||||
// npm install -g postcss-cli
|
// npm install -g postcss-cli
|
||||||
// npm install -g autoprefixer
|
// npm install -g autoprefixer
|
||||||
func (t *postcssTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
|
func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
|
||||||
|
|
||||||
const localPostCSSPath = "node_modules/postcss-cli/bin/"
|
const localPostCSSPath = "node_modules/postcss-cli/bin/"
|
||||||
const binaryName = "postcss"
|
const binaryName = "postcss"
|
|
@ -16,20 +16,21 @@ package templates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
"github.com/gohugoio/hugo/tpl"
|
"github.com/gohugoio/hugo/tpl"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client contains methods to perform template processing of Resource objects.
|
// Client contains methods to perform template processing of Resource objects.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
|
|
||||||
textTemplate tpl.TemplateParseFinder
|
textTemplate tpl.TemplateParseFinder
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Client with the given specification.
|
// New creates a new Client with the given specification.
|
||||||
func New(rs *resource.Spec, textTemplate tpl.TemplateParseFinder) *Client {
|
func New(rs *resources.Spec, textTemplate tpl.TemplateParseFinder) *Client {
|
||||||
if rs == nil {
|
if rs == nil {
|
||||||
panic("must provice a resource Spec")
|
panic("must provice a resource Spec")
|
||||||
}
|
}
|
||||||
|
@ -40,17 +41,17 @@ func New(rs *resource.Spec, textTemplate tpl.TemplateParseFinder) *Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
type executeAsTemplateTransform struct {
|
type executeAsTemplateTransform struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
textTemplate tpl.TemplateParseFinder
|
textTemplate tpl.TemplateParseFinder
|
||||||
targetPath string
|
targetPath string
|
||||||
data interface{}
|
data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *executeAsTemplateTransform) Key() resource.ResourceTransformationKey {
|
func (t *executeAsTemplateTransform) Key() resources.ResourceTransformationKey {
|
||||||
return resource.NewResourceTransformationKey("execute-as-template", t.targetPath)
|
return resources.NewResourceTransformationKey("execute-as-template", t.targetPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *executeAsTemplateTransform) Transform(ctx *resource.ResourceTransformationCtx) error {
|
func (t *executeAsTemplateTransform) Transform(ctx *resources.ResourceTransformationCtx) error {
|
||||||
tplStr := helpers.ReaderToString(ctx.From)
|
tplStr := helpers.ReaderToString(ctx.From)
|
||||||
templ, err := t.textTemplate.Parse(ctx.InPath, tplStr)
|
templ, err := t.textTemplate.Parse(ctx.InPath, tplStr)
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -17,17 +17,19 @@ import (
|
||||||
"github.com/bep/go-tocss/scss"
|
"github.com/bep/go-tocss/scss"
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/hugolib/filesystems"
|
"github.com/gohugoio/hugo/hugolib/filesystems"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
rs *resource.Spec
|
rs *resources.Spec
|
||||||
sfs *filesystems.SourceFilesystem
|
sfs *filesystems.SourceFilesystem
|
||||||
workFs *filesystems.SourceFilesystem
|
workFs *filesystems.SourceFilesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(fs *filesystems.SourceFilesystem, rs *resource.Spec) (*Client, error) {
|
func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error) {
|
||||||
return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs}, nil
|
return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +93,8 @@ type toCSSTransformation struct {
|
||||||
options options
|
options options
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *toCSSTransformation) Key() resource.ResourceTransformationKey {
|
func (t *toCSSTransformation) Key() resources.ResourceTransformationKey {
|
||||||
return resource.NewResourceTransformationKey("tocss", t.options.from)
|
return resources.NewResourceTransformationKey("tocss", t.options.from)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeOptions(m map[string]interface{}) (opts Options, err error) {
|
func DecodeOptions(m map[string]interface{}) (opts Options, err error) {
|
|
@ -28,7 +28,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/hugofs"
|
"github.com/gohugoio/hugo/hugofs"
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func Supports() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *toCSSTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
|
func (t *toCSSTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
|
||||||
ctx.OutMediaType = media.CSSType
|
ctx.OutMediaType = media.CSSType
|
||||||
|
|
||||||
var outName string
|
var outName string
|
|
@ -17,7 +17,7 @@ package scss
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gohugoio/hugo/common/herrors"
|
"github.com/gohugoio/hugo/common/herrors"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used in tests.
|
// Used in tests.
|
||||||
|
@ -25,6 +25,6 @@ func Supports() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *toCSSTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
|
func (t *toCSSTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
|
||||||
return herrors.ErrFeatureNotAvailable
|
return herrors.ErrFeatureNotAvailable
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
@ -1,4 +1,4 @@
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/hugofs"
|
"github.com/gohugoio/hugo/hugofs"
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
"github.com/gohugoio/hugo/output"
|
"github.com/gohugoio/hugo/output"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -112,7 +113,7 @@ func fetchImageForSpec(spec *Spec, assert *require.Assertions, name string) *Ima
|
||||||
return r.(*Image)
|
return r.(*Image)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) ContentResource {
|
func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) resource.ContentResource {
|
||||||
src, err := os.Open(filepath.FromSlash("testdata/" + name))
|
src, err := os.Open(filepath.FromSlash("testdata/" + name))
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) C
|
||||||
r, err := spec.New(ResourceSourceDescriptor{TargetPathBuilder: factory, SourceFilename: name})
|
r, err := spec.New(ResourceSourceDescriptor{TargetPathBuilder: factory, SourceFilename: name})
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
||||||
return r.(ContentResource)
|
return r.(resource.ContentResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertImageFile(assert *require.Assertions, fs afero.Fs, filename string, width, height int) {
|
func assertImageFile(assert *require.Assertions, fs afero.Fs, filename string, width, height int) {
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/gohugoio/hugo/common/herrors"
|
"github.com/gohugoio/hugo/common/herrors"
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
"github.com/mitchellh/hashstructure"
|
"github.com/mitchellh/hashstructure"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -35,13 +36,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ ContentResource = (*transformedResource)(nil)
|
_ resource.ContentResource = (*transformedResource)(nil)
|
||||||
_ ReadSeekCloserResource = (*transformedResource)(nil)
|
_ resource.ReadSeekCloserResource = (*transformedResource)(nil)
|
||||||
_ collections.Slicer = (*transformedResource)(nil)
|
_ collections.Slicer = (*transformedResource)(nil)
|
||||||
_ Identifier = (*transformedResource)(nil)
|
_ resource.Identifier = (*transformedResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Spec) Transform(r Resource, t ResourceTransformation) (Resource, error) {
|
func (s *Spec) Transform(r resource.Resource, t ResourceTransformation) (resource.Resource, error) {
|
||||||
return &transformedResource{
|
return &transformedResource{
|
||||||
Resource: r,
|
Resource: r,
|
||||||
transformation: t,
|
transformation: t,
|
||||||
|
@ -195,7 +196,7 @@ type transformedResource struct {
|
||||||
transformedResourceMetadata
|
transformedResourceMetadata
|
||||||
|
|
||||||
// The source
|
// The source
|
||||||
Resource
|
resource.Resource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *transformedResource) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
|
func (r *transformedResource) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
|
||||||
|
@ -292,11 +293,11 @@ func (r *transformedResource) transform(setContent, publish bool) (err error) {
|
||||||
|
|
||||||
// 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.
|
||||||
var chain []Resource
|
var chain []resource.Resource
|
||||||
current := r
|
current := r
|
||||||
for {
|
for {
|
||||||
rr := current.Resource
|
rr := current.Resource
|
||||||
chain = append(chain[:0], append([]Resource{rr}, chain[0:]...)...)
|
chain = append(chain[:0], append([]resource.Resource{rr}, chain[0:]...)...)
|
||||||
if tr, ok := rr.(*transformedResource); ok {
|
if tr, ok := rr.(*transformedResource); ok {
|
||||||
current = tr
|
current = tr
|
||||||
} else {
|
} else {
|
||||||
|
@ -538,9 +539,9 @@ func (r *transformedResource) initTransform(setContent, publish bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// contentReadSeekerCloser returns a ReadSeekerCloser if possible for a given Resource.
|
// contentReadSeekerCloser returns a ReadSeekerCloser if possible for a given Resource.
|
||||||
func contentReadSeekerCloser(r Resource) (hugio.ReadSeekCloser, error) {
|
func contentReadSeekerCloser(r resource.Resource) (hugio.ReadSeekCloser, error) {
|
||||||
switch rr := r.(type) {
|
switch rr := r.(type) {
|
||||||
case ReadSeekCloserResource:
|
case resource.ReadSeekCloserResource:
|
||||||
rc, err := rr.ReadSeekCloser()
|
rc, err := rr.ReadSeekCloser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package resource
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -22,14 +22,14 @@ import (
|
||||||
_errors "github.com/pkg/errors"
|
_errors "github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
"github.com/gohugoio/hugo/resource/resource_factories/bundler"
|
"github.com/gohugoio/hugo/resources/resource_factories/bundler"
|
||||||
"github.com/gohugoio/hugo/resource/resource_factories/create"
|
"github.com/gohugoio/hugo/resources/resource_factories/create"
|
||||||
"github.com/gohugoio/hugo/resource/resource_transformers/integrity"
|
"github.com/gohugoio/hugo/resources/resource_transformers/integrity"
|
||||||
"github.com/gohugoio/hugo/resource/resource_transformers/minifier"
|
"github.com/gohugoio/hugo/resources/resource_transformers/minifier"
|
||||||
"github.com/gohugoio/hugo/resource/resource_transformers/postcss"
|
"github.com/gohugoio/hugo/resources/resource_transformers/postcss"
|
||||||
"github.com/gohugoio/hugo/resource/resource_transformers/templates"
|
"github.com/gohugoio/hugo/resources/resource_transformers/templates"
|
||||||
"github.com/gohugoio/hugo/resource/resource_transformers/tocss/scss"
|
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -21,7 +21,7 @@ import (
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
"github.com/gohugoio/hugo/parser/metadecoders"
|
"github.com/gohugoio/hugo/parser/metadecoders"
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018 The Hugo Authors. All rights reserved.
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -23,7 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/media"
|
"github.com/gohugoio/hugo/media"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/resource"
|
"github.com/gohugoio/hugo/resources/resource"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|