16 Markdown双向转换 - ZeroHawkeye/wordZero GitHub Wiki

16-Markdown双向转换

WordZero提供了完整的Markdown和Word文档之间的双向转换功能,支持从Markdown生成专业的Word文档,也支持将Word文档反向导出为Markdown格式。

功能概览

🚀 Markdown → Word 转换

  • goldmark解析引擎: 基于CommonMark 0.31.2规范
  • 完整语法支持: 标题、格式化、列表、表格、图片、链接
  • 智能样式映射: 自动应用Word标准样式
  • 可配置选项: GitHub风味Markdown、脚注、错误处理

🔄 Word → Markdown 反向转换

  • 结构完整保持: 保持原文档的层次结构
  • 格式智能识别: 自动识别并转换文本格式
  • 图片导出支持: 提取图片并生成引用
  • 多种导出模式: GFM表格、Setext标题等选项

🔧 双向转换器

  • 统一接口: 自动检测文件类型并选择转换方向
  • 批量处理: 支持批量文件转换
  • 配置灵活: 独立配置两个转换方向

核心接口

Markdown转换器接口

type MarkdownConverter interface {
    // ConvertFile 转换单个文件
    ConvertFile(mdPath, docxPath string, options *ConvertOptions) error
    
    // ConvertBytes 转换字节数据
    ConvertBytes(mdContent []byte, options *ConvertOptions) (*document.Document, error)
    
    // ConvertString 转换字符串
    ConvertString(mdContent string, options *ConvertOptions) (*document.Document, error)
    
    // BatchConvert 批量转换
    BatchConvert(inputs []string, outputDir string, options *ConvertOptions) error
}

Word导出器接口

type WordToMarkdownExporter interface {
    // ExportToFile 导出Word文档到Markdown文件
    ExportToFile(docxPath, mdPath string, options *ExportOptions) error
    
    // ExportToString 导出Word文档到Markdown字符串
    ExportToString(doc *document.Document, options *ExportOptions) (string, error)
    
    // ExportToBytes 导出Word文档到Markdown字节数组
    ExportToBytes(doc *document.Document, options *ExportOptions) ([]byte, error)
    
    // BatchExport 批量导出
    BatchExport(inputs []string, outputDir string, options *ExportOptions) error
}

基本使用

1. Markdown → Word 转换

package main

import (
    "fmt"
    "github.com/ZeroHawkeye/wordZero/pkg/markdown"
)

func main() {
    // 创建转换器
    converter := markdown.NewConverter(markdown.DefaultOptions())
    
    // 方法1: 转换文件
    err := converter.ConvertFile("input.md", "output.docx", nil)
    if err != nil {
        fmt.Printf("转换失败: %v\n", err)
        return
    }
    
    // 方法2: 转换字符串
    markdownText := `# Hello World
    
这是一个**粗体**和*斜体*的示例。

- 列表项1
- 列表项2
`
    doc, err := converter.ConvertString(markdownText, nil)
    if err != nil {
        fmt.Printf("转换失败: %v\n", err)
        return
    }
    
    err = doc.Save("string_output.docx")
    if err != nil {
        fmt.Printf("保存失败: %v\n", err)
        return
    }
    
    fmt.Println("Markdown转换为Word成功!")
}

2. Word → Markdown 转换

package main

import (
    "fmt"
    "github.com/ZeroHawkeye/wordZero/pkg/markdown"
)

func main() {
    // 创建导出器
    exporter := markdown.NewExporter(markdown.DefaultExportOptions())
    
    // 方法1: 导出文件
    err := exporter.ExportToFile("document.docx", "output.md", nil)
    if err != nil {
        fmt.Printf("导出失败: %v\n", err)
        return
    }
    
    // 方法2: 导出为字符串
    doc, err := document.Open("document.docx")
    if err != nil {
        fmt.Printf("打开文档失败: %v\n", err)
        return
    }
    
    markdown, err := exporter.ExportToString(doc, nil)
    if err != nil {
        fmt.Printf("导出失败: %v\n", err)
        return
    }
    
    fmt.Printf("导出的Markdown内容:\n%s\n", markdown)
}

3. 双向转换器

package main

import (
    "fmt"
    "github.com/ZeroHawkeye/wordZero/pkg/markdown"
)

