package services import ( "html" "regexp" "strings" ) var ( mdImageRe = regexp.MustCompile(`!\[([^\]]*)\]\(([^)]+)\)`) mdLinkRe = regexp.MustCompile(`\[([^\]]+)\]\(([^)]+)\)`) ) // ComposeBodyToHTML 将发帖表单正文转为可消毒 HTML。 // 若已含块级 HTML 标签则原样交 Sanitize;否则按纯文本/轻量 Markdown 转段落。 func ComposeBodyToHTML(raw string) string { raw = strings.TrimSpace(raw) if raw == "" { return "" } lower := strings.ToLower(raw) if strings.Contains(lower, "` + alt + `

` }) esc = mdLinkRe.ReplaceAllStringFunc(esc, func(m string) string { sub := mdLinkRe.FindStringSubmatch(m) if len(sub) != 3 { return m } text, href := sub[1], sub[2] if !safeComposeURL(href) { return m } return `` + text + `` }) parts := strings.Split(esc, "\n\n") var b strings.Builder for _, p := range parts { p = strings.TrimSpace(p) if p == "" { continue } // 已是独立 img 段 if strings.HasPrefix(p, "

\n") b.WriteString("

") b.WriteString(p) b.WriteString("

\n") } return b.String() } func safeComposeURL(u string) bool { u = strings.TrimSpace(u) if strings.HasPrefix(u, "/uploads/") || strings.HasPrefix(u, "/media/") { return true } return strings.HasPrefix(u, "https://") || strings.HasPrefix(u, "http://") } // HTMLToComposePlain 编辑页回显:去掉简单标签便于 textarea 编辑(尽力而为) func HTMLToComposePlain(htmlBody string) string { s := strings.TrimSpace(htmlBody) if s == "" { return "" } // img → markdown imgRe := regexp.MustCompile(`(?i)]+src="([^"]+)"[^>]*>`) s = imgRe.ReplaceAllString(s, "![]($1)") s = regexp.MustCompile(`(?i)

\s*

`).ReplaceAllString(s, "\n\n") s = regexp.MustCompile(`(?i)`).ReplaceAllString(s, "\n") s = regexp.MustCompile(`(?i)]*>`).ReplaceAllString(s, "") s = regexp.MustCompile(`(?i)<[^>]+>`).ReplaceAllString(s, "") return strings.TrimSpace(html.UnescapeString(s)) }