Skip to content

Rich Messages: <sup> and <sub> inside a <tg-spoiler> are drawn outside the spoiler cover #2286

Description

@olsh

Description

In a Rich Message (Bot API 10.1 sendRichMessage), a <tg-spoiler> containing a <sup> or a
<sub> covers the normal-height text but not the raised or lowered run. The superscript is
painted above the cover and the subscript below it, both fully legible without tapping, and both
overlapping the neighbouring line of the message.

Image

Only the shifted run escapes — the rest of the same spoiler is covered correctly, and a spoiler
containing <b> or <a href> in the same position is covered in full.

The server parses the markup correctly — its own echo of the sent message nests the superscript
inside the spoiler:

{"type": "spoiler", "text": ["hidden text", {"type": "superscript", "text": "SUP"}]}

so this is client rendering, not parsing.

Expected behavior

Everything inside the spoiler is covered, including a superscript or a subscript.

Actual behavior

The superscript/subscript renders outside the cover and is readable straight away. The cover appears
to be sized to the normal line box, so a glyph shifted above or below that box falls outside the
covered area — which is also why the escaped text overlaps the adjacent line.

Steps to reproduce

Run the script with a bot token and your own numeric user id. It sends two messages. Do not tap
them
— a revealed spoiler shows its text in the clear anyway.

#!/usr/bin/env python3
"""Rich Message: <sup>/<sub> inside a <tg-spoiler> render outside the cover. Stdlib only.

    BOT_TOKEN=123:ABC CHAT_ID=<your id> python3 repro.py

Send the bot a message first so it may reply to you.
"""

import json
import os
import urllib.request

SPECIMENS = [
    "sup <tg-spoiler>hidden text<sup>SUP</sup></tg-spoiler>",
    "sub <tg-spoiler>hidden text<sub>SUB</sub></tg-spoiler>",
]


def main():
    url = "https://api.telegram.org/bot{}/sendRichMessage".format(os.environ["BOT_TOKEN"])
    for html in SPECIMENS:
        payload = {
            "chat_id": os.environ["CHAT_ID"],
            "rich_message": {"html": html, "skip_entity_detection": True},
        }
        req = urllib.request.Request(
            url, json.dumps(payload).encode(), {"Content-Type": "application/json"}
        )
        urllib.request.urlopen(req)


if __name__ == "__main__":
    main()

In both messages hidden text is covered, while SUP is readable above the cover and SUB below
it.

Environment

  • Device: iPhone 14 Pro Max
  • iOS: 26.6
  • Telegram for iOS: 12.9.2
  • Text Size: default (reproduces without changing any appearance setting)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions