diff --git a/DiscordChatExporter.Domain/DiscordChatExporter.Domain.csproj b/DiscordChatExporter.Domain/DiscordChatExporter.Domain.csproj index 49465ff..d76db52 100644 --- a/DiscordChatExporter.Domain/DiscordChatExporter.Domain.csproj +++ b/DiscordChatExporter.Domain/DiscordChatExporter.Domain.csproj @@ -2,8 +2,8 @@ + - @@ -11,9 +11,9 @@ - - + + - + \ No newline at end of file diff --git a/DiscordChatExporter.Domain/Exporting/ExportContext.cs b/DiscordChatExporter.Domain/Exporting/ExportContext.cs index 397716c..6c091a1 100644 --- a/DiscordChatExporter.Domain/Exporting/ExportContext.cs +++ b/DiscordChatExporter.Domain/Exporting/ExportContext.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; -using System.Net; using System.Net.Http; using System.Threading.Tasks; using DiscordChatExporter.Domain.Discord.Models; @@ -12,7 +11,7 @@ using Tyrrrz.Extensions; namespace DiscordChatExporter.Domain.Exporting { - public class ExportContext + internal class ExportContext { private readonly MediaDownloader _mediaDownloader; diff --git a/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplateContext.cs b/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplateContext.cs index 1930f4e..8614889 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplateContext.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplateContext.cs @@ -1,6 +1,6 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html { - public class LayoutTemplateContext + internal class LayoutTemplateContext { public ExportContext ExportContext { get; } diff --git a/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroup.cs b/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroup.cs index f0ad385..e747f51 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroup.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroup.cs @@ -6,7 +6,7 @@ using DiscordChatExporter.Domain.Discord.Models; namespace DiscordChatExporter.Domain.Exporting.Writers.Html { // Used for grouping contiguous messages in HTML export - public partial class MessageGroup + internal partial class MessageGroup { public User Author { get; } @@ -22,7 +22,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html } } - public partial class MessageGroup + internal partial class MessageGroup { public static bool CanJoin(Message message1, Message message2) => string.Equals(message1.Author.Id, message2.Author.Id, StringComparison.Ordinal) && diff --git a/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplate.cshtml b/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplate.cshtml index 88357d5..e6f9e19 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplate.cshtml +++ b/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplate.cshtml @@ -1,6 +1,7 @@ -@using RazorLight -@using DiscordChatExporter.Domain.Exporting.Writers.Html -@inherits TemplatePage +@using System +@using System.Linq +@using System.Threading.Tasks +@inherits MiniRazor.MiniRazorTemplateBase @{ string FormatDate(DateTimeOffset date) => Model.ExportContext.FormatDate(date); diff --git a/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplateContext.cs b/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplateContext.cs index 08c222b..fa1d335 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplateContext.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/Html/MessageGroupTemplateContext.cs @@ -2,7 +2,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html { - public class MessageGroupTemplateContext + internal class MessageGroupTemplateContext { public ExportContext ExportContext { get; } diff --git a/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplate-End.cshtml b/DiscordChatExporter.Domain/Exporting/Writers/Html/PostambleTemplate.cshtml similarity index 52% rename from DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplate-End.cshtml rename to DiscordChatExporter.Domain/Exporting/Writers/Html/PostambleTemplate.cshtml index 69dec67..33e3e75 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplate-End.cshtml +++ b/DiscordChatExporter.Domain/Exporting/Writers/Html/PostambleTemplate.cshtml @@ -1,6 +1,4 @@ -@using RazorLight -@using DiscordChatExporter.Domain.Exporting.Writers.Html -@inherits TemplatePage +@inherits MiniRazor.MiniRazorTemplateBase diff --git a/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplate-Begin.cshtml b/DiscordChatExporter.Domain/Exporting/Writers/Html/PreambleTemplate.cshtml similarity index 88% rename from DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplate-Begin.cshtml rename to DiscordChatExporter.Domain/Exporting/Writers/Html/PreambleTemplate.cshtml index af808f5..b086c9a 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/Html/LayoutTemplate-Begin.cshtml +++ b/DiscordChatExporter.Domain/Exporting/Writers/Html/PreambleTemplate.cshtml @@ -1,15 +1,14 @@ -@using RazorLight -@using DiscordChatExporter.Domain.Exporting.Writers.Html +@using System +@using System.Threading.Tasks @using Tyrrrz.Extensions -@inherits TemplatePage +@inherits MiniRazor.MiniRazorTemplateBase @{ string FormatDate(DateTimeOffset date) => Model.ExportContext.FormatDate(date); ValueTask ResolveUrlAsync(string url) => Model.ExportContext.ResolveMediaUrlAsync(url); - // Workaround: https://github.com/toddams/RazorLight/issues/359 - string RenderStyleSheet(string name) => Model.GetType().Assembly.GetManifestResourceString($"DiscordChatExporter.Domain.Exporting.Writers.Html.{name}.css"); + string GetStyleSheet(string name) => Model.GetType().Assembly.GetManifestResourceString($"DiscordChatExporter.Domain.Exporting.Writers.Html.{name}.css"); } @@ -21,10 +20,10 @@ diff --git a/DiscordChatExporter.Domain/Exporting/Writers/Html/TemplateBundle.cs b/DiscordChatExporter.Domain/Exporting/Writers/Html/TemplateBundle.cs new file mode 100644 index 0000000..7c87c0d --- /dev/null +++ b/DiscordChatExporter.Domain/Exporting/Writers/Html/TemplateBundle.cs @@ -0,0 +1,59 @@ +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using MiniRazor; +using Tyrrrz.Extensions; + +[assembly: InternalsVisibleTo("RazorAssembly")] + +namespace DiscordChatExporter.Domain.Exporting.Writers.Html +{ + internal partial class TemplateBundle + { + public MiniRazorTemplateDescriptor PreambleTemplate { get; } + + public MiniRazorTemplateDescriptor MessageGroupTemplate { get; } + + public MiniRazorTemplateDescriptor PostambleTemplate { get; } + + public TemplateBundle( + MiniRazorTemplateDescriptor preambleTemplate, + MiniRazorTemplateDescriptor messageGroupTemplate, + MiniRazorTemplateDescriptor postambleTemplate) + { + PreambleTemplate = preambleTemplate; + MessageGroupTemplate = messageGroupTemplate; + PostambleTemplate = postambleTemplate; + } + } + + internal partial class TemplateBundle + { + private static TemplateBundle? _lastBundle; + + // This is very CPU-heavy + private static async ValueTask CompileAsync() => await Task.Run(() => + { + var ns = typeof(TemplateBundle).Namespace!; + + var preambleTemplateSource = typeof(HtmlMessageWriter).Assembly + .GetManifestResourceString($"{ns}.PreambleTemplate.cshtml"); + + var messageGroupTemplateSource = typeof(HtmlMessageWriter).Assembly + .GetManifestResourceString($"{ns}.MessageGroupTemplate.cshtml"); + + var postambleTemplateSource = typeof(HtmlMessageWriter).Assembly + .GetManifestResourceString($"{ns}.PostambleTemplate.cshtml"); + + var engine = new MiniRazorTemplateEngine("RazorAssembly", ns); + + var preambleTemplate = engine.Compile(preambleTemplateSource); + var messageGroupTemplate = engine.Compile(messageGroupTemplateSource); + var postambleTemplate = engine.Compile(postambleTemplateSource); + + return new TemplateBundle(preambleTemplate, messageGroupTemplate, postambleTemplate); + }); + + public static async ValueTask ResolveAsync() => + _lastBundle ??= await CompileAsync(); + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs b/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs index 89a976b..c9e9906 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Threading.Tasks; using DiscordChatExporter.Domain.Discord.Models; using DiscordChatExporter.Domain.Exporting.Writers.Html; -using RazorLight; namespace DiscordChatExporter.Domain.Exporting.Writers { @@ -13,7 +12,6 @@ namespace DiscordChatExporter.Domain.Exporting.Writers private readonly TextWriter _writer; private readonly string _themeName; - private readonly RazorLightEngine _templateEngine; private readonly List _messageGroupBuffer = new List(); private long _messageCount; @@ -23,28 +21,25 @@ namespace DiscordChatExporter.Domain.Exporting.Writers { _writer = new StreamWriter(stream); _themeName = themeName; - - _templateEngine = new RazorLightEngineBuilder() - .EnableEncoding() - .UseEmbeddedResourcesProject(typeof(HtmlMessageWriter).Assembly, $"{typeof(HtmlMessageWriter).Namespace}.Html") - .Build(); } public override async ValueTask WritePreambleAsync() { var templateContext = new LayoutTemplateContext(Context, _themeName, _messageCount); + var templateBundle = await TemplateBundle.ResolveAsync(); await _writer.WriteLineAsync( - await _templateEngine.CompileRenderAsync("LayoutTemplate-Begin.cshtml", templateContext) + await templateBundle.PreambleTemplate.RenderAsync(templateContext) ); } private async ValueTask WriteMessageGroupAsync(MessageGroup messageGroup) { var templateContext = new MessageGroupTemplateContext(Context, messageGroup); + var templateBundle = await TemplateBundle.ResolveAsync(); await _writer.WriteLineAsync( - await _templateEngine.CompileRenderAsync("MessageGroupTemplate.cshtml", templateContext) + await templateBundle.MessageGroupTemplate.RenderAsync(templateContext) ); } @@ -75,9 +70,10 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await WriteMessageGroupAsync(MessageGroup.Join(_messageGroupBuffer)); var templateContext = new LayoutTemplateContext(Context, _themeName, _messageCount); + var templateBundle = await TemplateBundle.ResolveAsync(); await _writer.WriteLineAsync( - await _templateEngine.CompileRenderAsync("LayoutTemplate-End.cshtml", templateContext) + await templateBundle.PostambleTemplate.RenderAsync(templateContext) ); } diff --git a/DiscordChatExporter.props b/DiscordChatExporter.props index de597d2..b1ba65e 100644 --- a/DiscordChatExporter.props +++ b/DiscordChatExporter.props @@ -7,7 +7,6 @@ Copyright (c) Alexey Golub latest enable - true \ No newline at end of file