diff --git a/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs b/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs index 1823c01..2144603 100644 --- a/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs +++ b/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs @@ -44,7 +44,7 @@ namespace DiscordChatExporter.Cli.Commands.Base Description = "Format used when writing dates.")] public string DateFormat { get; set; } = "dd-MMM-yy hh:mm tt"; - protected ChannelExporter GetChannelExporter() => new ChannelExporter(GetDiscordClient()); + protected ChannelExporter GetChannelExporter() => new(GetDiscordClient()); protected async ValueTask ExportAsync(IConsole console, Guild guild, Channel channel) { diff --git a/DiscordChatExporter.Cli/Commands/Base/TokenCommandBase.cs b/DiscordChatExporter.Cli/Commands/Base/TokenCommandBase.cs index e74c964..870ca0a 100644 --- a/DiscordChatExporter.Cli/Commands/Base/TokenCommandBase.cs +++ b/DiscordChatExporter.Cli/Commands/Base/TokenCommandBase.cs @@ -17,14 +17,14 @@ namespace DiscordChatExporter.Cli.Commands.Base Description = "Authorize as a bot.")] public bool IsBotToken { get; set; } - protected AuthToken GetAuthToken() => new AuthToken( + protected AuthToken GetAuthToken() => new( IsBotToken ? AuthTokenType.Bot : AuthTokenType.User, TokenValue ); - protected DiscordClient GetDiscordClient() => new DiscordClient(GetAuthToken()); + protected DiscordClient GetDiscordClient() => new(GetAuthToken()); public abstract ValueTask ExecuteAsync(IConsole console); } diff --git a/DiscordChatExporter.Domain/Discord/DiscordClient.cs b/DiscordChatExporter.Domain/Discord/DiscordClient.cs index 16d8181..1bc96df 100644 --- a/DiscordChatExporter.Domain/Discord/DiscordClient.cs +++ b/DiscordChatExporter.Domain/Discord/DiscordClient.cs @@ -19,7 +19,7 @@ namespace DiscordChatExporter.Domain.Discord private readonly HttpClient _httpClient; private readonly AuthToken _token; - private readonly Uri _baseUri = new Uri("https://discord.com/api/v6/", UriKind.Absolute); + private readonly Uri _baseUri = new("https://discord.com/api/v6/", UriKind.Absolute); public DiscordClient(HttpClient httpClient, AuthToken token) { diff --git a/DiscordChatExporter.Domain/Discord/Models/Attachment.cs b/DiscordChatExporter.Domain/Discord/Models/Attachment.cs index 7f882fa..60c3487 100644 --- a/DiscordChatExporter.Domain/Discord/Models/Attachment.cs +++ b/DiscordChatExporter.Domain/Discord/Models/Attachment.cs @@ -47,17 +47,14 @@ namespace DiscordChatExporter.Domain.Discord.Models public partial class Attachment { - private static readonly HashSet ImageFileExtensions = - new HashSet(StringComparer.OrdinalIgnoreCase) - {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"}; + private static readonly HashSet ImageFileExtensions = new(StringComparer.OrdinalIgnoreCase) + {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"}; - private static readonly HashSet VideoFileExtensions = - new HashSet(StringComparer.OrdinalIgnoreCase) - {".mp4", ".webm"}; + private static readonly HashSet VideoFileExtensions = new(StringComparer.OrdinalIgnoreCase) + {".mp4", ".webm"}; - private static readonly HashSet AudioFileExtensions = - new HashSet(StringComparer.OrdinalIgnoreCase) - {".mp3", ".wav", ".ogg", ".flac", ".m4a"}; + private static readonly HashSet AudioFileExtensions = new(StringComparer.OrdinalIgnoreCase) + {".mp3", ".wav", ".ogg", ".flac", ".m4a"}; public static Attachment Parse(JsonElement json) { diff --git a/DiscordChatExporter.Domain/Discord/Models/Common/FileSize.cs b/DiscordChatExporter.Domain/Discord/Models/Common/FileSize.cs index dc568d4..aa411db 100644 --- a/DiscordChatExporter.Domain/Discord/Models/Common/FileSize.cs +++ b/DiscordChatExporter.Domain/Discord/Models/Common/FileSize.cs @@ -60,6 +60,6 @@ namespace DiscordChatExporter.Domain.Discord.Models.Common public partial struct FileSize { - public static FileSize FromBytes(long bytes) => new FileSize(bytes); + public static FileSize FromBytes(long bytes) => new(bytes); } } \ No newline at end of file diff --git a/DiscordChatExporter.Domain/Discord/Models/Common/IdBasedEqualityComparer.cs b/DiscordChatExporter.Domain/Discord/Models/Common/IdBasedEqualityComparer.cs index b3a0a60..fff743f 100644 --- a/DiscordChatExporter.Domain/Discord/Models/Common/IdBasedEqualityComparer.cs +++ b/DiscordChatExporter.Domain/Discord/Models/Common/IdBasedEqualityComparer.cs @@ -12,6 +12,6 @@ namespace DiscordChatExporter.Domain.Discord.Models.Common public partial class IdBasedEqualityComparer { - public static IdBasedEqualityComparer Instance { get; } = new IdBasedEqualityComparer(); + public static IdBasedEqualityComparer Instance { get; } = new(); } } \ No newline at end of file diff --git a/DiscordChatExporter.Domain/Discord/Models/Guild.cs b/DiscordChatExporter.Domain/Discord/Models/Guild.cs index d139135..b490690 100644 --- a/DiscordChatExporter.Domain/Discord/Models/Guild.cs +++ b/DiscordChatExporter.Domain/Discord/Models/Guild.cs @@ -24,8 +24,7 @@ namespace DiscordChatExporter.Domain.Discord.Models public partial class Guild { - public static Guild DirectMessages { get; } = - new Guild("@me", "Direct Messages", GetDefaultIconUrl()); + public static Guild DirectMessages { get; } = new("@me", "Direct Messages", GetDefaultIconUrl()); private static string GetDefaultIconUrl() => "https://cdn.discordapp.com/embed/avatars/0.png"; diff --git a/DiscordChatExporter.Domain/Discord/Models/Member.cs b/DiscordChatExporter.Domain/Discord/Models/Member.cs index fbd6a58..8487cd1 100644 --- a/DiscordChatExporter.Domain/Discord/Models/Member.cs +++ b/DiscordChatExporter.Domain/Discord/Models/Member.cs @@ -31,8 +31,7 @@ namespace DiscordChatExporter.Domain.Discord.Models public partial class Member { - public static Member CreateForUser(User user) => - new Member(user, null, Array.Empty()); + public static Member CreateForUser(User user) => new(user, null, Array.Empty()); public static Member Parse(JsonElement json) { diff --git a/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs b/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs index ad53d1c..4750b37 100644 --- a/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs +++ b/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs @@ -18,8 +18,7 @@ namespace DiscordChatExporter.Domain.Exporting private readonly bool _reuseMedia; // URL -> Local file path - private readonly Dictionary _pathCache = - new Dictionary(StringComparer.Ordinal); + private readonly Dictionary _pathCache = new(StringComparer.Ordinal); public MediaDownloader(HttpClient httpClient, string workingDirPath, bool reuseMedia) { diff --git a/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs b/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs index c9e9906..4cc05f9 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs @@ -12,7 +12,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers private readonly TextWriter _writer; private readonly string _themeName; - private readonly List _messageGroupBuffer = new List(); + private readonly List _messageGroupBuffer = new(); private long _messageCount; diff --git a/DiscordChatExporter.Domain/Internal/Http.cs b/DiscordChatExporter.Domain/Internal/Http.cs index c13b0e2..242441c 100644 --- a/DiscordChatExporter.Domain/Internal/Http.cs +++ b/DiscordChatExporter.Domain/Internal/Http.cs @@ -11,7 +11,7 @@ namespace DiscordChatExporter.Domain.Internal { internal static class Http { - public static HttpClient Client { get; } = new HttpClient(); + public static HttpClient Client { get; } = new(); public static IAsyncPolicy ResponsePolicy { get; } = Policy @@ -21,7 +21,7 @@ namespace DiscordChatExporter.Domain.Internal .OrResult(m => m.StatusCode == HttpStatusCode.RequestTimeout) .OrResult(m => m.StatusCode >= HttpStatusCode.InternalServerError) .WaitAndRetryAsync(8, - (i, result, ctx) => + (i, result, _) => { // If rate-limited, use retry-after as a guide if (result.Result?.StatusCode == HttpStatusCode.TooManyRequests) @@ -39,7 +39,7 @@ namespace DiscordChatExporter.Domain.Internal return TimeSpan.FromSeconds(Math.Pow(2, i) + 1); }, - (response, timespan, retryCount, context) => Task.CompletedTask); + (_, _, _, _) => Task.CompletedTask); private static HttpStatusCode? TryGetStatusCodeFromException(HttpRequestException ex) { diff --git a/DiscordChatExporter.Domain/Internal/UrlBuilder.cs b/DiscordChatExporter.Domain/Internal/UrlBuilder.cs index 4cdf9bf..85de6f0 100644 --- a/DiscordChatExporter.Domain/Internal/UrlBuilder.cs +++ b/DiscordChatExporter.Domain/Internal/UrlBuilder.cs @@ -10,8 +10,7 @@ namespace DiscordChatExporter.Domain.Internal { private string _path = ""; - private readonly Dictionary _queryParameters = - new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _queryParameters = new(StringComparer.OrdinalIgnoreCase); public UrlBuilder SetPath(string path) { diff --git a/DiscordChatExporter.Domain/Markdown/MarkdownParser.cs b/DiscordChatExporter.Domain/Markdown/MarkdownParser.cs index 13cf6cc..d0447af 100644 --- a/DiscordChatExporter.Domain/Markdown/MarkdownParser.cs +++ b/DiscordChatExporter.Domain/Markdown/MarkdownParser.cs @@ -9,74 +9,92 @@ namespace DiscordChatExporter.Domain.Markdown // The following parsing logic is meant to replicate Discord's markdown grammar as close as possible internal static partial class MarkdownParser { - private const RegexOptions DefaultRegexOptions = RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.Multiline; + private const RegexOptions DefaultRegexOptions = + RegexOptions.Compiled | + RegexOptions.CultureInvariant | + RegexOptions.Multiline; /* Formatting */ // Capture any character until the earliest double asterisk not followed by an asterisk private static readonly IMatcher BoldFormattedNodeMatcher = new RegexMatcher( new Regex("\\*\\*(.+?)\\*\\*(?!\\*)", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Bold, Parse(p.Slice(m.Groups[1])))); + (p, m) => new FormattedNode(TextFormatting.Bold, Parse(p.Slice(m.Groups[1]))) + ); // Capture any character until the earliest single asterisk not preceded or followed by an asterisk // Opening asterisk must not be followed by whitespace // Closing asterisk must not be preceded by whitespace private static readonly IMatcher ItalicFormattedNodeMatcher = new RegexMatcher( new Regex("\\*(?!\\s)(.+?)(? new FormattedNode(TextFormatting.Italic, Parse(p.Slice(m.Groups[1])))); + (p, m) => new FormattedNode(TextFormatting.Italic, Parse(p.Slice(m.Groups[1]))) + ); // Capture any character until the earliest triple asterisk not followed by an asterisk private static readonly IMatcher ItalicBoldFormattedNodeMatcher = new RegexMatcher( new Regex("\\*(\\*\\*.+?\\*\\*)\\*(?!\\*)", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Italic, Parse(p.Slice(m.Groups[1]), BoldFormattedNodeMatcher))); + (p, m) => new FormattedNode(TextFormatting.Italic, Parse(p.Slice(m.Groups[1]), BoldFormattedNodeMatcher)) + ); // Capture any character except underscore until an underscore // Closing underscore must not be followed by a word character private static readonly IMatcher ItalicAltFormattedNodeMatcher = new RegexMatcher( new Regex("_([^_]+)_(?!\\w)", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Italic, Parse(p.Slice(m.Groups[1])))); + (p, m) => new FormattedNode(TextFormatting.Italic, Parse(p.Slice(m.Groups[1]))) + ); // Capture any character until the earliest double underscore not followed by an underscore private static readonly IMatcher UnderlineFormattedNodeMatcher = new RegexMatcher( new Regex("__(.+?)__(?!_)", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Underline, Parse(p.Slice(m.Groups[1])))); + (p, m) => new FormattedNode(TextFormatting.Underline, Parse(p.Slice(m.Groups[1]))) + ); // Capture any character until the earliest triple underscore not followed by an underscore - private static readonly IMatcher ItalicUnderlineFormattedNodeMatcher = new RegexMatcher( - new Regex("_(__.+?__)_(?!_)", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Italic, Parse(p.Slice(m.Groups[1]), UnderlineFormattedNodeMatcher))); + private static readonly IMatcher ItalicUnderlineFormattedNodeMatcher = + new RegexMatcher( + new Regex("_(__.+?__)_(?!_)", DefaultRegexOptions | RegexOptions.Singleline), + (p, m) => new FormattedNode(TextFormatting.Italic, + Parse(p.Slice(m.Groups[1]), UnderlineFormattedNodeMatcher)) + ); // Capture any character until the earliest double tilde - private static readonly IMatcher StrikethroughFormattedNodeMatcher = new RegexMatcher( - new Regex("~~(.+?)~~", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Strikethrough, Parse(p.Slice(m.Groups[1])))); + private static readonly IMatcher StrikethroughFormattedNodeMatcher = + new RegexMatcher( + new Regex("~~(.+?)~~", DefaultRegexOptions | RegexOptions.Singleline), + (p, m) => new FormattedNode(TextFormatting.Strikethrough, Parse(p.Slice(m.Groups[1]))) + ); // Capture any character until the earliest double pipe private static readonly IMatcher SpoilerFormattedNodeMatcher = new RegexMatcher( new Regex("\\|\\|(.+?)\\|\\|", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Spoiler, Parse(p.Slice(m.Groups[1])))); + (p, m) => new FormattedNode(TextFormatting.Spoiler, Parse(p.Slice(m.Groups[1]))) + ); // Capture any character until the end of the line // Opening 'greater than' character must be followed by whitespace private static readonly IMatcher SingleLineQuoteNodeMatcher = new RegexMatcher( new Regex("^>\\s(.+\n?)", DefaultRegexOptions), - (p, m) => new FormattedNode(TextFormatting.Quote, Parse(p.Slice(m.Groups[1])))); + (p, m) => new FormattedNode(TextFormatting.Quote, Parse(p.Slice(m.Groups[1]))) + ); // Repeatedly capture any character until the end of the line // This one is tricky as it ends up producing multiple separate captures which need to be joined - private static readonly IMatcher RepeatedSingleLineQuoteNodeMatcher = new RegexMatcher( - new Regex("(?:^>\\s(.+\n?)){2,}", DefaultRegexOptions), - (p, m) => - { - var content = string.Concat(m.Groups[1].Captures.Select(c => c.Value)); - return new FormattedNode(TextFormatting.Quote, Parse(content)); - }); + private static readonly IMatcher RepeatedSingleLineQuoteNodeMatcher = + new RegexMatcher( + new Regex("(?:^>\\s(.+\n?)){2,}", DefaultRegexOptions), + (_, m) => + { + var content = string.Concat(m.Groups[1].Captures.Select(c => c.Value)); + return new FormattedNode(TextFormatting.Quote, Parse(content)); + } + ); // Capture any character until the end of the input // Opening 'greater than' characters must be followed by whitespace private static readonly IMatcher MultiLineQuoteNodeMatcher = new RegexMatcher( new Regex("^>>>\\s(.+)", DefaultRegexOptions | RegexOptions.Singleline), - (p, m) => new FormattedNode(TextFormatting.Quote, Parse(p.Slice(m.Groups[1])))); + (p, m) => new FormattedNode(TextFormatting.Quote, Parse(p.Slice(m.Groups[1]))) + ); /* Code blocks */ @@ -85,41 +103,48 @@ namespace DiscordChatExporter.Domain.Markdown // There can be either one or two backticks, but equal number on both sides private static readonly IMatcher InlineCodeBlockNodeMatcher = new RegexMatcher( new Regex("(`{1,2})([^`]+)\\1", DefaultRegexOptions | RegexOptions.Singleline), - m => new InlineCodeBlockNode(m.Groups[2].Value.Trim('\r', '\n'))); + m => new InlineCodeBlockNode(m.Groups[2].Value.Trim('\r', '\n')) + ); // Capture language identifier and then any character until the earliest triple backtick // Language identifier is one word immediately after opening backticks, followed immediately by newline // Blank lines at the beginning and end of content are trimmed private static readonly IMatcher MultiLineCodeBlockNodeMatcher = new RegexMatcher( new Regex("```(?:(\\w*)\\n)?(.+?)```", DefaultRegexOptions | RegexOptions.Singleline), - m => new MultiLineCodeBlockNode(m.Groups[1].Value, m.Groups[2].Value.Trim('\r', '\n'))); + m => new MultiLineCodeBlockNode(m.Groups[1].Value, m.Groups[2].Value.Trim('\r', '\n')) + ); /* Mentions */ // Capture @everyone private static readonly IMatcher EveryoneMentionNodeMatcher = new StringMatcher( "@everyone", - p => new MentionNode("everyone", MentionType.Meta)); + _ => new MentionNode("everyone", MentionType.Meta) + ); // Capture @here private static readonly IMatcher HereMentionNodeMatcher = new StringMatcher( "@here", - p => new MentionNode("here", MentionType.Meta)); + _ => new MentionNode("here", MentionType.Meta) + ); // Capture <@123456> or <@!123456> private static readonly IMatcher UserMentionNodeMatcher = new RegexMatcher( new Regex("<@!?(\\d+)>", DefaultRegexOptions), - m => new MentionNode(m.Groups[1].Value, MentionType.User)); + m => new MentionNode(m.Groups[1].Value, MentionType.User) + ); // Capture <#123456> private static readonly IMatcher ChannelMentionNodeMatcher = new RegexMatcher( new Regex("<#(\\d+)>", DefaultRegexOptions), - m => new MentionNode(m.Groups[1].Value, MentionType.Channel)); + m => new MentionNode(m.Groups[1].Value, MentionType.Channel) + ); // Capture <@&123456> private static readonly IMatcher RoleMentionNodeMatcher = new RegexMatcher( new Regex("<@&(\\d+)>", DefaultRegexOptions), - m => new MentionNode(m.Groups[1].Value, MentionType.Role)); + m => new MentionNode(m.Groups[1].Value, MentionType.Role) + ); /* Emojis */ @@ -129,30 +154,36 @@ namespace DiscordChatExporter.Domain.Markdown // ... or digit followed by enclosing mark // (this does not match all emojis in Discord but it's reasonably accurate enough) private static readonly IMatcher StandardEmojiNodeMatcher = new RegexMatcher( - new Regex("((?:[\\uD83C][\\uDDE6-\\uDDFF]){2}|[\\u2600-\\u26FF]|\\p{Cs}{2}|\\d\\p{Me})", DefaultRegexOptions), - m => new EmojiNode(m.Groups[1].Value)); + new Regex("((?:[\\uD83C][\\uDDE6-\\uDDFF]){2}|[\\u2600-\\u26FF]|\\p{Cs}{2}|\\d\\p{Me})", + DefaultRegexOptions), + m => new EmojiNode(m.Groups[1].Value) + ); // Capture <:lul:123456> or private static readonly IMatcher CustomEmojiNodeMatcher = new RegexMatcher( new Regex("<(a)?:(.+?):(\\d+?)>", DefaultRegexOptions), - m => new EmojiNode(m.Groups[3].Value, m.Groups[2].Value, !string.IsNullOrWhiteSpace(m.Groups[1].Value))); + m => new EmojiNode(m.Groups[3].Value, m.Groups[2].Value, !string.IsNullOrWhiteSpace(m.Groups[1].Value)) + ); /* Links */ // Capture [title](link) private static readonly IMatcher TitledLinkNodeMatcher = new RegexMatcher( new Regex("\\[(.+?)\\]\\((.+?)\\)", DefaultRegexOptions), - m => new LinkNode(m.Groups[2].Value, m.Groups[1].Value)); + m => new LinkNode(m.Groups[2].Value, m.Groups[1].Value) + ); // Capture any non-whitespace character after http:// or https:// until the last punctuation character or whitespace private static readonly IMatcher AutoLinkNodeMatcher = new RegexMatcher( new Regex("(https?://\\S*[^\\.,:;\"\'\\s])", DefaultRegexOptions), - m => new LinkNode(m.Groups[1].Value)); + m => new LinkNode(m.Groups[1].Value) + ); // Same as auto link but also surrounded by angular brackets private static readonly IMatcher HiddenLinkNodeMatcher = new RegexMatcher( new Regex("<(https?://\\S*[^\\.,:;\"\'\\s])>", DefaultRegexOptions), - m => new LinkNode(m.Groups[1].Value)); + m => new LinkNode(m.Groups[1].Value) + ); /* Text */ @@ -160,25 +191,29 @@ namespace DiscordChatExporter.Domain.Markdown // This escapes it from matching for formatting private static readonly IMatcher ShrugTextNodeMatcher = new StringMatcher( @"¯\_(ツ)_/¯", - p => new TextNode(p.ToString())); + p => new TextNode(p.ToString()) + ); // Capture some specific emojis that don't get rendered // This escapes it from matching for emoji private static readonly IMatcher IgnoredEmojiTextNodeMatcher = new RegexMatcher( new Regex("(\\u26A7|\\u2640|\\u2642|\\u2695|\\u267E|\\u00A9|\\u00AE|\\u2122)", DefaultRegexOptions), - m => new TextNode(m.Groups[1].Value)); + m => new TextNode(m.Groups[1].Value) + ); // Capture any "symbol/other" character or surrogate pair preceded by a backslash // This escapes it from matching for emoji private static readonly IMatcher EscapedSymbolTextNodeMatcher = new RegexMatcher( new Regex("\\\\(\\p{So}|\\p{Cs}{2})", DefaultRegexOptions), - m => new TextNode(m.Groups[1].Value)); + m => new TextNode(m.Groups[1].Value) + ); // Capture any non-whitespace, non latin alphanumeric character preceded by a backslash // This escapes it from matching for formatting or other tokens private static readonly IMatcher EscapedCharacterTextNodeMatcher = new RegexMatcher( new Regex("\\\\([^a-zA-Z0-9\\s])", DefaultRegexOptions), - m => new TextNode(m.Groups[1].Value)); + m => new TextNode(m.Groups[1].Value) + ); // Combine all matchers into one // Matchers that have similar patterns are ordered from most specific to least specific diff --git a/DiscordChatExporter.Domain/Markdown/Matching/StringPart.cs b/DiscordChatExporter.Domain/Markdown/Matching/StringPart.cs index ec076c6..cd3ad28 100644 --- a/DiscordChatExporter.Domain/Markdown/Matching/StringPart.cs +++ b/DiscordChatExporter.Domain/Markdown/Matching/StringPart.cs @@ -25,7 +25,7 @@ namespace DiscordChatExporter.Domain.Markdown.Matching { } - public StringPart Slice(int newStartIndex, int newLength) => new StringPart(Target, newStartIndex, newLength); + public StringPart Slice(int newStartIndex, int newLength) => new(Target, newStartIndex, newLength); public StringPart Slice(int newStartIndex) => Slice(newStartIndex, EndIndex - newStartIndex); diff --git a/DiscordChatExporter.Gui/Converters/DateTimeOffsetToDateTimeConverter.cs b/DiscordChatExporter.Gui/Converters/DateTimeOffsetToDateTimeConverter.cs index b493594..850415b 100644 --- a/DiscordChatExporter.Gui/Converters/DateTimeOffsetToDateTimeConverter.cs +++ b/DiscordChatExporter.Gui/Converters/DateTimeOffsetToDateTimeConverter.cs @@ -7,7 +7,7 @@ namespace DiscordChatExporter.Gui.Converters [ValueConversion(typeof(DateTimeOffset?), typeof(DateTime?))] public class DateTimeOffsetToDateTimeConverter : IValueConverter { - public static DateTimeOffsetToDateTimeConverter Instance { get; } = new DateTimeOffsetToDateTimeConverter(); + public static DateTimeOffsetToDateTimeConverter Instance { get; } = new(); public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) { diff --git a/DiscordChatExporter.Gui/Converters/ExportFormatToStringConverter.cs b/DiscordChatExporter.Gui/Converters/ExportFormatToStringConverter.cs index 4feadf1..0e44dd7 100644 --- a/DiscordChatExporter.Gui/Converters/ExportFormatToStringConverter.cs +++ b/DiscordChatExporter.Gui/Converters/ExportFormatToStringConverter.cs @@ -8,7 +8,7 @@ namespace DiscordChatExporter.Gui.Converters [ValueConversion(typeof(ExportFormat), typeof(string))] public class ExportFormatToStringConverter : IValueConverter { - public static ExportFormatToStringConverter Instance { get; } = new ExportFormatToStringConverter(); + public static ExportFormatToStringConverter Instance { get; } = new(); public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) { diff --git a/DiscordChatExporter.Gui/Converters/InverseBoolConverter.cs b/DiscordChatExporter.Gui/Converters/InverseBoolConverter.cs index 6c6c067..a32781a 100644 --- a/DiscordChatExporter.Gui/Converters/InverseBoolConverter.cs +++ b/DiscordChatExporter.Gui/Converters/InverseBoolConverter.cs @@ -7,7 +7,7 @@ namespace DiscordChatExporter.Gui.Converters [ValueConversion(typeof(bool), typeof(bool))] public class InverseBoolConverter : IValueConverter { - public static InverseBoolConverter Instance { get; } = new InverseBoolConverter(); + public static InverseBoolConverter Instance { get; } = new(); public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { diff --git a/DiscordChatExporter.Gui/Converters/TimeSpanToDateTimeConverter.cs b/DiscordChatExporter.Gui/Converters/TimeSpanToDateTimeConverter.cs index 124db66..22075ab 100644 --- a/DiscordChatExporter.Gui/Converters/TimeSpanToDateTimeConverter.cs +++ b/DiscordChatExporter.Gui/Converters/TimeSpanToDateTimeConverter.cs @@ -7,7 +7,7 @@ namespace DiscordChatExporter.Gui.Converters [ValueConversion(typeof(TimeSpan?), typeof(DateTime?))] public class TimeSpanToDateTimeConverter : IValueConverter { - public static TimeSpanToDateTimeConverter Instance { get; } = new TimeSpanToDateTimeConverter(); + public static TimeSpanToDateTimeConverter Instance { get; } = new(); public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) {