github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/common/urls/baseURL.go (about) 1 // Copyright 2023 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 urls 15 16 import ( 17 "fmt" 18 "net/url" 19 "strconv" 20 "strings" 21 ) 22 23 // A BaseURL in Hugo is normally on the form scheme://path, but the 24 // form scheme: is also valid (mailto:hugo@rules.com). 25 type BaseURL struct { 26 url *url.URL 27 WithPath string 28 WithoutPath string 29 BasePath string 30 } 31 32 func (b BaseURL) String() string { 33 return b.WithPath 34 } 35 36 func (b BaseURL) Path() string { 37 return b.url.Path 38 } 39 40 func (b BaseURL) Port() int { 41 p, _ := strconv.Atoi(b.url.Port()) 42 return p 43 } 44 45 // HostURL returns the URL to the host root without any path elements. 46 func (b BaseURL) HostURL() string { 47 return strings.TrimSuffix(b.String(), b.Path()) 48 } 49 50 // WithProtocol returns the BaseURL prefixed with the given protocol. 51 // The Protocol is normally of the form "scheme://", i.e. "webcal://". 52 func (b BaseURL) WithProtocol(protocol string) (BaseURL, error) { 53 u := b.URL() 54 55 scheme := protocol 56 isFullProtocol := strings.HasSuffix(scheme, "://") 57 isOpaqueProtocol := strings.HasSuffix(scheme, ":") 58 59 if isFullProtocol { 60 scheme = strings.TrimSuffix(scheme, "://") 61 } else if isOpaqueProtocol { 62 scheme = strings.TrimSuffix(scheme, ":") 63 } 64 65 u.Scheme = scheme 66 67 if isFullProtocol && u.Opaque != "" { 68 u.Opaque = "//" + u.Opaque 69 } else if isOpaqueProtocol && u.Opaque == "" { 70 return BaseURL{}, fmt.Errorf("cannot determine BaseURL for protocol %q", protocol) 71 } 72 73 return newBaseURLFromURL(u) 74 } 75 76 func (b BaseURL) WithPort(port int) (BaseURL, error) { 77 u := b.URL() 78 u.Host = u.Hostname() + ":" + strconv.Itoa(port) 79 return newBaseURLFromURL(u) 80 } 81 82 // URL returns a copy of the internal URL. 83 // The copy can be safely used and modified. 84 func (b BaseURL) URL() *url.URL { 85 c := *b.url 86 return &c 87 } 88 89 func NewBaseURLFromString(b string) (BaseURL, error) { 90 u, err := url.Parse(b) 91 if err != nil { 92 return BaseURL{}, err 93 } 94 return newBaseURLFromURL(u) 95 96 } 97 98 func newBaseURLFromURL(u *url.URL) (BaseURL, error) { 99 baseURL := BaseURL{url: u, WithPath: u.String()} 100 var baseURLNoPath = baseURL.URL() 101 baseURLNoPath.Path = "" 102 baseURL.WithoutPath = baseURLNoPath.String() 103 104 basePath := u.Path 105 if basePath != "" && basePath != "/" { 106 baseURL.BasePath = basePath 107 } 108 109 return baseURL, nil 110 }