2012-07-07 00:52:32 +02:00
|
|
|
class Markdowner
|
2013-03-24 03:05:13 +01:00
|
|
|
# opts[:allow_images] allows <img> tags
|
|
|
|
# opts[:disable_profile_links] disables @username -> /u/username links
|
|
|
|
|
|
|
|
def self.to_html(text, opts = {})
|
2012-07-07 00:52:32 +02:00
|
|
|
if text.blank?
|
|
|
|
return ""
|
2013-03-24 03:05:13 +01:00
|
|
|
end
|
|
|
|
|
2017-05-20 15:27:33 +02:00
|
|
|
exts = [:tagfilter, :autolink, :strikethrough]
|
2017-05-20 15:25:09 +02:00
|
|
|
root = CommonMarker.render_doc(text.to_s, [:SMART], exts)
|
2017-05-20 15:26:11 +02:00
|
|
|
|
|
|
|
unless opts[:disable_profile_links]
|
|
|
|
walk_text_nodes(root) {|n| postprocess_text_node(n)}
|
|
|
|
end
|
|
|
|
|
2017-05-20 15:25:09 +02:00
|
|
|
ng = Nokogiri::HTML(root.to_html([:SAFE], exts))
|
2015-12-03 22:56:52 +01:00
|
|
|
|
|
|
|
# change <h1>, <h2>, etc. headings to just bold tags
|
|
|
|
ng.css("h1, h2, h3, h4, h5, h6").each do |h|
|
|
|
|
h.name = "strong"
|
|
|
|
end
|
2013-03-24 03:05:13 +01:00
|
|
|
|
2017-05-20 15:25:09 +02:00
|
|
|
if !opts[:allow_images]
|
|
|
|
ng.css("img").remove
|
|
|
|
end
|
|
|
|
|
2013-03-24 03:05:13 +01:00
|
|
|
# make links have rel=nofollow
|
2015-12-03 22:56:52 +01:00
|
|
|
ng.css("a").each do |h|
|
2017-05-20 15:26:11 +02:00
|
|
|
h[:rel] = "nofollow" unless h[:href].starts_with?("/")
|
2015-12-03 22:56:52 +01:00
|
|
|
end
|
2013-03-24 03:05:13 +01:00
|
|
|
|
2017-05-20 15:26:11 +02:00
|
|
|
ng.at_css("body").inner_html
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.walk_text_nodes(node, &block)
|
|
|
|
return if node.type == :link
|
|
|
|
return block.call(node) if node.type == :text
|
|
|
|
|
|
|
|
node.each do |child|
|
|
|
|
walk_text_nodes(child, &block)
|
2012-07-07 00:52:32 +02:00
|
|
|
end
|
2017-05-20 15:26:11 +02:00
|
|
|
end
|
2013-03-24 03:05:13 +01:00
|
|
|
|
2017-05-20 15:26:11 +02:00
|
|
|
def self.postprocess_text_node(node)
|
|
|
|
while node
|
|
|
|
return unless node.string_content =~ /\B(@[\w\-]+)/
|
|
|
|
before, user, after = $`, $1, $'
|
|
|
|
|
|
|
|
node.string_content = before
|
|
|
|
|
|
|
|
if User.exists?(:username => user[1..-1])
|
|
|
|
link = CommonMarker::Node.new(:link)
|
|
|
|
link.url = "/u/#{user[1..-1]}"
|
|
|
|
node.insert_after(link)
|
|
|
|
|
|
|
|
link_text = CommonMarker::Node.new(:text)
|
|
|
|
link_text.string_content = user
|
|
|
|
link.append_child(link_text)
|
|
|
|
|
|
|
|
node = link
|
|
|
|
else
|
|
|
|
node.string_content += user
|
|
|
|
end
|
|
|
|
|
|
|
|
if after.length > 0
|
|
|
|
remainder = CommonMarker::Node.new(:text)
|
|
|
|
remainder.string_content = after
|
|
|
|
node.insert_after(remainder)
|
|
|
|
|
|
|
|
node = remainder
|
|
|
|
else
|
|
|
|
node = nil
|
|
|
|
end
|
|
|
|
end
|
2012-07-07 00:52:32 +02:00
|
|
|
end
|
2012-09-16 22:51:25 +02:00
|
|
|
end
|