@yaebal/fmt
html and md tagged templates that parse Telegram's markup subset into
real entities — with interpolations auto-escaped so user input can never break your formatting.
install
pnpm add @yaebal/fmtwhy
core ships format (entity builders: bold(), link()). @yaebal/fmt adds the parser angle — write familiar
markdown or HTML, get the same { text, entities } back. Both avoid parse_mode entirely, so there is nothing to escape.
import { html, md } from "@yaebal/fmt";
// parses into MessageEntity[] — no parse_mode, nothing to escape
ctx.send(html`<b>hello</b> <a href="https://yaebal.dev">docs</a>`);
ctx.send(md`**hello** and \`code\` and ||spoiler||`);auto-escaped interpolation
this is the headline. a $${string} interpolation is inserted as literal text — its *, <, ` are never
re-parsed as markup. user input cannot inject entities or break the message.
const name = "<script>**hax**";
// the interpolation is inserted as LITERAL text — never re-parsed
ctx.send(html`hi <b>${name}</b>`);
// → text: "hi <script>**hax**", one bold entity. no injection possible.composes with core. if an interpolation is itself a
FormatResult (e.g. from bold() / link()), it's merged in with its offsets shifted —
so dynamic links don't need attribute parsing, just drop in a link().import { html } from "@yaebal/fmt";
import { bold, link } from "@yaebal/core";
// a FormatResult sub (from core's builders) is MERGED, offsets shifted
ctx.send(html`welcome ${bold(user.name)} — ${link("open", url)}`);html tags
b / strong → bold
i / em → italic
u / ins → underline
s / strike / del → strikethrough
code → code
pre → pre
a href="…" → text_link
span.tg-spoiler → spoiler
tg-spoiler → spoiler
blockquote → blockquotemarkdown syntax
**bold** __italic__ ~~strike~~
||spoiler|| `code` [text](url)
\`\`\`lang
multi-line pre
\`\`\`this is a Telegram-oriented dialect (not full CommonMark): same delimiter can't nest in itself,
and dynamic links compose via core's
link() rather than [x]($${url}) (the url interpolation would be escaped as text).api
| export | signature | returns |
|---|---|---|
html | tagged template | FormatResult |
md | tagged template | FormatResult |
htmlToEntities | (s: string) | FormatResult |
mdToEntities | (s: string) | FormatResult |