resources/page: Expand parmalinks tokens in url

This change allows to use permalink tokens in url front matter fields. This should be useful to target more specific pages instead of using a global permalink configuration. It's expected to be used with cascade.

Fixes #9714
This commit is contained in:
n1xx1
2024-08-01 12:14:29 +02:00
committed by GitHub
parent 92573012e8
commit 566fe7ba12
7 changed files with 101 additions and 21 deletions

View File

@@ -40,6 +40,8 @@ type PermalinkExpander struct {
expanders map[string]map[string]func(Page) (string, error)
urlize func(uri string) string
patternCache *maps.Cache[string, func(Page) (string, error)]
}
// Time for checking date formats. Every field is different than the
@@ -71,7 +73,10 @@ func (p PermalinkExpander) callback(attr string) (pageToPermaAttribute, bool) {
// NewPermalinkExpander creates a new PermalinkExpander configured by the given
// urlize func.
func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]map[string]string) (PermalinkExpander, error) {
p := PermalinkExpander{urlize: urlize}
p := PermalinkExpander{
urlize: urlize,
patternCache: maps.NewCache[string, func(Page) (string, error)](),
}
p.knownPermalinkAttributes = map[string]pageToPermaAttribute{
"year": p.pageToPermalinkDate,
@@ -102,6 +107,16 @@ func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]ma
return p, nil
}
// ExpandPattern expands the path in p with the specified expand pattern.
func (l PermalinkExpander) ExpandPattern(pattern string, p Page) (string, error) {
expander, err := l.getOrParsePattern(pattern)
if err != nil {
return "", err
}
return expander(p)
}
// Expand expands the path in p according to the rules defined for the given key.
// If no rules are found for the given key, an empty string is returned.
func (l PermalinkExpander) Expand(key string, p Page) (string, error) {
@@ -129,17 +144,11 @@ func init() {
}
}
func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Page) (string, error), error) {
expanders := make(map[string]func(Page) (string, error))
for k, pattern := range patterns {
k = strings.Trim(k, sectionCutSet)
func (l PermalinkExpander) getOrParsePattern(pattern string) (func(Page) (string, error), error) {
return l.patternCache.GetOrCreate(pattern, func() (func(Page) (string, error), error) {
if !l.validate(pattern) {
return nil, &permalinkExpandError{pattern: pattern, err: errPermalinkIllFormed}
}
pattern := pattern
matches := attributeRegexp.FindAllStringSubmatch(pattern, -1)
callbacks := make([]pageToPermaAttribute, len(matches))
@@ -157,7 +166,7 @@ func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Pa
callbacks[i] = callback
}
expanders[k] = func(p Page) (string, error) {
return func(p Page) (string, error) {
if matches == nil {
return pattern, nil
}
@@ -173,12 +182,25 @@ func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Pa
}
newField = strings.Replace(newField, replacement, newAttr, 1)
}
return newField, nil
}, nil
})
}
func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Page) (string, error), error) {
expanders := make(map[string]func(Page) (string, error))
for k, pattern := range patterns {
k = strings.Trim(k, sectionCutSet)
expander, err := l.getOrParsePattern(pattern)
if err != nil {
return nil, err
}
expanders[k] = expander
}
return expanders, nil