package rag import ( "code.tczkiot.com/wlw/ai-agent/internal/pkg/enums" "strings" "github.com/yuin/goldmark" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/renderer/html" htmlparser "golang.org/x/net/html" ) var plainTextMarkdown = goldmark.New( goldmark.WithExtensions(extension.GFM), goldmark.WithParserOptions( parser.WithAutoHeadingID(), ), goldmark.WithRendererOptions( html.WithHardWraps(), html.WithXHTML(), ), ) func ExtractPlainText(content string, contentType enums.KnowledgeDocumentContentType) string { switch contentType { case enums.KnowledgeDocumentContentTypeMarkdown: return ExtractPlainTextFromMarkdown(content) case enums.KnowledgeDocumentContentTypeHTML: return ExtractPlainTextFromHTML(content) default: return normalizeWhitespace(content) } } func ExtractPlainTextFromMarkdown(content string) string { content = strings.TrimSpace(content) if content == "" { return "" } var buf strings.Builder if err := plainTextMarkdown.Convert([]byte(content), &buf); err != nil { return normalizeWhitespace(content) } return ExtractPlainTextFromHTML(buf.String()) } func ExtractPlainTextFromHTML(content string) string { content = strings.TrimSpace(content) if content == "" { return "" } var builder strings.Builder parent := &htmlparser.Node{ Type: htmlparser.ElementNode, Data: "div", } nodes, err := htmlparser.ParseFragment(strings.NewReader(content), parent) if err == nil { for _, node := range nodes { writeHTMLNodeText(&builder, node) } return normalizeWhitespace(builder.String()) } // 兜底:部分输入在 ParseFragment 下会失败(例如不符合 fragment 规则或上下文不匹配)。 // 这里用完整 HTML 解析保证可用性。 doc, err := htmlparser.Parse(strings.NewReader("