How to Modify Redcarpet Markdown so it can handle classes?
Asked Answered
B

1

10

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?

Besmirch answered 30/1, 2014 at 0:49 Comment(4)
Could you add some example of desired syntax and expected output?Impervious
If possible, a sample of the way you are using right now to get something close.Hoey
@UriAgassi I added an example.Besmirch
@daviscabral, I'm using HTML currently.Besmirch
I
3

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.

Impervious answered 18/2, 2014 at 20:38 Comment(3)
How would you recursively call render from e.g. every div?Besmirch
Thanks. So I should stick that method in a class MarkdownMore < Redcarpet::Render::HTML somewhere in Rails?Besmirch
Yes, and then use markdown = new Redcarpet::Markdown.new(MarkdownMore, ...)Impervious

© 2022 - 2024 — McMap. All rights reserved.