@borodin/mdgram

中文文档
1.2.0发布于 2026/07/04MITTypeScriptESM + CJS构建来源已验证近 30 天下载 3608

Streaming Markdown to Telegram HTML converter

原始使用文档
文档目录11 节
  1. Install
  2. Usage
  3. Classic Telegram HTML
  4. Rich HTML (Bot API 10.1+)
  5. Supported formatting
  6. mdgram — classic Telegram HTML
  7. mdgramRich — Rich HTML (superset)
  8. Truncation
  9. LLM system prompt
  10. How it works
  11. License

mdgram

Streaming Markdown to Telegram HTML converter. Safely converts incomplete Markdown (token-by-token from LLMs) into valid Telegram HTML at every step.

Supports both classic Telegram HTML (mdgram) and the Bot API 10.1 Rich HTML format (mdgramRich).

Install

npm install @borodin/mdgram

Usage

Classic Telegram HTML

import { mdgram } from "@borodin/mdgram";

mdgram("Hello **world**");
// "Hello <b>world</b>"

// Handles incomplete markdown (streaming)
mdgram("Hello **wor");
// "Hello <b>wor</b>"

Rich HTML (Bot API 10.1+)

import { mdgramRich } from "@borodin/mdgram";

mdgramRich("# Title\n\n- item 1\n- item 2");
// "<h1>Title</h1>\n<ul>\n<li>item 1</li>\n<li>item 2</li>\n</ul>"

// LaTeX
mdgramRich("Euler's formula: $e^{i\\pi} + 1 = 0$");
// "Euler&#39;s formula: <tg-math>e^{i\pi} + 1 = 0</tg-math>"

// Streaming — every prefix is valid Rich HTML
mdgramRich("$e^{i\\pi");
// "<tg-math>e^{i\pi}</tg-math>"

Use sendRichMessage / sendRichMessageDraft to send Rich HTML to Telegram.

paragraphMode: "br" — workaround for clients without <p> margins

Some Telegram clients currently render <p> without vertical margins, so adjacent paragraphs visually merge. Until the client fix rolls out, you can opt into a <br><br>-based layout that looks identical on all clients:

mdgramRich("First.\n\nSecond.", { paragraphMode: "br" });
// "First.<br><br>Second."  (default "p" mode: "<p>First.</p>\n<p>Second.</p>")

<br><br> is inserted only between adjacent paragraphs; boundaries with block elements (headings, lists, tables, etc.) are left as is. The default "p" mode follows the Rich HTML spec.

Supported formatting

mdgram — classic Telegram HTML

MarkdownOutput
**bold**<b>bold</b>
*italic*<i>italic</i>
`code`<code>code</code>
```lang\n...\n```<pre><code class="language-lang">...</code></pre>
[text](url)<a href="url">text</a>
~~strike~~<s>strike</s>
||spoiler||<tg-spoiler>spoiler</tg-spoiler>
> quote<blockquote>quote</blockquote>
# heading<b>heading</b>
- item / 1. item• item / 1. item

mdgramRich — Rich HTML (superset)

Everything from mdgram, plus:

MarkdownOutput
# H1 … ###### H6<h1> … <h6>
- item / 1. item<ul><li> / <ol><li>
- [x] task<li><input type="checkbox" checked>
| table |<table><tr><th/td>
==highlight==<mark>highlight</mark>
$formula$<tg-math>formula</tg-math>
$$formula$$<tg-math-block>formula</tg-math-block>
```math\nformula\n```<tg-math-block>formula</tg-math-block>
\(formula\)<tg-math>formula</tg-math>
\[formula\]<tg-math-block>formula</tg-math-block>
---<hr/>
![alt](url)<img src="url"/>
![alt](url "caption")<figure><img src="url"/><figcaption>caption</figcaption></figure>
Raw <tg-spoiler>, <tg-emoji>, <tg-thinking>, <u>, <ins>, <sub>, <sup>, <cite>, <details>, <aside>, <footer>passed through verbatim

Currency amounts like $100 are never misidentified as LaTeX.

Truncation

Telegram limits message text to 4096 and captions to 1024 UTF-16 code units. Rich messages support up to 32768 characters.

import { mdgram, mdgramRich, MESSAGE_LIMIT, CAPTION_LIMIT, RICH_MESSAGE_LIMIT } from "@borodin/mdgram";

mdgram(longMarkdown, { maxLength: MESSAGE_LIMIT });
mdgram(longMarkdown, { maxLength: CAPTION_LIMIT });
mdgramRich(longMarkdown, { maxLength: RICH_MESSAGE_LIMIT });

When truncated, output ends with … and all open tags are properly closed.

LLM system prompt

For mdgram:

Format responses using Markdown:
- **bold**, *italic*, ~~strikethrough~~
- `inline code` and fenced code blocks (```)
- [links](url), ||spoilers||, > blockquotes
- Lists: - item, 1. item
Do NOT use images, HTML tags, or LaTeX.

For mdgramRich:

Format responses using Markdown:
- **bold**, *italic*, ~~strikethrough~~, ==highlight==
- `inline code`, fenced code blocks (```), math blocks (```math)
- $inline LaTeX$, $$block LaTeX$$
- [links](url), ||spoilers||, > blockquotes
- Headings: # H1 through ###### H6
- Lists: - item, 1. item, - [x] task list
- Tables: | col | col |
- Horizontal rule: ---
- Images: ![caption](url) or ![caption](url "caption text")
Do NOT use raw HTML tags.

How it works

  1. remend auto-closes incomplete Markdown tokens (bold, italic, code, spoilers, LaTeX, etc.)
  2. marked parses the completed Markdown with a custom Telegram renderer
  3. Output is valid Telegram HTML at every step — safe to stream directly to editMessageText or sendRichMessageDraft

License

MIT

版本与发布记录

@borodin/mdgram 共发布 5 个版本,首次发布于 2026/04/23;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.2.0latest2026/07/044 个月前
1.1.12026/07/014 个月前
1.1.02026/06/234 个月前
1.0.12026/04/306 个月前
1.0.02026/04/236 个月前

关于 @borodin/mdgram 的常见问题

@borodin/mdgram 是什么?

Streaming Markdown to Telegram HTML converter

如何安装 @borodin/mdgram?

在项目目录运行 npm install @borodin/mdgram,或使用 pnpm add / yarn add / bun add。

@borodin/mdgram 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@borodin/mdgram 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@borodin/mdgram 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@borodin/mdgram 可以商用吗?

@borodin/mdgram 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@borodin/mdgram 的下载量有多少?

根据 npm 官方下载统计,@borodin/mdgram 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,608 次,日均约 120 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@borodin/mdgram 还在维护吗?

最新版本 1.2.0 发布于 2026/07/04(4 个月前);至今共发布 5 个版本,其中过去 12 个月发布了 5 个;首次发布于 2026/04/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。