Bug Description
On Slack, message.text drops the first line of a fenced code block when the code starts immediately after the opening triple backticks.
Slack represents a code block like this in an incoming message event:
```first line
second line
```
SlackFormatConverter#toAst normalizes the Slack mrkdwn and then passes it directly to the CommonMark parser:
toAst(mrkdwn: string): Root {
return parseMarkdown(slackMrkdwnToMarkdown(mrkdwn));
}
However, Slack and CommonMark interpret the opening line differently. Slack treats first line as code block content, while CommonMark treats it as the fenced code block's info string. The resulting mdast code node is equivalent to:
{
type: "code",
lang: "first",
meta: "line",
value: "second line",
}
The Slack adapter then derives message.text with toPlainText(formatted). For a code node, plain-text extraction returns only node.value, so the info string is omitted and the first line disappears:
text: toPlainText(formatted),
As a result, the example above produces message.text === "second line" instead of "first line\nsecond line". message.formatted is also incorrect because the first line is stored as lang / meta rather than code content.
Steps to Reproduce
- Create a
Chat instance with a Slack adapter.
- Send the bot a Slack message containing a fenced code block whose content begins immediately after the opening triple backticks:
```first line
second line
```
- Inspect the incoming
Message in a handler:
bot.onNewMention((_thread, message) => {
console.log(message.text);
console.log(message.formatted);
});
- Observe that
message.text contains only second line, while the first line appears as the code node's lang / meta fields.
Expected Behavior
Slack code block content should be preserved verbatim in both message.text and message.formatted:
message.text;
// "first line\nsecond line"
message.formatted.children[0];
// {
// type: "code",
// lang: null,
// meta: null,
// value: "first line\nsecond line",
// }
Actual Behavior
The first line is interpreted as a CommonMark info string and omitted from message.text:
message.text;
// "second line"
message.formatted.children[0];
// {
// type: "code",
// lang: "first",
// meta: "line",
// value: "second line",
// }
Code blocks with a newline immediately after the opening fence are unaffected:
```
first line
second line
```
Code Sample
import { Chat } from "chat";
import { createSlackAdapter } from "@chat-adapter/slack";
const bot = new Chat({
adapters: [createSlackAdapter({ /* ... */ })],
});
bot.onNewMention((_thread, message) => {
console.log(message.text);
// Slack input:
// line
// second line
//
//
// Actual: "second line"
// Expected: "first line\nsecond line"
});
Chat SDK Version
4.38.1
Node.js Version
24.18.0
Platform Adapter
Slack
Operating System
macOS
Additional Context
The existing Slack tests cover mentions inside triple-backtick code blocks and fenced code blocks surrounded by mentions, but they do not assert parsing when code content starts on the same line as the opening fence.
Bug Description
On Slack,
message.textdrops the first line of a fenced code block when the code starts immediately after the opening triple backticks.Slack represents a code block like this in an incoming message event:
SlackFormatConverter#toAstnormalizes the Slack mrkdwn and then passes it directly to the CommonMark parser:However, Slack and CommonMark interpret the opening line differently. Slack treats
first lineas code block content, while CommonMark treats it as the fenced code block's info string. The resulting mdast code node is equivalent to:The Slack adapter then derives
message.textwithtoPlainText(formatted). For a code node, plain-text extraction returns onlynode.value, so the info string is omitted and the first line disappears:As a result, the example above produces
message.text === "second line"instead of"first line\nsecond line".message.formattedis also incorrect because the first line is stored aslang/metarather than code content.Steps to Reproduce
Chatinstance with a Slack adapter.Messagein a handler:message.textcontains onlysecond line, while the first line appears as the code node'slang/metafields.Expected Behavior
Slack code block content should be preserved verbatim in both
message.textandmessage.formatted:Actual Behavior
The first line is interpreted as a CommonMark info string and omitted from
message.text:Code blocks with a newline immediately after the opening fence are unaffected:
Code Sample
Chat SDK Version
4.38.1
Node.js Version
24.18.0
Platform Adapter
Slack
Operating System
macOS
Additional Context
The existing Slack tests cover mentions inside triple-backtick code blocks and fenced code blocks surrounded by mentions, but they do not assert parsing when code content starts on the same line as the opening fence.