mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
parent
3eb313fef4
commit
d741064beb
8 changed files with 165 additions and 80 deletions
|
@ -81,6 +81,9 @@ weight: %d
|
|||
|
||||
Content.
|
||||
|
||||
SVP3-REF: {{< ref path="/sect/page3.md" lang="sv" >}}
|
||||
SVP3-RELREF: {{< relref path="/sect/page3.md" lang="sv" >}}
|
||||
|
||||
`
|
||||
|
||||
pageBundleTemplate := `
|
||||
|
@ -211,24 +214,32 @@ Content.
|
|||
assert.NoError(err)
|
||||
nnP2, err := nnSite.getPageNew(nil, "/sect/page2.md")
|
||||
assert.NoError(err)
|
||||
nnP2_2, err := svSite.getPageNew(nil, "/nn/sect/page2.md")
|
||||
assert.NoError(err)
|
||||
enP2_2, err := nnSite.getPageNew(nil, "/en/sect/page2.md")
|
||||
assert.NoError(err)
|
||||
svP2_2, err := enSite.getPageNew(nil, "/sv/sect/page2.md")
|
||||
assert.NoError(err)
|
||||
|
||||
enP2, err := enSite.getPageNew(nil, "/sect/page2.md")
|
||||
assert.NoError(err)
|
||||
assert.NotNil(enP2)
|
||||
assert.NotNil(svP2)
|
||||
assert.NotNil(nnP2)
|
||||
assert.Equal("en", enP2.Lang())
|
||||
assert.Equal("sv", svP2.Lang())
|
||||
assert.Equal("nn", nnP2.Lang())
|
||||
assert.Equal("en", enP2.Lang())
|
||||
assert.Equal(nnP2, nnP2_2)
|
||||
assert.Equal(enP2, enP2_2)
|
||||
assert.Equal(svP2, svP2_2)
|
||||
|
||||
content, _ := nnP2.Content()
|
||||
assert.Contains(content, "SVP3-REF: https://example.org/sv/sect/p-sv-3/")
|
||||
assert.Contains(content, "SVP3-RELREF: /sv/sect/p-sv-3/")
|
||||
|
||||
// Test RelRef with and without language indicator.
|
||||
nn3RefArgs := map[string]interface{}{
|
||||
"path": "/sect/page3.md",
|
||||
"lang": "nn",
|
||||
}
|
||||
nnP3RelRef, err := svP2.RelRef(
|
||||
nn3RefArgs,
|
||||
)
|
||||
assert.NoError(err)
|
||||
assert.Equal("/nn/sect/p-nn-3/", nnP3RelRef)
|
||||
nnP3Ref, err := svP2.Ref(
|
||||
nn3RefArgs,
|
||||
)
|
||||
assert.NoError(err)
|
||||
assert.Equal("https://example.org/nn/sect/p-nn-3/", nnP3Ref)
|
||||
|
||||
for i, p := range enSite.RegularPages {
|
||||
j := i + 1
|
||||
|
|
|
@ -2038,24 +2038,68 @@ func (p *Page) GetPage(ref string) (*Page, error) {
|
|||
return p.s.getPageNew(p, ref)
|
||||
}
|
||||
|
||||
func (p *Page) Ref(refs ...string) (string, error) {
|
||||
if len(refs) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
if len(refs) > 1 {
|
||||
return p.Site.Ref(refs[0], p, refs[1])
|
||||
}
|
||||
return p.Site.Ref(refs[0], p)
|
||||
type refArgs struct {
|
||||
Path string
|
||||
Lang string
|
||||
OutputFormat string
|
||||
}
|
||||
|
||||
func (p *Page) RelRef(refs ...string) (string, error) {
|
||||
if len(refs) == 0 {
|
||||
func (p *Page) decodeRefArgs(args map[string]interface{}) (refArgs, *SiteInfo, error) {
|
||||
var ra refArgs
|
||||
err := mapstructure.WeakDecode(args, &ra)
|
||||
if err != nil {
|
||||
return ra, nil, nil
|
||||
}
|
||||
s := p.Site
|
||||
|
||||
if ra.Lang != "" && ra.Lang != p.Lang() {
|
||||
// Find correct site
|
||||
found := false
|
||||
for _, ss := range p.s.owner.Sites {
|
||||
if ss.Lang() == ra.Lang {
|
||||
found = true
|
||||
s = &ss.Info
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return ra, nil, fmt.Errorf("no site found with lang %q", ra.Lang)
|
||||
}
|
||||
}
|
||||
|
||||
return ra, s, nil
|
||||
}
|
||||
|
||||
func (p *Page) Ref(argsm map[string]interface{}) (string, error) {
|
||||
args, s, err := p.decodeRefArgs(argsm)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid arguments to Ref: %s", err)
|
||||
}
|
||||
|
||||
if args.Path == "" {
|
||||
return "", nil
|
||||
}
|
||||
if len(refs) > 1 {
|
||||
return p.Site.RelRef(refs[0], p, refs[1])
|
||||
|
||||
if args.OutputFormat != "" {
|
||||
return s.Ref(args.Path, p, args.OutputFormat)
|
||||
}
|
||||
return p.Site.RelRef(refs[0], p)
|
||||
return s.Ref(args.Path, p)
|
||||
}
|
||||
|
||||
func (p *Page) RelRef(argsm map[string]interface{}) (string, error) {
|
||||
args, s, err := p.decodeRefArgs(argsm)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid arguments to Ref: %s", err)
|
||||
}
|
||||
|
||||
if args.Path == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if args.OutputFormat != "" {
|
||||
return s.RelRef(args.Path, p, args.OutputFormat)
|
||||
}
|
||||
return s.RelRef(args.Path, p)
|
||||
}
|
||||
|
||||
func (p *Page) String() string {
|
||||
|
|
|
@ -76,12 +76,6 @@ func (c *PageCollections) refreshPageCaches() {
|
|||
c.RegularPages = c.findPagesByKindIn(KindPage, c.Pages)
|
||||
c.AllRegularPages = c.findPagesByKindIn(KindPage, c.AllPages)
|
||||
|
||||
var s *Site
|
||||
|
||||
if len(c.Pages) > 0 {
|
||||
s = c.Pages[0].s
|
||||
}
|
||||
|
||||
indexLoader := func() (map[string]interface{}, error) {
|
||||
index := make(map[string]interface{})
|
||||
|
||||
|
@ -94,44 +88,34 @@ func (c *PageCollections) refreshPageCaches() {
|
|||
}
|
||||
}
|
||||
|
||||
// Note that we deliberately use the pages from all sites
|
||||
// in this index, as we intend to use this in the ref and relref
|
||||
// shortcodes.
|
||||
for _, pageCollection := range []Pages{c.AllRegularPages, c.headlessPages} {
|
||||
for _, pageCollection := range []Pages{c.RegularPages, c.headlessPages} {
|
||||
for _, p := range pageCollection {
|
||||
sourceRef := p.absoluteSourceRef()
|
||||
|
||||
// Allow cross language references by
|
||||
// adding the language code as prefix.
|
||||
add(path.Join("/"+p.Lang(), sourceRef), p)
|
||||
|
||||
// For pages in the current language.
|
||||
if s != nil && p.s == s {
|
||||
if sourceRef != "" {
|
||||
// index the canonical ref
|
||||
// e.g. /section/article.md
|
||||
add(sourceRef, p)
|
||||
}
|
||||
|
||||
// Ref/Relref supports this potentially ambiguous lookup.
|
||||
add(p.Source.LogicalName(), p)
|
||||
|
||||
translationBaseName := p.Source.TranslationBaseName()
|
||||
|
||||
dir, _ := path.Split(sourceRef)
|
||||
dir = strings.TrimSuffix(dir, "/")
|
||||
|
||||
if translationBaseName == "index" {
|
||||
add(dir, p)
|
||||
add(path.Base(dir), p)
|
||||
} else {
|
||||
add(translationBaseName, p)
|
||||
}
|
||||
|
||||
// We need a way to get to the current language version.
|
||||
pathWithNoExtensions := path.Join(dir, translationBaseName)
|
||||
add(pathWithNoExtensions, p)
|
||||
if sourceRef != "" {
|
||||
// index the canonical ref
|
||||
// e.g. /section/article.md
|
||||
add(sourceRef, p)
|
||||
}
|
||||
|
||||
// Ref/Relref supports this potentially ambiguous lookup.
|
||||
add(p.Source.LogicalName(), p)
|
||||
|
||||
translationBaseName := p.Source.TranslationBaseName()
|
||||
|
||||
dir, _ := path.Split(sourceRef)
|
||||
dir = strings.TrimSuffix(dir, "/")
|
||||
|
||||
if translationBaseName == "index" {
|
||||
add(dir, p)
|
||||
add(path.Base(dir), p)
|
||||
} else {
|
||||
add(translationBaseName, p)
|
||||
}
|
||||
|
||||
// We need a way to get to the current language version.
|
||||
pathWithNoExtensions := path.Join(dir, translationBaseName)
|
||||
add(pathWithNoExtensions, p)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,13 +55,13 @@ func (scp *ShortcodeWithPage) Site() *SiteInfo {
|
|||
}
|
||||
|
||||
// Ref is a shortcut to the Ref method on Page.
|
||||
func (scp *ShortcodeWithPage) Ref(ref string) (string, error) {
|
||||
return scp.Page.Ref(ref)
|
||||
func (scp *ShortcodeWithPage) Ref(args map[string]interface{}) (string, error) {
|
||||
return scp.Page.Ref(args)
|
||||
}
|
||||
|
||||
// RelRef is a shortcut to the RelRef method on Page.
|
||||
func (scp *ShortcodeWithPage) RelRef(ref string) (string, error) {
|
||||
return scp.Page.RelRef(ref)
|
||||
func (scp *ShortcodeWithPage) RelRef(args map[string]interface{}) (string, error) {
|
||||
return scp.Page.RelRef(args)
|
||||
}
|
||||
|
||||
// Scratch returns a scratch-pad scoped for this shortcode. This can be used
|
||||
|
|
|
@ -380,8 +380,8 @@ if (!doNotTrack) {
|
|||
</style>
|
||||
{{ end }}
|
||||
{{ end }}`},
|
||||
{`shortcodes/ref.html`, `{{ if len .Params | eq 2 }}{{ ref .Page (.Get 0) (.Get 1) }}{{ else }}{{ ref .Page (.Get 0) }}{{ end }}`},
|
||||
{`shortcodes/relref.html`, `{{ if len .Params | eq 2 }}{{ relref .Page (.Get 0) (.Get 1) }}{{ else }}{{ relref .Page (.Get 0) }}{{ end }}`},
|
||||
{`shortcodes/ref.html`, `{{ ref .Page .Params }}`},
|
||||
{`shortcodes/relref.html`, `{{ relref .Page .Params }}`},
|
||||
{`shortcodes/twitter.html`, `{{- $pc := .Page.Site.Config.Privacy.Twitter -}}
|
||||
{{- if not $pc.Disable -}}
|
||||
{{- if $pc.Simple -}}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{{ if len .Params | eq 2 }}{{ ref .Page (.Get 0) (.Get 1) }}{{ else }}{{ ref .Page (.Get 0) }}{{ end }}
|
||||
{{ ref .Page .Params }}
|
|
@ -1 +1 @@
|
|||
{{ if len .Params | eq 2 }}{{ relref .Page (.Get 0) (.Get 1) }}{{ else }}{{ relref .Page (.Get 0) }}{{ end }}
|
||||
{{ relref .Page .Params }}
|
|
@ -91,30 +91,76 @@ func (ns *Namespace) Anchorize(a interface{}) (string, error) {
|
|||
}
|
||||
|
||||
type reflinker interface {
|
||||
Ref(refs ...string) (string, error)
|
||||
RelRef(refs ...string) (string, error)
|
||||
Ref(args map[string]interface{}) (string, error)
|
||||
RelRef(args map[string]interface{}) (string, error)
|
||||
}
|
||||
|
||||
// Ref returns the absolute URL path to a given content item.
|
||||
func (ns *Namespace) Ref(in interface{}, refs ...string) (template.HTML, error) {
|
||||
func (ns *Namespace) Ref(in interface{}, args interface{}) (template.HTML, error) {
|
||||
p, ok := in.(reflinker)
|
||||
if !ok {
|
||||
return "", errors.New("invalid Page received in Ref")
|
||||
}
|
||||
s, err := p.Ref(refs...)
|
||||
argsm, err := ns.refArgsToMap(args)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s, err := p.Ref(argsm)
|
||||
return template.HTML(s), err
|
||||
}
|
||||
|
||||
// RelRef returns the relative URL path to a given content item.
|
||||
func (ns *Namespace) RelRef(in interface{}, refs ...string) (template.HTML, error) {
|
||||
func (ns *Namespace) RelRef(in interface{}, args interface{}) (template.HTML, error) {
|
||||
p, ok := in.(reflinker)
|
||||
if !ok {
|
||||
return "", errors.New("invalid Page received in RelRef")
|
||||
}
|
||||
s, err := p.RelRef(refs...)
|
||||
argsm, err := ns.refArgsToMap(args)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
s, err := p.RelRef(argsm)
|
||||
return template.HTML(s), err
|
||||
}
|
||||
|
||||
func (ns *Namespace) refArgsToMap(args interface{}) (map[string]interface{}, error) {
|
||||
var (
|
||||
s string
|
||||
of string
|
||||
)
|
||||
switch v := args.(type) {
|
||||
case map[string]interface{}:
|
||||
return v, nil
|
||||
case map[string]string:
|
||||
m := make(map[string]interface{})
|
||||
for k, v := range v {
|
||||
m[k] = v
|
||||
}
|
||||
return m, nil
|
||||
case []string:
|
||||
if len(v) == 0 || len(v) > 2 {
|
||||
return nil, fmt.Errorf("invalid numer of arguments to ref")
|
||||
}
|
||||
// These where the options before we introduced the map type:
|
||||
s = v[0]
|
||||
if len(v) == 2 {
|
||||
of = v[1]
|
||||
}
|
||||
default:
|
||||
var err error
|
||||
s, err = cast.ToStringE(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"path": s,
|
||||
"outputFormat": of,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RelLangURL takes a given string and prepends the relative path according to a
|
||||
// page's position in the project directory structure and the current language.
|
||||
func (ns *Namespace) RelLangURL(a interface{}) (template.HTML, error) {
|
||||
|
|
Loading…
Reference in a new issue