xoofx / xoofx/markdig

Feature-request: Transform relative file links

Open
#897 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement PR Welcome! question
Dominant language
C#
Stars
5.3k
Forks
510
Avg merge
8d 5h
Merged PRs (30d)
5

Description

Sometimes text is distributed among multiple markdown files, which refer to each other with links such as [Configuration-section](./configuration.md).

When transforming to HTML, it would be nice to link to the corresponding files (./configuration.html in the example above).

While I already have written a RelativeFileLinkExtension and included it in our project, I'd prefer to have it officially supported and would therefore like to create a merge-request for it. Would this be a welcome contribution, @xoofx ?

Code from our project as follows:

public static MarkdownPipelineBuilder TransformFileLinks(this MarkdownPipelineBuilder pipeline)
{
    pipeline.Extensions.AddIfNotAlready<RelativeFileLinkExtension>();
    return pipeline;
}
internal sealed class RelativeFileLinkExtension : IMarkdownExtension
{
    /// <inheritdoc/>
    public void Setup(MarkdownPipelineBuilder pipeline)
    {
        // Make sure we do not have a delegate twice
        pipeline.DocumentProcessed -= OnDocumentProcessed;
        pipeline.DocumentProcessed += OnDocumentProcessed;
    }

    /// <inheritdoc/>
    public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) { }

    private static void OnDocumentProcessed(MarkdownDocument document)
    {
        foreach (MarkdownObject node in document.Descendants())
        {
            if (node is not LinkInline link)
            {
                continue;
            }

            string? url = link.Url;
            if (string.IsNullOrEmpty(url))
            {
                continue;
            }

            const string oldExtension = "md";
            const string newExtension = "html";

            // we only want to modify relative paths linking to other .md files
            if (url.StartsWith('.') && url.EndsWith($".{oldExtension}", StringComparison.InvariantCultureIgnoreCase))
            {
                link.Url = string.Create(url.Length + (newExtension.Length - oldExtension.Length), url, static (chars, source) =>
                {
                    source.AsSpan()[..(source.Length - (newExtension.Length - oldExtension.Length))].CopyTo(chars);
                    newExtension.AsSpan().CopyTo(chars[^newExtension.Length..]);
                });
            }
        }
    }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the MarkdownPipelineBuilder extension point, DocumentProcessed event, and LinkInline handling shown in the issue. Compare the proposed RelativeFileLinkExtension with existing extension patterns and add coverage for relative Markdown links becoming HTML links. Done means the supported extension is integrated with the expected pipeline behavior and its link transformation is tested.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
tooling
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.