hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

urls.go (4825B)

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