typogrowth 0.9.1 → 0.9.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.
- 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
|
|