From 292433d200ba280b768897af26098b7bab359f7c Mon Sep 17 00:00:00 2001 From: Mia Winter Date: Tue, 30 Apr 2024 15:47:42 +0200 Subject: [PATCH] Improved Article slug generation --- Wave/Data/Article.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Wave/Data/Article.cs b/Wave/Data/Article.cs index 0cba687..1cb9579 100644 --- a/Wave/Data/Article.cs +++ b/Wave/Data/Article.cs @@ -46,20 +46,26 @@ public class Article : ISoftDelete { public IList Categories { get; } = []; public IList Images { get; } = []; - public void UpdateSlug(string? potentialNewSlug) { + public void UpdateSlug(string? potentialNewSlug = null) { + if (!string.IsNullOrWhiteSpace(potentialNewSlug) && Uri.IsWellFormedUriString(potentialNewSlug, UriKind.Relative)) { + Slug = potentialNewSlug; + return; + } + if (string.IsNullOrWhiteSpace(potentialNewSlug) && !string.IsNullOrWhiteSpace(Slug)) return; - + string baseSlug = potentialNewSlug ?? Title; baseSlug = baseSlug.ToLowerInvariant()[..Math.Min(64, baseSlug.Length)]; string slug = Uri.EscapeDataString(baseSlug).Replace("-", "+").Replace("%20", "-"); // if our escaping increases the slug length, there is a chance it ends with an escape // character, so if this overshoot is not divisible by 3, then we risk cutting of the // escape character, so we need to remove it in it's entirely if that's the case - int escapeTrimOvershoot = Math.Max(0, 3 - (slug.Length - baseSlug.Length) % 3); + int escapeTrimOvershoot = 0; + if (slug.Length > 64) escapeTrimOvershoot = slug[62..64].Contains('%') ? 1 : 0; // if the slug already fits 64 character, there will be no cutoff in the next operation anyway, // so we don't need to fix what is described in the previous comment - if (slug.Length <= 64) escapeTrimOvershoot = 0; Slug = slug[..Math.Min(slug.Length, 64 - escapeTrimOvershoot)]; + if (Slug.EndsWith("%")) Slug = Slug[..^1]; } public void UpdateBody() {