Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Modify Redcarpet Markdown so it can handle classes?

I'm using Redcarpet Markdown on my Rails site. Often I'd like to add classes (or other attributes) to a paragraph, table or other element, but it doesn't allow it. If I replace the markdown element with HTML, then I need to replace the inside markdown with HTML too, which is a nuisance.

For example, I want to add the class "table" to the markdown table element (so it get's Bootstrap's table styling), but then I'll need to replace the Markdown table with HTML.

What's the simplest solution to this? Is there an easy way to modify the Markdown so it can handle classes? Alternatively, is there a way to allow Markdown inside an HTML element?

Example Update

I want to add a class to a div, table or paragraph, but still keep markdown inside the element. For example, I want to generate the following HTML:

<p class="cool">
  <b>Hello world</b> <a href="http://google.com">Google</a>
</p>

There are 2 possible solutions, but I don't know how to do them with Redcarpet Markdown:

  1. Get special markdown syntax for classes, eg:

    {class: cool}
    **Hello world** [Google](http://google.com)

  2. Allow Markdown to work within HTML elements:

    <p class="cool">
    **Hello world** [Google](http://google.com)
    </p>

Currently I'm just doing such elements in pure HTML without markdown. But how can I get #1 or #2 to work?

like image 217
am-rails Avatar asked Jan 30 '14 00:01

am-rails


1 Answers

You can build your own renderer (based on Redcarpet::Render::HTML), which will override the methods you are interested in customizing:

Custom renderers are created by inheriting from an existing renderer. The built-in renderers, HTML and XHTML may be extended as such:

# create a custom renderer that allows highlighting of code blocks
class HTMLwithPygments < Redcarpet::Render::HTML
  def block_code(code, language)
    Pygments.highlight(code, :lexer => language)
  end
end

markdown = Redcarpet::Markdown.new(HTMLwithPygments, :fenced_code_blocks => true)

But new renderers can also be created from scratch (see lib/redcarpet/render_man.rb for an example implementation of a Manpage renderer)

<<snip>>

The following instance methods may be implemented by the renderer:

<<snip>>

  • table(header, body)

<<snip>>

  • raw_html(raw_html)

For example, to enable markdown inside raw HTML, I would suggest declaring a <markdown> element, which you can extract, and render (Warning - untested code ahead):

def raw_html(html)
  html.gsub(/<markdown>(.*)<\/markdown>/) { render $1 }
end

Override these methods to either add the needed class to your table, or to recursively call render from elements in your raw HTML.

like image 84
Uri Agassi Avatar answered Oct 06 '22 00:10

Uri Agassi