clausewitz-spelling 0.1.19 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile.lock +6 -6
- data/clausewitz-spelling.gemspec +2 -2
- data/en_GB_owb.dic +81 -0
- data/exe/clausewitz-spellcheck +22 -3
- data/lib/clausewitz/localisation.rb +3 -3
- data/lib/clausewitz/spelling/checker.rb +53 -108
- data/lib/clausewitz/spelling/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c3f825db29cf16aa71180113fdba663b417a44cab29a2cd9d4c2a447c3061ae3
|
4
|
+
data.tar.gz: ae39cd480cffe2f0a3ff6cb673c00c53d0d86def3136b274806dc9cacadff860
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1880d26258c57c61d8ba8a1b9b3177e998657cef265411a09c9f5fb95616e370386e3286112e468af581ea8cda235cd4483e95e8c525303598d9377dff363e0
|
7
|
+
data.tar.gz: afcd28a0b5f6250b5d4d2f6ec90b443feda4017be1543fb2466f485b261c1b256cd2b6875c26fac95e23d5c571e4a000b95d2738501b78be78c88ee2649ea301
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
clausewitz-spelling (0.
|
4
|
+
clausewitz-spelling (0.2.0)
|
5
5
|
colorize
|
6
6
|
damerau-levenshtein
|
7
|
-
ffi-
|
7
|
+
ffi-hunspell-wtchappell
|
8
8
|
optimist
|
9
9
|
pragmatic_tokenizer
|
10
10
|
|
@@ -16,8 +16,8 @@ GEM
|
|
16
16
|
damerau-levenshtein (1.3.1)
|
17
17
|
diff-lcs (1.3)
|
18
18
|
ffi (1.10.0)
|
19
|
-
ffi-
|
20
|
-
ffi
|
19
|
+
ffi-hunspell-wtchappell (0.4.0)
|
20
|
+
ffi (~> 1.0)
|
21
21
|
method_source (0.9.2)
|
22
22
|
optimist (3.0.0)
|
23
23
|
pragmatic_tokenizer (3.0.7)
|
@@ -45,11 +45,11 @@ PLATFORMS
|
|
45
45
|
ruby
|
46
46
|
|
47
47
|
DEPENDENCIES
|
48
|
-
bundler (~> 1.
|
48
|
+
bundler (~> 1.17.2)
|
49
49
|
clausewitz-spelling!
|
50
50
|
pry
|
51
51
|
rake (~> 10.0)
|
52
52
|
rspec (~> 3.0)
|
53
53
|
|
54
54
|
BUNDLED WITH
|
55
|
-
1.
|
55
|
+
1.17.2
|
data/clausewitz-spelling.gemspec
CHANGED
@@ -20,12 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler", "~> 1.
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.17.2"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
25
|
spec.add_development_dependency "rspec", "~> 3.0"
|
26
26
|
spec.add_development_dependency "pry"
|
27
27
|
|
28
|
-
spec.add_dependency "ffi-
|
28
|
+
spec.add_dependency "ffi-hunspell-wtchappell"
|
29
29
|
spec.add_dependency "optimist"
|
30
30
|
spec.add_dependency "colorize"
|
31
31
|
spec.add_dependency "damerau-levenshtein"
|
data/en_GB_owb.dic
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
35
|
2
|
+
Adytum/1
|
3
|
+
Almirante/1
|
4
|
+
APC/2 1
|
5
|
+
Allgood/1
|
6
|
+
Aradesh/1
|
7
|
+
Bearport/1
|
8
|
+
Boneyard/1
|
9
|
+
Chico/1
|
10
|
+
Ciudad/1
|
11
|
+
Colibrí/1
|
12
|
+
Darkwater/1
|
13
|
+
Dayglow/1
|
14
|
+
Elijah/1
|
15
|
+
Elijah's
|
16
|
+
FEV/1
|
17
|
+
GAI/1
|
18
|
+
Gizmo/1
|
19
|
+
Harbor/1
|
20
|
+
Hardin/2 1
|
21
|
+
Hardin's
|
22
|
+
Harlon/1
|
23
|
+
Héctor/1
|
24
|
+
Henderton/1
|
25
|
+
Hubology
|
26
|
+
Hubologist/2 1
|
27
|
+
Junktown/1
|
28
|
+
Klamath/1
|
29
|
+
Los
|
30
|
+
Maxson/1
|
31
|
+
Morbid/1
|
32
|
+
Mossman/1
|
33
|
+
NCR/1
|
34
|
+
Paz/1
|
35
|
+
Pesca/1
|
36
|
+
Peterson/1
|
37
|
+
Petro/1
|
38
|
+
Rafael/1
|
39
|
+
Rattletail/1
|
40
|
+
Reynosa/1
|
41
|
+
RobCo/1
|
42
|
+
Santángel/1
|
43
|
+
Seabear/1
|
44
|
+
Shi/1
|
45
|
+
Silus/1
|
46
|
+
Tamaulipas/1
|
47
|
+
Tampico/1
|
48
|
+
Tandi/1
|
49
|
+
Tech
|
50
|
+
Tlaloc/1
|
51
|
+
TODO/1
|
52
|
+
West-Tek/1
|
53
|
+
Valles/1
|
54
|
+
Vandenberg/1
|
55
|
+
Vault-Tec/1
|
56
|
+
bandito/2 1
|
57
|
+
brahmin/5 1
|
58
|
+
caudillo/2 1
|
59
|
+
commonfolk/5 1
|
60
|
+
deathclaw/2 1
|
61
|
+
doodad/2 1
|
62
|
+
eyebot/2
|
63
|
+
firefight/2 1
|
64
|
+
firepower/5 1
|
65
|
+
hardline/2 1
|
66
|
+
lakebed/2 1
|
67
|
+
malcontents
|
68
|
+
military's
|
69
|
+
playbook/2 1
|
70
|
+
protectron/2 1
|
71
|
+
radscorpion/2 1
|
72
|
+
robobrain/2 1
|
73
|
+
securitron/2 1
|
74
|
+
shopfront/2 1
|
75
|
+
superweapon/2 1
|
76
|
+
tribals/5 1
|
77
|
+
underway
|
78
|
+
unpowered
|
79
|
+
vertibird/2 1
|
80
|
+
weaponsmith/2 1
|
81
|
+
wildcard/2 1
|
data/exe/clausewitz-spellcheck
CHANGED
@@ -9,8 +9,11 @@ class Main
|
|
9
9
|
|
10
10
|
def parse_args(args)
|
11
11
|
opts = Optimist::options(args) do
|
12
|
-
opt :
|
13
|
-
"
|
12
|
+
opt :custom_dicts,
|
13
|
+
"List of custom dictionaries to load",
|
14
|
+
type: :strings
|
15
|
+
opt :custom_dict_root,
|
16
|
+
"Directory containing per-language-dialect custom dicts",
|
14
17
|
type: :string
|
15
18
|
opt :suggestion_count,
|
16
19
|
"How many suggestions to display",
|
@@ -21,7 +24,23 @@ class Main
|
|
21
24
|
type: :string
|
22
25
|
end
|
23
26
|
end
|
24
|
-
|
27
|
+
|
28
|
+
dialect_map = {}
|
29
|
+
dialect_opts = opts.keys.select { |k| k =~ /.+_dialect/ }
|
30
|
+
dialect_opts.each do |dialect_opt_key|
|
31
|
+
next unless opts[dialect_opt_key]
|
32
|
+
next if dialect_opt_key.to_s.end_with?('given')
|
33
|
+
language_name = dialect_opt_key[/(.+)_dialect/, 1]
|
34
|
+
dialect_map[language_name] = opts[dialect_opt_key]
|
35
|
+
end
|
36
|
+
|
37
|
+
checker_opts = {}
|
38
|
+
checker_opts[:custom_dict_root] = opts[:custom_dict_root]
|
39
|
+
checker_opts[:custom_dicts] = opts[:custom_dicts]
|
40
|
+
checker_opts[:dialect_map] = dialect_map
|
41
|
+
checker_opts[:suggestion_count] = opts[:suggestion_count]
|
42
|
+
|
43
|
+
[checker_opts, args]
|
25
44
|
end
|
26
45
|
|
27
46
|
def run
|
@@ -17,7 +17,7 @@ module Clausewitz
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def select_dialect(dialect)
|
20
|
-
if @dialects.include?(dialect)
|
20
|
+
if @dialects.include?(dialect.downcase)
|
21
21
|
@selected_dialect = dialect
|
22
22
|
else
|
23
23
|
fail("Unknown dialect override '#{dialect}'!")
|
@@ -48,11 +48,11 @@ module Clausewitz
|
|
48
48
|
),
|
49
49
|
'l_spanish' => LangConfig.new(
|
50
50
|
'spanish',
|
51
|
-
'es', []
|
51
|
+
'es', %w[mx es], 'es'
|
52
52
|
),
|
53
53
|
'l_russian' => LangConfig.new(
|
54
54
|
'russian',
|
55
|
-
'ru', []
|
55
|
+
'ru', %w[ru], 'ru'
|
56
56
|
)
|
57
57
|
}
|
58
58
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'ffi/
|
1
|
+
require 'ffi/hunspell'
|
2
2
|
require 'open3'
|
3
3
|
require 'pathname'
|
4
4
|
require 'set'
|
@@ -11,27 +11,39 @@ require 'clausewitz/spelling/results'
|
|
11
11
|
|
12
12
|
module Clausewitz; module Spelling
|
13
13
|
class Checker
|
14
|
-
|
14
|
+
DEFAULT_SUGGESTION_COUNT = 3
|
15
|
+
|
15
16
|
def initialize(opts = {})
|
16
|
-
@
|
17
|
-
@
|
17
|
+
@custom_dict_root = opts[:custom_dict_root]
|
18
|
+
@custom_dict_root = Pathname.new(@custom_dict_root) if @custom_dict_root
|
19
|
+
@custom_dicts = opts[:custom_dicts] || []
|
20
|
+
@dialect_map = opts[:dialect_map] || {}
|
21
|
+
@suggestion_count = opts[:suggestion_count] || DEFAULT_SUGGESTION_COUNT
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
end
|
23
|
+
load_dictionaries!
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
def load_dictionaries!
|
27
|
+
@loaded_dicts = {}
|
28
|
+
Localisation::LANG_MAP.each do |_, config|
|
29
|
+
if @dialect_map.key?(config.name)
|
30
|
+
config.select_dialect(@dialect_map[config.name])
|
31
|
+
end
|
32
|
+
|
33
|
+
dict = FFI::Hunspell.dict(config.full_name)
|
34
|
+
|
35
|
+
@custom_dicts.each do |custom_dict|
|
36
|
+
path = @custom_dict_root.join("#{config.full_name}_#{custom_dict}")
|
37
|
+
path = Pathname.new("#{path}.dic")
|
38
|
+
if path.exist?
|
39
|
+
dict.add_dic(path.to_s)
|
40
|
+
else
|
41
|
+
$stderr.puts("Could not load dictionary '#{path}', skipping...")
|
42
|
+
end
|
43
|
+
end
|
32
44
|
|
33
|
-
|
34
|
-
|
45
|
+
@loaded_dicts[config.name] = dict
|
46
|
+
end
|
35
47
|
end
|
36
48
|
|
37
49
|
def check_file(filepath)
|
@@ -43,7 +55,7 @@ module Clausewitz; module Spelling
|
|
43
55
|
return InvalidFilepathResult.new(filepath, e)
|
44
56
|
end
|
45
57
|
|
46
|
-
$stderr.puts "Skipping #{filepath}..." if filepath.directory?
|
58
|
+
$stderr.puts "Skipping directory '#{filepath}'..." if filepath.directory?
|
47
59
|
|
48
60
|
begin
|
49
61
|
contents = Clausewitz::Localisation.parse_file(filepath)
|
@@ -53,16 +65,14 @@ module Clausewitz; module Spelling
|
|
53
65
|
|
54
66
|
checks = contents.map do |lang_name, entries|
|
55
67
|
lc = language_config(lang_name)
|
56
|
-
check_entries(
|
68
|
+
check_entries(entries, lc)
|
57
69
|
end
|
58
70
|
FileResults.new(filepath, checks)
|
59
71
|
end
|
60
72
|
|
61
73
|
private
|
62
74
|
|
63
|
-
def check_entries(
|
64
|
-
wordlist = load_wordlist(lc)
|
65
|
-
aspell_checker = load_aspell_checker(lc)
|
75
|
+
def check_entries(entries, lc)
|
66
76
|
spellcheck_ignore = entries&.delete('spellcheck_ignore')
|
67
77
|
ignored_keys = spellcheck_ignore ? spellcheck_ignore.split(',') : []
|
68
78
|
ignored_keys << 'spellcheck_ignore'
|
@@ -74,13 +84,13 @@ module Clausewitz; module Spelling
|
|
74
84
|
if ignored_keys.include?(key)
|
75
85
|
IgnoredEntryResult.new(key)
|
76
86
|
else
|
77
|
-
check_entry(
|
87
|
+
check_entry(key, entry, lc)
|
78
88
|
end
|
79
89
|
end
|
80
90
|
LangResults.new(lc.clausewitz_name, checks)
|
81
91
|
end
|
82
92
|
|
83
|
-
def check_entry(
|
93
|
+
def check_entry(key, entry, lc)
|
84
94
|
# We don't want to pay attention to scripted localisation, so we'll strip
|
85
95
|
# it out before we start.
|
86
96
|
# TODO: Look into supporting escaped square brackets as part of the
|
@@ -123,13 +133,19 @@ module Clausewitz; module Spelling
|
|
123
133
|
}
|
124
134
|
words = PragmaticTokenizer::Tokenizer.new(opts).tokenize(entry)
|
125
135
|
words = words.map { |word| word.split('—') }.flatten(1)
|
136
|
+
words.map! do |word|
|
137
|
+
if word =~ /[[:alpha:]]\.$/ && word.chars.count('.') == 1
|
138
|
+
word.sub(/\.$/, '')
|
139
|
+
else
|
140
|
+
word
|
141
|
+
end
|
142
|
+
end
|
126
143
|
|
127
|
-
|
128
|
-
checks = words.map { |word| check_word(checker, wordlist, word) }.compact
|
144
|
+
checks = words.map { |word| check_word(word, lc) }.compact
|
129
145
|
EntryResults.new(key, checks)
|
130
146
|
end
|
131
147
|
|
132
|
-
def check_word(
|
148
|
+
def check_word(word, lc)
|
133
149
|
return if is_number?(word)
|
134
150
|
return if is_plural_number?(word)
|
135
151
|
return if is_ordinal?(word)
|
@@ -137,10 +153,11 @@ module Clausewitz; module Spelling
|
|
137
153
|
return if is_icon?(word)
|
138
154
|
return if is_initial?(word)
|
139
155
|
return if is_psalm?(word)
|
140
|
-
return if wordlist.include?(word)
|
141
156
|
|
142
|
-
|
143
|
-
|
157
|
+
lang_dict = @loaded_dicts[lc.name]
|
158
|
+
if !lang_dict.check?(word)
|
159
|
+
suggestions = lang_dict.suggest(word).take(@suggestion_count)
|
160
|
+
MisspelledWordResult.new(word, suggestions)
|
144
161
|
end
|
145
162
|
end
|
146
163
|
|
@@ -156,26 +173,6 @@ module Clausewitz; module Spelling
|
|
156
173
|
word =~ /^[A-Z]\.$/
|
157
174
|
end
|
158
175
|
|
159
|
-
def suggest_words(checker, wordlist, word)
|
160
|
-
return [] if word.size < 3
|
161
|
-
|
162
|
-
suggestions = Set.new
|
163
|
-
|
164
|
-
aspell_suggestions = checker.suggestions(word)
|
165
|
-
|
166
|
-
custom_suggestions = wordlist.select do |dict_word|
|
167
|
-
min = [word.size, dict_word.size].min
|
168
|
-
DamerauLevenshtein.distance(word, dict_word) < min
|
169
|
-
end
|
170
|
-
|
171
|
-
aspell_suggestions.each { |sug| suggestions.add(sug) }
|
172
|
-
custom_suggestions.each { |sug| suggestions.add(sug) }
|
173
|
-
|
174
|
-
suggestions.to_a.sort_by do |sug|
|
175
|
-
DamerauLevenshtein.distance(sug, word)
|
176
|
-
end.first(@suggestion_count)
|
177
|
-
end
|
178
|
-
|
179
176
|
def is_icon?(word)
|
180
177
|
word =~ /^£\w+/
|
181
178
|
end
|
@@ -193,71 +190,19 @@ module Clausewitz; module Spelling
|
|
193
190
|
word =~ /%(-|\+)?[0-9]+(\.[0-9]+)?/
|
194
191
|
end
|
195
192
|
|
196
|
-
# Loads our custom wordlist into a temporary Aspell dictionary.
|
197
|
-
# This way Aspell won't yell at us for custom words and will also
|
198
|
-
# potentially select from this list as suggestions for misspelled words.
|
199
|
-
def load_custom_dictionary(lc)
|
200
|
-
dir = Dir.mktmpdir("custom-wordlist-#{lc.full_name}-")
|
201
|
-
output = File.join(dir, "#{lc.full_name}-custom.wlst")
|
202
|
-
cmd = %W[
|
203
|
-
aspell --lang=#{lc.base} --encoding=UTF-8 create master #{output}
|
204
|
-
]
|
205
|
-
value = nil
|
206
|
-
Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|
|
207
|
-
dict_path = File.join(@dictionary_root, lc.full_name, 'dict.txt')
|
208
|
-
contents = File.read(dict_path)
|
209
|
-
words = contents.lines.map(&:chomp)
|
210
|
-
words.each do |word|
|
211
|
-
stdin.puts(word)
|
212
|
-
end
|
213
|
-
stdin.close
|
214
|
-
value = wait_thr.value
|
215
|
-
end
|
216
|
-
unless value.success?
|
217
|
-
fail("Could not generate custom word list for #{lc.full_name}!")
|
218
|
-
end
|
219
|
-
output
|
220
|
-
end
|
221
|
-
|
222
|
-
def load_aspell_checker(lc)
|
223
|
-
if @loaded_spellcheckers[lc.full_name]
|
224
|
-
return @loaded_spellcheckers[lc.full_name]
|
225
|
-
end
|
226
|
-
aspell_checker = FFI::Aspell::Speller.new(
|
227
|
-
lc.full_name, encoding: 'UTF-8'
|
228
|
-
)
|
229
|
-
aspell_checker.set('ignore-accents', true)
|
230
|
-
if @dictionary_root && @dictionary_root.join(lc.full_name).exist?
|
231
|
-
custom_words = load_custom_dictionary(lc)
|
232
|
-
aspell_checker.set('extra-dicts', custom_words)
|
233
|
-
end
|
234
|
-
@loaded_spellcheckers[lc.full_name] = aspell_checker
|
235
|
-
end
|
236
|
-
|
237
|
-
def load_wordlist(lc)
|
238
|
-
return @loaded_wordlists[lc.full_name] if @loaded_wordlists[lc.full_name]
|
239
|
-
contents = ''
|
240
|
-
dict_path = @dictionary_root.join(lc.full_name, 'dict.txt')
|
241
|
-
if @dictionary_root && dict_path.exist?
|
242
|
-
contents = File.read(@dictionary_root.join(lc.full_name, 'dict.txt'))
|
243
|
-
end
|
244
|
-
words = contents.lines.to_a.map(&:chomp)
|
245
|
-
@loaded_wordlists[lc.full_name] = Set.new(words)
|
246
|
-
end
|
247
|
-
|
248
193
|
def language_config(language_name)
|
249
194
|
language_name = "l_#{language_name}" if language_name !~ /^l_/
|
250
|
-
|
195
|
+
lang_config = Localisation::LANG_MAP.find do |config_key, _|
|
251
196
|
language_name == config_key
|
252
197
|
end
|
253
|
-
fail("Unknown language '#{language_name}'!") unless
|
254
|
-
|
198
|
+
fail("Unknown language '#{language_name}'!") unless lang_config
|
199
|
+
lang_config.last
|
255
200
|
end
|
256
201
|
|
257
202
|
# Make sure a file to be checked is actually present and readable.
|
258
203
|
def validate_filepath!(filepath)
|
259
|
-
fail("No such file #{filepath}!") unless filepath.exist?
|
260
|
-
fail("Cannot read #{filepath}!") unless filepath.readable?
|
204
|
+
fail("No such file '#{filepath}'!") unless filepath.exist?
|
205
|
+
fail("Cannot read '#{filepath}'!") unless filepath.readable?
|
261
206
|
end
|
262
207
|
end
|
263
208
|
end; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clausewitz-spelling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Chappell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.17.2
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.17.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name: ffi-
|
70
|
+
name: ffi-hunspell-wtchappell
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- bin/console
|
158
158
|
- bin/setup
|
159
159
|
- clausewitz-spelling.gemspec
|
160
|
+
- en_GB_owb.dic
|
160
161
|
- exe/clausewitz-spellcheck
|
161
162
|
- lib/clausewitz/localisation.rb
|
162
163
|
- lib/clausewitz/spelling.rb
|
@@ -182,8 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
183
|
- !ruby/object:Gem::Version
|
183
184
|
version: '0'
|
184
185
|
requirements: []
|
185
|
-
|
186
|
-
rubygems_version: 2.5.2.1
|
186
|
+
rubygems_version: 3.0.1
|
187
187
|
signing_key:
|
188
188
|
specification_version: 4
|
189
189
|
summary: Spellchecker tool for Clausewitz engine files
|