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