mirror of
https://github.com/ZeroHawkeye/wordZero.git
synced 2025-09-26 20:01:17 +08:00
更新文档和md操作示例
This commit is contained in:
@@ -1,797 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ZeroHawkeye/wordZero/pkg/document"
|
||||
)
|
||||
|
||||
// createSampleImage 创建一个示例图片
|
||||
func createSampleImage(width, height int, bgColor color.RGBA, text string) []byte {
|
||||
img := image.NewRGBA(image.Rect(0, 0, width, height))
|
||||
|
||||
// 填充背景色
|
||||
for y := 0; y < height; y++ {
|
||||
for x := 0; x < width; x++ {
|
||||
img.Set(x, y, bgColor)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加一个简单的边框
|
||||
borderColor := color.RGBA{255 - bgColor.R, 255 - bgColor.G, 255 - bgColor.B, 255}
|
||||
for x := 0; x < width; x++ {
|
||||
img.Set(x, 0, borderColor)
|
||||
img.Set(x, height-1, borderColor)
|
||||
}
|
||||
for y := 0; y < height; y++ {
|
||||
img.Set(0, y, borderColor)
|
||||
img.Set(width-1, y, borderColor)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
png.Encode(&buf, img)
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// saveImageToFile 将图片数据保存为文件
|
||||
func saveImageToFile(imageData []byte, filePath string) error {
|
||||
// 确保目录存在
|
||||
dir := filepath.Dir(filePath)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return fmt.Errorf("创建目录失败: %v", err)
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建文件失败: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = file.Write(imageData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("写入文件失败: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addSectionTitle 添加带样式的章节标题
|
||||
func addSectionTitle(doc *document.Document, title string, level int) {
|
||||
doc.AddParagraph("")
|
||||
para := doc.AddParagraph("")
|
||||
if level == 1 {
|
||||
para.AddFormattedText(title, &document.TextFormat{
|
||||
Bold: true,
|
||||
FontSize: 16,
|
||||
FontColor: "0066CC",
|
||||
})
|
||||
} else {
|
||||
para.AddFormattedText(title, &document.TextFormat{
|
||||
Bold: true,
|
||||
FontSize: 14,
|
||||
FontColor: "333333",
|
||||
})
|
||||
}
|
||||
doc.AddParagraph("")
|
||||
}
|
||||
|
||||
// addDescription 添加功能描述
|
||||
func addDescription(doc *document.Document, description string) {
|
||||
para := doc.AddParagraph("")
|
||||
para.AddFormattedText(description, &document.TextFormat{
|
||||
FontSize: 11,
|
||||
FontColor: "666666",
|
||||
Italic: true,
|
||||
})
|
||||
doc.AddParagraph("")
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("=== WordZero 高级图片功能演示 ===")
|
||||
|
||||
// 创建新文档
|
||||
doc := document.New()
|
||||
|
||||
// 添加文档标题
|
||||
titlePara := doc.AddParagraph("")
|
||||
titlePara.AddFormattedText("WordZero 图片功能完整演示", &document.TextFormat{
|
||||
Bold: true,
|
||||
FontSize: 20,
|
||||
FontColor: "000080",
|
||||
})
|
||||
doc.AddParagraph("")
|
||||
descPara := doc.AddParagraph("")
|
||||
descPara.AddFormattedText("本文档演示了WordZero图片处理的各种功能,包括图片位置、大小调整、文字环绕等特性。", &document.TextFormat{
|
||||
FontSize: 12,
|
||||
FontColor: "444444",
|
||||
})
|
||||
doc.AddParagraph("")
|
||||
|
||||
// 确保输出目录存在
|
||||
outputDir := "examples/output"
|
||||
imagesDir := outputDir + "/images"
|
||||
if err := os.MkdirAll(imagesDir, 0755); err != nil {
|
||||
log.Fatalf("创建输出目录失败: %v", err)
|
||||
}
|
||||
|
||||
// ==================== 第一部分:基础图片插入 ====================
|
||||
addSectionTitle(doc, "1. 基础图片插入功能", 1)
|
||||
addDescription(doc, "演示基本的图片插入功能,包括从数据和文件两种方式添加图片。")
|
||||
|
||||
fmt.Println("1. 基础图片插入功能演示...")
|
||||
|
||||
// 创建一个蓝色的示例图片
|
||||
basicImageData := createSampleImage(200, 120, color.RGBA{100, 150, 255, 255}, "基础图片")
|
||||
basicImagePath := filepath.Join(imagesDir, "basic_image.png")
|
||||
if err := saveImageToFile(basicImageData, basicImagePath); err != nil {
|
||||
log.Fatalf("保存基础图片失败: %v", err)
|
||||
}
|
||||
|
||||
basicImageInfo, err := doc.AddImageFromData(
|
||||
basicImageData,
|
||||
"basic_image.png",
|
||||
document.ImageFormatPNG,
|
||||
200,
|
||||
120,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 50.0, // 50毫米宽度
|
||||
Height: 30.0, // 30毫米高度
|
||||
},
|
||||
AltText: "基础演示图片",
|
||||
Title: "这是一个基础的图片插入示例",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加基础图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加基础图片成功,ID: %s\n", basicImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("上面是一个基础的图片插入示例。图片默认以嵌入式(inline)方式显示,会跟随文本流动。")
|
||||
|
||||
// ==================== 第二部分:图片位置控制 ====================
|
||||
addSectionTitle(doc, "2. 图片位置控制功能", 1)
|
||||
addDescription(doc, "演示不同的图片位置选项:嵌入式、左浮动、右浮动等。")
|
||||
|
||||
fmt.Println("2. 图片位置控制功能演示...")
|
||||
|
||||
// 2.1 嵌入式图片(默认)
|
||||
addSectionTitle(doc, "2.1 嵌入式图片(默认位置)", 2)
|
||||
doc.AddParagraph("嵌入式图片会跟随文本流,在文档中的固定位置显示,不会影响周围文本的布局。")
|
||||
|
||||
inlineImageData := createSampleImage(180, 100, color.RGBA{255, 100, 100, 255}, "嵌入式")
|
||||
inlineImagePath := filepath.Join(imagesDir, "inline_image.png")
|
||||
if err := saveImageToFile(inlineImageData, inlineImagePath); err != nil {
|
||||
log.Fatalf("保存嵌入式图片失败: %v", err)
|
||||
}
|
||||
|
||||
inlineImageInfo, err := doc.AddImageFromData(
|
||||
inlineImageData,
|
||||
"inline_image.png",
|
||||
document.ImageFormatPNG,
|
||||
180,
|
||||
100,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 45.0,
|
||||
Height: 25.0,
|
||||
},
|
||||
Position: document.ImagePositionInline,
|
||||
WrapText: document.ImageWrapNone,
|
||||
AltText: "嵌入式图片",
|
||||
Title: "嵌入式图片示例",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加嵌入式图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加嵌入式图片成功,ID: %s\n", inlineImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("这段文字紧跟在嵌入式图片后面。嵌入式图片不会让文字环绕,而是按照正常的文档流进行排列。")
|
||||
|
||||
// 2.2 左浮动图片
|
||||
addSectionTitle(doc, "2.2 左浮动图片", 2)
|
||||
doc.AddParagraph("左浮动图片会显示在页面左侧,右侧的文字可以环绕显示。")
|
||||
|
||||
leftFloatImageData := createSampleImage(150, 150, color.RGBA{100, 255, 100, 255}, "左浮动")
|
||||
leftFloatImagePath := filepath.Join(imagesDir, "left_float_image.png")
|
||||
if err := saveImageToFile(leftFloatImageData, leftFloatImagePath); err != nil {
|
||||
log.Fatalf("保存左浮动图片失败: %v", err)
|
||||
}
|
||||
|
||||
leftFloatImageInfo, err := doc.AddImageFromData(
|
||||
leftFloatImageData,
|
||||
"left_float_image.png",
|
||||
document.ImageFormatPNG,
|
||||
150,
|
||||
150,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 40.0,
|
||||
Height: 40.0,
|
||||
},
|
||||
Position: document.ImagePositionFloatLeft,
|
||||
WrapText: document.ImageWrapSquare,
|
||||
AltText: "左浮动图片",
|
||||
Title: "左浮动图片示例",
|
||||
OffsetX: 2.0, // 距离左边2毫米
|
||||
OffsetY: 0.0,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加左浮动图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加左浮动图片成功,ID: %s\n", leftFloatImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("这段文字演示了左浮动图片的效果。左浮动图片会靠左显示,而这段文字内容会在图片的右侧进行环绕显示。这种布局方式常用于杂志、报纸等出版物中,可以有效利用版面空间,让文档看起来更加美观和专业。左浮动图片适合在文章开头或段落中插入配图,不会打断阅读的连续性。")
|
||||
|
||||
// 2.3 右浮动图片
|
||||
addSectionTitle(doc, "2.3 右浮动图片", 2)
|
||||
doc.AddParagraph("右浮动图片会显示在页面右侧,左侧的文字可以环绕显示。")
|
||||
|
||||
rightFloatImageData := createSampleImage(160, 120, color.RGBA{255, 200, 100, 255}, "右浮动")
|
||||
rightFloatImagePath := filepath.Join(imagesDir, "right_float_image.png")
|
||||
if err := saveImageToFile(rightFloatImageData, rightFloatImagePath); err != nil {
|
||||
log.Fatalf("保存右浮动图片失败: %v", err)
|
||||
}
|
||||
|
||||
rightFloatImageInfo, err := doc.AddImageFromData(
|
||||
rightFloatImageData,
|
||||
"right_float_image.png",
|
||||
document.ImageFormatPNG,
|
||||
160,
|
||||
120,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 42.0,
|
||||
Height: 32.0,
|
||||
},
|
||||
Position: document.ImagePositionFloatRight,
|
||||
WrapText: document.ImageWrapSquare,
|
||||
AltText: "右浮动图片",
|
||||
Title: "右浮动图片示例",
|
||||
OffsetX: 2.0, // 距离右边2毫米
|
||||
OffsetY: 0.0,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加右浮动图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加右浮动图片成功,ID: %s\n", rightFloatImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("这段文字展示了右浮动图片的效果。右浮动图片会出现在页面的右侧,文字内容会从左侧开始环绕显示。这种布局方式特别适合在文档中插入说明性图片、图表或装饰性元素。右浮动布局可以让读者在阅读主要内容的同时,方便地查看相关的图片信息,提升文档的可读性和视觉效果。")
|
||||
|
||||
// ==================== 第三部分:文字环绕方式 ====================
|
||||
addSectionTitle(doc, "3. 文字环绕方式", 1)
|
||||
addDescription(doc, "演示不同的文字环绕模式:无环绕、四周环绕、紧密环绕、上下环绕等。")
|
||||
|
||||
fmt.Println("3. 文字环绕方式演示...")
|
||||
|
||||
// 3.1 无环绕
|
||||
addSectionTitle(doc, "3.1 无环绕模式", 2)
|
||||
doc.AddParagraph("无环绕模式下,文字不会环绕图片,图片会独占一行或一个段落。")
|
||||
|
||||
noWrapImageData := createSampleImage(140, 100, color.RGBA{200, 100, 255, 255}, "无环绕")
|
||||
noWrapImagePath := filepath.Join(imagesDir, "no_wrap_image.png")
|
||||
if err := saveImageToFile(noWrapImageData, noWrapImagePath); err != nil {
|
||||
log.Fatalf("保存无环绕图片失败: %v", err)
|
||||
}
|
||||
|
||||
noWrapImageInfo, err := doc.AddImageFromData(
|
||||
noWrapImageData,
|
||||
"no_wrap_image.png",
|
||||
document.ImageFormatPNG,
|
||||
140,
|
||||
100,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 35.0,
|
||||
Height: 25.0,
|
||||
},
|
||||
Position: document.ImagePositionInline,
|
||||
WrapText: document.ImageWrapNone,
|
||||
AltText: "无环绕图片",
|
||||
Title: "无环绕模式示例",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加无环绕图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加无环绕图片成功,ID: %s\n", noWrapImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("上面的图片使用了无环绕模式。在这种模式下,图片前后的文字会分别在图片的上方和下方显示,不会有文字出现在图片的左右两侧。")
|
||||
|
||||
// 3.2 四周环绕
|
||||
addSectionTitle(doc, "3.2 四周环绕模式", 2)
|
||||
doc.AddParagraph("四周环绕模式下,文字会在图片的四周进行环绕显示。")
|
||||
|
||||
squareWrapImageData := createSampleImage(130, 130, color.RGBA{100, 200, 255, 255}, "四周环绕")
|
||||
squareWrapImagePath := filepath.Join(imagesDir, "square_wrap_image.png")
|
||||
if err := saveImageToFile(squareWrapImageData, squareWrapImagePath); err != nil {
|
||||
log.Fatalf("保存四周环绕图片失败: %v", err)
|
||||
}
|
||||
|
||||
squareWrapImageInfo, err := doc.AddImageFromData(
|
||||
squareWrapImageData,
|
||||
"square_wrap_image.png",
|
||||
document.ImageFormatPNG,
|
||||
130,
|
||||
130,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 35.0,
|
||||
Height: 35.0,
|
||||
},
|
||||
Position: document.ImagePositionFloatLeft,
|
||||
WrapText: document.ImageWrapSquare,
|
||||
AltText: "四周环绕图片",
|
||||
Title: "四周环绕模式示例",
|
||||
OffsetX: 3.0,
|
||||
OffsetY: 0.0,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加四周环绕图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加四周环绕图片成功,ID: %s\n", squareWrapImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("这段文字演示了四周环绕的效果。四周环绕是最常用的文字环绕方式,文字会按照图片的矩形边界进行环绕,在图片周围形成整齐的文字布局。这种方式适合大多数文档场景,特别是在需要在正文中插入图片时。四周环绕模式可以保持文档的整洁性,同时有效利用版面空间,让图片和文字和谐地组合在一起。")
|
||||
|
||||
// 3.3 紧密环绕
|
||||
addSectionTitle(doc, "3.3 紧密环绕模式", 2)
|
||||
doc.AddParagraph("紧密环绕模式下,文字会更贴近图片的实际轮廓进行环绕。")
|
||||
|
||||
tightWrapImageData := createSampleImage(120, 140, color.RGBA{255, 150, 100, 255}, "紧密环绕")
|
||||
tightWrapImagePath := filepath.Join(imagesDir, "tight_wrap_image.png")
|
||||
if err := saveImageToFile(tightWrapImageData, tightWrapImagePath); err != nil {
|
||||
log.Fatalf("保存紧密环绕图片失败: %v", err)
|
||||
}
|
||||
|
||||
tightWrapImageInfo, err := doc.AddImageFromData(
|
||||
tightWrapImageData,
|
||||
"tight_wrap_image.png",
|
||||
document.ImageFormatPNG,
|
||||
120,
|
||||
140,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 32.0,
|
||||
Height: 37.0,
|
||||
},
|
||||
Position: document.ImagePositionFloatRight,
|
||||
WrapText: document.ImageWrapTight,
|
||||
AltText: "紧密环绕图片",
|
||||
Title: "紧密环绕模式示例",
|
||||
OffsetX: 2.0,
|
||||
OffsetY: 0.0,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加紧密环绕图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加紧密环绕图片成功,ID: %s\n", tightWrapImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("这段文字展示了紧密环绕模式的特点。与四周环绕不同,紧密环绕会让文字更贴近图片的实际边缘,可以获得更紧凑的布局效果。这种模式特别适合不规则形状的图片或者需要节省版面空间的场合。紧密环绕能够让文档看起来更加精致和专业,是高端出版物中常用的排版技巧。")
|
||||
|
||||
// 3.4 上下环绕
|
||||
addSectionTitle(doc, "3.4 上下环绕模式", 2)
|
||||
doc.AddParagraph("上下环绕模式下,文字只在图片的上方和下方显示,左右两侧留空。")
|
||||
|
||||
topBottomWrapImageData := createSampleImage(180, 80, color.RGBA{150, 255, 150, 255}, "上下环绕")
|
||||
topBottomWrapImagePath := filepath.Join(imagesDir, "top_bottom_wrap_image.png")
|
||||
if err := saveImageToFile(topBottomWrapImageData, topBottomWrapImagePath); err != nil {
|
||||
log.Fatalf("保存上下环绕图片失败: %v", err)
|
||||
}
|
||||
|
||||
topBottomWrapImageInfo, err := doc.AddImageFromData(
|
||||
topBottomWrapImageData,
|
||||
"top_bottom_wrap_image.png",
|
||||
document.ImageFormatPNG,
|
||||
180,
|
||||
80,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 48.0,
|
||||
Height: 21.0,
|
||||
},
|
||||
Position: document.ImagePositionInline,
|
||||
WrapText: document.ImageWrapTopAndBottom,
|
||||
AltText: "上下环绕图片",
|
||||
Title: "上下环绕模式示例",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加上下环绕图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加上下环绕图片成功,ID: %s\n", topBottomWrapImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("上面的图片演示了上下环绕模式。在这种模式下,图片的左右两侧不会有文字,所有文字内容都会在图片的上方和下方显示。这种布局方式适合横向较宽的图片,如图表、流程图、横幅等,可以让图片获得更好的展示效果。")
|
||||
|
||||
// ==================== 第四部分:图片大小调整 ====================
|
||||
addSectionTitle(doc, "4. 图片大小调整功能", 1)
|
||||
addDescription(doc, "演示各种图片大小调整选项:固定尺寸、保持比例、动态调整等。")
|
||||
|
||||
fmt.Println("4. 图片大小调整功能演示...")
|
||||
|
||||
// 4.1 固定尺寸
|
||||
addSectionTitle(doc, "4.1 固定尺寸设置", 2)
|
||||
doc.AddParagraph("可以为图片设置固定的宽度和高度,完全控制图片的显示尺寸。")
|
||||
|
||||
fixedSizeImageData := createSampleImage(200, 150, color.RGBA{255, 180, 200, 255}, "固定尺寸")
|
||||
fixedSizeImagePath := filepath.Join(imagesDir, "fixed_size_image.png")
|
||||
if err := saveImageToFile(fixedSizeImageData, fixedSizeImagePath); err != nil {
|
||||
log.Fatalf("保存固定尺寸图片失败: %v", err)
|
||||
}
|
||||
|
||||
fixedSizeImageInfo, err := doc.AddImageFromData(
|
||||
fixedSizeImageData,
|
||||
"fixed_size_image.png",
|
||||
document.ImageFormatPNG,
|
||||
200,
|
||||
150,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 60.0, // 固定宽度60毫米
|
||||
Height: 40.0, // 固定高度40毫米
|
||||
},
|
||||
AltText: "固定尺寸图片",
|
||||
Title: "固定尺寸设置示例",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加固定尺寸图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加固定尺寸图片成功,ID: %s,尺寸: 60x40毫米\n", fixedSizeImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("上面的图片被设置为固定尺寸60x40毫米。固定尺寸设置不考虑原始图片的长宽比,会严格按照指定的尺寸显示。")
|
||||
|
||||
// 4.2 保持长宽比
|
||||
addSectionTitle(doc, "4.2 保持长宽比缩放", 2)
|
||||
doc.AddParagraph("只设置宽度或高度,另一个维度自动计算以保持图片的原始长宽比。")
|
||||
|
||||
aspectRatioImageData := createSampleImage(300, 150, color.RGBA{180, 220, 255, 255}, "保持比例")
|
||||
aspectRatioImagePath := filepath.Join(imagesDir, "aspect_ratio_image.png")
|
||||
if err := saveImageToFile(aspectRatioImageData, aspectRatioImagePath); err != nil {
|
||||
log.Fatalf("保存长宽比图片失败: %v", err)
|
||||
}
|
||||
|
||||
aspectRatioImageInfo, err := doc.AddImageFromData(
|
||||
aspectRatioImageData,
|
||||
"aspect_ratio_image.png",
|
||||
document.ImageFormatPNG,
|
||||
300,
|
||||
150,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 70.0, // 只设置宽度70毫米
|
||||
KeepAspectRatio: true, // 保持长宽比
|
||||
},
|
||||
AltText: "保持长宽比图片",
|
||||
Title: "保持长宽比缩放示例",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加长宽比图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加长宽比图片成功,ID: %s,宽度: 70毫米(高度自动计算)\n", aspectRatioImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("上面的图片只设置了宽度为70毫米,高度根据原始长宽比自动计算。这样可以避免图片变形,保持图片的原始比例。")
|
||||
|
||||
// 4.3 动态调整大小
|
||||
addSectionTitle(doc, "4.3 动态调整图片大小", 2)
|
||||
doc.AddParagraph("演示在添加图片后动态调整其大小的功能。")
|
||||
|
||||
dynamicImageData := createSampleImage(160, 200, color.RGBA{200, 255, 180, 255}, "动态调整")
|
||||
dynamicImagePath := filepath.Join(imagesDir, "dynamic_image.png")
|
||||
if err := saveImageToFile(dynamicImageData, dynamicImagePath); err != nil {
|
||||
log.Fatalf("保存动态调整图片失败: %v", err)
|
||||
}
|
||||
|
||||
dynamicImageInfo, err := doc.AddImageFromData(
|
||||
dynamicImageData,
|
||||
"dynamic_image.png",
|
||||
document.ImageFormatPNG,
|
||||
160,
|
||||
200,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 30.0, // 初始宽度30毫米
|
||||
Height: 38.0, // 初始高度38毫米
|
||||
},
|
||||
AltText: "动态调整图片",
|
||||
Title: "动态调整大小示例",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加动态调整图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加动态调整图片成功,ID: %s,初始尺寸: 30x38毫米\n", dynamicImageInfo.ID)
|
||||
|
||||
// 动态调整图片大小
|
||||
newSize := &document.ImageSize{
|
||||
Width: 50.0, // 调整为50毫米宽度
|
||||
Height: 65.0, // 调整为65毫米高度
|
||||
}
|
||||
err = doc.ResizeImage(dynamicImageInfo, newSize)
|
||||
if err != nil {
|
||||
log.Fatalf("动态调整图片大小失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 图片大小已动态调整为50x65毫米\n")
|
||||
|
||||
doc.AddParagraph("上面的图片演示了动态大小调整。图片最初设置为30x38毫米,然后通过ResizeImage方法调整为50x65毫米。")
|
||||
|
||||
// ==================== 第五部分:图片属性设置 ====================
|
||||
addSectionTitle(doc, "5. 图片属性设置", 1)
|
||||
addDescription(doc, "演示图片的各种属性设置:替代文字、标题、偏移量等。")
|
||||
|
||||
fmt.Println("5. 图片属性设置演示...")
|
||||
|
||||
// 创建用于属性设置演示的图片
|
||||
propertiesImageData := createSampleImage(140, 110, color.RGBA{255, 220, 150, 255}, "属性设置")
|
||||
propertiesImagePath := filepath.Join(imagesDir, "properties_image.png")
|
||||
if err := saveImageToFile(propertiesImageData, propertiesImagePath); err != nil {
|
||||
log.Fatalf("保存属性设置图片失败: %v", err)
|
||||
}
|
||||
|
||||
propertiesImageInfo, err := doc.AddImageFromData(
|
||||
propertiesImageData,
|
||||
"properties_image.png",
|
||||
document.ImageFormatPNG,
|
||||
140,
|
||||
110,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 35.0,
|
||||
Height: 28.0,
|
||||
},
|
||||
Position: document.ImagePositionFloatRight,
|
||||
WrapText: document.ImageWrapSquare,
|
||||
OffsetX: 5.0, // 距离右边5毫米
|
||||
OffsetY: 2.0, // 向下偏移2毫米
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加属性设置图片失败: %v", err)
|
||||
}
|
||||
|
||||
// 设置图片属性
|
||||
err = doc.SetImageAltText(propertiesImageInfo, "这是一个用于演示属性设置的示例图片,包含了完整的可访问性信息")
|
||||
if err != nil {
|
||||
log.Fatalf("设置图片替代文字失败: %v", err)
|
||||
}
|
||||
|
||||
err = doc.SetImageTitle(propertiesImageInfo, "图片属性设置演示 - 包含标题、替代文字和位置偏移")
|
||||
if err != nil {
|
||||
log.Fatalf("设置图片标题失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf(" 添加属性设置图片成功,ID: %s\n", propertiesImageInfo.ID)
|
||||
fmt.Printf(" 设置了替代文字、标题和位置偏移\n")
|
||||
|
||||
doc.AddParagraph("这段文字旁边的图片演示了完整的属性设置功能。图片设置了详细的替代文字(Alt Text),这对于屏幕阅读器用户的可访问性非常重要。同时还设置了图片标题,提供了额外的描述信息。图片位置设置了偏移量,距离右边5毫米,向下偏移2毫米,可以实现精确的位置控制。这些属性设置让图片不仅在视觉上表现良好,在可访问性方面也符合现代文档的标准要求。")
|
||||
|
||||
// ==================== 第六部分:综合应用示例 ====================
|
||||
addSectionTitle(doc, "6. 综合应用示例", 1)
|
||||
addDescription(doc, "展示在实际文档中综合运用各种图片功能的效果。")
|
||||
|
||||
fmt.Println("6. 综合应用示例演示...")
|
||||
|
||||
doc.AddParagraph("以下是一个模拟真实文档的综合示例,展示了如何在一篇文档中合理运用各种图片功能:")
|
||||
|
||||
// 综合示例:创建多个不同用途的图片
|
||||
// 标题图片
|
||||
headerImageData := createSampleImage(400, 120, color.RGBA{70, 130, 200, 255}, "文档标题")
|
||||
headerImagePath := filepath.Join(imagesDir, "header_image.png")
|
||||
if err := saveImageToFile(headerImageData, headerImagePath); err != nil {
|
||||
log.Fatalf("保存标题图片失败: %v", err)
|
||||
}
|
||||
|
||||
headerImageInfo, err := doc.AddImageFromData(
|
||||
headerImageData,
|
||||
"header_image.png",
|
||||
document.ImageFormatPNG,
|
||||
400,
|
||||
120,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 100.0, // 100毫米宽度
|
||||
KeepAspectRatio: true,
|
||||
},
|
||||
Position: document.ImagePositionInline,
|
||||
WrapText: document.ImageWrapNone,
|
||||
AltText: "文档头部横幅图片",
|
||||
Title: "WordZero图片功能综合演示横幅",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加标题图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加文档横幅图片成功,ID: %s\n", headerImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("上方是文档的横幅图片,使用了嵌入式布局和保持长宽比的大小设置。")
|
||||
|
||||
// 左侧配图
|
||||
leftSideImageData := createSampleImage(120, 160, color.RGBA{150, 200, 100, 255}, "左侧配图")
|
||||
leftSideImagePath := filepath.Join(imagesDir, "left_side_image.png")
|
||||
if err := saveImageToFile(leftSideImageData, leftSideImagePath); err != nil {
|
||||
log.Fatalf("保存左侧配图失败: %v", err)
|
||||
}
|
||||
|
||||
leftSideImageInfo, err := doc.AddImageFromData(
|
||||
leftSideImageData,
|
||||
"left_side_image.png",
|
||||
document.ImageFormatPNG,
|
||||
120,
|
||||
160,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 30.0,
|
||||
Height: 40.0,
|
||||
},
|
||||
Position: document.ImagePositionFloatLeft,
|
||||
WrapText: document.ImageWrapTight,
|
||||
AltText: "文章左侧配图",
|
||||
Title: "左浮动紧密环绕配图示例",
|
||||
OffsetX: 1.0,
|
||||
OffsetY: 0.0,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加左侧配图失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加左侧配图成功,ID: %s\n", leftSideImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("这段文字展示了在实际文档中使用图片的效果。左侧的配图使用了左浮动和紧密环绕设置,文字会紧贴图片边缘环绕显示。这种布局在杂志、报告和营销材料中非常常见,可以有效提升文档的视觉吸引力和专业感。通过合理的图片布局,可以引导读者的视线,强调重要内容,同时让文档看起来更加生动有趣。")
|
||||
|
||||
// 右侧图表
|
||||
chartImageData := createSampleImage(180, 140, color.RGBA{255, 160, 160, 255}, "数据图表")
|
||||
chartImagePath := filepath.Join(imagesDir, "chart_image.png")
|
||||
if err := saveImageToFile(chartImageData, chartImagePath); err != nil {
|
||||
log.Fatalf("保存图表图片失败: %v", err)
|
||||
}
|
||||
|
||||
chartImageInfo, err := doc.AddImageFromData(
|
||||
chartImageData,
|
||||
"chart_image.png",
|
||||
document.ImageFormatPNG,
|
||||
180,
|
||||
140,
|
||||
&document.ImageConfig{
|
||||
Size: &document.ImageSize{
|
||||
Width: 45.0,
|
||||
Height: 35.0,
|
||||
},
|
||||
Position: document.ImagePositionFloatRight,
|
||||
WrapText: document.ImageWrapSquare,
|
||||
AltText: "数据分析图表",
|
||||
Title: "展示统计数据的图表",
|
||||
OffsetX: 3.0,
|
||||
OffsetY: 1.0,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("添加图表图片失败: %v", err)
|
||||
}
|
||||
fmt.Printf(" 添加右侧图表成功,ID: %s\n", chartImageInfo.ID)
|
||||
|
||||
doc.AddParagraph("右侧的图表展示了数据可视化的应用。在商业文档和技术报告中,图表是不可或缺的元素。通过右浮动和四周环绕的设置,图表可以与解释性文字完美结合,让数据更加清晰易懂。这种布局方式特别适合在分析报告、研究论文和业务提案中使用,可以有效传达复杂的信息内容。")
|
||||
|
||||
// ==================== 第七部分:功能总结 ====================
|
||||
addSectionTitle(doc, "7. 功能特性总结", 1)
|
||||
addDescription(doc, "总结WordZero图片功能的所有特性和应用场景。")
|
||||
|
||||
doc.AddParagraph("")
|
||||
featureTitlePara := doc.AddParagraph("")
|
||||
featureTitlePara.AddFormattedText("WordZero图片功能特性列表:", &document.TextFormat{
|
||||
Bold: true,
|
||||
FontSize: 12,
|
||||
})
|
||||
doc.AddParagraph("")
|
||||
|
||||
// 创建功能列表
|
||||
features := []string{
|
||||
"支持PNG、JPEG、GIF三种主流图片格式",
|
||||
"支持从文件和数据两种方式添加图片",
|
||||
"提供嵌入式、左浮动、右浮动三种位置选项",
|
||||
"支持无环绕、四周环绕、紧密环绕、上下环绕四种文字环绕模式",
|
||||
"可设置固定尺寸或保持长宽比的大小调整",
|
||||
"支持动态调整已添加图片的大小",
|
||||
"提供位置偏移量设置,实现精确位置控制",
|
||||
"包含完整的可访问性支持(替代文字、标题)",
|
||||
"所有图片数据自动嵌入到Word文档中",
|
||||
"兼容Microsoft Word和WPS Office",
|
||||
}
|
||||
|
||||
for _, feature := range features {
|
||||
featurePara := doc.AddParagraph("")
|
||||
featurePara.AddFormattedText(fmt.Sprintf("• %s", feature), &document.TextFormat{
|
||||
FontSize: 11,
|
||||
})
|
||||
}
|
||||
|
||||
doc.AddParagraph("")
|
||||
scenarioTitlePara := doc.AddParagraph("")
|
||||
scenarioTitlePara.AddFormattedText("应用场景:", &document.TextFormat{
|
||||
Bold: true,
|
||||
FontSize: 12,
|
||||
})
|
||||
doc.AddParagraph("")
|
||||
|
||||
scenarios := []string{
|
||||
"技术文档:插入流程图、架构图、截图等",
|
||||
"商业报告:添加图表、统计图、产品图片",
|
||||
"学术论文:插入实验图片、数据可视化图表",
|
||||
"营销材料:使用品牌图片、产品展示图",
|
||||
"用户手册:添加操作截图、示意图",
|
||||
"培训材料:插入教学图片、演示图表",
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
scenarioPara := doc.AddParagraph("")
|
||||
scenarioPara.AddFormattedText(fmt.Sprintf("• %s", scenario), &document.TextFormat{
|
||||
FontSize: 11,
|
||||
})
|
||||
}
|
||||
|
||||
// 添加结尾
|
||||
doc.AddParagraph("")
|
||||
endPara := doc.AddParagraph("")
|
||||
endPara.AddFormattedText("本演示文档展示了WordZero图片功能的完整特性。通过灵活运用这些功能,您可以创建出专业、美观的Word文档。", &document.TextFormat{
|
||||
FontSize: 12,
|
||||
FontColor: "666666",
|
||||
Italic: true,
|
||||
})
|
||||
|
||||
// 保存文档
|
||||
outputFile := outputDir + "/advanced_image_demo.docx"
|
||||
err = doc.Save(outputFile)
|
||||
if err != nil {
|
||||
log.Fatalf("保存文档失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("\n=== 高级图片功能演示完成 ===\n")
|
||||
fmt.Printf("文档已保存到: %s\n", outputFile)
|
||||
fmt.Printf("生成的图片文件保存在: %s\n", imagesDir)
|
||||
fmt.Printf("生成的图片文件包括:\n")
|
||||
|
||||
imageFiles := []string{
|
||||
"basic_image.png (基础图片,蓝色,200x120像素)",
|
||||
"inline_image.png (嵌入式图片,红色,180x100像素)",
|
||||
"left_float_image.png (左浮动图片,绿色,150x150像素)",
|
||||
"right_float_image.png (右浮动图片,橙色,160x120像素)",
|
||||
"no_wrap_image.png (无环绕图片,紫色,140x100像素)",
|
||||
"square_wrap_image.png (四周环绕图片,青色,130x130像素)",
|
||||
"tight_wrap_image.png (紧密环绕图片,橙红色,120x140像素)",
|
||||
"top_bottom_wrap_image.png (上下环绕图片,浅绿色,180x80像素)",
|
||||
"fixed_size_image.png (固定尺寸图片,粉色,200x150像素)",
|
||||
"aspect_ratio_image.png (长宽比图片,浅蓝色,300x150像素)",
|
||||
"dynamic_image.png (动态调整图片,浅绿色,160x200像素)",
|
||||
"properties_image.png (属性设置图片,浅黄色,140x110像素)",
|
||||
"header_image.png (横幅图片,蓝色,400x120像素)",
|
||||
"left_side_image.png (左侧配图,绿色,120x160像素)",
|
||||
"chart_image.png (图表图片,浅红色,180x140像素)",
|
||||
}
|
||||
|
||||
for i, file := range imageFiles {
|
||||
fmt.Printf(" %d. %s\n", i+1, file)
|
||||
}
|
||||
|
||||
fmt.Printf("\n功能演示统计:\n")
|
||||
fmt.Printf("- 演示的图片数量: 15张\n")
|
||||
fmt.Printf("- 覆盖的位置模式: 3种 (嵌入式、左浮动、右浮动)\n")
|
||||
fmt.Printf("- 覆盖的环绕模式: 4种 (无环绕、四周环绕、紧密环绕、上下环绕)\n")
|
||||
fmt.Printf("- 大小调整方式: 3种 (固定尺寸、保持比例、动态调整)\n")
|
||||
fmt.Printf("- 应用场景演示: 6个部分\n")
|
||||
fmt.Printf("- 文档章节: 7个主要部分\n")
|
||||
fmt.Printf("\n您可以用Microsoft Word或WPS Office打开查看完整效果\n")
|
||||
|
||||
fmt.Println("\n=== 所有图片功能演示已完成 ===")
|
||||
}
|
@@ -1,300 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ZeroHawkeye/wordZero/pkg/markdown"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("WordZero Markdown双向转换完整示例")
|
||||
fmt.Println("===================================")
|
||||
|
||||
// 确保输出目录存在
|
||||
outputDir := "examples/output"
|
||||
err := os.MkdirAll(outputDir, 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 创建输出目录失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 演示1: Markdown转Word
|
||||
demonstrateMarkdownToWord(outputDir)
|
||||
|
||||
// 演示2: Word转Markdown(反向转换)
|
||||
demonstrateWordToMarkdown(outputDir)
|
||||
|
||||
// 演示3: 双向转换器使用
|
||||
demonstrateBidirectionalConverter(outputDir)
|
||||
|
||||
// 演示4: 批量转换功能
|
||||
demonstrateBatchConversion(outputDir)
|
||||
|
||||
fmt.Println("\n🎉 所有转换示例运行完成!")
|
||||
}
|
||||
|
||||
// demonstrateMarkdownToWord 演示Markdown转Word功能
|
||||
func demonstrateMarkdownToWord(outputDir string) {
|
||||
fmt.Println("\n📝 演示1: Markdown → Word 转换")
|
||||
fmt.Println("================================")
|
||||
|
||||
// 创建示例Markdown内容
|
||||
markdownContent := `# WordZero Markdown双向转换功能
|
||||
|
||||
欢迎使用WordZero库的Markdown和Word文档双向转换功能!
|
||||
|
||||
## 功能特性概览
|
||||
|
||||
WordZero现在支持**完整的双向转换**:
|
||||
|
||||
### 🚀 Markdown → Word 转换
|
||||
- **goldmark解析引擎**: 基于CommonMark 0.31.2规范
|
||||
- **完整语法支持**: 标题、格式化、列表、表格、图片、链接
|
||||
- **智能样式映射**: 自动应用Word标准样式
|
||||
- **可配置选项**: GitHub风味Markdown、脚注、错误处理
|
||||
|
||||
### 🔄 Word → Markdown 反向转换
|
||||
- **结构完整保持**: 保持原文档的层次结构
|
||||
- **格式智能识别**: 自动识别并转换文本格式
|
||||
- **图片导出支持**: 提取图片并生成引用
|
||||
- **多种导出模式**: GFM表格、Setext标题等选项
|
||||
|
||||
### 文本格式化示例
|
||||
- **粗体文本**展示
|
||||
- *斜体文本*展示
|
||||
- ` + "`行内代码`" + `展示
|
||||
|
||||
### 列表支持示例
|
||||
|
||||
#### 无序列表
|
||||
- 功能A: 基础Markdown语法
|
||||
- 功能B: GitHub风味扩展
|
||||
- 功能C: 自定义配置选项
|
||||
|
||||
#### 有序列表
|
||||
1. 安装WordZero库
|
||||
2. 创建转换器实例
|
||||
3. 调用转换方法
|
||||
4. 处理转换结果
|
||||
|
||||
### 引用块示例
|
||||
|
||||
> 这是一个引用块示例,演示引用文本的转换效果。
|
||||
>
|
||||
> 引用块中可以包含多行内容,在Word中会以特殊格式显示。
|
||||
|
||||
### 代码块示例
|
||||
|
||||
` + "```" + `go
|
||||
// WordZero双向转换示例代码
|
||||
package main
|
||||
|
||||
import "github.com/ZeroHawkeye/wordZero/pkg/markdown"
|
||||
|
||||
func main() {
|
||||
// Markdown转Word
|
||||
converter := markdown.NewConverter(markdown.DefaultOptions())
|
||||
doc, _ := converter.ConvertString(markdownText, nil)
|
||||
doc.Save("output.docx")
|
||||
|
||||
// Word转Markdown
|
||||
exporter := markdown.NewExporter(markdown.DefaultExportOptions())
|
||||
exporter.ExportToFile("input.docx", "output.md", nil)
|
||||
}
|
||||
` + "```" + `
|
||||
|
||||
---
|
||||
|
||||
## 技术实现亮点
|
||||
|
||||
### 🔧 核心技术栈
|
||||
- **goldmark**: 高性能Markdown解析器
|
||||
- **WordZero**: 原生Go Word文档处理
|
||||
- **双向转换**: 无缝的格式转换支持
|
||||
|
||||
### 📋 支持的配置选项
|
||||
- ✅ GitHub Flavored Markdown扩展
|
||||
- ✅ 脚注和尾注支持
|
||||
- ✅ 表格格式转换(待完善)
|
||||
- ✅ 任务列表支持(待实现)
|
||||
- ✅ 图片处理和路径解析
|
||||
- ✅ 错误处理和进度报告
|
||||
|
||||
### 🎯 使用场景
|
||||
1. **技术文档转换**: 从Markdown快速生成Word文档
|
||||
2. **报告自动化**: 将Word报告转换为Markdown
|
||||
3. **版本控制友好**: Word文档转为可diff的Markdown
|
||||
4. **批量处理**: 大量文档的格式转换
|
||||
|
||||
## 总结
|
||||
|
||||
WordZero的双向转换功能为现代文档工作流提供了强大支持,
|
||||
无论是从轻量级的Markdown到专业的Word文档,
|
||||
还是反向的格式转换,都能满足不同场景的需求。`
|
||||
|
||||
// 创建转换器(使用高质量配置)
|
||||
opts := markdown.HighQualityOptions()
|
||||
opts.GenerateTOC = true
|
||||
opts.TOCMaxLevel = 3
|
||||
converter := markdown.NewConverter(opts)
|
||||
|
||||
fmt.Println("📝 正在转换Markdown内容...")
|
||||
|
||||
// 转换为Word文档
|
||||
doc, err := converter.ConvertString(markdownContent, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 转换失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 保存Word文档
|
||||
outputPath := outputDir + "/markdown_to_word_demo.docx"
|
||||
err = doc.Save(outputPath)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 保存文档失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("✅ Markdown转Word成功!输出: %s\n", outputPath)
|
||||
|
||||
// 同时保存Markdown源文件供后续演示使用
|
||||
markdownPath := outputDir + "/source_document.md"
|
||||
err = os.WriteFile(markdownPath, []byte(markdownContent), 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 保存Markdown文件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// demonstrateWordToMarkdown 演示Word转Markdown功能
|
||||
func demonstrateWordToMarkdown(outputDir string) {
|
||||
fmt.Println("\n📄 演示2: Word → Markdown 反向转换")
|
||||
fmt.Println("===================================")
|
||||
|
||||
// 使用上一步生成的Word文档
|
||||
wordPath := outputDir + "/markdown_to_word_demo.docx"
|
||||
markdownOutputPath := outputDir + "/word_to_markdown_result.md"
|
||||
|
||||
// 创建导出器(使用高质量配置)
|
||||
exportOpts := markdown.HighQualityExportOptions()
|
||||
exportOpts.ExtractImages = true
|
||||
exportOpts.ImageOutputDir = outputDir + "/extracted_images"
|
||||
exportOpts.UseGFMTables = true
|
||||
exportOpts.IncludeMetadata = true
|
||||
|
||||
exporter := markdown.NewExporter(exportOpts)
|
||||
|
||||
fmt.Println("📄 正在将Word文档转换为Markdown...")
|
||||
|
||||
// 执行反向转换
|
||||
err := exporter.ExportToFile(wordPath, markdownOutputPath, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ Word转Markdown失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("✅ Word转Markdown成功!输出: %s\n", markdownOutputPath)
|
||||
|
||||
// 显示转换结果预览
|
||||
content, err := os.ReadFile(markdownOutputPath)
|
||||
if err == nil && len(content) > 0 {
|
||||
preview := string(content)
|
||||
if len(preview) > 300 {
|
||||
preview = preview[:300] + "..."
|
||||
}
|
||||
fmt.Printf("📋 转换结果预览:\n%s\n", preview)
|
||||
}
|
||||
}
|
||||
|
||||
// demonstrateBidirectionalConverter 演示双向转换器
|
||||
func demonstrateBidirectionalConverter(outputDir string) {
|
||||
fmt.Println("\n🔄 演示3: 双向转换器统一接口")
|
||||
fmt.Println("===============================")
|
||||
|
||||
// 创建双向转换器
|
||||
converter := markdown.NewBidirectionalConverter(
|
||||
markdown.HighQualityOptions(),
|
||||
markdown.HighQualityExportOptions(),
|
||||
)
|
||||
|
||||
// 测试自动类型检测转换
|
||||
testCases := []struct {
|
||||
input string
|
||||
output string
|
||||
desc string
|
||||
}{
|
||||
{
|
||||
input: outputDir + "/source_document.md",
|
||||
output: outputDir + "/auto_converted.docx",
|
||||
desc: "Markdown自动转换为Word",
|
||||
},
|
||||
{
|
||||
input: outputDir + "/markdown_to_word_demo.docx",
|
||||
output: outputDir + "/auto_converted.md",
|
||||
desc: "Word自动转换为Markdown",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
fmt.Printf("🔄 测试%d: %s\n", i+1, tc.desc)
|
||||
|
||||
err := converter.AutoConvert(tc.input, tc.output)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 自动转换失败: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("✅ 自动转换成功: %s\n", tc.output)
|
||||
}
|
||||
}
|
||||
|
||||
// demonstrateBatchConversion 演示批量转换功能
|
||||
func demonstrateBatchConversion(outputDir string) {
|
||||
fmt.Println("\n📦 演示4: 批量转换功能")
|
||||
fmt.Println("=======================")
|
||||
|
||||
// 创建多个测试文件
|
||||
testMarkdownFiles := []string{
|
||||
outputDir + "/test1.md",
|
||||
outputDir + "/test2.md",
|
||||
outputDir + "/test3.md",
|
||||
}
|
||||
|
||||
testContents := []string{
|
||||
"# 测试文档1\n\n这是第一个测试文档。\n\n## 内容\n- 项目A\n- 项目B",
|
||||
"# 测试文档2\n\n这是第二个测试文档。\n\n> 引用内容示例",
|
||||
"# 测试文档3\n\n这是第三个测试文档。\n\n```go\nfmt.Println(\"Hello\")\n```",
|
||||
}
|
||||
|
||||
// 创建测试文件
|
||||
for i, content := range testContents {
|
||||
err := os.WriteFile(testMarkdownFiles[i], []byte(content), 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 创建测试文件失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 执行批量转换
|
||||
converter := markdown.NewConverter(markdown.DefaultOptions())
|
||||
batchOutputDir := outputDir + "/batch_output"
|
||||
|
||||
fmt.Println("📦 正在执行批量Markdown转Word...")
|
||||
|
||||
err := converter.BatchConvert(testMarkdownFiles, batchOutputDir, &markdown.ConvertOptions{
|
||||
ProgressCallback: func(current, total int) {
|
||||
fmt.Printf("📊 批量转换进度: %d/%d\n", current, total)
|
||||
},
|
||||
ErrorCallback: func(err error) {
|
||||
fmt.Printf("⚠️ 转换警告: %v\n", err)
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 批量转换失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("✅ 批量转换完成!输出目录: %s\n", batchOutputDir)
|
||||
}
|
@@ -8,67 +8,303 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 示例Markdown内容,包含表格和任务列表
|
||||
markdownContent := `# 表格和任务列表示例
|
||||
// 全面的Markdown内容示例,涵盖所有支持的功能
|
||||
markdownContent := `# WordZero Markdown 功能演示文档
|
||||
|
||||
## 表格示例
|
||||
这是一个全面展示 WordZero Markdown 转换功能的演示文档。
|
||||
|
||||
下面是一个简单的表格:
|
||||
## 1. 标题演示
|
||||
|
||||
| 姓名 | 年龄 | 城市 |
|
||||
|--------|------|--------|
|
||||
| 张三 | 25 | 北京 |
|
||||
| 李四 | 30 | 上海 |
|
||||
| 王五 | 28 | 广州 |
|
||||
### 1.1 标题级别测试
|
||||
|
||||
## 任务列表示例
|
||||
# 一级标题 (H1)
|
||||
## 二级标题 (H2)
|
||||
### 三级标题 (H3)
|
||||
#### 四级标题 (H4)
|
||||
##### 五级标题 (H5)
|
||||
###### 六级标题 (H6)
|
||||
|
||||
待办事项:
|
||||
## 2. 文本格式化
|
||||
|
||||
- [x] 完成项目需求分析
|
||||
- [ ] 设计系统架构
|
||||
- [ ] 实现核心功能
|
||||
- [x] 用户管理
|
||||
- [ ] 权限控制
|
||||
- [ ] 数据存储
|
||||
- [x] 编写测试用例
|
||||
- [ ] 部署到生产环境
|
||||
### 2.1 基础格式
|
||||
|
||||
## 混合内容
|
||||
这里有**粗体文本**和*斜体文本*。
|
||||
|
||||
这是一个包含**粗体**和*斜体*的段落。
|
||||
你也可以组合使用***粗斜体文本***。
|
||||
|
||||
### 对齐表格
|
||||
还支持行内代码 ` + "`var x = \"hello world\"`" + `。
|
||||
|
||||
| 左对齐 | 居中对齐 | 右对齐 |
|
||||
|:-------|:--------:|-------:|
|
||||
| 内容1 | 内容2 | 内容3 |
|
||||
| 较长内容 | 短内容 | 数字 |
|
||||
`
|
||||
### 2.2 链接演示
|
||||
|
||||
// 创建转换器
|
||||
这是一个[外部链接](https://github.com)的示例。
|
||||
|
||||
这是一个[WordZero项目链接](https://github.com/ZeroHawkeye/wordZero)。
|
||||
|
||||
## 3. 列表功能
|
||||
|
||||
### 3.1 无序列表
|
||||
|
||||
- 第一个项目
|
||||
- 第二个项目
|
||||
- 嵌套项目 1
|
||||
- 嵌套项目 2
|
||||
- 更深层嵌套
|
||||
- 第三个项目
|
||||
|
||||
### 3.2 有序列表
|
||||
|
||||
1. 步骤一:准备工作
|
||||
2. 步骤二:执行操作
|
||||
1. 子步骤 2.1
|
||||
2. 子步骤 2.2
|
||||
3. 步骤三:验证结果
|
||||
|
||||
### 3.3 任务列表(GitHub Flavored Markdown)
|
||||
|
||||
**项目待办事项清单:**
|
||||
|
||||
- [x] ✅ 完成项目需求分析
|
||||
- [x] ✅ 设计系统架构
|
||||
- [ ] ⏳ 实现核心功能
|
||||
- [x] ✅ 用户管理模块
|
||||
- [x] ✅ 文档处理模块
|
||||
- [ ] ⏳ 权限控制模块
|
||||
- [ ] ⏳ 数据存储模块
|
||||
- [x] ✅ 编写测试用例
|
||||
- [ ] ⏳ 部署到生产环境
|
||||
- [ ] ⏳ 编写用户文档
|
||||
|
||||
## 4. 表格功能
|
||||
|
||||
### 4.1 基础表格
|
||||
|
||||
| 功能特性 | 状态 | 优先级 | 备注 |
|
||||
|----------|------|--------|------|
|
||||
| 标题转换 | ✅ 完成 | 高 | 支持1-6级标题 |
|
||||
| 文本格式 | ✅ 完成 | 高 | 粗体、斜体、代码 |
|
||||
| 表格转换 | ✅ 完成 | 中 | 支持对齐方式 |
|
||||
| 任务列表 | ✅ 完成 | 中 | GFM扩展功能 |
|
||||
| 图片处理 | 🔄 开发中 | 低 | 基础支持 |
|
||||
|
||||
### 4.2 对齐方式表格
|
||||
|
||||
| 左对齐 | 居中对齐 | 右对齐 | 默认对齐 |
|
||||
|:-------|:--------:|-------:|----------|
|
||||
| 内容1 | 居中内容 | 右对齐内容 | 默认内容 |
|
||||
| 较长的内容文本 | 短内容 | 数字123 | 普通文本 |
|
||||
| Left | Center | Right | Normal |
|
||||
|
||||
### 4.3 复杂表格
|
||||
|
||||
| 序号 | 模块名称 | 实现状态 | 功能描述 | 测试覆盖率 |
|
||||
|------|----------|----------|----------|------------|
|
||||
| 1 | **核心解析器** | ✅ 已完成 | 基于goldmark的MD解析 | 95% |
|
||||
| 2 | **文本渲染** | ✅ 已完成 | 支持格式化文本输出 | 90% |
|
||||
| 3 | **表格处理** | ✅ 已完成 | *支持GFM表格规范* | 85% |
|
||||
| 4 | **列表渲染** | ✅ 已完成 | 包含任务列表支持 | 88% |
|
||||
| 5 | **图片处理** | 🔄 进行中 | 图片插入和路径处理 | 60% |
|
||||
|
||||
## 5. 代码块演示
|
||||
|
||||
### 5.1 内联代码
|
||||
|
||||
在Go语言中,你可以使用 ` + "`fmt.Println(\"Hello, World!\")`" + ` 来输出文本。
|
||||
|
||||
创建变量:` + "`var name string = \"WordZero\"`" + `
|
||||
|
||||
### 5.2 代码块
|
||||
|
||||
` + "```" + `go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ZeroHawkeye/wordZero/pkg/markdown"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建转换器
|
||||
converter := markdown.NewConverter(markdown.HighQualityOptions())
|
||||
|
||||
// 转换文档
|
||||
doc, err := converter.ConvertString(content, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 保存文档
|
||||
err = doc.Save("output.docx")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println("转换完成!")
|
||||
}
|
||||
` + "```" + `
|
||||
|
||||
` + "```" + `javascript
|
||||
// JavaScript示例
|
||||
function convertMarkdown(content) {
|
||||
const options = {
|
||||
enableGFM: true,
|
||||
enableTables: true,
|
||||
enableTaskList: true
|
||||
};
|
||||
|
||||
return markdownConverter.convert(content, options);
|
||||
}
|
||||
` + "```" + `
|
||||
|
||||
` + "```" + `json
|
||||
{
|
||||
"project": "WordZero",
|
||||
"version": "1.0.0",
|
||||
"features": [
|
||||
"markdown_conversion",
|
||||
"table_support",
|
||||
"task_lists",
|
||||
"gfm_support"
|
||||
],
|
||||
"status": "active"
|
||||
}
|
||||
` + "```" + `
|
||||
|
||||
## 6. 引用块
|
||||
|
||||
### 6.1 简单引用
|
||||
|
||||
> 这是一个简单的引用块示例。
|
||||
> 它可以包含多行内容。
|
||||
|
||||
### 6.2 嵌套引用
|
||||
|
||||
> 外层引用内容
|
||||
>
|
||||
> > 这是嵌套的引用内容
|
||||
> > 可以包含更深层的内容
|
||||
>
|
||||
> 回到外层引用
|
||||
|
||||
### 6.3 引用中的格式
|
||||
|
||||
> **重要提示:** 在使用WordZero时,请确保:
|
||||
>
|
||||
> - 使用 *最新版本* 的库
|
||||
> - 遵循 **官方文档** 的指导
|
||||
> - 测试你的 ` + "`代码实现`" + `
|
||||
|
||||
## 7. 分割线
|
||||
|
||||
下面是一条分割线:
|
||||
|
||||
---
|
||||
|
||||
上面和下面都有分割线。
|
||||
|
||||
***
|
||||
|
||||
### 8.2 网络图片
|
||||
|
||||

|
||||
|
||||
## 9. 混合内容示例
|
||||
|
||||
这个段落包含**多种格式**,包括*斜体*、` + "`代码`" + `和[链接](https://example.com)。
|
||||
|
||||
### 9.1 复杂列表混合
|
||||
|
||||
1. **第一步:环境准备**
|
||||
- 安装Go语言环境(版本 >= 1.19)
|
||||
- 克隆项目:` + "`git clone https://github.com/ZeroHawkeye/wordZero.git`" + `
|
||||
- 下载依赖:` + "`go mod download`" + `
|
||||
|
||||
2. **第二步:配置设置**
|
||||
` + "```" + `bash
|
||||
# 设置环境变量
|
||||
export WORDZERO_CONFIG=./config.json
|
||||
|
||||
# 运行测试
|
||||
go test ./...
|
||||
` + "```" + `
|
||||
|
||||
3. **第三步:运行示例**
|
||||
- [ ] 基础文档创建示例
|
||||
- [x] Markdown转换示例
|
||||
- [ ] 高级功能演示
|
||||
- [x] 表格和列表演示
|
||||
|
||||
## 10. 功能特性总结
|
||||
|
||||
| 分类 | 功能点 | Markdown语法 | Word输出 | 状态 |
|
||||
|------|--------|-------------|----------|------|
|
||||
| **标题** | 1-6级标题 | ` + "`# ## ### #### ##### ######`" + ` | Heading样式 | ✅ |
|
||||
| **格式** | 粗体 | ` + "`**text**`" + ` | Bold格式 | ✅ |
|
||||
| **格式** | 斜体 | ` + "`*text*`" + ` | Italic格式 | ✅ |
|
||||
| **格式** | 行内代码 | ` + "```text```" + ` | 等宽字体 | ✅ |
|
||||
| **链接** | 超链接 | ` + "`[text](url)`" + ` | 蓝色文本 | ✅ |
|
||||
| **列表** | 无序列表 | ` + "`- item`" + ` | 项目符号 | ✅ |
|
||||
| **列表** | 有序列表 | ` + "`1. item`" + ` | 编号列表 | ✅ |
|
||||
| **列表** | 任务列表 | ` + "`- [x] done`" + ` | 复选框 | ✅ |
|
||||
| **表格** | GFM表格 | ` + "`| cell |`" + ` | Word表格 | ✅ |
|
||||
| **代码** | 代码块 | ` + "```code```" + ` | 等宽字体块 | ✅ |
|
||||
| **引用** | 引用块 | ` + "`> quote`" + ` | 斜体格式 | ✅ |
|
||||
| **分割** | 分割线 | ` + "`---`" + ` | 横线 | ✅ |
|
||||
| **图片** | 图片引用 | ` + "``" + ` | 文本占位 | 🔄 |
|
||||
|
||||
---
|
||||
|
||||
**文档生成时间:** 2025年
|
||||
**功能完整性:** 核心功能100%实现
|
||||
|
||||
> 📝 **说明:** 这个文档展示了WordZero Markdown转换器的所有主要功能。
|
||||
> 所有标记为✅的功能都已完全实现并可正常使用。`
|
||||
|
||||
fmt.Println("🚀 开始创建全面的Markdown功能演示...")
|
||||
|
||||
// 创建高质量转换器配置
|
||||
opts := markdown.HighQualityOptions()
|
||||
opts.EnableTables = true
|
||||
opts.EnableTaskList = true
|
||||
opts.EnableGFM = true
|
||||
opts.EnableFootnotes = true
|
||||
opts.GenerateTOC = true
|
||||
opts.TOCMaxLevel = 3
|
||||
|
||||
converter := markdown.NewConverter(opts)
|
||||
|
||||
// 转换为Word文档
|
||||
doc, err := converter.ConvertString(markdownContent, opts)
|
||||
if err != nil {
|
||||
log.Fatalf("转换失败: %v", err)
|
||||
log.Fatalf("❌ 转换失败: %v", err)
|
||||
}
|
||||
|
||||
// 保存文档
|
||||
outputPath := "examples/output/table_and_tasklist_demo.docx"
|
||||
outputPath := "examples/output/comprehensive_markdown_demo.docx"
|
||||
err = doc.Save(outputPath)
|
||||
if err != nil {
|
||||
log.Fatalf("保存文档失败: %v", err)
|
||||
log.Fatalf("❌ 保存文档失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("✅ 表格和任务列表示例已保存到: %s\n", outputPath)
|
||||
fmt.Println("📝 示例包含以下功能:")
|
||||
fmt.Println(" • GFM表格转换为Word表格")
|
||||
fmt.Println(" • 任务列表复选框显示")
|
||||
fmt.Println(" • 表格对齐方式保持")
|
||||
fmt.Println(" • 混合格式文本支持")
|
||||
fmt.Printf("✅ 全面Markdown功能演示已保存到: %s\n", outputPath)
|
||||
fmt.Println("\n📋 演示包含以下功能特性:")
|
||||
fmt.Println(" 🔸 标题转换 (H1-H6)")
|
||||
fmt.Println(" 🔸 文本格式化 (粗体、斜体、行内代码)")
|
||||
fmt.Println(" 🔸 链接处理")
|
||||
fmt.Println(" 🔸 列表支持 (有序、无序、嵌套)")
|
||||
fmt.Println(" 🔸 任务列表 (GitHub Flavored Markdown)")
|
||||
fmt.Println(" 🔸 表格转换 (支持对齐方式)")
|
||||
fmt.Println(" 🔸 代码块 (多语言语法)")
|
||||
fmt.Println(" 🔸 引用块 (支持嵌套)")
|
||||
fmt.Println(" 🔸 分割线")
|
||||
fmt.Println(" 🔸 图片引用 (基础支持)")
|
||||
fmt.Println(" 🔸 混合内容处理")
|
||||
fmt.Println("\n🎯 配置选项:")
|
||||
fmt.Printf(" • GitHub Flavored Markdown: %v\n", opts.EnableGFM)
|
||||
fmt.Printf(" • 表格支持: %v\n", opts.EnableTables)
|
||||
fmt.Printf(" • 任务列表: %v\n", opts.EnableTaskList)
|
||||
fmt.Printf(" • 脚注支持: %v\n", opts.EnableFootnotes)
|
||||
fmt.Printf(" • 生成目录: %v\n", opts.GenerateTOC)
|
||||
fmt.Printf(" • 目录最大级别: %d\n", opts.TOCMaxLevel)
|
||||
fmt.Printf(" • 默认字体: %s\n", opts.DefaultFontFamily)
|
||||
fmt.Printf(" • 默认字号: %.1f\n", opts.DefaultFontSize)
|
||||
}
|
||||
|
306
examples/word_to_markdown_demo/word_to_markdown_demo.go
Normal file
306
examples/word_to_markdown_demo/word_to_markdown_demo.go
Normal file
@@ -0,0 +1,306 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ZeroHawkeye/wordZero/pkg/markdown"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("🔄 WordZero - Word转Markdown功能演示")
|
||||
fmt.Println("=====================================")
|
||||
|
||||
// 1. 准备输入和输出路径
|
||||
inputPath := "examples/output/comprehensive_markdown_demo.docx"
|
||||
outputDir := "examples/output"
|
||||
outputPath := filepath.Join(outputDir, "converted_from_word.md")
|
||||
imagesDir := filepath.Join(outputDir, "images")
|
||||
|
||||
// 检查输入文件是否存在
|
||||
if _, err := os.Stat(inputPath); os.IsNotExist(err) {
|
||||
fmt.Printf("⚠️ 输入文件不存在: %s\n", inputPath)
|
||||
fmt.Println("💡 请先运行 table_and_tasklist_demo.go 生成示例Word文档")
|
||||
return
|
||||
}
|
||||
|
||||
// 确保输出目录存在
|
||||
err := os.MkdirAll(outputDir, 0755)
|
||||
if err != nil {
|
||||
log.Fatalf("❌ 创建输出目录失败: %v", err)
|
||||
}
|
||||
|
||||
// 2. 演示基础Word转Markdown功能
|
||||
fmt.Println("\n📝 基础转换演示...")
|
||||
demonstrateBasicConversion(inputPath, outputPath)
|
||||
|
||||
// 3. 演示高质量转换配置
|
||||
fmt.Println("\n✨ 高质量转换演示...")
|
||||
demonstrateHighQualityConversion(inputPath, imagesDir)
|
||||
|
||||
// 4. 演示自定义配置转换
|
||||
fmt.Println("\n🔧 自定义配置演示...")
|
||||
demonstrateCustomConversion(inputPath, outputDir)
|
||||
|
||||
// 5. 演示双向转换器
|
||||
fmt.Println("\n🔄 双向转换演示...")
|
||||
demonstrateBidirectionalConversion(inputPath, outputDir)
|
||||
|
||||
// 6. 演示批量转换
|
||||
fmt.Println("\n📁 批量转换演示...")
|
||||
demonstrateBatchConversion(outputDir)
|
||||
|
||||
fmt.Println("\n🎉 所有Word转Markdown演示完成!")
|
||||
fmt.Println("📂 查看输出文件: " + outputDir)
|
||||
}
|
||||
|
||||
// demonstrateBasicConversion 演示基础转换功能
|
||||
func demonstrateBasicConversion(inputPath, outputPath string) {
|
||||
fmt.Printf(" 输入文件: %s\n", inputPath)
|
||||
fmt.Printf(" 输出文件: %s\n", outputPath)
|
||||
|
||||
// 使用默认配置创建导出器
|
||||
exporter := markdown.NewExporter(markdown.DefaultExportOptions())
|
||||
|
||||
// 执行转换
|
||||
err := exporter.ExportToFile(inputPath, outputPath, nil)
|
||||
if err != nil {
|
||||
fmt.Printf(" ❌ 转换失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(" ✅ 基础转换完成")
|
||||
|
||||
// 显示转换结果摘要
|
||||
showFileInfo(outputPath)
|
||||
}
|
||||
|
||||
// demonstrateHighQualityConversion 演示高质量转换
|
||||
func demonstrateHighQualityConversion(inputPath, imagesDir string) {
|
||||
outputPath := filepath.Join(filepath.Dir(imagesDir), "high_quality_conversion.md")
|
||||
|
||||
// 使用高质量配置
|
||||
options := markdown.HighQualityExportOptions()
|
||||
options.ImageOutputDir = imagesDir
|
||||
options.ExtractImages = true
|
||||
options.PreserveFootnotes = true
|
||||
options.PreserveTOC = true
|
||||
options.IncludeMetadata = true
|
||||
|
||||
// 添加进度回调
|
||||
options.ProgressCallback = func(current, total int) {
|
||||
fmt.Printf(" 📊 转换进度: %d/%d (%.1f%%)\n", current, total, float64(current)/float64(total)*100)
|
||||
}
|
||||
|
||||
fmt.Printf(" 输入文件: %s\n", inputPath)
|
||||
fmt.Printf(" 输出文件: %s\n", outputPath)
|
||||
fmt.Printf(" 图片目录: %s\n", imagesDir)
|
||||
|
||||
exporter := markdown.NewExporter(options)
|
||||
err := exporter.ExportToFile(inputPath, outputPath, nil)
|
||||
if err != nil {
|
||||
fmt.Printf(" ❌ 高质量转换失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(" ✅ 高质量转换完成")
|
||||
showFileInfo(outputPath)
|
||||
}
|
||||
|
||||
// demonstrateCustomConversion 演示自定义配置转换
|
||||
func demonstrateCustomConversion(inputPath, outputDir string) {
|
||||
outputPath := filepath.Join(outputDir, "custom_conversion.md")
|
||||
|
||||
// 创建自定义配置
|
||||
options := &markdown.ExportOptions{
|
||||
// 表格和格式
|
||||
UseGFMTables: true,
|
||||
PreserveFootnotes: true,
|
||||
PreserveLineBreaks: false,
|
||||
WrapLongLines: true,
|
||||
MaxLineLength: 80,
|
||||
|
||||
// 图片处理
|
||||
ExtractImages: false, // 不导出图片文件
|
||||
ImageRelativePath: true,
|
||||
|
||||
// 链接处理
|
||||
PreserveBookmarks: true,
|
||||
ConvertHyperlinks: true,
|
||||
|
||||
// 代码处理
|
||||
PreserveCodeStyle: true,
|
||||
DefaultCodeLang: "text",
|
||||
|
||||
// 内容处理
|
||||
PreserveTOC: false,
|
||||
IncludeMetadata: true,
|
||||
StripComments: true,
|
||||
|
||||
// 格式化选项
|
||||
UseSetext: false, // 使用ATX样式标题
|
||||
BulletListMarker: "*", // 使用*作为项目符号
|
||||
EmphasisMarker: "_", // 使用_表示斜体
|
||||
|
||||
// 错误处理
|
||||
StrictMode: true,
|
||||
IgnoreErrors: false,
|
||||
ErrorCallback: func(err error) {
|
||||
fmt.Printf(" ⚠️ 转换警告: %v\n", err)
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf(" 输入文件: %s\n", inputPath)
|
||||
fmt.Printf(" 输出文件: %s\n", outputPath)
|
||||
fmt.Println(" 配置特点:")
|
||||
fmt.Printf(" • GFM表格: %v\n", options.UseGFMTables)
|
||||
fmt.Printf(" • 最大行长: %d字符\n", options.MaxLineLength)
|
||||
fmt.Printf(" • 项目符号: %s\n", options.BulletListMarker)
|
||||
fmt.Printf(" • 强调符号: %s\n", options.EmphasisMarker)
|
||||
|
||||
exporter := markdown.NewExporter(options)
|
||||
err := exporter.ExportToFile(inputPath, outputPath, nil)
|
||||
if err != nil {
|
||||
fmt.Printf(" ❌ 自定义转换失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(" ✅ 自定义转换完成")
|
||||
showFileInfo(outputPath)
|
||||
}
|
||||
|
||||
// demonstrateBidirectionalConversion 演示双向转换器
|
||||
func demonstrateBidirectionalConversion(inputPath, outputDir string) {
|
||||
// 创建双向转换器
|
||||
converter := markdown.NewBidirectionalConverter(
|
||||
markdown.HighQualityOptions(), // Markdown→Word选项
|
||||
markdown.HighQualityExportOptions(), // Word→Markdown选项
|
||||
)
|
||||
|
||||
// 测试Word→Markdown
|
||||
mdPath := filepath.Join(outputDir, "bidirectional_word_to_md.md")
|
||||
fmt.Printf(" Word→Markdown: %s → %s\n", inputPath, mdPath)
|
||||
|
||||
err := converter.AutoConvert(inputPath, mdPath)
|
||||
if err != nil {
|
||||
fmt.Printf(" ❌ Word→Markdown失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(" ✅ Word→Markdown完成")
|
||||
|
||||
// 测试Markdown→Word (往回转换)
|
||||
docxPath := filepath.Join(outputDir, "bidirectional_md_to_word.docx")
|
||||
fmt.Printf(" Markdown→Word: %s → %s\n", mdPath, docxPath)
|
||||
|
||||
err = converter.AutoConvert(mdPath, docxPath)
|
||||
if err != nil {
|
||||
fmt.Printf(" ❌ Markdown→Word失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(" ✅ Markdown→Word完成")
|
||||
|
||||
showFileInfo(mdPath)
|
||||
showFileInfo(docxPath)
|
||||
}
|
||||
|
||||
// demonstrateBatchConversion 演示批量转换
|
||||
func demonstrateBatchConversion(outputDir string) {
|
||||
// 准备批量转换的输入文件
|
||||
inputFiles := []string{
|
||||
"examples/output/comprehensive_markdown_demo.docx",
|
||||
}
|
||||
|
||||
// 检查是否有其他可用的docx文件
|
||||
files, err := filepath.Glob(filepath.Join(outputDir, "*.docx"))
|
||||
if err == nil {
|
||||
for _, file := range files {
|
||||
if !contains(inputFiles, file) {
|
||||
inputFiles = append(inputFiles, file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(inputFiles) == 0 {
|
||||
fmt.Println(" ⚠️ 没有找到可用于批量转换的Word文档")
|
||||
return
|
||||
}
|
||||
|
||||
batchOutputDir := filepath.Join(outputDir, "batch_converted")
|
||||
fmt.Printf(" 输入文件数量: %d\n", len(inputFiles))
|
||||
fmt.Printf(" 输出目录: %s\n", batchOutputDir)
|
||||
|
||||
// 配置批量转换选项
|
||||
options := markdown.DefaultExportOptions()
|
||||
options.ProgressCallback = func(current, total int) {
|
||||
fmt.Printf(" 📊 批量转换进度: %d/%d\n", current, total)
|
||||
}
|
||||
options.ErrorCallback = func(err error) {
|
||||
fmt.Printf(" ⚠️ 转换错误: %v\n", err)
|
||||
}
|
||||
|
||||
// 执行批量转换
|
||||
exporter := markdown.NewExporter(options)
|
||||
err = exporter.BatchExport(inputFiles, batchOutputDir, options)
|
||||
if err != nil {
|
||||
fmt.Printf(" ❌ 批量转换失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(" ✅ 批量转换完成")
|
||||
|
||||
// 显示转换结果
|
||||
convertedFiles, _ := filepath.Glob(filepath.Join(batchOutputDir, "*.md"))
|
||||
fmt.Printf(" 📄 成功转换 %d 个文件\n", len(convertedFiles))
|
||||
for _, file := range convertedFiles {
|
||||
fmt.Printf(" • %s\n", filepath.Base(file))
|
||||
}
|
||||
}
|
||||
|
||||
// showFileInfo 显示文件信息
|
||||
func showFileInfo(filePath string) {
|
||||
info, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
fmt.Printf(" 📄 文件信息获取失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 读取文件内容获取行数
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
fmt.Printf(" 📄 %s (大小: %d 字节)\n", filepath.Base(filePath), info.Size())
|
||||
return
|
||||
}
|
||||
|
||||
lines := len(strings.Split(string(content), "\n"))
|
||||
fmt.Printf(" 📄 %s (大小: %d 字节, %d 行)\n", filepath.Base(filePath), info.Size(), lines)
|
||||
|
||||
// 显示前几行内容预览
|
||||
preview := strings.Split(string(content), "\n")
|
||||
maxPreview := 3
|
||||
if len(preview) > maxPreview {
|
||||
fmt.Println(" 📋 内容预览:")
|
||||
for i := 0; i < maxPreview && i < len(preview); i++ {
|
||||
line := preview[i]
|
||||
if len(line) > 60 {
|
||||
line = line[:57] + "..."
|
||||
}
|
||||
fmt.Printf(" %s\n", line)
|
||||
}
|
||||
if len(preview) > maxPreview {
|
||||
fmt.Printf(" ... (还有 %d 行)\n", len(preview)-maxPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// contains 检查切片是否包含指定元素
|
||||
func contains(slice []string, item string) bool {
|
||||
for _, s := range slice {
|
||||
if s == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@@ -967,6 +967,191 @@ options.StyleMapping = map[string]string{
|
||||
converter := markdown.NewConverter(options)
|
||||
```
|
||||
|
||||
## Word转Markdown功能 ✨ **新增功能**
|
||||
|
||||
WordZero现在支持将Word文档反向转换为Markdown格式,提供完整的双向转换能力。
|
||||
|
||||
### Word导出器API
|
||||
|
||||
#### 导出器接口
|
||||
- [`NewExporter(options *ExportOptions)`](../markdown/exporter.go) - 创建新的Word导出器
|
||||
- [`DefaultExportOptions()`](../markdown/exporter.go) - 获取默认导出选项
|
||||
- [`HighQualityExportOptions()`](../markdown/exporter.go) - 获取高质量导出选项
|
||||
|
||||
#### 导出方法
|
||||
- [`ExportToFile(docxPath, mdPath string, options *ExportOptions)`](../markdown/exporter.go) - 导出Word文档到Markdown文件
|
||||
- [`ExportToString(doc *Document, options *ExportOptions)`](../markdown/exporter.go) - 导出Word文档到Markdown字符串
|
||||
- [`ExportToBytes(doc *Document, options *ExportOptions)`](../markdown/exporter.go) - 导出Word文档到Markdown字节数组
|
||||
- [`BatchExport(inputs []string, outputDir string, options *ExportOptions)`](../markdown/exporter.go) - 批量导出Word文档
|
||||
|
||||
#### 导出配置选项 (`ExportOptions`)
|
||||
- `UseGFMTables` - 使用GitHub风味Markdown表格
|
||||
- `PreserveFootnotes` - 保留脚注
|
||||
- `PreserveLineBreaks` - 保留换行符
|
||||
- `WrapLongLines` - 自动换行
|
||||
- `MaxLineLength` - 最大行长度
|
||||
- `ExtractImages` - 导出图片文件
|
||||
- `ImageOutputDir` - 图片输出目录
|
||||
- `ImageNamePattern` - 图片命名模式
|
||||
- `ImageRelativePath` - 使用相对路径
|
||||
- `PreserveBookmarks` - 保留书签
|
||||
- `ConvertHyperlinks` - 转换超链接
|
||||
- `PreserveCodeStyle` - 保留代码样式
|
||||
- `DefaultCodeLang` - 默认代码语言
|
||||
- `IgnoreUnknownStyles` - 忽略未知样式
|
||||
- `PreserveTOC` - 保留目录
|
||||
- `IncludeMetadata` - 包含文档元数据
|
||||
- `StripComments` - 删除注释
|
||||
- `UseSetext` - 使用Setext样式标题
|
||||
- `BulletListMarker` - 项目符号标记
|
||||
- `EmphasisMarker` - 强调标记
|
||||
- `StrictMode` - 严格模式
|
||||
- `IgnoreErrors` - 忽略错误
|
||||
- `ErrorCallback` - 错误回调函数
|
||||
- `ProgressCallback` - 进度回调函数
|
||||
|
||||
### Word→Markdown转换映射
|
||||
|
||||
| Word元素 | Markdown语法 | 说明 |
|
||||
|----------|-------------|------|
|
||||
| Heading1-6 | `# ## ### #### ##### ######` | 标题级别对应 |
|
||||
| 粗体 | `**粗体**` | 文本格式 |
|
||||
| 斜体 | `*斜体*` | 文本格式 |
|
||||
| 删除线 | `~~删除线~~` | 文本格式 |
|
||||
| 行内代码 | `` `代码` `` | 代码格式 |
|
||||
| 代码块 | ```` 代码块 ```` | 代码块 |
|
||||
| 超链接 | `[链接文本](URL)` | 链接转换 |
|
||||
| 图片 | `` | 图片引用 |
|
||||
| 表格 | `\| 表格 \|` | GFM表格格式 |
|
||||
| 无序列表 | `- 项目` | 列表项 |
|
||||
| 有序列表 | `1. 项目` | 编号列表 |
|
||||
| 引用块 | `> 引用内容` | 引用格式 |
|
||||
|
||||
### Word转Markdown使用示例
|
||||
|
||||
#### 基础文件导出
|
||||
```go
|
||||
import "github.com/ZeroHawkeye/wordZero/pkg/markdown"
|
||||
|
||||
// 创建导出器
|
||||
exporter := markdown.NewExporter(markdown.DefaultExportOptions())
|
||||
|
||||
// 导出Word文档为Markdown
|
||||
err := exporter.ExportToFile("document.docx", "output.md", nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
#### 导出为字符串
|
||||
```go
|
||||
// 打开Word文档
|
||||
doc, err := document.Open("document.docx")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 导出为Markdown字符串
|
||||
exporter := markdown.NewExporter(markdown.DefaultExportOptions())
|
||||
markdownText, err := exporter.ExportToString(doc, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(markdownText)
|
||||
```
|
||||
|
||||
#### 高质量导出配置
|
||||
```go
|
||||
// 高质量导出配置
|
||||
options := &markdown.ExportOptions{
|
||||
UseGFMTables: true, // 使用GFM表格
|
||||
ExtractImages: true, // 导出图片
|
||||
ImageOutputDir: "./images", // 图片目录
|
||||
PreserveFootnotes: true, // 保留脚注
|
||||
IncludeMetadata: true, // 包含元数据
|
||||
ConvertHyperlinks: true, // 转换超链接
|
||||
PreserveCodeStyle: true, // 保留代码样式
|
||||
UseSetext: false, // 使用ATX标题
|
||||
BulletListMarker: "-", // 使用短横线
|
||||
EmphasisMarker: "*", // 使用星号
|
||||
ProgressCallback: func(current, total int) {
|
||||
fmt.Printf("导出进度: %d/%d\n", current, total)
|
||||
},
|
||||
}
|
||||
|
||||
exporter := markdown.NewExporter(options)
|
||||
err := exporter.ExportToFile("complex_document.docx", "output.md", options)
|
||||
```
|
||||
|
||||
#### 批量导出示例
|
||||
```go
|
||||
// 批量导出Word文档
|
||||
files := []string{"doc1.docx", "doc2.docx", "doc3.docx"}
|
||||
|
||||
options := &markdown.ExportOptions{
|
||||
ExtractImages: true,
|
||||
ImageOutputDir: "extracted_images/",
|
||||
UseGFMTables: true,
|
||||
ProgressCallback: func(current, total int) {
|
||||
fmt.Printf("批量导出进度: %d/%d\n", current, total)
|
||||
},
|
||||
}
|
||||
|
||||
exporter := markdown.NewExporter(options)
|
||||
err := exporter.BatchExport(files, "markdown_output/", options)
|
||||
```
|
||||
|
||||
## 双向转换器 ✨ **统一接口**
|
||||
|
||||
### 双向转换器API
|
||||
- [`NewBidirectionalConverter(mdOpts *ConvertOptions, exportOpts *ExportOptions)`](../markdown/exporter.go) - 创建双向转换器
|
||||
- [`AutoConvert(inputPath, outputPath string)`](../markdown/exporter.go) - 自动检测文件类型并转换
|
||||
|
||||
### 双向转换使用示例
|
||||
|
||||
#### 自动转换
|
||||
```go
|
||||
import "github.com/ZeroHawkeye/wordZero/pkg/markdown"
|
||||
|
||||
// 创建双向转换器
|
||||
converter := markdown.NewBidirectionalConverter(
|
||||
markdown.HighQualityOptions(), // Markdown→Word选项
|
||||
markdown.HighQualityExportOptions(), // Word→Markdown选项
|
||||
)
|
||||
|
||||
// 自动检测文件类型并转换
|
||||
err := converter.AutoConvert("input.docx", "output.md") // Word→Markdown
|
||||
err = converter.AutoConvert("input.md", "output.docx") // Markdown→Word
|
||||
```
|
||||
|
||||
#### 配置独立的转换方向
|
||||
```go
|
||||
// Markdown转Word配置
|
||||
mdToWordOpts := &markdown.ConvertOptions{
|
||||
EnableGFM: true,
|
||||
EnableTables: true,
|
||||
GenerateTOC: true,
|
||||
DefaultFontFamily: "Calibri",
|
||||
DefaultFontSize: 11.0,
|
||||
}
|
||||
|
||||
// Word转Markdown配置
|
||||
wordToMdOpts := &markdown.ExportOptions{
|
||||
UseGFMTables: true,
|
||||
ExtractImages: true,
|
||||
ImageOutputDir: "./images",
|
||||
PreserveFootnotes: true,
|
||||
ConvertHyperlinks: true,
|
||||
}
|
||||
|
||||
// 创建双向转换器
|
||||
converter := markdown.NewBidirectionalConverter(mdToWordOpts, wordToMdOpts)
|
||||
|
||||
// 执行转换
|
||||
err := converter.AutoConvert("document.docx", "document.md")
|
||||
```
|
||||
|
||||
### 技术特性
|
||||
|
||||
#### 架构设计
|
||||
|
Submodule wordZero.wiki updated: 31decacb58...defe2f93fc
Reference in New Issue
Block a user