assemblymade/coderwall

View on GitHub
lib/cfm.rb

Summary

Maintainability
A
0 mins
Test Coverage
# encoding: utf-8

#coderwall flavored markdown
module CFM
  class Markdown
    class << self
      def render(text)
        return nil if text.nil?

        extensions = {
          fenced_code_blocks: true,
          strikethrough: true,
          autolink: true
        }

        renderer  = Redcarpet::Render::HTML.new(  link_attributes: {rel: "nofollow"})
        redcarpet = Redcarpet::Markdown.new(renderer, extensions)
        html      = redcarpet.render(render_cfm(text))
        html      = add_nofollow(html)
        html
      end

      USERNAME_BLACKLIST = %w(include)

      private

      def add_nofollow( html)
        #redcarpet isn't adding nofollow like it is suppose to.
       html.scan(/(\<a href=["'].*?["']\>.*?\<\/a\>)/).flatten.each do |link|
         if link.match(/\<a href=["'](http:\/\/|www){0,1}((coderwall.com)(\/.*?){0,1}|\/.*?)["']\>(.*?)\<\/a\>/)
          else
          link.match(/(\<a href=["'](.*?)["']\>(.*?)\<\/a\>)/)
          html.gsub!(link, "<a href='#{$2}' rel='nofollow' >#{$3}</a>" )
          end
        end
        html
      end

      def render_cfm(text)
        text.lines.map do |x|
          inspect_line(x)
        end.join('')
      end

      def coderwall_user_link(username)
        (User.where(username: username).exists? && !USERNAME_BLACKLIST.include?(username)) ? ActionController::Base.helpers.link_to("@#{username}", "/#{username}") : "@#{username}"
      end

      def inspect_line(line)
        #hotlink coderwall usernames to their profile, but don't search for @mentions in code blocks
        if line.start_with?('    ')
          line
        else
          line.gsub(/((?<!\s{4}).*)@([a-zA-Z_\-0-9]+)/) { $1+coderwall_user_link($2) }
        end
      end
    end
  end
end