
Security News
/Research
Popular node-ipc npm Package Infected with Credential Stealer
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.
@gramio/format
Advanced tools
Library for formatting text for Telegram Bot API. Used under the hood by GramIO framework but it is framework-agnostic.
npm install @gramio/format
# or
bun add @gramio/format
@gramio/format builds MessageEntity objects alongside the text so you never have to track character offsets manually. All formatters compose freely — nest them as deeply as you like.
import { format, bold, italic, link, spoiler } from "@gramio/format";
const msg = format`${bold`Hi!`}
Can ${italic("you")} help ${spoiler`me`}?
Can you give me a ${link("star", "https://github.com/gramiojs/gramio")}?`;
// msg.text → the plain string
// msg.entities → ready-to-send MessageEntity[]
formatStrips leading indentation from every line (safe to indent inside your source).
import { format, bold, italic } from "@gramio/format";
format`Hello ${bold("world")}!`
// text: "Hello world!"
// entities: [{ type: "bold", offset: 6, length: 5 }]
formatSaveIndentsSame as format but preserves all whitespace exactly as written.
import { formatSaveIndents, code } from "@gramio/format";
formatSaveIndents`Run:\n ${code("bun install")}`
Every formatter accepts either a plain string, a FormattableString, or a tagged template literal.
bold("text")
bold`text`
bold(italic("text")) // nested: bold wraps italic
| Formatter | Telegram entity | Notes |
|---|---|---|
bold | bold | Cannot be combined with code / pre |
italic | italic | Cannot be combined with code / pre |
underline | underline | Cannot be combined with code / pre |
strikethrough | strikethrough | Cannot be combined with code / pre |
spoiler | spoiler | Cannot be combined with code / pre |
blockquote | blockquote | Cannot be nested |
expandableBlockquote | expandable_blockquote | Cannot be nested |
code | code | Inline monospace; cannot be combined with others |
pre(text, lang?) | pre | Code block; optional language for syntax highlight |
link(text, url) | text_link | Cannot be combined with code / pre |
mention(text, user) | text_mention | |
customEmoji(emoji, id) | custom_emoji | Requires purchased username on Fragment |
import {
bold, italic, underline, strikethrough, spoiler,
blockquote, expandableBlockquote,
code, pre, link, mention, customEmoji,
format,
} from "@gramio/format";
bold`Important`
italic`Subtle`
underline`Marked`
strikethrough`Removed`
spoiler`Secret`
blockquote`A quote from someone wise.`
expandableBlockquote`A very long quote that can be collapsed.`
code`npm install`
pre("console.log('hi')", "js")
link("GramIO", "https://gramio.dev")
mention("John", { id: 1, is_bot: false, first_name: "John" })
customEmoji("⚔️", "5222106016283378623")
// Compose freely
format`${bold("Price")}: ${italic("$42")}\nSee ${link("docs", "https://gramio.dev")}`
join — formatting arraysArray .join() discards entities. Use join instead:
import { join, bold, format } from "@gramio/format";
const items = ["apple", "banana", "cherry"];
format`Shopping list:\n${join(items, (item) => bold(item), "\n")}`;
// text: "Shopping list:\napple\nbanana\ncherry"
// entities: bold on each item at the correct offsets
The third argument is the separator (default ", "). Return null, undefined, or false from the iterator to skip an item.
markdownToFormattable — Markdown → FormattableStringConverts a Markdown string to a FormattableString with proper entities. Useful when your content comes from a Markdown source (e.g., API docs, user input).
Requires marked as a peer dependency:
npm install marked
import { markdownToFormattable } from "@gramio/format/markdown";
const result = markdownToFormattable(
"# Title\n\n**bold** and *italic*\n\n> Blockquote\n\n[link](https://gramio.dev)"
);
// result.text → "Title\n\nbold and italic\n\nBlockquote\n\nlink"
// result.entities → bold, italic, blockquote, text_link at correct offsets
| Markdown | Result |
|---|---|
**text** / __text__ | bold |
*text* / _text_ | italic |
~~text~~ | strikethrough |
`code` | inline code |
```lang\n...\n``` | pre block (with optional language) |
> text | blockquote |
[text](url) | link |
 | link (image → text link) |
# Heading … ###### Heading | bold |
- item / 1. item | list with bullet/number prefix |
htmlToFormattable — HTML → FormattableStringConverts an HTML string to a FormattableString. Designed for HTML produced by rich-text editors such as TipTap, ProseMirror, or Quill.
Requires node-html-parser as a peer dependency:
npm install node-html-parser
import { htmlToFormattable } from "@gramio/format/html";
const result = htmlToFormattable(
"<p><strong>Hello</strong> <em>world</em></p>"
);
// result.text → "Hello world"
// result.entities → [bold offset=0 len=5, italic offset=6 len=5]
| Element | Result | Notes |
|---|---|---|
<strong>, <b> | bold | |
<em>, <i> | italic | |
<u> | underline | |
<s>, <del>, <strike> | strikethrough | |
<code> | inline code | When not inside <pre> |
<pre><code class="language-js"> | pre block | Language extracted from language-* class |
<blockquote> | blockquote | Children processed recursively |
<a href="..."> | link | |
<h1> … <h6> | bold | |
<p>, <div> | transparent wrapper | Children joined with "" |
<br> | \n | |
<ul> | unordered list | Items prefixed with - |
<ol start="N"> | ordered list | Items numbered from start |
Block-level elements at the root are separated by \n\n. List items are separated by \n. Nested lists are supported and indented with \n before the sub-list.
import { htmlToFormattable } from "@gramio/format/html";
const html = `
<h1>Release notes</h1>
<p>Version <strong>2.0</strong> is out with <em>exciting</em> changes:</p>
<ul>
<li><p>New <code>htmlToFormattable</code> function</p></li>
<li><p>Performance improvements</p></li>
</ul>
<p>Read the <a href="https://gramio.dev">full docs</a>.</p>
`;
const result = htmlToFormattable(html);
// Sends correctly formatted message to Telegram with all entities intact
The FormattableString object has .text and .entities properties that map directly to Telegram's sendMessage parameters:
import { format, bold, link } from "@gramio/format";
const msg = format`Check out ${bold(link("GramIO", "https://gramio.dev"))}!`;
await bot.api.sendMessage({
chat_id: chatId,
text: msg.text,
entities: msg.entities,
});
With GramIO you can pass the FormattableString directly:
bot.on("message", (ctx) => {
ctx.send(format`Hello ${bold(ctx.from.first_name)}!`);
});
FAQs
Library for formatting text for Telegram Bot API
The npm package @gramio/format receives a total of 4,563 weekly downloads. As such, @gramio/format popularity was classified as popular.
We found that @gramio/format demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.

Security News
TeamPCP and BreachForums are promoting a Shai-Hulud supply chain attack contest with a $1,000 prize for the biggest package compromise.

Security News
Packagist urges PHP projects to update Composer after a GitHub token format change exposed some GitHub Actions tokens in CI logs.