github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/common/paths/url.go (about)

     1  // Copyright 2021 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 paths
    15  
    16  import (
    17  	"fmt"
    18  	"net/url"
    19  	"path"
    20  	"path/filepath"
    21  	"strings"
    22  )
    23  
    24  type pathBridge struct{}
    25  
    26  func (pathBridge) Base(in string) string {
    27  	return path.Base(in)
    28  }
    29  
    30  func (pathBridge) Clean(in string) string {
    31  	return path.Clean(in)
    32  }
    33  
    34  func (pathBridge) Dir(in string) string {
    35  	return path.Dir(in)
    36  }
    37  
    38  func (pathBridge) Ext(in string) string {
    39  	return path.Ext(in)
    40  }
    41  
    42  func (pathBridge) Join(elem ...string) string {
    43  	return path.Join(elem...)
    44  }
    45  
    46  func (pathBridge) Separator() string {
    47  	return "/"
    48  }
    49  
    50  var pb pathBridge
    51  
    52  // MakePermalink combines base URL with content path to create full URL paths.
    53  // Example
    54  //
    55  //	base:   http://spf13.com/
    56  //	path:   post/how-i-blog
    57  //	result: http://spf13.com/post/how-i-blog
    58  func MakePermalink(host, plink string) *url.URL {
    59  	base, err := url.Parse(host)
    60  	if err != nil {
    61  		panic(err)
    62  	}
    63  
    64  	p, err := url.Parse(plink)
    65  	if err != nil {
    66  		panic(err)
    67  	}
    68  
    69  	if p.Host != "" {
    70  		panic(fmt.Errorf("can't make permalink from absolute link %q", plink))
    71  	}
    72  
    73  	base.Path = path.Join(base.Path, p.Path)
    74  
    75  	// path.Join will strip off the last /, so put it back if it was there.
    76  	hadTrailingSlash := (plink == "" && strings.HasSuffix(host, "/")) || strings.HasSuffix(p.Path, "/")
    77  	if hadTrailingSlash && !strings.HasSuffix(base.Path, "/") {
    78  		base.Path = base.Path + "/"
    79  	}
    80  
    81  	return base
    82  }
    83  
    84  // AddContextRoot adds the context root to an URL if it's not already set.
    85  // For relative URL entries on sites with a base url with a context root set (i.e. http://example.com/mysite),
    86  // relative URLs must not include the context root if canonifyURLs is enabled. But if it's disabled, it must be set.
    87  func AddContextRoot(baseURL, relativePath string) string {
    88  	url, err := url.Parse(baseURL)
    89  	if err != nil {
    90  		panic(err)
    91  	}
    92  
    93  	newPath := path.Join(url.Path, relativePath)
    94  
    95  	// path strips trailing slash, ignore root path.
    96  	if newPath != "/" && strings.HasSuffix(relativePath, "/") {
    97  		newPath += "/"
    98  	}
    99  	return newPath
   100  }
   101  
   102  // URLizeAn
   103  
   104  // PrettifyURL takes a URL string and returns a semantic, clean URL.
   105  func PrettifyURL(in string) string {
   106  	x := PrettifyURLPath(in)
   107  
   108  	if path.Base(x) == "index.html" {
   109  		return path.Dir(x)
   110  	}
   111  
   112  	if in == "" {
   113  		return "/"
   114  	}
   115  
   116  	return x
   117  }
   118  
   119  // PrettifyURLPath takes a URL path to a content and converts it
   120  // to enable pretty URLs.
   121  //
   122  //	/section/name.html       becomes /section/name/index.html
   123  //	/section/name/           becomes /section/name/index.html
   124  //	/section/name/index.html becomes /section/name/index.html
   125  func PrettifyURLPath(in string) string {
   126  	return prettifyPath(in, pb)
   127  }
   128  
   129  // Uglify does the opposite of PrettifyURLPath().
   130  //
   131  //	/section/name/index.html becomes /section/name.html
   132  //	/section/name/           becomes /section/name.html
   133  //	/section/name.html       becomes /section/name.html
   134  func Uglify(in string) string {
   135  	if path.Ext(in) == "" {
   136  		if len(in) < 2 {
   137  			return "/"
   138  		}
   139  		// /section/name/  -> /section/name.html
   140  		return path.Clean(in) + ".html"
   141  	}
   142  
   143  	name, ext := fileAndExt(in, pb)
   144  	if name == "index" {
   145  		// /section/name/index.html -> /section/name.html
   146  		d := path.Dir(in)
   147  		if len(d) > 1 {
   148  			return d + ext
   149  		}
   150  		return in
   151  	}
   152  	// /.xml -> /index.xml
   153  	if name == "" {
   154  		return path.Dir(in) + "index" + ext
   155  	}
   156  	// /section/name.html -> /section/name.html
   157  	return path.Clean(in)
   158  }
   159  
   160  // UrlToFilename converts the URL s to a filename.
   161  // If ParseRequestURI fails, the input is just converted to OS specific slashes and returned.
   162  func UrlToFilename(s string) (string, bool) {
   163  	u, err := url.ParseRequestURI(s)
   164  
   165  	if err != nil {
   166  		return filepath.FromSlash(s), false
   167  	}
   168  
   169  	p := u.Path
   170  
   171  	if p == "" {
   172  		p, _ = url.QueryUnescape(u.Opaque)
   173  		return filepath.FromSlash(p), true
   174  	}
   175  
   176  	p = filepath.FromSlash(p)
   177  
   178  	if u.Host != "" {
   179  		// C:\data\file.txt
   180  		p = strings.ToUpper(u.Host) + ":" + p
   181  	}
   182  
   183  	return p, true
   184  }