using System.Text.RegularExpressions; namespace Application.Features.Api.Feed.Shared; public static partial class FeedContent { [GeneratedRegex(@"<[^>]+>", RegexOptions.Compiled)] private static partial Regex HtmlTagRegex(); [GeneratedRegex(@"\s+", RegexOptions.Compiled)] private static partial Regex WhitespaceRegex(); public static string Excerpt(string? html, int maxLength) { if (string.IsNullOrWhiteSpace(html)) { return string.Empty; } var stripped = HtmlTagRegex().Replace(html, " "); var normalized = WhitespaceRegex().Replace(stripped, " ").Trim(); if (normalized.Length <= maxLength) { return normalized; } return string.Concat(normalized.AsSpan(0, maxLength), "…"); } [GeneratedRegex(@"#([\p{L}\p{N}_가-힣]+)", RegexOptions.Compiled)] public static partial Regex HashtagRegex(); [GeneratedRegex(@"@([A-Za-z0-9]{3,20})", RegexOptions.Compiled)] public static partial Regex MentionRegex(); public static List ExtractHashtags(string? text, int maxTags = 10) { if (string.IsNullOrWhiteSpace(text)) { return []; } var seen = new HashSet(StringComparer.OrdinalIgnoreCase); var result = new List(); foreach (Match m in HashtagRegex().Matches(text)) { var tag = m.Groups[1].Value; if (seen.Add(tag)) { result.Add(tag); if (result.Count >= maxTags) { break; } } } return result; } public static List ExtractMentions(string? text, int maxMentions = 20) { if (string.IsNullOrWhiteSpace(text)) { return []; } var seen = new HashSet(StringComparer.OrdinalIgnoreCase); var result = new List(); foreach (Match m in MentionRegex().Matches(text)) { var sid = m.Groups[1].Value; if (seen.Add(sid)) { result.Add(sid); if (result.Count >= maxMentions) { break; } } } return result; } }