func main() {
    // 创建双向转换器
    converter := markdown.NewBidirectionalConverter(
        markdown.HighQualityOptions(),        // Markdown→Word选项
        markdown.HighQualityExportOptions(),  // Word→Markdown选项
    )
    
    // 自动检测文件类型并转换
    err := converter.AutoConvert("input.docx", "output.md")
    if err != nil {
        fmt.Printf("转换失败: %v\n", err)
        return
    }
    
    err = converter.AutoConvert("input.md", "output.docx")  
    if err != nil {
        fmt.Printf("转换失败: %v\n", err)
        return
    }
    
    fmt.Println("双向转换完成!")
}

配置选项

Markdown → Word 转换选项 (ConvertOptions)

type ConvertOptions struct {
    // 基础配置
    EnableGFM       bool  // 启用GitHub Flavored Markdown
    EnableFootnotes bool  // 启用脚注支持
    EnableTables    bool  // 启用表格支持
    EnableTaskList  bool  // 启用任务列表

    // 样式配置
    StyleMapping      map[string]string  // 自定义样式映射
    DefaultFontFamily string             // 默认字体
    DefaultFontSize   float64            // 默认字号

    // 图片处理
    ImageBasePath string   // 图片基础路径
    EmbedImages   bool     // 是否嵌入图片
    MaxImageWidth float64  // 最大图片宽度(英寸)

    // 链接处理
    PreserveLinkStyle  bool  // 保留链接样式
    ConvertToBookmarks bool  // 内部链接转书签

    // 文档设置
    GenerateTOC  bool                    // 生成目录
    TOCMaxLevel  int                     // 目录最大级别
    PageSettings *document.PageSettings  // 页面设置

    // 错误处理
    StrictMode    bool         // 严格模式
    IgnoreErrors  bool         // 忽略转换错误
    ErrorCallback func(error)  // 错误回调

    // 进度报告
    ProgressCallback func(int, int)  // 进度回调
}

预设配置

// 默认配置
opts := markdown.DefaultOptions()

// 高质量配置
opts := markdown.HighQualityOptions()

// 自定义配置
opts := &markdown.ConvertOptions{
    EnableGFM:         true,
    EnableFootnotes:   true,
    EnableTables:      true,
    DefaultFontFamily: "Microsoft YaHei",
    DefaultFontSize:   12.0,
    GenerateTOC:       true,
    TOCMaxLevel:       3,
    EmbedImages:       true,
    MaxImageWidth:     5.0,
}

Word → Markdown 导出选项 (ExportOptions)

type ExportOptions struct {
    // 表格处理
    UseGFMTables    bool    // 使用GitHub风味Markdown表格
    
    // 脚注处理
    PreserveFootnotes  bool  // 保留脚注
    
    // 文本格式化
    PreserveLineBreaks bool  // 保留换行符
    WrapLongLines      bool  // 自动换行
    MaxLineLength      int   // 最大行长度
    
    // 图片处理
    ExtractImages       bool    // 导出图片文件
    ImageOutputDir      string  // 图片输出目录
    ImageNamePattern    string  // 图片命名模式
    ImageRelativePath   bool    // 使用相对路径
    
    // 链接和书签
    PreserveBookmarks  bool  // 保留书签
    ConvertHyperlinks  bool  // 转换超链接
    
    // 代码块
    PreserveCodeStyle  bool    // 保留代码样式
    DefaultCodeLang    string  // 默认代码语言
    
    // 样式处理
    IgnoreUnknownStyles bool  // 忽略未知样式
    PreserveTOC         bool  // 保留目录
    
    // 元数据
    IncludeMetadata  bool  // 包含文档元数据
    StripComments    bool  // 删除注释
    
    // Markdown格式
    UseSetext         bool    // 使用Setext样式标题
    BulletListMarker  string  // 项目符号标记
    EmphasisMarker    string  // 强调标记
    
    // 错误处理
    StrictMode    bool           // 严格模式
    IgnoreErrors  bool           // 忽略错误
    ErrorCallback func(error)    // 错误回调
    
    // 进度报告
    ProgressCallback func(int, int)  // 进度回调
}

预设配置

// 默认导出配置
opts := markdown.DefaultExportOptions()

// 高质量导出配置
opts := markdown.HighQualityExportOptions()

// 自定义导出配置
opts := &markdown.ExportOptions{
    UseGFMTables:      true,
    ExtractImages:     true,
    ImageOutputDir:    "./images",
    PreserveFootnotes: true,
    IncludeMetadata:   true,
    UseSetext:         false,
    BulletListMarker:  "-",
    EmphasisMarker:    "*",
}

