From 285bd323daa8ac562ae5d111f7d4cf5bee0f0dab Mon Sep 17 00:00:00 2001 From: mdnanocom Date: Thu, 9 Apr 2026 19:07:57 +0200 Subject: [PATCH] [gchat] [bug] render markdown links with Google Chat custom link syntax --- .changeset/gchat-link-labels.md | 5 ++++ packages/adapter-gchat/src/markdown.test.ts | 4 +-- packages/adapter-gchat/src/markdown.ts | 6 ++--- packages/integration-tests/src/gchat.test.ts | 26 ++++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 .changeset/gchat-link-labels.md diff --git a/.changeset/gchat-link-labels.md b/.changeset/gchat-link-labels.md new file mode 100644 index 00000000..79741885 --- /dev/null +++ b/.changeset/gchat-link-labels.md @@ -0,0 +1,5 @@ +--- +"@chat-adapter/gchat": patch +--- + +Preserve custom link labels in Google Chat text messages by rendering Markdown links with Google Chat's supported `` syntax. diff --git a/packages/adapter-gchat/src/markdown.test.ts b/packages/adapter-gchat/src/markdown.test.ts index 30183665..4f3d5c24 100644 --- a/packages/adapter-gchat/src/markdown.test.ts +++ b/packages/adapter-gchat/src/markdown.test.ts @@ -43,10 +43,10 @@ describe("GoogleChatFormatConverter", () => { expect(result).toContain("https://example.com"); }); - it("should output 'text (url)' when link text differs", () => { + it("should output Google Chat custom link syntax when link text differs", () => { const ast = converter.toAst("[click here](https://example.com)"); const result = converter.fromAst(ast); - expect(result).toContain("click here (https://example.com)"); + expect(result).toContain(""); }); it("should handle blockquotes", () => { diff --git a/packages/adapter-gchat/src/markdown.ts b/packages/adapter-gchat/src/markdown.ts index 7ab2f4c7..efd114ba 100644 --- a/packages/adapter-gchat/src/markdown.ts +++ b/packages/adapter-gchat/src/markdown.ts @@ -106,16 +106,14 @@ export class GoogleChatFormatConverter extends BaseFormatConverter { } if (isLinkNode(node)) { - // Google Chat auto-detects links, so we just output the URL + // Google Chat supports custom link labels using syntax. const linkText = getNodeChildren(node) .map((child) => this.nodeToGChat(child)) .join(""); - // If link text matches URL, just output URL if (linkText === node.url) { return node.url; } - // Otherwise output "text (url)" - return `${linkText} (${node.url})`; + return `<${node.url}|${linkText}>`; } if (isBlockquoteNode(node)) { diff --git a/packages/integration-tests/src/gchat.test.ts b/packages/integration-tests/src/gchat.test.ts index d1f5c5c1..17dd0f16 100644 --- a/packages/integration-tests/src/gchat.test.ts +++ b/packages/integration-tests/src/gchat.test.ts @@ -415,6 +415,32 @@ describe("Google Chat Integration", () => { expect(sent.text).toContain("`code`"); }); + it("should preserve custom link labels in posted messages", async () => { + chat.onNewMention(async (thread) => { + await thread.post({ + markdown: "[Click here](https://example.com)", + }); + }); + + const event = createGoogleChatEvent({ + text: `@${GCHAT_BOT_NAME} link test`, + messageName: `${TEST_SPACE_NAME}/messages/msg-001`, + spaceName: TEST_SPACE_NAME, + threadName: TEST_THREAD_NAME, + senderId: "users/user-123", + senderName: "John Doe", + hasBotMention: true, + }); + + await chat.webhooks.gchat(createGoogleChatWebhookRequest(event), { + waitUntil: tracker.waitUntil, + }); + await tracker.waitForAll(); + + const sent = mockChatApi.sentMessages[0]; + expect(sent.text).toBe(""); + }); + it("should pass @mentions through as-is in posted messages", async () => { chat.onNewMention(async (thread) => { await thread.post("Hey @john, check this out!");