heckler 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +44 -0
- data/Rakefile +16 -0
- data/exe/heckler +6 -0
- data/heckler.json +10 -0
- data/lib/heckler/aspell.rb +47 -0
- data/lib/heckler/checker/file_system.rb +91 -0
- data/lib/heckler/cli.rb +50 -0
- data/lib/heckler/config.rb +86 -0
- data/lib/heckler/personn.rb +0 -0
- data/lib/heckler/preset.rb +20 -0
- data/lib/heckler/presets/base.stub +98 -0
- data/lib/heckler/version.rb +5 -0
- data/lib/heckler.rb +11 -0
- data/sig/heckler.rbs +4 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 605da338e5d75dfc3615fd7255390559228de9223cea8c4696a7781f64b7d33f
|
4
|
+
data.tar.gz: 067dfae307730437b0d5bae6a90e06f9033ab0f479469234d11da2dde64bff92
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0e84e49df096985d552c49bd91d9bae548904174d743c5ca6288884e9494ce4be5e5a4601f900b967334500b376e113c719888fbaa91ace5a02ef405b955d8bc
|
7
|
+
data.tar.gz: 3b1f705402cb5e522ee4f47d8652947ac1cb56b6e1d2ff539e2fd9d616b15e55a497f173295acbc917d58464fa79e9ab37e35fb03426b8871fad9cb4facfa12e
|
data/.standard.yml
ADDED
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Stanislav (Stas) Katkov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Heckler
|
2
|
+
|
3
|
+
**Heckler** is a tool to identify wording or spelling mistakes in ruby codebase: filenames, class names, method names, property names and more. Spelling correction is powered by [GNU Aspell](https://en.wikipedia.org/wiki/GNU_Aspell) and originally started as a ruby port of [Peck](https://github.com/peckphp/peck).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
bundle add heckler
|
9
|
+
```
|
10
|
+
|
11
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
12
|
+
|
13
|
+
```bash
|
14
|
+
gem install heckler
|
15
|
+
```
|
16
|
+
|
17
|
+
## Dependencies
|
18
|
+
Heckler requires Aspell to be present on a system to function.
|
19
|
+
|
20
|
+
### MacOS
|
21
|
+
`brew install aspell`
|
22
|
+
|
23
|
+
### Linux
|
24
|
+
- Debian/Ubuntu: `sudo apt-get install aspell aspell-en`
|
25
|
+
- Fedora: `sudo dnf install aspell aspell-en`
|
26
|
+
- Arch Linux: `sudo pacman -S aspell aspell-en`
|
27
|
+
- openSUSE: `sudo zypper install aspell aspell-en`
|
28
|
+
- Alpine: `sudo apk add aspell aspell-en`
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Start off by creating a configuration file, by running:
|
33
|
+
`heckler init`
|
34
|
+
|
35
|
+
Run spelling check with `heckler`
|
36
|
+
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/skatkov/heckler.
|
41
|
+
|
42
|
+
## License
|
43
|
+
|
44
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "minitest/test_task"
|
5
|
+
|
6
|
+
Minitest::TestTask.create
|
7
|
+
|
8
|
+
require "standard/rake"
|
9
|
+
|
10
|
+
task default: %i[test standard]
|
11
|
+
|
12
|
+
desc "Build and install gem locally"
|
13
|
+
task :local_install do
|
14
|
+
system "gem build heckler.gemspec"
|
15
|
+
system "gem install ./heckler-#{Heckler::VERSION}.gem"
|
16
|
+
end
|
data/exe/heckler
ADDED
data/heckler.json
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "open3"
|
2
|
+
require_relative "config"
|
3
|
+
|
4
|
+
Misspelling = Data.define(:word, :suggestions)
|
5
|
+
|
6
|
+
module Heckler
|
7
|
+
class Aspell
|
8
|
+
@process = nil
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
def check(text)
|
15
|
+
misspellings = get_misspellings(text)
|
16
|
+
misspellings.reject { |misspelling| @config.word_ignored?(misspelling.word) }
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def get_misspellings(text)
|
22
|
+
misspellings = run(text)
|
23
|
+
misspellings
|
24
|
+
end
|
25
|
+
|
26
|
+
def take_suggestions(suggestions)
|
27
|
+
suggestions = suggestions.select { |suggestion| suggestion.match(/[^a-zA-Z]/).nil? }
|
28
|
+
suggestions.uniq
|
29
|
+
end
|
30
|
+
|
31
|
+
def run(text)
|
32
|
+
stdin, stdout, stderr, wait_thr = Open3.popen3("aspell", "--encoding", "utf-8", "-a", "--ignore-case", "--lang=en_US", "--sug-mode=ultra")
|
33
|
+
stdin.puts text
|
34
|
+
stdin.close
|
35
|
+
output = stdout.read
|
36
|
+
stdout.close
|
37
|
+
stderr.close
|
38
|
+
|
39
|
+
output.lines.select { |line| line.start_with?("&") }.map do |line|
|
40
|
+
word_metadata, suggestions = line.strip.split(":")
|
41
|
+
word = word_metadata.split(" ")[1]
|
42
|
+
suggestions = suggestions.strip.split(", ")
|
43
|
+
Misspelling.new(word, take_suggestions(suggestions))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative "../aspell"
|
2
|
+
|
3
|
+
require "find"
|
4
|
+
|
5
|
+
# The Checker::FileSystem class provides functionality to check spelling in file and directory names within a given directory structure.
|
6
|
+
#
|
7
|
+
# Usage:
|
8
|
+
# checker = Checker::FileSystem.new
|
9
|
+
# issues = checker.check("/path/to/directory")
|
10
|
+
#
|
11
|
+
# The check method:
|
12
|
+
# - Recursively traverses the given directory
|
13
|
+
# - Skips hidden files/directories (starting with .)
|
14
|
+
# - Skips .git directories
|
15
|
+
# - Checks spelling of each file/directory name
|
16
|
+
# - Returns an array of Issue objects containing any misspellings found
|
17
|
+
#
|
18
|
+
# Each Issue object contains:
|
19
|
+
# - The misspelling that was found
|
20
|
+
# - The full path to the file/directory
|
21
|
+
# - The line number (always 0 for filenames)
|
22
|
+
module Heckler
|
23
|
+
class Checker
|
24
|
+
class FileSystem
|
25
|
+
def initialize(config, spellchecker)
|
26
|
+
@config = config
|
27
|
+
@spellchecker = spellchecker
|
28
|
+
end
|
29
|
+
|
30
|
+
def check(directory)
|
31
|
+
files_or_directories = []
|
32
|
+
Find.find(directory) do |path|
|
33
|
+
next if File.basename(path).start_with?(".")
|
34
|
+
next if File.fnmatch("*/.git/*", path)
|
35
|
+
|
36
|
+
files_or_directories << path
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
files_or_directories.sort_by! { |path| File.realpath(path) }
|
41
|
+
|
42
|
+
puts files_or_directories
|
43
|
+
|
44
|
+
issues = []
|
45
|
+
|
46
|
+
files_or_directories.each do |file_or_directory|
|
47
|
+
name = SpellcheckFormatter.format(File.basename(file_or_directory, ".*"))
|
48
|
+
new_issues = @spellchecker.check(name).map do |misspelling|
|
49
|
+
Issue.new(misspelling, File.realpath(file_or_directory), 0)
|
50
|
+
end
|
51
|
+
|
52
|
+
issues.concat(new_issues)
|
53
|
+
end
|
54
|
+
|
55
|
+
issues
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class SpellcheckFormatter
|
61
|
+
def self.format(input)
|
62
|
+
# Remove leading underscores
|
63
|
+
input = input.gsub(/^_+/, "")
|
64
|
+
|
65
|
+
# Replace underscores and dashes with spaces
|
66
|
+
input = input.tr("_-", " ")
|
67
|
+
|
68
|
+
# Insert spaces between lowercase and uppercase letters (camelCase or PascalCase)
|
69
|
+
input = input.gsub(/([a-z])([A-Z])/, '\1 \2')
|
70
|
+
|
71
|
+
# Split sequences of uppercase letters, ensuring the last uppercase letter starts a new word
|
72
|
+
input = input.gsub(/([A-Z]+)([A-Z][a-z])/, '\1 \2')
|
73
|
+
|
74
|
+
# Replace multiple spaces with a single space
|
75
|
+
input = input.gsub(/\s+/, " ")
|
76
|
+
|
77
|
+
# Convert the final result to lowercase
|
78
|
+
input.downcase
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Issue
|
83
|
+
attr_reader :misspelling, :file, :line
|
84
|
+
|
85
|
+
def initialize(misspelling, file, line)
|
86
|
+
@misspelling = misspelling
|
87
|
+
@file = file
|
88
|
+
@line = line
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/heckler/cli.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
require_relative "config"
|
4
|
+
require_relative "aspell"
|
5
|
+
require_relative "preset"
|
6
|
+
require_relative "checker/file_system"
|
7
|
+
|
8
|
+
|
9
|
+
module Heckler
|
10
|
+
class Runner
|
11
|
+
attr_reader :checkers
|
12
|
+
|
13
|
+
def initialize(checkers)
|
14
|
+
@checkers = checkers
|
15
|
+
end
|
16
|
+
|
17
|
+
def run(directory)
|
18
|
+
issues = []
|
19
|
+
|
20
|
+
puts directory
|
21
|
+
|
22
|
+
@checkers.each do |checker|
|
23
|
+
issues.concat(checker.check(directory))
|
24
|
+
end
|
25
|
+
|
26
|
+
issues
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class CLI
|
31
|
+
def self.start(args)
|
32
|
+
command = args.shift
|
33
|
+
|
34
|
+
case command
|
35
|
+
when 'init'
|
36
|
+
Config.init
|
37
|
+
when nil
|
38
|
+
config = Config.instance
|
39
|
+
aspell = Aspell.new(config)
|
40
|
+
|
41
|
+
Runner.new([
|
42
|
+
Heckler::Checker::FileSystem.new(config, aspell)
|
43
|
+
]).run(Dir.pwd)
|
44
|
+
else
|
45
|
+
puts "Unknown command: #{command}"
|
46
|
+
puts "Available commands: init, or no command for default behavior"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "json"
|
2
|
+
require "singleton"
|
3
|
+
require_relative "preset"
|
4
|
+
|
5
|
+
module Heckler
|
6
|
+
class Config
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
JSON_CONFIGURATION_NAME = "heckler.json".freeze
|
10
|
+
|
11
|
+
attr_accessor :whitelisted_words, :whitelisted_paths, :preset
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@whitelisted_words = []
|
15
|
+
@whitelisted_paths = []
|
16
|
+
@preset = nil
|
17
|
+
load_config
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.flush
|
21
|
+
instance.whitelisted_words = []
|
22
|
+
instance.whitelisted_paths = []
|
23
|
+
instance.preset = nil
|
24
|
+
@resolve_config_file_path_using = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.exists?
|
28
|
+
File.exist?(Dir.pwd + "/" + JSON_CONFIGURATION_NAME)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.init
|
32
|
+
file_path = Dir.pwd + "/" + JSON_CONFIGURATION_NAME
|
33
|
+
|
34
|
+
return false if File.exist?(file_path)
|
35
|
+
|
36
|
+
configuration = {
|
37
|
+
preset: "base",
|
38
|
+
ignore: {
|
39
|
+
words: [],
|
40
|
+
paths: ["tmp/", "log/"]
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
File.write(file_path, JSON.pretty_generate(configuration))
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def ignore_words(words)
|
49
|
+
@whitelisted_words.concat(words.map(&:downcase)).uniq!
|
50
|
+
persist
|
51
|
+
end
|
52
|
+
|
53
|
+
def word_ignored?(word)
|
54
|
+
@whitelisted_words.include?(word.downcase) ||
|
55
|
+
Preset.whitelisted_words(@preset).include?(word.downcase)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def load_config
|
61
|
+
base_path = Dir.pwd
|
62
|
+
file_path = base_path + "/" + (self.class.instance_variable_get(:@resolve_config_file_path_using)&.call || JSON_CONFIGURATION_NAME)
|
63
|
+
|
64
|
+
contents = File.exist?(file_path) ? File.read(file_path) : "{}"
|
65
|
+
json_as_array = JSON.parse(contents, symbolize_names: true) rescue {}
|
66
|
+
|
67
|
+
@whitelisted_words = (json_as_array.dig(:ignore, :words) || []).map(&:downcase)
|
68
|
+
@whitelisted_paths = json_as_array.dig(:ignore, :paths) || []
|
69
|
+
@preset = json_as_array[:preset]
|
70
|
+
end
|
71
|
+
|
72
|
+
def persist
|
73
|
+
file_path = Dir.pwd + "/" + JSON_CONFIGURATION_NAME
|
74
|
+
|
75
|
+
configuration = {
|
76
|
+
preset: @preset,
|
77
|
+
ignore: {
|
78
|
+
words: @whitelisted_words,
|
79
|
+
paths: @whitelisted_paths
|
80
|
+
}
|
81
|
+
}.compact
|
82
|
+
|
83
|
+
File.write(file_path, JSON.pretty_generate(configuration))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Heckler
|
2
|
+
class Preset
|
3
|
+
PRESET_STUBS_DIRECTORY = File.join(__dir__, "/presets")
|
4
|
+
|
5
|
+
def self.whitelisted_words(preset)
|
6
|
+
return [] if preset.nil? || !stub_exists?(preset)
|
7
|
+
|
8
|
+
get_words_from_stub("base") + get_words_from_stub(preset)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.get_words_from_stub(preset)
|
12
|
+
path = File.join(PRESET_STUBS_DIRECTORY, "#{preset}.stub")
|
13
|
+
File.read(path).lines.map(&:strip).reject(&:empty?)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.stub_exists?(preset)
|
17
|
+
File.exist?(File.join(PRESET_STUBS_DIRECTORY, "#{preset}.stub"))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
backfill
|
2
|
+
cancelled
|
3
|
+
propable
|
4
|
+
dns
|
5
|
+
verifier
|
6
|
+
enum
|
7
|
+
backend
|
8
|
+
formatter
|
9
|
+
init
|
10
|
+
enums
|
11
|
+
env
|
12
|
+
misconfigured
|
13
|
+
webhook
|
14
|
+
auth
|
15
|
+
webhooks
|
16
|
+
middleware
|
17
|
+
json
|
18
|
+
fakeable
|
19
|
+
fillable
|
20
|
+
verifiers
|
21
|
+
slugifier
|
22
|
+
txt
|
23
|
+
namespace
|
24
|
+
truncatable
|
25
|
+
unformatted
|
26
|
+
finishable
|
27
|
+
gitlab
|
28
|
+
gitfake
|
29
|
+
uri
|
30
|
+
authenticatable
|
31
|
+
hmac
|
32
|
+
callables
|
33
|
+
validator
|
34
|
+
hostname
|
35
|
+
ssl
|
36
|
+
backoff
|
37
|
+
bool
|
38
|
+
schemas
|
39
|
+
pre
|
40
|
+
accessors
|
41
|
+
unsuspend
|
42
|
+
frontend
|
43
|
+
repo
|
44
|
+
src
|
45
|
+
jwt
|
46
|
+
nano
|
47
|
+
slugify
|
48
|
+
config
|
49
|
+
ecr
|
50
|
+
cloudflare
|
51
|
+
bitbucket
|
52
|
+
serverless
|
53
|
+
postgres
|
54
|
+
dev
|
55
|
+
ui
|
56
|
+
vite
|
57
|
+
tls
|
58
|
+
acl
|
59
|
+
http
|
60
|
+
parsable
|
61
|
+
confirmable
|
62
|
+
changelog
|
63
|
+
livewire
|
64
|
+
autocomplete
|
65
|
+
followable
|
66
|
+
recaptcha
|
67
|
+
stringable
|
68
|
+
viewables
|
69
|
+
resizer
|
70
|
+
params
|
71
|
+
unfollow
|
72
|
+
unfollows
|
73
|
+
datetime
|
74
|
+
otp
|
75
|
+
lifecycle
|
76
|
+
unbookmark
|
77
|
+
pinnable
|
78
|
+
mailables
|
79
|
+
sharable
|
80
|
+
blocklist
|
81
|
+
conf
|
82
|
+
timezones
|
83
|
+
autocompletion
|
84
|
+
arrayable
|
85
|
+
pinkary
|
86
|
+
sponsorship
|
87
|
+
sponsorships
|
88
|
+
iframe
|
89
|
+
tokenize
|
90
|
+
pwa
|
91
|
+
stylesheets
|
92
|
+
rubygems
|
93
|
+
gemfile
|
94
|
+
rakefile
|
95
|
+
cli
|
96
|
+
exe
|
97
|
+
readme
|
98
|
+
sig
|
data/lib/heckler.rb
ADDED
data/sig/heckler.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: heckler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stanislav (Stas) Katkov
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-01-16 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: "**Heckler** is a tool to identify wording or spelling mistakes in ruby
|
14
|
+
codebase: filenames, class names, method names, property names and more. Spelling
|
15
|
+
correction is powered by **GNU Aspell**."
|
16
|
+
email:
|
17
|
+
- github@skatkov.com
|
18
|
+
executables:
|
19
|
+
- heckler
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- ".standard.yml"
|
24
|
+
- CHANGELOG.md
|
25
|
+
- LICENSE.txt
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- exe/heckler
|
29
|
+
- heckler.json
|
30
|
+
- lib/heckler.rb
|
31
|
+
- lib/heckler/aspell.rb
|
32
|
+
- lib/heckler/checker/file_system.rb
|
33
|
+
- lib/heckler/cli.rb
|
34
|
+
- lib/heckler/config.rb
|
35
|
+
- lib/heckler/personn.rb
|
36
|
+
- lib/heckler/preset.rb
|
37
|
+
- lib/heckler/presets/base.stub
|
38
|
+
- lib/heckler/version.rb
|
39
|
+
- sig/heckler.rbs
|
40
|
+
homepage: https://github.com/skatkov/heckler
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
metadata:
|
44
|
+
homepage_uri: https://github.com/skatkov/heckler
|
45
|
+
source_code_uri: https://github.com/skatkov/heckler
|
46
|
+
changelog_uri: https://github.com/skatkov/heckler/CHANGELOG.md
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 3.1.0
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubygems_version: 3.5.22
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: tool to identify wording or spelling mistakes in ruby codebase
|
66
|
+
test_files: []
|