In this post I will talk through how I updated Don Wilson's (@dontangg) nocco from .NET Framework v4.0 to .NET (Core) v9.
So what is nocco? It's a .NET port of Docco. What is Docco?
Docco is a quick-and-dirty documentation generator, written in Literate CoffeeScript. It produces an HTML document that displays your comments intermingled with your code. All prose is passed through Markdown, and code is passed through Highlight.js syntax highlighting. This page is the result of running Docco against its own source file.
Nocco is a quick-and-dirty, literate-programming-style
You can see an original output of nocco.cs
on http://donwilson.net/nocco/.
What does it do? The original takes a list of files, these could be C#, VB.NET, SQL or JS and produces a side by side view of code comments and their respective code.
From the nocco.cs
page at the Razor section their notes are the following:
Setup the Razor templating engine so that we can quickly pass the data in and generate HTML. The file
Resources\Nocco.cshtml
is read and compiled into a new dll with a type that extends theTemplateBase
class. This new assembly is loaded so that we can create an instance and pass data into it and generate the HTML.
This file was then executed to produce the output, along with the html documentation and syntax highlighted code, you can read more about it on the linked page or in the code itself.
I've got some experience with building DLLs using Microsoft.CodeAnalysis.CSharp
when I built BlazorInteractive but this has changed a little from the original CSharpCodeProvider
used here.
For the first pass I thought it might be easier to not have the code be compiled in the same way, instead I'll just build a Razor page, like before, and then pass the data I needed. Luckily Rob Anderson had told me about a method he'd used to do this:
- Render Razor components outside of ASP.NET Core
HtmlRenderer
to the rescue.
I made the project use the SDK: Microsoft.NET.Sdk.Razor
then added the Microsoft.AspNetCore.Components.Web
library.
Next the GenerateHtml()
method was where I got to work updating. Following the above tutorial was very quick. I renamed the original Nocco.cshtml
to Webpage.razor
and added in the corresponding @code {}
and [Parameter]
s. This now allows me to pass a Dictionary
of KVPs matching the Parameter names with the corresponding data types. It didn't like passing the Func<>
directly as an object?
so I made it it's own variable and passed that in.
GenerateHtml
private static async void GenerateHtml(string source, List<Section> sections)
{
int depth;
var destination = GetDestination(source, out depth);
string pathToRoot = string.Concat(Enumerable.Repeat(".." + Path.DirectorySeparatorChar, depth));
IServiceCollection services = new ServiceCollection();
services.AddLogging();
IServiceProvider serviceProvider = services.BuildServiceProvider();
ILoggerFactory loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
await using var htmlRenderer = new HtmlRenderer(serviceProvider, loggerFactory);
var html = await htmlRenderer.Dispatcher.InvokeAsync(async () =>
{
Func<string, string> getSourcePath = s =>
Path.Combine(pathToRoot, Path.ChangeExtension(s.ToLower(), ".html").Substring(2)).Replace('\\', '/');
var dictionary = new Dictionary<string, object?>
{
{ "Title", Path.GetFileName(source) },
{ "PathToCss", Path.Combine(pathToRoot, "nocco.css").Replace('\\', '/') },
{ "PathToJs", Path.Combine(pathToRoot, "prettify.js").Replace('\\', '/') },
{ "GetSourcePath", getSourcePath },
{ "Sections", sections },
{ "Sources", _files },
};
var parameters = ParameterView.FromDictionary(dictionary);
var output = await htmlRenderer.RenderComponentAsync<Webpage>(parameters);
return output.ToHtmlString();
});
File.WriteAllText(destination, html);
}
Build the app.
Navigate to the folder with your source files in
nocco *.cs
Open the newly created docs
folder and open any of the matching *.html
files.
Dependencies
The original also used MarkdownSharp v1.13.0.0, I updated this to MarkdownSharpCore v1.2.0 just to make the upgrade easier, I'm contemplating swapping to Markdig.