mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
12f4029610
* feat: telegram use parse mode ModeMarkdownV2 instead of ModeHTML * handle expandable block quotation starts, add test for all md2 formats * fix: linter issue * feat: added flag use_markdown_v2, corrected config, updated documentation * move parseChatID to parser_markdown_to_html * fix: tests and linter issues * fix: case with ~ * test: fixed Test_markdownToTelegramMarkdownV2 * fix: regex block-quote line > * fix: linter issues * fix: send chunk param mismatched, in edit msg use HTML parse mode too * fix: remove from .gitignore redundant comment
112 lines
2.4 KiB
Go
112 lines
2.4 KiB
Go
package telegram
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
func markdownToTelegramHTML(text string) string {
|
|
if text == "" {
|
|
return ""
|
|
}
|
|
|
|
codeBlocks := extractCodeBlocks(text)
|
|
text = codeBlocks.text
|
|
|
|
inlineCodes := extractInlineCodes(text)
|
|
text = inlineCodes.text
|
|
|
|
text = reHeading.ReplaceAllString(text, "$1")
|
|
|
|
text = reBlockquote.ReplaceAllString(text, "$1")
|
|
|
|
text = escapeHTML(text)
|
|
|
|
text = reLink.ReplaceAllString(text, `<a href="$2">$1</a>`)
|
|
|
|
text = reBoldStar.ReplaceAllString(text, "<b>$1</b>")
|
|
|
|
text = reBoldUnder.ReplaceAllString(text, "<b>$1</b>")
|
|
|
|
text = reItalic.ReplaceAllStringFunc(text, func(s string) string {
|
|
match := reItalic.FindStringSubmatch(s)
|
|
if len(match) < 2 {
|
|
return s
|
|
}
|
|
return "<i>" + match[1] + "</i>"
|
|
})
|
|
|
|
text = reStrike.ReplaceAllString(text, "<s>$1</s>")
|
|
|
|
text = reListItem.ReplaceAllString(text, "• ")
|
|
|
|
for i, code := range inlineCodes.codes {
|
|
escaped := escapeHTML(code)
|
|
text = strings.ReplaceAll(text, fmt.Sprintf("\x00IC%d\x00", i), fmt.Sprintf("<code>%s</code>", escaped))
|
|
}
|
|
|
|
for i, code := range codeBlocks.codes {
|
|
escaped := escapeHTML(code)
|
|
text = strings.ReplaceAll(
|
|
text,
|
|
fmt.Sprintf("\x00CB%d\x00", i),
|
|
fmt.Sprintf("<pre><code>%s</code></pre>", escaped),
|
|
)
|
|
}
|
|
|
|
return text
|
|
}
|
|
|
|
type codeBlockMatch struct {
|
|
text string
|
|
codes []string
|
|
}
|
|
|
|
func extractCodeBlocks(text string) codeBlockMatch {
|
|
matches := reCodeBlock.FindAllStringSubmatch(text, -1)
|
|
|
|
codes := make([]string, 0, len(matches))
|
|
for _, match := range matches {
|
|
codes = append(codes, match[1])
|
|
}
|
|
|
|
i := 0
|
|
text = reCodeBlock.ReplaceAllStringFunc(text, func(m string) string {
|
|
placeholder := fmt.Sprintf("\x00CB%d\x00", i)
|
|
i++
|
|
return placeholder
|
|
})
|
|
|
|
return codeBlockMatch{text: text, codes: codes}
|
|
}
|
|
|
|
type inlineCodeMatch struct {
|
|
text string
|
|
codes []string
|
|
}
|
|
|
|
func extractInlineCodes(text string) inlineCodeMatch {
|
|
matches := reInlineCode.FindAllStringSubmatch(text, -1)
|
|
|
|
codes := make([]string, 0, len(matches))
|
|
for _, match := range matches {
|
|
codes = append(codes, match[1])
|
|
}
|
|
|
|
i := 0
|
|
text = reInlineCode.ReplaceAllStringFunc(text, func(m string) string {
|
|
placeholder := fmt.Sprintf("\x00IC%d\x00", i)
|
|
i++
|
|
return placeholder
|
|
})
|
|
|
|
return inlineCodeMatch{text: text, codes: codes}
|
|
}
|
|
|
|
func escapeHTML(text string) string {
|
|
text = strings.ReplaceAll(text, "&", "&")
|
|
text = strings.ReplaceAll(text, "<", "<")
|
|
text = strings.ReplaceAll(text, ">", ">")
|
|
return text
|
|
}
|