You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在C#中为Markdig设置根目录以加载相对路径图片?

解决Markdig.Wpf渲染Markdown图片相对路径问题

要让Markdig识别项目根目录下的相对路径图片,你可以通过自定义图片渲染器修改图片路径,将相对路径转换为基于项目根目录的绝对路径,具体步骤如下:

1. 自定义ImageRenderer

创建继承自Markdig.Wpf.ImageRenderer的自定义渲染器,在渲染图片时替换相对路径为绝对路径:

public class CustomImageRenderer : Markdig.Wpf.ImageRenderer
{
    private readonly string _baseDirectory;

    public CustomImageRenderer(TextBlockRenderer renderer, string baseDirectory) : base(renderer)
    {
        _baseDirectory = baseDirectory;
    }

    protected override void Render(Markdig.Syntax.Inlines.LinkInline link)
    {
        if (link.IsImage)
        {
            var imagePath = link.Url;
            // 仅处理相对路径
            if (!Path.IsPathRooted(imagePath))
            {
                // 组合项目根目录与相对路径,生成绝对路径
                var absolutePath = Path.GetFullPath(Path.Combine(_baseDirectory, imagePath));
                // 转换为WPF可识别的Uri格式
                link.Url = new Uri(absolutePath).ToString();
            }
        }
        // 调用基类完成后续渲染
        base.Render(link);
    }
}

2. 修改Pipeline构建逻辑

修改BuildPipeline方法,传入项目根目录,并替换默认的图片渲染器为自定义实现:

private static Markdig.MarkdownPipeline BuildPipeline(string baseDirectory)
{
    var pipelineBuilder = new Markdig.MarkdownPipelineBuilder()
        .UseSupportedExtensions();

    var pipeline = pipelineBuilder.Build();

    // 找到WpfRenderer并替换ImageRenderer
    var wpfRenderer = pipeline.Renderers.Find<Markdig.Wpf.WpfRenderer>();
    if (wpfRenderer != null)
    {
        var defaultImageRenderer = wpfRenderer.ObjectRenderers.Find<Markdig.Wpf.ImageRenderer>();
        if (defaultImageRenderer != null)
        {
            wpfRenderer.ObjectRenderers.Remove(defaultImageRenderer);
        }
        wpfRenderer.ObjectRenderers.Add(new CustomImageRenderer(wpfRenderer.TextBlockRenderer, baseDirectory));
    }

    return pipeline;
}

3. 调用修改后的Pipeline

在加载Markdown时,将项目根目录传入BuildPipeline

private void OnReadmeLoaded(object sender, RoutedEventArgs e)
{
    var projectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\"));
    var readmePath = Path.Combine(projectDirectory, "README.md");

    if (File.Exists(readmePath))
    {
        var markdown = File.ReadAllText(readmePath);
        // 传入项目根目录构建Pipeline
        var xaml = Markdig.Wpf.Markdown.ToXaml(markdown, BuildPipeline(projectDirectory));
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml)))
        {
            using (var reader = new XamlXmlReader(stream, new MyXamlSchemaContext()))
            {
                if (XamlReader.Load(reader) is FlowDocument document)
                {
                    Viewer.Document = document;
                }
            }
        }
    }
    else
    {
        MessageBox.Show("Markdown file not found: " + readmePath);
    }
}

原理说明

Markdig.Wpf默认直接使用Markdown中的相对路径生成Image控件的Source,但WPF无法直接识别基于项目根目录的相对路径。自定义渲染器会在图片渲染前,将相对路径转换为绝对Uri,让WPF能够正确定位并加载图片文件。

内容的提问来源于stack exchange,提问作者Kenny Cason

火山引擎 最新活动