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 14package paths 15 16import ( 17 "fmt" 18 "net/url" 19 "strings" 20) 21 22// A BaseURL in Hugo is normally on the form scheme://path, but the 23// form scheme: is also valid (mailto:hugo@rules.com). 24type BaseURL struct { 25 url *url.URL 26 urlStr string 27} 28 29func (b BaseURL) String() string { 30 if b.urlStr != "" { 31 return b.urlStr 32 } 33 return b.url.String() 34} 35 36func (b BaseURL) Path() string { 37 return b.url.Path 38} 39 40// HostURL returns the URL to the host root without any path elements. 41func (b BaseURL) HostURL() string { 42 return strings.TrimSuffix(b.String(), b.Path()) 43} 44 45// WithProtocol returns the BaseURL prefixed with the given protocol. 46// The Protocol is normally of the form "scheme://", i.e. "webcal://". 47func (b BaseURL) WithProtocol(protocol string) (string, error) { 48 u := b.URL() 49 50 scheme := protocol 51 isFullProtocol := strings.HasSuffix(scheme, "://") 52 isOpaqueProtocol := strings.HasSuffix(scheme, ":") 53 54 if isFullProtocol { 55 scheme = strings.TrimSuffix(scheme, "://") 56 } else if isOpaqueProtocol { 57 scheme = strings.TrimSuffix(scheme, ":") 58 } 59 60 u.Scheme = scheme 61 62 if isFullProtocol && u.Opaque != "" { 63 u.Opaque = "//" + u.Opaque 64 } else if isOpaqueProtocol && u.Opaque == "" { 65 return "", fmt.Errorf("cannot determine BaseURL for protocol %q", protocol) 66 } 67 68 return u.String(), nil 69} 70 71// URL returns a copy of the internal URL. 72// The copy can be safely used and modified. 73func (b BaseURL) URL() *url.URL { 74 c := *b.url 75 return &c 76} 77 78func newBaseURLFromString(b string) (BaseURL, error) { 79 var result BaseURL 80 81 base, err := url.Parse(b) 82 if err != nil { 83 return result, err 84 } 85 86 return BaseURL{url: base, urlStr: base.String()}, nil 87} 88