resource: Implement Resource.Content

Fixes #4622
This commit is contained in:
Bjørn Erik Pedersen 2018-04-15 17:07:49 +02:00
parent 417c5e2b67
commit 0e7716a424
3 changed files with 48 additions and 0 deletions

View file

@ -568,6 +568,7 @@ func (i *Image) encodeToDestinations(img image.Image, conf imageConfig, resource
func (i *Image) clone() *Image { func (i *Image) clone() *Image {
g := *i.genericResource g := *i.genericResource
g.resourceContent = &resourceContent{}
return &Image{ return &Image{
imaging: i.imaging, imaging: i.imaging,

View file

@ -322,6 +322,18 @@ func TestSVGImage(t *testing.T) {
assert.NotNil(svg) assert.NotNil(svg)
} }
func TestSVGImageContent(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
svg := fetchResourceForSpec(spec, assert, "circle.svg")
assert.NotNil(svg)
content, err := svg.Content()
assert.NoError(err)
assert.IsType("", content)
assert.Contains(content.(string), `<svg height="100" width="100">`)
}
func BenchmarkResizeParallel(b *testing.B) { func BenchmarkResizeParallel(b *testing.B) {
assert := require.New(b) assert := require.New(b)
img := fetchSunset(assert) img := fetchSunset(assert)

View file

@ -87,6 +87,14 @@ type Resource interface {
// Params set in front matter for this resource. // Params set in front matter for this resource.
Params() map[string]interface{} Params() map[string]interface{}
// 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)
} }
// Resources represents a slice of resources, which can be a mix of different types. // Resources represents a slice of resources, which can be a mix of different types.
@ -360,6 +368,11 @@ func (d dirFile) path() string {
return path.Join(d.dir, d.file) return path.Join(d.dir, d.file)
} }
type resourceContent struct {
content string
contentInit sync.Once
}
// genericResource represents a generic linkable resource. // genericResource represents a generic linkable resource.
type genericResource struct { type genericResource struct {
// The relative path to this resource. // The relative path to this resource.
@ -390,6 +403,26 @@ type genericResource struct {
osFileInfo os.FileInfo osFileInfo os.FileInfo
targetPathBuilder func(rel string) string targetPathBuilder func(rel string) string
// We create copies of this struct, so this needs to be a pointer.
*resourceContent
}
func (l *genericResource) Content() (interface{}, error) {
var err error
l.contentInit.Do(func() {
var b []byte
b, err := afero.ReadFile(l.sourceFs(), l.AbsSourceFilename())
if err != nil {
return
}
l.content = string(b)
})
return l.content, err
} }
func (l *genericResource) sourceFs() afero.Fs { func (l *genericResource) sourceFs() afero.Fs {
@ -444,6 +477,7 @@ func (l *genericResource) updateParams(params map[string]interface{}) {
// Implement the Cloner interface. // Implement the Cloner interface.
func (l genericResource) WithNewBase(base string) Resource { func (l genericResource) WithNewBase(base string) Resource {
l.base = base l.base = base
l.resourceContent = &resourceContent{}
return &l return &l
} }
@ -611,5 +645,6 @@ func (r *Spec) newGenericResource(
params: make(map[string]interface{}), params: make(map[string]interface{}),
name: baseFilename, name: baseFilename,
title: baseFilename, title: baseFilename,
resourceContent: &resourceContent{},
} }
} }