Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ERB in Markdown with Redcarpet

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.


like image 410
Rich Avatar asked Jun 22 '19 11:06

Rich


People also ask

How does the redcarpet library work?

The core of the Redcarpet library is the Redcarpet::Markdown class. Each instance of the class is attached to a Renderer object; the Markdown class performs parsing of a document and uses the attached renderer to generate output.

Is Jinja2 or ERB better for scraping comments from source code?

While both Jinja2 and ERB are excellent for generating website markup, the ability to use all of Ruby’s language features in the templates - especially its Perl-like string manipulation features - made it much better-suited to tasks like scraping comments from source code.

Why do you use Ruby for Erb templating?

And the Ruby code is clean and simple and introduces no serious maintenance burden. I originally intended to use Python and Jinja2, because Python is a popular and easy language, but in the end I found benefits in the ERB templating that outweighed other considerations.

What is redcarpet?

Redcarpet is a Ruby library for Markdown processing that smells like butterflies and popcorn. Redcarpet was written by Vicent Martí. It is maintained by Robin Dupret and Matt Rogers. Redcarpet would not be possible without the Sundown library and its authors (Natacha Porté, Vicent Martí, and its many awesome contributors).


2 Answers

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.

like image 150
louim Avatar answered Oct 22 '22 00:10

louim


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)
like image 32
Don Davies Avatar answered Oct 21 '22 23:10

Don Davies