28 lines
1.0 KiB
C#
28 lines
1.0 KiB
C#
|
|
using System.Net;
|
||
|
|
using System.Text.RegularExpressions;
|
||
|
|
using Microsoft.AspNetCore.Html;
|
||
|
|
|
||
|
|
namespace JobsMedical.Web.Services;
|
||
|
|
|
||
|
|
/// <summary>Wraps query terms in <mark> for result highlighting (HTML-safe).</summary>
|
||
|
|
public static class SearchHighlight
|
||
|
|
{
|
||
|
|
public static HtmlString Mark(string? text, string? query)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrEmpty(text)) return HtmlString.Empty;
|
||
|
|
var encoded = WebUtility.HtmlEncode(text);
|
||
|
|
if (string.IsNullOrWhiteSpace(query)) return new HtmlString(encoded);
|
||
|
|
|
||
|
|
var terms = query.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||
|
|
.Where(t => t.Length >= 2)
|
||
|
|
.Select(t => Regex.Escape(WebUtility.HtmlEncode(t)))
|
||
|
|
.Distinct()
|
||
|
|
.ToList();
|
||
|
|
if (terms.Count == 0) return new HtmlString(encoded);
|
||
|
|
|
||
|
|
var pattern = string.Join("|", terms);
|
||
|
|
var marked = Regex.Replace(encoded, pattern, m => $"<mark>{m.Value}</mark>", RegexOptions.IgnoreCase);
|
||
|
|
return new HtmlString(marked);
|
||
|
|
}
|
||
|
|
}
|