hugo

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

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

path.go (5445B)

    1 // Copyright 2018 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 path provides template functions for manipulating paths.
   15 package path
   16 
   17 import (
   18 	"fmt"
   19 	_path "path"
   20 	"path/filepath"
   21 	"strings"
   22 
   23 	"github.com/gohugoio/hugo/deps"
   24 	"github.com/spf13/cast"
   25 )
   26 
   27 // New returns a new instance of the path-namespaced template functions.
   28 func New(deps *deps.Deps) *Namespace {
   29 	return &Namespace{
   30 		deps: deps,
   31 	}
   32 }
   33 
   34 // Namespace provides template functions for the "os" namespace.
   35 type Namespace struct {
   36 	deps *deps.Deps
   37 }
   38 
   39 // DirFile holds the result from path.Split.
   40 type DirFile struct {
   41 	Dir  string
   42 	File string
   43 }
   44 
   45 // Used in test.
   46 func (df DirFile) String() string {
   47 	return fmt.Sprintf("%s|%s", df.Dir, df.File)
   48 }
   49 
   50 // Ext returns the file name extension used by path.
   51 // The extension is the suffix beginning at the final dot
   52 // in the final slash-separated element of path;
   53 // it is empty if there is no dot.
   54 // The input path is passed into filepath.ToSlash converting any Windows slashes
   55 // to forward slashes.
   56 func (ns *Namespace) Ext(path any) (string, error) {
   57 	spath, err := cast.ToStringE(path)
   58 	if err != nil {
   59 		return "", err
   60 	}
   61 	spath = filepath.ToSlash(spath)
   62 	return _path.Ext(spath), nil
   63 }
   64 
   65 // Dir returns all but the last element of path, typically the path's directory.
   66 // After dropping the final element using Split, the path is Cleaned and trailing
   67 // slashes are removed.
   68 // If the path is empty, Dir returns ".".
   69 // If the path consists entirely of slashes followed by non-slash bytes, Dir
   70 // returns a single slash. In any other case, the returned path does not end in a
   71 // slash.
   72 // The input path is passed into filepath.ToSlash converting any Windows slashes
   73 // to forward slashes.
   74 func (ns *Namespace) Dir(path any) (string, error) {
   75 	spath, err := cast.ToStringE(path)
   76 	if err != nil {
   77 		return "", err
   78 	}
   79 	spath = filepath.ToSlash(spath)
   80 	return _path.Dir(spath), nil
   81 }
   82 
   83 // Base returns the last element of path.
   84 // Trailing slashes are removed before extracting the last element.
   85 // If the path is empty, Base returns ".".
   86 // If the path consists entirely of slashes, Base returns "/".
   87 // The input path is passed into filepath.ToSlash converting any Windows slashes
   88 // to forward slashes.
   89 func (ns *Namespace) Base(path any) (string, error) {
   90 	spath, err := cast.ToStringE(path)
   91 	if err != nil {
   92 		return "", err
   93 	}
   94 	spath = filepath.ToSlash(spath)
   95 	return _path.Base(spath), nil
   96 }
   97 
   98 // BaseName returns the last element of path, removing the extension if present.
   99 // Trailing slashes are removed before extracting the last element.
  100 // If the path is empty, Base returns ".".
  101 // If the path consists entirely of slashes, Base returns "/".
  102 // The input path is passed into filepath.ToSlash converting any Windows slashes
  103 // to forward slashes.
  104 func (ns *Namespace) BaseName(path any) (string, error) {
  105 	spath, err := cast.ToStringE(path)
  106 	if err != nil {
  107 		return "", err
  108 	}
  109 	spath = filepath.ToSlash(spath)
  110 	return strings.TrimSuffix(_path.Base(spath), _path.Ext(spath)), nil
  111 }
  112 
  113 // Split splits path immediately following the final slash,
  114 // separating it into a directory and file name component.
  115 // If there is no slash in path, Split returns an empty dir and
  116 // file set to path.
  117 // The input path is passed into filepath.ToSlash converting any Windows slashes
  118 // to forward slashes.
  119 // The returned values have the property that path = dir+file.
  120 func (ns *Namespace) Split(path any) (DirFile, error) {
  121 	spath, err := cast.ToStringE(path)
  122 	if err != nil {
  123 		return DirFile{}, err
  124 	}
  125 	spath = filepath.ToSlash(spath)
  126 	dir, file := _path.Split(spath)
  127 
  128 	return DirFile{Dir: dir, File: file}, nil
  129 }
  130 
  131 // Join joins any number of path elements into a single path, adding a
  132 // separating slash if necessary. All the input
  133 // path elements are passed into filepath.ToSlash converting any Windows slashes
  134 // to forward slashes.
  135 // The result is Cleaned; in particular,
  136 // all empty strings are ignored.
  137 func (ns *Namespace) Join(elements ...any) (string, error) {
  138 	var pathElements []string
  139 	for _, elem := range elements {
  140 		switch v := elem.(type) {
  141 		case []string:
  142 			for _, e := range v {
  143 				pathElements = append(pathElements, filepath.ToSlash(e))
  144 			}
  145 		case []any:
  146 			for _, e := range v {
  147 				elemStr, err := cast.ToStringE(e)
  148 				if err != nil {
  149 					return "", err
  150 				}
  151 				pathElements = append(pathElements, filepath.ToSlash(elemStr))
  152 			}
  153 		default:
  154 			elemStr, err := cast.ToStringE(elem)
  155 			if err != nil {
  156 				return "", err
  157 			}
  158 			pathElements = append(pathElements, filepath.ToSlash(elemStr))
  159 		}
  160 	}
  161 	return _path.Join(pathElements...), nil
  162 }
  163 
  164 // Clean replaces the separators used with standard slashes and then
  165 // extraneous slashes are removed.
  166 func (ns *Namespace) Clean(path any) (string, error) {
  167 	spath, err := cast.ToStringE(path)
  168 
  169 	if err != nil {
  170 		return "", err
  171 	}
  172 	spath = filepath.ToSlash(spath)
  173 	return _path.Clean(spath), nil
  174 }