6 "github.com/stretchr/testify/require"
9 func TestMarkdownEntities(t *testing.T) {
10 testCases := []struct {
14 entities []TelegramEntity
17 name: "double asterisks give bold",
18 markdown: "a **b** c",
20 entities: []TelegramEntity{
29 name: "double underscores give bold",
32 entities: []TelegramEntity{
41 name: "single asterisk gives italic",
42 markdown: "an *odd* word",
44 entities: []TelegramEntity{
53 name: "single underscore gives italic",
54 markdown: "an _odd_ word",
56 entities: []TelegramEntity{
65 name: "double tildes give strikethrough",
66 markdown: "~~old~~ new",
68 entities: []TelegramEntity{
70 Type: "strikethrough",
77 name: "backticks give inline code with no entity inside",
78 markdown: "run `go **test**` now",
79 text: "run go **test** now",
80 entities: []TelegramEntity{
89 name: "double backticks hold a backtick",
90 markdown: "``a ` b``",
92 entities: []TelegramEntity{
101 name: "link gives a text link",
102 markdown: "see [the docs](https://example.com/a_b) here",
103 text: "see the docs here",
104 entities: []TelegramEntity{
109 URL: "https://example.com/a_b",
114 name: "bold inside a link nests",
115 markdown: "[a **b** c](https://example.com)",
117 entities: []TelegramEntity{
122 URL: "https://example.com",
132 name: "code block with a language gives pre with the language",
133 markdown: "Commit:\n```text\nFix the **bug**\n\nBody\n```\nDone.",
134 text: "Commit:\nFix the **bug**\n\nBody\nDone.",
135 entities: []TelegramEntity{
145 name: "code block without a language gives pre",
146 markdown: "```\nls -l\n```",
148 entities: []TelegramEntity{
157 name: "heading becomes bold with its inline marks",
158 markdown: "## The `plan`\nnext",
159 text: "The plan\nnext",
160 entities: []TelegramEntity{
174 name: "list, quote and table stay as text",
175 markdown: "- one\n* two\n1. three\n> quote\n| a | b |\n|---|---|",
176 text: "- one\n* two\n1. three\n> quote\n| a | b |\n|---|---|",
179 name: "asterisk of a list item with italic later stays",
180 markdown: "* item with *stress*",
181 text: "* item with stress",
182 entities: []TelegramEntity{
191 name: "unclosed marks stay as text",
192 markdown: "**open, `tick, [link](, ~~gone and *star",
193 text: "**open, `tick, [link](, ~~gone and *star",
196 name: "unclosed code fence stays as text",
197 markdown: "```go\nfmt.Println()",
198 text: "```go\nfmt.Println()",
201 name: "snake case words stay as text",
202 markdown: "set snake_case_words and max_tokens_count",
203 text: "set snake_case_words and max_tokens_count",
206 name: "multiplication stays as text",
207 markdown: "2 * 3 * 4",
211 name: "mark does not cross a line break",
212 markdown: "**a\nb**",
216 name: "backslash makes a mark plain",
217 markdown: `\*not italic\* and C:\Users`,
218 text: `*not italic* and C:\Users`,
221 name: "character outside the BMP moves the offset by two",
222 markdown: "\U0001F600 **b**",
223 text: "\U0001F600 b",
224 entities: []TelegramEntity{
234 for _, tc := range testCases {
235 t.Run(tc.name, func(t *testing.T) {
236 text, entities := telegramMarkdownEntities(tc.markdown)
237 require.Equal(t, tc.text, text)
238 require.Equal(t, tc.entities, entities)
243 func TestEscapeTags(t *testing.T) {
244 testCases := []struct {
250 name: "tag in prose shows as text",
251 markdown: "Use a <details> tag for the rest.",
252 escaped: `Use a \<details> tag for the rest.`,
255 name: "tag in inline code stays as written",
256 markdown: "Use `<details>` and `` a<b ``, not <b>.",
257 escaped: "Use `<details>` and `` a<b ``, not \\<b>.",
260 name: "tag in a code block stays as written",
261 markdown: "<p>\n\n```html\n<details>\n```\n\n<p>",
262 escaped: "\\<p>\n\n```html\n<details>\n```\n\n\\<p>",
265 name: "code block that does not close stays as written",
266 markdown: "a <b>\n```\n<details>",
267 escaped: "a \\<b>\n```\n<details>",
270 name: "tag in a table cell shows as text",
271 markdown: "| Tag | Use |\n|-----|-----|\n| <br> | `<br>` |",
272 escaped: "| Tag | Use |\n|-----|-----|\n| \\<br> | `<br>` |",
275 name: "autolink shows as text",
276 markdown: "See <https://example.com>.",
277 escaped: `See \<https://example.com>.`,
280 name: "backtick run that opens no code stays as text",
281 markdown: "a ``b` <c>",
282 escaped: "a ``b` \\<c>",
285 name: "escaped bracket stays as written",
286 markdown: `a \<b> and \\<c>`,
287 escaped: `a \<b> and \\\<c>`,
290 name: "dollar, pipe, and equals signs stay as written",
291 markdown: "$5 or $10, a || b, ==c==",
292 escaped: "$5 or $10, a || b, ==c==",
296 for _, tc := range testCases {
297 t.Run(tc.name, func(t *testing.T) {
298 require.Equal(t, tc.escaped, telegramEscapeTags(tc.markdown))