![]() |
VOOZH | about |
dotnet add package BoxOfYellow.ConsoleMarkdownRenderer --version 0.11.1
NuGet\Install-Package BoxOfYellow.ConsoleMarkdownRenderer -Version 0.11.1
<PackageReference Include="BoxOfYellow.ConsoleMarkdownRenderer" Version="0.11.1" />
<PackageVersion Include="BoxOfYellow.ConsoleMarkdownRenderer" Version="0.11.1" />Directory.Packages.props
<PackageReference Include="BoxOfYellow.ConsoleMarkdownRenderer" />Project file
paket add BoxOfYellow.ConsoleMarkdownRenderer --version 0.11.1
#r "nuget: BoxOfYellow.ConsoleMarkdownRenderer, 0.11.1"
#:package BoxOfYellow.ConsoleMarkdownRenderer@0.11.1
#addin nuget:?package=BoxOfYellow.ConsoleMarkdownRenderer&version=0.11.1Install as a Cake Addin
#tool nuget:?package=BoxOfYellow.ConsoleMarkdownRenderer&version=0.11.1Install as a Cake Tool
I have markdown files, you have markdown files, we all have markdown files...
We create them to document various parts of projects. Sometimes that documentation would be helpful while folks are using those projects. And that's where this library comes in. This library provides support for displaying markdown within the console and provides a simple navigation list of links and images within the document. When items from the list are selected their content will be shown inline when possible (aka it's another markdown file, or it's an image and the console appears to be using )
I will totally admit README.md files and response that is displayed with --help are not 100% interchangeable, but there is a lot of overlap 🙂
Just call the one public method from the static Displayer.cs class called DisplayMarkdownAsync it accepts the following parameters
| name | type | description | required/default |
|---|---|---|---|
uri |
Uri |
The Uri that is either a file containing your markdown, or the web address where said content can be downloaded | Yes |
options |
DisplayOptions |
Properties and styles to apply to the Markdown elements | no / null |
allowFollowingLinks |
bool |
A flag, when set to true, the list of links will be provided, when false the list is omitted | no / true |
It has a second overload
| name | type | description | required/default |
|---|---|---|---|
text |
string |
the text to display | Yes |
uriBase |
Uri |
The Uri base for all links | no / the current working directory |
options |
DisplayOptions |
Properties and styles to apply to the Markdown elements | no / null |
allowFollowingLinks |
bool |
A flag, when set to true, the list of links will be provided, when false the list is omitted | no / true |
IMarkdownDisplayer)For dependency injection and testability, the library provides an IMarkdownDisplayer interface with the same display methods.
MarkdownDisplayer implements IDisposable; use a using declaration or let your DI container manage the lifetime:
// Short-lived / direct use
using IMarkdownDisplayer displayer = new MarkdownDisplayer();
// Display from a URI
await displayer.DisplayMarkdownAsync(uri, options, allowFollowingLinks: true);
// Display from text
await displayer.DisplayMarkdownAsync(markdownText, baseUri, options);
For DI registration without an IHttpClientFactory (the displayer manages its own HttpClient):
// Register as scoped so the container disposes it automatically
services.AddScoped<IMarkdownDisplayer, MarkdownDisplayer>();
To pipe the container's IHttpClientFactory through to MarkdownDisplayer, use a factory delegate:
// services.AddHttpClient() registers IHttpClientFactory
services.AddHttpClient();
services.AddScoped<IMarkdownDisplayer>(sp =>
new MarkdownDisplayer(sp.GetRequiredService<IHttpClientFactory>()));
// Or with a named client:
services.AddHttpClient("myClient", client => { /* configure */ });
services.AddScoped<IMarkdownDisplayer>(sp =>
new MarkdownDisplayer(sp.GetRequiredService<IHttpClientFactory>(), httpClientName: "myClient"));
IHttpClientFactoryIf your application already registers an IHttpClientFactory (e.g. in an ASP.NET Core or IHostBuilder setup),
you can pass it to MarkdownDisplayer so that all HTTP requests go through your configured factory.
The factory — and the clients it produces — is owned and managed by the caller.
// Using the default (unnamed) client from the factory:
using IMarkdownDisplayer displayer = new MarkdownDisplayer(httpClientFactory);
// Using a named client registered in your DI container:
using IMarkdownDisplayer displayer = new MarkdownDisplayer(httpClientFactory, httpClientName: "myClient");
When no factory is supplied, MarkdownDisplayer creates and reuses its own internal HttpClient with a
SocketsHttpHandler configured with a 15-minute pooled connection lifetime.
The ConsoleMarkdownRenderer.Fakes package provides an out-of-the-box test double:
// Install: BoxOfYellow.ConsoleMarkdownRenderer.Fakes
var fakeDisplayer = new FakeMarkdownDisplayer();
await fakeDisplayer.DisplayMarkdownAsync(new Uri("https://example.com/readme.md"));
// Assert on recorded calls
Assert.AreEqual(1, fakeDisplayer.Calls.Count);
Assert.AreEqual("https://example.com/readme.md", fakeDisplayer.Calls[0].Uri?.ToString());
See ConsoleMarkdownRenderer.ExampleTests for more examples.
Checkout ConsoleMarkdownRenderer.Example to see it in use
The defaults for the styling for the Markdown elements can be seen in the examples listed above. The details for that style can be changed by creating an instance of DisplayOptions and overwriting any that you see fit.
This object is more or less a bag of styles to use for the various parts of your markdown document. There are a few exceptions
| name | type | description | default |
|---|---|---|---|
Headers |
List<IHeaderStyle> |
Used as overrides of Header, an order lists of styles to use for different level of headers |
by default contains a single FigletTextStyle for H1; deeper levels fall back to Header |
WrapHeader |
bool |
When true, will wrap Headers with #'s to denote the level (only applies to plain TextStyle heading entries; ignored for FigletTextStyle) |
yes / true |
IncludeDebug |
bool |
When true will display all content within in boxes to help visualize how the content is being interpreted by the tool |
off / false |
ShowFencedCodeBlockInfo |
bool |
When true, displays the info field (e.g., language identifier) from fenced code blocks |
off / false |
Each entry in Headers (and the Header fallback) is an IHeaderStyle. Two implementations ship with the library:
TextStyle — inline styled markup, optionally wrapped with # characters via WrapHeader.FigletTextStyle — renders the heading text as large ASCII art through Spectre.Console's FigletText widget. Exposes an optional Justification (TextJustification.Left, Right, or Center) and an optional Foreground color. Instances are created via the static factory methods: FigletTextStyle.Create(…) for the default FIGlet font, and the async FigletTextStyle.CreateAsync(fontPath, …) to load a custom FIGlet font (.flf). Because FigletText does not support decoration or background, FigletTextStyle is a peer of TextStyle (both implement IHeaderStyle) rather than a subclass.Default behavior. By default the first entry in Headers is a FigletTextStyle, so top-level (#) headings render as FIGlet ASCII art out of the box. Deeper levels (##, ###, …) fall through to Header and continue to render as styled, #-wrapped markup. To opt H1 into the inline styled markup behavior, clear Headers so every level falls through to Header:
var options = new DisplayOptions();
options.Headers.Clear(); // every level (including H1) uses the styled-markup `Header` fallback
To opt a different level (or the Header fallback) in to FIGlet rendering, assign a FigletTextStyle:
var options = new DisplayOptions();
options.Headers.Add(FigletTextStyle.Create(
justification: TextJustification.Center,
foreground: TextColor.Blue)); // applies to '##' (H2)
It's also important to give credit where credit is due, this library is really just glue for the following packages
Contributions are welcome, please see CONTRIBUTING.md and CODE_OF_CONDUCT.md
The shadow.flf FIGlet font included in ConsoleMarkdownRenderer.Tests/data/fonts is "Shadow" by Glenn Chappell (6/93), distributed with the cmatsuoka/figlet project, and is used here only as a test resource.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 1 NuGet packages that depend on BoxOfYellow.ConsoleMarkdownRenderer:
| Package | Downloads |
|---|---|
|
BoxOfYellow.ConsoleMarkdownRenderer.Fakes
Test fakes for ConsoleMarkdownRenderer, enabling dependency injection and unit testing. See https://github.com/boxofyellow/ConsoleMarkdownRenderer/blob/main/ConsoleMarkdownRenderer.Fakes/README.md |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.11.1 | 215 | 5/22/2026 |
| 0.11.0 | 243 | 5/15/2026 |
| 0.10.1 | 246 | 5/10/2026 |
| 0.10.0 | 139 | 5/10/2026 |
| 0.9.4 | 143 | 5/10/2026 |
| 0.9.3 | 125 | 5/10/2026 |
| 0.9.2 | 161 | 5/9/2026 |
| 0.9.1 | 132 | 5/9/2026 |
| 0.9.0 | 173 | 5/3/2026 |
| 0.8.2 | 126 | 5/2/2026 |
| 0.8.1 | 119 | 5/2/2026 |
| 0.8.0 | 120 | 5/2/2026 |
| 0.7.15 | 131 | 5/2/2026 |
| 0.7.13 | 117 | 4/30/2026 |
| 0.7.12 | 128 | 4/24/2026 |
| 0.7.11 | 121 | 4/10/2026 |
| 0.7.10 | 123 | 4/1/2026 |
| 0.7.9 | 171 | 3/7/2026 |
| 0.7.8 | 119 | 3/4/2026 |
| 0.7.7 | 136 | 2/18/2026 |