mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-27 22:09:53 +02:00
committed by
GitHub
parent
4d22ad580e
commit
2dc222cec4
@@ -16,6 +16,7 @@ package page
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -54,6 +55,13 @@ func (p PermalinkExpander) callback(attr string) (pageToPermaAttribute, bool) {
|
||||
return p.pageToPermalinkDate, true
|
||||
}
|
||||
|
||||
if strings.HasPrefix(attr, "sections[") {
|
||||
fn := p.toSliceFunc(strings.TrimPrefix(attr, "sections"))
|
||||
return func(p Page, s string) (string, error) {
|
||||
return path.Join(fn(p.CurrentSection().SectionsEntries())...), nil
|
||||
}, true
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@@ -112,6 +120,7 @@ func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Pa
|
||||
|
||||
for k, pattern := range patterns {
|
||||
k = strings.Trim(k, sectionCutSet)
|
||||
|
||||
if !l.validate(pattern) {
|
||||
return nil, &permalinkExpandError{pattern: pattern, err: errPermalinkIllFormed}
|
||||
}
|
||||
@@ -165,7 +174,7 @@ func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Pa
|
||||
// can return a string to go in that position in the page (or an error)
|
||||
type pageToPermaAttribute func(Page, string) (string, error)
|
||||
|
||||
var attributeRegexp = regexp.MustCompile(`:\w+`)
|
||||
var attributeRegexp = regexp.MustCompile(`:\w+(\[.+\])?`)
|
||||
|
||||
// validate determines if a PathPattern is well-formed
|
||||
func (l PermalinkExpander) validate(pp string) bool {
|
||||
@@ -263,3 +272,90 @@ func (l PermalinkExpander) pageToPermalinkSection(p Page, _ string) (string, err
|
||||
func (l PermalinkExpander) pageToPermalinkSections(p Page, _ string) (string, error) {
|
||||
return p.CurrentSection().SectionsPath(), nil
|
||||
}
|
||||
|
||||
var (
|
||||
nilSliceFunc = func(s []string) []string {
|
||||
return nil
|
||||
}
|
||||
allSliceFunc = func(s []string) []string {
|
||||
return s
|
||||
}
|
||||
)
|
||||
|
||||
// toSliceFunc returns a slice func that slices s according to the cut spec.
|
||||
// The cut spec must be on form [low:high] (one or both can be omitted),
|
||||
// also allowing single slice indices (e.g. [2]) and the special [last] keyword
|
||||
// giving the last element of the slice.
|
||||
// The returned function will be lenient and not panic in out of bounds situation.
|
||||
//
|
||||
// The current use case for this is to use parts of the sections path in permalinks.
|
||||
func (l PermalinkExpander) toSliceFunc(cut string) func(s []string) []string {
|
||||
cut = strings.ToLower(strings.TrimSpace(cut))
|
||||
if cut == "" {
|
||||
return allSliceFunc
|
||||
}
|
||||
|
||||
if len(cut) < 3 || (cut[0] != '[' || cut[len(cut)-1] != ']') {
|
||||
return nilSliceFunc
|
||||
}
|
||||
|
||||
toNFunc := func(s string, low bool) func(ss []string) int {
|
||||
if s == "" {
|
||||
if low {
|
||||
return func(ss []string) int {
|
||||
return 0
|
||||
}
|
||||
} else {
|
||||
return func(ss []string) int {
|
||||
return len(ss)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s == "last" {
|
||||
return func(ss []string) int {
|
||||
return len(ss) - 1
|
||||
}
|
||||
}
|
||||
|
||||
n, _ := strconv.Atoi(s)
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
return func(ss []string) int {
|
||||
// Prevent out of bound situations. It would not make
|
||||
// much sense to panic here.
|
||||
if n > len(ss) {
|
||||
return len(ss)
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
opsStr := cut[1 : len(cut)-1]
|
||||
opts := strings.Split(opsStr, ":")
|
||||
|
||||
if !strings.Contains(opsStr, ":") {
|
||||
toN := toNFunc(opts[0], true)
|
||||
return func(s []string) []string {
|
||||
if len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
v := s[toN(s)]
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return []string{v}
|
||||
}
|
||||
}
|
||||
|
||||
toN1, toN2 := toNFunc(opts[0], true), toNFunc(opts[1], false)
|
||||
|
||||
return func(s []string) []string {
|
||||
if len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s[toN1(s):toN2(s)]
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user