From 92bf8444a7366211d1ac59dfc4e1029da50ef988 Mon Sep 17 00:00:00 2001 From: MrZYX Date: Sun, 3 Apr 2011 03:56:20 +0200 Subject: [PATCH] added spec; rtl? -> direction_for --- app/helpers/application_helper.rb | 2 +- app/views/comments/_comment.html.haml | 2 +- app/views/comments/_comment.mobile.haml | 2 +- app/views/conversations/_conversation.haml | 2 +- app/views/conversations/_show.haml | 2 +- app/views/messages/_message.haml | 2 +- app/views/people/_profile_sidebar.html.haml | 4 +- .../status_messages/_status_message.haml | 2 +- config/initializers/direction_detector.rb | 52 +---------- lib/direction_detector.rb | 52 +++++++++++ .../javascripts/widgets/directionDetector.js | 2 +- spec/lib/direction_detector_spec.rb | 89 +++++++++++++++++++ 12 files changed, 152 insertions(+), 61 deletions(-) create mode 100644 lib/direction_detector.rb create mode 100644 spec/lib/direction_detector_spec.rb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index bec1ffc8e..18f7298a4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -281,7 +281,7 @@ module ApplicationHelper defaults end - def rtl?(string) + def direction_for(string) return (string.cleaned_is_rtl?) ? 'rtl' : '' end end diff --git a/app/views/comments/_comment.html.haml b/app/views/comments/_comment.html.haml index 39926fae8..ad635af13 100644 --- a/app/views/comments/_comment.html.haml +++ b/app/views/comments/_comment.html.haml @@ -13,5 +13,5 @@ %time.timeago{:datetime => comment.created_at} = comment.created_at ? timeago(comment.created_at) : timeago(Time.now) - %p{ :class => rtl?(comment.text) } + %p{ :class => direction_for(comment.text) } = markdownify(comment.text, :youtube_maps => comment.youtube_titles) diff --git a/app/views/comments/_comment.mobile.haml b/app/views/comments/_comment.mobile.haml index 30eb78ae4..6056839f0 100644 --- a/app/views/comments/_comment.mobile.haml +++ b/app/views/comments/_comment.mobile.haml @@ -14,6 +14,6 @@ .content .from = person_link(comment.author) - %p{ :class => rtl?(comment.text) } + %p{ :class => direction_for(comment.text) } = markdownify(comment.text, :youtube_maps => comment[:youtube_titles]) diff --git a/app/views/conversations/_conversation.haml b/app/views/conversations/_conversation.haml index f04729a40..14d449cb7 100644 --- a/app/views/conversations/_conversation.haml +++ b/app/views/conversations/_conversation.haml @@ -10,7 +10,7 @@ .message_count = conversation.messages.size - %div{ :class => rtl?(conversation.subject) } + %div{ :class => direction_for(conversation.subject) } = conversation.subject[0..30] .last_author diff --git a/app/views/conversations/_show.haml b/app/views/conversations/_show.haml index ddefccd07..9d37c8501 100644 --- a/app/views/conversations/_show.haml +++ b/app/views/conversations/_show.haml @@ -6,7 +6,7 @@ .span-16.last .conversation_participants .span-9 - %h3{ :class => rtl?(conversation.subject) } + %h3{ :class => direction_for(conversation.subject) } = conversation.subject .conversation_controls diff --git a/app/views/messages/_message.haml b/app/views/messages/_message.haml index ea8f8422e..da5d1f506 100644 --- a/app/views/messages/_message.haml +++ b/app/views/messages/_message.haml @@ -11,6 +11,6 @@ %time.timeago{:datetime => message.created_at} = how_long_ago(message) - %p{ :class => rtl?(message.text) } + %p{ :class => direction_for(message.text) } = markdownify(message.text) diff --git a/app/views/people/_profile_sidebar.html.haml b/app/views/people/_profile_sidebar.html.haml index 0b314caf2..912a143f2 100644 --- a/app/views/people/_profile_sidebar.html.haml +++ b/app/views/people/_profile_sidebar.html.haml @@ -41,13 +41,13 @@ %li %h4 =t('.bio') - %div{ :class => rtl?(person.profile.bio) } + %div{ :class => direction_for(person.profile.bio) } = markdownify(person.profile.bio, :newlines => true) - unless person.profile.location.blank? %li %h4 =t('.location') - %div{ :class => rtl?(person.profile.location) } + %div{ :class => direction_for(person.profile.location) } = markdownify(person.profile.location, :newlines => true) %li.span-8.last diff --git a/app/views/status_messages/_status_message.haml b/app/views/status_messages/_status_message.haml index fbb336f44..1597f9f0c 100644 --- a/app/views/status_messages/_status_message.haml +++ b/app/views/status_messages/_status_message.haml @@ -14,5 +14,5 @@ - for photo in photos[1..photos.size] = link_to (image_tag photo.url(:thumb_small), :class => 'thumb_small'), photo_path(photo) -%p{ :class => rtl?(post.text) } +%p{ :class => direction_for(post.text) } = markdownify(post.text, :youtube_maps => post[:youtube_titles]) diff --git a/config/initializers/direction_detector.rb b/config/initializers/direction_detector.rb index 9e71648b9..2ba6401de 100644 --- a/config/initializers/direction_detector.rb +++ b/config/initializers/direction_detector.rb @@ -1,55 +1,5 @@ # Copyright (c) 2010, Diaspora Inc. This file is # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -# Deeply inspired by https://gitorious.org/statusnet/mainline/blobs/master/plugins/DirectionDetector/DirectionDetectorPlugin.php -class String - - def is_rtl? - count = 0 - self.strip.split(" ").each do |word| - if starts_with_rtl_char?(word) - count += 1 - else - count -= 1 - end - end - return true if count > 0 # more than half of the words are rtl words - return starts_with_rtl_char?(self.strip) # otherwise let the first word decide - end - - # Diaspora specific - def cleaned_is_rtl? - string = String.new(self) - [ /@[^ ]+|#[^ ]+/u, # mention, tag - /^RT[: ]{1}| RT | RT: |[♺♻:]/u, # retweet - /[ \r\t\n]+/ # whitespaces - ].each do |cleaner| - string.gsub!(cleaner, '') - end - string.is_rtl? - end - - private - - def starts_with_rtl_char?(string) - string = self.strip - return false if string.empty? - char = string.unpack('U*').first - limits = [ - [1536, 1791], # arabic, persian, urdu, kurdish, ... - [65136, 65279], # arabic peresent 2 - [64336, 65023], # arabic peresent 1 - [1424, 1535], # hebrew - [64256, 64335], # hebrew peresent - [1792, 1871], # syriac - [1920, 1983], # thaana - [1984, 2047], # nko - [11568, 11647] # tifinagh - ] - limits.each do |limit| - return true if char >= limit[0] && char <= limit[1] - end - return false - end -end +require File.join(Rails.root, 'lib/direction_detector') diff --git a/lib/direction_detector.rb b/lib/direction_detector.rb new file mode 100644 index 000000000..73736186d --- /dev/null +++ b/lib/direction_detector.rb @@ -0,0 +1,52 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. +# Deeply inspired by https://gitorious.org/statusnet/mainline/blobs/master/plugins/DirectionDetector/DirectionDetectorPlugin.php + +class String + + def is_rtl? + return false if self.strip.empty? + count = 0 + self.split(" ").each do |word| + if starts_with_rtl_char?(word) + count += 1 + else + count -= 1 + end + end + return true if count > 0 # more than half of the words are rtl words + return starts_with_rtl_char?(self) # otherwise let the first word decide + end + + # Diaspora specific + def cleaned_is_rtl? + string = String.new(self) + [ /@[^ ]+|#[^ ]+/u, # mention, tag + /^RT[: ]{1}| RT | RT: |[♺♻:]/u # retweet + ].each do |cleaner| + string.gsub!(cleaner, '') + end + string.is_rtl? + end + + def starts_with_rtl_char?(string = self) + return false if string.strip.empty? + char = string.strip.unpack('U*').first + limits = [ + [1536, 1791], # arabic, persian, urdu, kurdish, ... + [65136, 65279], # arabic peresent 2 + [64336, 65023], # arabic peresent 1 + [1424, 1535], # hebrew + [64256, 64335], # hebrew peresent + [1792, 1871], # syriac + [1920, 1983], # thaana + [1984, 2047], # nko + [11568, 11647] # tifinagh + ] + limits.each do |limit| + return true if char >= limit[0] && char <= limit[1] + end + return false + end +end diff --git a/public/javascripts/widgets/directionDetector.js b/public/javascripts/widgets/directionDetector.js index 54b5f502c..ab5ee9601 100644 --- a/public/javascripts/widgets/directionDetector.js +++ b/public/javascripts/widgets/directionDetector.js @@ -49,7 +49,7 @@ Diaspora.widgets.add("directionDetector", function() { }; this.bind = function() { - $(this).one('keyup', Diaspora.widgets.directionDetector.updateDirection); + $(this).bind('keyup', Diaspora.widgets.directionDetector.updateDirection); Diaspora.widgets.directionDetector.binds.push($(this)); }; diff --git a/spec/lib/direction_detector_spec.rb b/spec/lib/direction_detector_spec.rb new file mode 100644 index 000000000..fbbd5fa55 --- /dev/null +++ b/spec/lib/direction_detector_spec.rb @@ -0,0 +1,89 @@ +# 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 String do + let(:english) { "Hello World" } + let(:chinese) { "你好世界" } + let(:arabic) { "مرحبا العالم" } + let(:hebrew) { "שלום העולם" } + let(:english_chinese) { "#{english} #{chinese}" } + let(:english_arabic) { "#{english} #{chinese}" } + let(:english_hebrew) { "#{english} #{chinese}" } + let(:chinese_english) { "#{chinese} #{english}" } + let(:chinese_arabic) { "#{chinese} #{arabic}" } + let(:chinese_hebrew) { "#{chinese} #{hebrew}" } + let(:arabic_english) { "#{arabic} #{english}" } + let(:arabic_chinese) { "#{arabic} #{chinese}" } + let(:arabic_hebrew) { "#{arabic} #{hebrew}" } + let(:hebrew_english) { "#{hebrew} #{english}" } + let(:hebrew_chinese) { "#{hebrew} #{chinese}" } + let(:hebrew_arabic) { "#{hebrew} #{arabic}" } + + + describe "#stats_with_rtl_char?" do + it 'returns true or false correctly' do + english.starts_with_rtl_char?.should be_false + chinese.starts_with_rtl_char?.should be_false + arabic.starts_with_rtl_char?.should be_true + hebrew.starts_with_rtl_char?.should be_true + hebrew_arabic.starts_with_rtl_char?.should be_true + end + + it 'only looks at the first char' do + english_chinese.starts_with_rtl_char?.should be_false + chinese_english.starts_with_rtl_char?.should be_false + english_arabic.starts_with_rtl_char?.should be_false + hebrew_english.starts_with_rtl_char?.should be_true + arabic_chinese.starts_with_rtl_char?.should be_true + end + + it 'ignores whitespaces' do + " \n \r \t".starts_with_rtl_char?.should be_false + " #{arabic} ".starts_with_rtl_char?.should be_true + end + end + + describe "#is_rtl?" do + it 'returns true or false correctly' do + english.is_rtl?.should be_false + chinese.is_rtl?.should be_false + arabic.is_rtl?.should be_true + hebrew.is_rtl?.should be_true + end + + it 'respects all words' do + chinese_arabic.is_rtl?.should be_true + chinese_hebrew.is_rtl?.should be_true + english_hebrew.is_rtl?.should be_false + hebrew_arabic.is_rtl?.should be_true + "#{english} #{arabic} #{chinese}".is_rtl?.should be_false + "Translated to arabic, Hello World means: #{arabic}".is_rtl?.should be_false + "#{english} #{arabic} #{arabic}".is_rtl?.should be_true + end + + it "fallbacks to the first word if there's no majority" do + hebrew_english.is_rtl?.should be_true + english_hebrew.is_rtl?.should be_false + arabic_english.is_rtl?.should be_true + english_arabic.is_rtl?.should be_false + end + + it 'ignores whitespaces' do + " \n \r \t".is_rtl?.should be_false + " #{arabic} ".is_rtl?.should be_true + end + end + + describe '#cleaned_is_rtl?' do + it 'should clean the string' do + "RT: #{arabic}".cleaned_is_rtl?.should be_true + "#{hebrew} RT: #{arabic}".cleaned_is_rtl?.should be_true + "@foo #{arabic}".cleaned_is_rtl?.should be_true + "#{hebrew} #example".cleaned_is_rtl?.should be_true + "♺: #{arabic} ♻: #{hebrew}".cleaned_is_rtl?.should be_true + end + end +end