Switch from RazorLight to MiniRazor

pull/352/head
Alexey Golub 4 years ago
parent 752003abc3
commit 3db29b520c

@ -2,8 +2,8 @@
<Import Project="../DiscordChatExporter.props" /> <Import Project="../DiscordChatExporter.props" />
<ItemGroup> <ItemGroup>
<PackageReference Include="MiniRazor" Version="1.0.1" />
<PackageReference Include="Polly" Version="7.2.1" /> <PackageReference Include="Polly" Version="7.2.1" />
<PackageReference Include="RazorLight" Version="2.0.0-beta9" />
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" /> <PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
</ItemGroup> </ItemGroup>
@ -11,9 +11,9 @@
<EmbeddedResource Include="Exporting\Writers\Html\Core.css" /> <EmbeddedResource Include="Exporting\Writers\Html\Core.css" />
<EmbeddedResource Include="Exporting\Writers\Html\Dark.css" /> <EmbeddedResource Include="Exporting\Writers\Html\Dark.css" />
<EmbeddedResource Include="Exporting\Writers\Html\Light.css" /> <EmbeddedResource Include="Exporting\Writers\Html\Light.css" />
<EmbeddedResource Include="Exporting\Writers\Html\LayoutTemplate-End.cshtml" /> <EmbeddedResource Include="Exporting\Writers\Html\PreambleTemplate.cshtml" />
<EmbeddedResource Include="Exporting\Writers\Html\LayoutTemplate-Begin.cshtml" /> <EmbeddedResource Include="Exporting\Writers\Html\PostambleTemplate.cshtml" />
<EmbeddedResource Include="Exporting\Writers\Html\MessageGroupTemplate.cshtml" /> <EmbeddedResource Include="Exporting\Writers\Html\MessageGroupTemplate.cshtml" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Domain.Discord.Models; using DiscordChatExporter.Domain.Discord.Models;
@ -12,7 +11,7 @@ using Tyrrrz.Extensions;
namespace DiscordChatExporter.Domain.Exporting namespace DiscordChatExporter.Domain.Exporting
{ {
public class ExportContext internal class ExportContext
{ {
private readonly MediaDownloader _mediaDownloader; private readonly MediaDownloader _mediaDownloader;

@ -1,6 +1,6 @@
namespace DiscordChatExporter.Domain.Exporting.Writers.Html namespace DiscordChatExporter.Domain.Exporting.Writers.Html
{ {
public class LayoutTemplateContext internal class LayoutTemplateContext
{ {
public ExportContext ExportContext { get; } public ExportContext ExportContext { get; }

@ -6,7 +6,7 @@ using DiscordChatExporter.Domain.Discord.Models;
namespace DiscordChatExporter.Domain.Exporting.Writers.Html namespace DiscordChatExporter.Domain.Exporting.Writers.Html
{ {
// Used for grouping contiguous messages in HTML export // Used for grouping contiguous messages in HTML export
public partial class MessageGroup internal partial class MessageGroup
{ {
public User Author { get; } 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) => public static bool CanJoin(Message message1, Message message2) =>
string.Equals(message1.Author.Id, message2.Author.Id, StringComparison.Ordinal) && string.Equals(message1.Author.Id, message2.Author.Id, StringComparison.Ordinal) &&

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

@ -2,7 +2,7 @@
namespace DiscordChatExporter.Domain.Exporting.Writers.Html namespace DiscordChatExporter.Domain.Exporting.Writers.Html
{ {
public class MessageGroupTemplateContext internal class MessageGroupTemplateContext
{ {
public ExportContext ExportContext { get; } public ExportContext ExportContext { get; }

@ -1,6 +1,4 @@
@using RazorLight @inherits MiniRazor.MiniRazorTemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.LayoutTemplateContext>
@using DiscordChatExporter.Domain.Exporting.Writers.Html
@inherits TemplatePage<LayoutTemplateContext>
</div> </div>

@ -1,15 +1,14 @@
@using RazorLight @using System
@using DiscordChatExporter.Domain.Exporting.Writers.Html @using System.Threading.Tasks
@using Tyrrrz.Extensions @using Tyrrrz.Extensions
@inherits TemplatePage<LayoutTemplateContext> @inherits MiniRazor.MiniRazorTemplateBase<DiscordChatExporter.Domain.Exporting.Writers.Html.LayoutTemplateContext>
@{ @{
string FormatDate(DateTimeOffset date) => Model.ExportContext.FormatDate(date); string FormatDate(DateTimeOffset date) => Model.ExportContext.FormatDate(date);
ValueTask<string> ResolveUrlAsync(string url) => Model.ExportContext.ResolveMediaUrlAsync(url); ValueTask<string> ResolveUrlAsync(string url) => Model.ExportContext.ResolveMediaUrlAsync(url);
// Workaround: https://github.com/toddams/RazorLight/issues/359 string GetStyleSheet(string name) => Model.GetType().Assembly.GetManifestResourceString($"DiscordChatExporter.Domain.Exporting.Writers.Html.{name}.css");
string RenderStyleSheet(string name) => Model.GetType().Assembly.GetManifestResourceString($"DiscordChatExporter.Domain.Exporting.Writers.Html.{name}.css");
} }
<!DOCTYPE html> <!DOCTYPE html>
@ -21,10 +20,10 @@
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<style> <style>
@Raw(RenderStyleSheet("Core")) @Raw(GetStyleSheet("Core"))
</style> </style>
<style> <style>
@Raw(RenderStyleSheet(Model.ThemeName)) @Raw(GetStyleSheet(Model.ThemeName))
</style> </style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/solarized-@(Model.ThemeName.ToLowerInvariant()).min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/solarized-@(Model.ThemeName.ToLowerInvariant()).min.css">

@ -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<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("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<TemplateBundle> ResolveAsync() =>
_lastBundle ??= await CompileAsync();
}
}

@ -4,7 +4,6 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Domain.Discord.Models; using DiscordChatExporter.Domain.Discord.Models;
using DiscordChatExporter.Domain.Exporting.Writers.Html; using DiscordChatExporter.Domain.Exporting.Writers.Html;
using RazorLight;
namespace DiscordChatExporter.Domain.Exporting.Writers namespace DiscordChatExporter.Domain.Exporting.Writers
{ {
@ -13,7 +12,6 @@ namespace DiscordChatExporter.Domain.Exporting.Writers
private readonly TextWriter _writer; private readonly TextWriter _writer;
private readonly string _themeName; private readonly string _themeName;
private readonly RazorLightEngine _templateEngine;
private readonly List<Message> _messageGroupBuffer = new List<Message>(); private readonly List<Message> _messageGroupBuffer = new List<Message>();
private long _messageCount; private long _messageCount;
@ -23,28 +21,25 @@ namespace DiscordChatExporter.Domain.Exporting.Writers
{ {
_writer = new StreamWriter(stream); _writer = new StreamWriter(stream);
_themeName = themeName; _themeName = themeName;
_templateEngine = new RazorLightEngineBuilder()
.EnableEncoding()
.UseEmbeddedResourcesProject(typeof(HtmlMessageWriter).Assembly, $"{typeof(HtmlMessageWriter).Namespace}.Html")
.Build();
} }
public override async ValueTask WritePreambleAsync() public override async ValueTask WritePreambleAsync()
{ {
var templateContext = new LayoutTemplateContext(Context, _themeName, _messageCount); var templateContext = new LayoutTemplateContext(Context, _themeName, _messageCount);
var templateBundle = await TemplateBundle.ResolveAsync();
await _writer.WriteLineAsync( await _writer.WriteLineAsync(
await _templateEngine.CompileRenderAsync("LayoutTemplate-Begin.cshtml", templateContext) await templateBundle.PreambleTemplate.RenderAsync(templateContext)
); );
} }
private async ValueTask WriteMessageGroupAsync(MessageGroup messageGroup) private async ValueTask WriteMessageGroupAsync(MessageGroup messageGroup)
{ {
var templateContext = new MessageGroupTemplateContext(Context, messageGroup); var templateContext = new MessageGroupTemplateContext(Context, messageGroup);
var templateBundle = await TemplateBundle.ResolveAsync();
await _writer.WriteLineAsync( 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)); await WriteMessageGroupAsync(MessageGroup.Join(_messageGroupBuffer));
var templateContext = new LayoutTemplateContext(Context, _themeName, _messageCount); var templateContext = new LayoutTemplateContext(Context, _themeName, _messageCount);
var templateBundle = await TemplateBundle.ResolveAsync();
await _writer.WriteLineAsync( await _writer.WriteLineAsync(
await _templateEngine.CompileRenderAsync("LayoutTemplate-End.cshtml", templateContext) await templateBundle.PostambleTemplate.RenderAsync(templateContext)
); );
} }

@ -7,7 +7,6 @@
<Copyright>Copyright (c) Alexey Golub</Copyright> <Copyright>Copyright (c) Alexey Golub</Copyright>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup> </PropertyGroup>
</Project> </Project>
Loading…
Cancel
Save