This commit is contained in:
658
internal/shared/pdf/markdown_converter.go
Normal file
658
internal/shared/pdf/markdown_converter.go
Normal file
@@ -0,0 +1,658 @@
|
||||
package pdf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MarkdownConverter Markdown转换器 - 将各种格式的markdown内容标准化
|
||||
type MarkdownConverter struct {
|
||||
textProcessor *TextProcessor
|
||||
}
|
||||
|
||||
// NewMarkdownConverter 创建Markdown转换器
|
||||
func NewMarkdownConverter(textProcessor *TextProcessor) *MarkdownConverter {
|
||||
return &MarkdownConverter{
|
||||
textProcessor: textProcessor,
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertToStandardMarkdown 将各种格式的内容转换为标准的markdown格式
|
||||
// 这是第一步:预处理和标准化
|
||||
func (mc *MarkdownConverter) ConvertToStandardMarkdown(content string) string {
|
||||
if strings.TrimSpace(content) == "" {
|
||||
return content
|
||||
}
|
||||
|
||||
// 1. 先清理HTML标签(保留内容)
|
||||
content = mc.textProcessor.StripHTML(content)
|
||||
|
||||
// 2. 处理代码块 - 确保代码块格式正确
|
||||
content = mc.normalizeCodeBlocks(content)
|
||||
|
||||
// 3. 处理表格 - 确保表格格式正确
|
||||
content = mc.normalizeTables(content)
|
||||
|
||||
// 4. 处理列表 - 统一列表格式
|
||||
content = mc.normalizeLists(content)
|
||||
|
||||
// 5. 处理JSON内容 - 尝试识别并格式化JSON
|
||||
content = mc.normalizeJSONContent(content)
|
||||
|
||||
// 6. 处理链接和图片 - 转换为文本
|
||||
content = mc.convertLinksToText(content)
|
||||
content = mc.convertImagesToText(content)
|
||||
|
||||
// 7. 处理引用块
|
||||
content = mc.normalizeBlockquotes(content)
|
||||
|
||||
// 8. 处理水平线
|
||||
content = mc.normalizeHorizontalRules(content)
|
||||
|
||||
// 9. 清理多余空行(保留代码块内的空行)
|
||||
content = mc.cleanupExtraBlankLines(content)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
// normalizeCodeBlocks 规范化代码块
|
||||
func (mc *MarkdownConverter) normalizeCodeBlocks(content string) string {
|
||||
lines := strings.Split(content, "\n")
|
||||
var result []string
|
||||
inCodeBlock := false
|
||||
codeBlockLang := ""
|
||||
|
||||
for i, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 检查是否是代码块开始
|
||||
if strings.HasPrefix(trimmed, "```") {
|
||||
if inCodeBlock {
|
||||
// 代码块结束
|
||||
result = append(result, line)
|
||||
inCodeBlock = false
|
||||
codeBlockLang = ""
|
||||
} else {
|
||||
// 代码块开始
|
||||
inCodeBlock = true
|
||||
// 提取语言标识
|
||||
if len(trimmed) > 3 {
|
||||
codeBlockLang = strings.TrimSpace(trimmed[3:])
|
||||
if codeBlockLang != "" {
|
||||
result = append(result, fmt.Sprintf("```%s", codeBlockLang))
|
||||
} else {
|
||||
result = append(result, "```")
|
||||
}
|
||||
} else {
|
||||
result = append(result, "```")
|
||||
}
|
||||
}
|
||||
} else if inCodeBlock {
|
||||
// 在代码块中,保留原样
|
||||
result = append(result, line)
|
||||
} else {
|
||||
// 不在代码块中,处理其他内容
|
||||
result = append(result, line)
|
||||
}
|
||||
|
||||
// 如果代码块没有正确关闭,在文件末尾自动关闭
|
||||
if i == len(lines)-1 && inCodeBlock {
|
||||
result = append(result, "```")
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// normalizeTables 规范化表格格式
|
||||
func (mc *MarkdownConverter) normalizeTables(content string) string {
|
||||
lines := strings.Split(content, "\n")
|
||||
var result []string
|
||||
inCodeBlock := false
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 检查是否在代码块中
|
||||
if strings.HasPrefix(trimmed, "```") {
|
||||
inCodeBlock = !inCodeBlock
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
if inCodeBlock {
|
||||
// 代码块中的内容不处理
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// 检查是否是表格行
|
||||
if strings.Contains(trimmed, "|") {
|
||||
// 检查是否是分隔行
|
||||
isSeparator := mc.isTableSeparator(trimmed)
|
||||
if isSeparator {
|
||||
// 确保分隔行格式正确
|
||||
cells := strings.Split(trimmed, "|")
|
||||
// 清理首尾空元素
|
||||
if len(cells) > 0 && cells[0] == "" {
|
||||
cells = cells[1:]
|
||||
}
|
||||
if len(cells) > 0 && cells[len(cells)-1] == "" {
|
||||
cells = cells[:len(cells)-1]
|
||||
}
|
||||
// 构建标准分隔行
|
||||
separator := "|"
|
||||
for range cells {
|
||||
separator += " --- |"
|
||||
}
|
||||
result = append(result, separator)
|
||||
} else {
|
||||
// 普通表格行,确保格式正确
|
||||
normalizedLine := mc.normalizeTableRow(line)
|
||||
result = append(result, normalizedLine)
|
||||
}
|
||||
} else {
|
||||
result = append(result, line)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// isTableSeparator 检查是否是表格分隔行
|
||||
func (mc *MarkdownConverter) isTableSeparator(line string) bool {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if !strings.Contains(trimmed, "-") {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查是否只包含 |、-、:、空格
|
||||
for _, r := range trimmed {
|
||||
if r != '|' && r != '-' && r != ':' && r != ' ' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// normalizeTableRow 规范化表格行
|
||||
func (mc *MarkdownConverter) normalizeTableRow(line string) string {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if !strings.Contains(trimmed, "|") {
|
||||
return line
|
||||
}
|
||||
|
||||
cells := strings.Split(trimmed, "|")
|
||||
// 清理首尾空元素
|
||||
if len(cells) > 0 && cells[0] == "" {
|
||||
cells = cells[1:]
|
||||
}
|
||||
if len(cells) > 0 && cells[len(cells)-1] == "" {
|
||||
cells = cells[:len(cells)-1]
|
||||
}
|
||||
|
||||
// 清理每个单元格
|
||||
normalizedCells := make([]string, 0, len(cells))
|
||||
for _, cell := range cells {
|
||||
cell = strings.TrimSpace(cell)
|
||||
// 移除markdown格式但保留内容
|
||||
cell = mc.textProcessor.RemoveMarkdownSyntax(cell)
|
||||
normalizedCells = append(normalizedCells, cell)
|
||||
}
|
||||
|
||||
// 重新构建表格行
|
||||
return "| " + strings.Join(normalizedCells, " | ") + " |"
|
||||
}
|
||||
|
||||
// normalizeLists 规范化列表格式
|
||||
func (mc *MarkdownConverter) normalizeLists(content string) string {
|
||||
lines := strings.Split(content, "\n")
|
||||
var result []string
|
||||
inCodeBlock := false
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 检查是否在代码块中
|
||||
if strings.HasPrefix(trimmed, "```") {
|
||||
inCodeBlock = !inCodeBlock
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
if inCodeBlock {
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理有序列表
|
||||
if matched, _ := regexp.MatchString(`^\d+\.\s+`, trimmed); matched {
|
||||
// 确保格式统一:数字. 空格
|
||||
re := regexp.MustCompile(`^(\d+)\.\s*`)
|
||||
trimmed = re.ReplaceAllString(trimmed, "$1. ")
|
||||
result = append(result, trimmed)
|
||||
} else if strings.HasPrefix(trimmed, "- ") || strings.HasPrefix(trimmed, "* ") || strings.HasPrefix(trimmed, "+ ") {
|
||||
// 处理无序列表,统一使用 -
|
||||
re := regexp.MustCompile(`^[-*+]\s*`)
|
||||
trimmed = re.ReplaceAllString(trimmed, "- ")
|
||||
result = append(result, trimmed)
|
||||
} else {
|
||||
result = append(result, line)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// normalizeJSONContent 规范化JSON内容
|
||||
func (mc *MarkdownConverter) normalizeJSONContent(content string) string {
|
||||
// 尝试识别并格式化JSON代码块
|
||||
jsonBlockRegex := regexp.MustCompile("(?s)```(?:json)?\\s*\n(.*?)\n```")
|
||||
content = jsonBlockRegex.ReplaceAllStringFunc(content, func(match string) string {
|
||||
// 提取JSON内容
|
||||
submatch := jsonBlockRegex.FindStringSubmatch(match)
|
||||
if len(submatch) < 2 {
|
||||
return match
|
||||
}
|
||||
|
||||
jsonStr := strings.TrimSpace(submatch[1])
|
||||
// 尝试格式化JSON
|
||||
var jsonObj interface{}
|
||||
if err := json.Unmarshal([]byte(jsonStr), &jsonObj); err == nil {
|
||||
// 格式化成功
|
||||
formatted, err := json.MarshalIndent(jsonObj, "", " ")
|
||||
if err == nil {
|
||||
return fmt.Sprintf("```json\n%s\n```", string(formatted))
|
||||
}
|
||||
}
|
||||
return match
|
||||
})
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
// convertLinksToText 将链接转换为文本
|
||||
func (mc *MarkdownConverter) convertLinksToText(content string) string {
|
||||
// [text](url) -> text (url)
|
||||
linkRegex := regexp.MustCompile(`\[([^\]]+)\]\(([^\)]+)\)`)
|
||||
content = linkRegex.ReplaceAllString(content, "$1 ($2)")
|
||||
|
||||
// [text][ref] -> text
|
||||
refLinkRegex := regexp.MustCompile(`\[([^\]]+)\]\[[^\]]+\]`)
|
||||
content = refLinkRegex.ReplaceAllString(content, "$1")
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
// convertImagesToText 将图片转换为文本
|
||||
func (mc *MarkdownConverter) convertImagesToText(content string) string {
|
||||
//  -> [图片: alt]
|
||||
imageRegex := regexp.MustCompile(`!\[([^\]]*)\]\([^\)]+\)`)
|
||||
content = imageRegex.ReplaceAllString(content, "[图片: $1]")
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
// normalizeBlockquotes 规范化引用块
|
||||
func (mc *MarkdownConverter) normalizeBlockquotes(content string) string {
|
||||
lines := strings.Split(content, "\n")
|
||||
var result []string
|
||||
inCodeBlock := false
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 检查是否在代码块中
|
||||
if strings.HasPrefix(trimmed, "```") {
|
||||
inCodeBlock = !inCodeBlock
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
if inCodeBlock {
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理引用块 > text -> > text
|
||||
if strings.HasPrefix(trimmed, ">") {
|
||||
// 确保格式统一
|
||||
quoteText := strings.TrimSpace(trimmed[1:])
|
||||
if quoteText != "" {
|
||||
result = append(result, "> "+quoteText)
|
||||
} else {
|
||||
result = append(result, ">")
|
||||
}
|
||||
} else {
|
||||
result = append(result, line)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// normalizeHorizontalRules 规范化水平线
|
||||
func (mc *MarkdownConverter) normalizeHorizontalRules(content string) string {
|
||||
// 统一水平线格式为 ---
|
||||
hrRegex := regexp.MustCompile(`^[-*_]{3,}\s*$`)
|
||||
lines := strings.Split(content, "\n")
|
||||
var result []string
|
||||
inCodeBlock := false
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 检查是否在代码块中
|
||||
if strings.HasPrefix(trimmed, "```") {
|
||||
inCodeBlock = !inCodeBlock
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
if inCodeBlock {
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// 如果是水平线,统一格式
|
||||
if hrRegex.MatchString(trimmed) {
|
||||
result = append(result, "---")
|
||||
} else {
|
||||
result = append(result, line)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// cleanupExtraBlankLines 清理多余空行(保留代码块内的空行)
|
||||
func (mc *MarkdownConverter) cleanupExtraBlankLines(content string) string {
|
||||
lines := strings.Split(content, "\n")
|
||||
var result []string
|
||||
inCodeBlock := false
|
||||
lastWasBlank := false
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 检查是否在代码块中
|
||||
if strings.HasPrefix(trimmed, "```") {
|
||||
inCodeBlock = !inCodeBlock
|
||||
result = append(result, line)
|
||||
lastWasBlank = false
|
||||
continue
|
||||
}
|
||||
|
||||
if inCodeBlock {
|
||||
// 代码块中的内容全部保留
|
||||
result = append(result, line)
|
||||
lastWasBlank = (trimmed == "")
|
||||
continue
|
||||
}
|
||||
|
||||
// 不在代码块中
|
||||
if trimmed == "" {
|
||||
// 空行:最多保留一个连续空行
|
||||
if !lastWasBlank {
|
||||
result = append(result, "")
|
||||
lastWasBlank = true
|
||||
}
|
||||
} else {
|
||||
result = append(result, line)
|
||||
lastWasBlank = false
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// PreprocessContent 预处理内容 - 这是主要的转换入口
|
||||
// 先转换,再解析
|
||||
func (mc *MarkdownConverter) PreprocessContent(content string) string {
|
||||
if strings.TrimSpace(content) == "" {
|
||||
return content
|
||||
}
|
||||
|
||||
// 第一步:转换为标准markdown
|
||||
content = mc.ConvertToStandardMarkdown(content)
|
||||
|
||||
// 第二步:尝试识别并转换JSON数组为表格
|
||||
content = mc.convertJSONArrayToTable(content)
|
||||
|
||||
// 第三步:确保所有表格都有正确的分隔行
|
||||
content = mc.ensureTableSeparators(content)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
// convertJSONArrayToTable 将JSON数组转换为markdown表格
|
||||
func (mc *MarkdownConverter) convertJSONArrayToTable(content string) string {
|
||||
// 如果内容已经是表格格式,不处理
|
||||
if strings.Contains(content, "|") {
|
||||
lines := strings.Split(content, "\n")
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if strings.Contains(trimmed, "|") && !strings.HasPrefix(trimmed, "```") {
|
||||
// 已经有表格,不转换
|
||||
return content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试解析为JSON数组
|
||||
trimmedContent := strings.TrimSpace(content)
|
||||
if strings.HasPrefix(trimmedContent, "[") {
|
||||
var jsonArray []map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(trimmedContent), &jsonArray); err == nil && len(jsonArray) > 0 {
|
||||
// 转换为markdown表格
|
||||
return mc.jsonArrayToMarkdownTable(jsonArray)
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试解析为JSON对象(包含params或fields字段)
|
||||
if strings.HasPrefix(trimmedContent, "{") {
|
||||
var jsonObj map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(trimmedContent), &jsonObj); err == nil {
|
||||
// 检查是否有params字段
|
||||
if params, ok := jsonObj["params"].([]interface{}); ok {
|
||||
paramMaps := make([]map[string]interface{}, 0, len(params))
|
||||
for _, p := range params {
|
||||
if pm, ok := p.(map[string]interface{}); ok {
|
||||
paramMaps = append(paramMaps, pm)
|
||||
}
|
||||
}
|
||||
if len(paramMaps) > 0 {
|
||||
return mc.jsonArrayToMarkdownTable(paramMaps)
|
||||
}
|
||||
}
|
||||
// 检查是否有fields字段
|
||||
if fields, ok := jsonObj["fields"].([]interface{}); ok {
|
||||
fieldMaps := make([]map[string]interface{}, 0, len(fields))
|
||||
for _, f := range fields {
|
||||
if fm, ok := f.(map[string]interface{}); ok {
|
||||
fieldMaps = append(fieldMaps, fm)
|
||||
}
|
||||
}
|
||||
if len(fieldMaps) > 0 {
|
||||
return mc.jsonArrayToMarkdownTable(fieldMaps)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
// jsonArrayToMarkdownTable 将JSON数组转换为markdown表格
|
||||
func (mc *MarkdownConverter) jsonArrayToMarkdownTable(data []map[string]interface{}) string {
|
||||
if len(data) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var result strings.Builder
|
||||
|
||||
// 收集所有可能的列名(保持原始顺序)
|
||||
// 使用map记录是否已添加,使用slice保持顺序
|
||||
columnSet := make(map[string]bool)
|
||||
columns := make([]string, 0)
|
||||
|
||||
// 遍历所有数据行,按第一次出现的顺序收集列名
|
||||
for _, row := range data {
|
||||
for key := range row {
|
||||
if !columnSet[key] {
|
||||
columns = append(columns, key)
|
||||
columnSet[key] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(columns) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 构建表头(直接使用原始列名,不做映射)
|
||||
result.WriteString("|")
|
||||
for _, col := range columns {
|
||||
result.WriteString(" ")
|
||||
result.WriteString(col) // 直接使用原始列名
|
||||
result.WriteString(" |")
|
||||
}
|
||||
result.WriteString("\n")
|
||||
|
||||
// 构建分隔行
|
||||
result.WriteString("|")
|
||||
for range columns {
|
||||
result.WriteString(" --- |")
|
||||
}
|
||||
result.WriteString("\n")
|
||||
|
||||
// 构建数据行
|
||||
for _, row := range data {
|
||||
result.WriteString("|")
|
||||
for _, col := range columns {
|
||||
result.WriteString(" ")
|
||||
value := mc.formatCellValue(row[col])
|
||||
result.WriteString(value)
|
||||
result.WriteString(" |")
|
||||
}
|
||||
result.WriteString("\n")
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// formatColumnName 格式化列名(直接返回原始列名,不做映射)
|
||||
// 保持数据库原始数据的列名,不进行转换
|
||||
func (mc *MarkdownConverter) formatColumnName(name string) string {
|
||||
// 直接返回原始列名,保持数据库数据的原始格式
|
||||
return name
|
||||
}
|
||||
|
||||
// formatCellValue 格式化单元格值
|
||||
func (mc *MarkdownConverter) formatCellValue(value interface{}) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
v = strings.ReplaceAll(v, "\n", " ")
|
||||
v = strings.ReplaceAll(v, "\r", " ")
|
||||
v = strings.TrimSpace(v)
|
||||
v = strings.ReplaceAll(v, "|", "\\|")
|
||||
return v
|
||||
case bool:
|
||||
if v {
|
||||
return "是"
|
||||
}
|
||||
return "否"
|
||||
case float64:
|
||||
if v == float64(int64(v)) {
|
||||
return fmt.Sprintf("%.0f", v)
|
||||
}
|
||||
return fmt.Sprintf("%g", v)
|
||||
case int, int8, int16, int32, int64:
|
||||
return fmt.Sprintf("%d", v)
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
return fmt.Sprintf("%d", v)
|
||||
default:
|
||||
str := fmt.Sprintf("%v", v)
|
||||
str = strings.ReplaceAll(str, "\n", " ")
|
||||
str = strings.ReplaceAll(str, "\r", " ")
|
||||
str = strings.ReplaceAll(str, "|", "\\|")
|
||||
return strings.TrimSpace(str)
|
||||
}
|
||||
}
|
||||
|
||||
// ensureTableSeparators 确保所有表格都有正确的分隔行
|
||||
func (mc *MarkdownConverter) ensureTableSeparators(content string) string {
|
||||
lines := strings.Split(content, "\n")
|
||||
var result []string
|
||||
inCodeBlock := false
|
||||
lastLineWasTableHeader := false
|
||||
|
||||
for i, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
|
||||
// 检查是否在代码块中
|
||||
if strings.HasPrefix(trimmed, "```") {
|
||||
inCodeBlock = !inCodeBlock
|
||||
result = append(result, line)
|
||||
lastLineWasTableHeader = false
|
||||
continue
|
||||
}
|
||||
|
||||
if inCodeBlock {
|
||||
result = append(result, line)
|
||||
lastLineWasTableHeader = false
|
||||
continue
|
||||
}
|
||||
|
||||
// 检查是否是表格行
|
||||
if strings.Contains(trimmed, "|") {
|
||||
// 检查是否是分隔行
|
||||
if mc.isTableSeparator(trimmed) {
|
||||
result = append(result, line)
|
||||
lastLineWasTableHeader = false
|
||||
} else {
|
||||
// 普通表格行
|
||||
result = append(result, line)
|
||||
// 检查上一行是否是表头
|
||||
if lastLineWasTableHeader {
|
||||
// 在表头后插入分隔行
|
||||
cells := strings.Split(trimmed, "|")
|
||||
if len(cells) > 0 && cells[0] == "" {
|
||||
cells = cells[1:]
|
||||
}
|
||||
if len(cells) > 0 && cells[len(cells)-1] == "" {
|
||||
cells = cells[:len(cells)-1]
|
||||
}
|
||||
separator := "|"
|
||||
for range cells {
|
||||
separator += " --- |"
|
||||
}
|
||||
// 在当前位置插入分隔行
|
||||
result = append(result[:len(result)-1], separator, line)
|
||||
} else {
|
||||
// 检查是否是表头(第一行表格)
|
||||
if i > 0 {
|
||||
prevLine := strings.TrimSpace(lines[i-1])
|
||||
if !strings.Contains(prevLine, "|") || mc.isTableSeparator(prevLine) {
|
||||
// 这可能是表头
|
||||
lastLineWasTableHeader = true
|
||||
}
|
||||
} else {
|
||||
lastLineWasTableHeader = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = append(result, line)
|
||||
lastLineWasTableHeader = false
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
Reference in New Issue
Block a user