Sube carpetas API, API.Tests, Application y Domain del Backend
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace Application.Utils.Helper.Slug;
|
||||
|
||||
/// <summary>
|
||||
/// Composes the display string a Match's slug is generated from, fed through SlugGenerator.GenerateUniqueSlugAsync.
|
||||
/// </summary>
|
||||
public static class MatchSlugSourceBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Placeholder team name used when a match's home or visitor team is not yet assigned.
|
||||
/// </summary>
|
||||
public const string UnassignedTeamPlaceholder = "TBD";
|
||||
|
||||
/// <summary>
|
||||
/// Builds the slug source string for a match.
|
||||
/// </summary>
|
||||
/// <param name="homeTeamName">The home team's name, or null/empty when not yet assigned.</param>
|
||||
/// <param name="visitorTeamName">The visitor team's name, or null/empty when not yet assigned.</param>
|
||||
/// <param name="matchDate">The match's date.</param>
|
||||
public static string Build(string? homeTeamName, string? visitorTeamName, DateTime matchDate)
|
||||
{
|
||||
string home = string.IsNullOrWhiteSpace(homeTeamName) ? UnassignedTeamPlaceholder : homeTeamName;
|
||||
string visitor = string.IsNullOrWhiteSpace(visitorTeamName) ? UnassignedTeamPlaceholder : visitorTeamName;
|
||||
|
||||
return $"{home} vs {visitor} {matchDate:yyyy-MM-dd}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Application.Utils.Helper.Slug;
|
||||
|
||||
/// <summary>
|
||||
/// Generates lowercase, kebab-case, URL-friendly slugs from display names.
|
||||
/// </summary>
|
||||
public static partial class SlugGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts text into a lowercase, kebab-case slug.
|
||||
/// </summary>
|
||||
/// <param name="text">The display name to convert.</param>
|
||||
/// <returns>The generated slug. Never null, may be empty for input with no alphanumeric characters.</returns>
|
||||
public static string GenerateSlug(string text)
|
||||
{
|
||||
string normalized = text.Normalize(NormalizationForm.FormD);
|
||||
StringBuilder withoutAccents = new(normalized.Length);
|
||||
|
||||
foreach (char character in normalized)
|
||||
{
|
||||
if (CharUnicodeInfo.GetUnicodeCategory(character) != UnicodeCategory.NonSpacingMark)
|
||||
{
|
||||
withoutAccents.Append(character);
|
||||
}
|
||||
}
|
||||
|
||||
string lowercase = withoutAccents.ToString().Normalize(NormalizationForm.FormC).ToLowerInvariant();
|
||||
string hyphenated = NonAlphanumericRunRegex().Replace(lowercase, "-");
|
||||
|
||||
return hyphenated.Trim('-');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a slug from text and, when it collides with an existing slug, appends a numeric suffix until slugExists reports no collision.
|
||||
/// </summary>
|
||||
/// <param name="text">The display name to convert.</param>
|
||||
/// <param name="slugExists">Predicate that checks whether a candidate slug is already taken.</param>
|
||||
/// <returns>A unique slug derived from text.</returns>
|
||||
public static async Task<string> GenerateUniqueSlugAsync(string text, Func<string, Task<bool>> slugExists)
|
||||
{
|
||||
string baseSlug = GenerateSlug(text);
|
||||
string candidate = baseSlug;
|
||||
int suffix = 1;
|
||||
|
||||
while (await slugExists(candidate))
|
||||
{
|
||||
suffix++;
|
||||
candidate = $"{baseSlug}-{suffix}";
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
[GeneratedRegex("[^a-z0-9]+")]
|
||||
private static partial Regex NonAlphanumericRunRegex();
|
||||
}
|
||||
Reference in New Issue
Block a user