fix: Add code_block method to WhatsApp and Instagram markdown renderers (#13166)
Problem: SystemStackError: stack level too deep occurred when rendering
messages with indented content (4+ spaces) for WhatsApp, Instagram, and
Facebook channels.
Root Cause: CommonMarker::Renderer#code_block contains a self-recursive
placeholder that must be overridden:
```
def code_block(node)
code_block(node) # calls itself infinitely
end
```
WhatsAppRenderer and InstagramRenderer were missing this override,
causing infinite recursion when markdown with 4-space indentation
(interpreted as code blocks) was rendered.
Fix: Added code_block method to both renderers that outputs the node
content as plain text:
```
def code_block(node)
out(node.string_content)
end
```
Fix https://linear.app/chatwoot/issue/CW-6217/systemstackerror-stack-level-too-deep-systemstackerror
This commit is contained in:
@@ -42,6 +42,10 @@ class Messages::MarkdownRenderers::InstagramRenderer < Messages::MarkdownRendere
|
||||
cr
|
||||
end
|
||||
|
||||
def code_block(node)
|
||||
out(node.string_content)
|
||||
end
|
||||
|
||||
def softbreak(_node)
|
||||
out("\n")
|
||||
end
|
||||
|
||||
@@ -30,6 +30,10 @@ class Messages::MarkdownRenderers::WhatsAppRenderer < Messages::MarkdownRenderer
|
||||
cr
|
||||
end
|
||||
|
||||
def code_block(node)
|
||||
out(node.string_content)
|
||||
end
|
||||
|
||||
def softbreak(_node)
|
||||
out("\n")
|
||||
end
|
||||
|
||||
@@ -74,6 +74,24 @@ RSpec.describe Messages::MarkdownRendererService, type: :service do
|
||||
expect(result.scan("\n").count).to eq(4)
|
||||
expect(result).to include("Para 1\n\n\n\nPara 2")
|
||||
end
|
||||
|
||||
it 'renders code blocks as plain text' do
|
||||
content = "```\ncode here\n```"
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result.strip).to eq('code here')
|
||||
end
|
||||
|
||||
it 'renders indented code blocks as plain text preserving exact content' do
|
||||
content = ' indented code line'
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result).to eq('indented code line')
|
||||
end
|
||||
|
||||
it 'handles code blocks with emojis and special characters without stack overflow' do
|
||||
content = " first line\n 🌐 second line\n"
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result).to eq("first line\n🌐 second line")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when channel is Channel::Instagram' do
|
||||
@@ -130,6 +148,24 @@ RSpec.describe Messages::MarkdownRendererService, type: :service do
|
||||
expect(result.scan("\n").count).to eq(4)
|
||||
expect(result).to include("Para 1\n\n\n\nPara 2")
|
||||
end
|
||||
|
||||
it 'renders code blocks as plain text' do
|
||||
content = "```\ncode here\n```"
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result.strip).to eq('code here')
|
||||
end
|
||||
|
||||
it 'renders indented code blocks as plain text preserving exact content' do
|
||||
content = ' indented code line'
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result).to eq('indented code line')
|
||||
end
|
||||
|
||||
it 'handles code blocks with emojis and special characters without stack overflow' do
|
||||
content = " first line\n 🌐 second line\n"
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result).to eq("first line\n🌐 second line")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when channel is Channel::Line' do
|
||||
@@ -358,6 +394,18 @@ RSpec.describe Messages::MarkdownRendererService, type: :service do
|
||||
expect(result).to include('1. first step')
|
||||
expect(result).to include('2. second step')
|
||||
end
|
||||
|
||||
it 'renders code blocks as plain text' do
|
||||
content = "```\ncode here\n```"
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result.strip).to eq('code here')
|
||||
end
|
||||
|
||||
it 'handles code blocks with emojis and special characters without stack overflow' do
|
||||
content = " first line\n 🌐 second line\n"
|
||||
result = described_class.new(content, channel_type).render
|
||||
expect(result).to eq("first line\n🌐 second line")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when channel is Channel::TwilioSms' do
|
||||
|
||||
Reference in New Issue
Block a user