Using ERB in Markdown with Redcarpet in Rails 7.1

89 Views Asked by At

I am trying to add Markdown support in Rails 7.1.1 app.
Redcarpet gem version is 3.6.0.

I follow advice from this question:
Using ERB in Markdown with Redcarpet

My current code (in /config/initializers/markdown_handler.rb) is:

module MarkdownHandler
  def self.erb
    @erb ||= ActionView::Template.registered_template_handler(:erb)
  end

  def self.call(template, source)
    compiled_source = erb.call(template, source)
    "Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(begin;#{compiled_source};end).html_safe"
  end
end

ActionView::Template.register_template_handler :md, MarkdownHandler

And I get an error:
ActionView::Template::Error: wrong argument type ActionView::OutputBuffer (expected String)

Could someone kindly explain why is it happening and how to fix it, please?

1

There are 1 best solutions below

0
On

The custom template handler uses compiled output from ActionView::Template::Handlers::ERB.
The output was String but since Rails 7.1 it's ActionView::OutputBuffer (https://github.com/rails/rails/commit/ee68644c284aa7512d06b4b5514b1236c1b63f55).
Commit message describes why this change was made:

With the recent changes to OutputBuffer, calling to_s is extremely expensive if the buffer later is concatenated to (if the buffer never changes it should be relatively inexpensive, as Ruby will share memory).

So we see an error:
ActionView::Template::Error: wrong argument type ActionView::OutputBuffer (expected String)

To fix it we can simply convert to String:

module MarkdownHandler
  def self.erb
    @erb ||= ActionView::Template.registered_template_handler(:erb)
  end

  def self.call(template, source)
    compiled_source = erb.call(template, source)
    "Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(begin;#{compiled_source};end.to_s).html_safe"
  end
end

ActionView::Template.register_template_handler :md, MarkdownHandler