Compare commits
4 Commits
1cdad4c17c
...
20eabeeb1e
Author | SHA1 | Date | |
---|---|---|---|
20eabeeb1e | |||
fe4701c1bf | |||
d9c6034aa0 | |||
7ee9d3637c |
@ -11,9 +11,10 @@ internal sealed class TemplateConfiguration : IEntityTypeConfiguration<Template>
|
||||
public void Configure(EntityTypeBuilder<Template> builder)
|
||||
{
|
||||
builder.ToTable("Template");
|
||||
builder.HasKey(e => e.Name);
|
||||
builder.HasKey(e => new { e.Name, e.Variant });
|
||||
|
||||
builder.Property(e => e.Name).IsRequired();
|
||||
builder.Property(e => e.Name).HasMaxLength(50).IsRequired();
|
||||
builder.Property(e => e.Variant).HasMaxLength(50).IsRequired();
|
||||
builder.Property(e => e.FormatString).IsRequired();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace OliverBooth.Data;
|
||||
namespace OliverBooth.Data.Web;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a template.
|
||||
@ -15,4 +15,10 @@ public interface ITemplate
|
||||
/// Gets the name of the template.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the variant of the template.
|
||||
/// </summary>
|
||||
/// <value>The variant of the template.</value>
|
||||
string Variant { get; }
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ public sealed class Template : ITemplate, IEquatable<Template>
|
||||
/// <inheritdoc />
|
||||
public string Name { get; private set; } = string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Variant { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether two instances of <see cref="Template" /> are equal.
|
||||
/// </summary>
|
||||
@ -46,7 +49,7 @@ public sealed class Template : ITemplate, IEquatable<Template>
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return Name == other.Name;
|
||||
return Name == other.Name && Variant == other.Variant;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -68,7 +71,7 @@ public sealed class Template : ITemplate, IEquatable<Template>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
return Name.GetHashCode();
|
||||
// ReSharper disable NonReadonlyMemberInGetHashCode
|
||||
return HashCode.Combine(Name, Variant);
|
||||
}
|
||||
}
|
||||
|
@ -30,4 +30,10 @@ public sealed class TemplateInline : Inline
|
||||
/// </summary>
|
||||
/// <value>The template parameters.</value>
|
||||
public IReadOnlyDictionary<string, string> Params { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the variant of the template.
|
||||
/// </summary>
|
||||
/// <value>The variant of the template.</value>
|
||||
public string Variant { get; set; } = string.Empty;
|
||||
}
|
||||
|
@ -37,11 +37,22 @@ public sealed class TemplateInlineParser : InlineParser
|
||||
|
||||
template = template[2..^2]; // trim {{ and }}
|
||||
ReadOnlySpan<char> name = ReadTemplateName(template, out ReadOnlySpan<char> argumentSpan);
|
||||
int variantIndex = name.IndexOf(':');
|
||||
bool hasVariant = variantIndex > -1;
|
||||
var variant = ReadOnlySpan<char>.Empty;
|
||||
|
||||
if (hasVariant)
|
||||
{
|
||||
variant = name[(variantIndex + 1)..];
|
||||
name = name[..variantIndex];
|
||||
}
|
||||
|
||||
if (argumentSpan.IsEmpty)
|
||||
{
|
||||
processor.Inline = new TemplateInline
|
||||
{
|
||||
Name = name.ToString(),
|
||||
Variant = hasVariant ? variant.ToString() : string.Empty,
|
||||
ArgumentString = string.Empty,
|
||||
ArgumentList = ArraySegment<string>.Empty,
|
||||
Params = EmptyParams
|
||||
@ -60,6 +71,7 @@ public sealed class TemplateInlineParser : InlineParser
|
||||
processor.Inline = new TemplateInline
|
||||
{
|
||||
Name = name.ToString(),
|
||||
Variant = hasVariant ? variant.ToString() : string.Empty,
|
||||
ArgumentString = argumentSpan.ToString(),
|
||||
ArgumentList = argumentList.AsReadOnly(),
|
||||
Params = paramsList.AsReadOnly()
|
||||
|
@ -18,7 +18,7 @@
|
||||
<nav style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a asp-page="/index">Blog</a>
|
||||
<a asp-page="index">Blog</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active" aria-current="page">@post.Title</li>
|
||||
</ol>
|
||||
|
@ -10,6 +10,9 @@ using Serilog;
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.Console()
|
||||
.WriteTo.File("logs/latest.log", rollingInterval: RollingInterval.Day)
|
||||
#if DEBUG
|
||||
.MinimumLevel.Debug()
|
||||
#endif
|
||||
.CreateLogger();
|
||||
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using OliverBooth.Data;
|
||||
using OliverBooth.Data.Web;
|
||||
using OliverBooth.Markdown.Template;
|
||||
|
||||
namespace OliverBooth.Services;
|
||||
@ -28,4 +30,27 @@ public interface ITemplateService
|
||||
/// <paramref name="templateInline" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
string RenderTemplate(TemplateInline templateInline, ITemplate? template);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to get the template with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the template.</param>
|
||||
/// <param name="template">
|
||||
/// When this method returns, contains the template with the specified name, if the template is found;
|
||||
/// otherwise, <see langword="null" />.
|
||||
/// </param>
|
||||
/// <returns><see langword="true" /> if the template exists; otherwise, <see langword="false" />.</returns>
|
||||
bool TryGetTemplate(string name, [NotNullWhen(true)] out ITemplate? template);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to get the template with the specified name and variant.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the template.</param>
|
||||
/// <param name="variant">The variant of the template.</param>
|
||||
/// <param name="template">
|
||||
/// When this method returns, contains the template with the specified name and variant, if the template is
|
||||
/// found; otherwise, <see langword="null" />.
|
||||
/// </param>
|
||||
/// <returns><see langword="true" /> if the template exists; otherwise, <see langword="false" />.</returns>
|
||||
bool TryGetTemplate(string name, string variant, [NotNullWhen(true)] out ITemplate? template);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Buffers.Binary;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using OliverBooth.Data;
|
||||
using OliverBooth.Data.Web;
|
||||
@ -40,17 +41,17 @@ internal sealed class TemplateService : ITemplateService
|
||||
{
|
||||
if (templateInline is null) throw new ArgumentNullException(nameof(templateInline));
|
||||
|
||||
using WebContext context = _webContextFactory.CreateDbContext();
|
||||
Template? template = context.Templates.Find(templateInline.Name);
|
||||
return RenderTemplate(templateInline, template);
|
||||
return TryGetTemplate(templateInline.Name, templateInline.Variant, out ITemplate? template)
|
||||
? RenderTemplate(templateInline, template)
|
||||
: GetDefaultRender(templateInline);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string RenderTemplate(TemplateInline inline, ITemplate? template)
|
||||
public string RenderTemplate(TemplateInline templateInline, ITemplate? template)
|
||||
{
|
||||
if (template is null)
|
||||
{
|
||||
return $"{{{{{inline.Name}}}}}";
|
||||
return GetDefaultRender(templateInline);
|
||||
}
|
||||
|
||||
Span<byte> randomBytes = stackalloc byte[20];
|
||||
@ -58,9 +59,9 @@ internal sealed class TemplateService : ITemplateService
|
||||
|
||||
var formatted = new
|
||||
{
|
||||
inline.ArgumentList,
|
||||
inline.ArgumentString,
|
||||
inline.Params,
|
||||
templateInline.ArgumentList,
|
||||
templateInline.ArgumentString,
|
||||
templateInline.Params,
|
||||
RandomInt = BinaryPrimitives.ReadInt32LittleEndian(randomBytes[..4]),
|
||||
RandomGuid = new Guid(randomBytes[4..]).ToString("N"),
|
||||
};
|
||||
@ -71,7 +72,28 @@ internal sealed class TemplateService : ITemplateService
|
||||
}
|
||||
catch
|
||||
{
|
||||
return $"{{{{{inline.Name}|{inline.ArgumentString}}}}}";
|
||||
return GetDefaultRender(templateInline);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetTemplate(string name, [NotNullWhen(true)] out ITemplate? template)
|
||||
{
|
||||
return TryGetTemplate(name, string.Empty, out template);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetTemplate(string name, string variant, [NotNullWhen(true)] out ITemplate? template)
|
||||
{
|
||||
using WebContext context = _webContextFactory.CreateDbContext();
|
||||
template = context.Templates.FirstOrDefault(t => t.Name == name && t.Variant == variant);
|
||||
return template is not null;
|
||||
}
|
||||
|
||||
private static string GetDefaultRender(TemplateInline templateInline)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(templateInline.ArgumentString)
|
||||
? $"{{{{{templateInline.Name}}}}}"
|
||||
: $"{{{{{templateInline.Name}|{templateInline.ArgumentString}}}}}";
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user