Files
chapter-organizer/WebApp/Services/MarkdownHelper.cs
T
poprhythm 8b0451c2ec Add IsPinned and IsDeleted properties to Note entity with corresponding database configurations and migrations
This commit enhances the Note entity by introducing two new properties: IsPinned and IsDeleted, allowing for better management of note visibility and status. The NoteConfiguration class has been updated to include indexes for these properties, improving query performance. Additionally, new migrations have been created to reflect these changes in the database schema. The UI components have been updated to support pinning and restoring notes, enhancing user interaction and functionality within the note management system.
2026-01-16 23:12:18 -05:00

96 lines
3.9 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;
}
}