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() |
 |
图片 | 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图表转换
- 更好的列表嵌套支持
- 自定义样式映射配置文件