< Summary

Information
Class: Chronicis.Shared.Utilities.SlugGenerator
Assembly: Chronicis.Shared
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Shared/Utilities/SlugGenerator.cs
Line coverage
78%
Covered lines: 15
Uncovered lines: 4
Coverable lines: 19
Total lines: 76
Line coverage: 78.9%
Branch coverage
60%
Covered branches: 6
Total branches: 10
Branch coverage: 60%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
GenerateSlug(...)50%4487.5%
IsValidSlug(...)0%620%
GenerateUniqueSlug(...)100%44100%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Shared/Utilities/SlugGenerator.cs

#LineLine coverage
 1using System.Text.RegularExpressions;
 2
 3namespace Chronicis.Shared.Utilities;
 4
 5/// <summary>
 6/// Utility class for generating URL-safe slugs from article titles.
 7/// </summary>
 8public static class SlugGenerator
 9{
 110    private static readonly Regex InvalidCharsRegex = new(@"[^a-z0-9-]", RegexOptions.Compiled);
 111    private static readonly Regex MultipleHyphensRegex = new(@"-{2,}", RegexOptions.Compiled);
 12
 13    /// <summary>
 14    /// Generates a URL-safe slug from a title.
 15    /// Rules:
 16    /// - Converts to lowercase
 17    /// - Replaces spaces with hyphens
 18    /// - Removes all characters except a-z, 0-9, and hyphens
 19    /// - Collapses multiple consecutive hyphens into single hyphen
 20    /// - Trims hyphens from start and end
 21    /// - Returns "untitled" if result is empty
 22    /// </summary>
 23    public static string GenerateSlug(string title)
 24    {
 925        if (string.IsNullOrWhiteSpace(title))
 026            return "untitled";
 27
 28        // Convert to lowercase
 929        var slug = title.ToLowerInvariant();
 30
 31        // Replace spaces with hyphens
 932        slug = slug.Replace(" ", "-");
 33
 34        // Remove invalid characters (keep only a-z, 0-9, hyphens)
 935        slug = InvalidCharsRegex.Replace(slug, string.Empty);
 36
 37        // Replace multiple consecutive hyphens with single hyphen
 938        slug = MultipleHyphensRegex.Replace(slug, "-");
 39
 40        // Trim hyphens from start and end
 941        slug = slug.Trim('-');
 42
 943        return string.IsNullOrEmpty(slug) ? "untitled" : slug;
 44    }
 45
 46    /// <summary>
 47    /// Validates if a slug is URL-safe.
 48    /// </summary>
 49    public static bool IsValidSlug(string slug)
 50    {
 051        if (string.IsNullOrWhiteSpace(slug))
 052            return false;
 53
 54        // Must be lowercase alphanumeric and hyphens only
 055        return Regex.IsMatch(slug, @"^[a-z0-9-]+$");
 56    }
 57
 58    /// <summary>
 59    /// Generates a unique slug by appending a counter if needed.
 60    /// </summary>
 61    public static string GenerateUniqueSlug(string baseSlug, HashSet<string> existingSlugs)
 62    {
 963        if (!existingSlugs.Contains(baseSlug))
 764            return baseSlug;
 65
 266        var counter = 2;
 67        string uniqueSlug;
 68        do
 69        {
 270            uniqueSlug = $"{baseSlug}-{counter++}";
 71        }
 272        while (existingSlugs.Contains(uniqueSlug));
 73
 274        return uniqueSlug;
 75    }
 76}