@adriangalilea/utils 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -371,6 +371,21 @@ transform('<h1>Title</h1><ul><li>Point one</li><li>Point two</li></ul>')
371
371
  // '<b><u>Title</u></b>\n\n• Point one\n• Point two'
372
372
  ```
373
373
 
374
+ ### Telegram Markdown (`tg-md`)
375
+
376
+ The MARKDOWN twin of `tg-html`, for the markdown LLMs actually emit (grown in xtldr's bot, moved here verbatim). One opinionated dialect — `_` is NEVER emphasis so `snake_case` survives, every tag balanced by construction so Telegram can't reject a render, pure whole-string functions so full-frame draft repaints (`bot/draft`) degrade malformed mid-stream markdown to literal text — rendered to every shape a bot sends:
377
+
378
+ ```typescript
379
+ import { markdownToRichHtml, markdownToTelegramHtml, toPlainText, tidyRichMarkdown } from '@adriangalilea/utils/tg-md'
380
+
381
+ markdownToRichHtml(md, coverUrl) // rich-message HTML (Bot API 10.1): real <h1>/<ul>, cover <img> spliced after the title
382
+ markdownToTelegramHtml(md) // strict parse_mode=HTML subset: bold-underlined title, breathing headings, • bullets, ###### footer stays quiet
383
+ toPlainText(md) // last-ditch fallback; quotes keep their > marker
384
+ tidyRichMarkdown(md) // strip the stray ```fence``` models wrap replies in
385
+ ```
386
+
387
+ Zero dependencies, Worker-safe. Typography (heading air, bullet glyph, title underline) IS the opinion; it gets options when a second consumer needs a different look, not before.
388
+
374
389
  ### Telegram bot plugins (GramIO)
375
390
 
376
391
  Plugins for personal Telegram bots built on [GramIO](https://gramio.dev). Each plugin lives at its own subpath; peer deps (`gramio`, `@gramio/storage`, `@gramio/session`, `@gramio/format`, `marked`) are **all optional** — install only what you import.
@@ -0,0 +1,73 @@
1
+ /**
2
+ * tg-md — the opinionated Telegram-Markdown formatter (xtldr's house style,
3
+ * grown from theSummaryBot's tg-html lineage). ONE input dialect, the
4
+ * markdown LLMs actually emit, rendered to every shape a bot sends:
5
+ *
6
+ * markdownToRichHtml(md, coverUrl?) rich-message HTML (Bot API 10.1): real
7
+ * headings/lists, optional cover <img>
8
+ * spliced after the title
9
+ * markdownToTelegramHtml(md) strict parse_mode=HTML subset: # title
10
+ * -> bold underlined line, ## headings ->
11
+ * bold lines with breathing room, ######
12
+ * footer -> quiet plain line, bullets -> •
13
+ * toPlainText(md) last-ditch fallback (quotes keep their
14
+ * > marker so they still read as quotes)
15
+ * tidyRichMarkdown(md) strip the stray ```fence``` models add
16
+ *
17
+ * The dialect contract, load-bearing and deliberate:
18
+ * - `_` is NEVER emphasis — snake_case in model output survives verbatim.
19
+ * Only `*italic*` / `**bold**` are honored.
20
+ * - Every tag is balanced by construction: a render can never produce a
21
+ * message Telegram rejects; unmatched markers stay literal.
22
+ * - Pure functions of the whole string — safe for full-frame draft repaints
23
+ * (bot/draft): malformed mid-stream markdown degrades to literal text
24
+ * this frame and renders correctly the next.
25
+ *
26
+ * Typography (heading air, bullet glyph, the title underline) IS the opinion;
27
+ * it becomes configurable when a second consumer needs a different look, not
28
+ * before. Zero deps, worker-safe.
29
+ */
30
+ /** Unwrap a leading/trailing ```…``` code fence (some models add one) and trim. */
31
+ export declare function tidyRichMarkdown(raw: string): string;
32
+ /**
33
+ * Render the model's rich Markdown into Telegram's strict `parse_mode=HTML` subset,
34
+ * which has no headings or lists:
35
+ * `#` title -> a bold UNDERLINED line + blank line (the wordmark look)
36
+ * `##`..`#####` headings -> a bold line + blank line after (air between head and body)
37
+ * `######` footer heading -> a bold line, no forced air (it's the last line)
38
+ * bullets (`- `/`* `/`+ `) -> a `• ` prefix
39
+ * blockquote (`> `) -> `<blockquote>` (consecutive lines merged)
40
+ * `**bold**`/`*italic*` -> `<b>`/`<i>`; `` `code` `` -> `<code>`; links -> `<a>`
41
+ * Only `*`-based emphasis is honored (never `_`), so `snake_case` survives. Every tag
42
+ * is balanced, so Telegram can't reject the message; unmatched markers stay literal.
43
+ * The spacing is the legacy tghtml contract (now @adriangalilea/utils/tg-html): every
44
+ * heading is followed by a blank line so sections breathe — a heading hugging its
45
+ * bullets reads as a wall.
46
+ */
47
+ export declare function markdownToTelegramHtml(markdown: string): string;
48
+ /**
49
+ * Render the model's rich Markdown into rich-message HTML (the `rich_message.html`
50
+ * field, Bot API 10.1), which supports tags `parse_mode=HTML` lacks, so headings and
51
+ * lists survive as real structure instead of flattening:
52
+ * headings (`#`..`######`) -> `<h1>`..`<h6>` (level = count of `#`)
53
+ * bullets (`- `/`* `/`+ `) -> `<ul><li>…</li></ul>` (consecutive items merged)
54
+ * blockquote (`> `) -> `<blockquote>` (consecutive lines merged)
55
+ * Inline emphasis/code/links reuse {@link inlineMd}. Every tag is balanced, so Telegram
56
+ * can't reject the message; unmatched markers stay literal.
57
+ *
58
+ * `coverUrl` (rich path only) embeds a cover image as a standalone `<img>` block right after
59
+ * the title heading (title, cover, then body), matching the rich-message photo block, which
60
+ * accepts HTTP(S) URLs only. Ignored unless it's a well-formed http(s) URL. The strict-HTML and
61
+ * plain fallbacks have no image support, so they never carry a cover.
62
+ */
63
+ export declare function markdownToRichHtml(markdown: string, coverUrl?: string): string;
64
+ /** Escape text/code content for Telegram HTML. */
65
+ export declare function escapeHtml(s: string): string;
66
+ /**
67
+ * Strip Markdown to plain text: the fallback when Telegram rejects the rich message.
68
+ * Removes heading/bullet markers and emphasis, unwraps links to their text, but KEEPS
69
+ * the `>` blockquote marker on every quote line so quotes still read as quotes with no
70
+ * formatting to lean on. Best-effort, not a full parser.
71
+ */
72
+ export declare function toPlainText(markdown: string): string;
73
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tg-md/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkD/D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GACf,MAAM,CA+DR;AAwED,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAWD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYpD"}
@@ -0,0 +1,251 @@
1
+ /**
2
+ * tg-md — the opinionated Telegram-Markdown formatter (xtldr's house style,
3
+ * grown from theSummaryBot's tg-html lineage). ONE input dialect, the
4
+ * markdown LLMs actually emit, rendered to every shape a bot sends:
5
+ *
6
+ * markdownToRichHtml(md, coverUrl?) rich-message HTML (Bot API 10.1): real
7
+ * headings/lists, optional cover <img>
8
+ * spliced after the title
9
+ * markdownToTelegramHtml(md) strict parse_mode=HTML subset: # title
10
+ * -> bold underlined line, ## headings ->
11
+ * bold lines with breathing room, ######
12
+ * footer -> quiet plain line, bullets -> •
13
+ * toPlainText(md) last-ditch fallback (quotes keep their
14
+ * > marker so they still read as quotes)
15
+ * tidyRichMarkdown(md) strip the stray ```fence``` models add
16
+ *
17
+ * The dialect contract, load-bearing and deliberate:
18
+ * - `_` is NEVER emphasis — snake_case in model output survives verbatim.
19
+ * Only `*italic*` / `**bold**` are honored.
20
+ * - Every tag is balanced by construction: a render can never produce a
21
+ * message Telegram rejects; unmatched markers stay literal.
22
+ * - Pure functions of the whole string — safe for full-frame draft repaints
23
+ * (bot/draft): malformed mid-stream markdown degrades to literal text
24
+ * this frame and renders correctly the next.
25
+ *
26
+ * Typography (heading air, bullet glyph, the title underline) IS the opinion;
27
+ * it becomes configurable when a second consumer needs a different look, not
28
+ * before. Zero deps, worker-safe.
29
+ */
30
+ /** Unwrap a leading/trailing ```…``` code fence (some models add one) and trim. */
31
+ export function tidyRichMarkdown(raw) {
32
+ const trimmed = raw.trim();
33
+ const fenced = /^```[a-zA-Z]*\n([\s\S]*?)\n?```$/.exec(trimmed);
34
+ return (fenced ? fenced[1] : trimmed).trim();
35
+ }
36
+ /**
37
+ * Render the model's rich Markdown into Telegram's strict `parse_mode=HTML` subset,
38
+ * which has no headings or lists:
39
+ * `#` title -> a bold UNDERLINED line + blank line (the wordmark look)
40
+ * `##`..`#####` headings -> a bold line + blank line after (air between head and body)
41
+ * `######` footer heading -> a bold line, no forced air (it's the last line)
42
+ * bullets (`- `/`* `/`+ `) -> a `• ` prefix
43
+ * blockquote (`> `) -> `<blockquote>` (consecutive lines merged)
44
+ * `**bold**`/`*italic*` -> `<b>`/`<i>`; `` `code` `` -> `<code>`; links -> `<a>`
45
+ * Only `*`-based emphasis is honored (never `_`), so `snake_case` survives. Every tag
46
+ * is balanced, so Telegram can't reject the message; unmatched markers stay literal.
47
+ * The spacing is the legacy tghtml contract (now @adriangalilea/utils/tg-html): every
48
+ * heading is followed by a blank line so sections breathe — a heading hugging its
49
+ * bullets reads as a wall.
50
+ */
51
+ export function markdownToTelegramHtml(markdown) {
52
+ const lines = tidyRichMarkdown(markdown).split(/\r?\n/);
53
+ const out = [];
54
+ let quote = [];
55
+ const flushQuote = () => {
56
+ if (quote.length) {
57
+ out.push(`<blockquote>${quote.join("\n")}</blockquote>`);
58
+ quote = [];
59
+ }
60
+ };
61
+ for (const raw of lines) {
62
+ const line = raw.replace(/\s+$/, "");
63
+ const q = /^\s{0,3}>\s?(.*)$/.exec(line);
64
+ if (q) {
65
+ quote.push(inlineMd(q[1]));
66
+ continue;
67
+ }
68
+ flushQuote();
69
+ if (!line.trim()) {
70
+ out.push("");
71
+ continue;
72
+ }
73
+ const heading = /^\s{0,3}(#{1,6})\s+(.*)$/.exec(line);
74
+ if (heading) {
75
+ const level = heading[1].length;
76
+ const text = inlineMd(heading[2]);
77
+ // ###### is the source footer: metadata, not a heading — it renders as a quiet
78
+ // plain line (the legacy look), never bold.
79
+ if (level === 1)
80
+ out.push(`<b><u>${text}</u></b>`, "");
81
+ else if (level === 6)
82
+ out.push(text);
83
+ else
84
+ out.push(`<b>${text}</b>`, "");
85
+ continue;
86
+ }
87
+ const bullet = /^\s{0,3}[-*+]\s+(.*)$/.exec(line);
88
+ if (bullet) {
89
+ out.push(`• ${inlineMd(bullet[1])}`);
90
+ continue;
91
+ }
92
+ out.push(inlineMd(line));
93
+ }
94
+ flushQuote();
95
+ return tidyHtml(out.join("\n"));
96
+ }
97
+ /**
98
+ * Render the model's rich Markdown into rich-message HTML (the `rich_message.html`
99
+ * field, Bot API 10.1), which supports tags `parse_mode=HTML` lacks, so headings and
100
+ * lists survive as real structure instead of flattening:
101
+ * headings (`#`..`######`) -> `<h1>`..`<h6>` (level = count of `#`)
102
+ * bullets (`- `/`* `/`+ `) -> `<ul><li>…</li></ul>` (consecutive items merged)
103
+ * blockquote (`> `) -> `<blockquote>` (consecutive lines merged)
104
+ * Inline emphasis/code/links reuse {@link inlineMd}. Every tag is balanced, so Telegram
105
+ * can't reject the message; unmatched markers stay literal.
106
+ *
107
+ * `coverUrl` (rich path only) embeds a cover image as a standalone `<img>` block right after
108
+ * the title heading (title, cover, then body), matching the rich-message photo block, which
109
+ * accepts HTTP(S) URLs only. Ignored unless it's a well-formed http(s) URL. The strict-HTML and
110
+ * plain fallbacks have no image support, so they never carry a cover.
111
+ */
112
+ export function markdownToRichHtml(markdown, coverUrl) {
113
+ const lines = tidyRichMarkdown(markdown).split(/\r?\n/);
114
+ const out = [];
115
+ let quote = [];
116
+ let bullets = [];
117
+ const flushQuote = () => {
118
+ if (quote.length) {
119
+ out.push(`<blockquote>${quote.join("\n")}</blockquote>`);
120
+ quote = [];
121
+ }
122
+ };
123
+ const flushBullets = () => {
124
+ if (bullets.length) {
125
+ out.push(`<ul>${bullets.map((b) => `<li>${b}</li>`).join("")}</ul>`);
126
+ bullets = [];
127
+ }
128
+ };
129
+ for (const raw of lines) {
130
+ const line = raw.replace(/\s+$/, "");
131
+ const q = /^\s{0,3}>\s?(.*)$/.exec(line);
132
+ if (q) {
133
+ flushBullets();
134
+ quote.push(inlineMd(q[1]));
135
+ continue;
136
+ }
137
+ const bullet = /^\s{0,3}[-*+]\s+(.*)$/.exec(line);
138
+ if (bullet) {
139
+ flushQuote();
140
+ bullets.push(inlineMd(bullet[1]));
141
+ continue;
142
+ }
143
+ flushQuote();
144
+ flushBullets();
145
+ if (!line.trim()) {
146
+ out.push("");
147
+ continue;
148
+ }
149
+ const heading = /^\s{0,3}(#{1,6})\s+(.*)$/.exec(line);
150
+ if (heading) {
151
+ const level = heading[1].length;
152
+ out.push(`<h${level}>${inlineMd(heading[2])}</h${level}>`);
153
+ continue;
154
+ }
155
+ out.push(inlineMd(line));
156
+ }
157
+ flushQuote();
158
+ flushBullets();
159
+ insertCover(out, coverUrl);
160
+ return out
161
+ .join("\n")
162
+ .replace(/[ \t]+\n/g, "\n")
163
+ .replace(/\n{3,}/g, "\n\n")
164
+ .trim();
165
+ }
166
+ /**
167
+ * Insert a cover `<img>` block into the rendered rich-HTML lines: right after the title heading
168
+ * (so it reads title → cover → body), or at the very top when there's no title. Anchors on `<h1>`
169
+ * only, since the summary's title is `#` (h1) while section headings are `##` (h2) and the source
170
+ * footer is `######` (h6): matching any `<h[1-6]>` would splice the cover below the footer when the
171
+ * model omits the title. A blank line surrounds it so it stays its own block (media blocks can't be
172
+ * inline). No-op unless `url` is a well-formed http(s) URL, since the rich photo block accepts only those.
173
+ */
174
+ function insertCover(out, url) {
175
+ if (!url || !/^https?:\/\/\S+$/i.test(url.trim()))
176
+ return;
177
+ const img = `<img src="${escapeAttr(url.trim())}"/>`;
178
+ const titleAt = out.findIndex((line) => /^<h1>/.test(line));
179
+ const at = titleAt === -1 ? 0 : titleAt + 1;
180
+ out.splice(at, 0, "", img, "");
181
+ }
182
+ /** Normalize rendered HTML: strip trailing whitespace, collapse blank-line runs. Blank lines
183
+ * around lists stay — that air is the layout (the legacy look); only runs of 3+ collapse. */
184
+ function tidyHtml(html) {
185
+ return html
186
+ .replace(/[ \t]+\n/g, "\n")
187
+ .replace(/\n{3,}/g, "\n\n")
188
+ .trim();
189
+ }
190
+ /**
191
+ * Inline Markdown to Telegram HTML for one line. Code spans and links are pulled out
192
+ * first (so their contents aren't escaped twice or treated as emphasis) and stashed;
193
+ * the rest is escaped, `**bold**`/`*italic*` become tags, then the fragments are restored.
194
+ */
195
+ // Placeholder sentinel for stashed fragments: U+F8FF, a private-use codepoint
196
+ // that renders INVISIBLY in most editors — declared here as an escape so the
197
+ // load-bearing character can never be destroyed by a well-meaning hand edit.
198
+ // It cannot occur in model output the way any printable marker could.
199
+ const STASH = "\uf8ff";
200
+ function inlineMd(text) {
201
+ const tokens = [];
202
+ const stash = (html) => {
203
+ tokens.push(html);
204
+ return `${STASH}${tokens.length - 1}${STASH}`;
205
+ };
206
+ // Code spans first: their contents are literal (no emphasis, no nested links).
207
+ let s = text.replace(/`([^`]+)`/g, (_, code) => stash(`<code>${escapeHtml(code)}</code>`));
208
+ // Then links: drop the href unless it's a trusted scheme, keeping the label.
209
+ s = s.replace(/\[([^\]]*)\]\(([^)\s]+)\)/g, (_, label, url) => {
210
+ const safe = /^(https?:|tg:|mailto:)/i.test(url) ? url : null;
211
+ return stash(safe
212
+ ? `<a href="${escapeAttr(safe)}">${escapeHtml(label)}</a>`
213
+ : escapeHtml(label));
214
+ });
215
+ s = escapeHtml(s);
216
+ s = s.replace(/\*\*([^*]+)\*\*/g, "<b>$1</b>"); // bold before italic so `**` wins over `*`
217
+ s = s.replace(/(^|[^*])\*(?!\s)([^*]+?)\*/g, "$1<i>$2</i>");
218
+ return s.replace(new RegExp(`${STASH}(\\d+)${STASH}`, "g"), (_, i) => tokens[Number(i)]);
219
+ }
220
+ /** Escape text/code content for Telegram HTML. */
221
+ export function escapeHtml(s) {
222
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
223
+ }
224
+ /** Escape an href for a Telegram HTML attribute. */
225
+ function escapeAttr(s) {
226
+ return s
227
+ .replace(/&/g, "&amp;")
228
+ .replace(/"/g, "&quot;")
229
+ .replace(/</g, "&lt;")
230
+ .replace(/>/g, "&gt;");
231
+ }
232
+ /**
233
+ * Strip Markdown to plain text: the fallback when Telegram rejects the rich message.
234
+ * Removes heading/bullet markers and emphasis, unwraps links to their text, but KEEPS
235
+ * the `>` blockquote marker on every quote line so quotes still read as quotes with no
236
+ * formatting to lean on. Best-effort, not a full parser.
237
+ */
238
+ export function toPlainText(markdown) {
239
+ return tidyRichMarkdown(markdown)
240
+ .replace(/```[a-zA-Z]*\n?([\s\S]*?)```/g, "$1") // fenced code -> its contents
241
+ .replace(/^\s{0,3}#{1,6}\s+/gm, "") // heading markers
242
+ .replace(/^\s{0,3}>\s?/gm, "> ") // normalize blockquote markers, keep them
243
+ .replace(/^(\s*)[-*+]\s+/gm, "$1• ") // bullet markers -> •
244
+ .replace(/\[([^\]]*)\]\([^)]*\)/g, "$1") // [text](url) -> text
245
+ .replace(/(\*\*|__)(.*?)\1/g, "$2") // bold
246
+ .replace(/(\*|_)(.*?)\1/g, "$2") // italic
247
+ .replace(/`([^`]*)`/g, "$1") // inline code
248
+ .replace(/\n{3,}/g, "\n\n")
249
+ .trim();
250
+ }
251
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tg-md/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adriangalilea/utils",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "TypeScript utilities - logger, currency, formatter, GramIO bot plugins, and more",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -44,6 +44,10 @@
44
44
  "types": "./dist/tg-html/index.d.ts",
45
45
  "default": "./dist/tg-html/index.js"
46
46
  },
47
+ "./tg-md": {
48
+ "types": "./dist/tg-md/index.d.ts",
49
+ "default": "./dist/tg-md/index.js"
50
+ },
47
51
  "./bot": {
48
52
  "types": "./dist/bot/index.d.ts",
49
53
  "default": "./dist/bot/index.js"