diff --git a/.changeset/discord-bare-url-links.md b/.changeset/discord-bare-url-links.md new file mode 100644 index 000000000..c6704f8ee --- /dev/null +++ b/.changeset/discord-bare-url-links.md @@ -0,0 +1,5 @@ +--- +"@chat-adapter/discord": patch +--- + +fix: render bare URLs and autolinks as bare URLs instead of `[url](url)` masked links, which Discord only renders inside embeds (in normal messages they showed up as literal text) diff --git a/packages/adapter-discord/src/markdown.test.ts b/packages/adapter-discord/src/markdown.test.ts index 0d48cbb98..99e96b584 100644 --- a/packages/adapter-discord/src/markdown.test.ts +++ b/packages/adapter-discord/src/markdown.test.ts @@ -29,6 +29,26 @@ describe("DiscordFormatConverter", () => { expect(result).toContain("[link text](https://example.com)"); }); + it("should render a bare URL as a bare URL, not a masked link", () => { + // Discord renders masked links `[text](url)` only in embeds, so wrapping + // a bare URL as `[url](url)` shows up as literal text in a normal message. + const ast = converter.toAst("https://example.com"); + const result = converter.fromAst(ast); + expect(result).toContain("https://example.com"); + expect(result).not.toContain( + "[https://example.com](https://example.com)" + ); + }); + + it("should render an autolink as a bare URL, not a masked link", () => { + const ast = converter.toAst(""); + const result = converter.fromAst(ast); + expect(result).toContain("https://example.com"); + expect(result).not.toContain( + "[https://example.com](https://example.com)" + ); + }); + it("should preserve inline code", () => { const ast = converter.toAst("Use `const x = 1`"); const result = converter.fromAst(ast); diff --git a/packages/adapter-discord/src/markdown.ts b/packages/adapter-discord/src/markdown.ts index 02366c6d7..22795f8a7 100644 --- a/packages/adapter-discord/src/markdown.ts +++ b/packages/adapter-discord/src/markdown.ts @@ -146,6 +146,12 @@ export class DiscordFormatConverter extends BaseFormatConverter { const linkText = getNodeChildren(node) .map((child) => this.nodeToDiscordMarkdown(child)) .join(""); + // Bare URLs / autolinks (label === url) must stay bare: Discord only + // renders masked links `[text](url)` inside embeds, so `[url](url)` in a + // normal message shows up as literal text instead of a clickable link. + if (linkText === node.url) { + return node.url; + } // Standard markdown [text](url) return `[${linkText}](${node.url})`; }