返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
Markdown

Resolve the issue where Markdig cannot recognize images with filenames containing spaces

Markdig can't even handle images with spaces in filenames? This library really hit a new low. I'll just fix it myself—adding a regex switch should do the trick. Also, gotta say, this framework is as primitive as a brick.

曦远 (DealiAxy)约 22 分钟
目录10 个章节

Preface

Yesterday, while publishing the article "Installing Linux on Ji-Ge 14x: A Hands-On Experience with Fedora 42",
(I was using the StarBlog Publisher tool to publish the article) I noticed that the webp images were not being uploaded automatically.

At first, I thought it might be due to an inability to recognize the webp format.

Regarding the StarBlog Publisher tool: It is a cross-platform Markdown article publishing tool for StarBlog. It features built-in intelligent assistants from various major AI models, supports writing and publishing in real-time, and offers intuitive content management to assist in efficient creation.

Project open-source address: https://github.com/star-blog/starblog-publisher

For more information, you can check out these articles:

Problem Resolution

After writing a few demo tests, I realized the issue was due to spaces in the file name. Markdig is very strict and does not support recognizing file names with spaces 😂. The solution was either to escape the file names when inserting images (in Typora) or to handle image parsing manually.

The images in the article are in the following format:

![](./2025-09-07-在鸡哥14x上安装使用Fedora42.assets/截图 2025-09-07 21-14-46.webp)

Later, I modified the method for analyzing images in starblog-publisher and made the following improvements:

  • Used the regular expression @"!\[([^\]]*)\]\(([^)]+)\)" to match image syntax.
  • Supported special characters in paths, such as spaces and Chinese characters.
  • Automatically handled paths enclosed in quotes and URL encoding.

Code

Let's get straight to the code.

First, take a look at the original image parsing code, which is entirely implemented using Markdig.

/// <summary>
/// Extracts all image paths from the Markdown content
/// </summary>
/// <returns>An array of image paths</returns>
public string[] ExtractImagePaths() {
    if (post.Content == null) {
        return Array.Empty<string>();
    }

    var document = Markdig.Markdown.Parse(post.Content);
    var imagePaths = new List<string>();
    var baseDir = Path.GetDirectoryName(filepath) ?? "";

    foreach (var node in document.AsEnumerable()) {
        if (node is not ParagraphBlock { Inline: { } } paragraphBlock) continue;
        foreach (var inline in paragraphBlock.Inline) {
            if (inline is not LinkInline { IsImage: true } linkInline) continue;
            if (string.IsNullOrWhiteSpace(linkInline.Url)) continue;

            var imgUrl = Uri.UnescapeDataString(linkInline.Url);

            // If it's a local image path, convert it to an absolute path
            if (!imgUrl.StartsWith("http")) {
                // Normalize the path
                imgUrl = imgUrl.Replace('/', Path.DirectorySeparatorChar) // Unify path separators
                    .Replace(".\\\\", "") // Remove relative path prefix
                    .Replace("./", ""); // Remove relative path prefix

                imgUrl = Path.GetFullPath(Path.Combine(baseDir, imgUrl));
                imagePaths.Add(imgUrl);
            }
        }
    }

    return imagePaths.ToArray();
}

Implementing Image Parsing Ourselves

But Markdig really struggles with this.

So I had to implement the parsing myself.

It's not difficult—you can just use regular expressions.

/// <summary>
/// Extract image paths with spaces (cases that Markdig cannot parse correctly)
/// </summary>
/// <param name="content">Markdown content</param>
/// <param name="baseDir">Base directory</param>
/// <returns>List of image paths</returns>
private List<string> ExtractImagePathsWithSpaces(string content, string baseDir) {
    var imagePaths = new List<string>();

    // Use regex to match image syntax: ![alt](path)
    // Supports paths with spaces, Chinese characters, etc.
    var imagePattern = @"!\[([^\]]*)\]\(([^)]+)\)";
    var matches = System.Text.RegularExpressions.Regex.Matches(content, imagePattern);

    foreach (System.Text.RegularExpressions.Match match in matches) {
        if (match.Groups.Count >= 3) {
            var imagePath = match.Groups[2].Value.Trim();

            // Remove possible quotes
            if ((imagePath.StartsWith('"') && imagePath.EndsWith('"')) ||
                (imagePath.StartsWith('\'') && imagePath.EndsWith('\''))) {
                imagePath = imagePath.Substring(1, imagePath.Length - 2);
            }

            // URL decoding
            imagePath = Uri.UnescapeDataString(imagePath);

            // Only process local paths
            if (!imagePath.StartsWith("http")) {
                // Normalize path
                imagePath = imagePath.Replace('/', Path.DirectorySeparatorChar)
                    .Replace(".\\\\", "")
                    .Replace("./", "");

                var fullPath = Path.GetFullPath(Path.Combine(baseDir, imagePath));
                imagePaths.Add(fullPath);
            }
        }
    }

    return imagePaths;
}

