108 lines
4.3 KiB
C#
108 lines
4.3 KiB
C#
using Markdig;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace WebApp.Services;
|
|
|
|
/// <summary>
|
|
/// Helper class for rendering markdown to HTML.
|
|
/// </summary>
|
|
public static class MarkdownHelper
|
|
{
|
|
private static readonly MarkdownPipeline _pipeline = new MarkdownPipelineBuilder()
|
|
.UseAdvancedExtensions()
|
|
.Build();
|
|
|
|
// Compiled regex patterns for stripping markdown
|
|
private static readonly Regex MarkdownLinkRegex =
|
|
new(@"\[([^\]]+)\]\([^\)]+\)", RegexOptions.Compiled);
|
|
private static readonly Regex BoldRegex =
|
|
new(@"\*\*([^\*]+)\*\*", RegexOptions.Compiled);
|
|
private static readonly Regex ItalicRegex =
|
|
new(@"\*([^\*]+)\*", RegexOptions.Compiled);
|
|
private static readonly Regex InlineCodeRegex =
|
|
new(@"`([^`]+)`", RegexOptions.Compiled);
|
|
private static readonly Regex HeaderRegex =
|
|
new(@"#+\s+", RegexOptions.Compiled);
|
|
private static readonly Regex NewlineRegex =
|
|
new(@"\n+", RegexOptions.Compiled);
|
|
private static readonly Regex HtmlTagRegex =
|
|
new(@"<[^>]+>", RegexOptions.Compiled);
|
|
|
|
/// <summary>
|
|
/// Converts markdown text to HTML.
|
|
/// </summary>
|
|
/// <param name="markdown">The markdown text to convert.</param>
|
|
/// <returns>HTML string ready for rendering.</returns>
|
|
public static string ToHtml(string? markdown)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(markdown))
|
|
return string.Empty;
|
|
|
|
var html = Markdown.ToHtml(markdown, _pipeline);
|
|
|
|
// Add target="_blank" and rel="noopener noreferrer" to all links
|
|
html = Regex.Replace(html, @"<a\s+([^>]*?)href=""([^""]*?)""([^>]*?)>",
|
|
match =>
|
|
{
|
|
var beforeHref = match.Groups[1].Value;
|
|
var href = match.Groups[2].Value;
|
|
var afterHref = match.Groups[3].Value;
|
|
|
|
// Check if target is already present
|
|
if (Regex.IsMatch(beforeHref + afterHref, @"target\s*=", RegexOptions.IgnoreCase))
|
|
{
|
|
return match.Value; // Return unchanged if target already exists
|
|
}
|
|
|
|
// Add target="_blank" and rel="noopener noreferrer"
|
|
return $"<a {beforeHref}href=\"{href}\" target=\"_blank\" rel=\"noopener noreferrer\"{afterHref}>";
|
|
},
|
|
RegexOptions.IgnoreCase);
|
|
|
|
return html;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Strips markdown formatting from content and returns plain text for preview.
|
|
/// </summary>
|
|
/// <param name="content">The markdown content to strip.</param>
|
|
/// <param name="maxLength">Maximum length of the preview. If 0 or negative, no truncation is performed.</param>
|
|
/// <returns>Plain text preview with markdown formatting removed.</returns>
|
|
public static string StripMarkdownPreview(string? content, int maxLength = 0)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(content))
|
|
return string.Empty;
|
|
|
|
// Strip markdown formatting for preview using compiled regex
|
|
var plainText = MarkdownLinkRegex.Replace(content, "$1"); // Replace markdown links with link text
|
|
plainText = BoldRegex.Replace(plainText, "$1"); // Remove bold
|
|
plainText = ItalicRegex.Replace(plainText, "$1"); // Remove italic
|
|
plainText = InlineCodeRegex.Replace(plainText, "$1"); // Remove inline code
|
|
plainText = HeaderRegex.Replace(plainText, ""); // Remove headers
|
|
plainText = NewlineRegex.Replace(plainText, " "); // Replace newlines with spaces
|
|
plainText = HtmlTagRegex.Replace(plainText, ""); // Remove HTML tags
|
|
|
|
plainText = plainText.Trim();
|
|
|
|
// Truncate if maxLength is specified and content exceeds it
|
|
if (maxLength > 0 && plainText.Length > maxLength)
|
|
{
|
|
return plainText.Substring(0, maxLength - 3) + "...";
|
|
}
|
|
|
|
return plainText;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the CSS class name for a note's color based on its ID.
|
|
/// Uses modulo 3 to cycle through 3 pastel color classes.
|
|
/// </summary>
|
|
/// <param name="noteId">The note ID.</param>
|
|
/// <returns>CSS class name (e.g., "note-color-0", "note-color-1", "note-color-2"), or empty string if noteId is 0.</returns>
|
|
public static string GetNoteColorClass(int noteId)
|
|
{
|
|
if (noteId == 0) return string.Empty;
|
|
return $"note-color-{noteId % 3}";
|
|
}
|
|
}
|