mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
helpers: Consolidate MakeSegment vs MakePathSanitized
In short: * Avoid double tolower in MakeSegment * Use MakePathSanitized for taxonomies in pageToPermalinkTitle; this matches what MakeSegment does. * Move the "double hyphen and space" logic into UnicodeSanitize The last bullet may be slightly breaking for some that now does not get the "--" in some URLs, but we need to reduce the amount of URL logic. See #4926
This commit is contained in:
parent
4b4af2c52e
commit
e421696d02
3 changed files with 19 additions and 26 deletions
|
@ -81,26 +81,8 @@ var segmentReplacer = strings.NewReplacer("/", "-", "#", "-")
|
||||||
// segment. MakeSegment is similar to MakePath but disallows the '/' and
|
// segment. MakeSegment is similar to MakePath but disallows the '/' and
|
||||||
// '#' characters because of their reserved meaning in URIs.
|
// '#' characters because of their reserved meaning in URIs.
|
||||||
func (p *PathSpec) MakeSegment(s string) string {
|
func (p *PathSpec) MakeSegment(s string) string {
|
||||||
s = p.MakePathSanitized(strings.Trim(segmentReplacer.Replace(s), "- "))
|
return p.MakePathSanitized(segmentReplacer.Replace(s))
|
||||||
|
|
||||||
var pos int
|
|
||||||
var last byte
|
|
||||||
b := make([]byte, len(s))
|
|
||||||
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
// consolidate dashes
|
|
||||||
if s[i] == '-' && last == '-' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
b[pos], last = s[i], s[i]
|
|
||||||
pos++
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.DisablePathToLower {
|
|
||||||
return string(b[:pos])
|
|
||||||
}
|
|
||||||
return strings.ToLower(string(b[:pos]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakePath takes a string with any characters and replace it
|
// MakePath takes a string with any characters and replace it
|
||||||
|
@ -109,7 +91,7 @@ func (p *PathSpec) MakeSegment(s string) string {
|
||||||
// whilst preserving the original casing of the string.
|
// whilst preserving the original casing of the string.
|
||||||
// E.g. Social Media -> Social-Media
|
// E.g. Social Media -> Social-Media
|
||||||
func (p *PathSpec) MakePath(s string) string {
|
func (p *PathSpec) MakePath(s string) string {
|
||||||
return p.UnicodeSanitize(strings.Replace(strings.TrimSpace(s), " ", "-", -1))
|
return p.UnicodeSanitize(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakePathSanitized creates a Unicode-sanitized string, with the spaces replaced
|
// MakePathSanitized creates a Unicode-sanitized string, with the spaces replaced
|
||||||
|
@ -148,15 +130,25 @@ func ishex(c rune) bool {
|
||||||
// a predefined set of special Unicode characters.
|
// a predefined set of special Unicode characters.
|
||||||
// If RemovePathAccents configuration flag is enabled, Uniccode accents
|
// If RemovePathAccents configuration flag is enabled, Uniccode accents
|
||||||
// are also removed.
|
// are also removed.
|
||||||
|
// Spaces will be replaced with a single hyphen, and sequential hyphens will be reduced to one.
|
||||||
func (p *PathSpec) UnicodeSanitize(s string) string {
|
func (p *PathSpec) UnicodeSanitize(s string) string {
|
||||||
source := []rune(s)
|
source := []rune(s)
|
||||||
target := make([]rune, 0, len(source))
|
target := make([]rune, 0, len(source))
|
||||||
|
var prependHyphen bool
|
||||||
|
|
||||||
for i, r := range source {
|
for i, r := range source {
|
||||||
if r == '%' && i+2 < len(source) && ishex(source[i+1]) && ishex(source[i+2]) {
|
isAllowed := r == '.' || r == '/' || r == '\\' || r == '_' || r == '#' || r == '+' || r == '~'
|
||||||
target = append(target, r)
|
isAllowed = isAllowed || unicode.IsLetter(r) || unicode.IsDigit(r) || unicode.IsMark(r)
|
||||||
} else if unicode.IsLetter(r) || unicode.IsDigit(r) || unicode.IsMark(r) || r == '.' || r == '/' || r == '\\' || r == '_' || r == '-' || r == '#' || r == '+' || r == '~' {
|
isAllowed = isAllowed || (r == '%' && i+2 < len(source) && ishex(source[i+1]) && ishex(source[i+2]))
|
||||||
|
|
||||||
|
if isAllowed {
|
||||||
|
if prependHyphen {
|
||||||
|
target = append(target, '-')
|
||||||
|
prependHyphen = false
|
||||||
|
}
|
||||||
target = append(target, r)
|
target = append(target, r)
|
||||||
|
} else if len(target) > 0 && (r == '-' || unicode.IsSpace(r)) {
|
||||||
|
prependHyphen = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,8 @@ func TestMakeSegment(t *testing.T) {
|
||||||
{"Your #1 Fan", "your-1-fan"},
|
{"Your #1 Fan", "your-1-fan"},
|
||||||
{"Red & Blue", "red-blue"},
|
{"Red & Blue", "red-blue"},
|
||||||
{"double//slash", "double-slash"},
|
{"double//slash", "double-slash"},
|
||||||
{"My // Taxonomy", "my-taxonomy"},
|
{"triple///slash", "triple-slash"},
|
||||||
|
{"-my/way-", "my-way"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
|
@ -152,10 +152,10 @@ func pageToPermalinkDate(p *Page, dateField string) (string, error) {
|
||||||
|
|
||||||
// pageToPermalinkTitle returns the URL-safe form of the title
|
// pageToPermalinkTitle returns the URL-safe form of the title
|
||||||
func pageToPermalinkTitle(p *Page, _ string) (string, error) {
|
func pageToPermalinkTitle(p *Page, _ string) (string, error) {
|
||||||
if p.Kind == "taxonomy" {
|
if p.Kind == KindTaxonomy {
|
||||||
// Taxonomies are allowed to have '/' characters, so don't normalize
|
// Taxonomies are allowed to have '/' characters, so don't normalize
|
||||||
// them with MakeSegment.
|
// them with MakeSegment.
|
||||||
return p.s.PathSpec.URLize(p.title), nil
|
return p.s.PathSpec.MakePathSanitized(p.title), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.s.PathSpec.MakeSegment(p.title), nil
|
return p.s.PathSpec.MakeSegment(p.title), nil
|
||||||
|
|
Loading…
Reference in a new issue