Update MiniRazor to use build-time template compilation

This commit is contained in:
Tyrrrz 2020-12-15 03:44:00 +02:00
parent 43c50324d8
commit 9394824943
6 changed files with 18 additions and 78 deletions

View file

@ -1,8 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JsonExtensions" Version="1.0.1" />
<PackageReference Include="MiniRazor" Version="1.1.0" />
<PackageReference Include="MiniRazor" Version="2.0.3" />
<PackageReference Include="Polly" Version="7.2.1" />
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
</ItemGroup>
@ -11,9 +15,9 @@
<EmbeddedResource Include="Exporting\Writers\Html\Core.css" />
<EmbeddedResource Include="Exporting\Writers\Html\Dark.css" />
<EmbeddedResource Include="Exporting\Writers\Html\Light.css" />
<EmbeddedResource Include="Exporting\Writers\Html\PreambleTemplate.cshtml" />
<EmbeddedResource Include="Exporting\Writers\Html\PostambleTemplate.cshtml" />
<EmbeddedResource Include="Exporting\Writers\Html\MessageGroupTemplate.cshtml" />
<AdditionalFiles Include="Exporting\Writers\Html\PreambleTemplate.cshtml" IsRazorTemplate="true" />
<AdditionalFiles Include="Exporting\Writers\Html\PostambleTemplate.cshtml" IsRazorTemplate="true" />
<AdditionalFiles Include="Exporting\Writers\Html\MessageGroupTemplate.cshtml" IsRazorTemplate="true" />
</ItemGroup>
</Project>

View file

@ -1,7 +1,8 @@
@using System
@using System.Linq
@using System.Threading.Tasks
@inherits MiniRazor.MiniRazorTemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.MessageGroupTemplateContext>
@namespace DiscordChatExporter.Domain.Exporting.Writers.Html
@inherits MiniRazor.TemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.MessageGroupTemplateContext>
@{
string FormatDate(DateTimeOffset date) => Model.ExportContext.FormatDate(date);

View file

@ -1,4 +1,5 @@
@inherits MiniRazor.MiniRazorTemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.LayoutTemplateContext>
@namespace DiscordChatExporter.Domain.Exporting.Writers.Html
@inherits MiniRazor.TemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.LayoutTemplateContext>
</div>
@ -7,4 +8,5 @@
</div>
</body>
</html>

View file

@ -1,7 +1,8 @@
@using System
@using System.Threading.Tasks
@using Tyrrrz.Extensions
@inherits MiniRazor.MiniRazorTemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.LayoutTemplateContext>
@namespace DiscordChatExporter.Domain.Exporting.Writers.Html
@inherits MiniRazor.TemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.LayoutTemplateContext>
@{
string FormatDate(DateTimeOffset date) => Model.ExportContext.FormatDate(date);

View file

@ -1,65 +0,0 @@
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using MiniRazor;
using Tyrrrz.Extensions;
[assembly: InternalsVisibleTo(DiscordChatExporter.Domain.Exporting.Writers.Html.TemplateBundle.PreambleTemplateAssemblyName)]
[assembly: InternalsVisibleTo(DiscordChatExporter.Domain.Exporting.Writers.Html.TemplateBundle.MessageGroupTemplateAssemblyName)]
[assembly: InternalsVisibleTo(DiscordChatExporter.Domain.Exporting.Writers.Html.TemplateBundle.PostambleTemplateAssemblyName)]
namespace DiscordChatExporter.Domain.Exporting.Writers.Html
{
internal partial class TemplateBundle
{
public const string PreambleTemplateAssemblyName = "RazorAssembly_Preamble";
public const string MessageGroupTemplateAssemblyName = "RazorAssembly_MessageGroup";
public const string PostambleTemplateAssemblyName = "RazorAssembly_Postamble";
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<TemplateBundle> 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();
var preambleTemplate = engine.Compile(preambleTemplateSource, PreambleTemplateAssemblyName, ns);
var messageGroupTemplate = engine.Compile(messageGroupTemplateSource, MessageGroupTemplateAssemblyName, ns);
var postambleTemplate = engine.Compile(postambleTemplateSource, PostambleTemplateAssemblyName, ns);
return new TemplateBundle(preambleTemplate, messageGroupTemplate, postambleTemplate);
});
public static async ValueTask<TemplateBundle> ResolveAsync() =>
_lastBundle ??= await CompileAsync();
}
}

View file

@ -26,20 +26,18 @@ namespace DiscordChatExporter.Domain.Exporting.Writers
public override async ValueTask WritePreambleAsync()
{
var templateContext = new LayoutTemplateContext(Context, _themeName, _messageCount);
var templateBundle = await TemplateBundle.ResolveAsync();
await _writer.WriteLineAsync(
await templateBundle.PreambleTemplate.RenderAsync(templateContext)
await PreambleTemplate.RenderAsync(templateContext)
);
}
private async ValueTask WriteMessageGroupAsync(MessageGroup messageGroup)
{
var templateContext = new MessageGroupTemplateContext(Context, messageGroup);
var templateBundle = await TemplateBundle.ResolveAsync();
await _writer.WriteLineAsync(
await templateBundle.MessageGroupTemplate.RenderAsync(templateContext)
await MessageGroupTemplate.RenderAsync(templateContext)
);
}
@ -70,10 +68,9 @@ 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 templateBundle.PostambleTemplate.RenderAsync(templateContext)
await PostambleTemplate.RenderAsync(templateContext)
);
}