julik-rutils 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/History.txt +162 -0
  2. data/Manifest.txt +42 -0
  3. data/README.txt +234 -0
  4. data/Rakefile.rb +41 -0
  5. data/TODO.txt +6 -0
  6. data/WHAT_HAS_CHANGED.txt +44 -0
  7. data/bin/gilensize +22 -0
  8. data/bin/rutilize +38 -0
  9. data/init.rb +27 -0
  10. data/lib/countries/countries.rb +1773 -0
  11. data/lib/datetime/datetime.rb +83 -0
  12. data/lib/gilenson/bluecloth_extra.rb +7 -0
  13. data/lib/gilenson/gilenson.rb +665 -0
  14. data/lib/gilenson/helper.rb +34 -0
  15. data/lib/gilenson/maruku_extra.rb +19 -0
  16. data/lib/gilenson/rdiscount_extra.rb +7 -0
  17. data/lib/gilenson/redcloth_extra.rb +42 -0
  18. data/lib/integration/integration.rb +1 -0
  19. data/lib/integration/rails_date_helper_override.rb +127 -0
  20. data/lib/integration/rails_pre_filter.rb +4 -0
  21. data/lib/pluralizer/pluralizer.rb +261 -0
  22. data/lib/rutils.rb +54 -0
  23. data/lib/transliteration/bidi.rb +21 -0
  24. data/lib/transliteration/simple.rb +75 -0
  25. data/lib/transliteration/transliteration.rb +53 -0
  26. data/lib/version.rb +5 -0
  27. data/test/extras/integration_bluecloth.rb +13 -0
  28. data/test/extras/integration_maruku.rb +15 -0
  29. data/test/extras/integration_rails_filter.rb +29 -0
  30. data/test/extras/integration_rails_gilenson_helpers.rb +80 -0
  31. data/test/extras/integration_rails_helpers.rb +85 -0
  32. data/test/extras/integration_rdiscount.rb +15 -0
  33. data/test/extras/integration_redcloth3.rb +18 -0
  34. data/test/extras/integration_redcloth4.rb +19 -0
  35. data/test/run_tests.rb +4 -0
  36. data/test/test_datetime.rb +145 -0
  37. data/test/test_gilenson.rb +396 -0
  38. data/test/test_integration.rb +22 -0
  39. data/test/test_integration_flag.rb +18 -0
  40. data/test/test_pluralize.rb +84 -0
  41. data/test/test_rutils_base.rb +11 -0
  42. data/test/test_transliteration.rb +53 -0
  43. metadata +121 -0
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $KCODE = 'u'
3
+
4
+ require File.dirname(__FILE__) + '/version'
5
+
6
+ # Главный контейнер модуля
7
+ module RuTils
8
+ # Папка, куда установлен модуль RuTils. Нужно чтобы автоматически копировать RuTils в другие приложения.
9
+ INSTALLATION_DIRECTORY = File.expand_path(File.dirname(__FILE__) + '/../') #:nodoc:
10
+
11
+ # Стандартный маркер для подстановок - Unicode Character 'OBJECT REPLACEMENT CHARACTER' (U+FFFC)
12
+ # http://unicode.org/reports/tr20/tr20-1.html
13
+ # Он официально применяется для обозначения вложенного обьекта
14
+ SUBSTITUTION_MARKER = [0xEF, 0xBF, 0xBC].pack("U*").freeze
15
+
16
+ class RemovedFeature < RuntimeError
17
+ end
18
+
19
+ # Метод позволяет проверить, включена ли перегрузка функций других модулей.
20
+ # Попутно он спрашивает модуль Locale (если таковой имеется) является ли русский
21
+ # текущим языком, и если является, включает перегрузку функций имплицитно.
22
+ # Это позволяет подчинить настройку перегруженных функций настроенной локали.
23
+ # Модуль Locale можно получить как часть Ruby-Gettext или как отдельный
24
+ # модуль ruby-locale. Мы поддерживаем оба.
25
+ def overrides_enabled?
26
+ if defined?(Locale) and Locale.respond_to?(:current)
27
+ return true if Locale.current.to_s.split('_').first == 'ru'
28
+ end
29
+ thread_local_or_own_flag ? true : false
30
+ end
31
+ alias_method :overrides, :overrides_enabled?
32
+ module_function :overrides_enabled?
33
+
34
+ # Включает или выключает перегрузки других модулей. Полезно, например, в случае когда нужно рендерить страницу
35
+ # сайта на нескольких языках и нужно отключить русское оформление текста для других языков.
36
+ #
37
+ # Флаг overrides в RuTils работают в контексте текущей нити
38
+ def overrides=(new_override_flag)
39
+ Thread.current[:rutils_overrided_enabled] = (new_override_flag ? true : false)
40
+ end
41
+ module_function :overrides=
42
+
43
+ def self.thread_local_or_own_flag #:nodoc:
44
+ Thread.current.keys.include?(:rutils_overrided_enabled) ? Thread.current[:rutils_overrided_enabled] : false
45
+ end
46
+
47
+ def self.load_component(name) #:nodoc:
48
+ require File.join(RuTils::INSTALLATION_DIRECTORY, "lib", name.to_s, name.to_s)
49
+ end
50
+ end
51
+
52
+ [:pluralizer, :gilenson, :datetime, :transliteration, :integration, :countries].each do | submodule |
53
+ require File.join(RuTils::INSTALLATION_DIRECTORY, "lib", submodule.to_s, submodule.to_s)
54
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # ++DEPRECATED++ Этот модуль удален и присутствует только для выдачи сообщения об ошибке.
3
+ module RuTils::Transliteration::BiDi
4
+ ERR = "Equivalent bidirectional transliteration for URLs is malpractive. BiDi translit has been removed from RuTils"
5
+
6
+ extend self
7
+
8
+ # ++DEPRECATED++
9
+ def translify(str, allow_slashes = true)
10
+ bail!
11
+ end
12
+
13
+ # ++DEPRECATED++
14
+ def detranslify(str, allow_slashes = true)
15
+ bail!
16
+ end
17
+
18
+ def bail! #:nodoc:
19
+ raise RuTils::RemovedFeature, ERR
20
+ end
21
+ end
@@ -0,0 +1,75 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Реализует простейшую транслитерацию
3
+ # "вот мы и здесь".translify => "vot my i zdes"
4
+ # "vot my i zdes".detranslify => "вот мы и здесь"
5
+ module RuTils::Transliteration::Simple
6
+ TABLE_LOWER = {
7
+ "і"=>"i","ґ"=>"g","ё"=>"yo","№"=>"#","є"=>"e",
8
+ "ї"=>"yi","а"=>"a","б"=>"b",
9
+ "в"=>"v","г"=>"g","д"=>"d","е"=>"e","ж"=>"zh",
10
+ "з"=>"z","и"=>"i","й"=>"y","к"=>"k","л"=>"l",
11
+ "м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r",
12
+ "с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"h",
13
+ "ц"=>"ts","ч"=>"ch","ш"=>"sh","щ"=>"sch","ъ"=>"'",
14
+ "ы"=>"yi","ь"=>"","э"=>"e","ю"=>"yu","я"=>"ya"
15
+ }.sort do | one, two|
16
+ two[1].size <=> one[1].size
17
+ end
18
+
19
+ TABLE_UPPER = {
20
+ "Ґ"=>"G","Ё"=>"YO","Є"=>"E","Ї"=>"YI","І"=>"I",
21
+ "А"=>"A","Б"=>"B","В"=>"V","Г"=>"G",
22
+ "Д"=>"D","Е"=>"E","Ж"=>"ZH","З"=>"Z","И"=>"I",
23
+ "Й"=>"Y","К"=>"K","Л"=>"L","М"=>"M","Н"=>"N",
24
+ "О"=>"O","П"=>"P","Р"=>"R","С"=>"S","Т"=>"T",
25
+ "У"=>"U","Ф"=>"F","Х"=>"H","Ц"=>"TS","Ч"=>"CH",
26
+ "Ш"=>"SH","Щ"=>"SCH","Ъ"=>"'","Ы"=>"YI","Ь"=>"",
27
+ "Э"=>"E","Ю"=>"YU","Я"=>"YA",
28
+ }.sort do | one, two|
29
+ two[1].size <=> one[1].size
30
+ end
31
+
32
+ TABLE = TABLE_UPPER + TABLE_LOWER
33
+
34
+ # Заменяет кириллицу в строке на латиницу. Немного специфично потому что поддерживает
35
+ # комби-регистр (Щука -> Shuka)
36
+ def self.translify(str)
37
+ chars = str.split(//)
38
+
39
+ lowers = TABLE_LOWER.map{|e| e[0] }
40
+ uppers = TABLE_UPPER.map{|e| e[0] }
41
+
42
+ hashtable = {}
43
+ TABLE.each do | item |
44
+ next unless item[0] && item[1]
45
+ hashtable[item[0]] = item[1]
46
+ end
47
+
48
+ result = ''
49
+ chars.each_with_index do | char, index |
50
+ if uppers.include?(char) && lowers.include?(chars[index+1])
51
+ # Combined case. Here we deal with Latin letters so there is no problem to use
52
+ # Ruby's builtin upcase_downcase
53
+ ch = hashtable[char].downcase.capitalize
54
+ result << ch
55
+ elsif uppers.include?(char)
56
+ result << hashtable[char]
57
+ elsif lowers.include?(char)
58
+ result << hashtable[char]
59
+ else
60
+ result << char
61
+ end
62
+ end
63
+ return result
64
+ end
65
+
66
+ # Транслитерирует строку, делая ее пригодной для применения как имя директории или URL
67
+ def self.dirify(string)
68
+ st = self.translify(string)
69
+ st.gsub!(/(\s\&\s)|(\s\&amp\;\s)/, ' and ') # convert & to "and"
70
+ st.gsub!(/\W/, ' ') #replace non-chars
71
+ st.gsub!(/(_)$/, '') #trailing underscores
72
+ st.gsub!(/^(_)/, '') #leading unders
73
+ st.strip.translify.gsub(/(\s)/,'-').downcase.squeeze('-')
74
+ end
75
+ end
@@ -0,0 +1,53 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module RuTils
3
+ module Transliteration #:nodoc:
4
+ end
5
+ end
6
+
7
+ require File.join(File.dirname(__FILE__), 'simple')
8
+
9
+ # Заглушка
10
+ require File.join(File.dirname(__FILE__), 'bidi')
11
+
12
+ # Реализует транслитерацию любого объекта, реализующего String или to_s
13
+ module RuTils::Transliteration::StringFormatting
14
+
15
+ # Транслитерирует строку в латиницу, и возвращает измененную строку
16
+ def translify
17
+ RuTils::Transliteration::Simple::translify(self.to_s)
18
+ end
19
+
20
+ # Транслитерирует строку, меняя объект
21
+ def translify!
22
+ self.replace(self.translify)
23
+ end
24
+
25
+ # Транслитерирует строку, делая ее пригодной для применения как имя директории или URL
26
+ def dirify
27
+ RuTils::Transliteration::Simple::dirify(self.to_s)
28
+ end
29
+
30
+ # ++DEPRECATED++ Вызывает ошибку
31
+ def bidi_translify(allow_slashes = true)
32
+ RuTils::Transliteration::BiDi.bail!
33
+ end
34
+
35
+ # ++DEPRECATED++ Вызывает ошибку
36
+ def bidi_translify!(allow_slashes = true)
37
+ RuTils::Transliteration::BiDi.bail!
38
+ end
39
+
40
+ # ++DEPRECATED++ Вызывает ошибку
41
+ def bidi_detranslify!(allow_slashes = true)
42
+ RuTils::Transliteration::BiDi.bail!
43
+ end
44
+
45
+ # ++DEPRECATED++ Вызывает ошибку
46
+ def bidi_detranslify(allow_slashes = true)
47
+ RuTils::Transliteration::BiDi.bail!
48
+ end
49
+ end
50
+
51
+ class Object::String
52
+ include RuTils::Transliteration::StringFormatting
53
+ end
@@ -0,0 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module RuTils
3
+ # Версия RuTils
4
+ VERSION = '1.0.2'
5
+ end
@@ -0,0 +1,13 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'bluecloth'
3
+
4
+ # Интеграция с BlueCloth - Markdown
5
+ # Сам Markdown никакой обработки типографики не производит (это делает RubyPants, но вряд ли его кто-то юзает на практике)
6
+ class BlueclothIntegrationTest < Test::Unit::TestCase
7
+ C = RuTils::Gilenson::BlueClothExtra
8
+
9
+ def test_integration_markdown
10
+ assert_equal "<p>И вот&#160;&#171;они пошли туда&#187;, и&#160;шли шли&#160;шли</p>",
11
+ C.new('И вот "они пошли туда", и шли шли шли').to_html
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'maruku'
3
+
4
+ # Интеграция с BlueCloth - Markdown
5
+ # Сам Markdown никакой обработки типографики не производит (это делает RubyPants, но вряд ли его кто-то юзает на практике)
6
+ class MarukuIntegrationTest < Test::Unit::TestCase
7
+ C = RuTils::Gilenson::MarukuExtra
8
+
9
+ def test_integration_maruku
10
+
11
+ assert_equal "<p>И вот&#160;&#171;они пошли туда&#187;, и&#160;шли шли&#160;шли</p>",
12
+ C.new('И вот "они пошли туда", и шли шли шли').to_html
13
+
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'action_controller'
3
+ require 'action_controller/test_process'
4
+ require File.dirname(__FILE__) + '/../../init.rb'
5
+
6
+ ActionController::Routing::Routes.draw { |map| map.connect ':controller/:action/:id' }
7
+
8
+ class RutiledController < ActionController::Base #:nodoc:
9
+ def overridden
10
+ raise "Overrides are off" unless RuTils::overrides_enabled?
11
+ render :inline => '<%= Time.local(2008,8,8).strftime("%B") %>'
12
+ end
13
+ def rescue_action(e); raise e; end
14
+ end
15
+
16
+ class RailsFilterTest < Test::Unit::TestCase
17
+
18
+ def setup
19
+ @controller = RutiledController.new
20
+ @request = ActionController::TestRequest.new
21
+ @response = ActionController::TestResponse.new
22
+ end
23
+
24
+ def test_overrides_preserved_in_render
25
+ assert_nothing_raised { get :overridden }
26
+ assert_response :success
27
+ assert_equal "август", @response.body
28
+ end
29
+ end
@@ -0,0 +1,80 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'action_controller'
4
+ require 'action_view'
5
+
6
+ require 'action_controller/test_process'
7
+ require File.dirname(__FILE__) + '/../../init.rb'
8
+
9
+ # Перегрузка helper'ов Rails
10
+ class RailsGilensonHelpersTest < Test::Unit::TestCase
11
+
12
+ class Kontroller < ActionController::Base
13
+ def action_with_gilensize
14
+ render :inline => "<%= gilensize('Они пришли -- туда -- к А. П. Чехову') %>"
15
+ end
16
+
17
+ def action_with_gilensize_and_options
18
+ render :inline => "<%= gilensize('Они пришли -- туда -- к А. П. Чехову', :raw_output => true) %>"
19
+ end
20
+
21
+ def action_with_textilize
22
+ render :inline => "<%= textilize('Они пришли -- туда -- к А. П. Чехову') %>"
23
+ end
24
+
25
+ def action_with_textilize_without_overrides
26
+ RuTils.overrides = false
27
+ render :inline => "<%= textilize('Они пришли -- туда -- к А. П. Чехову') %>"
28
+ end
29
+
30
+ def action_with_markdown
31
+ render :inline => "<%= markdown('Они пришли -- туда -- к А. П. Чехову') %>"
32
+ end
33
+
34
+ def action_with_markdown_without_overrides
35
+ RuTils.overrides = false
36
+ render :inline => "<%= markdown('Они пришли -- туда -- к А. П. Чехову') %>"
37
+ end
38
+
39
+ def rescue_action(e)
40
+ raise e
41
+ end
42
+ end
43
+
44
+ def setup
45
+ @request = ActionController::TestRequest.new
46
+ @response = ActionController::TestResponse.new
47
+ @controller = Kontroller.new
48
+ end
49
+
50
+ def test_action_with_gilensize
51
+ get :action_with_gilensize
52
+ assert_equal 'Они&#160;пришли &#8212; туда &#8212; к&#160;А.П.&#8201;Чехову', @response.body
53
+ end
54
+
55
+ def test_action_with_gilensize_and_options
56
+ get :action_with_gilensize_and_options
57
+ assert_equal "Они пришли — туда — к А.П. Чехову", @response.body
58
+ end
59
+
60
+ def test_action_with_textilize
61
+ get :action_with_textilize
62
+ assert_equal "<p>Они пришли &#8212; туда &#8212; к&#160;А.П.&#8201;Чехову</p>", @response.body
63
+ end
64
+
65
+ def test_action_with_textilize_without_overrides
66
+ get :action_with_textilize_without_overrides
67
+ assert_equal "<p>Они пришли &#8212; туда &#8212; к А. П. Чехову</p>", @response.body, "Initials should not be formatted"
68
+ end
69
+
70
+ def test_action_with_markdown
71
+ get :action_with_markdown
72
+ assert_equal "<p>Они пришли &#8212; туда &#8212; к&#160;А.П.&#8201;Чехову</p>", @response.body
73
+ end
74
+
75
+ def test_action_with_markdown_without_overrides
76
+ get :action_with_markdown_without_overrides
77
+ assert_equal "<p>Они пришли -- туда -- к А. П. Чехову</p>", @response.body
78
+ end
79
+
80
+ end
@@ -0,0 +1,85 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'action_controller'
4
+ require 'action_view'
5
+
6
+ require 'action_controller/test_process'
7
+ require File.dirname(__FILE__) + '/../../init.rb'
8
+ require 'action_pack/version'
9
+
10
+ ma, mi, ti = ActionPack::VERSION::MAJOR, ActionPack::VERSION::MINOR, ActionPack::VERSION::TINY
11
+
12
+ raise LoadError, "RuTils is not 2.2.2 compat" if (ma >= 2 && mi >= 2 && ti >= 1)
13
+
14
+ # Перегрузка helper'ов Rails
15
+ class RailsHelpersOverrideTest < Test::Unit::TestCase
16
+ TEST_DATE = Date.parse("1983-10-15") # coincidentially...
17
+ TEST_TIME = Time.local(1983, 10, 15, 12, 15) # also coincidentially...
18
+
19
+ # Вспомогательный класс для тестирования перегруженного DateHelper
20
+ class HelperStub
21
+ # для тестирования to_datetime_select_tag
22
+ def date_field; TEST_TIME; end
23
+ end
24
+
25
+ def setup
26
+ RuTils::overrides = true
27
+ # А никто и не говорил что класс должен быть один :-)
28
+ k = Class.new(HelperStub)
29
+ [ActionView::Helpers::TagHelper, ActionView::Helpers::DateHelper].each{|m| k.send(:include, m)}
30
+ @stub = k.new
31
+ end
32
+
33
+ def test_distance_of_time_in_words
34
+ assert_equal "20 минут", @stub.distance_of_time_in_words(Time.now - 20.minutes, Time.now)
35
+ end
36
+
37
+ def test_select_month
38
+ assert_match /июль/, @stub.select_month(TEST_DATE),
39
+ "Месяц в выборе месяца должен быть указан в именительном падеже"
40
+ assert_match />7\<\/option\>/, @stub.select_month(TEST_DATE, :use_month_numbers => true),
41
+ "Хелпер select_month с номером месяца вместо названия месяца"
42
+ assert_match /10\ \-\ октябрь/, @stub.select_month(TEST_DATE, :add_month_numbers => true),
43
+ "Хелпер select_month с номером и названием месяца"
44
+ assert_match /\>июн\<\/option\>/, @stub.select_month(TEST_DATE, :use_short_month => true),
45
+ "Короткое имя месяца при использовании опции :use_short_month"
46
+ assert_match /name\=\"date\[foobar\]\"/, @stub.select_month(TEST_DATE, :field_name => "foobar"),
47
+ "Хелпер select_month должен принимать опцию :field_name"
48
+ assert_match /type\=\"hidden\".+value\=\"10\"/m, @stub.select_month(TEST_DATE, :use_hidden => true),
49
+ "Хелпер select_month должен принимать опцию :use_hidden"
50
+ end
51
+
52
+ def test_select_date
53
+ assert_match /date\_day.+date\_month.+date\_year/m, @stub.select_date(TEST_DATE),
54
+ "Хелпер select_date должен выводить поля в следующем порядке: день, месяц, год"
55
+ assert_match /декабря/, @stub.select_date(TEST_DATE),
56
+ "Имя месяца должно быть указано в родительном падеже"
57
+ assert_match /декабря/, @stub.select_date(TEST_DATE, :order => [:month, :year]),
58
+ "Хелпер select_date не позволяет опускать фрагменты, имя месяца должно быть указано в родительном падеже"
59
+ assert_match @stub.select_date, @stub.select_date(Time.now),
60
+ "Хелпер select_date без параметров работает с текущей датой"
61
+ end
62
+
63
+ def test_select_datetime
64
+ assert_match /date\_day.+date\_month.+date\_year/m, @stub.select_datetime(TEST_TIME),
65
+ "Хелпер select_datetime должен выводить поля в следующем порядке: день, месяц, год"
66
+ end
67
+
68
+ def test_html_options
69
+ if ActionView::Helpers::DateHelper::DATE_HELPERS_RECEIVE_HTML_OPTIONS
70
+ assert_match /id\=\"foobar\"/m, @stub.select_month(TEST_DATE, {}, :id => "foobar"),
71
+ "Хелпер select_month принимает html_options"
72
+
73
+ assert_match /id\=\"foobar\"/m, @stub.select_date(TEST_DATE, {}, :id => "foobar"),
74
+ "Хелпер select_date принимает html_options"
75
+ end
76
+ end
77
+
78
+ def test_instance_tag
79
+ @it = ActionView::Helpers::InstanceTag.new(:stub, :date_field, self).to_datetime_select_tag
80
+ assert_match /\>10\<.+\>октября\<.+\>1983\</m, @it,
81
+ "to_datetime_select_rag должен выводить поля в следующем порядке: день, месяц, год"
82
+ assert_match /июля/m, @it,
83
+ "to_datetime_select_tag выводит месяц в родительном падеже"
84
+ end
85
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'rdiscount'
3
+
4
+ # Интеграция с BlueCloth - Markdown
5
+ # Сам Markdown никакой обработки типографики не производит (это делает RubyPants, но вряд ли его кто-то юзает на практике)
6
+ class RdiscountIntegrationTest < Test::Unit::TestCase
7
+ C = RuTils::Gilenson::RDiscountExtra
8
+
9
+ def test_integration_markdown
10
+
11
+ assert_equal "<p>И вот&#160;&#171;они пошли туда&#187;, и&#160;шли шли&#160;шли</p>",
12
+ C.new('И вот "они пошли туда", и шли шли шли').to_html
13
+
14
+ end
15
+ end