How to Extend Redcarpet to Support Auto Linking User Mentions

How to extend redcarpet to support auto linking user mentions?

I found it pretty easy to extend redcarpet's parser in Ruby for my rails 3 app. It wasn't scary at all.

First, start by deriving a class from Redcarpet's HTML renderer and override the preprocess method as recommended in the docs. In Rails 3.2 and Rails 4, this file can go anywhere and you don't need to require it. I use a 'services' folder to hold code like this.

# app/services/my_flavored_markdown.rb
class MyFlavoredMarkdown < Redcarpet::Render::HTML
def preprocess(text)
text
end
end

Next step is to add methods that do text substitutions you want. Here I use regex to wrap text that looks like "@mention" in an HTML span tag with a css class 'mention'.

# app/services/my_flavored_markdown.rb
class MyFlavoredMarkdown < Redcarpet::Render::HTML

def preprocess(text)
wrap_mentions(text)
end

def wrap_mentions(text)
text.gsub! /(^|\s)(@\w+)/ do
"#{$1}<span class='mention'>#{$2}</span>"
end
text
end

end

You could just as easily look up a user's profile page and wrap the @mention in an anchor tag instead. In my case, I also made methods for emoticons and hashtags that worked the same way and chained the methods together.

The last step is to add a helper that accepts some text, creates an instance of your Redcarpet-derived class, passes the text into that for processing, and returns the html result.

# app/helpers/application_helper.rb
def flavored_markdown_to_html(text)
renderer = MyFlavoredMarkdown.new()
# These options might be helpful but are not required
options = {
safe_links_only: true,
no_intra_emphasis: true,
autolink: true
}
Redcarpet::Markdown.new(renderer, options).render(text)
}

In your views you can call it like this:

<%= flavored_markdown_to_html("This is something worth @mentioning") %>

The output would then be:

This is something worth <span class='mention'>@mentioning</span>.

How to embed a YouTube video in Markdown with Redcarpet for Rails?

The simplest solution seems to be the following. I use http://youtube/VMD-z2Xni8U in my Markdown to embed a YouTube video. I then allow autolinking in Redcarpet to autolink this.

# /lib/helpers/markdown_renderer_with_special_links.rb
class MarkdownRendererWithSpecialLinks < Redcarpet::Render::HTML
def autolink(link, link_type)
case link_type
when :url then url_link(link)
when :email then email_link(link)
end
end
def url_link(link)
case link
when /^http:\/\/youtube/ then youtube_link(link)
else normal_link(link)
end
end
def youtube_link(link)
parameters_start = link.index('?')
video_id = link[15..(parameters_start ? parameters_start-1 : -1)]
"<iframe width=\"560\" height=\"315\" src=\"//www.youtube.com/embed/#{video_id}?rel=0\" frameborder=\"0\" allowfullscreen></iframe>"
end
def normal_link(link)
"<a href=\"#{link}\">#{link}</a>"
end
def email_link(email)
"<a href=\"mailto:#{email}\">#{email}</a>"
end
end

I then create a markdown method to use in any view or controller when displaying markdown content:

# /app/helpers/application_helper.rb
module ApplicationHelper
require './lib/helpers/markdown_renderer_with_special_links'
def markdown(content)
@markdown ||= Redcarpet::Markdown.new(MarkdownRendererWithSpecialLinks, autolink: true, space_after_headers: true, fenced_code_blocks: true)
@markdown.render(content).html_safe
end
end

Has anyone figured out how to embed video using the Redcarpet gem for Markdown in Rails 3.2?

Make sure the :filter_html flag is disabled in your renderer.

Redcarpet::Render::HTML.new(:filter_html => false)

EDIT:

If you want to let only certain html tags through, you have to create a custom Renderer (here's how) and define the block_html method.

For example:

class MyRenderer < Redcarpet::Render::HTML
def block_html(raw_html)
if raw_html =~ /^<iframe.*>$/ # You may want to optimize this.
raw_html
end
end
end

Then set :filter_html back to true when you call your own renderer:

MyRenderer.new(:filter_html => true)

How to get rid of additional spaces using redcarpet gem (Ruby on Rails)

This is caused by Haml indenting the block so that the output HTML is neatly formatted, which is often what people want but can cause issues with whitespace sensitive code like this.

There are a couple of ways to fix it. Firstly if you run with the :ugly option set to true (which should be the case in production) then the extra whitespace won’t be added anywhere and you’ll get the desired result.

Alternatively you can use the whitespace preservation operator ~ instead of =. This will convert all newlines in the block to the entity ( ), and so no extra whitespace will be added (as there are no newlines to add it to). This will change the HTML produces, but will look as you want when viewed in the browser.

how to write a table of contents with jekyll and redcarpet

The problem here is that :with_toc_data is an option for an instance of the redcarpet renderer, and not a configuration extension.

Unfortunately, Jekyll doesn't seem to expose this renderer option, so I don't think you'll be able to use it. The docs say:

no renderer options aside from smart can be specified in Jekyll.

But you can use a table of contents jekyll plugin instead. A quick search returns a number of available options, and one is linked from the official Jekyll site.



Related Topics



Leave a reply



Submit