standalone_typograf 2.0.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/README.md +108 -72
- data/Rakefile +1 -9
- data/doc/fonts.md +1 -4
- data/doc/logo.png +0 -0
- data/doc/logo.psd +0 -0
- data/lib/standalone_typograf/dashes.rb +23 -0
- data/lib/standalone_typograf/ellipsis.rb +23 -0
- data/lib/standalone_typograf/fractions.rb +12 -28
- data/lib/standalone_typograf/mnemonics.rb +33 -0
- data/lib/standalone_typograf/nbspaces.rb +36 -0
- data/lib/standalone_typograf/quotes.rb +109 -77
- data/lib/standalone_typograf/version.rb +1 -1
- data/lib/standalone_typograf.rb +86 -42
- data/spec/processors/dashes_spec.rb +31 -0
- data/spec/processors/ellipsis_spec.rb +28 -0
- data/spec/processors/fractions_spec.rb +18 -0
- data/spec/processors/mnemonics_spec.rb +34 -0
- data/spec/processors/nbspaces_spec.rb +31 -0
- data/spec/processors/quotes_spec.rb +32 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/standalone_typograf_spec.rb +12 -0
- data/spec/typograf_spec.rb +57 -0
- data/standalone_typograf.gemspec +6 -3
- metadata +76 -45
- data/.DS_Store +0 -0
- data/.rvmrc +0 -1
- data/lib/standalone_typograf/dasherize.rb +0 -12
- data/lib/standalone_typograf/dots.rb +0 -9
- data/lib/standalone_typograf/endash.rb +0 -9
- data/lib/standalone_typograf/nbspace.rb +0 -42
- data/lib/standalone_typograf/signs.rb +0 -26
- data/test/test_dash.rb +0 -24
- data/test/test_dots.rb +0 -24
- data/test/test_endash.rb +0 -12
- data/test/test_fractions.rb +0 -25
- data/test/test_nbspace.rb +0 -33
- data/test/test_prepare.rb +0 -34
- data/test/test_quotes.rb +0 -32
- data/test/test_signs.rb +0 -36
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b43853037131f6e6f5688014e63d55263bc1a0f2
|
4
|
+
data.tar.gz: 76b0f8cbc97462ed5added4a66c100ac3297db08
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 90f4013887443a5732e44fce7ee5b967833997f8598064ccfbb058b27b595c2d448dcd645b4a6de4b7e29ed7446dc0b8b8e92c4429807287d146d814731945bb
|
7
|
+
data.tar.gz: 2cd5fd4359a50620cf154a6dc1fbf2465993c62569e866e95093c83dddb0ea5bd89c51b5bfa953b4011e1126f3e2105711ff762d6be370c6ae2df105cefeffe9
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,97 +1,135 @@
|
|
1
|
-
|
1
|
+
# StandaloneTypograf
|
2
2
|
|
3
|
-
|
3
|
+
[![Travis CI ](https://api.travis-ci.org/shlima/standalone_typograf.png) ](https://travis-ci.org/shlima/standalone_typograf)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/shlima/standalone_typograf.png) ](https://codeclimate.com/github/shlima/standalone_typograf)
|
5
|
+
[![Gemnasium ](https://gemnasium.com/shlima/standalone_typograf.png) ](https://gemnasium.com/shlima/standalone_typograf)
|
4
6
|
|
5
|
-
|
7
|
+
|
8
|
+
![StandaloneTypograf](https://raw.github.com/shlima/standalone_typograf/master/doc/logo.png)
|
9
|
+
|
10
|
+
StandaloneTypograf — gem для подготовки текста к публикации или типографирования текста на лету (вывод комментариев, например)
|
11
|
+
|
12
|
+
> Пушкин писал Дельвигу: "Жду "Цыганов" и тотчас тисну...", (c) 1827 - А. С. Пушкин
|
6
13
|
|
7
14
|
Превратится в:
|
8
|
-
|
9
|
-
|
10
|
-
|
15
|
+
|
16
|
+
> Пушкин писал Дельвигу: «Жду „Цыганов“ и тотчас тисну…», © 1827 — А. С. Пушкин
|
17
|
+
|
11
18
|
Пример работы (онлайн типограф): http://typograf.herokuapp.com
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- подстановка длинного тире (с использованием неразрывного пробела);
|
21
|
-
- привязка одно- и двухбуквенных слов к следующему за ними слову с помощью неразрывного пробела;
|
22
|
-
- привязка частиц (>=3) к предыдущему слову с помощью неразрывного пробела;
|
23
|
-
- замена всех 19 цельных символов дробей европейского вида, поддерживаемых стандартом Юникод.
|
24
|
-
|
25
|
-
## Отличия **StandaloneTypograf**
|
26
|
-
|
27
|
-
- автономность (самостоятельная обработка текста не зависящая от сторонних сайтов и сервисов);
|
28
|
-
- выполняет прямую функцию (не преобразует в html, работает с plain текстом, UTF-8 символы (© вместо ©);
|
29
|
-
- корректная обработка двойных кавычек (в отличие от gilenson);
|
30
|
-
- высокая скорость;
|
31
|
-
|
19
|
+
|
20
|
+
### Отличия StandaloneTypograf
|
21
|
+
Отличия от типографа Лебедева и ruby библиотеки Gilenson
|
22
|
+
|
23
|
+
* автономность (самостоятельная/standalone обработка текста не зависящая от сторонних сервисов);
|
24
|
+
* выполняет прямую функцию (не преобразует в html, работает с plain текстом);
|
25
|
+
* корректная обработка вложенных кавычек (в отличие от gilenson);
|
26
|
+
|
32
27
|
## Использование
|
33
28
|
|
34
|
-
|
29
|
+
Создайте экземпляр типографа и передайте ему текст как единственный обязательный аргумент:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
@text = %Q( "Я "читал" стихи Быкова,- сказал он." (c) )
|
33
|
+
typograph = StandaloneTypograph::Typograph.new(@text)
|
34
|
+
typograph.prepare #=> «Я „читал“ стихи Быкова,— сказал он.» ©
|
35
|
+
```
|
36
|
+
|
37
|
+
По умолчанию типограф работает в режиме `utf`, если вам необходма подстановка html-кодов, передайте переметр `mode` со значением `html`
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
typograph = StandaloneTypograph::Typograph.new(@text, mode: :html)
|
41
|
+
typograph.prepare #=> «Я „читал“ стихи Быкова,— сказал он.» ©
|
42
|
+
```
|
43
|
+
|
44
|
+
Метод `prepare` вызывает все возможные обработчики текста. Вы можете вызвать только некоторые, передав массив с названием необходимых _процессоров_, в метод `processor`
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
typograph = StandaloneTypograph::Typograph.new(@text)
|
48
|
+
typograph.processor(:dashes, :mnemonics)
|
49
|
+
```
|
50
|
+
|
51
|
+
Вы так же можете использовать метод `prepare` исключив ненужные обработчики. Для этого необходимо передать массив с названием ненужных _процессоров_ с параметром `exclude` при инициализации типографа:
|
35
52
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
text.signs # Заменит знаки (с) => ©
|
41
|
-
text.quotes # Преобразует кавычки
|
42
|
-
|
43
|
-
# Эти три метода можно заменить одной командой: prepare
|
44
|
-
text.prepare # => «StandaloneTypograf» — простой и быстрый, его можно использовать «на лету»
|
45
|
-
|
46
|
-
## Параметры
|
47
|
-
### Вызов определенных обработчиков
|
53
|
+
```ruby
|
54
|
+
typograph = StandaloneTypograph::Typograph.new(@text, exclude: :fractions)
|
55
|
+
typograph.prepare # бедут выполнены все преобразования кроме замены дробей
|
56
|
+
```
|
48
57
|
|
49
|
-
Вы можете вызвать только нужные вам типографы или использовать все одной командой *prepare*. Список поддерживаемых типографов:
|
50
58
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
59
|
+
## Обработчики
|
60
|
+
### Кавычки
|
61
|
+
Значение | Тип | Замена Utf | Замена Html
|
62
|
+
--- | --- | --- | ---
|
63
|
+
" | Внешняя, открывающая | « | \«
|
64
|
+
" | Внешняя, закрывающая | » | \»
|
65
|
+
" | Внутренняя, открывающая | „ | \„
|
66
|
+
" | Внутренняя, закрывающая | “ | \“
|
58
67
|
|
59
|
-
|
68
|
+
```ruby
|
69
|
+
StandaloneTypograf::Typograf.new(text).processor(:quotes)
|
70
|
+
```
|
60
71
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
### Переопределение или добавление знаков
|
72
|
+
### Длинное тире
|
73
|
+
Значение | Замена Utf | Замена Html
|
74
|
+
--- | --- | ---
|
75
|
+
- | — | \—
|
67
76
|
|
68
|
-
|
77
|
+
```ruby
|
78
|
+
StandaloneTypograf::Typograf.new(text).processor(:dashes)
|
79
|
+
```
|
69
80
|
|
70
|
-
|
71
|
-
|
81
|
+
### Неразрывные пробелы
|
82
|
+
Значение | Замена Utf | Замена Html
|
83
|
+
--- | --- | ---
|
84
|
+
- | | \
|
72
85
|
|
73
|
-
|
86
|
+
Неразрывные пробелы используются при отбивке длинного тире, одно-двухбуквенных слов и некоторых частиц.
|
74
87
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
text.quotes # => "«Мерседес»'
|
88
|
+
```ruby
|
89
|
+
StandaloneTypograf::Typograf.new(text).processor(:nbspaces)
|
90
|
+
```
|
79
91
|
|
80
|
-
|
92
|
+
### Мнемоники
|
93
|
+
Значение | Замена Utf | Замена Html
|
94
|
+
--- | --- | ---
|
95
|
+
(c) | © | \©
|
96
|
+
(tm) | ™ | \™
|
97
|
+
(r) | ® | \®
|
98
|
+
+- | ± | \±
|
99
|
+
-> | → | \→
|
100
|
+
<- | ← | \←
|
101
|
+
~= | ≈ | \≈
|
81
102
|
|
82
|
-
|
103
|
+
```ruby
|
104
|
+
StandaloneTypograf::Typograf.new(text).processor(:mnemonics)
|
105
|
+
```
|
83
106
|
|
84
|
-
|
107
|
+
### Дроби
|
108
|
+
Значение | Замена Utf | Замена Html | Html код
|
109
|
+
--- | --- | --- | ---
|
110
|
+
1/1 | none | <sup>1</sup>⁄<sub>1</sub> | `<sup>1</sup>⁄<sub>1</sub>`
|
111
|
+
1234124/454325 | none | <sup>1234124</sup>⁄<sub>454325</sub> | `<sup>1234124</sup>⁄<sub>454325</sub>`
|
85
112
|
|
86
|
-
|
113
|
+
Типограф производит замену дробей только в режиме **html**, при этом он генерирует html код используя теги верхнего и нижнего индексов, вследствие чего, количество заменяемых дробей бесконечно.
|
87
114
|
|
88
|
-
|
115
|
+
```ruby
|
116
|
+
StandaloneTypograf::Typograf.new(text).processor(:fractions)
|
117
|
+
```
|
89
118
|
|
90
|
-
|
119
|
+
Чтобы отключить замену дробей используйте параметр `exclude` при инициализации
|
91
120
|
|
92
|
-
|
121
|
+
```ruby
|
122
|
+
StandaloneTypograf::Typograf.new(text, :exclude => :fractions)
|
123
|
+
```
|
93
124
|
|
94
|
-
|
125
|
+
### Многоточие
|
126
|
+
Значение | Замена Utf | Замена Html
|
127
|
+
--- | --- | ---
|
128
|
+
... | … | \…
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
StandaloneTypograf::Typograf.new(text).processor(:ellipsis)
|
132
|
+
```
|
95
133
|
|
96
134
|
## Contributing
|
97
135
|
|
@@ -100,5 +138,3 @@ Or install it yourself as:
|
|
100
138
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
101
139
|
4. Push to the branch (`git push origin my-new-feature`)
|
102
140
|
5. Create new Pull Request
|
103
|
-
|
104
|
-
|
data/Rakefile
CHANGED
data/doc/fonts.md
CHANGED
data/doc/logo.png
CHANGED
Binary file
|
data/doc/logo.psd
CHANGED
Binary file
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module StandaloneTypograf #:nodoc:
|
4
|
+
module Dashes
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
CHAR = {
|
8
|
+
:html => '—',
|
9
|
+
:utf => '—',
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
included do
|
13
|
+
register_processor(Processor)
|
14
|
+
end
|
15
|
+
|
16
|
+
module Processor
|
17
|
+
def self.compile(text, mode)
|
18
|
+
text.gsub!(/-(\s)/, CHAR[mode]+'\1')
|
19
|
+
return text
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module StandaloneTypograf #:nodoc:
|
4
|
+
module Ellipsis
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
CHAR = {
|
8
|
+
:html => '…',
|
9
|
+
:utf => '…',
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
included do
|
13
|
+
register_processor(Processor)
|
14
|
+
end
|
15
|
+
|
16
|
+
module Processor
|
17
|
+
def self.compile(text, mode)
|
18
|
+
text.gsub!(/([[:alpha:]])([.][.][.])(\s|$)/, '\1'+CHAR[mode]+'\3')
|
19
|
+
return text
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,35 +1,19 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
module StandaloneTypograf
|
3
|
+
module StandaloneTypograf #:nodoc:
|
4
4
|
module Fractions
|
5
|
-
|
6
|
-
'1/4' => '¼',
|
7
|
-
'1/2' => '½',
|
8
|
-
'3/4' => '¾',
|
9
|
-
'1/7' => '⅐',
|
10
|
-
'1/9' => '⅑',
|
11
|
-
'1/10' => '⅒',
|
12
|
-
'1/3' => '⅓',
|
13
|
-
'2/3' => '⅔',
|
14
|
-
'1/5' => '⅕',
|
15
|
-
'2/5' => '⅖',
|
16
|
-
'3/5' => '⅗',
|
17
|
-
'4/5' => '⅘',
|
18
|
-
'1/6' => '⅙',
|
19
|
-
'5/6' => '⅚',
|
20
|
-
'1/8' => '⅛',
|
21
|
-
'3/8' => '⅜',
|
22
|
-
'5/8' => '⅝',
|
23
|
-
'7/8' => '⅞',
|
24
|
-
'0/3' => '↉'
|
25
|
-
}
|
5
|
+
extend ActiveSupport::Concern
|
26
6
|
|
27
|
-
|
28
|
-
|
29
|
-
#@text = @text.gsub(/#{text}/i, sign)
|
30
|
-
@text = @text.gsub(/(\D|\A)([#{text[0]}][\/][#{text[2]}])(\D|\z)/i, '\1' + sign + '\3')
|
31
|
-
end
|
32
|
-
@text
|
7
|
+
included do
|
8
|
+
register_processor(Processor)
|
33
9
|
end
|
10
|
+
|
11
|
+
module Processor
|
12
|
+
def self.compile(text, mode)
|
13
|
+
return text unless mode == :html
|
14
|
+
text.gsub!(/(\s|^)(\d+)(\/)(\d+)(?:\s|$)/, '\1<sup>\2</sup>⁄<sub>\4</sub>')
|
15
|
+
return text
|
16
|
+
end
|
34
17
|
end
|
18
|
+
end
|
35
19
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module StandaloneTypograf #:nodoc:
|
4
|
+
module Mnemonics
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
# Contains regexps.
|
8
|
+
# May contain signs in several languages separated by regexp's OR
|
9
|
+
# e.g. eng|рус
|
10
|
+
TEMPLATES = {
|
11
|
+
'\([c|с]\)' => { html: '©', utf: '©' },
|
12
|
+
'\((tm|тм)\)' => { html: '™', utf: '™' },
|
13
|
+
'\([r|р]\)' => { html: '®', utf: '®' },
|
14
|
+
'(\+\-)' => { html: '±', utf: '±' },
|
15
|
+
'(\-\>)' => { html: '→', utf: '→' },
|
16
|
+
'(\<\-)' => { html: '←', utf: '←' },
|
17
|
+
'(\~\=)' => { html: '≈', utf: '≈' },
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
included do
|
21
|
+
register_processor(Processor)
|
22
|
+
end
|
23
|
+
|
24
|
+
module Processor
|
25
|
+
def self.compile(text, mode)
|
26
|
+
TEMPLATES.each_pair do |regexp, data|
|
27
|
+
text.gsub!(/#{regexp}/i, data[mode])
|
28
|
+
end
|
29
|
+
return text
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module StandaloneTypograf #:nodoc:
|
4
|
+
module Nbspaces
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
CHAR = {
|
8
|
+
:html => ' ',
|
9
|
+
:utf => ' ',
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
PARTICLES = %w(
|
13
|
+
разве неужели едва вряд вроде якобы мол дескать даже ведь таки лишь
|
14
|
+
почти только исключительно вон вот именно точь-в-точь приблизительно прямо
|
15
|
+
)
|
16
|
+
|
17
|
+
included do
|
18
|
+
register_processor(Processor)
|
19
|
+
end
|
20
|
+
|
21
|
+
module Processor
|
22
|
+
def self.compile(text, mode)
|
23
|
+
# One or three letter word - nbspace to the right
|
24
|
+
text.gsub!(/(\s|^)([[:alpha:]]{1,2})(\s)/i, '\1\2'+CHAR[mode])
|
25
|
+
|
26
|
+
# nbspace to the right
|
27
|
+
text.gsub!(/(#{PARTICLES.join('|')})(\s)/i, '\1'+CHAR[mode])
|
28
|
+
|
29
|
+
# dash - nbspace to the left
|
30
|
+
text.gsub!(/(\s)(-|#{Dashes::CHAR[:html]}|#{Dashes::CHAR[:utf]})/i, CHAR[mode]+'\2')
|
31
|
+
|
32
|
+
return text
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,94 +1,126 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
module StandaloneTypograf
|
3
|
+
module StandaloneTypograf #:nodoc:
|
4
4
|
module Quotes
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
Q = '"' # source quote
|
8
|
+
|
9
|
+
CHARS = {
|
10
|
+
:outer_left => {html: '«', utf: '«'},
|
11
|
+
:outer_right => {html: '»', utf: '»'},
|
12
|
+
:inner_left => {html: '„', utf: '„'},
|
13
|
+
:inner_right => {html: '“', utf: '“'},
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
included do
|
17
|
+
register_processor(Processor)
|
18
|
+
end
|
9
19
|
|
10
|
-
|
11
|
-
|
20
|
+
# global locks
|
21
|
+
LOCK = {
|
22
|
+
inside: false, # inside outer quotes
|
23
|
+
outer_open: false, # outer quote opens but not still closed
|
24
|
+
inner_open: false, # inner quote opens but not still closed
|
12
25
|
}
|
13
26
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
type_tree.each do |e|
|
22
|
-
# ОТКРЫВАЮЩИЕ
|
23
|
-
if e[1] == :open
|
24
|
-
arr_text[e[0]] = (e[2] == :inner) ? @quotes[:inner][0] : @quotes[:outer][0]
|
25
|
-
else
|
26
|
-
# ЗАКРЫВАЮЩИЕ
|
27
|
-
arr_text[e[0]] = (e[2] == :inner) ? @quotes[:inner][1] : @quotes[:outer][1]
|
28
|
-
end
|
27
|
+
class Processor
|
28
|
+
attr_reader :text, :mode, :tarr
|
29
|
+
|
30
|
+
def self.compile(text, mode)
|
31
|
+
compiler = self.new(text, mode)
|
32
|
+
compiler.compile
|
33
|
+
text = compiler.tarr.join()
|
29
34
|
end
|
30
|
-
@text = arr_text.join
|
31
|
-
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
arr_text.each_with_index do |char, index|
|
45
|
-
_next_, _prev_ = index + 1, index - 1
|
46
|
-
# Если кавычка - первый символ в строке или за кавычкой примыкает буква,
|
47
|
-
# то эта кавычка - открывающая.
|
48
|
-
if char == SOURCE[:double]
|
49
|
-
if index == 0 || (arr_text[_next_] != ' ' and arr_text[_prev_] == ' ')
|
50
|
-
quotes_tree << [index, :open]
|
51
|
-
# Ситуация с двойными кавычками идущими сразу за одинарными, например:
|
52
|
-
# "Привет, "Медвед"".
|
53
|
-
elsif arr_text[_prev_] == SOURCE[:double] and (arr_text[_next_] != ' ' and index + 1 != total)
|
54
|
-
quotes_tree << [index, :open]
|
55
|
-
else
|
56
|
-
quotes_tree << [index, :close]
|
57
|
-
end
|
58
|
-
end
|
36
|
+
def initialize(text, mode)
|
37
|
+
@text = text
|
38
|
+
@mode = mode
|
39
|
+
# `tarr` means <b>text array</b>
|
40
|
+
# this is because replaced item may contain more than 1 char (like `«`)
|
41
|
+
# so replaced value will be placed into the one array cell.
|
42
|
+
@tarr = text.split(//)
|
43
|
+
end
|
44
|
+
|
45
|
+
def lock
|
46
|
+
@lock ||= LOCK.deep_dup
|
59
47
|
end
|
60
|
-
quotes_tree
|
61
|
-
end
|
62
48
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
type_tree[i] << :inner
|
49
|
+
def compile
|
50
|
+
tarr.each_with_index do |symbol, index|
|
51
|
+
next unless symbol == Q
|
52
|
+
|
53
|
+
# == Outer
|
54
|
+
if outside? && open_quote?(index)
|
55
|
+
tarr[index] = CHARS[:outer_left][mode]
|
56
|
+
outer_open_lock!
|
57
|
+
next
|
58
|
+
end
|
59
|
+
if inside? && !lock[:inner_open] && close_quote?(index)
|
60
|
+
tarr[index] = CHARS[:outer_right][mode]
|
61
|
+
outer_open_unlock!
|
62
|
+
next
|
78
63
|
end
|
79
|
-
end
|
80
64
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
65
|
+
# == Inner
|
66
|
+
if inside? && !lock[:inner_open] && open_quote?(index)
|
67
|
+
tarr[index] = CHARS[:inner_left][mode]
|
68
|
+
inner_open_lock!
|
69
|
+
next
|
70
|
+
end
|
71
|
+
if inside? && lock[:inner_open] && close_quote?(index)
|
72
|
+
tarr[index] = CHARS[:inner_right][mode]
|
73
|
+
inner_open_unlock!
|
74
|
+
next
|
88
75
|
end
|
89
76
|
end
|
90
|
-
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# @return [Boolean]
|
82
|
+
# If this quote is open
|
83
|
+
def open_quote?(index)
|
84
|
+
return true if index == 0
|
85
|
+
(text[index-1] =~ /\s|^/) && (text[index+1] =~ /[[:alpha:]]/)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [Boolean]
|
89
|
+
# If this quote is close
|
90
|
+
def close_quote?(index)
|
91
|
+
return true if index == (@tarr.length-1)
|
92
|
+
(text[index-1] =~ /[[:alpha:]]|[?!."]/) && (text[index+1] =~ /\s|[,.;!?#{Q}]/)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [Boolean]
|
96
|
+
# If we outside of outer quotes
|
97
|
+
def outside?
|
98
|
+
!lock[:outer_open] && !lock[:inside]
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Boolean]
|
102
|
+
# If we inside of outer quotes
|
103
|
+
def inside?
|
104
|
+
!outside?
|
105
|
+
end
|
106
|
+
|
107
|
+
def outer_open_lock!
|
108
|
+
lock[:inside] = true
|
109
|
+
lock[:outer_open] = true
|
110
|
+
end
|
111
|
+
|
112
|
+
def outer_open_unlock!
|
113
|
+
lock[:inside] = false
|
114
|
+
lock[:outer_open] = false
|
115
|
+
end
|
116
|
+
|
117
|
+
def inner_open_lock!
|
118
|
+
lock[:inner_open] = true
|
119
|
+
end
|
120
|
+
|
121
|
+
def inner_open_unlock!
|
122
|
+
lock[:inner_open] = false
|
91
123
|
end
|
92
124
|
end
|
93
125
|
end
|
94
|
-
end
|
126
|
+
end
|