Skip to content

Commit d5b56d4

Browse files
committed
Update Rich Messages and Text Formatting
1 parent 65f97ed commit d5b56d4

1 file changed

Lines changed: 151 additions & 32 deletions

File tree

src/rich-messages-and-text-formatting.md

Lines changed: 151 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,57 +4,180 @@ parent: /#walkthrough
44
prev: /inline-queries
55
---
66

7-
Messages and media captions can contain formatting such as bold text, links, spoilers, and code. MTKruto can parse HTML or Markdown into Telegram message entities.
7+
MTKruto supports both rich messages and formatted text messages. Rich messages contain structured page content such as headings, paragraphs, lists, tables, and media. Regular messages and media captions remain strings, with formatting described by message entities.
88

9-
## HTML
9+
## Rich Messages
10+
11+
Send a rich message with {{ "sendRichText" |> m }} and an {{ "InputRichText" |> t }}. The input can be expressed in three ways:
12+
13+
- `blocks` provides the page structure and nested text components directly.
14+
- `html` lets bots provide the page as HTML.
15+
- `markdown` lets bots provide the page as Markdown.
16+
17+
Choose blocks when the content is assembled programmatically or when you want the TypeScript type system to check its structure. HTML and Markdown are convenient when the content already exists as markup.
18+
19+
### Page Blocks
1020

11-
Set `parseMode` to `"HTML"` for a message that contains supported HTML tags.
21+
The `blocks` variant accepts an array of {{ "InputPageBlock" |> t }} objects. Text inside a block is represented by nested {{ "RichTextComponent" |> t }} objects, so inline styles do not rely on offsets or escaped markup.
1222

1323
```ts
14-
await client.sendMessage(
15-
chatId,
16-
'Hello, <b>world</b>! Visit <a href="https://mtkru.to">MTKruto</a>.',
17-
{ parseMode: "HTML" },
18-
);
24+
await client.sendRichText(chatId, {
25+
type: "blocks",
26+
blocks: [
27+
{
28+
type: "heading1",
29+
text: { type: "plain", text: "Release notes" },
30+
},
31+
{
32+
type: "paragraph",
33+
text: {
34+
type: "concatenate",
35+
components: [
36+
{ type: "plain", text: "Version " },
37+
{
38+
type: "bold",
39+
text: { type: "plain", text: "1.0" },
40+
},
41+
{ type: "plain", text: " is ready." },
42+
],
43+
},
44+
},
45+
{
46+
type: "list",
47+
items: [
48+
{
49+
type: "text",
50+
isCheckbox: true,
51+
isChecked: true,
52+
text: { type: "plain", text: "Faster startup" },
53+
},
54+
{
55+
type: "text",
56+
isCheckbox: true,
57+
isChecked: false,
58+
text: { type: "plain", text: "New themes" },
59+
},
60+
],
61+
},
62+
],
63+
});
1964
```
2065

21-
Common supported tags include `<b>`, `<i>`, `<u>`, `<s>`, `<code>`, `<pre>`, `<blockquote>`, and `<a>`.
66+
Blocks can also contain media directly. MTKruto accepts any supported {{ "FileSource" |> t }} and uploads it as part of the rich message.
2267

23-
## Markdown
68+
```ts
69+
await client.sendRichText(chatId, {
70+
type: "blocks",
71+
blocks: [
72+
{
73+
type: "photo",
74+
photo: "./release-banner.jpg",
75+
caption: {
76+
text: { type: "plain", text: "Version 1.0" },
77+
credit: { type: "empty" },
78+
},
79+
},
80+
],
81+
});
82+
```
2483

25-
Set `parseMode` to `"Markdown"` to use Markdown formatting.
84+
### HTML
85+
86+
The `html` variant sends an HTML document for Telegram to turn into page blocks. It is available to bots.
2687

