带有消息实体的样式文本
Telegram 支持使用消息实体实现样式化文本。
想要发送样式化消息的客户端只需集成一个Markdown/HTML解析器,并通过遍历解析后的标签生成消息实体数组即可。
支持嵌套实体。
实体长度
即使消息本身必须使用 UTF-8 编码,在生成消息实体时也必须特别注意字符串的长度,将其视为UTF-16代码单元的数量。
示例实现:tdlib、MadelineProto。
Unicode 码位和编码
Unicode 代码点是一个介于0x00 到 1 之间的数字0x10FFFF,通常使用U+00000 到U+10FFFF1 的语法表示。Unicode
定义了一个包含 1,112,064 个可分配代码点的代码空间,其范围为U+00000 到 1。每个可分配代码点一旦由 Unicode 联盟分配,就会映射到一个特定的字符、表情符号或控制符号。U+10FFFF
Unicode 代码空间进一步细分为 17 个平面:
- 平面 1:U+0000至U+FFFF:基本多语言平面 (BMP)
- 平面 2-17:U+00000至:Unicode 标准U+10FFFF规定的多个补充平面
由于为每个字母存储一个 21 位数字会造成空间浪费,Unicode 联盟定义了多种编码方式,允许将一个代码点存储到更小的代码单元中:
UTF-8
UTF-8是一种 Unicode 编码,它允许将 21 位 Unicode 代码点存储到小至 8 位的代码单元中。MTProto 和 Bot API 在传输和接收字符串
类型的字段时使用 UTF-8。
UTF-16
UTF-16 »是一种 Unicode 编码,它允许将 21 位 Unicode 代码点存储到一个或两个 16 位代码单元中。
在 MTProto 和机器人 API 中计算实体的长度和偏移量时,会使用 UTF-16,方法是计算 UTF-16 代码单元的数量(而不是代码点)。
计算实体长度
- BMP(U+0000到U+FFFF)中的码位计数为 1,因为它们被编码成单个 UTF-16 码单元。
- 所有其他平面中的码点都计为 2,因为它们被编码成两个 UTF-16 码单元(也称为代理对)。
计算实体长度的一种简单但效率不高的方法是将文本转换为 UTF-16,然后将字节长度除以 2(=UTF-16 代码单元的数量)。
然而,由于 UTF-8 将非 BMP 平面中的码点编码为以 0 开头的 32 位代码单元,因此0b11110,无需将消息转换为 UTF-16 即可计算实体长度的更高效方法如下:
- 如果该字节标志着一个 32 位 UTF-8 代码单元(所有以 开头的字节)的开始,0b11110则计数加 2;否则,计数不变。
- 如果该字节标记 UTF-8 代码单元的开始(所有不以 开头的字节0b10),则计数加 1。
例子:
length := 0for byte in text {if (byte & 0xc0) != 0x80 {length += (byte >= 0xf0 ? 2 : 1)}}注意:实体的长度不得包含尾随换行符或空格的长度,rtrim实体在计算其长度之前的长度:但是,下一个偏移量必须包含其前面的换行符或空格的长度。
示例实现:tdlib、MadelineProto。
允许的实体
例如,可以使用以下 HTML/Markdown 别名来表示消息实体:
- messageEntityBold=><b>bold</b>,<strong>bold</strong>,**bold**
- messageEntityItalic=><i>italic</i>,<em>italic</em>*italic*
- messageEntityCode »=><code>code</code>,`code`
- 消息实体打击=><s>strike</s>,,,<strike>strike</strike><del>strike</del>~~strike~~
- messageEntityUnderline=><u>underline</u>
- messageEntityPre »=><pre language="c++">code</pre>,
以下实体也可用于提及用户:
- inputMessageEntityMentionName=>提及用户
- messageEntityMention=>@botfather(此提及由服务器端自动为消息中的 @usernames 生成)
此外,messageEntityCustomEmoji实体用于自定义表情符号 »。
还有许多其他实体可供选择,请参阅类型页面以获取完整列表»。