Add HTML minification

Closes #345
Closes #743
pull/882/head
Oleksii Holub 2 years ago
parent 94ef4b6981
commit 4283ef22b1

@ -10,6 +10,7 @@
<PackageReference Include="MiniRazor.CodeGen" Version="2.2.1" /> <PackageReference Include="MiniRazor.CodeGen" Version="2.2.1" />
<PackageReference Include="Polly" Version="7.2.3" /> <PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="Superpower" Version="3.0.0" /> <PackageReference Include="Superpower" Version="3.0.0" />
<PackageReference Include="WebMarkupMin.Core" Version="2.9.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -85,7 +85,7 @@
<span class="chatlog__reference-link" onclick="scrollToMessage(event, '@message.ReferencedMessage.Id')"> <span class="chatlog__reference-link" onclick="scrollToMessage(event, '@message.ReferencedMessage.Id')">
@if (!string.IsNullOrWhiteSpace(message.ReferencedMessage.Content)) @if (!string.IsNullOrWhiteSpace(message.ReferencedMessage.Content))
{ {
@Raw(FormatEmbedMarkdown(message.ReferencedMessage.Content)) <!--wmm:ignore-->@Raw(FormatEmbedMarkdown(message.ReferencedMessage.Content))<!--/wmm:ignore-->
} }
else if (message.ReferencedMessage.Attachments.Any() || message.ReferencedMessage.Embeds.Any()) else if (message.ReferencedMessage.Attachments.Any() || message.ReferencedMessage.Embeds.Any())
{ {
@ -134,7 +134,7 @@
{ {
<div class="chatlog__content chatlog__markdown"> <div class="chatlog__content chatlog__markdown">
@{/* Text */} @{/* Text */}
<span class="chatlog__markdown-preserve">@Raw(FormatMarkdown(message.Content))</span> <span class="chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatMarkdown(message.Content))<!--/wmm:ignore--></span>
@{/* Edited timestamp */} @{/* Edited timestamp */}
@if (message.EditedTimestamp is not null) @if (message.EditedTimestamp is not null)
@ -262,12 +262,12 @@
@if (!string.IsNullOrWhiteSpace(embed.Url)) @if (!string.IsNullOrWhiteSpace(embed.Url))
{ {
<a class="chatlog__embed-title-link" href="@embed.Url"> <a class="chatlog__embed-title-link" href="@embed.Url">
<div class="chatlog__markdown chatlog__markdown-preserve">@Raw(FormatEmbedMarkdown(embed.Title))</div> <div class="chatlog__markdown chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatEmbedMarkdown(embed.Title))<!--/wmm:ignore--></div>
</a> </a>
} }
else else
{ {
<div class="chatlog__markdown chatlog__markdown-preserve">@Raw(FormatEmbedMarkdown(embed.Title))</div> <div class="chatlog__markdown chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatEmbedMarkdown(embed.Title))<!--/wmm:ignore--></div>
} }
</div> </div>
} }
@ -330,12 +330,12 @@
@if (!string.IsNullOrWhiteSpace(embed.Url)) @if (!string.IsNullOrWhiteSpace(embed.Url))
{ {
<a class="chatlog__embed-title-link" href="@embed.Url"> <a class="chatlog__embed-title-link" href="@embed.Url">
<div class="chatlog__markdown chatlog__markdown-preserve">@Raw(FormatEmbedMarkdown(embed.Title))</div> <div class="chatlog__markdown chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatEmbedMarkdown(embed.Title))<!--/wmm:ignore--></div>
</a> </a>
} }
else else
{ {
<div class="chatlog__markdown chatlog__markdown-preserve">@Raw(FormatEmbedMarkdown(embed.Title))</div> <div class="chatlog__markdown chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatEmbedMarkdown(embed.Title))<!--/wmm:ignore--></div>
} }
</div> </div>
} }
@ -344,7 +344,7 @@
@if (!string.IsNullOrWhiteSpace(embed.Description)) @if (!string.IsNullOrWhiteSpace(embed.Description))
{ {
<div class="chatlog__embed-description"> <div class="chatlog__embed-description">
<div class="chatlog__markdown chatlog__markdown-preserve">@Raw(FormatEmbedMarkdown(embed.Description))</div> <div class="chatlog__markdown chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatEmbedMarkdown(embed.Description))<!--/wmm:ignore--></div>
</div> </div>
} }
@ -358,14 +358,14 @@
@if (!string.IsNullOrWhiteSpace(field.Name)) @if (!string.IsNullOrWhiteSpace(field.Name))
{ {
<div class="chatlog__embed-field-name"> <div class="chatlog__embed-field-name">
<div class="chatlog__markdown chatlog__markdown-preserve">@Raw(FormatEmbedMarkdown(field.Name))</div> <div class="chatlog__markdown chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatEmbedMarkdown(field.Name))<!--/wmm:ignore--></div>
</div> </div>
} }
@if (!string.IsNullOrWhiteSpace(field.Value)) @if (!string.IsNullOrWhiteSpace(field.Value))
{ {
<div class="chatlog__embed-field-value"> <div class="chatlog__embed-field-value">
<div class="chatlog__markdown chatlog__markdown-preserve">@Raw(FormatEmbedMarkdown(field.Value))</div> <div class="chatlog__markdown chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatEmbedMarkdown(field.Value))<!--/wmm:ignore--></div>
</div> </div>
} }
</div> </div>

