diff --git a/internal/channels/telegram/format.go b/internal/channels/telegram/format.go
index e81bf411..5ab481b2 100644
--- a/internal/channels/telegram/format.go
+++ b/internal/channels/telegram/format.go
@@ -21,8 +21,10 @@ var htmlToMdReplacers = []struct {
{regexp.MustCompile(`(?i)?p\s*>`), "\n"},
{regexp.MustCompile(`(?i)([\s\S]*?)`), "**$1**"},
{regexp.MustCompile(`(?i)([\s\S]*?)`), "**$1**"},
- {regexp.MustCompile(`(?i)([\s\S]*?)`), "_$1_"},
- {regexp.MustCompile(`(?i)([\s\S]*?)`), "_$1_"},
+ // ${1}_ (not $1_) — Go regexp treats $1_ as a named group reference (identifier
+ // characters include `_`), which drops the capture. Curly braces delimit the group.
+ {regexp.MustCompile(`(?i)([\s\S]*?)`), "_${1}_"},
+ {regexp.MustCompile(`(?i)([\s\S]*?)`), "_${1}_"},
{regexp.MustCompile(`(?i)([\s\S]*?)`), "~~$1~~"},
{regexp.MustCompile(`(?i)([\s\S]*?)`), "~~$1~~"},
{regexp.MustCompile(`(?i)([\s\S]*?)`), "~~$1~~"},
diff --git a/internal/channels/telegram/format_extended_test.go b/internal/channels/telegram/format_extended_test.go
index e5eb09e6..8b7cd4fa 100644
--- a/internal/channels/telegram/format_extended_test.go
+++ b/internal/channels/telegram/format_extended_test.go
@@ -161,12 +161,17 @@ func TestMarkdownToTelegramHTML_HTMLTagsConvertedFirst(t *testing.T) {
t.Errorf("bold should remain bold in output, got: %q", got)
}
})
- t.Run("html italic input produces output", func(t *testing.T) {
- // italic goes through htmlTagToMarkdown (→ _italic_ with known $1_ caveat)
- // then through markdownToTelegramHTML — the result is non-empty, no panics.
+ t.Run("html italic tag round-trips", func(t *testing.T) {
+ // italic → _italic_ → italic through the full pipeline.
got := markdownToTelegramHTML("italic")
- if got == "" {
- t.Error("markdownToTelegramHTML should return non-empty for italic")
+ if !strings.Contains(got, "italic") {
+ t.Errorf("italic should remain italic in output, got: %q", got)
+ }
+ })
+ t.Run("html em tag round-trips", func(t *testing.T) {
+ got := markdownToTelegramHTML("emphasis")
+ if !strings.Contains(got, "emphasis") {
+ t.Errorf("emphasis should become emphasis, got: %q", got)
}
})
t.Run("html strike tag round-trips", func(t *testing.T) {
@@ -419,11 +424,8 @@ func TestHTMLTagToMarkdown(t *testing.T) {
{"
", []string{"\n"}},
{"bold", []string{"**bold**"}},
{"bold", []string{"**bold**"}},
- // NOTE: / use "_$1_" replacement where Go regexp treats $1_ as
- // a named group reference (not group 1 + literal _), so content is lost.
- // This is documented behavior of the current implementation.
- // The pipeline still works end-to-end because only appears in LLM
- // output which gets processed through the full markdownToTelegramHTML chain.
+ {"italic", []string{"_italic_"}},
+ {"italic", []string{"_italic_"}},
{"struck", []string{"~~struck~~"}},
{"deleted", []string{"~~deleted~~"}},
{"var", []string{"`var`"}},