rutils 1.0.3 → 1.1.1
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/History.txt +8 -0
- data/Manifest.txt +1 -4
- data/README.txt +0 -4
- data/Rakefile.rb +1 -0
- data/TODO.txt +1 -4
- data/init.rb +4 -4
- data/lib/gilenson/gilenson_stub.rb +21 -0
- data/lib/integration/rails_date_helper_override.rb +15 -26
- data/lib/pluralizer/pluralizer.rb +27 -0
- data/lib/rutils.rb +6 -2
- data/lib/transliteration/bidi.rb +1 -1
- data/lib/transliteration/transliteration.rb +28 -2
- data/lib/version.rb +1 -1
- data/test/extras/integration_rails_filter.rb +8 -1
- data/test/extras/integration_rails_gilenson_helpers.rb +13 -7
- data/test/extras/integration_rails_helpers.rb +37 -9
- data/test/extras/integration_rdiscount.rb +0 -1
- data/test/test_pluralize.rb +9 -0
- metadata +59 -17
- data/WHAT_HAS_CHANGED.txt +0 -44
- data/bin/gilensize +0 -22
- data/lib/gilenson/gilenson.rb +0 -665
- data/test/test_gilenson.rb +0 -396
data/test/test_pluralize.rb
CHANGED
@@ -43,6 +43,15 @@ class PropisjuTestCase < Test::Unit::TestCase
|
|
43
43
|
assert_equal "один рубль", 1.rubl
|
44
44
|
assert_equal "три рубля четырнадцать копеек", (3.14).rublja
|
45
45
|
end
|
46
|
+
|
47
|
+
def test_griven
|
48
|
+
assert_equal "сто двадцать три гривны", 123.griven
|
49
|
+
assert_equal "триста сорок три гривны двадцать копеек", (343.20).griven
|
50
|
+
assert_equal "сорок две копейки", (0.4187).griven
|
51
|
+
assert_equal "триста тридцать две гривны", (331.995).griven
|
52
|
+
assert_equal "одна гривна", 1.grivna
|
53
|
+
assert_equal "три гривны четырнадцать копеек", (3.14).grivny
|
54
|
+
end
|
46
55
|
|
47
56
|
def test_kopeek
|
48
57
|
assert_equal "сто двадцать три рубля", 12300.kopeek
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rutils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 17
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 1.1.1
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Julian 'Julik' Tarkhanov
|
@@ -11,25 +17,60 @@ autorequire:
|
|
11
17
|
bindir: bin
|
12
18
|
cert_chain: []
|
13
19
|
|
14
|
-
date:
|
20
|
+
date: 2010-08-15 00:00:00 +02:00
|
15
21
|
default_executable:
|
16
22
|
dependencies:
|
17
23
|
- !ruby/object:Gem::Dependency
|
18
|
-
name:
|
24
|
+
name: gilenson
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 3
|
32
|
+
segments:
|
33
|
+
- 0
|
34
|
+
version: "0"
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rubyforge
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 0
|
49
|
+
- 4
|
50
|
+
version: 2.0.4
|
19
51
|
type: :development
|
20
|
-
|
21
|
-
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: hoe
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
22
58
|
requirements:
|
23
59
|
- - ">="
|
24
60
|
- !ruby/object:Gem::Version
|
25
|
-
|
26
|
-
|
61
|
+
hash: 21
|
62
|
+
segments:
|
63
|
+
- 2
|
64
|
+
- 6
|
65
|
+
- 1
|
66
|
+
version: 2.6.1
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
27
69
|
description: Simple processing of russian strings
|
28
70
|
email:
|
29
71
|
- me@julik.nl
|
30
72
|
- yaroslav@markin.net
|
31
73
|
executables:
|
32
|
-
- gilensize
|
33
74
|
- rutilize
|
34
75
|
extensions: []
|
35
76
|
|
@@ -38,21 +79,18 @@ extra_rdoc_files:
|
|
38
79
|
- Manifest.txt
|
39
80
|
- README.txt
|
40
81
|
- TODO.txt
|
41
|
-
- WHAT_HAS_CHANGED.txt
|
42
82
|
files:
|
43
83
|
- History.txt
|
44
84
|
- Manifest.txt
|
45
85
|
- README.txt
|
46
86
|
- Rakefile.rb
|
47
87
|
- TODO.txt
|
48
|
-
- WHAT_HAS_CHANGED.txt
|
49
|
-
- bin/gilensize
|
50
88
|
- bin/rutilize
|
51
89
|
- init.rb
|
52
90
|
- lib/countries/countries.rb
|
53
91
|
- lib/datetime/datetime.rb
|
54
92
|
- lib/gilenson/bluecloth_extra.rb
|
55
|
-
- lib/gilenson/
|
93
|
+
- lib/gilenson/gilenson_stub.rb
|
56
94
|
- lib/gilenson/helper.rb
|
57
95
|
- lib/gilenson/maruku_extra.rb
|
58
96
|
- lib/gilenson/rdiscount_extra.rb
|
@@ -76,7 +114,6 @@ files:
|
|
76
114
|
- test/extras/integration_redcloth4.rb
|
77
115
|
- test/run_tests.rb
|
78
116
|
- test/test_datetime.rb
|
79
|
-
- test/test_gilenson.rb
|
80
117
|
- test/test_integration.rb
|
81
118
|
- test/test_integration_flag.rb
|
82
119
|
- test/test_pluralize.rb
|
@@ -96,27 +133,32 @@ rdoc_options:
|
|
96
133
|
require_paths:
|
97
134
|
- lib
|
98
135
|
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
99
137
|
requirements:
|
100
138
|
- - ">="
|
101
139
|
- !ruby/object:Gem::Version
|
140
|
+
hash: 3
|
141
|
+
segments:
|
142
|
+
- 0
|
102
143
|
version: "0"
|
103
|
-
version:
|
104
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
105
146
|
requirements:
|
106
147
|
- - ">="
|
107
148
|
- !ruby/object:Gem::Version
|
149
|
+
hash: 3
|
150
|
+
segments:
|
151
|
+
- 0
|
108
152
|
version: "0"
|
109
|
-
version:
|
110
153
|
requirements: []
|
111
154
|
|
112
155
|
rubyforge_project: rutils
|
113
|
-
rubygems_version: 1.3.
|
156
|
+
rubygems_version: 1.3.7
|
114
157
|
signing_key:
|
115
158
|
specification_version: 3
|
116
159
|
summary: Simple processing of russian strings
|
117
160
|
test_files:
|
118
161
|
- test/test_datetime.rb
|
119
|
-
- test/test_gilenson.rb
|
120
162
|
- test/test_integration.rb
|
121
163
|
- test/test_integration_flag.rb
|
122
164
|
- test/test_pluralize.rb
|
data/WHAT_HAS_CHANGED.txt
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
== Изменения по отношению к RuTils 0.2.x
|
2
|
-
|
3
|
-
=== Никаких оверрайдов
|
4
|
-
|
5
|
-
К сожалению, переделать все существующие во Вселенной библиотеки невозможно. Мы предоставляем
|
6
|
-
унаследованные классы которые реализуют нужную нам функциональность с минимальной хирургией чужих
|
7
|
-
модулей. Например, если раньше вы делали так:
|
8
|
-
|
9
|
-
RuTils.overrides = true
|
10
|
-
BlueCloth.new(text_to_markdown_and_gilensize).to_html
|
11
|
-
|
12
|
-
то теперь нужно делать так
|
13
|
-
|
14
|
-
RuTils::Gilenson::BlueClothExtra.new(text_to_markdown_and_gilensize).to_html
|
15
|
-
|
16
|
-
=== Почему удален BiDi-транслит?
|
17
|
-
|
18
|
-
В отличие от DHH авторы RuTils придерживаются стратегии синтактической серной кислоты вместо синтактического уксуса. Основная область
|
19
|
-
применения bidi-транслитераций - генерация "как-бы" более удобочитаемых URL. К сожалению, у нее есть ряд свойств которые делают ее
|
20
|
-
бессмысленной (кроме как в качестве упражнения по строковым итераторам Ruby). Приводим список аргументов почему вам не нужны
|
21
|
-
автоматические транслитерированные URL:
|
22
|
-
|
23
|
-
* Они будут работать только для набора символов "ASCII + русский". Любая попытка засунуть в ваш URL слово stød закончится печально.
|
24
|
-
* Они будут работать только для русского языка, кириллиц много. Транслитерация по определению языкозависима.
|
25
|
-
* Вашим пользователям придется непрерывно угадывать, пишется буква "я". "Ja"? "Ya"? "J"? Если вы хоть раз наблюдали иностранца, пытающегося
|
26
|
-
выговорить "ОВИРскую" транслитерацию вашей фамилии из загранпаспорта, вы знаете о чем мы говорим.
|
27
|
-
* Приличные браузеры не кодируют русский текст в адресной строке если Ваш вебсервер его принял. Если браузер неприличный то он позволяет этот текст ввести.
|
28
|
-
Если браузер совсем неприличный, то средство ввода у него - стилус размером с зубочистку, а пользуются им в трамвае. Вводить ваш транслит
|
29
|
-
в таких условиях все равно никто не будет, успокойтесь.
|
30
|
-
|
31
|
-
Приводить список аргументов "почему такой транслит вам нужен" мы не будем дабы никого не травмировать.
|
32
|
-
|
33
|
-
Если вам таки страшно неймется реализовать транслит в URL, рекомендуем следующий подход:
|
34
|
-
|
35
|
-
* Для адресуемого обьекта сохраняется поле ++slug++
|
36
|
-
* При сохранении в это поле автоматически пишется "дирифицированное" название, но пользователь может его вручную отредактировать
|
37
|
-
* Дальнейшая адресация производится без "транслитерации обратно", по полю slug напрямую
|
38
|
-
|
39
|
-
Дополнительно рекомендуется запретить загрузку файлов с русскими именами (с помощью Javascript и свойства value элемента input).
|
40
|
-
|
41
|
-
=== Рубинов много
|
42
|
-
|
43
|
-
Это актуально только для тех кто собирается слать патчи. RuTils тестирован и работает под двумя версиями MRI и под JRuby. Это автоматически означает
|
44
|
-
что патчи должны тестироваться во всех этих средах.
|
data/bin/gilensize
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# == Synopsis
|
3
|
-
#
|
4
|
-
# Processes text on standard input with Gilenson. Please feed it UTF-8!
|
5
|
-
#
|
6
|
-
# == Usage
|
7
|
-
#
|
8
|
-
# cat myfile.txt | gilensize > output.txt
|
9
|
-
#
|
10
|
-
# == Author
|
11
|
-
# Julik <me@julik.nl>
|
12
|
-
|
13
|
-
$KCODE = 'u'
|
14
|
-
require File.dirname(__FILE__) + '/../lib/rutils'
|
15
|
-
require 'optparse'
|
16
|
-
OptionParser.new do | p |
|
17
|
-
p.on(" -h", "--help") { require 'rdoc/usage'; RDoc::usage }
|
18
|
-
end.parse!
|
19
|
-
|
20
|
-
while st = gets do
|
21
|
-
puts RuTils::Gilenson.new(st).to_html
|
22
|
-
end
|
data/lib/gilenson/gilenson.rb
DELETED
@@ -1,665 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
module RuTils
|
3
|
-
module Gilenson
|
4
|
-
# Позволяет возвращать класс форматтера при вызове
|
5
|
-
# RuTils::Gilenson.new
|
6
|
-
def self.new(*args) #:nodoc:
|
7
|
-
RuTils::Gilenson::Formatter.new(*args)
|
8
|
-
end
|
9
|
-
|
10
|
-
autoload :BlueClothExtra, File.dirname(__FILE__) + '/bluecloth_extra'
|
11
|
-
autoload :RedClothExtra, File.dirname(__FILE__) + '/redcloth_extra'
|
12
|
-
autoload :RDiscountExtra, File.dirname(__FILE__) + '/rdiscount_extra'
|
13
|
-
autoload :MarukuExtra, File.dirname(__FILE__) + '/maruku_extra'
|
14
|
-
autoload :Helper, File.dirname(__FILE__) + '/helper'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# ==Что такое Gilenson
|
19
|
-
# Обработчик типографских символов в HTML согласно общепринятым правилам.
|
20
|
-
# Посвящается П.Г.Гиленсону[http://www.rudtp.ru/lib.php?book=172], благодаря которому русские правила тех.
|
21
|
-
# редактуры еще как минимум 20 лет таки останутся бессмысленно старомодными.
|
22
|
-
#
|
23
|
-
# Gilenson расставит в тексте "умные" правильные кавычки (русские - для кириллицы, английские - для латиницы),
|
24
|
-
# заменит "хитрые" пунктуационные символы на entities и отформатирует знаки типа (c), (tm), телефоны и адреса.
|
25
|
-
#
|
26
|
-
# Gilenson базируется на коде Typografica[http://pixel-apes.com/typografica] от PixelApes,
|
27
|
-
# который был приведен к положенному в Ruby стандарту. Основные отличия Gilenson от Typografica на PHP:
|
28
|
-
# * работа только и полностью в UTF-8 (включая entities, применимые в XML)
|
29
|
-
# * поддержка "raw"-вывода (символов вместо entities) - текст выводимый Gilenson можно верстать на бумаге
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# ==Использование
|
33
|
-
# Быстрее всего - через метод ++gilensize++ для любой строковой переменной
|
34
|
-
# %{ И вот они таки "приехали"}.gilensize => 'И вот они таки «приехали»'
|
35
|
-
# Все дополнительные настройки в таком случае передаются форматтеру
|
36
|
-
# %{ И вот они таки "приехали"}.gilensize(:laquo=>false) => 'И вот они таки "приехали"'
|
37
|
-
#
|
38
|
-
# Если форматтер надо настроить более тонко, можно использовать его и так:
|
39
|
-
# typ = RuTils::Gilenson.new('Эти "так называемые" великие деятели')
|
40
|
-
# typ.to_html => 'Эти «так называемые» великие деятели'
|
41
|
-
#
|
42
|
-
# или как фильтр
|
43
|
-
# formatter = RuTils::Gilenson.new
|
44
|
-
# formatter.configure(:dash=>true)
|
45
|
-
# for string in strings
|
46
|
-
# puts formatter.process(string)
|
47
|
-
# end
|
48
|
-
#
|
49
|
-
# ==Настройки
|
50
|
-
# Настройки регулируются через методы
|
51
|
-
# formatter.dashglue = true
|
52
|
-
# или ассоциированным хешем
|
53
|
-
# formatter.configure!(:dash=>true, :quotes=>false)
|
54
|
-
#
|
55
|
-
# Хеш также можно передавать как последний аргумент методам process и to_html,
|
56
|
-
# в таком случае настройки будут применены только при этом вызове
|
57
|
-
#
|
58
|
-
# beautified = formatter.process(my_text, :dash=>true)
|
59
|
-
#
|
60
|
-
# В параметры можно подставить также ключ :all чтобы временно включить или выключить все фильтры
|
61
|
-
#
|
62
|
-
# beautified = formatter.process(my_text, :all=>true)
|
63
|
-
#
|
64
|
-
# Помимо этого можно пользоваться каждым фильтром по отдельности используя метод +apply+
|
65
|
-
#
|
66
|
-
# Можно менять глифы, которые форматтер использует для подстановок. К примеру,
|
67
|
-
# formatter.glyph[:nbsp] = ' '
|
68
|
-
# заставит форматтер расставлять "традиционные" неразрывные пробелы. Именно это - большая глупость,
|
69
|
-
# но другие глифы заменить может быть нужно.
|
70
|
-
#
|
71
|
-
# ==Настройки форматтера
|
72
|
-
# "inches" - преобразовывать дюймы в знак дюйма;
|
73
|
-
# "laquo" - кавычки-ёлочки
|
74
|
-
# "quotes" - кавычки-английские лапки
|
75
|
-
# "dash" - проставлять короткое тире (150)
|
76
|
-
# "emdash" - длинное тире двумя минусами (151)
|
77
|
-
# "initials" - проставлять тонкие шпации в инициалах
|
78
|
-
# "copypaste" - замена непечатных и "специальных" юникодных символов на entities
|
79
|
-
# "(c)" - обрабатывать знак копирайта
|
80
|
-
# "(r)", "(tm)", "(p)", "+-" - спецсимволы, какие - понятно
|
81
|
-
# "acronyms" - сворачивание пояснений к аббревиатурам (пояснение - в скобках после аббревиатуры
|
82
|
-
# без пробела). В текстовой версии пояснение будет "приклеено" к аббревиатуре
|
83
|
-
# полукруглой шпацией
|
84
|
-
# "degrees" - знак градуса
|
85
|
-
# "dashglue", "wordglue" - приклеивание предлогов и дефисов
|
86
|
-
# "spacing" - запятые и пробелы, перестановка
|
87
|
-
# "phones" - обработка телефонов
|
88
|
-
# "html" - при false - запрет использования тагов html
|
89
|
-
# "de_nobr" - при true все <nobr/> заменяются на <span class="nobr"/>
|
90
|
-
# "raw_output" - (по умолчанию false) - при true вместо entities выводятся UTF-символы
|
91
|
-
# "skip_attr" - (по умолчанию false) - при true не отрабатывать типографику в атрибутах тегов (title, alt)
|
92
|
-
# "skip_code" - (по умолчанию true) - при true не отрабатывать типографику внутри <code/>, <tt/>, CDATA
|
93
|
-
class RuTils::Gilenson::Formatter
|
94
|
-
attr_accessor :glyph
|
95
|
-
attr_accessor :settings
|
96
|
-
|
97
|
-
SETTINGS = {
|
98
|
-
"inches" => true, # преобразовывать дюймы в знак дюйма;
|
99
|
-
"laquo" => true, # кавычки-ёлочки
|
100
|
-
"quotes" => true, # кавычки-английские лапки
|
101
|
-
"dash" => true, # короткое тире (150)
|
102
|
-
"emdash" => true, # длинное тире двумя минусами (151)
|
103
|
-
"initials" => true, # тонкие шпации в инициалах
|
104
|
-
"copypaste" => false, # замена непечатных и "специальных" юникодных символов на entities
|
105
|
-
"(c)" => true, # обрабатывать знак копирайта
|
106
|
-
"(r)" => true,
|
107
|
-
"(tm)" => true,
|
108
|
-
"(p)" => true,
|
109
|
-
"acronyms" => true, # Акронимы с пояснениями - ЖЗЛ(Жизнь Замечатльных Людей)
|
110
|
-
"+-" => true, # спецсимволы, какие - понятно
|
111
|
-
"degrees" => true, # знак градуса
|
112
|
-
"dashglue" => true, "wordglue" => true, # приклеивание предлогов и дефисов
|
113
|
-
"spacing" => true, # запятые и пробелы, перестановка
|
114
|
-
"phones" => true, # обработка телефонов
|
115
|
-
"html" => true, # разрешение использования тагов html
|
116
|
-
"de_nobr" => false, # при true все <nobr/> заменяются на <span class="nobr"/>
|
117
|
-
"raw_output" => false, # выводить UTF-8 вместо entities
|
118
|
-
"skip_attr" => false, # при true не отрабатывать типографику в атрибутах тегов
|
119
|
-
"skip_code" => true, # при true не отрабатывать типографику внутри <code/>, <tt/>, CDATA
|
120
|
-
"enforce_en_quotes" => false, # только латинские кавычки
|
121
|
-
"enforce_ru_quotes" => false, # только русские кавычки (enforce_en_quotes при этом игнорируется)
|
122
|
-
} #:nodoc:
|
123
|
-
|
124
|
-
SETTINGS.freeze
|
125
|
-
|
126
|
-
# Глифы, использующиеся в подстановках по-умолчанию
|
127
|
-
GLYPHS = {
|
128
|
-
:quot => """, # quotation mark
|
129
|
-
:amp => "&", # ampersand
|
130
|
-
:apos => "'", # apos
|
131
|
-
:gt => ">", # greater-than sign
|
132
|
-
:lt => "<", # less-than sign
|
133
|
-
:nbsp => " ", # non-breaking space
|
134
|
-
:sect => "§", # section sign
|
135
|
-
:copy => "©", # copyright sign
|
136
|
-
:laquo => "«", # left-pointing double angle quotation mark = left pointing guillemet
|
137
|
-
:reg => "®", # registered sign = registered trade mark sign
|
138
|
-
:deg => "°", # degree sign
|
139
|
-
:plusmn => "±", # plus-minus sign = plus-or-minus sign
|
140
|
-
:para => "¶", # pilcrow sign = paragraph sign
|
141
|
-
:middot => "·", # middle dot = Georgian comma = Greek middle dot
|
142
|
-
:raquo => "»", # right-pointing double angle quotation mark = right pointing guillemet
|
143
|
-
:ndash => "–", # en dash
|
144
|
-
:mdash => "—", # em dash
|
145
|
-
:lsquo => "‘", # left single quotation mark
|
146
|
-
:rsquo => "’", # right single quotation mark
|
147
|
-
:ldquo => "“", # left double quotation mark
|
148
|
-
:rdquo => "”", # right double quotation mark
|
149
|
-
:bdquo => "„", # double low-9 quotation mark
|
150
|
-
:bull => "•", # bullet = black small circle
|
151
|
-
:hellip => "…", # horizontal ellipsis = three dot leader
|
152
|
-
:numero => "№", # numero
|
153
|
-
:trade => "™", # trade mark sign
|
154
|
-
:minus => "−", # minus sign
|
155
|
-
:inch => "″", # inch/second sign (u0x2033) (не путать с кавычками!)
|
156
|
-
:thinsp => " ", # полукруглая шпация (тонкий пробел)
|
157
|
-
:nob_open => '<span class="nobr">', # открывающий блок без переноса слов
|
158
|
-
:nob_close => '</span>', # закрывающий блок без переноса слов
|
159
|
-
}.freeze
|
160
|
-
|
161
|
-
# Нормальные "типографские" символы в UTF-виде. Браузерами обрабатываются плохонько, поэтому
|
162
|
-
# лучше заменять их на entities.
|
163
|
-
VERBATIM_GLYPHS = {
|
164
|
-
' ' => :nbsp,# alt+0160 (NBSP here)
|
165
|
-
'«' => :laquo,
|
166
|
-
'»' => :raquo,
|
167
|
-
'§' => :sect,
|
168
|
-
'©' => :copy,
|
169
|
-
'®' => :reg,
|
170
|
-
'°' => :deg,
|
171
|
-
'±' => :plusmn,
|
172
|
-
'¶' => :para,
|
173
|
-
'·' => :middot,
|
174
|
-
'–' => :ndash,
|
175
|
-
'—' => :mdash,
|
176
|
-
'‘' => :lsquo,
|
177
|
-
'’' => :rsquo,
|
178
|
-
'“' => :ldquo,
|
179
|
-
'”' => :rdquo,
|
180
|
-
'„' => :bdquo,
|
181
|
-
'•' => :bull,
|
182
|
-
'…' => :hellip,
|
183
|
-
'№' => :numero,
|
184
|
-
'™' => :trade,
|
185
|
-
'−' => :minus,
|
186
|
-
' ' => :thinsp,
|
187
|
-
'″' => :inch,
|
188
|
-
}.freeze
|
189
|
-
|
190
|
-
# Метка на которую подменяются вынутые теги
|
191
|
-
REPLACEMENT_MARKER = RuTils::SUBSTITUTION_MARKER #:nodoc:
|
192
|
-
|
193
|
-
# Кто придумал “? Не учите людей плохому...
|
194
|
-
# Привет А.Лебедеву http://www.artlebedev.ru/kovodstvo/62/
|
195
|
-
# Используем символы, потом берем по символам из glyphs форматтера.
|
196
|
-
# Молодец mash!
|
197
|
-
FORBIDDEN_NUMERIC_ENTITIES = {
|
198
|
-
'132' => :bdquo,
|
199
|
-
'133' => :hellip,
|
200
|
-
'146' => :apos,
|
201
|
-
'147' => :ldquo,
|
202
|
-
'148' => :rdquo,
|
203
|
-
'149' => :bull,
|
204
|
-
'150' => :ndash,
|
205
|
-
'151' => :mdash,
|
206
|
-
'153' => :trade,
|
207
|
-
}.freeze
|
208
|
-
|
209
|
-
# All the unicode whitespace
|
210
|
-
UNICODE_WHITESPACE = [
|
211
|
-
(0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
|
212
|
-
0x0020, # White_Space # Zs SPACE
|
213
|
-
0x0085, # White_Space # Cc <control-0085>
|
214
|
-
0x00A0, # White_Space # Zs NO-BREAK SPACE
|
215
|
-
0x1680, # White_Space # Zs OGHAM SPACE MARK
|
216
|
-
0x180E, # White_Space # Zs MONGOLIAN VOWEL SEPARATOR
|
217
|
-
(0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
|
218
|
-
0x2028, # White_Space # Zl LINE SEPARATOR
|
219
|
-
0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
|
220
|
-
0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
|
221
|
-
0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
|
222
|
-
0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
|
223
|
-
].flatten.pack("U*").freeze
|
224
|
-
|
225
|
-
PROTECTED_SETTINGS = [ :raw_output ] #:nodoc:
|
226
|
-
|
227
|
-
def initialize(*args)
|
228
|
-
@_text = args[0].is_a?(String) ? args[0] : ''
|
229
|
-
setup_default_settings!
|
230
|
-
accept_configuration_arguments!(args.last) if args.last.is_a?(Hash)
|
231
|
-
end
|
232
|
-
|
233
|
-
# Настраивает форматтер ассоциированным хешем
|
234
|
-
# formatter.configure!(:dash=>true, :wordglue=>false)
|
235
|
-
def configure!(*config)
|
236
|
-
accept_configuration_arguments!(config.last) if config.last.is_a?(Hash)
|
237
|
-
end
|
238
|
-
|
239
|
-
alias :configure :configure! #Дружественный API
|
240
|
-
|
241
|
-
# Неизвестные методы - настройки. С = - установка ключа, без - получение значения
|
242
|
-
def method_missing(meth, *args) #:nodoc:
|
243
|
-
setting = meth.to_s.gsub(/=$/, '')
|
244
|
-
super(meth, *args) unless @settings.has_key?(setting) #this will pop the exception if we have no such setting
|
245
|
-
|
246
|
-
return (@settings[setting] = args[0])
|
247
|
-
end
|
248
|
-
|
249
|
-
# Обрабатывает text_to_process с сохранением настроек, присвоенных обьекту-форматтеру
|
250
|
-
# Дополнительные аргументы передаются как параметры форматтера и не сохраняются после прогона.
|
251
|
-
def process(text_to_process, *args)
|
252
|
-
@_text = text_to_process
|
253
|
-
|
254
|
-
args.last.is_a?(Hash) ? with_configuration(args.last) { to_html } : to_html
|
255
|
-
end
|
256
|
-
|
257
|
-
# Обрабатывает текст, присвоенный форматтеру при создании и возвращает результат обработки
|
258
|
-
def to_html
|
259
|
-
return '' unless @_text
|
260
|
-
|
261
|
-
# NOTE: strip is Unicode-space aware on 1.9.1, so here we simulate that
|
262
|
-
text = @_text.gsub(/[#{UNICODE_WHITESPACE}]\z/, '').gsub(/\A[#{UNICODE_WHITESPACE}]/, '')
|
263
|
-
|
264
|
-
# -6. Подмухляем таблицу глифов, если нам ее передали
|
265
|
-
glyph_table = glyph.dup
|
266
|
-
|
267
|
-
if @settings["enforce_ru_quotes"]
|
268
|
-
glyph_table[:ldquo], glyph_table[:rdquo] = glyph_table[:laquo], glyph_table[:raquo]
|
269
|
-
elsif @settings["enforce_en_quotes"]
|
270
|
-
glyph_table[:laquo], glyph_table[:raquo] = glyph_table[:ldquo], glyph_table[:rdquo]
|
271
|
-
end
|
272
|
-
|
273
|
-
# -5. Копируем глифы в ивары, к ним доступ быстр и в коде они глаза тоже не мозолят
|
274
|
-
glyph_table.each_pair do | ki, wi |
|
275
|
-
instance_variable_set("@#{ki}", wi)
|
276
|
-
end
|
277
|
-
|
278
|
-
# -4. запрет тагов html
|
279
|
-
process_escape_html(text) unless @settings["html"]
|
280
|
-
|
281
|
-
# -3. Никогда (вы слышите?!) не пущать лабуду &#not_correct_number;
|
282
|
-
FORBIDDEN_NUMERIC_ENTITIES.dup.each_pair do | key, rep |
|
283
|
-
text.gsub!(/&##{key};/, self.glyph[rep])
|
284
|
-
end
|
285
|
-
|
286
|
-
# -2. Чистим copy&paste
|
287
|
-
process_copy_paste_clearing(text) if @settings['copypaste']
|
288
|
-
|
289
|
-
# -1. Замена &entity_name; на входе (' ' => ' ' и т.д.)
|
290
|
-
process_html_entities(text)
|
291
|
-
|
292
|
-
# 0. Вырезаем таги
|
293
|
-
tags = lift_ignored_elements(text) if @skip_tags
|
294
|
-
|
295
|
-
# 1. Запятые и пробелы
|
296
|
-
process_spacing(text) if @settings["spacing"]
|
297
|
-
|
298
|
-
# 1. лапки
|
299
|
-
process_quotes(text) if @settings["quotes"]
|
300
|
-
|
301
|
-
# 2. ёлочки
|
302
|
-
process_laquo(text) if @settings["laquo"]
|
303
|
-
|
304
|
-
# 3. Инчи
|
305
|
-
process_inches(text) if @settings["inches"]
|
306
|
-
|
307
|
-
# 2b. одновременно ёлочки и лапки
|
308
|
-
process_compound_quotes(text) if (@settings["quotes"] && @settings["laquo"])
|
309
|
-
|
310
|
-
# 3. тире
|
311
|
-
process_dash(text) if @settings["dash"]
|
312
|
-
|
313
|
-
# 3a. тире длинное
|
314
|
-
process_emdash(text) if @settings["emdash"]
|
315
|
-
|
316
|
-
# 5. +/-
|
317
|
-
process_plusmin(text) if @settings["+-"]
|
318
|
-
|
319
|
-
# 5a. 12^C
|
320
|
-
process_degrees(text) if @settings["degrees"]
|
321
|
-
|
322
|
-
# 6. телефоны
|
323
|
-
process_phones(text) if @settings["phones"]
|
324
|
-
|
325
|
-
# 7. Короткие слова и
|
326
|
-
process_wordglue(text) if @settings["wordglue"]
|
327
|
-
|
328
|
-
# 8. Склейка ласт. Тьфу! дефисов.
|
329
|
-
process_dashglue(text) if @settings["dashglue"]
|
330
|
-
|
331
|
-
# 8a. Инициалы
|
332
|
-
process_initials(text) if @settings['initials']
|
333
|
-
|
334
|
-
# 8b. Троеточия
|
335
|
-
process_ellipsises(text) if @settings["wordglue"]
|
336
|
-
|
337
|
-
# 9. Акронимы от Текстиля
|
338
|
-
process_acronyms(text) if @settings["acronyms"]
|
339
|
-
|
340
|
-
# БЕСКОНЕЧНОСТЬ. Вставляем таги обратно.
|
341
|
-
reinsert_fragments(text, tags) if @skip_tags
|
342
|
-
|
343
|
-
# фуф, закончили.
|
344
|
-
process_span_instead_of_nobr(text) if @settings["de_nobr"]
|
345
|
-
|
346
|
-
# заменяем entities на истинные символы
|
347
|
-
process_raw_output(text) if @settings["raw_output"]
|
348
|
-
|
349
|
-
text.strip
|
350
|
-
end
|
351
|
-
|
352
|
-
|
353
|
-
# Применяет отдельный фильтр к text и возвращает результат. Например:
|
354
|
-
# formatter.apply(:wordglue, "Вот так") => "Вот так"
|
355
|
-
# Удобно применять когда вам нужно задействовать отдельный фильтр Гиленсона, но не нужна остальная механика
|
356
|
-
# Последний аргумент определяет, нужно ли при применении фильтра сохранить в неприкосновенности таги и другие
|
357
|
-
# игнорируемые фрагменты текста (по умолчанию они сохраняются).
|
358
|
-
def apply(filter, text, lift_ignored_elements = true)
|
359
|
-
copy = text.dup
|
360
|
-
unless lift_ignored_elements
|
361
|
-
self.send("process_#{filter}".to_sym, copy)
|
362
|
-
else
|
363
|
-
lifting_fragments(copy) { self.send("process_#{filter}".to_sym, copy) }
|
364
|
-
end
|
365
|
-
copy
|
366
|
-
end
|
367
|
-
|
368
|
-
private
|
369
|
-
|
370
|
-
def setup_default_settings!
|
371
|
-
@skip_tags = true;
|
372
|
-
@ignore = /notypo/ # regex, который игнорируется. Этим надо воспользоваться для обработки pre и code
|
373
|
-
|
374
|
-
@glueleft = ['рис.', 'табл.', 'см.', 'им.', 'ул.', 'пер.', 'кв.', 'офис', 'оф.', 'г.']
|
375
|
-
@glueright = ['руб.', 'коп.', 'у.е.', 'мин.']
|
376
|
-
|
377
|
-
# Установки можно менять в каждом экземпляре
|
378
|
-
@settings = SETTINGS.dup
|
379
|
-
|
380
|
-
@mark_tag = REPLACEMENT_MARKER
|
381
|
-
# Глифы можено подменять в экземпляре форматтера поэтому копируем их из константы
|
382
|
-
@glyph = GLYPHS.dup
|
383
|
-
|
384
|
-
@phonemasks = [[ /([0-9]{4})\-([0-9]{2})\-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/,
|
385
|
-
/([0-9]{4})\-([0-9]{2})\-([0-9]{2})/,
|
386
|
-
/(\([0-9\+\-]+\)) ?([0-9]{3})\-([0-9]{2})\-([0-9]{2})/,
|
387
|
-
/(\([0-9\+\-]+\)) ?([0-9]{2})\-([0-9]{2})\-([0-9]{2})/,
|
388
|
-
/(\([0-9\+\-]+\)) ?([0-9]{3})\-([0-9]{2})/,
|
389
|
-
/(\([0-9\+\-]+\)) ?([0-9]{2})\-([0-9]{3})/,
|
390
|
-
/([0-9]{3})\-([0-9]{2})\-([0-9]{2})/,
|
391
|
-
/([0-9]{2})\-([0-9]{2})\-([0-9]{2})/,
|
392
|
-
/([0-9]{1})\-([0-9]{2})\-([0-9]{2})/,
|
393
|
-
/([0-9]{2})\-([0-9]{3})/,
|
394
|
-
/([0-9]+)\-([0-9]+)/,
|
395
|
-
],[
|
396
|
-
':nob_open\1:ndash\2:ndash\3:nbsp\4:\5:\6:nob_close',
|
397
|
-
':nob_open\1:ndash\2:ndash\3:nob_close',
|
398
|
-
':nob_open\1:nbsp\2:ndash\3:ndash\4:nob_close',
|
399
|
-
':nob_open\1:nbsp\2:ndash\3:ndash\4:nob_close',
|
400
|
-
':nob_open\1:nbsp\2:ndash\3:nob_close',
|
401
|
-
':nob_open\1:nbsp\2:ndash\3:nob_close',
|
402
|
-
':nob_open\1:ndash\2:ndash\3:nob_close',
|
403
|
-
':nob_open\1:ndash\2:ndash\3:nob_close',
|
404
|
-
':nob_open\1:ndash\2:ndash\3:nob_close',
|
405
|
-
':nob_open\1:ndash\2:nob_close',
|
406
|
-
':nob_open\1:ndash\2:nob_close'
|
407
|
-
]]
|
408
|
-
end
|
409
|
-
|
410
|
-
# Позволяет получить процедуру, при вызове возвращающую значение глифа
|
411
|
-
# def lookup(glyph_to_lookup)
|
412
|
-
# return Proc.new { g[glyph_to_lookup] }
|
413
|
-
# end
|
414
|
-
|
415
|
-
# Подставляет "символы" (двоеточие + имя глифа) на нужное значение глифа заданное в данном форматтере
|
416
|
-
def substitute_glyphs_in_string(str)
|
417
|
-
re = str.dup
|
418
|
-
@glyph.each_pair do | key, subst |
|
419
|
-
re.gsub!(":#{key.to_s}", subst)
|
420
|
-
end
|
421
|
-
re
|
422
|
-
end
|
423
|
-
|
424
|
-
# Выполняет блок, временно включая настройки переданные в +hash+
|
425
|
-
def with_configuration(hash, &block)
|
426
|
-
old_settings, old_glyphs = @settings.dup, @glyph.dup
|
427
|
-
accept_configuration_arguments!(hash)
|
428
|
-
txt = yield
|
429
|
-
@settings, @glyph = old_settings, old_glyphs
|
430
|
-
|
431
|
-
return txt
|
432
|
-
end
|
433
|
-
|
434
|
-
def accept_configuration_arguments!(args_hash)
|
435
|
-
|
436
|
-
# Специальный случай - :all=>true|false
|
437
|
-
if args_hash.has_key?(:all)
|
438
|
-
if args_hash[:all]
|
439
|
-
@settings.each_pair {|k, v| @settings[k] = true unless PROTECTED_SETTINGS.include?(k.to_sym)}
|
440
|
-
else
|
441
|
-
@settings.each_pair {|k, v| @settings[k] = false unless PROTECTED_SETTINGS.include?(k.to_sym)}
|
442
|
-
end
|
443
|
-
else
|
444
|
-
|
445
|
-
# Кинуть ошибку если настройка нам неизвестна
|
446
|
-
unknown_settings = args_hash.keys.collect{|k|k.to_s} - @settings.keys.collect { |k| k.to_s }
|
447
|
-
raise RuTils::Gilenson::UnknownSetting, unknown_settings if unknown_settings.any?
|
448
|
-
|
449
|
-
args_hash.each_pair do | key, value |
|
450
|
-
@settings[key.to_s] = (value ? true : false)
|
451
|
-
end
|
452
|
-
end
|
453
|
-
end
|
454
|
-
|
455
|
-
# Вынимает игнорируемые фрагменты и заменяет их маркером, выполняет переданный блок и вставляет вынутое на место
|
456
|
-
def lifting_fragments(text, &block)
|
457
|
-
lifted = lift_ignored_elements(text)
|
458
|
-
yield
|
459
|
-
reinsert_fragments(text, lifted)
|
460
|
-
end
|
461
|
-
|
462
|
-
#Вынимает фрагменты из текста и возвращает массив с фрагментами
|
463
|
-
def lift_ignored_elements(text)
|
464
|
-
# re = /<\/?[a-z0-9]+("+ # имя тага
|
465
|
-
# "\s+("+ # повторяющая конструкция: хотя бы один разделитель и тельце
|
466
|
-
# "[a-z]+("+ # атрибут из букв, за которым может стоять знак равенства и потом
|
467
|
-
# "=((\'[^\']*\')|(\"[^\"]*\")|([0-9@\-_a-z:\/?&=\.]+))"+ #
|
468
|
-
# ")?"+
|
469
|
-
# ")?"+
|
470
|
-
# ")*\/?>|\xA2\xA2[^\n]*?==/i;
|
471
|
-
|
472
|
-
re_skipcode = '((<(code|tt)[ >](.*?)<\/(code|tt)>)|(<!\[CDATA\[(.*?)\]\]>))|' if @settings['skip_code']
|
473
|
-
re = /(#{re_skipcode}<\/?[a-z0-9]+(\s+([a-z]+(=((\'[^\']*\')|(\"[^\"]*\")|([0-9@\-_a-z:\/?&=\.]+)))?)?)*\/?>)/uim
|
474
|
-
tags = text.scan(re).map{ |tag| tag[0] } # первая группа!
|
475
|
-
text.gsub!(re, @mark_tag) #маркер тега, мы используем Invalid UTF-sequence для него
|
476
|
-
return tags
|
477
|
-
end
|
478
|
-
|
479
|
-
def reinsert_fragments(text, fragments)
|
480
|
-
fragments.each do |fragment|
|
481
|
-
fragment.gsub!(/ (href|src|data)=((?:(\')([^\']*)(\'))|(?:(\")([^\"]*)(\")))/uim) do
|
482
|
-
" #{$1}=" + $2.gsub(/&(?!(#0*38)|(amp);)/, @amp)
|
483
|
-
end # unless @settings['raw_output'] -- делать это надо всегда (mash)
|
484
|
-
|
485
|
-
unless @settings['skip_attr']
|
486
|
-
fragment.gsub!(/ (title|alt)=((?:(\')([^\']*)(\'))|(?:(\")([^\"]*)(\")))/uim) do
|
487
|
-
" #{$1}=#{$3}" + self.process($4.to_s) + "#{$5}#{$6}" + self.process($7.to_s) + "#{$8}"
|
488
|
-
end
|
489
|
-
end
|
490
|
-
text.sub!(@mark_tag, fragment)
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
### Имплементации фильтров
|
495
|
-
def process_html_entities(text)
|
496
|
-
self.glyph.each { |key, value| text.gsub!(/&#{key};/, value)}
|
497
|
-
end
|
498
|
-
|
499
|
-
def process_initials(text)
|
500
|
-
initials = /([А-Я])[\.]{1,2}[\s]*?([А-Я])[\.]*[\s]*?([А-Я])([а-я])/u
|
501
|
-
replacement = substitute_glyphs_in_string('\1.\2.:thinsp\3\4')
|
502
|
-
text.gsub!(initials, replacement)
|
503
|
-
end
|
504
|
-
|
505
|
-
def process_copy_paste_clearing(text)
|
506
|
-
VERBATIM_GLYPHS.each {|key,value| text.gsub!(/#{Regexp.escape(key)}/, glyph[value]) }
|
507
|
-
end
|
508
|
-
|
509
|
-
def process_spacing(text)
|
510
|
-
text.gsub!( /(\s*)([,]*)/sui, '\2\1');
|
511
|
-
text.gsub!( /(\s*)([\.?!]*)(\s*[ЁА-ЯA-Z])/su, '\2\1\3');
|
512
|
-
end
|
513
|
-
|
514
|
-
def process_dashglue(text)
|
515
|
-
text.gsub!( /([a-zа-яА-Я0-9]+(\-[a-zа-яА-Я0-9]+)+)/ui, @nob_open+'\1'+ @nob_close)
|
516
|
-
end
|
517
|
-
|
518
|
-
def process_escape_html(text)
|
519
|
-
text.gsub!(/&/, @amp)
|
520
|
-
text.gsub!(/</, @lt)
|
521
|
-
text.gsub!(/>/, @gt)
|
522
|
-
end
|
523
|
-
|
524
|
-
def process_span_instead_of_nobr(text)
|
525
|
-
text.gsub!(/<nobr>/, '<span class="nobr">')
|
526
|
-
text.gsub!(/<\/nobr>/, '</span>')
|
527
|
-
end
|
528
|
-
|
529
|
-
def process_dash(text)
|
530
|
-
text.gsub!( /(\s|;)\-(\s)/ui, '\1'+@ndash+'\2')
|
531
|
-
end
|
532
|
-
|
533
|
-
def process_emdash(text)
|
534
|
-
text.gsub!( /(\s|;)\-\-(\s)/ui, '\1'+@mdash+'\2')
|
535
|
-
# 4. (с)
|
536
|
-
text.gsub!(/\([сСcC]\)((?=\w)|(?=\s[0-9]+))/u, @copy) if @settings["(c)"]
|
537
|
-
# 4a. (r)
|
538
|
-
text.gsub!( /\(r\)/ui, '<sup>'+@reg+'</sup>') if @settings["(r)"]
|
539
|
-
|
540
|
-
# 4b. (tm)
|
541
|
-
text.gsub!( /\(tm\)|\(тм\)/ui, @trade) if @settings["(tm)"]
|
542
|
-
# 4c. (p)
|
543
|
-
text.gsub!( /\(p\)/ui, @sect) if @settings["(p)"]
|
544
|
-
end
|
545
|
-
|
546
|
-
def process_ellipsises(text)
|
547
|
-
text.gsub!( '...', @hellip)
|
548
|
-
end
|
549
|
-
|
550
|
-
def process_laquo(text)
|
551
|
-
text.gsub!( /\"\"/ui, @quot * 2);
|
552
|
-
text.gsub!( /(^|\s|#{@mark_tag}|>|\()\"((#{@mark_tag})*[~0-9ёЁA-Za-zА-Яа-я\-:\/\.])/ui, '\1' + @laquo + '\2');
|
553
|
-
_text = '""';
|
554
|
-
until _text == text do
|
555
|
-
_text = text;
|
556
|
-
text.gsub!( /(#{@laquo}([^\"]*)[ёЁA-Za-zА-Яа-я0-9\.\-:\/\?\!](#{@mark_tag})*)\"/sui, '\1' + @raquo)
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
def process_quotes(text)
|
561
|
-
text.gsub!( /\"\"/ui, @quot*2)
|
562
|
-
text.gsub!( /\"\.\"/ui, @quot+"."+@quot)
|
563
|
-
_text = '""';
|
564
|
-
lat_c = '0-9A-Za-z'
|
565
|
-
punct = /\'\!\s\.\?\,\-\&\;\:\\/
|
566
|
-
|
567
|
-
until _text == text do
|
568
|
-
_text = text.dup
|
569
|
-
text.gsub!( /(^|\s|#{@mark_tag}|>)\"([#{lat_c}#{punct}\_\#{@mark_tag}]+(\"|#{@rdquo}))/ui, '\1'+ @ldquo +'\2')
|
570
|
-
text.gsub!( /(#{@ldquo}([#{lat_c}#{punct}#{@mark_tag}\_]*).*[#{lat_c}][\#{@mark_tag}\?\.\!\,\\]*)\"/ui, '\1'+ @rdquo)
|
571
|
-
end
|
572
|
-
end
|
573
|
-
|
574
|
-
def process_compound_quotes(text)
|
575
|
-
text.gsub!(/(#{@ldquo}(([A-Za-z0-9'!\.?,\-&;:]|\s|#{@mark_tag})*)#{@laquo}(.*)#{@raquo})#{@raquo}/ui, '\1' + @rdquo);
|
576
|
-
end
|
577
|
-
|
578
|
-
def process_degrees(text)
|
579
|
-
text.gsub!( /-([0-9])+\^([FCС])/, @ndash+'\1'+ @deg +'\2') #deg
|
580
|
-
text.gsub!( /\+([0-9])+\^([FCС])/, '+\1'+ @deg +'\2')
|
581
|
-
text.gsub!( /\^([FCС])/, @deg+'\1')
|
582
|
-
end
|
583
|
-
|
584
|
-
def process_wordglue(text)
|
585
|
-
text.replace(" " + text + " ")
|
586
|
-
_text = " " + text + " "
|
587
|
-
|
588
|
-
until _text == text
|
589
|
-
_text = text
|
590
|
-
text.gsub!( /(\s+)([a-zа-яА-Я0-9]{1,2})(\s+)([^\\s$])/ui, '\1\2' + @nbsp +'\4')
|
591
|
-
text.gsub!( /(\s+)([a-zа-яА-Я0-9]{3})(\s+)([^\\s$])/ui, '\1\2' + @nbsp+'\4')
|
592
|
-
end
|
593
|
-
|
594
|
-
# Пунктуация это либо один из наших глифов, либо мемберы класса. В данном случае
|
595
|
-
# мы цепляемся за кончик строки поэтому можум прихватить и глиф тоже
|
596
|
-
# Пунктуация включает наши собственные глифы!
|
597
|
-
punct = glyph.values.map{|v| Regexp.escape(v)}.join('|')
|
598
|
-
vpunct = /(#{punct}|[\)\]\!\?,\.;])/
|
599
|
-
|
600
|
-
text.gsub!(/(\s+)([a-zа-яА-Я0-9]{1,2}#{vpunct}{0,3}\s$)/ui, @nbsp+'\2')
|
601
|
-
|
602
|
-
@glueleft.each { | i | text.gsub!( /(\s)(#{i})(\s+)/sui, '\1\2' + @nbsp) }
|
603
|
-
|
604
|
-
@glueright.each { | i | text.gsub!( /(\s)(#{i})(\s+)/sui, @nbsp+'\2\3') }
|
605
|
-
|
606
|
-
end
|
607
|
-
|
608
|
-
def process_phones(text)
|
609
|
-
@phonemasks[0].each_with_index do |pattern, i|
|
610
|
-
replacement = substitute_glyphs_in_string(@phonemasks[1][i])
|
611
|
-
text.gsub!(pattern, replacement)
|
612
|
-
end
|
613
|
-
end
|
614
|
-
|
615
|
-
def process_acronyms(text)
|
616
|
-
acronym = /\b([A-ZА-Я][A-ZА-Я0-9]{2,})\b(?:[(]([^)]*)[)])/u
|
617
|
-
if @settings["raw_output"]
|
618
|
-
text.gsub!(acronym, '\1%s(\2)' % @thinsp)
|
619
|
-
else
|
620
|
-
text.gsub!(acronym) do
|
621
|
-
expl = $2.to_s; process_escape_html(expl)
|
622
|
-
"<acronym title=\"#{expl}\">#{$1}</acronym>"
|
623
|
-
end
|
624
|
-
end
|
625
|
-
end
|
626
|
-
|
627
|
-
# Обработка знака дюйма, кроме случаев когда он внутри кавычек
|
628
|
-
def process_inches(text)
|
629
|
-
text.gsub!(/\s([0-9]{1,2}([\.,][0-9]{1,2})?)(\"){1,1}/ui, ' \1' + @inch)
|
630
|
-
end
|
631
|
-
|
632
|
-
def process_plusmin(text)
|
633
|
-
text.gsub!(/[^+]\+\-/ui, @plusmn)
|
634
|
-
end
|
635
|
-
|
636
|
-
# Подменяет все юникодные entities в тексте на истинные UTF-8-символы
|
637
|
-
def process_raw_output(text)
|
638
|
-
# Все глифы
|
639
|
-
@glyph.values.each do | entity |
|
640
|
-
next unless entity =~ /^&#(\d+);/
|
641
|
-
text.gsub!(/#{entity}/, entity_to_raw_utf8(entity))
|
642
|
-
end
|
643
|
-
end
|
644
|
-
|
645
|
-
# Конвертирует юникодные entities в UTF-8-codepoints
|
646
|
-
def entity_to_raw_utf8(entity)
|
647
|
-
entity =~ /^&#(\d+);/
|
648
|
-
$1 ? [$1.to_i].pack("U") : entity
|
649
|
-
end
|
650
|
-
|
651
|
-
end #end Gilenson
|
652
|
-
|
653
|
-
# Выбрасывается если форматтеру задается неизвестная настройка
|
654
|
-
class RuTils::Gilenson::UnknownSetting < RuntimeError
|
655
|
-
end
|
656
|
-
|
657
|
-
module RuTils::Gilenson::StringFormatting
|
658
|
-
# Форматирует строку с помощью Gilenson::Formatter. Все дополнительные опции передаются форматтеру.
|
659
|
-
def gilensize(*args)
|
660
|
-
RuTils::Gilenson::Formatter.new(self, args.shift || {}).to_html
|
661
|
-
end
|
662
|
-
|
663
|
-
end
|
664
|
-
|
665
|
-
Object::String.send(:include, RuTils::Gilenson::StringFormatting)
|