Supplementing the Original Method

Then, let's supplement the code for the original ExtractImagePaths method.

Change the bottom code to this:

// 添加自定义解析逻辑处理带空格的图片路径
// Markdig 无法正确解析带空格的图片路径,需要手动处理
var customPaths = ExtractImagePathsWithSpaces(post.Content, baseDir);
imagePaths.AddRange(customPaths);

// 去重并返回
return imagePaths.Distinct().ToArray();

Implementation Effect

After the problem was resolved, all images can now be properly recognized.

Previously, I implemented a gallery feature in starblog-publisher, which conveniently displays all the images contained within an article.

image-20250908122447207

Existing Issues

Using regular expressions is simple and direct, but sometimes it can be overly sensitive.

For example, the line of comment // 使用正则表达式匹配图片语法:![alt](path) posted in the code in this article would also be detected.

It's quite annoying, and the temporary solution is to make it a toggle, allowing users to decide whether to enable regex recognition.

It should only be enabled when Markdig fails to recognize it. Then, adding an option to ignore nonexistent images would resolve the issue.

Toggle

I added a toggle in the settings without hesitation.

<!-- 图片解析设置卡片 -->
<Border Classes="Card">
    <StackPanel Spacing="15" Margin="15">
        <StackPanel Orientation="Horizontal" Spacing="8">
            <i:Icon Value="fa-solid fa-image" Foreground="#FF9800" />
            <TextBlock Text="图片解析设置" FontWeight="Bold" FontSize="16" />
        </StackPanel>

        <StackPanel Spacing="10">
            <ToggleSwitch OnContent="启用正则识别" OffContent="仅使用标准识别"
                          IsChecked="{Binding EnableRegexImageParsing}" />
            <TextBlock Text="启用后将使用正则表达式额外识别带空格的图片路径,但可能会过度识别。建议仅在需要处理特殊路径时开启。" 
                       TextWrapping="Wrap" 
                       FontSize="12" 
                       Foreground="{DynamicResource SystemBaseMediumColor}" 
                       Margin="0,5,0,0" />
        </StackPanel>
    </StackPanel>
</Border>

The effect looks like this.

image-20250908124055845

When disabled, it recognizes the images in this text like this.

image-20250908124224250

When enabled, it looks like this. I've also added annotations for non-existent images.

image-20250908124158289

Skip non-existent

Add code in the MarkdownParse method of StarBlogPublisher/Services/MarkdownProcessor.cs

// Check if the file exists, skip non-existent images
if (!File.Exists(imgUrl)) {
    Console.WriteLine($"Skipping non-existent image file: {imgUrl}");
    continue;
}

Summary

Building a useful tool requires continuous iteration and optimization.

That said, I still have to complain a bit—Markdig feels like a bare-bones house 🤣

_EOF_

Resolve the issue where Markdig cannot recognize images with filenames containing spaces

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

Asp-Net-Core开发笔记:FrameworkDependent搭配docker部署

之前我写过一篇使用 docker 部署 AspNetCore 应用的文章,这种方式搭配 CICD 非常方便, build 之后 push 到私有的 dockerhub ,在生产服务器上 pull 下来镜像就可以直接运行了。 然而,有时需要一种更传统的部署方式,比如在本地打包可执行文件之后直接放到服务器上执行。 这种方式配置完成之后,每次更新只需要重新本地重新 publish 后把可执行文件上传

2023-09-08 · Asp-Net-Core开发笔记 · 约 1 分钟

买条新内存给台式机扩容,没想到出现玄学花屏

背景 我目前的配置是i5-8400,16G内存(两条威刚8G 2400) image-20221101101011261 然后在日常使用中,16G内存已经捉襟见肘了,无论是Android开发还是后端开发,每次编译都卡得很 正好双十一,就想着买条16G内存来扩容,组个32G的双通道。 某东看了一圈,2400的16G内存基本绝迹了,只能选择2666的,我想着主板会自动把2666降频到2400,问题应该

2022-11-07 · 2022 · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…