using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using DiscordChatExporter.Core.Discord.Data;
using DiscordChatExporter.Core.Markdown;
using DiscordChatExporter.Core.Markdown.Parsing;
using DiscordChatExporter.Core.Utils.Extensions;
namespace DiscordChatExporter.Core.Exporting;
internal partial class HtmlMarkdownVisitor : MarkdownVisitor
{
private readonly ExportContext _context;
private readonly StringBuilder _buffer;
private readonly bool _isJumbo;
public HtmlMarkdownVisitor(ExportContext context, StringBuilder buffer, bool isJumbo)
{
_context = context;
_buffer = buffer;
_isJumbo = isJumbo;
}
protected override ValueTask VisitTextAsync(
TextNode text,
CancellationToken cancellationToken = default)
{
_buffer.Append(HtmlEncode(text.Text));
return default;
}
protected override async ValueTask VisitFormattingAsync(
FormattingNode formatting,
CancellationToken cancellationToken = default)
{
var (openingTag, closingTag) = formatting.Kind switch
{
FormattingKind.Bold => (
// lang=html
"",
// lang=html
""
),
FormattingKind.Italic => (
// lang=html
"",
// lang=html
""
),
FormattingKind.Underline => (
// lang=html
"",
// lang=html
""
),
FormattingKind.Strikethrough => (
// lang=html
"",
// lang=html
""
),
FormattingKind.Spoiler => (
// lang=html
"""""",
// lang=html
""""""
),
FormattingKind.Quote => (
// lang=html
"""
{HtmlEncode(inlineCodeBlock.Code)}
"""
);
return default;
}
protected override ValueTask VisitMultiLineCodeBlockAsync(
MultiLineCodeBlockNode multiLineCodeBlock,
CancellationToken cancellationToken = default)
{
var highlightClass = !string.IsNullOrWhiteSpace(multiLineCodeBlock.Language)
? $"language-{multiLineCodeBlock.Language}"
: "nohighlight";
_buffer.Append(
// lang=html
$"""
{HtmlEncode(multiLineCodeBlock.Code)}
"""
);
return default;
}
protected override async ValueTask VisitLinkAsync(
LinkNode link,
CancellationToken cancellationToken = default)
{
// Try to extract the message ID if the link points to a Discord message
var linkedMessageId = Regex.Match(
link.Url,
@"^https?://(?:discord|discordapp)\.com/channels/.*?/(\d+)/?$"
).Groups[1].Value;
_buffer.Append(
!string.IsNullOrWhiteSpace(linkedMessageId)
// lang=html
? $""""""
// lang=html
: $""""""
);
await VisitAsync(link.Children, cancellationToken);
_buffer.Append(
// lang=html
""
);
}
protected override async ValueTask VisitEmojiAsync(
EmojiNode emoji,
CancellationToken cancellationToken = default)
{
var emojiImageUrl = Emoji.GetImageUrl(emoji.Id, emoji.Name, emoji.IsAnimated);
var jumboClass = _isJumbo ? "chatlog__emoji--large" : "";
_buffer.Append(
// lang=html
$"""