package main import ( "testing" "github.com/stretchr/testify/require" ) func TestMarkdownEntities(t *testing.T) { testCases := []struct { name string markdown string text string entities []TelegramEntity }{ { name: "double asterisks give bold", markdown: "a **b** c", text: "a b c", entities: []TelegramEntity{ { Type: "bold", Offset: 2, Length: 1, }, }, }, { name: "double underscores give bold", markdown: "__bold__", text: "bold", entities: []TelegramEntity{ { Type: "bold", Offset: 0, Length: 4, }, }, }, { name: "single asterisk gives italic", markdown: "an *odd* word", text: "an odd word", entities: []TelegramEntity{ { Type: "italic", Offset: 3, Length: 3, }, }, }, { name: "single underscore gives italic", markdown: "an _odd_ word", text: "an odd word", entities: []TelegramEntity{ { Type: "italic", Offset: 3, Length: 3, }, }, }, { name: "double tildes give strikethrough", markdown: "~~old~~ new", text: "old new", entities: []TelegramEntity{ { Type: "strikethrough", Offset: 0, Length: 3, }, }, }, { name: "backticks give inline code with no entity inside", markdown: "run `go **test**` now", text: "run go **test** now", entities: []TelegramEntity{ { Type: "code", Offset: 4, Length: 11, }, }, }, { name: "double backticks hold a backtick", markdown: "``a ` b``", text: "a ` b", entities: []TelegramEntity{ { Type: "code", Offset: 0, Length: 5, }, }, }, { name: "link gives a text link", markdown: "see [the docs](https://example.com/a_b) here", text: "see the docs here", entities: []TelegramEntity{ { Type: "text_link", Offset: 4, Length: 8, URL: "https://example.com/a_b", }, }, }, { name: "bold inside a link nests", markdown: "[a **b** c](https://example.com)", text: "a b c", entities: []TelegramEntity{ { Type: "text_link", Offset: 0, Length: 5, URL: "https://example.com", }, { Type: "bold", Offset: 2, Length: 1, }, }, }, { name: "code block with a language gives pre with the language", markdown: "Commit:\n```text\nFix the **bug**\n\nBody\n```\nDone.", text: "Commit:\nFix the **bug**\n\nBody\nDone.", entities: []TelegramEntity{ { Type: "pre", Offset: 8, Length: 21, Language: "text", }, }, }, { name: "code block without a language gives pre", markdown: "```\nls -l\n```", text: "ls -l", entities: []TelegramEntity{ { Type: "pre", Offset: 0, Length: 5, }, }, }, { name: "heading becomes bold with its inline marks", markdown: "## The `plan`\nnext", text: "The plan\nnext", entities: []TelegramEntity{ { Type: "bold", Offset: 0, Length: 8, }, { Type: "code", Offset: 4, Length: 4, }, }, }, { name: "list, quote and table stay as text", markdown: "- one\n* two\n1. three\n> quote\n| a | b |\n|---|---|", text: "- one\n* two\n1. three\n> quote\n| a | b |\n|---|---|", }, { name: "asterisk of a list item with italic later stays", markdown: "* item with *stress*", text: "* item with stress", entities: []TelegramEntity{ { Type: "italic", Offset: 12, Length: 6, }, }, }, { name: "unclosed marks stay as text", markdown: "**open, `tick, [link](, ~~gone and *star", text: "**open, `tick, [link](, ~~gone and *star", }, { name: "unclosed code fence stays as text", markdown: "```go\nfmt.Println()", text: "```go\nfmt.Println()", }, { name: "snake case words stay as text", markdown: "set snake_case_words and max_tokens_count", text: "set snake_case_words and max_tokens_count", }, { name: "multiplication stays as text", markdown: "2 * 3 * 4", text: "2 * 3 * 4", }, { name: "mark does not cross a line break", markdown: "**a\nb**", text: "**a\nb**", }, { name: "backslash makes a mark plain", markdown: `\*not italic\* and C:\Users`, text: `*not italic* and C:\Users`, }, { name: "character outside the BMP moves the offset by two", markdown: "\U0001F600 **b**", text: "\U0001F600 b", entities: []TelegramEntity{ { Type: "bold", Offset: 3, Length: 1, }, }, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { text, entities := telegramMarkdownEntities(tc.markdown) require.Equal(t, tc.text, text) require.Equal(t, tc.entities, entities) }) } }