Skip to content

Latest commit

 

History

History
285 lines (211 loc) · 6.25 KB

File metadata and controls

285 lines (211 loc) · 6.25 KB
title
Custom Markdown Containers

Custom Containers are a popular method for implementing Markdown Extensions for enabling rich, wrist-friendly consistent content in your Markdown documents.

Built-in Containers

Most of VitePress Containers are also implemented in Razor Press, e.g:

Input

::: info
This is an info box.
:::

::: tip
This is a tip.
:::

::: warning
This is a warning.
:::

::: danger
This is a dangerous warning.
:::

Output

::: info This is an info box. :::

::: tip This is a tip. :::

::: warning This is a warning. :::

::: danger This is a dangerous warning. :::

Custom Title

You can specify a custom title by appending the text right after the container type:

Input

::: danger STOP
Danger zone, do not proceed
:::

Output

::: danger STOP Danger zone, do not proceed :::

Pre

The pre container can be used to capture its content in a <pre> element instead of it's default markdown rendering:

:::pre
...
:::

copy

The copy container is ideal for displaying text snippets in a component that allows for easy copying:

Input

:::copy
Copy Me!
:::

Output

:::copy Copy Me! :::

HTML or XML fragments can also be copied by escaping them first:

Input

:::copy
`<PackageReference Include="ServiceStack" Version="8.*" />`
:::

Output

:::copy <PackageReference Include="ServiceStack" Version="8.*" /> :::

sh

Similarly the sh container is ideal for displaying and copying shell commands:

Input

:::sh
npm run prerender
:::

Output

:::sh npm run prerender :::

Implementing Block Containers

Markdig Containers are a great way to create rich widgets that can be used directly in Markdown.

They're useful for ensuring similar content is displayed consistently across all your documentation. A good use-case for this could be to implement a YouTube component for standardizing how YouTube videos are displayed.

For this example we want to display a YouTube video using just its YouTube id and a title for the video which we can capture in the Custom Container:

:::YouTube MRQMBrXi5Sc
Using Razor SSG to Create Websites in GitHub Codespaces
:::

Which we can implement with a normal Markdig HtmlObjectRenderer<CustomContainer>:

public class YouTubeContainer : HtmlObjectRenderer<CustomContainer>
{
    protected override void Write(HtmlRenderer renderer, CustomContainer obj)
    {
        if (obj.Arguments == null)
        {
            renderer.WriteLine($"Missing YouTube Id, Usage :::{obj.Info} <id>");
            return;
        }
        
        renderer.EnsureLine();

        var youtubeId = obj.Arguments!;
        var attrs = obj.TryGetAttributes()!;
        attrs.Classes ??= new();
        attrs.Classes.Add("not-prose text-center");
        
        renderer.Write("<div").WriteAttributes(obj).Write('>');
        renderer.WriteLine("<div class=\"text-3xl font-extrabold tracking-tight\">");
        renderer.WriteChildren(obj);
        renderer.WriteLine("</div>");
        renderer.WriteLine(@$"<div class=""mt-3 flex justify-center"">
            <lite-youtube class=""w-full mx-4 my-4"" width=""560"" height=""315"" videoid=""{youtubeId}"" 
                style=""background-image:url('https://img.youtube.com/vi/{youtubeId}/maxresdefault.jpg')"">
            </lite-youtube>
            </div>
        </div>");
    }
}

That should be registered in Configure.Ssg.cs with the name we want to use for the container:

MarkdigConfig.Set(new MarkdigConfig
{
    ConfigureContainers = config =>
    {
        // Add Custom Block or Inline containers
        config.AddBlockContainer("YouTube", new YouTubeContainer());
    }
});

After which it can be used in your Markdown documentation:

Input

:::YouTube MRQMBrXi5Sc
Using Razor SSG to Create Websites in GitHub Codespaces
:::

Output

:::YouTube MRQMBrXi5Sc Using Razor SSG to Create Websites in GitHub Codespaces :::

Custom Attributes

Since we use WriteAttributes(obj) to emit any attributes we're also able to customize the widget to use a custom id and classes, e.g:

Input

:::YouTube MRQMBrXi5Sc {.text-indigo-600}
Using Razor SSG to Create Websites in GitHub Codespaces
:::

Output

:::YouTube MRQMBrXi5Sc {.text-indigo-600} Using Razor SSG to Create Websites in GitHub Codespaces :::

Implementing Inline Containers

Custom Inline Containers are useful when you don't need a to capture a block of content, like if we just want to display a video without a title, e.g:

::YouTube MRQMBrXi5Sc::

Inline Containers can be implemented with a Markdig HtmlObjectRenderer<CustomContainerInline>, e.g:

public class YouTubeInlineContainer : HtmlObjectRenderer<CustomContainerInline>
{
    protected override void Write(HtmlRenderer renderer, CustomContainerInline obj)
    {
        var youtubeId = obj.FirstChild is Markdig.Syntax.Inlines.LiteralInline literalInline
            ? literalInline.Content.AsSpan().RightPart(' ').ToString()
            : null;
        if (string.IsNullOrEmpty(youtubeId))
        {
            renderer.WriteLine($"Missing YouTube Id, Usage ::YouTube <id>::");
            return;
        }
        renderer.WriteLine(@$"<div class=""mt-3 flex justify-center"">
            <lite-youtube class=""w-full mx-4 my-4"" width=""560"" height=""315"" videoid=""{youtubeId}"" 
                style=""background-image:url('https://img.youtube.com/vi/{youtubeId}/maxresdefault.jpg')"">
            </lite-youtube>
        </div>");
    }
}

That can be registered in Configure.Ssg.cs with:

MarkdigConfig.Set(new MarkdigConfig
{
    ConfigureContainers = config =>
    {
        // Add Custom Block or Inline containers
        config.AddInlineContainer("YouTube", new YouTubeInlineContainer());
    }
});

Where it can then be used in your Markdown documentation:

Input

::YouTube MRQMBrXi5Sc::

Output

::YouTube MRQMBrXi5Sc::