113 lines
3.6 KiB
Go
113 lines
3.6 KiB
Go
package utils
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// BBCodeToMarkdown converts simplified Siropu-style BBCode into Matrix-safe Markdown.
|
|
//
|
|
// RULES:
|
|
// - [img]URL[/img] remains an image but without video tagging
|
|
// - [url] and [url=...] become markdown links
|
|
// - All [video]...[/video] wrappers are REMOVED entirely (your requirement)
|
|
// - Bold/italic/underline basic BBCode converted to markdown
|
|
// - Unknown tags stripped and inner text preserved
|
|
//
|
|
func BBCodeToMarkdown(in string) string {
|
|
if in == "" {
|
|
return ""
|
|
}
|
|
s := in
|
|
|
|
// ----------------------------------------------------
|
|
// STRIP VIDEO TAGS COMPLETELY
|
|
// ----------------------------------------------------
|
|
s = stripTagCompletely(s, "video")
|
|
|
|
// ----------------------------------------------------
|
|
// IMAGE TAGS → leave as-is, but sanitize formatting
|
|
// ----------------------------------------------------
|
|
s = regexp.MustCompile(`(?i)\[img\](.*?)\[/img\]`).ReplaceAllString(s, "")
|
|
|
|
// ----------------------------------------------------
|
|
// URL TAGS → Markdown links
|
|
// ----------------------------------------------------
|
|
// [url]http://x[/url]
|
|
s = regexp.MustCompile(`(?i)\[url\](.*?)\[/url\]`).ReplaceAllString(s, "[$1]($1)")
|
|
|
|
// [url=http://x]label[/url]
|
|
s = regexp.MustCompile(`(?i)\[url=(.*?)\](.*?)\[/url\]`).ReplaceAllString(s, "[$2]($1)")
|
|
|
|
// ----------------------------------------------------
|
|
// BASIC FORMATTING → Markdown
|
|
// ----------------------------------------------------
|
|
replacements := map[*regexp.Regexp]string{
|
|
regexp.MustCompile(`(?i)\[b\](.*?)\[/b\]`): "**$1**",
|
|
regexp.MustCompile(`(?i)\[i\](.*?)\[/i\]`): "*$1*",
|
|
regexp.MustCompile(`(?i)\[u\](.*?)\[/u\]`): "__$1__",
|
|
regexp.MustCompile(`(?i)\[s\](.*?)\[/s\]`): "~~$1~~",
|
|
regexp.MustCompile(`(?i)\[quote\](.*?)\[/quote\]`): "> $1",
|
|
}
|
|
|
|
for re, repl := range replacements {
|
|
s = re.ReplaceAllString(s, repl)
|
|
}
|
|
|
|
// ----------------------------------------------------
|
|
// REMOVE ANY OTHER BBCODE TAGS, KEEP CONTENT
|
|
// ----------------------------------------------------
|
|
s = regexp.MustCompile(`(?i)\[(\/?)[a-zA-Z0-9\=\#]+?\]`).ReplaceAllString(s, "")
|
|
|
|
// Cleanup whitespace
|
|
return strings.TrimSpace(s)
|
|
}
|
|
|
|
// stripTagCompletely removes [tag]...[/tag] entirely, preserving inner text only if desired.
|
|
// Here we drop everything inside video tags.
|
|
func stripTagCompletely(s, tag string) string {
|
|
re := regexp.MustCompile(`(?is)\[` + tag + `(?:=[^\]]*)?\].*?\[\/` + tag + `\]`)
|
|
return re.ReplaceAllString(s, "")
|
|
}
|
|
// IsImageURL determines whether a string looks like an image link.
|
|
// Used by both Matrix → Sneed and Sneed → Matrix paths.
|
|
func IsImageURL(u string) bool {
|
|
u = strings.ToLower(strings.TrimSpace(u))
|
|
if !(strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://")) {
|
|
return false
|
|
}
|
|
|
|
// strip query
|
|
if i := strings.Index(u, "?"); i > 0 {
|
|
u = u[:i]
|
|
}
|
|
|
|
return strings.HasSuffix(u, ".png") ||
|
|
strings.HasSuffix(u, ".jpg") ||
|
|
strings.HasSuffix(u, ".jpeg") ||
|
|
strings.HasSuffix(u, ".gif") ||
|
|
strings.HasSuffix(u, ".webp")
|
|
}
|
|
|
|
// WrapImageForSneed produces the BBCode wrapper used for outbound
|
|
// Matrix → Sneed image messages.
|
|
//
|
|
// Example:
|
|
// input: "https://example.com/img.jpg"
|
|
// output: "[url=https://example.com/img.jpg][img]https://example.com/img.jpg[/img][/url]"
|
|
//
|
|
func WrapImageForSneed(url string) string {
|
|
if url == "" {
|
|
return ""
|
|
}
|
|
return "[url=" + url + "][img]" + url + "[/img][/url]"
|
|
}
|
|
|
|
// ExtractFirstURL finds the first URL-like token in a message.
|
|
// Useful for deciding if a message is an image-only post.
|
|
func ExtractFirstURL(s string) string {
|
|
re := regexp.MustCompile(`https?://[^\s]+`)
|
|
found := re.FindString(s)
|
|
return found
|
|
}
|