1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-07-03 00:25:29 +00:00

Rename RichText source to rawText and move it into members

Replace the RichText.source extension property (a when over every subtype)
with a rawText member declared on RichText and implemented directly by each
inheritor: RichTextPlain.rawText = text, the wrapping entities delegate to
text.rawText, and custom emoji / mathematical expression / anchor fall back
to their own representation. Update the RichBlockPreformatted and media
markdown builders and the formatting tests accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 21:59:18 +06:00
parent 8acd7453a6
commit 88a54350df
7 changed files with 70 additions and 45 deletions

View File

@@ -45,7 +45,7 @@ internal fun richMediaContainerHtml(tag: String, blocks: List<RichBlock>, captio
}
internal fun richMediaMarkdown(source: String, caption: RichBlockCaption?): String =
caption?.let { "![](" + source + " \"" + it.text.source + "\")" } ?: "![]($source)"
caption?.let { "![](" + source + " \"" + it.text.rawText + "\")" } ?: "![]($source)"
internal fun richMediaHtml(tag: String, source: String, spoiler: Boolean, selfClosing: Boolean, caption: RichBlockCaption?): String {
val spoilerAttribute = if (spoiler) " tg-spoiler" else ""

View File

@@ -109,7 +109,7 @@ data class RichBlockPreformatted(
companion object {
const val TYPE = "pre"
fun markdown(text: RichText, language: String?): String = "```" + (language ?: "") + "\n" + text.source + "\n```"
fun markdown(text: RichText, language: String?): String = "```" + (language ?: "") + "\n" + text.rawText + "\n```"
fun html(text: RichText, language: String?): String =
language?.let { "<pre><code class=\"language-$it\">${text.html}</code></pre>" } ?: "<pre>${text.html}</pre>"
}

View File

@@ -20,6 +20,13 @@ import kotlinx.serialization.json.*
@Serializable(RichTextSerializer::class)
@ClassCastsIncluded
sealed interface RichText {
/**
* Plain (unformatted) text of this [RichText]. For [RichTextEntity]s without an inner [RichText] it falls back to
* the most meaningful textual representation: alternative text for custom emojis, the expression for mathematical
* expressions and an empty string for anchors.
*/
val rawText: String
/**
* [Rich Markdown style](https://core.telegram.org/bots/api#rich-markdown-style) representation of this [RichText].
*/
@@ -38,6 +45,7 @@ sealed interface RichText {
data class RichTextPlain(
val text: String
) : RichText {
override val rawText: String = text
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -54,6 +62,7 @@ data class RichTextPlain(
data class RichTextGroup(
val parts: List<RichText>
) : RichText {
override val rawText: String = parts.joinToString(separator = "") { it.rawText }
override val markdown: String = markdown(parts)
override val html: String = html(parts)

View File

@@ -41,6 +41,7 @@ data class RichTextBold(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -65,6 +66,7 @@ data class RichTextItalic(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -89,6 +91,7 @@ data class RichTextUnderline(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -113,6 +116,7 @@ data class RichTextStrikethrough(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -137,6 +141,7 @@ data class RichTextSpoiler(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -161,6 +166,7 @@ data class RichTextSubscript(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -185,6 +191,7 @@ data class RichTextSuperscript(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -209,6 +216,7 @@ data class RichTextMarked(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -233,12 +241,13 @@ data class RichTextCode(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
companion object {
const val TYPE = "code"
fun markdown(text: RichText): String = "`${text.source}`"
fun markdown(text: RichText): String = "`${text.rawText}`"
fun html(text: RichText): String = "<code>${text.html}</code>"
}
}
@@ -261,6 +270,7 @@ data class RichTextDateTime(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, unixTime, dateTimeFormat)
override val html: String = html(text, unixTime, dateTimeFormat)
@@ -289,6 +299,7 @@ data class RichTextTextMention(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, user)
override val html: String = html(text, user)
@@ -317,6 +328,7 @@ data class RichTextCustomEmoji(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = alternativeText
override val markdown: String = markdown(customEmojiId, alternativeText)
override val html: String = html(customEmojiId, alternativeText)
@@ -343,6 +355,7 @@ data class RichTextMathematicalExpression(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = expression
override val markdown: String = markdown(expression)
override val html: String = html(expression)
@@ -369,6 +382,7 @@ data class RichTextUrl(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, url)
override val html: String = html(text, url)
@@ -395,6 +409,7 @@ data class RichTextEmailAddress(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, emailAddress)
override val html: String = html(text, emailAddress)
@@ -421,6 +436,7 @@ data class RichTextPhoneNumber(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, phoneNumber)
override val html: String = html(text, phoneNumber)
@@ -447,6 +463,7 @@ data class RichTextBankCardNumber(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -473,6 +490,7 @@ data class RichTextMention(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -499,6 +517,7 @@ data class RichTextHashtag(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -525,6 +544,7 @@ data class RichTextCashtag(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -551,6 +571,7 @@ data class RichTextBotCommand(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text)
override val html: String = html(text)
@@ -575,6 +596,7 @@ data class RichTextAnchor(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = ""
override val markdown: String = markdown(name)
override val html: String = html(name)
@@ -601,6 +623,7 @@ data class RichTextAnchorLink(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, anchorName)
override val html: String = html(text, anchorName)
@@ -627,6 +650,7 @@ data class RichTextReference(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, name)
override val html: String = html(text, name)
@@ -653,6 +677,7 @@ data class RichTextReferenceLink(
@SerialName(typeField)
override val type: String = TYPE
override val rawText: String = text.rawText
override val markdown: String = markdown(text, referenceName)
override val html: String = html(text, referenceName)

View File

@@ -21,39 +21,3 @@ fun String.escapeRichMarkdown(): String = buildString {
append(character)
}
}
/**
* Plain (unformatted) text of this [RichText]. For [RichTextEntity]s without an inner [RichText] it falls back to the
* most meaningful textual representation: alternative text for custom emojis, the expression for mathematical
* expressions and an empty string for anchors.
*/
val RichText.source: String
get() = when (this) {
is RichTextPlain -> text
is RichTextGroup -> parts.joinToString(separator = "") { it.source }
is RichTextCustomEmoji -> alternativeText
is RichTextMathematicalExpression -> expression
is RichTextAnchor -> ""
is RichTextBold -> text.source
is RichTextItalic -> text.source
is RichTextUnderline -> text.source
is RichTextStrikethrough -> text.source
is RichTextSpoiler -> text.source
is RichTextSubscript -> text.source
is RichTextSuperscript -> text.source
is RichTextMarked -> text.source
is RichTextCode -> text.source
is RichTextDateTime -> text.source
is RichTextTextMention -> text.source
is RichTextUrl -> text.source
is RichTextEmailAddress -> text.source
is RichTextPhoneNumber -> text.source
is RichTextBankCardNumber -> text.source
is RichTextMention -> text.source
is RichTextHashtag -> text.source
is RichTextCashtag -> text.source
is RichTextBotCommand -> text.source
is RichTextAnchorLink -> text.source
is RichTextReference -> text.source
is RichTextReferenceLink -> text.source
}

View File

@@ -209,13 +209,13 @@ class RichTextFormattingTest {
}
@Test
fun sourceExtractsPlainText() {
assertEquals("x", RichTextBold(RichTextPlain("x")).source)
assertEquals("alt", RichTextCustomEmoji(CustomEmojiId("1"), "alt").source)
assertEquals("e", RichTextMathematicalExpression("e").source)
fun rawTextExtractsPlainText() {
assertEquals("x", RichTextBold(RichTextPlain("x")).rawText)
assertEquals("alt", RichTextCustomEmoji(CustomEmojiId("1"), "alt").rawText)
assertEquals("e", RichTextMathematicalExpression("e").rawText)
assertEquals(
"a b",
RichTextGroup(listOf(RichTextPlain("a "), RichTextBold(RichTextPlain("b")))).source
RichTextGroup(listOf(RichTextPlain("a "), RichTextBold(RichTextPlain("b")))).rawText
)
}
}