using Aspose.Words; using Aspose.Words.Loading; using Markdig; using System.Text; using System.Text.RegularExpressions; public static class WordExporter { private static readonly MarkdownPipeline MarkdownPipeline = new MarkdownPipelineBuilder() .UseAdvancedExtensions() .Build(); public static void MarkdownToWord(string markdown, string outputPath) { if (string.IsNullOrWhiteSpace(markdown)) throw new ArgumentException("markdown 不能为空", nameof(markdown)); // 清理 AI 常带的 ```markdown 和 ``` markdown = CleanMarkdown(markdown); // AI 返回内容有时会把表格压成一行,这里做一次轻量修复 markdown = NormalizeSingleLineTableMarkdown(markdown); // Markdown -> HTML,再由 Aspose 读取 HTML 保留格式 var htmlBody = Markdown.ToHtml(markdown, MarkdownPipeline); var htmlContent = BuildHtmlDocument(htmlBody); var htmlBytes = Encoding.UTF8.GetBytes(htmlContent); using var stream = new MemoryStream(htmlBytes); stream.Position = 0; var loadOptions = new LoadOptions { LoadFormat = LoadFormat.Html, Encoding = Encoding.UTF8 }; //判断路径是否存在 var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var doc = new Document(stream, loadOptions); doc.Save(outputPath, SaveFormat.Docx); } private static string CleanMarkdown(string input) { input = input.Trim(); if (input.StartsWith("```markdown", StringComparison.OrdinalIgnoreCase)) input = input.Substring("```markdown".Length); if (input.StartsWith("```")) input = input.Substring(3); if (input.EndsWith("```")) input = input.Substring(0, input.Length - 3); return input.Trim(); } private static string NormalizeSingleLineTableMarkdown(string markdown) { if (string.IsNullOrWhiteSpace(markdown)) return markdown; // 已经是多行内容则不处理 if (markdown.Contains('\n') || markdown.Contains('\r')) return markdown; // 仅在明显是表格时处理,避免误伤普通文本 if (!markdown.Contains("|") || !Regex.IsMatch(markdown, @"\|\s*[-:]{3,}")) return markdown; // 把单行中的“行结束 + 下一行开始”从 "| |" 规整为换行 var normalized = Regex.Replace(markdown, @"\|\s+\|", "|\n|"); return normalized; } private static string BuildHtmlDocument(string body) { return $@" {body} "; } }