批量转换

批量Markdown转Word

converter := markdown.NewConverter(markdown.DefaultOptions())

inputs := []string{
    "doc1.md",
    "doc2.md", 
    "doc3.md",
}

options := &markdown.ConvertOptions{
    ProgressCallback: func(current, total int) {
        fmt.Printf("转换进度: %d/%d\n", current, total)
    },
    ErrorCallback: func(err error) {
        fmt.Printf("转换错误: %v\n", err)
    },
}

err := converter.BatchConvert(inputs, "output/", options)
if err != nil {
    fmt.Printf("批量转换失败: %v\n", err)
}

批量Word转Markdown

exporter := markdown.NewExporter(markdown.DefaultExportOptions())

inputs := []string{
    "doc1.docx",
    "doc2.docx",
    "doc3.docx", 
}

options := &markdown.ExportOptions{
    ExtractImages: true,
    ImageOutputDir: "extracted_images/",
    ProgressCallback: func(current, total int) {
        fmt.Printf("导出进度: %d/%d\n", current, total)
    },
}

err := exporter.BatchExport(inputs, "markdown/", options)
if err != nil {
    fmt.Printf("批量导出失败: %v\n", err)
}

支持的转换映射

Word → Markdown 映射

Word元素 Markdown语法 说明
Heading1 # 标题 一级标题
Heading2 ## 标题 二级标题
Heading3-6 ### 标题 三到六级标题
粗体 **粗体** 文本格式
斜体 *斜体* 文本格式
删除线 ~~删除线~~ 文本格式
行内代码 `代码` 代码格式
代码块 代码块 代码块
超链接 [链接文本](URL) 链接转换
图片 ![图片](路径) 图片引用
表格 | 表格 | GFM表格格式
无序列表 - 项目 列表项
有序列表 1. 项目 编号列表
引用块 > 引用内容 引用格式

Markdown → Word 映射

Markdown语法 Word实现 使用的API
# 标题 Heading1样式 AddHeadingParagraph()
## 标题 Heading2样式 AddHeadingParagraph()
**粗体** 粗体格式 RunProperties.Bold
*斜体* 斜体格式 RunProperties.Italic
`代码` 等宽字体 Courier New字体
[链接](url) 超链接 AddHyperlink()
![图片](src) 图片 AddImageFromFile()
| 表格 | Word表格 AddTable()
- 列表 项目符号 AddBulletList()
1. 列表 编号列表 AddNumberedList()
> 引用 引用样式 特殊段落格式

高级功能

图片处理

// Markdown转Word时的图片处理
opts := &markdown.ConvertOptions{
    ImageBasePath: "./images",     // 图片基础路径
    EmbedImages:   true,           // 嵌入图片到文档
    MaxImageWidth: 6.0,            // 最大宽度6英寸
}

// Word转Markdown时的图片导出
exportOpts := &markdown.ExportOptions{
    ExtractImages:     true,                    // 导出图片
    ImageOutputDir:    "./extracted_images",   // 图片输出目录
    ImageNamePattern:  "image_%d.png",        // 图片命名模式
    ImageRelativePath: true,                   // 使用相对路径
}

目录生成

opts := &markdown.ConvertOptions{
    GenerateTOC: true,   // 生成目录
    TOCMaxLevel: 3,      // 目录最大级别
}

// 在Markdown中使用[TOC]标记来指定目录位置
markdownContent := `# 文档标题

[TOC]

## 第一章
内容...

## 第二章  
内容...`

自定义样式映射

opts := &markdown.ConvertOptions{
    StyleMapping: map[string]string{
        "heading1": "Title",           // 自定义标题样式
        "heading2": "Subtitle",        // 自定义副标题样式
        "code":     "CodeStyle",       // 自定义代码样式
    },
    DefaultFontFamily: "Microsoft YaHei",  // 默认字体
    DefaultFontSize:   12.0,               // 默认字号
}

进度监控和错误处理

opts := &markdown.ConvertOptions{
    StrictMode:   true,                     // 严格模式
    IgnoreErrors: false,                    // 不忽略错误
    
    ProgressCallback: func(current, total int) {
        percentage := float64(current) / float64(total) * 100
        fmt.Printf("转换进度: %.1f%% (%d/%d)\n", percentage, current, total)
    },
    
    ErrorCallback: func(err error) {
        fmt.Printf("转换警告: %v\n", err)
    },
}

