fix(wiki): preserve slashes in page titles #535

Merged
jmiller merged 1 commits from feat/79-wiki-folders into dev 2026-06-06 20:16:57 +00:00
+25 -9
View File
@@ -151,14 +151,16 @@ func WebPathFromRequest(s string) WebPath {
var multiHyphenRe = regexp.MustCompile(`-{2,}`)
var nonSlugRe = regexp.MustCompile(`[^a-zA-Z0-9+.\-]`)
var nonSlugReWithSlash = regexp.MustCompile(`[^a-zA-Z0-9+.\-/]`)
// sanitizeWikiTitle converts a user-provided title into a clean, URL-friendly slug.
// Spaces and special characters become hyphens, consecutive hyphens collapse to one.
// Preserves: letters, digits, hyphens, plus signs (+), and dots (.)
// Preserves: letters, digits, hyphens, plus signs (+), dots (.), and slashes (/).
func sanitizeWikiTitle(title string) string {
title = strings.TrimSpace(title)
title = strings.ReplaceAll(title, " ", "-")
title = nonSlugRe.ReplaceAllString(title, "-")
// Preserve slashes as directory separators
title = nonSlugReWithSlash.ReplaceAllString(title, "-")
title = multiHyphenRe.ReplaceAllString(title, "-")
title = strings.NewReplacer("-+-", "-", "+-", "-", "-+", "-").Replace(title) // clean stray plus signs
title = strings.Trim(title, "-+.")
@@ -166,14 +168,28 @@ func sanitizeWikiTitle(title string) string {
}
func UserTitleToWebPath(base, title string) WebPath {
// TODO: no support for subdirectory, because the old wiki code's behavior is always using %2F, instead of subdirectory.
// So we do not add the support for writing slashes in title at the moment.
title = sanitizeWikiTitle(title)
title = util.PathJoinRelX(base, escapeSegToWeb(title, false))
if title == "" || title == "." {
title = "unnamed"
// MokoGitea: support subdirectories - slashes in title create folder structure.
// Split on /, sanitize each segment, rejoin.
parts := strings.Split(title, "/")
sanitized := make([]string, 0, len(parts))
for _, p := range parts {
p = strings.TrimSpace(p)
if p == "" {
continue
}
p = sanitizeWikiTitle(p)
if p != "" {
sanitized = append(sanitized, escapeSegToWeb(p, false))
}
}
return WebPath(title)
result := strings.Join(sanitized, "/")
if base != "" {
result = util.PathJoinRelX(base, result)
}
if result == "" || result == "." {
result = "unnamed"
}
return WebPath(result)
}
// ToWikiPageMetaData converts meta information to a WikiPageMetaData