2

I'm using Middleman (and Ruby, and Rails) for the first time, and I've hit a bit of a roadblock when it comes to rendering individual pages using Redcarpet as my markdown processor, and ERb for layout.

I want to use Markdown to style individual blocks of content, but each page will have more than one piece of content, uniquely styled.

Rather than using partials, is there a way to instantiate the Redcarpet renderer on multiple areas of the page? So in index.html.erb, there would be something like this:

<div class="grid5 container">
    <% markdown do %>
    # Some markdown
    <% end %>
</div>

<section class="grid6">
    <% markdown do %>
    ## More markdown
    <% end %>
</section>

I've tried to build a helper based on several tutorials, but I'm just not that good at Rails yet.

Edit My config.rb helper looks like:

module MD
    def markdown(text)
        Redcarpet.new(text).to_html
    end
end

helpers MD

per ASCIIcasts, linked above, and my ERb template uses similar code to the above:

<span class="g6 pre3">
<% markdown do %>
...etc...
<% end %>

but I'm getting an error when I load the page: ArgumentError at /about wrong number of arguments (0 for 1)

Community
  • 1
  • 1
bigsweater
  • 498
  • 1
  • 6
  • 19
  • I'm actually not really understanding your problem? Why does the helper built in the Railscast for example does not work multiple times in a view? Yes, it is not very performant to recreate the Renderer for every Markdown section, but it should work, right? Or do you want to know how to make it more efficient? – lawitschka Sep 20 '13 at 15:14
  • It's not working at all, actually, and I can't quite figure out why. I'll update the question with the code I'm using and the error I'm getting... – bigsweater Sep 20 '13 at 15:17
  • OK, let's do that and then we'll see! – lawitschka Sep 20 '13 at 15:22
  • @lawitschka Updated to include a bit more info about the code itself. – bigsweater Sep 20 '13 at 16:25
  • The 'wrong number of arguments' error is pointing specifically to line that says `def markdown(text)`. – bigsweater Sep 20 '13 at 16:26

5 Answers5

4

You defined your markdown method to receive one parameter called text. But what you provide in your views is a block.

To make things work, you either change the way you call the markdown helper method in the view

<%= markdown 'this is some markdown text in here' %>

or you change the markdown helper to accept a block

def markdown
  Redcarpet.new(yield).to_html
end

P.S.: The Redcarpet syntax has changed a bit since the Railscast, so if you are using a more recent gem version, implementing it this way won't work.

Starting at least from 3.3.4, perhaps earlier, you have to create a specific renderer and then call render on it with the markdown as an argument, i.e.

def markdown
   Redcarpet::Render::XHTML.new.render(yield)
end

Up to date documentation can be found here: https://github.com/vmg/redcarpet

sameers
  • 4,855
  • 3
  • 35
  • 44
lawitschka
  • 745
  • 3
  • 9
  • I actually tried something similar to your latter example, as well, based on the original documentation (and [an article linked from it](http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html)), but couldn't get it to work. The `def` above results in an error, so I hid it behind a helper, [as you can see on pastebin](http://pastebin.com/jHFtC19V). The helper returns the text, but just as plain text--no markdown parsing. What the heck am I doing wrong? Am I even approaching this from the correct angle? – bigsweater Sep 21 '13 at 06:35
  • Created [a gist](https://gist.github.com/bigsweater/6647871) actually, for the sake of the pullings and the forkings. The description of the gist should help explain what I'm trying to accomplish. – bigsweater Sep 21 '13 at 06:42
  • I just discovered by doing a `puts markdown.render(yield)` from the above gist that Redcarpet _is_ processing the block; I'm just not sure, now, how to replace the un-processed block with the processed one. – bigsweater Sep 22 '13 at 02:05
  • Just like you did it in your question above. Use ERB tags in your view and put markdown in your block. Remember to use the ERB tag with the equal sign, i.e. <%= %>. Otherwise the method's result won't show up in your view. – lawitschka Sep 22 '13 at 09:27
  • I did that, but I get a weird syntax error: `/path/to/about.html.erb:2: syntax error, unexpected ')' ; @_out_buf.concat(( md do ).to_s) ^ /path/to/about.html.erb:66: syntax error, unexpected keyword_ensure, expecting ')' /path/to/about.html.erb:68: syntax error, unexpected keyword_end, expecting ')'` Confusing because there's no `)` on line 2 of about.erb, nor `keyword_ensure` on line 68. – bigsweater Sep 22 '13 at 11:34
  • I created a Gist for Redcarpet in Rails. This way it works with Rails. https://gist.github.com/lawitschka/6667570. I tried the same with Middleman and get the same error you get. It tries do evaluate the ERB but does not capture the whole block but stops at the end of the ERB tag. It looks like a bug in the Tilt gem (i.e. ERB renderer) or Tilt simply does not support ERB blocks. When using HAML it worked... – lawitschka Sep 23 '13 at 08:22
  • Hmm. I'll file a bug then. ERB is one of the templating languages Middleman is built to be used with, so I don't see why it wouldn't support ERB blocks...then again, I'm a newb at this thing. Thank you very much for investigating. – bigsweater Sep 23 '13 at 20:31
1

I had the same issue. Above didn't work. This is a much simpler solution with no custom code.

https://github.com/middleman/middleman/issues/1221#issuecomment-38104894

don.najd
  • 630
  • 6
  • 12
1

This is what I did:

helpers do
  def markdown(&block)
    raise ArgumentError, "Missing block" unless block_given?
    content = capture_html(&block)
    concat Tilt['markdown'].new { content }.render
  end
end

It uses the default Middleman markdown render.

danigb
  • 711
  • 6
  • 13
1

Helper to convert a markdown String to html in middleman

helpers do
    def markdown(content)
        Tilt['markdown'].new(context: @app) { content }.render
    end
end

Set context: @app argument to handle images, links with middleman helpers and avoid exceptions.

Atika
  • 1,560
  • 18
  • 18
0

I tried several methods I found here, with no success. Finally this is the solution that worked for me:

def markdown(text)
  require 'redcarpet'
  require 'redcarpet/render_strip'
  markdown = Redcarpet::Markdown.new(Redcarpet::Render::StripDown)
  Markdown.new(text).to_html
end
GuayoMena
  • 53
  • 1
  • 9