typogrowth 0.9.1 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/features/step_definitions/typogrowth_steps.rb +1 -1
- data/features/typogrowth.feature +8 -4
- data/lib/config/typogrowth.yaml +29 -17
- data/lib/typogrowth/string.rb +2 -2
- data/lib/typogrowth/version.rb +1 -1
- data/lib/typogrowth.rb +69 -48
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d96c37d2c10f0fc9f73caaeda6be11910a725c7d
|
4
|
+
data.tar.gz: abc183314746913a04adca10b88e380e75981a61
|
5
5
|
!binary "U0hBNTEy":
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9277400dec9a0f43219676988fdac4dfc6e1b257537a9bdf8ba2218abcdf35c473d223f9ed9a07c02b14838687ca9aee923bf380bf3f5047e50534809ef016b2
|
7
|
+
data.tar.gz: 5fd258973bb34862e20c77a0ec8a6b203bb5d60be67ee9736e3a5b90107b21d63625507b5dfd8bac2bb9c7acd9cc40d944c57895de06b533fa9caba2cdba613b
|
data/.travis.yml
CHANGED
@@ -11,7 +11,7 @@ end
|
|
11
11
|
|
12
12
|
When(/^input string is processed with Typogrowl’s typography parser with lang "(.*?)"$/) do |lang|
|
13
13
|
@content.gsub! /\\+"/, '"'
|
14
|
-
@typo = Typogrowth.parse @content, lang
|
14
|
+
@typo = Typogrowth.parse @content, lang: lang
|
15
15
|
end
|
16
16
|
|
17
17
|
When(/^input string is modified inplace with typo!$/) do
|
data/features/typogrowth.feature
CHANGED
@@ -30,8 +30,8 @@ Feature: Text is to be typographed (spacing and pubctuation are to be sanitized)
|
|
30
30
|
| input | output |
|
31
31
|
| "И Бог сказал: \"Я - слышу \"Бум\" и \"Бам\" где-то там\" , и стало светло." | "И Бог сказал: «Я — слышу „Бум“ и „Бам“ где-то там», и стало светло." |
|
32
32
|
| "И Бог сказал: \"Я - слышу \"Бум \"и\" Бам\" где-то там\" , и стало светло." | "И Бог сказал: «Я — слышу „Бум «и» Бам“ где-то там», и стало светло." |
|
33
|
-
| "Строка со ссылкой: http://wikipedia.org (ссылка)." | "Строка со ссылкой: http://wikipedia.org (ссылка)." |
|
34
|
-
|
33
|
+
| "Строка со ссылкой: http://wikipedia.org (ссылка)." | "Строка со ссылкой: http://wikipedia.org (ссылка)." |
|
34
|
+
|
35
35
|
Scenario Outline: Spacing before/after punctuation
|
36
36
|
Given the input string is <input>
|
37
37
|
When input string is processed with Typogrowl’s typography parser
|
@@ -47,12 +47,16 @@ Feature: Text is to be typographed (spacing and pubctuation are to be sanitized)
|
|
47
47
|
| "Here is http://wikipedia.org. See?." | "Here is http://wikipedia.org. See?." |
|
48
48
|
| "Here is exclamation ellipsis!.." | "Here is exclamation ellipsis!.." |
|
49
49
|
| "Here is exclamation ellipsis! . ." | "Here is exclamation ellipsis!.." |
|
50
|
+
| "Here we go ; semicolon .. ." | "Here we go; semicolon…" |
|
51
|
+
| "Here are ' english ' quotes . ." | "Here are ‘english’ quotes.." |
|
52
|
+
| "Here are " english " quotes . ." | "Here are “english” quotes.." |
|
53
|
+
| "Here we go : colon . ." | "Here we go: colon.." |
|
50
54
|
|
51
55
|
Scenario: Inplace string modification
|
52
56
|
Given the input string is "Foo 'Bar' Baz"
|
53
57
|
When input string is modified inplace with typo!
|
54
58
|
Then typoed result should equal to "Foo “Bar” Baz"
|
55
|
-
|
59
|
+
|
56
60
|
Scenario Outline: Orphans handling
|
57
61
|
Given the input string is <input>
|
58
62
|
When input string is processed with Typogrowl’s typography parser
|
@@ -62,4 +66,4 @@ Feature: Text is to be typographed (spacing and pubctuation are to be sanitized)
|
|
62
66
|
Examples:
|
63
67
|
| input | output |
|
64
68
|
| "This is a cat." | "This is a cat." |
|
65
|
-
|
69
|
+
|
data/lib/config/typogrowth.yaml
CHANGED
@@ -34,14 +34,14 @@
|
|
34
34
|
:apostrophe_pre :
|
35
35
|
:pattern : ''''
|
36
36
|
:re : '(?<=\p{Alpha})('')(?=\p{Alpha})'
|
37
|
-
:default :
|
37
|
+
:default :
|
38
38
|
- '♻'
|
39
39
|
# And God said 'Foos' game is over'.
|
40
40
|
# ⇑
|
41
41
|
:apostrophe_squeez :
|
42
42
|
:pattern : ''''
|
43
43
|
:re : '(?<=s)('')(?=\s)'
|
44
|
-
:default :
|
44
|
+
:default :
|
45
45
|
- '♻'
|
46
46
|
# And God said "∇×(∇×F) = ∇(∇·F) − ∇2F" and there was light.
|
47
47
|
# ⇑
|
@@ -87,6 +87,19 @@
|
|
87
87
|
:default :
|
88
88
|
- '’'
|
89
89
|
|
90
|
+
:quotes_single :
|
91
|
+
:re : '\s+''\s+(.+?)\s+''\s+'
|
92
|
+
:default :
|
93
|
+
- ' ‘\1’ '
|
94
|
+
:ru :
|
95
|
+
- ' «\1» '
|
96
|
+
:quotes_double :
|
97
|
+
:re : '\s+"\s+(.+?)\s+"\s+'
|
98
|
+
:default :
|
99
|
+
- ' “\1” '
|
100
|
+
:ru :
|
101
|
+
- ' «\1» '
|
102
|
+
|
90
103
|
:alone_single :
|
91
104
|
:re : '('')'
|
92
105
|
:alert: true
|
@@ -99,20 +112,6 @@
|
|
99
112
|
:default :
|
100
113
|
- '”'
|
101
114
|
|
102
|
-
:others :
|
103
|
-
:ellipsis :
|
104
|
-
:re : '\.{3,}'
|
105
|
-
:default :
|
106
|
-
- '…'
|
107
|
-
:mdash :
|
108
|
-
:re : '\s*(?<dash> - |--)\s*'
|
109
|
-
:default :
|
110
|
-
- '—'
|
111
|
-
:ru :
|
112
|
-
- ' — '
|
113
|
-
:us :
|
114
|
-
- ' – '
|
115
|
-
|
116
115
|
:punctuation :
|
117
116
|
:opening_orphan :
|
118
117
|
:re : '([(¿¡§#№]|\p{Sc})(?:\s+)'
|
@@ -130,7 +129,20 @@
|
|
130
129
|
:re : '([!?.]+)(?:\s*)(\.+)'
|
131
130
|
:default :
|
132
131
|
- '\1\2'
|
133
|
-
|
132
|
+
:ellipsis :
|
133
|
+
:re : '\.{3,}'
|
134
|
+
:default :
|
135
|
+
- '…'
|
136
|
+
:mdash :
|
137
|
+
:re : '\s*(?<dash> - |--|–|—)\s*'
|
138
|
+
:default :
|
139
|
+
- '—'
|
140
|
+
:ru :
|
141
|
+
- ' — '
|
142
|
+
:us :
|
143
|
+
- ' – '
|
144
|
+
|
145
|
+
# MUST be the last section, since it’ kinda cleanup
|
134
146
|
:orphans :
|
135
147
|
:dangling_right :
|
136
148
|
:re : '(?<=\s|\A)(\p{L})\s+'
|
data/lib/typogrowth/string.rb
CHANGED
@@ -7,11 +7,11 @@ class String
|
|
7
7
|
# Typographyes the string and returns a result
|
8
8
|
# See Typogrowth::Parser#parse
|
9
9
|
def typo lang = nil
|
10
|
-
Typogrowth::Parser.parse(self, lang ? lang : I18n.locale)
|
10
|
+
Typogrowth::Parser.parse(self, lang: lang ? lang : I18n.locale)
|
11
11
|
end
|
12
12
|
# Typographyes the string inplace
|
13
13
|
# See Typogrowth::Parser#parse!
|
14
14
|
def typo! lang = nil
|
15
|
-
Typogrowth::Parser.parse!(self, lang ? lang : I18n.locale)
|
15
|
+
Typogrowth::Parser.parse!(self, lang: lang ? lang : I18n.locale)
|
16
16
|
end
|
17
17
|
end
|
data/lib/typogrowth/version.rb
CHANGED
data/lib/typogrowth.rb
CHANGED
@@ -8,15 +8,15 @@ require_relative 'typogrowth/version'
|
|
8
8
|
require_relative 'typogrowth/string'
|
9
9
|
require_relative 'utils/hash_recursive_merge'
|
10
10
|
|
11
|
-
#
|
12
|
-
# = String typographing with language support.
|
13
|
-
#
|
14
|
-
# Parses and corrects the typography in strings. It supports
|
11
|
+
#
|
12
|
+
# = String typographing with language support.
|
13
|
+
#
|
14
|
+
# Parses and corrects the typography in strings. It supports
|
15
15
|
# different language rules and user rules customization.
|
16
|
-
#
|
16
|
+
#
|
17
17
|
# The package also monkeypatches `String` class with both
|
18
18
|
# `typo` and `typo!` methods.
|
19
|
-
#
|
19
|
+
#
|
20
20
|
# Category:: Ruby
|
21
21
|
# Author:: Alexei Matyushkin <am@mudasobwa.ru>
|
22
22
|
# Copyright:: 2013 The Authors
|
@@ -27,58 +27,69 @@ require_relative 'utils/hash_recursive_merge'
|
|
27
27
|
module Typogrowth
|
28
28
|
# Internal exception class just to make the exception distinction possible
|
29
29
|
class MalformedRulesFile < Exception ; end
|
30
|
-
|
31
|
-
# Parses and corrects the typography in strings. It supports
|
30
|
+
|
31
|
+
# Parses and corrects the typography in strings. It supports
|
32
32
|
# different language rules and easy user rules customization.
|
33
33
|
class Parser
|
34
|
-
attr_reader :yaml
|
35
|
-
|
34
|
+
attr_reader :yaml, :shadows
|
35
|
+
|
36
|
+
def self.safe_delimiters str
|
37
|
+
delimiters = ['❮', '❯']
|
38
|
+
loop do
|
39
|
+
break delimiters unless str.match(/#{delimiters.join('|')}/)
|
40
|
+
delimiters.map! {|d| d*2}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
36
44
|
#
|
37
45
|
# Recursively merges the initial settings with custom.
|
38
|
-
#
|
46
|
+
#
|
39
47
|
# To supply your own rules to processing:
|
40
|
-
#
|
41
|
-
# - create a +hash+ of additional rules in the same form as in the
|
48
|
+
#
|
49
|
+
# - create a +hash+ of additional rules in the same form as in the
|
42
50
|
# standard `typogrowth.yaml` file shipped with a project
|
43
51
|
# - merge the hash with the standard one using this function
|
44
|
-
#
|
52
|
+
#
|
45
53
|
# For instance, to add french rules one is to merge in the following yaml:
|
46
|
-
#
|
54
|
+
#
|
47
55
|
# :quotes :
|
48
56
|
# :punctuation :
|
49
57
|
# :fr : "\\k<quote>\\k<punct>"
|
50
58
|
# …
|
51
59
|
#
|
52
|
-
def
|
53
|
-
|
60
|
+
def merge custom
|
61
|
+
yaml.rmerge!(custom)
|
54
62
|
end
|
55
|
-
|
63
|
+
|
56
64
|
#
|
57
65
|
# Inplace version of string typographying.
|
58
|
-
#
|
66
|
+
#
|
59
67
|
# Retrieves the string and changes all the typewriters quotes (doubles
|
60
68
|
# and sigles), to inches, minutes, seconds, proper quotation signs.
|
61
|
-
#
|
62
|
-
# While the input strings are e.g.
|
63
|
-
#
|
69
|
+
#
|
70
|
+
# While the input strings are e.g.
|
71
|
+
#
|
64
72
|
# And God said "Baz heard "Bar" once" , and there was light.
|
65
73
|
# That's a 6.3" man, he sees sunsets at 10°20'30" E.
|
66
|
-
#
|
74
|
+
#
|
67
75
|
# It will produce:
|
68
|
-
#
|
76
|
+
#
|
69
77
|
# And God said “Baz heard ‘Bar’ once,” and there was light.
|
70
78
|
# That’s a 6.3″ man, he sees sunsets at 10°20′30″ E.
|
71
|
-
#
|
79
|
+
#
|
72
80
|
# The utility also handles dashes as well.
|
73
|
-
#
|
81
|
+
#
|
74
82
|
# @param str [String] the string to be typographyed inplace
|
75
83
|
# @param lang the language to use rules for
|
76
84
|
#
|
77
|
-
def
|
85
|
+
def parse str, lang: :default, shadows: []
|
78
86
|
lang = lang.to_sym
|
87
|
+
delims = Parser.safe_delimiters str
|
79
88
|
str.split(/\R{2,}/).map { |para|
|
80
|
-
|
81
|
-
|
89
|
+
@shadows.concat([*shadows]).uniq.each { |re|
|
90
|
+
para.gsub!(re) { |m| "#{delims.first}#{Base64.encode64 m}#{delims.last}" }
|
91
|
+
}
|
92
|
+
@yaml.each { |key, values|
|
82
93
|
values.each { |k, v|
|
83
94
|
if !!v[:re]
|
84
95
|
v[lang] = v[:default] if (!v[lang] || v[lang].size.zero?)
|
@@ -93,14 +104,14 @@ module Typogrowth
|
|
93
104
|
para.gsub!(/#{v[lang].first}/) { |m|
|
94
105
|
prev = $`
|
95
106
|
obsoletes = prev.count(v[lang].join)
|
96
|
-
compliants = values[v[:compliant].to_sym][lang] ||
|
107
|
+
compliants = values[v[:compliant].to_sym][lang] ||
|
97
108
|
values[v[:compliant].to_sym][:default]
|
98
109
|
obsoletes -= prev.count(compliants.join) \
|
99
110
|
if !!v[:compliant]
|
100
111
|
!!v[:slave] ?
|
101
112
|
obsoletes -= prev.count(v[:original]) + 1 :
|
102
113
|
obsoletes += prev.count(v[:original])
|
103
|
-
|
114
|
+
|
104
115
|
v[lang][obsoletes % v[lang].size]
|
105
116
|
}
|
106
117
|
end
|
@@ -111,35 +122,45 @@ module Typogrowth
|
|
111
122
|
}.join(%Q(
|
112
123
|
|
113
124
|
))
|
114
|
-
.gsub(
|
125
|
+
.gsub(/#{delims.first}(.*)#{delims.last}/m) { |m| Base64.decode64 m }
|
126
|
+
end
|
127
|
+
|
128
|
+
def add_shadows re
|
129
|
+
@shadows.concat [*re]
|
130
|
+
end
|
131
|
+
|
132
|
+
def del_shadows re
|
133
|
+
@shadows.delete_if { |stored| [*re].include? stored }
|
134
|
+
end
|
135
|
+
|
136
|
+
# Out-of-place version of `String` typographing. See #parse!
|
137
|
+
def self.parse str, lang: :default, shadows: []
|
138
|
+
Parser.new.parse str, lang: lang, shadows: shadows
|
115
139
|
end
|
116
140
|
|
117
141
|
# Out-of-place version of `String` typographing. See #parse!
|
118
|
-
def self.parse! str, lang
|
119
|
-
str.replace self.parse
|
142
|
+
def self.parse! str, lang: :default, shadows: []
|
143
|
+
str.replace self.parse str, lang: lang, shadows: shadows
|
120
144
|
end
|
121
|
-
|
145
|
+
|
122
146
|
DEFAULT_SET = 'typogrowth'
|
123
|
-
|
124
|
-
|
147
|
+
HTML_TAG_RE = /<[A-Za-z]+(.*?)>/
|
148
|
+
|
149
|
+
def initialize file = nil
|
150
|
+
file = DEFAULT_SET unless file
|
125
151
|
@yaml = YAML.load_file "#{File.dirname(__FILE__)}/config/#{file}.yaml"
|
126
152
|
@yaml.delete(:placeholder)
|
153
|
+
@shadows = [URI.regexp, HTML_TAG_RE]
|
127
154
|
end
|
128
155
|
|
129
|
-
@@instance = Parser.new(DEFAULT_SET)
|
130
|
-
|
131
|
-
def self.instance
|
132
|
-
@@instance
|
133
|
-
end
|
134
|
-
|
135
|
-
private_class_method :new
|
136
156
|
end
|
137
157
|
|
138
|
-
def self.parse str, lang
|
139
|
-
Parser.parse str, lang
|
158
|
+
def self.parse str, lang: :default, shadows: []
|
159
|
+
Parser.parse str, lang: lang, shadows: shadows
|
140
160
|
end
|
141
|
-
|
142
|
-
|
161
|
+
|
162
|
+
def self.parse! str, lang: :default, shadows: []
|
163
|
+
Parser.parse! str, lang: lang, shadows: shadows
|
143
164
|
end
|
144
165
|
end
|
145
166
|
|