)
var (
- // telegramTagEscaper writes the characters that rich Markdown reads as HTML
- // as HTML entities.
+ // telegramTagEscaper writes the characters that rich Markdown reads as
+ // HTML as HTML entities.
telegramTagEscaper = strings.NewReplacer("&", "&", "<", "<")
// telegramTagUnescaper reverses telegramTagEscaper.
telegramTagUnescaper = strings.NewReplacer("&", "&", "<", "<")
)
+// TelegramMarkdownText is the plain text of a Markdown reply and its Telegram
+// entities, while the conversion builds it. Units counts the UTF-16 code units
+// of text, the unit of the entity offsets and lengths.
+type TelegramMarkdownText struct {
+ text strings.Builder
+ units int
+ entities []TelegramEntity
+}
+
+// add appends text.
+func (m *TelegramMarkdownText) add(text string) {
+ m.text.WriteString(text)
+
+ m.units += telegramUTF16Units(text)
+}
+
+// entity keeps entity, unless it is empty, because Telegram refuses an entity
+// of length 0.
+func (m *TelegramMarkdownText) entity(entity TelegramEntity) {
+ if entity.Length > 0 {
+ m.entities = append(m.entities, entity)
+ }
+}
+
+// inline appends one line of Markdown with its inline marks as entities. A
+// backslash before an ASCII punctuation character makes the character plain
+// text.
+func (m *TelegramMarkdownText) inline(line string) {
+ plain := 0
+ index := 0
+ for index < len(line) {
+ if line[index] == '\\' && index+1 < len(line) && strings.IndexByte(markdownPunctuation, line[index+1]) >= 0 {
+ m.add(line[plain:index])
+
+ plain = index + 1
+ index += 2
+
+ continue
+ }
+
+ span, found := markdownMarkSpan(line, index)
+ if !found {
+ index++
+ continue
+ }
+
+ m.add(line[plain:index])
+
+ start := m.units
+ if span.kind == "code" {
+ m.add(span.content)
+ } else {
+ m.inline(span.content)
+ }
+
+ m.entity(TelegramEntity{
+ Type: span.kind,
+ Offset: start,
+ Length: m.units - start,
+ URL: span.url,
+ })
+
+ index = span.end
+ plain = span.end
+ }
+
+ m.add(line[plain:])
+}
+
// telegramMarkdownEntities converts the Markdown of a reply to plain text and
// Telegram message entities. It knows bold (** and __), italic (* and _),
// strikethrough (~~), inline code, fenced code blocks with an optional
return units
}
-// TelegramMarkdownText is the plain text of a Markdown reply and its Telegram
-// entities, while the conversion builds it. Units counts the UTF-16 code units
-// of text, the unit of the entity offsets and lengths.
-type TelegramMarkdownText struct {
- text strings.Builder
- units int
- entities []TelegramEntity
-}
-
-// add appends text.
-func (m *TelegramMarkdownText) add(text string) {
- m.text.WriteString(text)
-
- m.units += telegramUTF16Units(text)
-}
-
-// entity keeps entity, unless it is empty, because Telegram refuses an entity
-// of length 0.
-func (m *TelegramMarkdownText) entity(entity TelegramEntity) {
- if entity.Length > 0 {
- m.entities = append(m.entities, entity)
- }
-}
-
-// inline appends one line of Markdown with its inline marks as entities. A
-// backslash before an ASCII punctuation character makes the character plain
-// text.
-func (m *TelegramMarkdownText) inline(line string) {
- plain := 0
- index := 0
- for index < len(line) {
- if line[index] == '\\' && index+1 < len(line) && strings.IndexByte(markdownPunctuation, line[index+1]) >= 0 {
- m.add(line[plain:index])
-
- plain = index + 1
- index += 2
-
- continue
- }
-
- span, found := markdownMarkSpan(line, index)
- if !found {
- index++
- continue
- }
-
- m.add(line[plain:index])
-
- start := m.units
- if span.kind == "code" {
- m.add(span.content)
- } else {
- m.inline(span.content)
- }
-
- m.entity(TelegramEntity{
- Type: span.kind,
- Offset: start,
- Length: m.units - start,
- URL: span.url,
- })
-
- index = span.end
- plain = span.end
- }
-
- m.add(line[plain:])
-}
-
// telegramRewriteProse returns markdown with rewrite applied to each part of a
// line outside inline code and fenced code blocks. A code block that does not
// close runs to the end, as in Markdown.