From 5851bd432ad6b806be9b7931397799e86c03a40c Mon Sep 17 00:00:00 2001 From: santhreal <64453045+santhreal@users.noreply.github.com> Date: Wed, 22 Jul 2026 00:31:25 -0700 Subject: [PATCH] fix(slack): keep fenced markdown tables intact in _to_mrkdwn --- nanobot/channels/slack/runtime.py | 9 +++++++++ .../channels/slack/tests/test_slack_channel.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/nanobot/channels/slack/runtime.py b/nanobot/channels/slack/runtime.py index a9a43c11d..6b7b37a41 100644 --- a/nanobot/channels/slack/runtime.py +++ b/nanobot/channels/slack/runtime.py @@ -701,7 +701,16 @@ class SlackChannel(BaseChannel): """Convert Markdown to Slack mrkdwn, including tables.""" if not text: return "" + code_blocks: list[str] = [] + + def _save_fence(m: re.Match) -> str: + code_blocks.append(m.group(0)) + return f"\x00CB{len(code_blocks) - 1}\x00" + + text = cls._CODE_FENCE_RE.sub(_save_fence, text) text = cls._TABLE_RE.sub(cls._convert_table, text) + for i, block in enumerate(code_blocks): + text = text.replace(f"\x00CB{i}\x00", block) return cls._fixup_mrkdwn(slackify_markdown(text)).rstrip("\n") @classmethod diff --git a/nanobot/channels/slack/tests/test_slack_channel.py b/nanobot/channels/slack/tests/test_slack_channel.py index 77b87cb35..a79c564a5 100644 --- a/nanobot/channels/slack/tests/test_slack_channel.py +++ b/nanobot/channels/slack/tests/test_slack_channel.py @@ -714,3 +714,19 @@ def test_group_require_mention_accepts_camel_case_alias() -> None: ) assert config.group_require_mention is True assert config.group_allow_from == ["C_OK"] + + +def test_to_mrkdwn_keeps_fenced_markdown_tables_intact() -> None: + text = "Intro\n\n```\n| a | b |\n| - | - |\n| 1 | 2 |\n```\n\nOutro" + out = SlackChannel._to_mrkdwn(text) + + assert "```\n| a | b |\n| - | - |\n| 1 | 2 |\n```" in out + assert "**a**: 1" not in out + assert "*a*: 1" not in out + + +def test_to_mrkdwn_still_converts_unfenced_markdown_tables() -> None: + out = SlackChannel._to_mrkdwn("| a | b |\n| - | - |\n| 1 | 2 |") + + assert "| a | b |" not in out + assert "a" in out and "1" in out and "b" in out and "2" in out