github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/resources/resource_factories/create/create.go (about) 1 // Copyright 2019 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 // Package create contains functions for to create Resource objects. This will 15 // typically non-files. 16 package create 17 18 import ( 19 "net/http" 20 "path" 21 "path/filepath" 22 "strings" 23 "time" 24 25 "github.com/gohugoio/hugo/hugofs/glob" 26 27 "github.com/gohugoio/hugo/hugofs" 28 29 "github.com/gohugoio/hugo/cache/filecache" 30 "github.com/gohugoio/hugo/common/hugio" 31 "github.com/gohugoio/hugo/resources" 32 "github.com/gohugoio/hugo/resources/resource" 33 ) 34 35 // Client contains methods to create Resource objects. 36 // tasks to Resource objects. 37 type Client struct { 38 rs *resources.Spec 39 httpClient *http.Client 40 cacheGetResource *filecache.Cache 41 } 42 43 // New creates a new Client with the given specification. 44 func New(rs *resources.Spec) *Client { 45 return &Client{ 46 rs: rs, 47 httpClient: &http.Client{ 48 Timeout: 10 * time.Second, 49 }, 50 cacheGetResource: rs.FileCaches.GetResourceCache(), 51 } 52 } 53 54 // Get creates a new Resource by opening the given filename in the assets filesystem. 55 func (c *Client) Get(filename string) (resource.Resource, error) { 56 filename = filepath.Clean(filename) 57 return c.rs.ResourceCache.GetOrCreate(resources.ResourceCacheKey(filename), func() (resource.Resource, error) { 58 return c.rs.New(resources.ResourceSourceDescriptor{ 59 Fs: c.rs.BaseFs.Assets.Fs, 60 LazyPublish: true, 61 SourceFilename: filename, 62 }) 63 }) 64 } 65 66 // Match gets the resources matching the given pattern from the assets filesystem. 67 func (c *Client) Match(pattern string) (resource.Resources, error) { 68 return c.match(pattern, false) 69 } 70 71 // GetMatch gets first resource matching the given pattern from the assets filesystem. 72 func (c *Client) GetMatch(pattern string) (resource.Resource, error) { 73 res, err := c.match(pattern, true) 74 if err != nil || len(res) == 0 { 75 return nil, err 76 } 77 return res[0], err 78 } 79 80 func (c *Client) match(pattern string, firstOnly bool) (resource.Resources, error) { 81 var name string 82 if firstOnly { 83 name = "__get-match" 84 } else { 85 name = "__match" 86 } 87 88 pattern = glob.NormalizePath(pattern) 89 partitions := glob.FilterGlobParts(strings.Split(pattern, "/")) 90 if len(partitions) == 0 { 91 partitions = []string{resources.CACHE_OTHER} 92 } 93 key := path.Join(name, path.Join(partitions...)) 94 key = path.Join(key, pattern) 95 96 return c.rs.ResourceCache.GetOrCreateResources(key, func() (resource.Resources, error) { 97 var res resource.Resources 98 99 handle := func(info hugofs.FileMetaInfo) (bool, error) { 100 meta := info.Meta() 101 r, err := c.rs.New(resources.ResourceSourceDescriptor{ 102 LazyPublish: true, 103 FileInfo: info, 104 OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { 105 return meta.Open() 106 }, 107 RelTargetFilename: meta.Path, 108 }) 109 if err != nil { 110 return true, err 111 } 112 113 res = append(res, r) 114 115 return firstOnly, nil 116 } 117 118 if err := hugofs.Glob(c.rs.BaseFs.Assets.Fs, pattern, handle); err != nil { 119 return nil, err 120 } 121 122 return res, nil 123 }) 124 } 125 126 // FromString creates a new Resource from a string with the given relative target path. 127 func (c *Client) FromString(targetPath, content string) (resource.Resource, error) { 128 return c.rs.ResourceCache.GetOrCreate(path.Join(resources.CACHE_OTHER, targetPath), func() (resource.Resource, error) { 129 return c.rs.New( 130 resources.ResourceSourceDescriptor{ 131 Fs: c.rs.FileCaches.AssetsCache().Fs, 132 LazyPublish: true, 133 OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { 134 return hugio.NewReadSeekerNoOpCloserFromString(content), nil 135 }, 136 RelTargetFilename: filepath.Clean(targetPath), 137 }) 138 }) 139 }