* chore: add markdown lint to ignore no h1 heading in markdown files * chore: update example settings * chore: update example development env file * fix: remove fixed 100% height on container * feat: add individual post page * chore: update README.md * feat: add links to headings in post and add copy button to code blocks * tests: add tests for get post async method * tests: remove heading for test blogs * fix: only add links to headings in markdown body * tests: add tests for post page * tests: add test to check for blog content * docs: add jsdoc comments * chore: fix incorrect env variable format in example * fix: don't render anything if blog post is null * fix: don't render anything until posts are fetched * chore: add docker compose file for prod
82 lines
1.9 KiB
Plaintext
82 lines
1.9 KiB
Plaintext
@page "/{slug:nonfile}"
|
|
@implements IAsyncDisposable
|
|
@inject IPostService PostService
|
|
@inject NavigationManager NavigationManager
|
|
@inject IJSRuntime JSRuntime
|
|
@inject ILogger<Post> Logger
|
|
|
|
@if (BlogPost is null)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
<PageTitle>@BlogPost.Title - journal</PageTitle>
|
|
|
|
<HeadContent>
|
|
<meta name="description" content="@BlogPost.Lead">
|
|
<link rel="stylesheet" href="markdown.css">
|
|
<link rel="stylesheet" href="prism.css">
|
|
<script src="prism.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script>
|
|
</HeadContent>
|
|
|
|
<article>
|
|
<div class="heading-container">
|
|
<h2>@BlogPost.Title</h2>
|
|
<p>@BlogPost.PublishedAt.ToString("MMMM d, yyyy")</p>
|
|
</div>
|
|
<div class="markdown-body">
|
|
@((MarkupString)BlogPost.Content)
|
|
</div>
|
|
</article>
|
|
}
|
|
|
|
@code {
|
|
[Parameter]
|
|
public string Slug { get; set; } = string.Empty;
|
|
private PostWithContent? BlogPost;
|
|
private IJSObjectReference? module;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
var post = await PostService.GetPostAsync(Slug);
|
|
|
|
if (post is null)
|
|
{
|
|
NavigationManager.NavigateTo("/Error/404");
|
|
return;
|
|
}
|
|
|
|
BlogPost = post;
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender)
|
|
{
|
|
module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Components/Pages/Post.razor.js");
|
|
await module.InvokeVoidAsync("addAnchors");
|
|
await module.InvokeVoidAsync("addClipboard");
|
|
}
|
|
}
|
|
|
|
async ValueTask IAsyncDisposable.DisposeAsync()
|
|
{
|
|
try
|
|
{
|
|
if (module is not null)
|
|
{
|
|
await module.DisposeAsync();
|
|
}
|
|
}
|
|
catch (Exception ex) when (ex is JSDisconnectedException)
|
|
{
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.LogError(ex, "Error disposing of the module");
|
|
}
|
|
}
|
|
} |