{"_id":"@borodin/mdgram","_rev":"5-871be9566bffea6a1edc4d7b6a7d277a","name":"@borodin/mdgram","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@borodin/mdgram","version":"1.0.0","keywords":["telegram","markdown","html","streaming","bot","telegraf"],"author":{"name":"Maxim Borodin"},"license":"MIT","_id":"@borodin/mdgram@1.0.0","maintainers":[{"name":"borodin","email":"borodinmk@gmail.com"}],"homepage":"https://github.com/Borodin/mdgram#readme","bugs":{"url":"https://github.com/Borodin/mdgram/issues"},"dist":{"shasum":"8af80efb87323ab83d31d277afa82661440492d0","tarball":"https://registry.npmjs.org/@borodin/mdgram/-/mdgram-1.0.0.tgz","fileCount":7,"integrity":"sha512-bXox4asP86xuzN3YXef156qahRIfxseB3L+hePV03deQ+rLaY9kqGO11KRkIUaEQyrw2fpW91/zYCkFWZAWZpQ==","signatures":[{"sig":"MEQCIF3wVsAblHjTw1h+gntOin5pLG7M4VrJaMwko/oznCjoAiBuMhH+SnKskzJ3CMjQFvM6lJcLZYRAohYsjuWKEBosdA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@borodin%2fmdgram@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":47960},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"7a5bafbc5b00bfe47b0728df302259e8e25d416a","scripts":{"lint":"biome check .","test":"vitest run","bench":"vitest bench","build":"tsup","lint:fix":"biome check --write .","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"tsup"},"_npmUser":{"name":"borodin","email":"borodinmk@gmail.com"},"repository":{"url":"git+https://github.com/Borodin/mdgram.git","type":"git"},"_npmVersion":"11.10.0","description":"Streaming Markdown to Telegram HTML converter","directories":{},"_nodeVersion":"22.22.2","dependencies":{"marked":"^15"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","remend":"^1","vitest":"^3","typescript":"^5","@biomejs/biome":"^2.4.2","@telegraf/entity":"~0.7.0","semantic-release":"^25"},"_npmOperationalInternal":{"tmp":"tmp/mdgram_1.0.0_1776881743359_0.17437706557811183","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@borodin/mdgram","version":"1.0.1","keywords":["telegram","markdown","html","streaming","bot","telegraf"],"author":{"name":"Maxim Borodin"},"license":"MIT","_id":"@borodin/mdgram@1.0.1","maintainers":[{"name":"borodin","email":"borodinmk@gmail.com"}],"homepage":"https://github.com/Borodin/mdgram#readme","bugs":{"url":"https://github.com/Borodin/mdgram/issues"},"dist":{"shasum":"c1b3d8ffa72c929892a67ea5972aec1854ce74d9","tarball":"https://registry.npmjs.org/@borodin/mdgram/-/mdgram-1.0.1.tgz","fileCount":7,"integrity":"sha512-x/0+wBpnYNzP5+75U8Semj7JO50udSBb9E9FlMyYX5JLf8BzetL0uPFauXkQecnZ3tL+fzHA4/eQNsaSw8Giow==","signatures":[{"sig":"MEQCIHilSe+Cd66R89iaDtI5qzRho9WVzo5vlT2h85zlrvJ6AiBi469td+Ge8g/fF75hWOl5aAH6XNAa5qRyzCxisPQxPA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@borodin%2fmdgram@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":48116},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"83ad7c82a46c7717c3393a10db3011a81b354af8","scripts":{"lint":"biome check .","test":"vitest run","bench":"vitest bench","build":"tsup","lint:fix":"biome check --write .","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"tsup"},"_npmUser":{"name":"borodin","email":"borodinmk@gmail.com"},"repository":{"url":"git+https://github.com/Borodin/mdgram.git","type":"git"},"_npmVersion":"11.10.0","description":"Streaming Markdown to Telegram HTML converter","directories":{},"_nodeVersion":"22.22.2","dependencies":{"marked":"^15"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","remend":"^1","vitest":"^3","typescript":"^5","@biomejs/biome":"^2.4.2","@telegraf/entity":"~0.7.0","semantic-release":"^25"},"_npmOperationalInternal":{"tmp":"tmp/mdgram_1.0.1_1777550659103_0.2775395430140837","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@borodin/mdgram","version":"1.1.0","keywords":["telegram","markdown","html","streaming","bot","telegraf"],"author":{"name":"Maxim Borodin"},"license":"MIT","_id":"@borodin/mdgram@1.1.0","maintainers":[{"name":"borodin","email":"borodinmk@gmail.com"}],"homepage":"https://github.com/Borodin/mdgram#readme","bugs":{"url":"https://github.com/Borodin/mdgram/issues"},"dist":{"shasum":"dc3714ca227620ab18cb58f520de62e91c42fab5","tarball":"https://registry.npmjs.org/@borodin/mdgram/-/mdgram-1.1.0.tgz","fileCount":7,"integrity":"sha512-pGEXeuIfEVFsa+xBLwxU3W/EgGB40NLliU39pgGEh9lHn4NUbQh4SFiV+oN8Yc/LknVl6dOAJA8IW3B2u0z80w==","signatures":[{"sig":"MEUCIF7LdbcfJrH8+nspjPxbxAqzlWBK5UT4PVj/87Lh4iTqAiEA/sFsE4ISbu5ETSdR+/QzO0DdCyzu5ry+FMKJFKCcr8M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@borodin%2fmdgram@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":64832},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"0a45cd01f134770295e1082deb35c0bc987d83a6","scripts":{"lint":"biome check .","test":"vitest run","bench":"vitest bench","build":"tsup","lint:fix":"biome check --write .","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"tsup"},"_npmUser":{"name":"borodin","email":"borodinmk@gmail.com"},"repository":{"url":"git+https://github.com/Borodin/mdgram.git","type":"git"},"_npmVersion":"11.10.0","description":"Streaming Markdown to Telegram HTML converter","directories":{},"_nodeVersion":"22.22.3","dependencies":{"marked":"^15"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","remend":"^1","vitest":"^3","typescript":"^5","@biomejs/biome":"^2.4.2","@telegraf/entity":"~0.7.0","node-html-parser":"^7.1.0","semantic-release":"^25"},"_npmOperationalInternal":{"tmp":"tmp/mdgram_1.1.0_1782208218021_0.035778909332889075","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@borodin/mdgram","version":"1.1.1","keywords":["telegram","markdown","html","streaming","bot","telegraf"],"author":{"name":"Maxim Borodin"},"license":"MIT","_id":"@borodin/mdgram@1.1.1","maintainers":[{"name":"borodin","email":"borodinmk@gmail.com"}],"homepage":"https://github.com/Borodin/mdgram#readme","bugs":{"url":"https://github.com/Borodin/mdgram/issues"},"dist":{"shasum":"d664f5b6f8e8d4d791167e7f9a3ebfa0ba771683","tarball":"https://registry.npmjs.org/@borodin/mdgram/-/mdgram-1.1.1.tgz","fileCount":7,"integrity":"sha512-wgMLFd5aa3rYW0ReSflfFRf4cBrslUHJpS4z1mB+AKblHvkrcLUZ8gRvF5c47HfCAS1+YEtaXxUm9fCGCiGtww==","signatures":[{"sig":"MEUCIAD7YRaZSZwU+nx0cgCMaRwSezvrTIhKWnA/GmiNw5a6AiEA612usTicLBc/fuwyWzE2OKeTWeZF3CL2c33+baeu3Jc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@borodin%2fmdgram@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":67036},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"2dd0c3dcbe83e5844c0c3ebc34b7464d6fd6d4f8","scripts":{"lint":"biome check .","test":"vitest run","bench":"vitest bench","build":"tsup","lint:fix":"biome check --write .","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"tsup"},"_npmUser":{"name":"borodin","email":"borodinmk@gmail.com"},"repository":{"url":"git+https://github.com/Borodin/mdgram.git","type":"git"},"_npmVersion":"11.10.0","description":"Streaming Markdown to Telegram HTML converter","directories":{},"_nodeVersion":"22.23.0","dependencies":{"marked":"^15"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","remend":"^1","vitest":"^3","typescript":"^5","@biomejs/biome":"^2.4.2","@telegraf/entity":"~0.7.0","node-html-parser":"^7.1.0","semantic-release":"^25"},"_npmOperationalInternal":{"tmp":"tmp/mdgram_1.1.1_1782836992609_0.9967854785367067","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@borodin/mdgram","version":"1.2.0","description":"Streaming Markdown to Telegram HTML converter","author":{"name":"Maxim Borodin"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Borodin/mdgram.git"},"homepage":"https://github.com/Borodin/mdgram#readme","bugs":{"url":"https://github.com/Borodin/mdgram/issues"},"keywords":["telegram","markdown","html","streaming","bot","telegraf"],"engines":{"node":">=18"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"publishConfig":{"access":"public","provenance":true},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","lint":"biome check .","typecheck":"tsc --noEmit","lint:fix":"biome check --write .","bench":"vitest bench","prepublishOnly":"tsup"},"dependencies":{"marked":"^15"},"devDependencies":{"@biomejs/biome":"^2.4.2","@telegraf/entity":"~0.7.0","node-html-parser":"^7.1.0","remend":"^1","semantic-release":"^25","tsup":"^8","typescript":"^5","vitest":"^3"},"gitHead":"72733d3ed2a186797919cbf8faf6ea7e3bf2cc5d","_id":"@borodin/mdgram@1.2.0","_nodeVersion":"22.23.1","_npmVersion":"11.10.0","dist":{"integrity":"sha512-ZgXPyeQSoTojZeUvXMYkzsrg3BS/qQ/EXizZpgmPgoLCGxeLLUCdxjJwbwa4zjjNRD5hUnu/ioSgNjKfW0290A==","shasum":"0fb735a292130f60384588b2b185d2b460b0726a","tarball":"https://registry.npmjs.org/@borodin/mdgram/-/mdgram-1.2.0.tgz","fileCount":7,"unpackedSize":69033,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@borodin%2fmdgram@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDZzctPFz5jOcMLtNi7Iksa2+wQH1Leg5KkrjG/O/x8CQIhANOFmI67Ktqt0KOk/JgqdaieRic5hOTnpzY3YcTW60Rh"}]},"_npmUser":{"name":"borodin","email":"borodinmk@gmail.com"},"directories":{},"maintainers":[{"name":"borodin","email":"borodinmk@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mdgram_1.2.0_1783097891661_0.9760958110609652"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-22T18:15:43.249Z","modified":"2026-07-03T16:58:12.113Z","1.0.0":"2026-04-22T18:15:43.503Z","1.0.1":"2026-04-30T12:04:19.242Z","1.1.0":"2026-06-23T09:50:18.174Z","1.1.1":"2026-06-30T16:29:52.749Z","1.2.0":"2026-07-03T16:58:11.793Z"},"bugs":{"url":"https://github.com/Borodin/mdgram/issues"},"author":{"name":"Maxim Borodin"},"license":"MIT","homepage":"https://github.com/Borodin/mdgram#readme","keywords":["telegram","markdown","html","streaming","bot","telegraf"],"repository":{"type":"git","url":"git+https://github.com/Borodin/mdgram.git"},"description":"Streaming Markdown to Telegram HTML converter","maintainers":[{"name":"borodin","email":"borodinmk@gmail.com"}],"readme":"# mdgram\n\nStreaming Markdown to Telegram HTML converter. Safely converts incomplete Markdown (token-by-token from LLMs) into valid Telegram HTML at every step.\n\nSupports both classic Telegram HTML (`mdgram`) and the Bot API 10.1 Rich HTML format (`mdgramRich`).\n\n## Install\n\n```bash\nnpm install @borodin/mdgram\n```\n\n## Usage\n\n### Classic Telegram HTML\n\n```ts\nimport { mdgram } from \"@borodin/mdgram\";\n\nmdgram(\"Hello **world**\");\n// \"Hello <b>world</b>\"\n\n// Handles incomplete markdown (streaming)\nmdgram(\"Hello **wor\");\n// \"Hello <b>wor</b>\"\n```\n\n### Rich HTML (Bot API 10.1+)\n\n```ts\nimport { mdgramRich } from \"@borodin/mdgram\";\n\nmdgramRich(\"# Title\\n\\n- item 1\\n- item 2\");\n// \"<h1>Title</h1>\\n<ul>\\n<li>item 1</li>\\n<li>item 2</li>\\n</ul>\"\n\n// LaTeX\nmdgramRich(\"Euler's formula: $e^{i\\\\pi} + 1 = 0$\");\n// \"Euler&#39;s formula: <tg-math>e^{i\\pi} + 1 = 0</tg-math>\"\n\n// Streaming — every prefix is valid Rich HTML\nmdgramRich(\"$e^{i\\\\pi\");\n// \"<tg-math>e^{i\\pi}</tg-math>\"\n```\n\nUse `sendRichMessage` / `sendRichMessageDraft` to send Rich HTML to Telegram.\n\n#### `paragraphMode: \"br\"` — workaround for clients without `<p>` margins\n\nSome Telegram clients currently render `<p>` without vertical margins, so adjacent\nparagraphs visually merge. Until the client fix rolls out, you can opt into a\n`<br><br>`-based layout that looks identical on all clients:\n\n```ts\nmdgramRich(\"First.\\n\\nSecond.\", { paragraphMode: \"br\" });\n// \"First.<br><br>Second.\"  (default \"p\" mode: \"<p>First.</p>\\n<p>Second.</p>\")\n```\n\n`<br><br>` is inserted only between adjacent paragraphs; boundaries with block\nelements (headings, lists, tables, etc.) are left as is. The default `\"p\"` mode\nfollows the Rich HTML spec.\n\n## Supported formatting\n\n### `mdgram` — classic Telegram HTML\n\n| Markdown | Output |\n|---|---|\n| `**bold**` | `<b>bold</b>` |\n| `*italic*` | `<i>italic</i>` |\n| `` `code` `` | `<code>code</code>` |\n| ` ```lang\\n...\\n``` ` | `<pre><code class=\"language-lang\">...</code></pre>` |\n| `[text](url)` | `<a href=\"url\">text</a>` |\n| `~~strike~~` | `<s>strike</s>` |\n| `\\|\\|spoiler\\|\\|` | `<tg-spoiler>spoiler</tg-spoiler>` |\n| `> quote` | `<blockquote>quote</blockquote>` |\n| `# heading` | `<b>heading</b>` |\n| `- item` / `1. item` | `• item` / `1. item` |\n\n### `mdgramRich` — Rich HTML (superset)\n\nEverything from `mdgram`, plus:\n\n| Markdown | Output |\n|---|---|\n| `# H1` … `###### H6` | `<h1>` … `<h6>` |\n| `- item` / `1. item` | `<ul><li>` / `<ol><li>` |\n| `- [x] task` | `<li><input type=\"checkbox\" checked>` |\n| `\\| table \\|` | `<table><tr><th/td>` |\n| `==highlight==` | `<mark>highlight</mark>` |\n| `$formula$` | `<tg-math>formula</tg-math>` |\n| `$$formula$$` | `<tg-math-block>formula</tg-math-block>` |\n| ` ```math\\nformula\\n``` ` | `<tg-math-block>formula</tg-math-block>` |\n| `\\(formula\\)` | `<tg-math>formula</tg-math>` |\n| `\\[formula\\]` | `<tg-math-block>formula</tg-math-block>` |\n| `---` | `<hr/>` |\n| `![alt](url)` | `<img src=\"url\"/>` |\n| `![alt](url \"caption\")` | `<figure><img src=\"url\"/><figcaption>caption</figcaption></figure>` |\n| Raw `<tg-spoiler>`, `<tg-emoji>`, `<tg-thinking>`, `<u>`, `<ins>`, `<sub>`, `<sup>`, `<cite>`, `<details>`, `<aside>`, `<footer>` | passed through verbatim |\n\nCurrency amounts like `$100` are never misidentified as LaTeX.\n\n## Truncation\n\nTelegram limits message text to **4096** and captions to **1024** UTF-16 code units. Rich messages support up to **32768** characters.\n\n```ts\nimport { mdgram, mdgramRich, MESSAGE_LIMIT, CAPTION_LIMIT, RICH_MESSAGE_LIMIT } from \"@borodin/mdgram\";\n\nmdgram(longMarkdown, { maxLength: MESSAGE_LIMIT });\nmdgram(longMarkdown, { maxLength: CAPTION_LIMIT });\nmdgramRich(longMarkdown, { maxLength: RICH_MESSAGE_LIMIT });\n```\n\nWhen truncated, output ends with `…` and all open tags are properly closed.\n\n## LLM system prompt\n\nFor `mdgram`:\n\n    Format responses using Markdown:\n    - **bold**, *italic*, ~~strikethrough~~\n    - `inline code` and fenced code blocks (```)\n    - [links](url), ||spoilers||, > blockquotes\n    - Lists: - item, 1. item\n    Do NOT use images, HTML tags, or LaTeX.\n\nFor `mdgramRich`:\n\n    Format responses using Markdown:\n    - **bold**, *italic*, ~~strikethrough~~, ==highlight==\n    - `inline code`, fenced code blocks (```), math blocks (```math)\n    - $inline LaTeX$, $$block LaTeX$$\n    - [links](url), ||spoilers||, > blockquotes\n    - Headings: # H1 through ###### H6\n    - Lists: - item, 1. item, - [x] task list\n    - Tables: | col | col |\n    - Horizontal rule: ---\n    - Images: ![caption](url) or ![caption](url \"caption text\")\n    Do NOT use raw HTML tags.\n\n## How it works\n\n1. **[remend](https://npm.im/remend)** auto-closes incomplete Markdown tokens (bold, italic, code, spoilers, LaTeX, etc.)\n2. **[marked](https://npm.im/marked)** parses the completed Markdown with a custom Telegram renderer\n3. Output is valid Telegram HTML at every step — safe to stream directly to `editMessageText` or `sendRichMessageDraft`\n\n## License\n\nMIT\n","readmeFilename":"README.md"}