diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9f1432300..8b94c832d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,7 +4,7 @@ class ApplicationController < ActionController::Base clear_helpers - helper :layout, :error_messages + helper :layout, :error_messages, :markdownify, :aspect_global has_mobile_fu protect_from_forgery :except => :receive diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7b8038b3b..7a522dbd8 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -3,8 +3,11 @@ # the COPYRIGHT file. module ApplicationHelper - @@youtube_title_cache = Hash.new("no-title") - def time_for_sort post + def how_long_ago(obj) + timeago(obj.created_at) + end + + def time_for_sort(post) post.created_at end @@ -13,94 +16,10 @@ module ApplicationHelper content_tag(:abbr, time.to_s, options.merge(:title => time.iso8601)) if time end - def page_title(text=nil) - return text unless text.blank? - current_user ? current_user.name : t("application.helper.diaspora_alpha") - end - - def aspects_with_post(aspects, post) - aspects.select do |aspect| - AspectVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id) - end - end - - def aspects_without_post(aspects, post) - aspects.reject do |aspect| - AspectVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id) - end - end - - def aspect_badges(aspects, opts={}) - str = '' - aspects.each do |aspect| - str << aspect_badge(aspect, opts) - end - str.html_safe - end - def bookmarklet "javascript:(function(){f='#{AppConfig[:pod_url]}bookmarklet?url='+encodeURIComponent(window.location.href)+'&title='+encodeURIComponent(document.title)+'¬es='+encodeURIComponent(''+(window.getSelection?window.getSelection():document.getSelection?document.getSelection():document.selection.createRange().text))+'&v=1&';a=function(){if(!window.open(f+'noui=1&jump=doclose','diasporav1','location=yes,links=no,scrollbars=no,toolbar=no,width=620,height=250'))location.href=f+'jump=yes'};if(/Firefox/.test(navigator.userAgent)){setTimeout(a,0)}else{a()}})()" end - def aspect_badge(aspect, opts={}) - str = "" - link = opts.delete(:link) - if !link - str << link_to(aspect.name, "#", 'data-guid' => aspect.id, :class => 'hard_aspect_link').html_safe - else - str << link_for_aspect(aspect).html_safe - end - str << "" - end - - def aspect_links(aspects, opts={}) - str = "" - aspects.each do |aspect| - str << '
  • ' - str << link_for_aspect(aspect, :params => opts, 'data-guid' => aspect.id, :class => 'hard_aspect_link').html_safe - str << '
  • ' - end - str.html_safe - end - - def aspect_li(aspect, opts={}) - param_string = "" - if opts.size > 0 - param_string << '?' - opts.each_pair do |k, v| - param_string << "#{k}=#{v}" - end - end -"
  • - - #{aspect.name} - -
  • ".html_safe - end - - def link_for_aspect(aspect, opts={}) - opts[:params] ||= {} - params ||= {} - opts[:params] = opts[:params].merge("a_ids[]" => aspect.id, :created_at => params[:created_at]) - opts[:class] ||= "" - opts[:class] << " hard_aspect_link" - opts['data-guid'] = aspect.id - - link_to aspect.name, aspects_path( opts[:params] ), opts - end - - def current_aspect?(aspect) - !@aspect.nil? && !@aspect.instance_of?(Symbol) && @aspect.id == aspect.id - end - - def aspect_or_all_path(aspect) - if @aspect.is_a? Aspect - aspect_path @aspect - else - aspects_path - end - end - def object_path(object, opts={}) return "" if object.nil? object = object.person if object.is_a? User @@ -120,10 +39,6 @@ module ApplicationHelper "#{class_name.pluralize}/#{class_name}" end - def how_long_ago(obj) - timeago(obj.created_at) - end - def profile_photo(person) person_image_link(person, :size => :thumb_large, :to => :photos) end @@ -165,136 +80,6 @@ module ApplicationHelper (':' + post.id.to_s).to_sym end - def markdownify(message, options={}) - message = h(message).html_safe - - options[:newlines] = true if !options.has_key?(:newlines) - options[:emoticons] = true if !options.has_key?(:emoticons) - - message = process_links(message) - message = process_autolinks(message) - message = process_emphasis(message) - message = process_youtube(message, options[:youtube_maps]) - message = process_vimeo(message, options[:vimeo_maps]) - message = process_emoticons(message) if options[:emoticons] - - message.gsub!(/\n+/, '
    ') if options[:newlines] - - message - end - - - def process_links(message) - message.gsub!(/\[([^\[]+)\]\(([^ ]+) \"(([^&]|(&[^q])|(&q[^u])|(&qu[^o])|(&quo[^t])|("[^;]))+)\"\)/) do |m| - escape = "\\" - link = $1 - url = $2 - title = $3 - url.gsub!("_", "\\_") - url.gsub!("*", "\\*") - protocol = (url =~ /^\w+:\/\//) ? '' :'http://' - res = "#{link}" - res - end - - message.gsub!(/\[([^\[]+)\]\(([^ ]+)\)/) do |m| - escape = "\\" - link = $1 - url = $2 - url.gsub!("_", "\\_") - url.gsub!("*", "\\*") - protocol = (url =~ /^\w+:\/\//) ? '' :'http://' - res = "#{link}" - res - end - - message - end - - def process_youtube(message, youtube_maps) - processed_message = message.gsub(YoutubeTitles::YOUTUBE_ID_REGEX) do |matched_string| - match_data = matched_string.match(YoutubeTitles::YOUTUBE_ID_REGEX) - video_id = match_data[1] - anchor = match_data[2] - anchor ||= '' - if youtube_maps && youtube_maps[video_id] - title = h(CGI::unescape(youtube_maps[video_id])) - else - title = I18n.t 'application.helper.video_title.unknown' - end - ' Youtube: ' + title + '' - end - processed_message - end - - def process_autolinks(message) - message.gsub!(/( |^)(www\.[^\s]+\.[^\s])/, '\1http://\2') - message.gsub!(/(#{captures[2]}} - res.gsub!(/(\*|_)/) { |m| "\\#{$1}" } - res - end - end - message - end - - def process_emphasis(message) - message.gsub!("\\**", "-^doublestar^-") - message.gsub!("\\__", "-^doublescore^-") - message.gsub!("\\*", "-^star^-") - message.gsub!("\\_", "-^score^-") - message.gsub!(/(\*\*\*|___)(.+?)\1/m, '\2') - message.gsub!(/(\*\*|__)(.+?)\1/m, '\2') - message.gsub!(/(\*|_)(.+?)\1/m, '\2') - message.gsub!("-^doublestar^-", "**") - message.gsub!("-^doublescore^-", "__") - message.gsub!("-^star^-", "*") - message.gsub!("-^score^-", "_") - message - end - - def process_vimeo(message, vimeo_maps) - regex = /https?:\/\/(?:w{3}\.)?vimeo.com\/(\d{6,})/ - processed_message = message.gsub(regex) do |matched_string| - match_data = message.match(regex) - video_id = match_data[1] - if vimeo_maps && vimeo_maps[video_id] - title = h(CGI::unescape(vimeo_maps[video_id])) - else - title = I18n.t 'application.helper.video_title.unknown' - end - ' Vimeo: ' + title + '' - end - processed_message - end - - def process_emoticons(message) - map = { - "<3" => "♥", - ":(" => "☹", - ":-(" => "☹", - ":)" => "☺", - ":-)" => "☺", - "->" => "→", - "<-" => "←", - "..." => "…", - "(tm)" => "™", - "(r)" => "®", - "(c)" => "©" - } - - map.each do |search, replace| - message.gsub!(search, replace) - end - message - end - def info_text(text) image_tag 'icons/monotone_question.png', :class => 'what_is_this', :title => text end diff --git a/app/helpers/aspect_global_helper.rb b/app/helpers/aspect_global_helper.rb new file mode 100644 index 000000000..65ecc4b12 --- /dev/null +++ b/app/helpers/aspect_global_helper.rb @@ -0,0 +1,84 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +module AspectGlobalHelper + def aspects_with_post(aspects, post) + aspects.select do |aspect| + AspectVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id) + end + end + + def aspects_without_post(aspects, post) + aspects.reject do |aspect| + AspectVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id) + end + end + + def aspect_badges(aspects, opts={}) + str = '' + aspects.each do |aspect| + str << aspect_badge(aspect, opts) + end + str.html_safe + end + + def aspect_badge(aspect, opts={}) + str = "" + link = opts.delete(:link) + if !link + str << link_to(aspect.name, "#", 'data-guid' => aspect.id, :class => 'hard_aspect_link').html_safe + else + str << link_for_aspect(aspect).html_safe + end + str << "" + end + + def aspect_links(aspects, opts={}) + str = "" + aspects.each do |aspect| + str << '
  • ' + str << link_for_aspect(aspect, :params => opts, 'data-guid' => aspect.id, :class => 'hard_aspect_link').html_safe + str << '
  • ' + end + str.html_safe + end + + def aspect_li(aspect, opts={}) + param_string = "" + if opts.size > 0 + param_string << '?' + opts.each_pair do |k, v| + param_string << "#{k}=#{v}" + end + end +"
  • + + #{aspect.name} + +
  • ".html_safe + end + + def link_for_aspect(aspect, opts={}) + opts[:params] ||= {} + params ||= {} + opts[:params] = opts[:params].merge("a_ids[]" => aspect.id, :created_at => params[:created_at]) + opts[:class] ||= "" + opts[:class] << " hard_aspect_link" + opts['data-guid'] = aspect.id + + link_to aspect.name, aspects_path( opts[:params] ), opts + end + + def current_aspect?(aspect) + !@aspect.nil? && !@aspect.instance_of?(Symbol) && @aspect.id == aspect.id + end + + def aspect_or_all_path(aspect) + if @aspect.is_a? Aspect + aspect_path @aspect + else + aspects_path + end + end +end \ No newline at end of file diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb index e8707e412..211768ddb 100644 --- a/app/helpers/layout_helper.rb +++ b/app/helpers/layout_helper.rb @@ -12,6 +12,11 @@ module LayoutHelper @show_title = show_title end + def page_title(text=nil) + return text unless text.blank? + current_user ? current_user.name : t("application.helper.diaspora_alpha") + end + def show_title? @show_title end diff --git a/app/helpers/markdownify_helper.rb b/app/helpers/markdownify_helper.rb new file mode 100644 index 000000000..3fffdda30 --- /dev/null +++ b/app/helpers/markdownify_helper.rb @@ -0,0 +1,134 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +module MarkdownifyHelper + def markdownify(message, options={}) + message = h(message).html_safe + + options[:newlines] = true if !options.has_key?(:newlines) + options[:emoticons] = true if !options.has_key?(:emoticons) + + message = process_links(message) + message = process_autolinks(message) + message = process_emphasis(message) + message = process_youtube(message, options[:youtube_maps]) + message = process_vimeo(message, options[:vimeo_maps]) + message = process_emoticons(message) if options[:emoticons] + + message.gsub!(/\n+/, '
    ') if options[:newlines] + + message + end + + def process_links(message) + message.gsub!(/\[([^\[]+)\]\(([^ ]+) \"(([^&]|(&[^q])|(&q[^u])|(&qu[^o])|(&quo[^t])|("[^;]))+)\"\)/) do |m| + escape = "\\" + link = $1 + url = $2 + title = $3 + url.gsub!("_", "\\_") + url.gsub!("*", "\\*") + protocol = (url =~ /^\w+:\/\//) ? '' :'http://' + res = "#{link}" + res + end + + message.gsub!(/\[([^\[]+)\]\(([^ ]+)\)/) do |m| + escape = "\\" + link = $1 + url = $2 + url.gsub!("_", "\\_") + url.gsub!("*", "\\*") + protocol = (url =~ /^\w+:\/\//) ? '' :'http://' + res = "#{link}" + res + end + + message + end + + def process_youtube(message, youtube_maps) + processed_message = message.gsub(YoutubeTitles::YOUTUBE_ID_REGEX) do |matched_string| + match_data = matched_string.match(YoutubeTitles::YOUTUBE_ID_REGEX) + video_id = match_data[1] + anchor = match_data[2] + anchor ||= '' + if youtube_maps && youtube_maps[video_id] + title = h(CGI::unescape(youtube_maps[video_id])) + else + title = I18n.t 'application.helper.video_title.unknown' + end + ' Youtube: ' + title + '' + end + processed_message + end + + def process_autolinks(message) + message.gsub!(/( |^)(www\.[^\s]+\.[^\s])/, '\1http://\2') + message.gsub!(/(#{captures[2]}} + res.gsub!(/(\*|_)/) { |m| "\\#{$1}" } + res + end + end + message + end + + def process_emphasis(message) + message.gsub!("\\**", "-^doublestar^-") + message.gsub!("\\__", "-^doublescore^-") + message.gsub!("\\*", "-^star^-") + message.gsub!("\\_", "-^score^-") + message.gsub!(/(\*\*\*|___)(.+?)\1/m, '\2') + message.gsub!(/(\*\*|__)(.+?)\1/m, '\2') + message.gsub!(/(\*|_)(.+?)\1/m, '\2') + message.gsub!("-^doublestar^-", "**") + message.gsub!("-^doublescore^-", "__") + message.gsub!("-^star^-", "*") + message.gsub!("-^score^-", "_") + message + end + + def process_vimeo(message, vimeo_maps) + regex = /https?:\/\/(?:w{3}\.)?vimeo.com\/(\d{6,})/ + processed_message = message.gsub(regex) do |matched_string| + match_data = message.match(regex) + video_id = match_data[1] + if vimeo_maps && vimeo_maps[video_id] + title = h(CGI::unescape(vimeo_maps[video_id])) + else + title = I18n.t 'application.helper.video_title.unknown' + end + ' Vimeo: ' + title + '' + end + processed_message + end + + def process_emoticons(message) + map = { + "<3" => "♥", + ":(" => "☹", + ":-(" => "☹", + ":)" => "☺", + ":-)" => "☺", + "->" => "→", + "<-" => "←", + "..." => "…", + "(tm)" => "™", + "(r)" => "®", + "(c)" => "©" + } + + map.each do |search, replace| + message.gsub!(search, replace) + end + message + end +end \ No newline at end of file diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 005b3fd97..de2f93b56 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -42,290 +42,40 @@ describe ApplicationHelper do end end - describe "#markdownify" do - describe "autolinks" do - it "should not allow basic XSS/HTML" do - markdownify("").should == "<script>alert('XSS is evil')</script>" - end - - it "should recognize basic http links (1/3)" do - proto="http" - url="bugs.joindiaspora.com/issues/332" - markdownify(proto+"://"+url).should == ""+url+"" - end - - it "should recognize basic http links (2/3)" do - proto="http" - url="webmail.example.com?~()!*/" - markdownify(proto+"://"+url).should == ""+url+"" - end - - it "should recognize basic http links (3/3)" do - proto="http" - url="127.0.0.1:3000/users/sign_in" - markdownify(proto+"://"+url).should == ""+url+"" - end - - it "should recognize secure https links" do - proto="https" - url="127.0.0.1:3000/users/sign_in" - markdownify(proto+"://"+url).should == ""+url+"" - end - - - - describe "video links" do - it "recognizes vimeo links" do - video_id = "17449557" - url = "http://www.vimeo.com/#{video_id}" - res = markdownify(url) - res.should =~ /data-host="vimeo.com"/ - res.should =~ /data-video-id="#{video_id}"/ - end - - it "recognizes youtube links" do - video_id = "0x__dDWdf23" - url = "http://www.youtube.com/watch?v=" + video_id + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" - res = markdownify(url) - res.should =~ /Youtube:/ - res.should =~ /data-host="youtube.com"/ - res.should =~ /data-video-id="#{video_id}"/ - end - - it "recognizes youtube links with hyphens" do - video_id = "ABYnqp-bxvg" - url = "http://www.youtube.com/watch?v=" + video_id + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" - res = markdownify(url) - res.should =~ /Youtube:/ - res.should =~ /data-host="youtube.com"/ - res.should =~ /data-video-id="#{video_id}"/ - end - - it "keeps anchors" do - anchor = "#t=11m34" - video_id = "DHRoHuv3I8E" - url = "http://www.youtube.com/watch?v=" + video_id + anchor - res = markdownify(url) - res.should =~ /Youtube:/ - res.should =~ /data-host="youtube.com"/ - res.should =~ /data-video-id="#{video_id}"/ - res.should =~ /data-anchor="#{anchor}"/ - end - - it "has an empty data-anchor attribute if there is no anchor" do - video_id = "DHRoHuv3I8E" - url = "http://www.youtube.com/watch?v=" + video_id - res = markdownify(url) - res.should =~ /Youtube:/ - res.should =~ /data-host="youtube.com"/ - res.should =~ /data-video-id="#{video_id}"/ - res.should =~ /data-anchor=""/ - end - - it "leaves the links in the href of the #a tag" do - video_id = "ABYnqp-bxvg" - start_url ="http://www.youtube.com/watch?v=" + video_id - url = start_url + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" - res = markdownify(url) - res.should =~ /href=[\S]+v=#{video_id}/ - end - it 'does not autolink inside the link' do - video_id = "ABYnqp-bxvg" - start_url ="http://www.youtube.com/watch?v=" + video_id - url = start_url + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" - res = markdownify(url) - res.match(/href=""+url+"" - end - - it "should recognize www links" do - url="www.joindiaspora.com" - markdownify(url).should == ""+url+"" - end - end - - describe "emoticons" do - it "replaces <3 with ♥" do - message = "i <3 you" - markdownify(message).should == "i ♥ you" - end - - it "replaces various things with (their) HTML entities" do - message = ":) :-) :( :-( ... -> <- (tm) (r) (c)" - markdownify(message).should == "☺ ☺ ☹ ☹ … → ← ™ ® ©" - end - - it "skips doing it if you say so" do - message = ":) :-) :( :-( ... -> <-" - markdownify(message, :emoticons => false).should == ":) :-) :( :-( ... -> <-" - end - end - - describe "weak emphasis" do - it "should be recognized (1/2)" do - message = "*some text* some text *some text* some text" - markdownify(message).should == "some text some text some text some text" - end - - it "should be recognized (2/2)" do - message = "_some text_ some text _some text_ some text" - markdownify(message).should == "some text some text some text some text" - end - end - - describe "strong emphasis" do - it "should be recognized (1/2)" do - message = "**some text** some text **some text** some text" - markdownify(message).should == "some text some text some text some text" - end - - it "should be recognized (2/2)" do - message = "__some text__ some text __some text__ some text" - markdownify(message).should == "some text some text some text some text" - end - end - - describe "nested weak and strong emphasis" do - it "should be rendered correctly" do - message = "__this is _some_ text__" - markdownify(message).should == "this is some text" - message = "*this is **some** text*" - markdownify(message).should == "this is some text" - message = "___some text___" - markdownify(message).should == "some text" - end - end - - describe "links" do - it "should be recognized without title attribute" do - message = "[link text](http://someurl.com) [link text](http://someurl.com)" - markdownify(message).should == 'link text link text' - end - - it "should be recognized with title attribute" do - message = '[link text](http://someurl.com "some title") [link text](http://someurl.com "some title")' - markdownify(message).should == 'link text link text' - end - - it "should have a robust link parsing" do - message = "This [*text*](http://en.wikipedia.org/wiki/Text_(literary_theory)) with many [links](google.com) tests [_http_](http://google.com/search?q=with_multiple__underscores*and**asterisks), [___FTP___](ftp://ftp.uni-kl.de/CCC/26C3/mp4/26c3-3540-en-a_hackers_utopia.mp4 \"File Transfer Protocol\"), [**any protocol**](foo://bar.example.org/yes_it*makes*no_sense)" - markdownify(message).should == 'This text with many links tests http, FTP, any protocol' - end - end - - describe "nested emphasis and links tags" do - it "should be rendered correctly" do - message = '[**some *link* text**](someurl.com "some title")' - markdownify(message).should == 'some link text' - end - end - - it "should allow escaping" do - message = '*some text* \\*some text* \\**some text* _some text_ \\_some text_ \\__some text_' - markdownify(message).should == "some text *some text **some text some text _some text __some text" - end - - describe "newlines" do - it 'skips inserting newlines if you pass the newlines option' do - message = "These\nare\n\some\nnew\lines" - res = markdownify(message, :newlines => false) - res.should == message - end - - it 'generates breaklines' do - message = "These\nare\nsome\nnew\nlines" - res = markdownify(message) - res.should == "These
    are
    some
    new
    lines" - end - - it 'should render newlines and basic http links correctly' do - message = "Some text, then a line break and a link\nhttp://joindiaspora.com\nsome more text" - res = markdownify(message) - res.should == 'Some text, then a line break and a link
    joindiaspora.com
    some more text' - end - end - - describe '#person_link' do - before do - @person = Factory(:person) - end - it 'includes the name of the person if they have a first name' do - person_link(@person).should include @person.profile.first_name - end - - it 'uses diaspora handle if the person has no first or last name' do - @person.profile.first_name = nil - @person.profile.last_name = nil - - person_link(@person).should include @person.diaspora_handle - end - - it 'uses diaspora handle if first name and first name are rails#blank?' do - @person.profile.first_name = " " - @person.profile.last_name = " " - - person_link(@person).should include @person.diaspora_handle - end - - it "should not allow basic XSS/HTML" do - @person.profile.first_name = "I'm

    Evil" - @person.profile.last_name = "I'm

    Evil" - person_link(@person).should_not include("

    ") - 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 " - end - it 'is sub millisecond' do - Benchmark.realtime{ - markdownify(@message) - }.should < 0.001 - end - end - end - - describe "#page_title" do + describe '#person_link' do before do - def current_user - @current_user - end + @person = Factory(:person) end - context "passed blank text" do - it "returns current_user.name if logged in" do - @current_user = @user - page_title.should == @user.name - end - - it "returns default title if not logged in" do - @current_user = nil - page_title.should == I18n.t("application.helper.diaspora_alpha") - end + it 'includes the name of the person if they have a first name' do + person_link(@person).should include @person.profile.first_name end - context "passed text" do - it "returns the text" do - text = "This is the title" - page_title(text).should == text - end + it 'uses diaspora handle if the person has no first or last name' do + @person.profile.first_name = nil + @person.profile.last_name = nil + + person_link(@person).should include @person.diaspora_handle + end + + it 'uses diaspora handle if first name and first name are rails#blank?' do + @person.profile.first_name = " " + @person.profile.last_name = " " + + person_link(@person).should include @person.diaspora_handle + end + + it "should not allow basic XSS/HTML" do + @person.profile.first_name = "I'm

    Evil" + @person.profile.last_name = "I'm

    Evil" + person_link(@person).should_not include("

    ") end end -end + + describe "#time_for_sort" do + it "returns created_at" do + post = @user.post(:status_message, :text => "hello", :public => true, :to => 'all') + time_for_sort(post).should == post.created_at + end + end +end \ No newline at end of file diff --git a/spec/helpers/layout_helper_spec.rb b/spec/helpers/layout_helper_spec.rb new file mode 100644 index 000000000..3bf5c1359 --- /dev/null +++ b/spec/helpers/layout_helper_spec.rb @@ -0,0 +1,38 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require 'spec_helper' + +describe LayoutHelper do + before do + @user = alice + end + + describe "#page_title" do + before do + def current_user + @current_user + end + end + + context "passed blank text" do + it "returns current_user.name if logged in" do + @current_user = @user + page_title.should == @user.name + end + + it "returns default title if not logged in" do + @current_user = nil + page_title.should == I18n.t("application.helper.diaspora_alpha") + end + end + + context "passed text" do + it "returns the text" do + text = "This is the title" + page_title(text).should == text + end + end + end +end \ No newline at end of file diff --git a/spec/helpers/markdownify_helper_spec.rb b/spec/helpers/markdownify_helper_spec.rb new file mode 100644 index 000000000..e292490d4 --- /dev/null +++ b/spec/helpers/markdownify_helper_spec.rb @@ -0,0 +1,239 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require 'spec_helper' + +describe MarkdownifyHelper do + describe "#markdownify" do + describe "autolinks" do + it "should not allow basic XSS/HTML" do + markdownify("").should == "<script>alert('XSS is evil')</script>" + end + + it "should recognize basic http links (1/3)" do + proto="http" + url="bugs.joindiaspora.com/issues/332" + markdownify(proto+"://"+url).should == ""+url+"" + end + + it "should recognize basic http links (2/3)" do + proto="http" + url="webmail.example.com?~()!*/" + markdownify(proto+"://"+url).should == ""+url+"" + end + + it "should recognize basic http links (3/3)" do + proto="http" + url="127.0.0.1:3000/users/sign_in" + markdownify(proto+"://"+url).should == ""+url+"" + end + + it "should recognize secure https links" do + proto="https" + url="127.0.0.1:3000/users/sign_in" + markdownify(proto+"://"+url).should == ""+url+"" + end + + describe "video links" do + it "recognizes vimeo links" do + video_id = "17449557" + url = "http://www.vimeo.com/#{video_id}" + res = markdownify(url) + res.should =~ /data-host="vimeo.com"/ + res.should =~ /data-video-id="#{video_id}"/ + end + + it "recognizes youtube links" do + video_id = "0x__dDWdf23" + url = "http://www.youtube.com/watch?v=" + video_id + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" + res = markdownify(url) + res.should =~ /Youtube:/ + res.should =~ /data-host="youtube.com"/ + res.should =~ /data-video-id="#{video_id}"/ + end + + it "recognizes youtube links with hyphens" do + video_id = "ABYnqp-bxvg" + url = "http://www.youtube.com/watch?v=" + video_id + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" + res = markdownify(url) + res.should =~ /Youtube:/ + res.should =~ /data-host="youtube.com"/ + res.should =~ /data-video-id="#{video_id}"/ + end + + it "keeps anchors" do + anchor = "#t=11m34" + video_id = "DHRoHuv3I8E" + url = "http://www.youtube.com/watch?v=" + video_id + anchor + res = markdownify(url) + res.should =~ /Youtube:/ + res.should =~ /data-host="youtube.com"/ + res.should =~ /data-video-id="#{video_id}"/ + res.should =~ /data-anchor="#{anchor}"/ + end + + it "has an empty data-anchor attribute if there is no anchor" do + video_id = "DHRoHuv3I8E" + url = "http://www.youtube.com/watch?v=" + video_id + res = markdownify(url) + res.should =~ /Youtube:/ + res.should =~ /data-host="youtube.com"/ + res.should =~ /data-video-id="#{video_id}"/ + res.should =~ /data-anchor=""/ + end + + it "leaves the links in the href of the #a tag" do + video_id = "ABYnqp-bxvg" + start_url ="http://www.youtube.com/watch?v=" + video_id + url = start_url + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" + res = markdownify(url) + res.should =~ /href=[\S]+v=#{video_id}/ + end + + it 'does not autolink inside the link' do + video_id = "ABYnqp-bxvg" + start_url ="http://www.youtube.com/watch?v=" + video_id + url = start_url + "&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" + res = markdownify(url) + res.match(/href=""+url+"" + end + + it "should recognize www links" do + url="www.joindiaspora.com" + markdownify(url).should == ""+url+"" + end + end + + describe "emoticons" do + it "replaces <3 with ♥" do + message = "i <3 you" + markdownify(message).should == "i ♥ you" + end + + it "replaces various things with (their) HTML entities" do + message = ":) :-) :( :-( ... -> <- (tm) (r) (c)" + markdownify(message).should == "☺ ☺ ☹ ☹ … → ← ™ ® ©" + end + + it "skips doing it if you say so" do + message = ":) :-) :( :-( ... -> <-" + markdownify(message, :emoticons => false).should == ":) :-) :( :-( ... -> <-" + end + end + + describe "weak emphasis" do + it "should be recognized (1/2)" do + message = "*some text* some text *some text* some text" + markdownify(message).should == "some text some text some text some text" + end + + it "should be recognized (2/2)" do + message = "_some text_ some text _some text_ some text" + markdownify(message).should == "some text some text some text some text" + end + end + + describe "strong emphasis" do + it "should be recognized (1/2)" do + message = "**some text** some text **some text** some text" + markdownify(message).should == "some text some text some text some text" + end + + it "should be recognized (2/2)" do + message = "__some text__ some text __some text__ some text" + markdownify(message).should == "some text some text some text some text" + end + end + + describe "nested weak and strong emphasis" do + it "should be rendered correctly" do + message = "__this is _some_ text__" + markdownify(message).should == "this is some text" + message = "*this is **some** text*" + markdownify(message).should == "this is some text" + message = "___some text___" + markdownify(message).should == "some text" + end + end + + describe "links" do + it "should be recognized without title attribute" do + message = "[link text](http://someurl.com) [link text](http://someurl.com)" + markdownify(message).should == 'link text link text' + end + + it "should be recognized with title attribute" do + message = '[link text](http://someurl.com "some title") [link text](http://someurl.com "some title")' + markdownify(message).should == 'link text link text' + end + + it "should have a robust link parsing" do + message = "This [*text*](http://en.wikipedia.org/wiki/Text_(literary_theory)) with many [links](google.com) tests [_http_](http://google.com/search?q=with_multiple__underscores*and**asterisks), [___FTP___](ftp://ftp.uni-kl.de/CCC/26C3/mp4/26c3-3540-en-a_hackers_utopia.mp4 \"File Transfer Protocol\"), [**any protocol**](foo://bar.example.org/yes_it*makes*no_sense)" + markdownify(message).should == 'This text with many links tests http, FTP, any protocol' + end + end + + describe "nested emphasis and links tags" do + it "should be rendered correctly" do + message = '[**some *link* text**](someurl.com "some title")' + markdownify(message).should == 'some link text' + end + end + + it "should allow escaping" do + message = '*some text* \\*some text* \\**some text* _some text_ \\_some text_ \\__some text_' + markdownify(message).should == "some text *some text **some text some text _some text __some text" + end + + describe "newlines" do + it 'skips inserting newlines if you pass the newlines option' do + message = "These\nare\n\some\nnew\lines" + res = markdownify(message, :newlines => false) + res.should == message + end + + it 'generates breaklines' do + message = "These\nare\nsome\nnew\nlines" + res = markdownify(message) + res.should == "These
    are
    some
    new
    lines" + end + + it 'should render newlines and basic http links correctly' do + message = "Some text, then a line break and a link\nhttp://joindiaspora.com\nsome more text" + res = markdownify(message) + res.should == 'Some text, then a line break and a link
    joindiaspora.com
    some more text' + 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 " + end + + it 'is sub millisecond' do + Benchmark.realtime{ + markdownify(@message) + }.should < 0.001 + end + end + end +end \ No newline at end of file