错误处理

错误类型

// 转换错误
type ConversionError struct {
    Type     string  // 错误类型
    Message  string  // 错误信息
    Line     int     // 行号
    Column   int     // 列号
    Original error   // 原始错误
}

// 导出错误
type ExportError struct {
    Type     string  // 错误类型
    Message  string  // 错误信息
    Original error   // 原始错误
}

错误处理示例

converter := markdown.NewConverter(markdown.DefaultOptions())

doc, err := converter.ConvertString(markdownContent, nil)
if err != nil {
    if convErr, ok := err.(*markdown.ConversionError); ok {
        fmt.Printf("转换错误: %s (第%d行, 第%d列): %s\n", 
            convErr.Type, convErr.Line, convErr.Column, convErr.Message)
    } else {
        fmt.Printf("未知错误: %v\n", err)
    }
    return
}

性能优化

批量处理优化

// 对于大量文件,使用批量处理
converter := markdown.NewConverter(markdown.DefaultOptions())

// 设置合理的并发数
opts := &markdown.ConvertOptions{
    IgnoreErrors: true,  // 忽略单个文件错误,继续处理其他文件
}

err := converter.BatchConvert(fileList, outputDir, opts)

内存使用优化

// 对于大文件,分段处理
func convertLargeMarkdown(filepath string) error {
    content, err := os.ReadFile(filepath)
    if err != nil {
        return err
    }
    
    // 如果文件过大,考虑分段处理
    if len(content) > 10*1024*1024 { // 10MB
        // 实现分段处理逻辑
        return convertInChunks(content)
    }
    
    // 正常处理
    converter := markdown.NewConverter(markdown.DefaultOptions())
    return converter.ConvertFile(filepath, "output.docx", nil)
}

兼容性说明

与现有API的兼容性

  • Markdown转换功能与现有的pkg/document包完全兼容
  • 不修改任何现有API接口
  • 可以与现有代码无缝集成
  • 支持所有现有的Word文档操作功能

Word功能支持

完全支持的功能

  • ✅ 基础文本格式(粗体、斜体、下划线)
  • ✅ 标题级别(H1-H6)
  • ✅ 列表(有序、无序)
  • ✅ 表格(基本格式)
  • ✅ 图片插入
  • ✅ 超链接
  • ✅ 代码块和行内代码

部分支持的功能

  • ⚠️ 复杂表格(跨行跨列)
  • ⚠️ 脚注和尾注
  • ⚠️ 书签和交叉引用
  • ⚠️ 复杂样式格式

不支持的功能

  • ❌ 数学公式
  • ❌ 图表和SmartArt
  • ❌ 页眉页脚(Markdown限制)
  • ❌ 分页符(Markdown限制)
  • ❌ 批注和修订

最佳实践

1. 选择合适的配置

// 基础文档转换
opts := markdown.DefaultOptions()

// 高质量文档(报告、技术文档)
opts := markdown.HighQualityOptions()

// 简单博客文章
opts := &markdown.ConvertOptions{
    EnableGFM:    true,
    EnableTables: true,
    EmbedImages:  false,  // 使用外部图片链接
}

2. 图片处理策略

// 内嵌图片(小文档)
opts := &markdown.ConvertOptions{
    EmbedImages:   true,
    MaxImageWidth: 6.0,
}

// 外部图片(大文档或网络发布)
opts := &markdown.ConvertOptions{
    EmbedImages:   false,
    ImageBasePath: "./images",
}

3. 错误处理策略

// 生产环境:严格模式
opts := &markdown.ConvertOptions{
    StrictMode:   true,
    IgnoreErrors: false,
    ErrorCallback: func(err error) {
        // 记录到日志系统
        log.Printf("转换错误: %v", err)
    },
}

// 开发环境:宽松模式
opts := &markdown.ConvertOptions{
    StrictMode:   false,
    IgnoreErrors: true,
}

示例项目

完整的示例代码可以在以下位置找到:

  • examples/markdown_demo/ - 基础Markdown功能演示
  • test/ - 单元测试和功能测试

未来计划

即将支持的功能

  • 数学公式支持(MathJax/KaTeX)
  • Mermaid图表转换
  • 更好的列表嵌套支持
  • 自定义样式映射配置文件