diff --git a/src/markdown/render.ts b/src/markdown/render.ts index 502ab69ef..111430f3a 100644 --- a/src/markdown/render.ts +++ b/src/markdown/render.ts @@ -93,13 +93,8 @@ export function renderMarkdownWithMarkers(ir: MarkdownIR, options: RenderOptions for (let i = 0; i < points.length; i += 1) { const pos = points[i]; - while (stack.length && stack[stack.length - 1]?.end === pos) { - const span = stack.pop(); - if (!span) break; - const marker = styleMarkers[span.style]; - if (marker) out += marker.close; - } - + // Close links before styles to maintain proper nesting order + // (links are typically nested inside styles like bold/italic) const closingLinks = linkEnds.get(pos); if (closingLinks && closingLinks.length > 0) { for (const link of closingLinks) { @@ -107,6 +102,13 @@ export function renderMarkdownWithMarkers(ir: MarkdownIR, options: RenderOptions } } + while (stack.length && stack[stack.length - 1]?.end === pos) { + const span = stack.pop(); + if (!span) break; + const marker = styleMarkers[span.style]; + if (marker) out += marker.close; + } + const openingLinks = linkStarts.get(pos); if (openingLinks && openingLinks.length > 0) { for (const link of openingLinks) { diff --git a/src/telegram/format.test.ts b/src/telegram/format.test.ts index 831782815..105626c12 100644 --- a/src/telegram/format.test.ts +++ b/src/telegram/format.test.ts @@ -47,4 +47,19 @@ describe("markdownToTelegramHtml", () => { const res = markdownToTelegramHtml("```js\nconst x = 1;\n```"); expect(res).toBe("
const x = 1;\n
"); }); + + it("properly nests link tags inside bold when URL is at end of bold span", () => { + const res = markdownToTelegramHtml("**Check https://example.com**"); + expect(res).toBe('Check https://example.com'); + }); + + it("properly nests link tags inside italic", () => { + const res = markdownToTelegramHtml("_visit https://docs.molt.bot_"); + expect(res).toBe('visit https://docs.molt.bot'); + }); + + it("renders emoji before bold correctly", () => { + const res = markdownToTelegramHtml("🧪 **Header text**"); + expect(res).toBe("🧪 Header text"); + }); });