diff --git a/app/helpers/markdownify_helper.rb b/app/helpers/markdownify_helper.rb index 42febefeef51530a5368b43635be290f3e749af2..a49ce2381e39d27f760c71cce0113435d86b3f9f 100644 --- a/app/helpers/markdownify_helper.rb +++ b/app/helpers/markdownify_helper.rb @@ -5,8 +5,8 @@ require File.expand_path("#{Rails.root}/lib/diaspora/markdownify") module MarkdownifyHelper - def markdownify(message, render_options={}) - return '' if message.blank? + def markdownify(target, render_options={}) + markdown_options = { :autolink => true, :fenced_code_blocks => true, @@ -18,9 +18,30 @@ module MarkdownifyHelper render_options[:filter_html] = true + + # This ugly little hack basically means + # "Give me the rawest contents of target available" + if target.respond_to?(:raw_message) + message = target.raw_message + elsif target.respond_to?(:text) + message = target.text + else + message = target.to_s + end + + return '' if message.blank? + renderer = Diaspora::Markdownify::HTML.new(render_options) markdown = Redcarpet::Markdown.new(renderer, markdown_options) + message = markdown.render(message) + + if target.respond_to?(:format_mentions) + message = target.format_mentions(message) + end + + message = Diaspora::Taggable.format_tags(message, :no_escape => true) + return message.html_safe end diff --git a/app/views/comments/_comment.html.haml b/app/views/comments/_comment.html.haml index b92be2366003330bcc706f9c0f3606e7504483ed..4ecef5d38e9405c39c68d44d4c9186d445ad9e71 100644 --- a/app/views/comments/_comment.html.haml +++ b/app/views/comments/_comment.html.haml @@ -14,7 +14,7 @@ – %span{:class => direction_for(comment.text)} - = markdownify(Diaspora::Taggable.format_tags(comment.text), :youtube_maps => comment.youtube_titles) + = markdownify(comment, :youtube_maps => comment.youtube_titles) .comment_info %time.timeago{:datetime => comment.created_at} diff --git a/app/views/comments/_comment.mobile.haml b/app/views/comments/_comment.mobile.haml index 6056839f0d6b0ecc825e0f23fc4b132c31123d15..19738dc6bfb0c4fb398765a1b03059d6aae7a100 100644 --- a/app/views/comments/_comment.mobile.haml +++ b/app/views/comments/_comment.mobile.haml @@ -15,5 +15,5 @@ .from = person_link(comment.author) %p{ :class => direction_for(comment.text) } - = markdownify(comment.text, :youtube_maps => comment[:youtube_titles]) + = markdownify(comment, :youtube_maps => comment[:youtube_titles]) diff --git a/app/views/messages/_message.haml b/app/views/messages/_message.haml index da5d1f5066dbe27c53f75ff50bf233cc2bbff1de..7b5ff3264938d0e0a02e49325c0b01fa082874a7 100644 --- a/app/views/messages/_message.haml +++ b/app/views/messages/_message.haml @@ -12,5 +12,5 @@ = how_long_ago(message) %p{ :class => direction_for(message.text) } - = markdownify(message.text) + = markdownify(message) diff --git a/app/views/photos/show.html.haml b/app/views/photos/show.html.haml index 2d8f2885d7cefe6181e540b685b776e95767a7fd..f68e919a7302c69ba7210b02ac5bc10bdf44bc2e 100644 --- a/app/views/photos/show.html.haml +++ b/app/views/photos/show.html.haml @@ -40,7 +40,7 @@ .span-8.last %p - = markdownify(photo.status_message.text) + = markdownify(photo.status_message) %span{:style=>'font-size:smaller'} =link_to t('.collection_permalink'), post_path(photo.status_message) %br diff --git a/app/views/posts/show.mobile.haml b/app/views/posts/show.mobile.haml index af3a960a1c70f05e7aca4166c6abc16b44bb7f3e..faa1bf245b2bf1c96340f4995dec4e80bbbb6051 100644 --- a/app/views/posts/show.mobile.haml +++ b/app/views/posts/show.mobile.haml @@ -11,7 +11,7 @@ = render 'reshares/reshare', :reshare => @post, :post => @post.root - else %p - = markdownify(@post.text, :youtube_maps => @post[:youtube_titles]) + = markdownify(@post, :youtube_maps => @post[:youtube_titles]) - for photo in @post.photos = link_to (image_tag photo.url(:thumb_small), :class => 'thumb_small'), photo.url(:thumb_medium) diff --git a/app/views/status_messages/_status_message.haml b/app/views/status_messages/_status_message.haml index c3be5bad94582808eed3ad63d28fcef8f1b30196..73b43c2487e7eac4f60845f60078d293157a5008 100644 --- a/app/views/status_messages/_status_message.haml +++ b/app/views/status_messages/_status_message.haml @@ -16,4 +16,4 @@ = link_to (image_tag photo.url(:thumb_small), :class => 'stream-photo thumb_small', 'data-small-photo' => photo.url(:thumb_medium), 'data-full-photo' => photo.url), photo_path(photo), :class => 'stream-photo-link' %p{:class => direction_for(post.text)} - != markdownify(post.text, :youtube_maps => post[:youtube_titles]) + != markdownify(post, :youtube_maps => post[:youtube_titles]) diff --git a/lib/diaspora/markdownify.rb b/lib/diaspora/markdownify.rb index 0d2d01f725a39b5cca17eee0f5c48a04039cf298..8515cf881b0f84ba6399fb9cf76a26c0b62e8948 100644 --- a/lib/diaspora/markdownify.rb +++ b/lib/diaspora/markdownify.rb @@ -8,7 +8,6 @@ module Diaspora def initialize(options={}) super - @expand_tags = options.fetch(:expand_tabs, true) @newlines = options.fetch(:newlines, true) @specialchars = options.fetch(:specialchars, true) @youtube_maps = options.fetch(:youtube_maps, {}) @@ -100,10 +99,6 @@ module Diaspora end def paragraph(text) - if @expand_tags - text = Diaspora::Taggable.format_tags(text, :no_escape => true) - end - if @newlines br = linebreak @@ -118,6 +113,15 @@ module Diaspora end def preprocess(full_document) + entities = { + '>' => '>', + '<' => '<', + '&' => '&', + } + entities.each do |k,v| + full_document = full_document.gsub(k, v) + end + if @specialchars full_document = specialchars(full_document) end @@ -152,10 +156,10 @@ module Diaspora def specialchars(text) if @specialchars map = [ - ["<3", "♥"], - ["<->", "↔"], - ["->", "→"], - ["<-", "←"], + ["<3", "♥"], + ["<->", "↔"], + ["->", "→"], + ["<-", "←"], ["\.\.\.", "…"], ["(tm)", "™"], ["(r)", "®"], diff --git a/spec/helpers/markdownify_helper_spec.rb b/spec/helpers/markdownify_helper_spec.rb index a9ec0048831d6aaae36d8b8c585ea8d9f235c300..a86cb13d14381f63306f6fb77ac24447b7b40af7 100644 --- a/spec/helpers/markdownify_helper_spec.rb +++ b/spec/helpers/markdownify_helper_spec.rb @@ -5,10 +5,11 @@ require 'spec_helper' describe MarkdownifyHelper do + describe "#markdownify" do describe "autolinks" do it "should not allow basic XSS/HTML" do - markdownify("<script>alert('XSS is evil')</script>").should == "<p>alert('XSS is evil')</p>" + markdownify("<script>alert('XSS is evil')</script>").should == "<p><script>alert('XSS is evil')</script></p>" end it "should recognize basic http links (1/3)" do @@ -250,12 +251,6 @@ describe MarkdownifyHelper do markdownify(message).should == '<p>This <a target="_blank" href="http://en.wikipedia.org/wiki/Text_%28literary_theory%29"><em>text</em></a> with many <a target="_blank" href="http://google.com">links</a> tests <a target="_blank" href="http://google.com/search?q=with_multiple__underscores*and**asterisks"><em>http</em></a>, <a target="_blank" href="ftp://ftp.uni-kl.de/CCC/26C3/mp4/26c3-3540-en-a_hackers_utopia.mp4" title="File Transfer Protocol"><em><strong>FTP</strong></em></a>, <a target="_blank" href="foo://bar.example.org/yes_it*makes*no_sense"><strong>any protocol</strong></a></p>' end - it "should leave #tag links intact" do - message = %{<a href="/tags/tagged" class="tag">#tagged</a>} - markdownify(message).should == "<p>#{message}</p>" - message = %{alice - 1 - <a href="/tags/tagged" class="tag">#tagged</a>} - markdownify(message).should == "<p>#{message}</p>" - end end describe "nested emphasis and links tags" do @@ -294,6 +289,26 @@ describe MarkdownifyHelper do markdownify(nil).should == '' end + context 'when formatting status messages' do + + it "should leave tags intact" do + message = Factory.create(:status_message, + :author => alice.person, + :text => "I love #markdown") + formatted = markdownify(message) + formatted.should =~ %r{<a href="/tags/markdown" class="tag">#markdown</a>} + end + + it "should leave mentions intact" do + message = Factory.create(:status_message, + :author => alice.person, + :text => "Hey @{Bob; #{bob.diaspora_handle}}!") + formatted = markdownify(message) + formatted.should =~ /hovercard/ + end + + end + context 'performance' do before do @message = "HHello,Hello_, I _am a strong robot.*Hello, I am *a strong robot.Hello, I am a strong robot.Hello, I am a strong robot.Hello, I am a strong robot.Hello, I am a **strong robot.Hello, I am _a _strong *robot**.Hello*, I am a strong "