2788
```ts
89+
await client.sendRichText(chatId, {
90+
type: "html",
91+
html: `
92+
<h1>Release notes</h1>
93+
<p>Version <b>1.0</b> is ready.</p>
94+
<ul>
95+
<li>Faster startup</li>
96+
<li>New themes</li>
97+
</ul>
98+
`,
99+
});
100+
```
101+
102+
This is separate from the `"HTML"` parse mode used by regular text messages: no `parseMode` option is involved.
103+
104+
### Markdown
105+
106+
The `markdown` variant does the same with a Markdown document. It is also available to bots.
107+
108+
```ts
109+
await client.sendRichText(chatId, {
110+
type: "markdown",
111+
markdown: `
112+
# Release notes
113+
114+
Version **1.0** is ready.
115+
116+
- Faster startup
117+
- New themes
118+
`,
119+
});
120+
```
121+
122+
HTML and Markdown inputs can include a `media` array of {{ "InputRichTextMedia" |> t }} objects. Each item associates an identifier used in the markup with a photo, video, animation, audio, or voice message input.
123+
124+
```ts
125+
await client.sendRichText(chatId, {
126+
type: "markdown",
127+
markdown,
128+
media: [
129+
{
130+
id: "release-banner",
131+
media: {
132+
type: "photo",
133+
photo: "./release-banner.jpg",
134+
},
135+
},
136+
],
137+
});
138+
```
139+
140+
All three variants accept `isRtl`. They also accept `isAutomaticLinkDetectionDisabled` when URLs, email addresses, and similar text should not automatically become interactive blocks.
141+
142+
## Formatting Regular Messages
143+
144+
Messages and media captions can contain bold text, links, spoilers, code, and other inline formatting. This formatting is represented by {{ "MessageEntity" |> t }} objects. MTKruto can create the entities by parsing HTML or Markdown, or you can provide them directly.
145+
146+
### HTML and Markdown
147+
148+
Set `parseMode` on a method call when its text contains supported markup.
149+
150+
```ts
151+
await client.sendMessage(
152+
chatId,
153+
'Hello, <b>world</b>! Visit <a href="https://mtkru.to">MTKruto</a>.',
154+
{ parseMode: "HTML" },
155+
);
156+
28157
await ctx.reply(
29158
"Hello, *world*\\! Visit [MTKruto](https://mtkru.to)\\.",
30159
{ parseMode: "Markdown" },
31160
);
32161
```
33162

34-
Characters with special meaning must be escaped when they should appear literally. Be especially careful when inserting user-provided text into HTML or Markdown.
35-
36-
## Default Parse Mode
163+
Characters with special meaning must be escaped when they should appear literally. Escape or otherwise sanitize user-provided text before inserting it into markup.
37164

38-
A default parse mode can be configured when constructing the client. It is then used whenever a method does not specify one.
165+
A default parse mode can be configured on the client and overridden per call. Pass `null` to keep the text unchanged.
39166

40167
```ts
41168
const client = new Client({
42169
parseMode: "HTML",
43170
/* ... */
44171
});
45-
```
46172

47-
Override the default for a single message by passing another parse mode, or pass `null` to disable parsing.
48-
49-
```ts
50173
await client.sendMessage(chatId, "<b>This remains unchanged.</b>", {
51174
parseMode: null,
52175
});
53176
```
54177

55-
## Explicit Entities
178+
### Explicit Entities
56179

57-
You can provide {{ "MessageEntity" |> t }} objects instead of using markup. Entity offsets and lengths use UTF-16 code units, which is how JavaScript measures string length.
180+
Pass entities directly when the text is assembled programmatically. Entity offsets and lengths use UTF-16 code units, which is how JavaScript measures string length.
58181

59182
```ts
60183
const text = "Important message";
@@ -71,14 +194,14 @@ await client.sendMessage(chatId, text, {
71194
});
72195
```
73196

74-
Explicit entities are useful when text is assembled dynamically because formatting does not depend on escaping markup characters.
197+
## Entity and Block Builders
75198

76-
## Entity Builders
77-
78-
The [@mtkruto/fmt](https://jsr.io/@mtkruto/fmt) package provides chainable builders that create text and entities together, keeping their offsets aligned as text is added.
199+
The [@mtkruto/fmt](https://jsr.io/@mtkruto/fmt) package provides chainable builders for message entities and rich-message blocks. It is useful when content is assembled dynamically and you do not want to maintain entity offsets or deeply nested objects by hand.
79200

80201
{{ "jsr:@mtkruto/fmt" |> install }}
81202

203+
Build regular message text and its entities together with the `entities` export:
204+
82205
```ts
83206
import { text } from "@mtkruto/fmt/entities";
84207

@@ -93,13 +216,7 @@ await client.sendMessage(chatId, formatted.rawText, {
93216
});
94217
```
95218

96-
The package also provides builders for secret-chat entities through its `secret-entities` export.
97-
98-
## Rich Messages
99-
100-
Rich messages are built from page blocks and can contain headings, paragraphs, lists, tables, media, and other structured content. Use {{ "sendRichText" |> m }} with an {{ "InputRichText" |> t }} made from blocks, HTML, or Markdown.
101-
102-
The `rich` export of `@mtkruto/fmt` makes it easier to construct blocks and nested text components.
219+
Build page blocks and nested rich-text components with the `rich` export:
103220

104221
```ts
105222
import { bold, heading1 } from "@mtkruto/fmt/rich";
@@ -112,3 +229,5 @@ await client.sendRichText(chatId, {
112229
blocks: blocks.toArray(),
113230
});
114231
```
232+
233+
The package also provides builders for secret-chat entities through its `secret-entities` export.

0 commit comments

Comments
 (0)