From 25d4f16831576f7cdee369fa82a88f34344c17e1 Mon Sep 17 00:00:00 2001 From: Aleksandr Bortnikov Date: Wed, 4 Mar 2026 08:37:55 +0300 Subject: [PATCH] handle expandable block quotation starts, add test for all md2 formats --- pkg/channels/telegram/telegram.go | 11 +++++-- pkg/channels/telegram/telegram_test.go | 9 ++++++ .../telegram/testdata/md2_all_formats.txt | 31 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 pkg/channels/telegram/testdata/md2_all_formats.txt diff --git a/pkg/channels/telegram/telegram.go b/pkg/channels/telegram/telegram.go index b008d57ca..9b439cc02 100644 --- a/pkg/channels/telegram/telegram.go +++ b/pkg/channels/telegram/telegram.go @@ -635,7 +635,14 @@ func markdownToTelegramMarkdownV2(text string) string { continue } - // 5. Handle standard Markdown Entities Boundaries + // 5. Handle expandable block quotation starts + if runes[i] == '>' && runes[i-1] == '*' && runes[i-2] == '*' && (i == 0 || runes[i-3] == '\n') { + result.WriteRune(runes[i]) + i++ + continue + } + + // 6. Handle standard Markdown Entities Boundaries // If they are part of valid markdown boundaries, we write them as-is. // We trust the syntax rules: * _ ~ || [ ] // (Assuming the text is a valid markdown, we don't escape these if formatting is intended) @@ -668,7 +675,7 @@ func markdownToTelegramMarkdownV2(text string) string { continue } - // 6. Handle plain text characters + // 7. Handle plain text characters // Escape remaining special characters if they aren't forming intended valid markup if needsNormalEscape(runes[i]) { // Check if it's already escaped; if an escape character exists, consume it legitimately diff --git a/pkg/channels/telegram/telegram_test.go b/pkg/channels/telegram/telegram_test.go index 0de803fd8..c7658b7c7 100644 --- a/pkg/channels/telegram/telegram_test.go +++ b/pkg/channels/telegram/telegram_test.go @@ -4,9 +4,14 @@ import ( "fmt" "testing" + _ "embed" + "github.com/stretchr/testify/require" ) +//go:embed testdata/md2_all_formats.txt +var md2AllFormats string + func Test_markdownToTelegramMarkdownV2(t *testing.T) { cases := []struct { input string @@ -24,6 +29,10 @@ func Test_markdownToTelegramMarkdownV2(t *testing.T) { input: "[inline URL](http://www.example.com/)", expected: "[inline URL](http://www.example.com/)", }, + { + input: md2AllFormats, + expected: md2AllFormats, + }, } for _, tc := range cases { diff --git a/pkg/channels/telegram/testdata/md2_all_formats.txt b/pkg/channels/telegram/testdata/md2_all_formats.txt new file mode 100644 index 000000000..f78fcc72f --- /dev/null +++ b/pkg/channels/telegram/testdata/md2_all_formats.txt @@ -0,0 +1,31 @@ +*bold \*text* +_italic \*text_ +__underline__ +~strikethrough~ +||spoiler|| +*bold _italic bold ~italic bold strikethrough ||italic bold strikethrough spoiler||~ __underline italic bold___ bold* +[inline URL](http://www.example.com/) +[inline mention of a user](tg://user?id=123456789) +![👍](tg://emoji?id=5368324170671202286) +![22:45 tomorrow](tg://time?unix=1647531900&format=wDT) +![22:45 tomorrow](tg://time?unix=1647531900&format=t) +![22:45 tomorrow](tg://time?unix=1647531900&format=r) +![22:45 tomorrow](tg://time?unix=1647531900) +`inline fixed-width code` +``` +pre-formatted fixed-width code block +``` +```python +pre-formatted fixed-width code block written in the Python programming language +``` +>Block quotation started +>Block quotation continued +>Block quotation continued +>Block quotation continued +>The last line of the block quotation +**>The expandable block quotation started right after the previous block quotation +>It is separated from the previous block quotation by an empty bold entity +>Expandable block quotation continued +>Hidden by default part of the expandable block quotation started +>Expandable block quotation continued +>The last line of the expandable block quotation with the expandability mark||