markdown-generator icon indicating copy to clipboard operation
markdown-generator copied to clipboard

How to implement a custom `MdSpan`

Open ChristopherHaws opened this issue 2 years ago • 2 comments

Hi there! I would like to implement a custom MdSpan but there are internal abstract methods on it so I am not able to and the implemented types are all sealed. How would I go about creating a custom span. The type of span I am trying to make is a MdShieldSpan which would be based on https://shields.io/

Thanks!

ChristopherHaws avatar Jan 07 '23 21:01 ChristopherHaws

FYI, I found a way to do this using the implicit operator, but would like to hear if there is a better way or not. Thanks!

public abstract class CustomMdSpan {
    public abstract MdSpan AsMdSpan();
    public static implicit operator MdSpan(CustomMdSpan x) => x.AsMdSpan();
}

public class MdShieldSpan : CustomMdSpan {
    private static readonly string baseUrl = "https://img.shields.io/";

    public MdShieldSpan(string label, string message, string color) {
        this.Label = label;
        this.Message = message;
        this.Color = color;
    }
    
    public string Label { get; set; }
    public string Message { get; set; }
    public string Color { get; set; }

    public override MdSpan AsMdSpan() {
        var url = new Url(baseUrl);
        url.AppendPathSegments("static", "v1");
        url.SetQueryParams(new {
            label = this.Label,
            message = this.Message,
            color = this.Color
        });

        return new MdImageSpan(
            description: this.Label,
            uri: url
        );
    }
}

public class MdShieldLinkSpan : MdShieldSpan {
    public MdShieldLinkSpan(
        string label,
        string message,
        string color,
        string linkUrl
    ) : base(label, message, color) {
        this.LinkUrl = linkUrl;
    }

    public string LinkUrl { get; set; }

    public override MdSpan AsMdSpan() {
        var imageSpan = base.AsMdSpan();
        
        return new MdLinkSpan(
            text: imageSpan,
            uri: this.LinkUrl
        );
    }
}

ChristopherHaws avatar Jan 07 '23 22:01 ChristopherHaws

Implementing a custom MdSpan outside the MarkdownGenerator assembly is not possible at the moment.

The core issue is that MdSpan uses the Visitor pattern which requires all possible types of MdSpan implementations to be handled in ISpanVisitor.

I'd generally be open to making this less restrictive, but it requires more changes than only making the internal abstract members accessible.

I think in the current state, your solution using implicit conversions is the best way to achieve your goal (other than including MdShieldSpan in MarkdownGenerator itself)

ap0llo avatar Jan 09 '23 22:01 ap0llo