markdig icon indicating copy to clipboard operation
markdig copied to clipboard

Prefix auto-generated identifiers

Open kirtithorat opened this issue 4 years ago • 6 comments

Is it possible to add a prefix to the auto-generated identifiers? If not, then are there any plans for it to be supported in the future?

Usecase: We are using markdig in only a part of the page or multiple different parts of the same page. Planning to enable AutoIdentifiers for headers but we need to be able to specify our own prefix so as not to conflict with existing identifiers on a page.

Will appreciate any suggestions. Thank you!

kirtithorat avatar Jun 25 '21 19:06 kirtithorat

Not currently possible, no plans but PR opened and welcome 🙂

xoofx avatar Jul 06 '21 16:07 xoofx

Being able to control the generated identifier in general would be nice. I tried having a look at extending the AutoIdentifierExtension class, but most methods in the class are private. On the other hand, trying to copy the code for the class isn't easily possible either as the ValueStringBuilder class as well as the HtmlRenderer.Reset method are both internal.

Would a PR to change the AutoIdentifierExtension methods from private to protected virtual be accepted?

Right now the urilization of each identifier is handled by either of the LinkHelper.Urilize or LinkHelper.UrilizeAsGfm methods depending of the options. Would moving this a new protected virtual Urilize method be accepted as well? I'm not thinking moving the urilization logic to this method - instead the default implementation would call either of these methods as today. But the new method being virtual would allow developers to override it.

abjerner avatar May 11 '23 16:05 abjerner

FWIW modifying the generated ID after parsing may be simpler:

MarkdownDocument document = Markdown.Parse(md, pipeline);

foreach (HeadingBlock heading in document.Descendants<HeadingBlock>())
{
    HtmlAttributes attributes = heading.GetAttributes();
    attributes.Id = $"my-prefix-{attributes.Id}";
}

string html = document.ToHtml(pipeline);

MihaZupan avatar May 11 '23 17:05 MihaZupan

Thanks. My use case was to handle certain special characters before they are stripped for the ID. But this could possibly work as well 👍

abjerner avatar May 11 '23 18:05 abjerner

Note that you have access to the original information as well via the HeadingBlock, so you can create a new id from scratch this way too

MihaZupan avatar May 11 '23 18:05 MihaZupan

Yes, I assumed from your snippet that something like that would be possible as well. After playing a bit around with the code, I ended up like the method below. I'm not super familiar with the inner workings of Markdig, so maybe it can be done more efficient - but this as least does the job.

For one, my issue was that C# was converted to c. With the method below, it's now converted to csharp instead 😎

private static void UpdateHeadingIds(MarkdownDocument document)
{

    foreach (HeadingBlock heading in document.Descendants<HeadingBlock>())
    {

        if (heading.Inline is null) continue;

        StringWriter writer = new();

        HtmlRenderer renderer = new(writer)
        {
            EnableHtmlForInline = false,
            EnableHtmlEscape = false
        };

        renderer.Render(heading.Inline);

        string innerText = writer
            .ToString()
            .Replace("C#", "csharp");

        heading.GetAttributes().Id = LinkHelper.Urilize(innerText, true);

    }

}

Thanks for the pointers 👍

abjerner avatar May 11 '23 19:05 abjerner