mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
parent
3eb313fef4
commit
d741064beb
8 changed files with 165 additions and 80 deletions
|
@ -81,6 +81,9 @@ weight: %d
|
||||||
|
|
||||||
Content.
|
Content.
|
||||||
|
|
||||||
|
SVP3-REF: {{< ref path="/sect/page3.md" lang="sv" >}}
|
||||||
|
SVP3-RELREF: {{< relref path="/sect/page3.md" lang="sv" >}}
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
pageBundleTemplate := `
|
pageBundleTemplate := `
|
||||||
|
@ -211,24 +214,32 @@ Content.
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
nnP2, err := nnSite.getPageNew(nil, "/sect/page2.md")
|
nnP2, err := nnSite.getPageNew(nil, "/sect/page2.md")
|
||||||
assert.NoError(err)
|
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")
|
enP2, err := enSite.getPageNew(nil, "/sect/page2.md")
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
assert.NotNil(enP2)
|
assert.Equal("en", enP2.Lang())
|
||||||
assert.NotNil(svP2)
|
|
||||||
assert.NotNil(nnP2)
|
|
||||||
assert.Equal("sv", svP2.Lang())
|
assert.Equal("sv", svP2.Lang())
|
||||||
assert.Equal("nn", nnP2.Lang())
|
assert.Equal("nn", nnP2.Lang())
|
||||||
assert.Equal("en", enP2.Lang())
|
|
||||||
assert.Equal(nnP2, nnP2_2)
|
content, _ := nnP2.Content()
|
||||||
assert.Equal(enP2, enP2_2)
|
assert.Contains(content, "SVP3-REF: https://example.org/sv/sect/p-sv-3/")
|
||||||
assert.Equal(svP2, svP2_2)
|
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 {
|
for i, p := range enSite.RegularPages {
|
||||||
j := i + 1
|
j := i + 1
|
||||||
|
|
|
@ -2038,24 +2038,68 @@ func (p *Page) GetPage(ref string) (*Page, error) {
|
||||||
return p.s.getPageNew(p, ref)
|
return p.s.getPageNew(p, ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Page) Ref(refs ...string) (string, error) {
|
type refArgs struct {
|
||||||
if len(refs) == 0 {
|
Path string
|
||||||
return "", nil
|
Lang string
|
||||||
}
|
OutputFormat string
|
||||||
if len(refs) > 1 {
|
|
||||||
return p.Site.Ref(refs[0], p, refs[1])
|
|
||||||
}
|
|
||||||
return p.Site.Ref(refs[0], p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Page) RelRef(refs ...string) (string, error) {
|
func (p *Page) decodeRefArgs(args map[string]interface{}) (refArgs, *SiteInfo, error) {
|
||||||
if len(refs) == 0 {
|
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
|
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 {
|
func (p *Page) String() string {
|
||||||
|
|
|
@ -76,12 +76,6 @@ func (c *PageCollections) refreshPageCaches() {
|
||||||
c.RegularPages = c.findPagesByKindIn(KindPage, c.Pages)
|
c.RegularPages = c.findPagesByKindIn(KindPage, c.Pages)
|
||||||
c.AllRegularPages = c.findPagesByKindIn(KindPage, c.AllPages)
|
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) {
|
indexLoader := func() (map[string]interface{}, error) {
|
||||||
index := make(map[string]interface{})
|
index := make(map[string]interface{})
|
||||||
|
|
||||||
|
@ -94,19 +88,10 @@ func (c *PageCollections) refreshPageCaches() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we deliberately use the pages from all sites
|
for _, pageCollection := range []Pages{c.RegularPages, c.headlessPages} {
|
||||||
// in this index, as we intend to use this in the ref and relref
|
|
||||||
// shortcodes.
|
|
||||||
for _, pageCollection := range []Pages{c.AllRegularPages, c.headlessPages} {
|
|
||||||
for _, p := range pageCollection {
|
for _, p := range pageCollection {
|
||||||
sourceRef := p.absoluteSourceRef()
|
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 != "" {
|
if sourceRef != "" {
|
||||||
// index the canonical ref
|
// index the canonical ref
|
||||||
// e.g. /section/article.md
|
// e.g. /section/article.md
|
||||||
|
@ -133,7 +118,6 @@ func (c *PageCollections) refreshPageCaches() {
|
||||||
add(pathWithNoExtensions, p)
|
add(pathWithNoExtensions, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for _, p := range c.indexPages {
|
for _, p := range c.indexPages {
|
||||||
// index the canonical, unambiguous ref for any backing file
|
// index the canonical, unambiguous ref for any backing file
|
||||||
|
|
|
@ -55,13 +55,13 @@ func (scp *ShortcodeWithPage) Site() *SiteInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ref is a shortcut to the Ref method on Page.
|
// Ref is a shortcut to the Ref method on Page.
|
||||||
func (scp *ShortcodeWithPage) Ref(ref string) (string, error) {
|
func (scp *ShortcodeWithPage) Ref(args map[string]interface{}) (string, error) {
|
||||||
return scp.Page.Ref(ref)
|
return scp.Page.Ref(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RelRef is a shortcut to the RelRef method on Page.
|
// RelRef is a shortcut to the RelRef method on Page.
|
||||||
func (scp *ShortcodeWithPage) RelRef(ref string) (string, error) {
|
func (scp *ShortcodeWithPage) RelRef(args map[string]interface{}) (string, error) {
|
||||||
return scp.Page.RelRef(ref)
|
return scp.Page.RelRef(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scratch returns a scratch-pad scoped for this shortcode. This can be used
|
// Scratch returns a scratch-pad scoped for this shortcode. This can be used
|
||||||
|
|
|
@ -380,8 +380,8 @@ if (!doNotTrack) {
|
||||||
</style>
|
</style>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}`},
|
{{ end }}`},
|
||||||
{`shortcodes/ref.html`, `{{ if len .Params | eq 2 }}{{ ref .Page (.Get 0) (.Get 1) }}{{ else }}{{ ref .Page (.Get 0) }}{{ end }}`},
|
{`shortcodes/ref.html`, `{{ ref .Page .Params }}`},
|
||||||
{`shortcodes/relref.html`, `{{ if len .Params | eq 2 }}{{ relref .Page (.Get 0) (.Get 1) }}{{ else }}{{ relref .Page (.Get 0) }}{{ end }}`},
|
{`shortcodes/relref.html`, `{{ relref .Page .Params }}`},
|
||||||
{`shortcodes/twitter.html`, `{{- $pc := .Page.Site.Config.Privacy.Twitter -}}
|
{`shortcodes/twitter.html`, `{{- $pc := .Page.Site.Config.Privacy.Twitter -}}
|
||||||
{{- if not $pc.Disable -}}
|
{{- if not $pc.Disable -}}
|
||||||
{{- if $pc.Simple -}}
|
{{- 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 {
|
type reflinker interface {
|
||||||
Ref(refs ...string) (string, error)
|
Ref(args map[string]interface{}) (string, error)
|
||||||
RelRef(refs ...string) (string, error)
|
RelRef(args map[string]interface{}) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ref returns the absolute URL path to a given content item.
|
// 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)
|
p, ok := in.(reflinker)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", errors.New("invalid Page received in Ref")
|
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
|
return template.HTML(s), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RelRef returns the relative URL path to a given content item.
|
// 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)
|
p, ok := in.(reflinker)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", errors.New("invalid Page received in RelRef")
|
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
|
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
|
// 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.
|
// page's position in the project directory structure and the current language.
|
||||||
func (ns *Namespace) RelLangURL(a interface{}) (template.HTML, error) {
|
func (ns *Namespace) RelLangURL(a interface{}) (template.HTML, error) {
|
||||||
|
|
Loading…
Reference in a new issue