From e02d144af9d4d0ab290c1ba4a87ab27149131223 Mon Sep 17 00:00:00 2001 From: ezhikkk <105670095+ezhikkk@users.noreply.github.com> Date: Sun, 8 Feb 2026 06:55:56 +0100 Subject: [PATCH] feat(telegram): add spoiler tag support (#11543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(telegram): add spoiler tag support Render markdown ||spoiler|| syntax as tags in Telegram HTML output. The markdown IR already parses spoiler syntax, but the Telegram renderer was missing the style marker. This adds the spoiler marker to renderTelegramHtml(). Fixes spoiler text appearing as raw ||text|| instead of hidden text. * fix: enable Telegram spoiler rendering (#11543) (thanks @ezhikkk) --------- Co-authored-by: Параша Co-authored-by: Muhammed Mukhthar CM --- CHANGELOG.md | 1 + src/telegram/format.test.ts | 10 ++++++++++ src/telegram/format.ts | 3 +++ 3 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index afa038b92..a494c5f7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai - Cron: route text-only isolated agent announces through the shared subagent announce flow; add exponential backoff for repeated errors; preserve future `nextRunAtMs` on restart; include current-boundary schedule matches; prevent stale threadId reuse across targets; and add per-job execution timeout. (#11641) Thanks @tyler6204. - Subagents: stabilize announce timing, preserve compaction metrics across retries, clamp overflow-prone long timeouts, and cap impossible context usage token totals. (#11551) Thanks @tyler6204. - Agents: recover from context overflow caused by oversized tool results (pre-emptive capping + fallback truncation). (#11579) Thanks @tyler6204. +- Telegram: render markdown spoilers with `` HTML tags. (#11543) Thanks @ezhikkk. - Gateway/CLI: when `gateway.bind=lan`, use a LAN IP for probe URLs and Control UI links. (#11448) Thanks @AnonO6. - Memory: set Voyage embeddings `input_type` for improved retrieval. (#10818) Thanks @mcinteerj. - Memory/QMD: run boot refresh in background by default, add configurable QMD maintenance timeouts, and retry QMD after fallback failures. (#9690, #9705) diff --git a/src/telegram/format.test.ts b/src/telegram/format.test.ts index 7dedc2c6f..67aaba3d3 100644 --- a/src/telegram/format.test.ts +++ b/src/telegram/format.test.ts @@ -68,4 +68,14 @@ describe("markdownToTelegramHtml", () => { const res = markdownToTelegramHtml("[**bold**](https://example.com)"); expect(res).toBe('bold'); }); + + it("renders spoiler tags", () => { + const res = markdownToTelegramHtml("the answer is ||42||"); + expect(res).toBe("the answer is 42"); + }); + + it("renders spoiler with nested formatting", () => { + const res = markdownToTelegramHtml("||**secret** text||"); + expect(res).toBe("secret text"); + }); }); diff --git a/src/telegram/format.ts b/src/telegram/format.ts index e3d7e4c43..3d50b9902 100644 --- a/src/telegram/format.ts +++ b/src/telegram/format.ts @@ -45,6 +45,7 @@ function renderTelegramHtml(ir: MarkdownIR): string { strikethrough: { open: "", close: "" }, code: { open: "", close: "" }, code_block: { open: "
", close: "
" }, + spoiler: { open: "", close: "" }, }, escapeText: escapeHtml, buildLink: buildTelegramLink, @@ -57,6 +58,7 @@ export function markdownToTelegramHtml( ): string { const ir = markdownToIR(markdown ?? "", { linkify: true, + enableSpoilers: true, headingStyle: "none", blockquotePrefix: "", tableMode: options.tableMode, @@ -82,6 +84,7 @@ export function markdownToTelegramChunks( ): TelegramFormattedChunk[] { const ir = markdownToIR(markdown ?? "", { linkify: true, + enableSpoilers: true, headingStyle: "none", blockquotePrefix: "", tableMode: options.tableMode,