github.com/lyeb/hugo@v0.47.1/tpl/urls/urls.go (about) 1 // Copyright 2017 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 "errors" 18 "fmt" 19 20 "github.com/russross/blackfriday" 21 22 "html/template" 23 "net/url" 24 25 "github.com/gohugoio/hugo/deps" 26 "github.com/spf13/cast" 27 ) 28 29 // New returns a new instance of the urls-namespaced template functions. 30 func New(deps *deps.Deps) *Namespace { 31 return &Namespace{ 32 deps: deps, 33 multihost: deps.Cfg.GetBool("multihost"), 34 } 35 } 36 37 // Namespace provides template functions for the "urls" namespace. 38 type Namespace struct { 39 deps *deps.Deps 40 multihost bool 41 } 42 43 // AbsURL takes a given string and converts it to an absolute URL. 44 func (ns *Namespace) AbsURL(a interface{}) (template.HTML, error) { 45 s, err := cast.ToStringE(a) 46 if err != nil { 47 return "", nil 48 } 49 50 return template.HTML(ns.deps.PathSpec.AbsURL(s, false)), nil 51 } 52 53 // Parse parses rawurl into a URL structure. The rawurl may be relative or 54 // absolute. 55 func (ns *Namespace) Parse(rawurl interface{}) (*url.URL, error) { 56 s, err := cast.ToStringE(rawurl) 57 if err != nil { 58 return nil, fmt.Errorf("Error in Parse: %s", err) 59 } 60 61 return url.Parse(s) 62 } 63 64 // RelURL takes a given string and prepends the relative path according to a 65 // page's position in the project directory structure. 66 func (ns *Namespace) RelURL(a interface{}) (template.HTML, error) { 67 s, err := cast.ToStringE(a) 68 if err != nil { 69 return "", nil 70 } 71 72 return template.HTML(ns.deps.PathSpec.RelURL(s, false)), nil 73 } 74 75 // URLize returns the given argument formatted as URL. 76 func (ns *Namespace) URLize(a interface{}) (string, error) { 77 s, err := cast.ToStringE(a) 78 if err != nil { 79 return "", nil 80 } 81 return ns.deps.PathSpec.URLize(s), nil 82 } 83 84 // Anchorize creates sanitized anchor names that are compatible with Blackfriday. 85 func (ns *Namespace) Anchorize(a interface{}) (string, error) { 86 s, err := cast.ToStringE(a) 87 if err != nil { 88 return "", nil 89 } 90 return blackfriday.SanitizedAnchorName(s), nil 91 } 92 93 type reflinker interface { 94 Ref(args map[string]interface{}) (string, error) 95 RelRef(args map[string]interface{}) (string, error) 96 } 97 98 // Ref returns the absolute URL path to a given content item. 99 func (ns *Namespace) Ref(in interface{}, args interface{}) (template.HTML, error) { 100 p, ok := in.(reflinker) 101 if !ok { 102 return "", errors.New("invalid Page received in Ref") 103 } 104 argsm, err := ns.refArgsToMap(args) 105 if err != nil { 106 return "", err 107 } 108 s, err := p.Ref(argsm) 109 return template.HTML(s), err 110 } 111 112 // RelRef returns the relative URL path to a given content item. 113 func (ns *Namespace) RelRef(in interface{}, args interface{}) (template.HTML, error) { 114 p, ok := in.(reflinker) 115 if !ok { 116 return "", errors.New("invalid Page received in RelRef") 117 } 118 argsm, err := ns.refArgsToMap(args) 119 if err != nil { 120 return "", err 121 } 122 123 s, err := p.RelRef(argsm) 124 return template.HTML(s), err 125 } 126 127 func (ns *Namespace) refArgsToMap(args interface{}) (map[string]interface{}, error) { 128 var ( 129 s string 130 of string 131 ) 132 switch v := args.(type) { 133 case map[string]interface{}: 134 return v, nil 135 case map[string]string: 136 m := make(map[string]interface{}) 137 for k, v := range v { 138 m[k] = v 139 } 140 return m, nil 141 case []string: 142 if len(v) == 0 || len(v) > 2 { 143 return nil, fmt.Errorf("invalid numer of arguments to ref") 144 } 145 // These where the options before we introduced the map type: 146 s = v[0] 147 if len(v) == 2 { 148 of = v[1] 149 } 150 default: 151 var err error 152 s, err = cast.ToStringE(args) 153 if err != nil { 154 return nil, err 155 } 156 157 } 158 return map[string]interface{}{ 159 "path": s, 160 "outputFormat": of, 161 }, nil 162 } 163 164 // RelLangURL takes a given string and prepends the relative path according to a 165 // page's position in the project directory structure and the current language. 166 func (ns *Namespace) RelLangURL(a interface{}) (template.HTML, error) { 167 s, err := cast.ToStringE(a) 168 if err != nil { 169 return "", err 170 } 171 172 return template.HTML(ns.deps.PathSpec.RelURL(s, !ns.multihost)), nil 173 } 174 175 // AbsLangURL takes a given string and converts it to an absolute URL according 176 // to a page's position in the project directory structure and the current 177 // language. 178 func (ns *Namespace) AbsLangURL(a interface{}) (template.HTML, error) { 179 s, err := cast.ToStringE(a) 180 if err != nil { 181 return "", err 182 } 183 184 return template.HTML(ns.deps.PathSpec.AbsURL(s, !ns.multihost)), nil 185 }