protected override MarkdownNode VisitEmoji(EmojiNode emoji)
        {
            var emojiImageUrl = Emoji.GetImageUrl(emoji.Id, emoji.Name, emoji.IsAnimated);
            var jumboClass    = _isJumbo ? "emoji--large" : "";

            _buffer
            .Append($"<img class=\"emoji {jumboClass}\" alt=\"{emoji.Name}\" title=\"{emoji.Name}\" src=\"{emojiImageUrl}\">");

            return(base.VisitEmoji(emoji));
        }
Exemplo n.º 2
0
        private static string FormatMarkdownNode(RenderContext context, Node node, bool isJumbo)
        {
            // Text node
            if (node is TextNode textNode)
            {
                // Return HTML-encoded text
                return(HtmlEncode(textNode.Text));
            }

            // Formatted node
            if (node is FormattedNode formattedNode)
            {
                // Recursively get inner html
                var innerHtml = FormatMarkdownNodes(context, formattedNode.Children, false);

                // Bold
                if (formattedNode.Formatting == TextFormatting.Bold)
                {
                    return($"<strong>{innerHtml}</strong>");
                }

                // Italic
                if (formattedNode.Formatting == TextFormatting.Italic)
                {
                    return($"<em>{innerHtml}</em>");
                }

                // Underline
                if (formattedNode.Formatting == TextFormatting.Underline)
                {
                    return($"<u>{innerHtml}</u>");
                }

                // Strikethrough
                if (formattedNode.Formatting == TextFormatting.Strikethrough)
                {
                    return($"<s>{innerHtml}</s>");
                }

                // Spoiler
                if (formattedNode.Formatting == TextFormatting.Spoiler)
                {
                    return($"<span class=\"spoiler spoiler--hidden\" onclick=\"showSpoiler(event, this)\"><span class=\"spoiler-text\">{innerHtml}</span></span>");
                }

                // Quote
                if (formattedNode.Formatting == TextFormatting.Quote)
                {
                    return($"<div class=\"quote\">{innerHtml}</div>");
                }
            }

            // Inline code block node
            if (node is InlineCodeBlockNode inlineCodeBlockNode)
            {
                return($"<span class=\"pre pre--inline\">{HtmlEncode(inlineCodeBlockNode.Code)}</span>");
            }

            // Multi-line code block node
            if (node is MultiLineCodeBlockNode multilineCodeBlockNode)
            {
                // Set CSS class for syntax highlighting
                var highlightCssClass = !string.IsNullOrWhiteSpace(multilineCodeBlockNode.Language)
                    ? $"language-{multilineCodeBlockNode.Language}"
                    : "nohighlight";

                return($"<div class=\"pre pre--multiline {highlightCssClass}\">{HtmlEncode(multilineCodeBlockNode.Code)}</div>");
            }

            // Mention node
            if (node is MentionNode mentionNode)
            {
                // Meta mention node
                if (mentionNode.Type == MentionType.Meta)
                {
                    return($"<span class=\"mention\">@{HtmlEncode(mentionNode.Id)}</span>");
                }

                // User mention node
                if (mentionNode.Type == MentionType.User)
                {
                    var user = context.MentionableUsers.FirstOrDefault(u => u.Id == mentionNode.Id) ??
                               User.CreateUnknownUser(mentionNode.Id);

                    var nick = Guild.GetUserNick(context.Guild, user);

                    return($"<span class=\"mention\" title=\"{HtmlEncode(user.FullName)}\">@{HtmlEncode(nick)}</span>");
                }

                // Channel mention node
                if (mentionNode.Type == MentionType.Channel)
                {
                    var channel = context.MentionableChannels.FirstOrDefault(c => c.Id == mentionNode.Id) ??
                                  Channel.CreateDeletedChannel(mentionNode.Id);

                    return($"<span class=\"mention\">#{HtmlEncode(channel.Name)}</span>");
                }

                // Role mention node
                if (mentionNode.Type == MentionType.Role)
                {
                    var role = context.MentionableRoles.FirstOrDefault(r => r.Id == mentionNode.Id) ??
                               Role.CreateDeletedRole(mentionNode.Id);

                    var style = "";
                    if (role.Color != Color.Black)
                    {
                        style = $"style=\"color: {role.ColorAsHex}; background-color: rgba({role.ColorAsRgb}, 0.1); font-weight: 400;\"";
                    }

                    return($"<span class=\"mention\" {style}>@{HtmlEncode(role.Name)}</span>");
                }
            }

            // Emoji node
            if (node is EmojiNode emojiNode)
            {
                // Get emoji image URL
                var emojiImageUrl = Emoji.GetImageUrl(emojiNode.Id, emojiNode.Name, emojiNode.IsAnimated);

                // Make emoji large if it's jumbo
                var jumboableCssClass = isJumbo ? "emoji--large" : null;

                return
                    ($"<img class=\"emoji {jumboableCssClass}\" alt=\"{emojiNode.Name}\" title=\"{emojiNode.Name}\" src=\"{emojiImageUrl}\" />");
            }

            // Link node
            if (node is LinkNode linkNode)
            {
                // Extract message ID if the link points to a Discord message
                var linkedMessageId = Regex.Match(linkNode.Url, "^https?://discordapp.com/channels/.*?/(\\d+)/?$").Groups[1].Value;

                return(string.IsNullOrWhiteSpace(linkedMessageId)
                    ? $"<a href=\"{Uri.EscapeUriString(linkNode.Url)}\">{HtmlEncode(linkNode.Title)}</a>"
                    : $"<a href=\"{Uri.EscapeUriString(linkNode.Url)}\" onclick=\"scrollToMessage(event, '{linkedMessageId}')\">{HtmlEncode(linkNode.Title)}</a>");
            }

            // Throw on unexpected nodes
            throw new InvalidOperationException($"Unexpected node [{node.GetType()}].");
        }
        private string FormatMarkdown(Node node, bool isJumbo)
        {
            // Text node
            if (node is TextNode textNode)
            {
                // Return HTML-encoded text
                return(HtmlEncode(textNode.Text));
            }

            // Formatted node
            if (node is FormattedNode formattedNode)
            {
                // Recursively get inner html
                var innerHtml = FormatMarkdown(formattedNode.Children, false);

                // Bold
                if (formattedNode.Formatting == TextFormatting.Bold)
                {
                    return($"<strong>{innerHtml}</strong>");
                }

                // Italic
                if (formattedNode.Formatting == TextFormatting.Italic)
                {
                    return($"<em>{innerHtml}</em>");
                }

                // Underline
                if (formattedNode.Formatting == TextFormatting.Underline)
                {
                    return($"<u>{innerHtml}</u>");
                }

                // Strikethrough
                if (formattedNode.Formatting == TextFormatting.Strikethrough)
                {
                    return($"<s>{innerHtml}</s>");
                }

                // Spoiler
                if (formattedNode.Formatting == TextFormatting.Spoiler)
                {
                    return($"<span class=\"spoiler\">{innerHtml}</span>");
                }

                // Quote
                if (formattedNode.Formatting == TextFormatting.Quote)
                {
                    return($"<div class=\"quote\">{innerHtml}</div>");
                }
            }

            // Inline code block node
            if (node is InlineCodeBlockNode inlineCodeBlockNode)
            {
                return($"<span class=\"pre pre--inline\">{HtmlEncode(inlineCodeBlockNode.Code)}</span>");
            }

            // Multi-line code block node
            if (node is MultiLineCodeBlockNode multilineCodeBlockNode)
            {
                // Set CSS class for syntax highlighting
                var highlightCssClass = !multilineCodeBlockNode.Language.IsNullOrWhiteSpace()
                    ? $"language-{multilineCodeBlockNode.Language}"
                    : "nohighlight";

                return($"<div class=\"pre pre--multiline {highlightCssClass}\">{HtmlEncode(multilineCodeBlockNode.Code)}</div>");
            }

            // Mention node
            if (node is MentionNode mentionNode)
            {
                // Meta mention node
                if (mentionNode.Type == MentionType.Meta)
                {
                    return($"<span class=\"mention\">@{HtmlEncode(mentionNode.Id)}</span>");
                }

                // User mention node
                if (mentionNode.Type == MentionType.User)
                {
                    var user = _chatLog.Mentionables.GetUser(mentionNode.Id);
                    return($"<span class=\"mention\" title=\"{HtmlEncode(user.FullName)}\">@{HtmlEncode(user.Name)}</span>");
                }

                // Channel mention node
                if (mentionNode.Type == MentionType.Channel)
                {
                    var channel = _chatLog.Mentionables.GetChannel(mentionNode.Id);
                    return($"<span class=\"mention\">#{HtmlEncode(channel.Name)}</span>");
                }

                // Role mention node
                if (mentionNode.Type == MentionType.Role)
                {
                    var role = _chatLog.Mentionables.GetRole(mentionNode.Id);
                    return($"<span class=\"mention\">@{HtmlEncode(role.Name)}</span>");
                }
            }

            // Emoji node
            if (node is EmojiNode emojiNode)
            {
                // Get emoji image URL
                var emojiImageUrl = Emoji.GetImageUrl(emojiNode.Id, emojiNode.Name, emojiNode.IsAnimated);

                // Make emoji large if it's jumbo
                var jumboableCssClass = isJumbo ? "emoji--large" : null;

                return($"<img class=\"emoji {jumboableCssClass}\" alt=\"{emojiNode.Name}\" title=\"{emojiNode.Name}\" src=\"{emojiImageUrl}\" />");
            }

            // Link node
            if (node is LinkNode linkNode)
            {
                // Extract message ID if the link points to a Discord message
                var linkedMessageId = Regex.Match(linkNode.Url, "^https?://discordapp.com/channels/.*?/(\\d+)/?$").Groups[1].Value;

                return(linkedMessageId.IsNullOrWhiteSpace()
                    ? $"<a href=\"{Uri.EscapeUriString(linkNode.Url)}\">{HtmlEncode(linkNode.Title)}</a>"
                    : $"<a href=\"{Uri.EscapeUriString(linkNode.Url)}\" onclick=\"scrollToMessage(event, '{linkedMessageId}')\">{HtmlEncode(linkNode.Title)}</a>");
            }

            // Throw on unexpected nodes
            throw new InvalidOperationException($"Unexpected node: [{node.GetType()}].");
        }
