Using ERB in Markdown with Redcarpet
Asked Answered
K

2

7

I'm trying to get Markdown to play nicely with .erb. I'd like to use high_voltage to render markdown pages (or normal .html.erb files with markdown partials) that are parsed with Redcarpet and am struggling to get it to all work together.

At the moment I have an initializer called markdown_template_handler.rb that contains the following code:

class MarkdownTemplateHandler
  def erb
    @erb ||= ActionView::Template.registered_template_handler(:erb)
  end

  def call(template)
    compiled_source = erb.call(template)
    markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)

    "#{markdown.render(compiled_source.source).inspect}.html_safe;"
  end
end

ActionView::Template.register_template_handler(:md, MarkdownTemplateHandler.new)

However it is failing at line 7, compiled_source = erb.call(template) with the error code saying "wrong number of arguments (given 1, expected 2)"

I looked at the ERB Ruby documentation but from what I understood, the call method is a derivative of the new method, which only requires 1 argument, the text. However, when I tried to use it just in a quick rails console session, it also required two arguments.

When I remove the requirement to parse erb from the above code, everything works as expected, so I don't think it has anything to do with Redcarpet not working.

I am using Rails v6.0.0.rc1 & Ruby v2.5.3p105

Any help is appreciated.

Edit

Further research has led me to finding the Rails 6.0 ERB ActionView template handler. The call method of this handler does indeed require two arguments, the template and the source. That said, in Rails 5.2.3, the ERB Action View template handler call method only requires one argument, the template.

Could someone please point me in the direction of figuring out what source is in this context? There is no documentation for it that I can find.


Kitsch answered 22/6, 2019 at 11:38 Comment(0)
M
7

In this case, source would be passed to the call by ActionView when the handler is called.

You would rewrite your call function like that:

def call(template, source)
  compiled_source = erb.call(template, source)
  markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)

  "#{markdown.render(compiled_source).inspect}.html_safe;"
end

Before Rails 6, the source value was extracted from template.source, but it is now passed as a separate parameter.

Mannuela answered 25/6, 2019 at 21:11 Comment(0)
A
6

This approach for rendering markdown with ERB in Rails 6 worked well for me. Thanks to Louis-Michel for pointing me in the right direction, including both parameters in the call.

require 'redcarpet'

class MarkdownTemplateHandler

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

  def 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, MarkdownTemplateHandler.new)
Anthem answered 14/3, 2020 at 1:27 Comment(4)
This works great for me with Rails 7Sparklesparkler
I get the error, wrong argument type ActionView::OutputBuffer (expected String). It looks like it's from a render call. Digging into it.Cherrylchersonese
Maybe the Redcarpet#render API changed. This works in Rails 7.1 (adding .to_s): "Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(begin;#{compiled_source};end.to_s).html_safe"Cherrylchersonese
@Cherrylchersonese It's not because of Redcarpet#render API change. It's because of change in Rails 7.1 ActionView. I wrote down details here, please see: https://mcmap.net/q/394098/-using-erb-in-markdown-with-redcarpet-in-rails-7-1Neither

© 2022 - 2024 — McMap. All rights reserved.