Skip to content

Commit

Permalink
resources/page: Allow colons in permalinks to be escaped
Browse files Browse the repository at this point in the history
Updates #12918
  • Loading branch information
n1xx1 authored and bep committed Oct 15, 2024
1 parent 6b5e117 commit e7d0757
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
22 changes: 17 additions & 5 deletions resources/page/permalinks.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,22 @@ func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]ma
return p, nil
}

func (l PermalinkExpander) normalizeEscapeSequences(result string) string {
return strings.ReplaceAll(result, "\\:", ":")
}

// 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)
result, err := expander(p)
if err != nil {
return "", err
}
return l.normalizeEscapeSequences(result), nil
}

// Expand expands the path in p according to the rules defined for the given key.
Expand All @@ -132,7 +140,11 @@ func (l PermalinkExpander) Expand(key string, p Page) (string, error) {
return "", nil
}

return expand(p)
result, err := expand(p)
if err != nil {
return "", err
}
return l.normalizeEscapeSequences(result), nil
}

// Allow " " and / to represent the root section.
Expand All @@ -154,7 +166,7 @@ func (l PermalinkExpander) getOrParsePattern(pattern string) (func(Page) (string
callbacks := make([]pageToPermaAttribute, len(matches))
replacements := make([]string, len(matches))
for i, m := range matches {
replacement := m[0]
replacement := m[1]
attr := replacement[1:]
replacements[i] = replacement
callback, ok := l.callback(attr)
Expand Down Expand Up @@ -210,7 +222,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 {
Expand All @@ -234,7 +246,7 @@ func (l PermalinkExpander) validate(pp string) bool {
}

for _, match := range matches {
k := match[0][1:]
k := match[1][1:]
if _, ok := l.callback(k); !ok {
return false
}
Expand Down
7 changes: 7 additions & 0 deletions resources/page/permalinks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ var testdataPermalinks = []struct {
{"/:sections/", true, "/a/b/c/"}, // Sections
{"/:sections[last]/", true, "/c/"}, // Sections
{"/:sections[0]/:sections[last]/", true, "/a/c/"}, // Sections
{"/\\:filename", true, "/:filename"}, // Escape sequence
{"/special\\::slug/", true, "/special:the-slug/"}, // Escape sequence

// Failures
{"/blog/:fred", false, ""},
Expand Down Expand Up @@ -117,6 +119,7 @@ func TestPermalinkExpansionMultiSection(t *testing.T) {
"posts": "/:slug",
"blog": "/:section/:year",
"recipes": "/:slugorfilename",
"special": "/special\\::slug",
},
}
expander, err := NewPermalinkExpander(urlize, permalinksConfig)
Expand All @@ -137,6 +140,10 @@ func TestPermalinkExpansionMultiSection(t *testing.T) {
expanded, err = expander.Expand("recipes", page_slug_fallback)
c.Assert(err, qt.IsNil)
c.Assert(expanded, qt.Equals, "/page-filename")

expanded, err = expander.Expand("special", page)
c.Assert(err, qt.IsNil)
c.Assert(expanded, qt.Equals, "/special:the-slug")
}

func TestPermalinkExpansionConcurrent(t *testing.T) {
Expand Down

0 comments on commit e7d0757

Please sign in to comment.