From 90974e1030f3d3e8ddf37c31ed14e139412c03ea Mon Sep 17 00:00:00 2001 From: divanoli Date: Thu, 5 Feb 2026 12:41:08 +0300 Subject: [PATCH] refactor(telegram): use snapshot for orphaned TLD offset clarity Use explicit snapshot variable when checking tag positions in orphaned TLD pass. While JavaScript's replace() doesn't mutate during iteration, this makes intent explicit and adds test coverage for multi-TLD HTML. Co-Authored-By: Claude Opus 4.5 --- src/telegram/format.ts | 9 ++++++--- src/telegram/format.wrap-md.test.ts | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/telegram/format.ts b/src/telegram/format.ts index 2972acb9845..501b6ac776f 100644 --- a/src/telegram/format.ts +++ b/src/telegram/format.ts @@ -222,14 +222,17 @@ export function wrapFileReferencesInHtml(html: string): string { `([^a-zA-Z0-9]|^)([A-Za-z]\\.(?:${extensionsPattern}))(?=[^a-zA-Z0-9/]|$)`, "g", ); - result = result.replace(orphanedTldPattern, (m, prefix, tld, offset) => { + // Snapshot for offset calculations (offset is relative to pre-replacement string) + // Note: replace() doesn't mutate, but snapshot makes intent explicit + const snapshot = result; + result = snapshot.replace(orphanedTldPattern, (m, prefix, tld, offset) => { // Skip if prefix is > (right after a tag close) if (prefix === ">") { return m; } // Skip if we're inside an HTML tag (between < and >) - const lastOpen = result.lastIndexOf("<", offset); - const lastClose = result.lastIndexOf(">", offset); + const lastOpen = snapshot.lastIndexOf("<", offset); + const lastClose = snapshot.lastIndexOf(">", offset); if (lastOpen > lastClose) { return m; // Inside a tag } diff --git a/src/telegram/format.wrap-md.test.ts b/src/telegram/format.wrap-md.test.ts index 413b91c1576..96b7628f71d 100644 --- a/src/telegram/format.wrap-md.test.ts +++ b/src/telegram/format.wrap-md.test.ts @@ -341,4 +341,22 @@ describe("edge cases", () => { const result = wrapFileReferencesInHtml(input); expect(result).toBe(input); }); + + it("handles multiple orphaned TLDs with HTML tags (offset stability)", () => { + // This tests the bug where offset is relative to pre-replacement string + // but we were checking against the mutating result string + const input = 'link B.md text D.py'; + const result = wrapFileReferencesInHtml(input); + // A.md in href should NOT be wrapped (inside attribute) + // B.md outside tags SHOULD be wrapped + // C.sh in title attribute should NOT be wrapped + // D.py outside tags SHOULD be wrapped + expect(result).toContain("B.md"); + expect(result).toContain("D.py"); + expect(result).not.toContain("A.md"); + expect(result).not.toContain("C.sh"); + // Attributes should be unchanged + expect(result).toContain('href="http://A.md"'); + expect(result).toContain('title="C.sh"'); + }); });