Exemplo n.º 4
0
        private string FormatMarkdown(Node node, bool isJumbo)
        {
            // Text node
            if (node is TextNode textNode)
            {
                // Return HTML-encoded text
                return(HtmlEncode(textNode.Text));
            }

            // Formatted node
            if (node is FormattedNode formattedNode)
            {
                // Recursively get inner html
                var innerHtml = FormatMarkdown(formattedNode.Children, false);

                // Bold
                if (formattedNode.Formatting == TextFormatting.Bold)
                {
                    return($"<strong>{innerHtml}</strong>");
                }

                // Italic
                if (formattedNode.Formatting == TextFormatting.Italic)
                {
                    return($"<em>{innerHtml}</em>");
                }

                // Underline
                if (formattedNode.Formatting == TextFormatting.Underline)
                {
                    return($"<u>{innerHtml}</u>");
                }

                // Strikethrough
                if (formattedNode.Formatting == TextFormatting.Strikethrough)
                {
                    return($"<s>{innerHtml}</s>");
                }

                // Spoiler
                if (formattedNode.Formatting == TextFormatting.Spoiler)
                {
                    return($"<span class=\"spoiler\">{innerHtml}</span>");
                }
            }

            // Inline code block node
            if (node is InlineCodeBlockNode inlineCodeBlockNode)
            {
                return($"<span class=\"pre pre--inline\">{HtmlEncode(inlineCodeBlockNode.Code)}</span>");
            }

            // Multi-line code block node
            if (node is MultilineCodeBlockNode multilineCodeBlockNode)
            {
                // Set language class for syntax highlighting
                var languageCssClass = !multilineCodeBlockNode.Language.IsNullOrWhiteSpace()
                    ? "language-" + multilineCodeBlockNode.Language
                    : null;

                return($"<div class=\"pre pre--multiline {languageCssClass}\">{HtmlEncode(multilineCodeBlockNode.Code)}</div>");
            }

            // Mention node
            if (node is MentionNode mentionNode)
            {
                // Meta mention node
                if (mentionNode.Type == MentionType.Meta)
                {
                    return($"<span class=\"mention\">@{HtmlEncode(mentionNode.Id)}</span>");
                }

                // User mention node
                if (mentionNode.Type == MentionType.User)
                {
                    var user = _chatLog.Mentionables.GetUser(mentionNode.Id);
                    return($"<span class=\"mention\" title=\"{HtmlEncode(user.FullName)}\">@{HtmlEncode(user.Name)}</span>");
                }

                // Channel mention node
                if (mentionNode.Type == MentionType.Channel)
                {
                    var channel = _chatLog.Mentionables.GetChannel(mentionNode.Id);
                    return($"<span class=\"mention\">#{HtmlEncode(channel.Name)}</span>");
                }

                // Role mention node
                if (mentionNode.Type == MentionType.Role)
                {
                    var role = _chatLog.Mentionables.GetRole(mentionNode.Id);
                    return($"<span class=\"mention\">@{HtmlEncode(role.Name)}</span>");
                }
            }

            // Emoji node
            if (node is EmojiNode emojiNode)
            {
                // Get emoji image URL
                var emojiImageUrl = Emoji.GetImageUrl(emojiNode.Id, emojiNode.Name, emojiNode.IsAnimated);

                // Make emoji large if it's jumbo
                var jumboableCssClass = isJumbo ? "emoji--large" : null;

                return($"<img class=\"emoji {jumboableCssClass}\" alt=\"{emojiNode.Name}\" title=\"{emojiNode.Name}\" src=\"{emojiImageUrl}\" />");
            }

            // Link node
            if (node is LinkNode linkNode)
            {
                return($"<a href=\"{Uri.EscapeUriString(linkNode.Url)}\">{HtmlEncode(linkNode.Title)}</a>");
            }

            // All other nodes - simply return source
            return(node.Source);
        }