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  }