@ -4,7 +4,9 @@
@inherits MiniRazor.TemplateBase<PostambleTemplateContext> @inherits MiniRazor.TemplateBase<PostambleTemplateContext>
@{/* Close elements opened by preamble */} @{/* Close elements opened by preamble */}
<!--wmm:ignore-->
</div> </div>
<!--/wmm:ignore-->
<div class="postamble"> <div class="postamble">
<div class="postamble__entry">Exported @Model.MessagesWritten.ToString("N0") message(s)</div> <div class="postamble__entry">Exported @Model.MessagesWritten.ToString("N0") message(s)</div>

@ -807,4 +807,6 @@
</div> </div>
@{/* Preamble cuts off at this point */} @{/* Preamble cuts off at this point */}
<!--wmm:ignore-->
<div class="chatlog"> <div class="chatlog">
<!--/wmm:ignore-->

@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Core.Discord.Data; using DiscordChatExporter.Core.Discord.Data;
using DiscordChatExporter.Core.Exporting.Writers.Html; using DiscordChatExporter.Core.Exporting.Writers.Html;
using WebMarkupMin.Core;
namespace DiscordChatExporter.Core.Exporting.Writers; namespace DiscordChatExporter.Core.Exporting.Writers;
@ -14,6 +15,7 @@ internal class HtmlMessageWriter : MessageWriter
private readonly TextWriter _writer; private readonly TextWriter _writer;
private readonly string _themeName; private readonly string _themeName;
private readonly HtmlMinifier _minifier = new();
private readonly List<Message> _messageGroup = new(); private readonly List<Message> _messageGroup = new();
public HtmlMessageWriter(Stream stream, ExportContext context, string themeName) public HtmlMessageWriter(Stream stream, ExportContext context, string themeName)
@ -23,22 +25,22 @@ internal class HtmlMessageWriter : MessageWriter
_themeName = themeName; _themeName = themeName;
} }
private bool CanJoinGroup(Message message) private bool CanJoinGroup(Message message) =>
{ // First message in the group can always join
var lastMessage = _messageGroup.LastOrDefault(); _messageGroup.LastOrDefault() is not { } lastMessage ||
if (lastMessage is null) // Must be from the same author
return true; lastMessage.Author.Id == message.Author.Id &&
// Author's name must not have changed between messages
return string.Equals(lastMessage.Author.FullName, message.Author.FullName, StringComparison.Ordinal) &&
// Must be from the same author // Duration between messages must be 7 minutes or less
lastMessage.Author.Id == message.Author.Id && (message.Timestamp - lastMessage.Timestamp).Duration().TotalMinutes <= 7 &&
// Author's name must not have changed between messages // Other message must not be a reply
string.Equals(lastMessage.Author.FullName, message.Author.FullName, StringComparison.Ordinal) && message.Reference is null;
// Duration between messages must be 7 minutes or less
(message.Timestamp - lastMessage.Timestamp).Duration().TotalMinutes <= 7 && // Use <!--wmm:ignore--> to preserve blocks of code inside the templates
// Other message must not be a reply private string Minify(string html) => _minifier
message.Reference is null; .Minify(html, false)
} .MinifiedContent;
public override async ValueTask WritePreambleAsync(CancellationToken cancellationToken = default) public override async ValueTask WritePreambleAsync(CancellationToken cancellationToken = default)
{ {
@ -47,7 +49,9 @@ internal class HtmlMessageWriter : MessageWriter
// We are not writing directly to output because Razor // We are not writing directly to output because Razor
// does not actually do asynchronous writes to stream. // does not actually do asynchronous writes to stream.
await _writer.WriteLineAsync( await _writer.WriteLineAsync(
await PreambleTemplate.RenderAsync(templateContext, cancellationToken) Minify(
await PreambleTemplate.RenderAsync(templateContext, cancellationToken)
)
); );
} }
@ -60,7 +64,9 @@ internal class HtmlMessageWriter : MessageWriter
// We are not writing directly to output because Razor // We are not writing directly to output because Razor
// does not actually do asynchronous writes to stream. // does not actually do asynchronous writes to stream.
await _writer.WriteLineAsync( await _writer.WriteLineAsync(
await MessageGroupTemplate.RenderAsync(templateContext, cancellationToken) Minify(
await MessageGroupTemplate.RenderAsync(templateContext, cancellationToken)
)
); );
} }
@ -96,7 +102,9 @@ internal class HtmlMessageWriter : MessageWriter
// We are not writing directly to output because Razor // We are not writing directly to output because Razor
// does not actually do asynchronous writes to stream. // does not actually do asynchronous writes to stream.
await _writer.WriteLineAsync( await _writer.WriteLineAsync(
await PostambleTemplate.RenderAsync(templateContext, cancellationToken) Minify(
await PostambleTemplate.RenderAsync(templateContext, cancellationToken)
)
); );
} }

Loading…
Cancel
Save