julik-rutils 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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