forspell 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/clone_repos.sh +1 -1
- data/exe/create_dictionary +14 -16
- data/exe/generate_logs +5 -2
- data/lib/forspell/cli.rb +9 -4
- data/lib/forspell/file_list.rb +8 -4
- data/lib/forspell/loaders/markdown.rb +3 -1
- data/lib/forspell/loaders/ruby.rb +13 -3
- data/lib/forspell/reporter.rb +33 -8
- data/lib/forspell/ruby.dict +384 -7
- data/lib/forspell/runner.rb +6 -1
- data/lib/forspell/sanitizer.rb +3 -9
- data/lib/forspell/speller.rb +14 -4
- data/lib/forspell/word_matcher.rb +4 -6
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67422b4f2942f8a061b0551a4fa837c0c0c93140
|
4
|
+
data.tar.gz: b56c34d10ecd2bee9dbfa14757ec7853d8a6fe17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e2512ac8231b29ac095fdf2d71b426a82ba9365c6ae4d9cbf52f349f76b12bf7cdfe170b2001b4f0fe7b3fc4239175f59d8cec7f9742880c30d7a0bc8c88cff
|
7
|
+
data.tar.gz: 432eb94fcf818aba269b8292988956ba905964426e239ae35a9c3972813d6d1b7c19d9a1da2e4146d3f649bfbe13902359ba49fe532458e330e04c6cc4ad89b7
|
data/exe/clone_repos.sh
CHANGED
@@ -43,7 +43,7 @@ array=( "https://github.com/rspec/rspec-core.git"
|
|
43
43
|
"https://github.com/paper-trail-gem/paper_trail.git"
|
44
44
|
"https://github.com/aasm/aasm.git"
|
45
45
|
"https://github.com/rubysherpas/paranoia.git"
|
46
|
-
""
|
46
|
+
"https://github.com/rubocop-hq/rubocop.git"
|
47
47
|
""
|
48
48
|
""
|
49
49
|
""
|
data/exe/create_dictionary
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'yaml'
|
3
|
-
require 'pry'
|
4
3
|
require 'csv'
|
4
|
+
require 'pry'
|
5
5
|
|
6
6
|
class DictionaryCreator
|
7
7
|
attr_reader :result
|
8
8
|
|
9
|
-
def initialize(path: '
|
9
|
+
def initialize(path: 'test/popular_gems/')
|
10
10
|
@path = path
|
11
11
|
@data = {}
|
12
12
|
@result = {}
|
@@ -14,21 +14,20 @@ class DictionaryCreator
|
|
14
14
|
|
15
15
|
def process
|
16
16
|
(Dir.entries(@path) - ['.', '..']).each do |filename|
|
17
|
-
|
18
|
-
@data[filename] = YAML.load_file("#{@path}#{filename}")
|
17
|
+
@data[filename] = File.read("#{@path}#{filename}")
|
19
18
|
end
|
20
19
|
|
21
20
|
@data.each_pair do |log_filename, data|
|
22
21
|
next if data == false
|
23
22
|
|
24
23
|
gem_name = log_filename.split('.').first
|
25
|
-
data.each do |
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
data.split(/\n/).each do |error_with_count|
|
25
|
+
error, count = error_with_count.split(' # ')
|
26
|
+
count = count.to_i
|
27
|
+
if @result[error]
|
28
|
+
@result[error] = @result[error].merge(count: @result.dig(error, :count) + count, gems: (@result.dig(error, :gems) + [gem_name]).uniq)
|
29
|
+
else
|
30
|
+
@result[error] = { count: count, gems: [gem_name] }
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
@@ -37,11 +36,10 @@ class DictionaryCreator
|
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
CSV.open('../ruby_dict.csv', 'wb') do |csv|
|
39
|
+
CSV.open('ruby_dict_sort.csv', 'wb') do |csv|
|
43
40
|
csv << ['word', 'count', 'gems', 'should_include?']
|
44
|
-
DictionaryCreator.new.process.result
|
45
|
-
|
41
|
+
res = DictionaryCreator.new.process.result
|
42
|
+
res.keys.sort.each do |word|
|
43
|
+
csv << [word, res[word][:count], res[word][:gems].join(', '), nil]
|
46
44
|
end
|
47
45
|
end
|
data/exe/generate_logs
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
#!/bin/bash
|
2
2
|
cd ~/forspell
|
3
|
-
rm ./test/popular_gems
|
3
|
+
rm ./test/popular_gems/*.dict
|
4
4
|
|
5
5
|
for var in $(ls ../gem_src/)
|
6
6
|
do
|
7
|
-
|
7
|
+
cd ~/gem_src/$var
|
8
|
+
rm forspell.dict
|
9
|
+
~/forspell/exe/forspell --gen-dictionary .
|
10
|
+
cp forspell.dict ~/forspell/test/popular_gems/$var.forspell.dict
|
8
11
|
done
|
data/lib/forspell/cli.rb
CHANGED
@@ -20,9 +20,12 @@ module Forspell
|
|
20
20
|
o.string '-d', '--dictionary-path', 'Path to main hunspell dictionary to use (by default, forspell\'s en_US)', default: 'en_US'
|
21
21
|
o.array '-c', '--custom-paths', 'Paths to custom dictionaries', default: []
|
22
22
|
o.string '-f', '--format', 'Output formats: readable(default), JSON, YAML', default: 'readable'
|
23
|
-
o.
|
23
|
+
o.bool '--gen-dictionary', 'Generate custom dictionary', default: false
|
24
|
+
o.bool '--print-filepaths', 'Enable file paths in dictionary mode', default: false
|
24
25
|
o.string '-l', '--logfile', 'Log to specified path'
|
25
|
-
o.bool '-v', '--verbose', 'Verbose mode'
|
26
|
+
o.bool '-v', '--verbose', 'Verbose mode', default: false
|
27
|
+
o.bool '--no-suggest', 'Output without suggestions', default: false
|
28
|
+
o.integer '--suggestions-size', 'How many suggestions for each error should be returned', default: 3
|
26
29
|
o.on '--help' do
|
27
30
|
puts o
|
28
31
|
exit
|
@@ -71,12 +74,14 @@ module Forspell
|
|
71
74
|
end
|
72
75
|
|
73
76
|
@opts[:custom_paths] << DEFAULT_CUSTOM_DICT if File.exist?(DEFAULT_CUSTOM_DICT)
|
77
|
+
suggestions_size = (@opts[:gen_dictionary] || @opts[:no_suggest]) ? 0 : @opts[:suggestions_size]
|
78
|
+
suggestions_size ||= 0
|
74
79
|
|
75
|
-
@speller = Speller.new(@opts[:dictionary_path], *@opts[:custom_paths])
|
80
|
+
@speller = Speller.new(@opts[:dictionary_path], *@opts[:custom_paths], suggestions_size: suggestions_size)
|
76
81
|
end
|
77
82
|
|
78
83
|
def init_reporter
|
79
|
-
@reporter = Reporter.new(**@opts.to_hash.slice(:logfile, :format, :verbose))
|
84
|
+
@reporter = Reporter.new(**@opts.to_hash.slice(:logfile, :format, :verbose, :print_filepaths))
|
80
85
|
end
|
81
86
|
|
82
87
|
def run
|
data/lib/forspell/file_list.rb
CHANGED
@@ -16,17 +16,21 @@ module Forspell
|
|
16
16
|
def initialize(paths:, exclude_paths:)
|
17
17
|
@paths = paths
|
18
18
|
@exclude_paths = exclude_paths
|
19
|
-
end
|
20
19
|
|
21
|
-
def each(&block)
|
22
20
|
to_process = @paths.flat_map(&method(:expand_paths))
|
23
|
-
|
24
21
|
to_exclude = @exclude_paths.flat_map(&method(:expand_paths))
|
22
|
+
@files = to_process - to_exclude
|
23
|
+
end
|
25
24
|
|
26
|
-
|
25
|
+
def each(&block)
|
26
|
+
@files.map{ |path| path.gsub('//', '/')}
|
27
27
|
.each(&block)
|
28
28
|
end
|
29
29
|
|
30
|
+
def size
|
31
|
+
@size ||= @files.size
|
32
|
+
end
|
33
|
+
|
30
34
|
private
|
31
35
|
|
32
36
|
def expand_paths(path)
|
@@ -45,8 +45,10 @@ module Forspell::Loaders
|
|
45
45
|
|
46
46
|
group_by_location = chunks.group_by { |res| res[:location] }
|
47
47
|
.transform_values do |lines|
|
48
|
-
lines.map { |v| SPECIAL_CHARS_MAP[v[:value]] || v[:value] }
|
48
|
+
lines.map { |v| SPECIAL_CHARS_MAP[v[:value]] || v[:value] }
|
49
|
+
.join.split(%r{[[:punct:]]&&[^-'_./\\:]|\s})
|
49
50
|
end
|
51
|
+
|
50
52
|
group_by_location.each_pair do |location, words|
|
51
53
|
words.reject(&:empty?)
|
52
54
|
.each { |word| result << Word.new(@file, location || 0, word) }
|
@@ -2,20 +2,30 @@
|
|
2
2
|
|
3
3
|
require 'yard'
|
4
4
|
require 'yard/parser/ruby/ruby_parser'
|
5
|
+
require 'rdoc'
|
5
6
|
require_relative 'source'
|
6
7
|
|
7
8
|
module Forspell::Loaders
|
8
9
|
class Ruby < Source
|
10
|
+
MAX_COMMENT_LENGTH = 777
|
11
|
+
|
12
|
+
def initialize(file: nil, text: nil)
|
13
|
+
super
|
14
|
+
@markup = RDoc::Markup.new
|
15
|
+
@formatter = RDoc::Markup::ToMarkdown.new
|
16
|
+
@formatter.width = MAX_COMMENT_LENGTH
|
17
|
+
end
|
18
|
+
|
9
19
|
private
|
10
20
|
|
11
21
|
def comments
|
12
22
|
YARD::Parser::Ruby::RubyParser.new(@input, @file).parse
|
13
|
-
.tokens.select{ |
|
14
|
-
|
23
|
+
.tokens.select{ |type,| type == :comment }
|
24
|
+
.reject{ |_, text,| text.start_with?('# ') }
|
15
25
|
end
|
16
26
|
|
17
27
|
def text(comment)
|
18
|
-
comment[1]
|
28
|
+
@markup.convert(comment[1], @formatter)
|
19
29
|
end
|
20
30
|
|
21
31
|
def line(comment)
|
data/lib/forspell/reporter.rb
CHANGED
@@ -4,18 +4,26 @@ require 'fileutils'
|
|
4
4
|
require 'pastel'
|
5
5
|
require 'logger'
|
6
6
|
require 'json'
|
7
|
+
require 'highline'
|
8
|
+
require 'ruby-progressbar'
|
7
9
|
|
8
10
|
module Forspell
|
9
11
|
class Reporter
|
10
12
|
SUCCESS_CODE = 0
|
11
13
|
ERROR_CODE = 1
|
12
|
-
|
14
|
+
DICT_PATH = File.join(Dir.pwd, 'forspell.dict')
|
15
|
+
DICT_OVERWRITE = 'Do you want to overwrite forspell.dict? (yN)'
|
16
|
+
SUGGEST_FORMAT = '(suggestions: %<suggestions>s)'
|
17
|
+
ERROR_FORMAT = '%<file>s:%<line>i: %<text>s %<suggest>s'
|
13
18
|
SUMMARY = "Forspell inspects *.rb, *.c, *.cpp, *.md files\n"\
|
14
19
|
'%<files>i inspected, %<errors>s detected'
|
15
20
|
|
21
|
+
attr_accessor :progress_bar
|
22
|
+
|
16
23
|
def initialize(logfile:,
|
17
24
|
verbose:,
|
18
|
-
format
|
25
|
+
format:,
|
26
|
+
print_filepaths: false)
|
19
27
|
|
20
28
|
FileUtils.touch(logfile) if logfile.is_a?(String)
|
21
29
|
@logger = Logger.new(logfile || STDERR)
|
@@ -26,6 +34,7 @@ module Forspell
|
|
26
34
|
@pastel = Pastel.new(enabled: $stdout.tty?)
|
27
35
|
@errors = []
|
28
36
|
@files = []
|
37
|
+
@print_filepaths = print_filepaths
|
29
38
|
end
|
30
39
|
|
31
40
|
def file(path)
|
@@ -35,7 +44,7 @@ module Forspell
|
|
35
44
|
|
36
45
|
def error(word, suggestions)
|
37
46
|
@errors << [word, suggestions]
|
38
|
-
|
47
|
+
print(readable(word, suggestions)) if @format == 'readable'
|
39
48
|
end
|
40
49
|
|
41
50
|
def parsing_error(error)
|
@@ -64,17 +73,19 @@ module Forspell
|
|
64
73
|
private
|
65
74
|
|
66
75
|
def readable(word, suggestions)
|
76
|
+
suggest = format(SUGGEST_FORMAT, suggestions: suggestions.join(', ')) unless suggestions.empty?
|
77
|
+
|
67
78
|
format(ERROR_FORMAT,
|
68
79
|
file: word[:file],
|
69
80
|
line: word[:line],
|
70
81
|
text: @pastel.red(word[:text]),
|
71
|
-
|
82
|
+
suggest: suggest)
|
72
83
|
end
|
73
84
|
|
74
85
|
def print_formatted
|
75
86
|
@errors.map { |word, suggestions| word.to_h.merge(suggestions: suggestions) }
|
76
87
|
.public_send("to_#{@format}")
|
77
|
-
.tap { |res|
|
88
|
+
.tap { |res| print res }
|
78
89
|
end
|
79
90
|
|
80
91
|
def print_summary
|
@@ -82,18 +93,32 @@ module Forspell
|
|
82
93
|
color = err_count.positive? ? :red : :green
|
83
94
|
total_errors_colorized = @pastel.decorate(err_count.to_s, color)
|
84
95
|
|
85
|
-
|
96
|
+
print format(SUMMARY, files: @files.size, errors: total_errors_colorized)
|
86
97
|
end
|
87
98
|
|
88
99
|
def print_dictionary
|
100
|
+
puts DICT_PATH
|
101
|
+
if File.exist?(DICT_PATH)
|
102
|
+
cli = HighLine.new
|
103
|
+
answer = cli.ask(DICT_OVERWRITE)
|
104
|
+
out = answer.downcase == 'y' ? File.new(DICT_PATH, 'w') : exit(1)
|
105
|
+
else
|
106
|
+
out = File.new(DICT_PATH, 'w')
|
107
|
+
end
|
89
108
|
@errors.map(&:first)
|
90
109
|
.group_by(&:text)
|
91
110
|
.transform_values { |v| v.map(&:file).uniq }
|
92
111
|
.sort_by { |word, *| word.downcase }
|
93
112
|
.each do |text, files|
|
94
|
-
files.each { |file| puts "\# #{file}" }
|
95
|
-
puts @pastel.decorate(text, :red)
|
113
|
+
files.each { |file| out.puts "\# #{file}" } if @print_filepaths
|
114
|
+
out.puts out.tty? ? @pastel.decorate(text, :red) : text
|
96
115
|
end
|
97
116
|
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def print something
|
121
|
+
$stdout.tty? ? @progress_bar&.log(something) : puts(something)
|
122
|
+
end
|
98
123
|
end
|
99
124
|
end
|
data/lib/forspell/ruby.dict
CHANGED
@@ -1,77 +1,454 @@
|
|
1
|
+
Cianfrocca
|
1
2
|
Gemfile: example
|
3
|
+
Hansson
|
4
|
+
Heinemeier
|
2
5
|
Rakefile
|
6
|
+
aasm
|
3
7
|
accessor: example
|
8
|
+
activerecord
|
9
|
+
activesupport
|
10
|
+
addon
|
4
11
|
admin: example
|
5
|
-
|
12
|
+
amongst
|
13
|
+
arel
|
14
|
+
arg: argument
|
15
|
+
arity
|
16
|
+
asciidoc
|
17
|
+
asciidoctor
|
6
18
|
async
|
7
19
|
attr: example
|
20
|
+
auth
|
21
|
+
authenticatable
|
22
|
+
autocorrect
|
23
|
+
autocorrected
|
24
|
+
autogenerated
|
25
|
+
autoload: load
|
26
|
+
autoloadable
|
27
|
+
autoloaded
|
28
|
+
autoloading
|
29
|
+
autosave
|
8
30
|
backend: example
|
9
31
|
backport: port
|
32
|
+
backtick
|
10
33
|
backtrace: example
|
34
|
+
basecamp
|
35
|
+
basename: name
|
36
|
+
baseurl
|
37
|
+
bcrypt
|
38
|
+
behaviour: behavior
|
39
|
+
benchmarking
|
40
|
+
bigint
|
41
|
+
bignum
|
42
|
+
bing
|
43
|
+
binstubs
|
11
44
|
bitwise
|
12
45
|
boolean: example
|
46
|
+
broadcastings
|
47
|
+
bugfix: fix
|
48
|
+
bugfixes
|
13
49
|
builtin
|
14
|
-
bundler
|
50
|
+
bundler: example
|
51
|
+
byebug
|
52
|
+
bytesize: size
|
53
|
+
capybara: example
|
54
|
+
chainable
|
55
|
+
changelog: log
|
56
|
+
changeset: set
|
15
57
|
charset: example
|
58
|
+
checkbox: box
|
59
|
+
checksum: gum
|
60
|
+
chmod
|
61
|
+
cli
|
62
|
+
cmd
|
63
|
+
codebase: base
|
16
64
|
codepoint: example
|
65
|
+
coderay
|
66
|
+
colour: color
|
67
|
+
commandline: line
|
68
|
+
compat
|
69
|
+
compatability
|
17
70
|
composable
|
18
|
-
|
71
|
+
concat
|
72
|
+
config: example
|
73
|
+
confirmable
|
74
|
+
const
|
75
|
+
constantize
|
76
|
+
crossref
|
77
|
+
cryptographically
|
78
|
+
ctx
|
79
|
+
cukes
|
80
|
+
customizable
|
81
|
+
customizations
|
82
|
+
datagram
|
19
83
|
dataset: set
|
84
|
+
datetime
|
85
|
+
declaratively
|
86
|
+
decrypt
|
87
|
+
dedupe
|
88
|
+
deferrable
|
89
|
+
defs
|
90
|
+
delegator
|
91
|
+
deprecations
|
92
|
+
deprecator
|
93
|
+
desc
|
94
|
+
deserialised
|
20
95
|
deserialization
|
21
96
|
deserialize: rise
|
22
|
-
|
97
|
+
deserialized
|
98
|
+
dest
|
99
|
+
destructor
|
100
|
+
destructuring
|
101
|
+
deterministically
|
102
|
+
dev
|
103
|
+
diff
|
104
|
+
diffable
|
105
|
+
dir: beer
|
106
|
+
docstring
|
107
|
+
docstrings
|
108
|
+
dogfoods
|
109
|
+
downcase
|
110
|
+
downcased
|
111
|
+
dup
|
112
|
+
dynamoid
|
113
|
+
eg
|
114
|
+
el
|
115
|
+
elsif
|
23
116
|
encoding: example
|
117
|
+
endian
|
118
|
+
enqueue
|
119
|
+
enqueued
|
120
|
+
enqueues
|
121
|
+
enqueuing
|
24
122
|
enum
|
123
|
+
enumerables
|
124
|
+
enums
|
125
|
+
env
|
126
|
+
epoll
|
127
|
+
erb
|
128
|
+
errback
|
129
|
+
erubi
|
130
|
+
erubis
|
131
|
+
erubis
|
132
|
+
etag
|
133
|
+
etag
|
134
|
+
eval
|
135
|
+
eval'd
|
136
|
+
evented
|
137
|
+
extensibility
|
138
|
+
extname
|
25
139
|
fallback: example
|
140
|
+
falsey
|
141
|
+
falsy
|
142
|
+
favour
|
143
|
+
fieldset
|
26
144
|
filesystem: system
|
145
|
+
fixnum
|
27
146
|
formatter: example
|
147
|
+
freenode
|
148
|
+
frontend
|
149
|
+
gemspec: specification
|
150
|
+
geocode: code
|
151
|
+
geocoded
|
152
|
+
geocoder
|
153
|
+
geocoding
|
28
154
|
geospatial
|
155
|
+
getter
|
156
|
+
gettext
|
157
|
+
gitter
|
158
|
+
globbing
|
159
|
+
gmail
|
160
|
+
grapheme
|
161
|
+
graphviz
|
162
|
+
gsub
|
163
|
+
gzip
|
164
|
+
gzipped
|
165
|
+
habtm
|
166
|
+
haml
|
167
|
+
hardcode
|
168
|
+
hardcoded
|
169
|
+
heredoc: document
|
170
|
+
highline
|
171
|
+
hiredis
|
172
|
+
hostname: name
|
173
|
+
href
|
174
|
+
hstore
|
175
|
+
https
|
29
176
|
i18n
|
177
|
+
iconv
|
178
|
+
iframe
|
179
|
+
impl
|
180
|
+
incrementing
|
181
|
+
inflector
|
182
|
+
initialised
|
30
183
|
initializer: example
|
31
184
|
inline
|
185
|
+
instantiation
|
186
|
+
interdependencies
|
187
|
+
invoker
|
32
188
|
io
|
189
|
+
irb
|
190
|
+
iteratively
|
191
|
+
ivar: variable
|
192
|
+
javascripts
|
193
|
+
jbuilder
|
194
|
+
jruby
|
195
|
+
jruby
|
196
|
+
js
|
197
|
+
json
|
198
|
+
klass
|
199
|
+
kqueue
|
200
|
+
kramdown
|
201
|
+
lcs
|
33
202
|
lexer: example
|
34
203
|
lib: rib
|
204
|
+
libxml
|
205
|
+
libxml-ruby
|
206
|
+
libxslt
|
35
207
|
lifecycle: example
|
208
|
+
localhost
|
209
|
+
lookups
|
210
|
+
loopback
|
211
|
+
lua
|
212
|
+
markaby
|
213
|
+
maruku
|
214
|
+
matcher: catcher
|
215
|
+
mediawiki
|
216
|
+
memcache
|
36
217
|
memoization
|
218
|
+
memoize
|
37
219
|
memoized
|
220
|
+
merb
|
38
221
|
metadata
|
222
|
+
metaprogramming
|
39
223
|
middleware: example
|
224
|
+
minitest: example
|
225
|
+
mins
|
40
226
|
mixin: toxin
|
227
|
+
modularity
|
228
|
+
mongo
|
229
|
+
mongoid
|
41
230
|
monkeypatch: patch
|
42
231
|
monkeypatching
|
232
|
+
mtime
|
233
|
+
multibyte
|
234
|
+
multiline
|
43
235
|
multithreaded
|
44
236
|
multithreading
|
237
|
+
mustermann
|
238
|
+
mutator
|
45
239
|
mutex: class
|
240
|
+
namer
|
46
241
|
namespace: example
|
242
|
+
natively
|
243
|
+
nginx
|
244
|
+
nginx
|
245
|
+
nils
|
246
|
+
nodoc
|
247
|
+
nokogiri: example
|
248
|
+
nonces
|
249
|
+
noop
|
250
|
+
npm
|
251
|
+
numericality
|
252
|
+
offence
|
253
|
+
openssl
|
254
|
+
overridable
|
47
255
|
override: ride
|
256
|
+
overriden
|
257
|
+
pandoc
|
258
|
+
parallelize
|
48
259
|
param: example
|
49
260
|
parens
|
261
|
+
parseable
|
50
262
|
parser: example
|
263
|
+
pathname
|
264
|
+
pathname
|
265
|
+
perf
|
266
|
+
performant
|
267
|
+
permalink: link
|
268
|
+
pid
|
269
|
+
pipelined
|
270
|
+
pipelining
|
271
|
+
plaintext
|
272
|
+
pluggable
|
51
273
|
plugin: penguin
|
274
|
+
populator
|
275
|
+
postfix
|
276
|
+
postgres
|
52
277
|
pre
|
278
|
+
precompile
|
279
|
+
precompiled
|
280
|
+
preload
|
281
|
+
preloaded
|
282
|
+
preloader
|
283
|
+
preloading
|
284
|
+
preloads
|
53
285
|
prepend: append
|
54
|
-
|
286
|
+
preprocessing
|
287
|
+
prerelease
|
288
|
+
proc: example
|
289
|
+
profiler
|
290
|
+
programmatically
|
291
|
+
proxied
|
292
|
+
proxying
|
293
|
+
pubsub
|
294
|
+
pygments
|
295
|
+
rack-contrib
|
296
|
+
rackup
|
297
|
+
ragel
|
298
|
+
rails's
|
299
|
+
railtie
|
300
|
+
railties
|
301
|
+
rbenv
|
302
|
+
rbx
|
303
|
+
rdoc
|
304
|
+
readline
|
305
|
+
readme
|
306
|
+
readonly
|
307
|
+
rebase
|
308
|
+
reconfirmable
|
309
|
+
redcarpet
|
310
|
+
redistribution: distribution
|
55
311
|
refactor
|
56
312
|
refactoring
|
313
|
+
refactorings
|
57
314
|
regex
|
58
315
|
regexp
|
59
|
-
|
316
|
+
reloader: loader
|
317
|
+
rememberable
|
318
|
+
renderer: example
|
319
|
+
repl
|
320
|
+
repo: example
|
321
|
+
representable
|
322
|
+
representer
|
323
|
+
repro
|
324
|
+
reraise
|
325
|
+
resque
|
326
|
+
rhs
|
327
|
+
roadmap
|
328
|
+
rspec
|
329
|
+
rspec-dev
|
330
|
+
rspec-support
|
331
|
+
rubinius
|
332
|
+
rubocop
|
60
333
|
rubygems
|
61
334
|
runtime: example
|
335
|
+
sanitization
|
336
|
+
savepoint: point
|
337
|
+
scalability
|
338
|
+
schemas
|
339
|
+
scss
|
340
|
+
segv
|
341
|
+
sendmail
|
342
|
+
serializable
|
343
|
+
serializer: example
|
344
|
+
serializers
|
345
|
+
servlet
|
346
|
+
sexualized
|
347
|
+
sharding
|
348
|
+
sidekiq
|
349
|
+
signalling
|
350
|
+
simples
|
351
|
+
singularized
|
352
|
+
solaris
|
353
|
+
src
|
354
|
+
ssl
|
355
|
+
stabby
|
356
|
+
stateful
|
357
|
+
stdcall
|
62
358
|
stderr
|
63
359
|
stdin
|
64
360
|
stdlib
|
361
|
+
stdlibs
|
65
362
|
stdout
|
363
|
+
str
|
364
|
+
strftime
|
365
|
+
stringified
|
366
|
+
stringify
|
367
|
+
stringify
|
368
|
+
struct: structure
|
66
369
|
stylesheet: sheet
|
67
370
|
subclass: class
|
68
371
|
subclassing
|
69
|
-
|
372
|
+
subcommand: commnad
|
373
|
+
subdirectory: directory
|
374
|
+
subfolder: folder
|
375
|
+
sublicense: license
|
376
|
+
subpath: path
|
377
|
+
subprocess
|
378
|
+
substring: string
|
379
|
+
subtype: type
|
380
|
+
sudo
|
70
381
|
superclass: class
|
382
|
+
symlink: link
|
383
|
+
symlinked
|
384
|
+
syntaxes
|
385
|
+
sysrandom
|
386
|
+
teardown
|
387
|
+
tempfile: file
|
388
|
+
templating
|
389
|
+
textarea: area
|
390
|
+
thoughtbot
|
391
|
+
threadsafe
|
71
392
|
timestamp: stamp
|
393
|
+
timezone: zone
|
394
|
+
tmp
|
395
|
+
todo
|
396
|
+
tokenize
|
397
|
+
tokenized
|
72
398
|
tokenizer: example
|
399
|
+
toplevel
|
400
|
+
trackable
|
401
|
+
tradeoff
|
402
|
+
transactional
|
403
|
+
transcoding
|
404
|
+
triaging
|
73
405
|
truthy
|
406
|
+
tt
|
407
|
+
tty
|
408
|
+
turbolinks
|
409
|
+
typedef
|
410
|
+
tz
|
411
|
+
uglifier
|
412
|
+
unary
|
413
|
+
uncomment
|
74
414
|
unescape
|
415
|
+
unescaped
|
416
|
+
unescapes
|
417
|
+
unescaping
|
418
|
+
unformatted
|
419
|
+
unhandled
|
75
420
|
unicode
|
421
|
+
unindent
|
422
|
+
uniq
|
423
|
+
unlink: link
|
424
|
+
unlinked
|
425
|
+
unparenthesized
|
426
|
+
unreferenced
|
427
|
+
unregister
|
428
|
+
unscoped
|
429
|
+
untrusted
|
430
|
+
uri
|
431
|
+
usec
|
76
432
|
username: example
|
433
|
+
uuid
|
434
|
+
valgrind
|
435
|
+
validator: predator
|
436
|
+
validators
|
437
|
+
vendored
|
438
|
+
vendoring
|
439
|
+
verifier
|
440
|
+
verifiers
|
441
|
+
viewport
|
442
|
+
webrick
|
443
|
+
webserver
|
77
444
|
whitespace: example
|
445
|
+
wkhtmltopdf
|
446
|
+
writeable
|
447
|
+
wtf
|
448
|
+
xmlns
|
449
|
+
xpath
|
450
|
+
yajl
|
451
|
+
yaml
|
452
|
+
yardoc
|
453
|
+
yay
|
454
|
+
zoneinfo
|
data/lib/forspell/runner.rb
CHANGED
@@ -10,8 +10,13 @@ module Forspell
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def call
|
13
|
-
@files.
|
13
|
+
increment = (@files.size / 100.0).ceil
|
14
|
+
total = @files.size <= 100 ? @files.size : 100
|
15
|
+
@reporter.progress_bar = ProgressBar.create(total: total, output: $stderr)
|
16
|
+
|
17
|
+
@files.each_with_index do |path, index|
|
14
18
|
process_file path
|
19
|
+
@reporter.progress_bar.increment if (index + 1) % increment == 0
|
15
20
|
end
|
16
21
|
|
17
22
|
@reporter.report
|
data/lib/forspell/sanitizer.rb
CHANGED
@@ -5,18 +5,12 @@ require 'cgi'
|
|
5
5
|
|
6
6
|
module Forspell
|
7
7
|
module Sanitizer
|
8
|
-
REMOVE_PUNCT =
|
8
|
+
REMOVE_PUNCT = %r{[!|?|,|(|)|"|;]+}.freeze
|
9
9
|
|
10
10
|
def self.sanitize(input)
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
.gsub(REMOVE_PUNCT, '').gsub(/[\!\.\?]{1}$/, '')
|
15
|
-
if result.start_with?("'") && result.end_with?("'")
|
16
|
-
result[1..-2]
|
17
|
-
else
|
18
|
-
result
|
12
|
+
CGI.unescapeHTML(Sanitize.fragment(input, elements: [], remove_contents: true))
|
13
|
+
.gsub(REMOVE_PUNCT, '').gsub(%r{[.:]+$}, '')
|
19
14
|
end
|
20
|
-
end
|
21
15
|
end
|
22
16
|
end
|
data/lib/forspell/speller.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'ffi/hunspell'
|
4
|
+
require 'backports/2.5.0/enumerable/all'
|
4
5
|
|
5
6
|
module Forspell
|
6
7
|
class Speller
|
7
8
|
attr_reader :dictionary
|
8
9
|
|
9
|
-
SUGGESTIONS_SIZE = 3
|
10
10
|
HUNSPELL_DIRS = [File.join(__dir__, 'dictionaries')]
|
11
11
|
RUBY_DICT = File.join(__dir__, 'ruby.dict')
|
12
12
|
|
13
|
-
def initialize(main_dictionary, *custom_dictionaries)
|
13
|
+
def initialize(main_dictionary, *custom_dictionaries, suggestions_size: 0)
|
14
|
+
@suggestions_size = suggestions_size
|
14
15
|
FFI::Hunspell.directories = HUNSPELL_DIRS << File.dirname(main_dictionary)
|
15
16
|
@dictionary = FFI::Hunspell.dict(File.basename(main_dictionary))
|
16
17
|
|
@@ -28,11 +29,20 @@ module Forspell
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def correct?(word)
|
31
|
-
|
32
|
+
parts = word.split('-')
|
33
|
+
if parts.size == 1
|
34
|
+
alterations = [word]
|
35
|
+
alterations << word.capitalize unless word.capitalize == word
|
36
|
+
alterations << word.upcase unless word.upcase == word
|
37
|
+
|
38
|
+
alterations.any?{ |w| dictionary.check?(w) }
|
39
|
+
else
|
40
|
+
parts.all? { |part| correct?(part) }
|
41
|
+
end
|
32
42
|
end
|
33
43
|
|
34
44
|
def suggest(word)
|
35
|
-
dictionary.suggest(word).first(
|
45
|
+
@suggestions_size.positive? ? dictionary.suggest(word).first(@suggestions_size) : []
|
36
46
|
end
|
37
47
|
end
|
38
48
|
end
|
@@ -3,12 +3,10 @@ require 'backports/2.4.0/regexp/match'
|
|
3
3
|
module Forspell
|
4
4
|
module WordMatcher
|
5
5
|
WORD = %r{^
|
6
|
-
|
7
|
-
([
|
8
|
-
([[:lower:]])
|
9
|
-
([
|
10
|
-
([[:lower:]])* # another bunch of letters
|
11
|
-
\'? # could end with apostrophe
|
6
|
+
([a-z]|[A-Z]) # at least one letter,
|
7
|
+
([[:lower:]])* # then any number of letters,
|
8
|
+
([\'\-][[:lower:]])? # optional dash/apostrophe, followed by letter
|
9
|
+
([[:lower:]])* # another bunch of letters
|
12
10
|
$}x
|
13
11
|
|
14
12
|
def self.word? text
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forspell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kirill Kuprikov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-05-
|
12
|
+
date: 2019-05-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: slop
|
@@ -137,6 +137,34 @@ dependencies:
|
|
137
137
|
- - ">="
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: highline
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
type: :runtime
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: ruby-progressbar
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
type: :runtime
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
140
168
|
- !ruby/object:Gem::Dependency
|
141
169
|
name: rspec
|
142
170
|
requirement: !ruby/object:Gem::Requirement
|