rutils 0.0.3

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.
data/CHANGELOG ADDED
@@ -0,0 +1,5 @@
1
+ Версия 0.03 - 18.10.2005
2
+ * Легкий рефакторинг и чистка документации, добавлена реализация BiDi-транслита
3
+
4
+ Версия 0.02 - 12.07.2005
5
+ * Заменен маркер подстановки тегов в Gilenson. Ранее без oniguruma из-за его применения "проглатывалась" буква "р"
data/README ADDED
@@ -0,0 +1,104 @@
1
+ == Добро пожаловать в RuTils
2
+
3
+ RuTils - простой обработчик русского текста, позволяющий использовать и обрабатывать
4
+ русский текст несколькими несложными способами. Основная цель RuTils - сделать
5
+ разработку русскоязычных приложений на Ruby (и Rails) максимально простой и приятной (в идеале - столь же
6
+ простой как и разработку оных на английском)
7
+
8
+ Весь функционал RuTils поддерживает только UTF-8 (настройка $KCODE / KanjiCode 'u'). Стандартно работа RuTils проверяется
9
+ как на стандартной версии Ruby, так и на парсере регулярных выражений Oniguruma (правда имейте в виду, что с ним
10
+ Gilenson работает медленнее).
11
+
12
+
13
+ Это версия RuTils
14
+
15
+ $Revision: 1.6 $
16
+
17
+ Пожалуйста упоминайте версию при сообщении ошибок.
18
+
19
+ Удостоверьтесь, что ваш скрипт правильно обрабатывает Unicode - то есть:
20
+
21
+ * Переменная $KCODE включена в режим 'u'
22
+ * В скрипт загружена библиотека jcode
23
+
24
+ Если вы используете RuTils для сайта под mod_ruby воспользуйтесь директивой RubyKanjiCode в своем httpd.conf.
25
+
26
+ == Cумма прописью
27
+
28
+ RuTils реализует сумму прописью для целых и дробных чисел, с дополнительным учетом рода. Например:
29
+
30
+ 4.propisju => "четыре"
31
+ 345.propisju => "триста сорок пять"
32
+ 231.propisju(2) => "двести тридцать одна"
33
+ 341.propisju_items(1, "чемодан", "чемодана", "чемоданов") => "триста сорок один чемодан"
34
+ (212.40).propisju_items(2, "сволочь", "сволочи", "сволочей") => "двести двенадцать целых четыре десятых сволочи"
35
+
36
+ Также реализуется выбор варианта числительного в зависимости от числа
37
+
38
+ 15.items("кодер", "кодера", "кодеров") => "кодеров"
39
+
40
+ == Транслит
41
+
42
+ RuTils на данный момент реализует простейший транслит "в одну сторону".
43
+
44
+ "Вот такое вот дело".translify => "Vot takoye vot delo"
45
+ "Несомненный прогресс по сравнению с PHP".dirify => "nesomnennyi-progress-po-sravneniu-s-php"
46
+
47
+ В ближайшее время будет добавлен BiDi-транслит.
48
+
49
+ == Обработка русской типографики в HTML
50
+
51
+ RuTils включает Gilenson - порт Тыпографицы[http://pixel-apes.com/typografica] от
52
+ Pixel Apes на Ruby. Тыпографица - механизм автоматической расстановки подстановок в тексте
53
+ перед его выводом в HTML, оформляющий неразрывные пробелы, типографские кавычки
54
+ и реализующая элементарные макроподстановки.
55
+
56
+ Большое спасибо Роману Иванову aka Kukutz и Николаю Яремко aka Kuso Mendokuzee за изначальную реализацию
57
+ на PHP.
58
+
59
+ Имейте в виду, что на баги в Gilenson жаловаться разработчикам Typografica не стоит -
60
+ они вас не поймут и будут правы. Поддержку Gilenson PixelApes не осуществляют.
61
+
62
+ В комплекте также есть скрипт gilensize, которым можно поточно обрабатывать Unicode-тексты в среде UNIX
63
+ пользуясь стандартным выводом
64
+
65
+ $ cat myfile.txt | gilensize > myfile.html
66
+
67
+ == Интеграция с Rails, RedCloth и BlueCloth
68
+
69
+ RuTils в первую очередь задумывался как максимально "прозрачный" механизм обработки русского текста
70
+ в контексте Rails-приложения. Если вы используете RuTils в одном приложении с RedCloth или BlueCloth,
71
+ RuTils автоматически будет обрабатывать типографику во всех текстах, пропускаемых через них. Имейте в виду, что для
72
+ корректной работы этой функции RuTils надо загружать после модулей RedCloth и BlueCloth.
73
+
74
+
75
+ В принципе если вы пользуетесь RedCloth или BlueCloth все что ими обрабатывается будет автоматически
76
+ обрабатываться и Gilenson'ом тоже. В случае с RedCloth Glienson автоматически заменяет стандартные для
77
+ Textile английские кавычки и типографские знаки на свои - русские.
78
+
79
+ Перегрузку всех функций (RedCloth, BlueCloth и компоненты Rails) можно включать и отключать в любое время
80
+ с помощью метода overrides= модуля RuTils. Когда перегрузка выключена, все сторонние библиотеки будут работать
81
+ в стандартном режиме (например, RedCloth будет расставлять английские типографские кавычки).
82
+
83
+ == Требования
84
+
85
+ * Ruby 1.8.2, немного прямых рук.
86
+ * Rake[http://rake.rubyforge.org], Rails, RedCloth и BlueCloth для выполнения тестов
87
+
88
+ == Как использовать
89
+
90
+ Просто включите rutils в свою программу как gem
91
+
92
+ require_gem 'rutils'
93
+
94
+ или как библиотеку
95
+
96
+ require 'rutils'
97
+
98
+ == Где получить помощь
99
+
100
+ На странице проекта на RubyForge[http://rubyforge.org/projects/rutils]
101
+
102
+ == Работает ли это с текстом в кодировке Windows-1251
103
+
104
+ Нет и никогда не будет.
data/TODO ADDED
@@ -0,0 +1,26 @@
1
+ =TODO
2
+
3
+ ==Gilenson
4
+
5
+ * Заменить все entities в Гиленсоне на UTF-эквиваленты (в том числе и в тестах)
6
+ (пока генерируемый им код содержит, например, raquo и nbsp - неприменимо для XML)
7
+ * Выяснить, стоит ли отрабатывать типографику в атрибутах тегов
8
+ * Полностью рефакторнуть (вынести каждую трансформацию в метод)
9
+ * чтобы тестить трансформации по одной
10
+ * чтобы применять трансформации по одной буде на то нужда
11
+
12
+ ==Pluralization
13
+
14
+ * Истинная плюрализация без передачи рода и вариантов (как в Rails)
15
+
16
+ ==Даты
17
+
18
+ * В принципе нужно обеспечить полноценное покрытие stfmt
19
+
20
+ ==Rails
21
+
22
+ * distance_of_time_in_words и тому подобные
23
+
24
+ ==Транслит
25
+
26
+ * bidi-транслит (Данил)
data/bin/gilensize ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ $KCODE = 'u'
3
+ require 'rubygems'
4
+ require_gem 'rutils'
5
+
6
+ while st = gets do
7
+ puts RuTils::Gilenson::Formatter.new(st).to_html
8
+ end
@@ -0,0 +1,61 @@
1
+ require 'date'
2
+
3
+ module RuTils
4
+ module DateTime
5
+ ABBR_MONTHNAMES = %w{ Янв Фев Мар Апр Май Июн Июл Авг Сен Окт Ноя Дек }
6
+ MONTHNAMES = %w{ Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь }
7
+ def self.distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, absolute = false) #nodoc
8
+ from_time = from_time.to_time if from_time.respond_to?(:to_time)
9
+ to_time = to_time.to_time if to_time.respond_to?(:to_time)
10
+ distance_in_minutes = (((to_time - from_time).abs)/60).round
11
+ distance_in_seconds = ((to_time - from_time).abs).round
12
+
13
+ case distance_in_minutes
14
+ when 0..1
15
+ return (distance_in_minutes==0) ? 'меньше минуты' : '1 минуту' unless include_seconds
16
+
17
+ case distance_in_seconds
18
+ when 0..5 then 'менее чем 5 секунд'
19
+ when 6..10 then 'менее чем 10 секунд'
20
+ when 11..20 then 'менее чем 20 секунд'
21
+ when 21..40 then 'пол-минуты'
22
+ when 41..59 then 'меньше минуты'
23
+ else '1 минуту'
24
+ end
25
+
26
+ when 2..45 then distance_in_minutes.propisju_items(2, "минута", "минуты", "минут")
27
+ when 46..90 then 'около часа'
28
+ when 90..1440 then "около " + (distance_in_minutes.to_f / 60.0).round.items("час", "часа", "часов")
29
+ when 1441..2880 then '1 день'
30
+ else (distance_in_minutes / 1440).round.items("день", "дня", "дней")
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+ class RuTils::DateTime::RussianDate < Date
38
+ # Full month names, in English. Months count from 1 to 12; a
39
+ # month's numerical representation indexed into this array
40
+ # gives the name of that month (hence the first element is nil).
41
+ MONTHNAMES = [nil] + %w(Январь Февраль Март Апрель Май Июнь Июль
42
+ Август Сентябрь Октябрь Ноябрь Декабрь)
43
+
44
+ # Full names of days of the week, in English. Days of the week
45
+ # count from 0 to 6 (except in the commercial week); a day's numerical
46
+ # representation indexed into this array gives the name of that day.
47
+ DAYNAMES = %w(Воскресенье Понедельник Вторник Среда Четверг Пятница Суббота)
48
+
49
+ # Abbreviated month names, in English.
50
+ ABBR_MONTHNAMES = [nil] + %w(Янв Фев Мар Апр Май Июнь
51
+ Июль Авг Сен Окт Ноя Дек)
52
+ # Abbreviated day names, in English.
53
+ ABBR_DAYNAMES = %w(Вск Пн Вт Ср Чт Пт Сб)
54
+
55
+ end
56
+
57
+ class Date
58
+ def ru_strftime(*args)
59
+ RuTils::DateTime::RussianDate.new(self).strftime(*args)
60
+ end
61
+ end
@@ -0,0 +1,280 @@
1
+ module RuTils
2
+ class Gilenson < String #:nodoc:
3
+
4
+ def initialize(*args)
5
+ # Задача (вкратце) состоит в том чтобы все ступени разработки развести в отдельные методы
6
+ # и тестировать их отдельно друг от друга (а также иметь возможность их по-одному включать и выключать).
7
+ # Фильтры, которые начинаются с lift работают с блоком (например - вытащить таги, провести обработку
8
+ # текста и вернуть все назад)
9
+
10
+ # Фильтры обрабатываются именно в таком порядке. Этот массив стравнивается с настройками, и если настройки
11
+ # для конкретного фильтра установлены в false этот фильтр обработан не будет.
12
+ # Каждый фильтр должен именоваться process_{filter}, принимать аргументом текст для обработки и возвращать его же!
13
+ # После того как фильтр включен в массив order_of_filters и для него написан метод фильтр по лумолчанию включается,
14
+ # и его настройку можно поменять с помощью аксессора с соотв. именем. Это делается автоматом.
15
+ # Главный обработчик должен сам понимать, использовать ли блок (если метод-делегат начинается с lift_)
16
+ # или просто process.
17
+
18
+ # Аксессор само собой генерируется автоматом.
19
+
20
+ @@order_of_filters = [
21
+ :inches,
22
+ :dashes,
23
+ :emdashes,
24
+ :specials,
25
+ :spacing,
26
+ :dashglue,
27
+ :nonbreakables,
28
+ :plusmin,
29
+ :degrees,
30
+ :phones,
31
+ :simple_quotes,
32
+ :typographer_quotes,
33
+ :compound_quotes,
34
+ ]
35
+
36
+ # Символы, используемые в подстановках. Меняются через substitute_set(subst_name, subst_content)
37
+ # Нужно потому как ващето &nbsp; недопустим в XML, равно как и всякие mdash.
38
+ @@spec_chars = {
39
+ :laquo=>'&laquo;', #left acute
40
+ :raquo=>'&raquo;', #right acute
41
+ :ndash=>'&ndash;', #en dash
42
+ :mdash=>'&mdash;', #en dash
43
+ :inch=>'&quot;', #en dash
44
+ }
45
+
46
+ @@phonemasks = [[ /([0-9]{4})\-([0-9]{2})\-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/,
47
+ /([0-9]{4})\-([0-9]{2})\-([0-9]{2})/,
48
+ /(\([0-9\+\-]+\)) ?([0-9]{3})\-([0-9]{2})\-([0-9]{2})/,
49
+ /(\([0-9\+\-]+\)) ?([0-9]{2})\-([0-9]{2})\-([0-9]{2})/,
50
+ /(\([0-9\+\-]+\)) ?([0-9]{3})\-([0-9]{2})/,
51
+ /(\([0-9\+\-]+\)) ?([0-9]{2})\-([0-9]{3})/,
52
+ /([0-9]{3})\-([0-9]{2})\-([0-9]{2})/,
53
+ /([0-9]{2})\-([0-9]{2})\-([0-9]{2})/,
54
+ /([0-9]{1})\-([0-9]{2})\-([0-9]{2})/,
55
+ /([0-9]{2})\-([0-9]{3})/,
56
+ /([0-9]+)\-([0-9]+)/,
57
+ ],[
58
+ '<nobr>\1&ndash;\2&ndash;\3&nbsp;\4:\5:\6</nobr>',
59
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
60
+ '<nobr>\1&nbsp;\2&ndash;\3&ndash;\4</nobr>',
61
+ '<nobr>\1&nbsp;\2&ndash;\3&ndash;\4</nobr>',
62
+ '<nobr>\1&nbsp;\2&ndash;\3</nobr>',
63
+ '<nobr>\1&nbsp;\2&ndash;\3</nobr>',
64
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
65
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
66
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
67
+ '<nobr>\1&ndash;\2</nobr>',
68
+ '<nobr>\1&ndash;\2</nobr>'
69
+ ]]
70
+
71
+ @@glueleft = ['рис.', 'табл.', 'см.', 'им.', 'ул.', 'пер.', 'кв.', 'офис', 'оф.', 'г.']
72
+ @@glueright = ['руб.', 'коп.', 'у.е.', 'мин.']
73
+
74
+ @@settings = {
75
+ "inches" => true, # преобразовывать дюймы в &quot;
76
+ "laquo" => true, # кавычки-ёлочки
77
+ "farlaquo" => false, # кавычки-ёлочки для фара (знаки "больше-меньше")
78
+ "quotes" => true, # кавычки-английские лапки
79
+ "dash" => true, # короткое тире (150)
80
+ "emdash" => true, # длинное тире двумя минусами (151)
81
+ "(c)" => true,
82
+ "(r)" => true,
83
+ "(tm)" => true,
84
+ "(p)" => true,
85
+ "+-" => true, # спецсимволы, какие - понятно
86
+ "degrees" => true, # знак градуса
87
+ "<-->" => true, # отступы $Indent*
88
+ "dashglue" => true, "wordglue" => true, # приклеивание предлогов и дефисов
89
+ "spacing" => true, # запятые и пробелы, перестановка
90
+ "phones" => true, # обработка телефонов
91
+ "fixed" => false, # подгон под фиксированную ширину
92
+ "html" => false # запрет тагов html
93
+ }
94
+ # irrelevant - indentation with images
95
+ @@indent_a = "<!--indent-->"
96
+ @@indent_b = "<!--indent-->"
97
+
98
+ @@mark_tag = "\xF0\xF0\xF0\xF0" # Подстановочные маркеры тегов - BOM
99
+ @@mark_ignored = "\xFF\xFF\xFF\xFF" # Подстановочные маркеры неизменяемых групп - BOM+ =)
100
+
101
+ @@ignore = /notypo/ # regex, который игнорируется. Этим надо воспользоваться для обработки pre и code
102
+
103
+ self.methods.each do | m |
104
+ next unless m.include?("process_")
105
+ raise NoMethodError, "No hook for " + m unless @@order_of_filters.include?(m.gsub(/process_/, '').to_sym)
106
+ end
107
+
108
+ @@order_of_filters.each do |filter|
109
+ raise NoMethodError, "No process method for " + filter unless self.methods.include?("process_#{filter}".to_sym)
110
+ end
111
+
112
+ super(*args)
113
+
114
+ end
115
+
116
+
117
+ def to_html(*opts)
118
+ text = self.to_s.clone
119
+ lift_tags(text) do | text |
120
+ # lift_ignored(text) do |text|
121
+ for filter in @@order_of_filters
122
+ raise "UnknownFilter #process_#{filter} in filterlist!" unless self.respond_to?("process_#{filter}".to_sym)
123
+ self.send("process_#{filter}".to_sym, text) # if @settings[filter.to_sym] # вызываем конкретный фильтр
124
+ end
125
+ # end
126
+ end
127
+ text
128
+ end
129
+
130
+ # Вытаскивает теги из текста, выполняет переданный блок и возвращает теги на место.
131
+ # Теги в процессе заменяются на специальный маркер
132
+ def lift_tags(text, marker="\xF0\xF0\xF0\xF0", &block)
133
+
134
+ # Выцепляем таги
135
+ # re = /<\/?[a-z0-9]+("+ # имя тага
136
+ # "\s+("+ # повторяющая конструкция: хотя бы один разделитель и тельце
137
+ # "[a-z]+("+ # атрибут из букв, за которым может стоять знак равенства и потом
138
+ # "=((\'[^\']*\')|(\"[^\"]*\")|([0-9@\-_a-z:\/?&=\.]+))"+ #
139
+ # ")?"+
140
+ # ")?"+
141
+ # ")*\/?>|\xA2\xA2[^\n]*?==/i;
142
+
143
+ re = /(<\/?[a-z0-9]+(\s+([a-z]+(=((\'[^\']*\')|(\"[^\"]*\")|([0-9@\-_a-z:\/?&=\.]+)))?)?)*\/?>)/ui
144
+
145
+ tags = text.scan(re).inject([]) { | ar, match | ar << match[0] }
146
+ text.gsub!(re, "\xF0\xF0\xF0\xF0") #маркер тега
147
+
148
+ yield(text, marker) if block_given? #делаем все что надо сделать без тегов
149
+
150
+ tags.each { | tag | text.sub!(marker, tag) } # Вставляем таги обратно.
151
+
152
+ end
153
+
154
+ # Выцепляет игнорированные символы, выполняет блок с текстом
155
+ # без этих символов а затем вставляет их на место
156
+ def lift_ignored(text, marker = "\xFF\xFF\xFF\xFF", &block)
157
+ ignored = text.scan(@ignore)
158
+ text.gsub!(@ignore, marker)
159
+
160
+ # обрабатываем текст
161
+ yield(text, marker) if block_given?
162
+
163
+ # возвращаем игнорированные символы
164
+ ignored.each { | tag | text.sub!(marker, tag) }
165
+ end
166
+
167
+ # Кавычки - лапки
168
+ def process_simple_quotes(text)
169
+ text.gsub!( /\"\"/ui, "&quot;&quot;")
170
+ text.gsub!( /\"\.\"/ui, "&quot;.&quot;")
171
+ _text = '""';
172
+ while _text != text do
173
+ _text = text
174
+ text.gsub!( /(^|\s|\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0|>)\"([0-9A-Za-z\'\!\s\.\?\,\-\&\;\:\_\xF0\xF0\xF0\xF0\xFF\xFF\xFF\xFF]+(\"|&#148;))/ui, '\1&#147;\2')
175
+ #this doesnt work in-place. somehow.
176
+ text.replace text.gsub( /(\&\#147\;([A-Za-z0-9\'\!\s\.\?\,\-\&\;\:\xF0\xF0\xF0\xF0\xFF\xFF\xFF\xFF\_]*).*[A-Za-z0-9][\xF0\xF0\xF0\xF0\xFF\xFF\xFF\xFF\?\.\!\,]*)\"/ui, '\1&#148;')
177
+ end
178
+ end
179
+
180
+ # Кавычки - елочки
181
+ def process_typographer_quotes(text)
182
+ # 2. ёлочки
183
+ text.gsub!( /\"\"/ui, "&quot;&quot;");
184
+ text.gsub!( /(^|\s|\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0|>|\()\"((\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0)*[~0-9ёЁA-Za-zА-Яа-я\-:\/\.])/ui, "\\1&laquo;\\2");
185
+ # nb: wacko only regexp follows:
186
+ text.gsub!( /(^|\s|\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0|>|\()\"((\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0|\/&nbsp;|\/|\!)*[~0-9ёЁA-Za-zА-Яа-я\-:\/\.])/ui, "\\1&laquo;\\2")
187
+ _text = "\"\"";
188
+ while (_text != text) do
189
+ _text = text;
190
+ text.gsub!( /(\&laquo\;([^\"]*)[ёЁA-Za-zА-Яа-я0-9\.\-:\/](\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0)*)\"/sui, "\\1&raquo;")
191
+ # nb: wacko only regexps follows:
192
+ text.gsub!( /(\&laquo\;([^\"]*)[ёЁA-Za-zА-Яа-я0-9\.\-:\/](\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0)*\?(\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0)*)\"/sui, "\\1&raquo;")
193
+ text.gsub!( /(\&laquo\;([^\"]*)[ёЁA-Za-zА-Яа-я0-9\.\-:\/](\xFF\xFF\xFF\xFF|\xF0\xF0\xF0\xF0|\/|\!)*)\"/sui, "\\1&raquo;")
194
+ end
195
+ end
196
+
197
+ # Cложные кавычки
198
+ def process_compound_quotes(text)
199
+ text.gsub!(/(\&\#147\;(([A-Za-z0-9'!\.?,\-&;:]|\s|\xF0\xF0\xF0\xF0|\xFF\xFF\xFF\xFF)*)&laquo;(.*)&raquo;)&raquo;/ui,"\\1&#148;");
200
+ end
201
+
202
+ # Обрабатывает короткое тире
203
+ def process_dashes(text)
204
+ text.gsub!( /(\s|;)\-(\s)/ui, "\\1&ndash;\\2")
205
+ end
206
+
207
+ # Обрабатывает длинные тире
208
+ def process_emdashes(text)
209
+ text.gsub!( /(\s|;)\-\-(\s)/ui, "\\1&mdash;\\2")
210
+ end
211
+
212
+ # Обрабатывает знаки копирайта, торговой марки и т.д.
213
+ def process_specials(text)
214
+ # 4. (с)
215
+ text.gsub!(/\([сСcC]\)((?=\w)|(?=\s[0-9]+))/u, "&copy;")
216
+ # 4a. (r)
217
+ text.gsub!( /\(r\)/ui, "<sup>&#174;</sup>")
218
+
219
+ # 4b. (tm)
220
+ text.gsub!( /\(tm\)|\(тм\)/ui, "&#153;")
221
+ # 4c. (p)
222
+ text.gsub!( /\(p\)/ui, "&#167;")
223
+ end
224
+
225
+ # Склейка дефисоов
226
+ def process_dashglue(text)
227
+ text.gsub!( /([a-zа-яА-Я0-9]+(\-[a-zа-яА-Я0-9]+)+)/ui, '<nobr>\1</nobr>')
228
+ end
229
+
230
+ # Запятые и пробелы
231
+ def process_spacing(text)
232
+ text.gsub!( /(\s*)([,]*)/sui, "\\2\\1");
233
+ text.gsub!( /(\s*)([\.?!]*)(\s*[ЁА-ЯA-Z])/su, "\\2\\1\\3");
234
+ end
235
+
236
+ # Неразрывные пробелы - пока глючит страшным образом
237
+ def process_nonbreakables(text)
238
+ text.replace " " + text + " ";
239
+ _text = " " + text + " ";
240
+ until _text == text
241
+ _text.replace text.clone
242
+ text.gsub!( /(\s+)([a-zа-яА-Я]{1,2})(\s+)([^\\s$])/ui, '\1\2&nbsp;\4')
243
+ text.gsub!( /(\s+)([a-zа-яА-Я]{3})(\s+)([^\\s$])/ui, '\1\2&nbsp;\4')
244
+ end
245
+
246
+ for i in @glueleft
247
+ text.gsub!( /(\s)(#{i})(\s+)/sui, '\1\2&nbsp;')
248
+ end
249
+
250
+ for i in @glueright
251
+ text.gsub!( /(\s)(#{i})(\s+)/sui, '&nbsp;\2\3')
252
+ end
253
+
254
+ end
255
+
256
+ # Знак дюйма
257
+ def process_inches(text)
258
+ text.gsub!(/\s([0-9]{1,2}([\.,][0-9]{1,2})?)\"/ui, ' \1&quot;') if @settings["inches"]
259
+ end
260
+
261
+ # Обрабатывает знак +/-
262
+ def process_plusmin(text)
263
+ text.gsub!(/\+\-/ui, "&#177;") if @settings["+-"]
264
+ end
265
+
266
+ # Обрабатывает телефоны
267
+ def process_phones(text)
268
+ @phonemasks[0].each_with_index do |regex, i|
269
+ text.gsub!(regex, @phonemasks[1][i])
270
+ end
271
+ end
272
+
273
+ # Обрабатывает знак градуса, набранный как caret
274
+ def process_degrees(text)
275
+ text.gsub!( /-([0-9])+\^([FCС])/, '&ndash;\1&#176\2')
276
+ text.gsub!( /\+([0-9])+\^([FCС])/, "+\\1&#176\\2")
277
+ text.gsub!( /\^([FCС])/, "&#176\\1")
278
+ end
279
+ end
280
+ end