hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

create.go (4746B)

    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 // Copy copies r to the new targetPath.
   55 func (c *Client) Copy(r resource.Resource, targetPath string) (resource.Resource, error) {
   56 	return c.rs.ResourceCache.GetOrCreate(resources.ResourceCacheKey(targetPath), func() (resource.Resource, error) {
   57 		return resources.Copy(r, targetPath), nil
   58 	})
   59 }
   60 
   61 // Get creates a new Resource by opening the given filename in the assets filesystem.
   62 func (c *Client) Get(filename string) (resource.Resource, error) {
   63 	filename = filepath.Clean(filename)
   64 	return c.rs.ResourceCache.GetOrCreate(resources.ResourceCacheKey(filename), func() (resource.Resource, error) {
   65 		return c.rs.New(resources.ResourceSourceDescriptor{
   66 			Fs:             c.rs.BaseFs.Assets.Fs,
   67 			LazyPublish:    true,
   68 			SourceFilename: filename,
   69 		})
   70 	})
   71 }
   72 
   73 // Match gets the resources matching the given pattern from the assets filesystem.
   74 func (c *Client) Match(pattern string) (resource.Resources, error) {
   75 	return c.match("__match", pattern, nil, false)
   76 }
   77 
   78 func (c *Client) ByType(tp string) resource.Resources {
   79 	res, err := c.match(path.Join("_byType", tp), "**", func(r resource.Resource) bool { return r.ResourceType() == tp }, false)
   80 	if err != nil {
   81 		panic(err)
   82 	}
   83 	return res
   84 }
   85 
   86 // GetMatch gets first resource matching the given pattern from the assets filesystem.
   87 func (c *Client) GetMatch(pattern string) (resource.Resource, error) {
   88 	res, err := c.match("__get-match", pattern, nil, true)
   89 	if err != nil || len(res) == 0 {
   90 		return nil, err
   91 	}
   92 	return res[0], err
   93 }
   94 
   95 func (c *Client) match(name, pattern string, matchFunc func(r resource.Resource) bool, firstOnly bool) (resource.Resources, error) {
   96 	pattern = glob.NormalizePath(pattern)
   97 	partitions := glob.FilterGlobParts(strings.Split(pattern, "/"))
   98 	if len(partitions) == 0 {
   99 		partitions = []string{resources.CACHE_OTHER}
  100 	}
  101 	key := path.Join(name, path.Join(partitions...))
  102 	key = path.Join(key, pattern)
  103 
  104 	return c.rs.ResourceCache.GetOrCreateResources(key, func() (resource.Resources, error) {
  105 		var res resource.Resources
  106 
  107 		handle := func(info hugofs.FileMetaInfo) (bool, error) {
  108 			meta := info.Meta()
  109 			r, err := c.rs.New(resources.ResourceSourceDescriptor{
  110 				LazyPublish: true,
  111 				FileInfo:    info,
  112 				OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
  113 					return meta.Open()
  114 				},
  115 				RelTargetFilename: meta.Path,
  116 			})
  117 			if err != nil {
  118 				return true, err
  119 			}
  120 
  121 			if matchFunc != nil && !matchFunc(r) {
  122 				return false, nil
  123 			}
  124 
  125 			res = append(res, r)
  126 
  127 			return firstOnly, nil
  128 		}
  129 
  130 		if err := hugofs.Glob(c.rs.BaseFs.Assets.Fs, pattern, handle); err != nil {
  131 			return nil, err
  132 		}
  133 
  134 		return res, nil
  135 	})
  136 }
  137 
  138 // FromString creates a new Resource from a string with the given relative target path.
  139 func (c *Client) FromString(targetPath, content string) (resource.Resource, error) {
  140 	return c.rs.ResourceCache.GetOrCreate(path.Join(resources.CACHE_OTHER, targetPath), func() (resource.Resource, error) {
  141 		return c.rs.New(
  142 			resources.ResourceSourceDescriptor{
  143 				Fs:          c.rs.FileCaches.AssetsCache().Fs,
  144 				LazyPublish: true,
  145 				OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
  146 					return hugio.NewReadSeekerNoOpCloserFromString(content), nil
  147 				},
  148 				RelTargetFilename: filepath.Clean(targetPath),
  149 			})
  150 	})
  151 }