Making a Blog with C# - Part 3

Building the MVP


Rendering Posts

The first couple of blog posts are simply .md files stored in my project.

In order to actually display them on the website, I added the code below to Index.razor:

@page "/"
@using Pilgaard.Blog.Extensions

    @foreach (var blogPost in _blogPosts)
{
    @blogPost
}

@code {
    private readonly List<MarkupString> _blogPosts = new();
    protected override async Task OnInitializedAsync()
    {
        var postsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Posts");
        var fileNames = Directory.EnumerateFiles(postsPath, " *.md", SearchOption.TopDirectoryOnly);
        foreach (var fileName in fileNames)
        {
            var text = await File.ReadAllTextAsync(fileName);
            _blogPosts.Add(text.ToHtml());
        }
    }
}

This does the following:

  • Find all .md files that should be displayed
    • With this approach, files must be copied to the output directory on build
  • Read the files
  • Convert their text to HTML
  • Render the HTML

Rendering Markdown with Markdig

I used Markdig to convert markdown to HTML, through an extension method:

public static class StringExtensions
{
    public static readonly MarkdownPipeline MarkdownPipeline =
        new MarkdownPipelineBuilder()
            .UseAdvancedExtensions()
            .UseEmojiAndSmiley()
            .Build();

    public static MarkupString ToHtml(this string text)
    {
        var htmlText = Markdown.ToHtml(text, MarkdownPipeline);
        return new MarkupString(htmlText);
    }
}

Syntax Highlighted Code Blocks

I started out using the Markdig extension Markdig.SyntaxHighlighting to add color to code blocks, but I thought the colors were a bit dull, so I switched it out with PrismJs. To get Prism to colorize code blocks, here's what to do:

  • Customize and download Prism from https://prismjs.com/download.html
  • Put the prism.js and prism.css files in the wwwroot folder of the project.
  • Add links to the files in the _Layout.cshtml:
<head>
  ...
  <link href="css/prism.css" rel="stylesheet" />
</head>

<body>
  ...
  <script src="scripts/prism.js"></script>
</body>
  • Add this function to the page that should be highlighted:
@inject IJSRuntime JsRuntime

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await JsRuntime.InvokeVoidAsync("window.Prism.highlightAll");
        await base.OnAfterRenderAsync(firstRender);
    }
}

And that's it!

I wanted to add a little section at the top with links to each part of this blog series, but I just couldn't get page links like this one to work:

<a href="#item-id-here"></a>

After an intense googling session, I stumpled upon this issue: https://github.com/dotnet/aspnetcore/issues/8393

Apparently, this type of link just doesn't work in Blazor yet. Huh.

Luckily, there's a workaround that works just fine for my use-case: Adding onclick="event.stopPropagation();"

<a href="#item-id-here" onclick="event.stopPropagation();"></a>

The caveat is that this will stop any other onclick EventHandler from firing for that specific element, but I can live with that. Credit to SQL-MisterMagoo for the workaround 😄

Accidental SEO

While adding Prism to _Layout.cstml, I couldn't help myself and added some meta tags while I was in there:

<meta
  name="description"
  content="Hi! I write about code - Particularly C#, but also the occasional PowerShell and JavaScript."
/>
<meta property="og:url" content="https://pilgaard-blog.azurewebsites.net/" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Pilgaard | dotnet blog" />
<meta
  property="og:description"
  content="Hi! I write about code - Particularly C#, but also the occasional PowerShell and JavaScript."
/>
<meta
  property="og:image"
  content="https://pilgaard-blog.azurewebsites.net/favicon.ico"
/>

That should make links to the blog render nicely on Twitter, and Facebook.

Going Live

And with that, the website MVP was ready to go live! At this point, I announced the website and my plans on Twitter: https://twitter.com/Niels_Pilgaard/status/1579210443687890946

See the code

Source Code as of this post

The state of the blog

State of the blog

An error has occurred. This app may no longer respond until reloaded. Reload 🗙