How to extend redcarpet to support auto linking user mentions?

青春壹個敷衍的年華 提交于 2019-12-18 13:27:24

问题


On my rails3 application I want to use redcarpet to handle user's posts and the user comment section. As such I'd like to extend redcarpet to support turning @username into a link to a user on my site. I know redcarpet is written in C but is there anyway easy way to extend it in ruby? How hard would it be to write it in C? Should I just do this outside of redcarpet?

Also I'm intrested in some other extensions of redcarpet that would be shorthand for linking to other models in my app. I'm not sure the syntax yet but I'm guessing it would be similar to how github handles linking to issues.


回答1:


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>.




回答2:


I once tried to extend redcarpet, but found it very difficult. If there are no other dependencies on redcarpet I'd recommend you try rpeg-markdown which is a (somewhat outdated) Ruby gem providing bindings to the excellent peg-markdown.

peg-markdown is a markdown interpreter written as a formal grammar. This means that it is very easy to extend it with own syntax. I've successfully extended peg-markdown for my own projects (see my fork here) and I found it to be much simpler than fiddling with redcarpet's custom parser code.

I also found peg-markdown to have fewer bugs.

The Ruby bindings may have to be made current by updating the git submodule. (I'm planning to submit a pull request to update rpeg-markdown to the latest version of peg-markdown.)



来源:https://stackoverflow.com/questions/12381230/how-to-extend-redcarpet-to-support-auto-linking-user-mentions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!