module GitHubParser extend self class HTMLWithPantsRenderer < Redcarpet::Render::HTML include Redcarpet::Render::SmartyPants def block_code(code, language) if language language.sub!(/\Alang(uage)?-/, '') %{
#{html_escape(code)}
} else %{
#{html_escape(code)}
} end end private # This is a method copy/pasted from redcarpet/lib/redcarpet.rb # It's a private instance method on the Render::Safe class which inherits # from the HTML renderer. # I'm not sure why our tests expect escaped code while we inherit from the # HTML renderer and not the Safe renderer though. def html_escape(string) string.gsub(/['&\"<>\/]/, { '&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => ''', "/" => '/', }) end end def self.parse(markdown) html = github_parser.render(markdown.to_s) doc = Nokogiri::HTML5::DocumentFragment.parse(html) special_blocks(doc) doc end private def self.github_parser @@github_parser ||= Redcarpet::Markdown.new(HTMLWithPantsRenderer, fenced_code_blocks: true, tables: true, no_intra_emphasis: true) end def self.special_blocks(doc) doc.css('blockquote>p:first').each do |node| if match = node.inner_html.match(/\A\W*(callout|warning|note)\W/) node.parent.name = 'div' node.parent['class'] = match[1] new_html = node.inner_html.gsub(/\A\W*(callout|warning|note)\W/, '') # Assigning inner_html directly causes encoding issues in old libxml versions, # workaround from https://github.com/sparklemotion/nokogiri/issues/458#issuecomment-3136620 node.children = Nokogiri::HTML.fragment(new_html, 'utf-8') end end end end