typo_checker 0.1.5 → 0.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7173dd0294a0f7645db2dde57c7fdd4dedd49643668ce2c7d59bc13d09d1d9f4
4
- data.tar.gz: 37477c3e7eb020a7112fae39b9c30bdc3b78d8b4cb526da8ecab38a17e3ecfce
3
+ metadata.gz: c08c05d34a0569f214adc5a2f01416f2ce6302aadca2dabd597bc3581ff5d8b1
4
+ data.tar.gz: d54006052dfbc69df8998d0c5012935c42fe14240643a058eaa0584fae829db9
5
5
  SHA512:
6
- metadata.gz: 954a4e7a09375a52125d1db49ac0a5845ae8ef56867eb1e7c984244513ff0e801977a5f691ef181d8f7f91bb471af706fd94b04246c5bdc11a37aced5a6ffaf4
7
- data.tar.gz: 38b377026a5433b5800517076afd009222e2a903cbd0df9b324b3e3c2ccd1fbf2e5b7679d7a505f5d073ccbf54bdad6061c2da3e056f4990e5de46cae74ec555
6
+ metadata.gz: 7dd706b82d00f6f3c40bc8bc9c5ae42b04f2dc8c01b7a33732207008c39aa97a481430bb1cf76ec519cdca86e8da312eef5d278496be5a462f5b935010533050
7
+ data.tar.gz: bb49fd0e16e06c9fb08a396d39f4ee80ae1ba64124e336f1e2da3f957de69c8ff4ce2ccd10ec902cf590f88fdd4d2af9df7b6a5c1acd2d9963bae696131f96ee
data/lib/data/typos.csv CHANGED
@@ -44440,7 +44440,6 @@ falsde,false
44440
44440
  falsei,false
44441
44441
  falseley,falsely
44442
44442
  falsemounted,false
44443
- falsey,false
44444
44443
  falsh,flash
44445
44444
  falshbacks,flashbacks
44446
44445
  falshed,flashed
@@ -47029,7 +47028,6 @@ frezeang,freezing
47029
47028
  frezeing,freezing
47030
47029
  frezing,freezing
47031
47030
  frezzing,freezing
47032
- fri,fry
47033
47031
  friand,friend
47034
47032
  fribease,firebase
47035
47033
  frictioin,friction
@@ -61983,7 +61981,6 @@ jamiacan,jamaican
61983
61981
  jamine,jasmine
61984
61982
  jammming,jamming
61985
61983
  jamsine,jasmine
61986
- jan,jam
61987
61984
  janacek,janáček
61988
61985
  janaury,january
61989
61986
  janaček,janáček
@@ -69687,7 +69684,6 @@ mommentarily,momentarily
69687
69684
  mommentary,momentary
69688
69685
  momments,moments
69689
69686
  momories,memories
69690
- mon,moon
69691
69687
  monacco,Monaco
69692
69688
  monagomous,monogamous
69693
69689
  monagomy,monogamy
@@ -97175,7 +97171,6 @@ seocondary,secondary
97175
97171
  seonc,second
97176
97172
  seond,second
97177
97173
  seonds,seconds
97178
- sep,step
97179
97174
  sepaated,separated
97180
97175
  sepamns,specimens
97181
97176
  sepaphore,semaphore
@@ -110182,7 +110177,6 @@ tuched,touched
110182
110177
  tucknolgies,tucknologies
110183
110178
  tucowws,tucows
110184
110179
  tudents,students
110185
- tue,true
110186
110180
  tuesdsay,tuesdays
110187
110181
  tuesdsy,tuesdays
110188
110182
  tuitioin,tuition
@@ -112652,7 +112646,6 @@ unintuive,unintuitive
112652
112646
  uniomus,unanimous
112653
112647
  unionous,unanimous
112654
112648
  unioun,union
112655
- uniq,unique
112656
112649
  uniqe,unique
112657
112650
  uniqely,uniquely
112658
112651
  uniqu,unique
@@ -114460,7 +114453,6 @@ uther,other
114460
114453
  uthor,author
114461
114454
  utiility,utility
114462
114455
  utiity,utility
114463
- util,until
114464
114456
  utilaties,utilities
114465
114457
  utilaty,utility
114466
114458
  utiliatrian,utilitarian
@@ -0,0 +1,11 @@
1
+ module TypoChecker
2
+ class Configuration
3
+ attr_reader :excludes, :skips, :stdoutput
4
+
5
+ def initialize(excludes = nil, skips = nil, stdoutput = true)
6
+ @excludes = excludes || []
7
+ @skips = (skips || []).map(&:downcase)
8
+ @stdoutput = stdoutput.nil? ? true : stdoutput
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,81 @@
1
+ module TypoChecker
2
+ class FileScanner
3
+ def initialize(typos, stdoutput)
4
+ @typos = typos
5
+ @stdoutput = stdoutput
6
+ end
7
+
8
+ def scan_file(path, result)
9
+ File.foreach(path).with_index do |line, line_number|
10
+ words = line.split(/[^a-zA-Z0-9']+/)
11
+ check_words = words.map { |word| split_function_name(word) }.flatten
12
+ check_words.each do |word|
13
+ clean_word = word.gsub(/^[^\w]+|[^\w]+$/, '')
14
+ char_index = line.index(clean_word)
15
+ check_word(clean_word, path, line_number, char_index, result)
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def check_word(word, file, line_num, char_index, result)
23
+ return unless @typos.key?(word.downcase)
24
+
25
+ corrected_word = corrected_word(word, @typos[word.downcase])
26
+ typo_details = { incorrect_word: word, correct_word: corrected_word }
27
+ typo_path = "#{file}:#{line_num + 1}:#{char_index + 1}"
28
+ path = file.sub(%r{^./}, '')
29
+
30
+ result[path] ||= {}
31
+ result[path][:typos] ||= []
32
+ line_entry = result[path][:typos].find { |entry| entry[:line] == line_num + 1 }
33
+
34
+ if line_entry
35
+ line_entry[:typos] << typo_details
36
+ else
37
+ result[path][:typos] << { line: line_num + 1, typos: [typo_details] }
38
+ end
39
+
40
+ stdout(typo_path, word, corrected_word)
41
+ end
42
+
43
+ def split_function_name(name)
44
+ # Split on capital letters or digit transitions.
45
+ # This handles cases like camelCase, PascalCase, and mixed cases with digits.
46
+ name.gsub(/([a-zA-Z])(\d)/, '\1 \2') # Between letter and digit
47
+ .gsub(/(\d)([A-Z])/, '\1 \2') # Between digit and capital letter
48
+ .gsub(/([a-z])([A-Z])/, '\1 \2') # Between lowercase and uppercase
49
+ .split(/[\s_]+/) # Split on spaces and underscores
50
+ end
51
+
52
+ def corrected_word(word, typo_correct_word)
53
+ if word == word.capitalize
54
+ typo_correct_word.capitalize
55
+ elsif word == word.upcase
56
+ typo_correct_word.upcase
57
+ else
58
+ typo_correct_word
59
+ end
60
+ end
61
+
62
+ def stdout(typo_path, word, corrected_word)
63
+ return unless @stdoutput
64
+
65
+ puts "Typo found in #{colorize_light_blue(typo_path)}: " \
66
+ "#{colorize_red(word)} -> #{colorize_green(corrected_word)}"
67
+ end
68
+
69
+ def colorize_red(text)
70
+ "\e[31m#{text}\e[0m"
71
+ end
72
+
73
+ def colorize_green(text)
74
+ "\e[32m#{text}\e[0m"
75
+ end
76
+
77
+ def colorize_light_blue(text)
78
+ "\e[94m#{text}\e[0m"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,58 @@
1
+ require 'find'
2
+
3
+ module TypoChecker
4
+ class RepositoryScanner
5
+ def initialize(repo_path, configuration)
6
+ @repo_path = repo_path
7
+ @configuration = configuration
8
+ @file_scanner = FileScanner.new(load_typos, configuration.stdoutput)
9
+ end
10
+
11
+ def scan
12
+ result = {}
13
+ Find.find(@repo_path) do |path|
14
+ next if exclude_path?(path)
15
+
16
+ @file_scanner.scan_file(path, result) if File.file?(path) && text_file?(path)
17
+ end
18
+ result.map do |path, data|
19
+ data[:typos].map do |entry|
20
+ { path: path, line: entry[:line], typos: entry[:typos] }
21
+ end
22
+ end.flatten
23
+ end
24
+
25
+ private
26
+
27
+ def exclude_path?(path)
28
+ exclude_patterns.any? { |pattern| path.match?(pattern) }
29
+ end
30
+
31
+ def exclude_patterns
32
+ @exclude_patterns ||= @configuration.excludes + [
33
+ %r{\.git/.*}, # Skip all files and directories inside .git
34
+ %r{node_modules/.*}, # Skip all files and directories inside node_modules
35
+ %r{vendor/.*}, # Skip all files and directories inside vendor
36
+ %r{tmp/.*} # Skip all files and directories inside tmp
37
+ ]
38
+ end
39
+
40
+ def text_file?(path)
41
+ excluded_extensions = %w[.log]
42
+
43
+ return false if excluded_extensions.include?(File.extname(path))
44
+
45
+ %w[
46
+ .rb .txt .md .html .css .js .py .java .php .go .swift .ts .scala .c .cpp .csharp .h .lua .pl .rs .kt
47
+ .d .r .m .sh .bash .bat .json .yaml .xml .scss .tsv .vb .ps1 .clj .elixir .f# .vhdl .verilog
48
+ .ada .ml .lisp .prolog .tcl .rexx .awk .sed .coffee .groovy .dart .haxe .zig .nim .crystal .reason .ocaml
49
+ .forth .v .xhtml .julia .racket .scheme .rust .graphql
50
+ ].include? File.extname(path)
51
+ end
52
+
53
+ def load_typos
54
+ csv_file = File.expand_path('../data/typos.csv', __dir__)
55
+ TyposLoader.new(@configuration.skips).load_typos(csv_file)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,19 @@
1
+ require 'csv'
2
+
3
+ module TypoChecker
4
+ class TyposLoader
5
+ def initialize(skips)
6
+ @skips = skips
7
+ end
8
+
9
+ def load_typos(file_path)
10
+ typos = {}
11
+ CSV.foreach(file_path, headers: false) do |row|
12
+ next if @skips.include?(row[0])
13
+
14
+ typos[row[0]] = row[1]
15
+ end
16
+ typos
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TypoChecker
4
- VERSION = '0.1.5'
4
+ VERSION = '0.1.7'
5
5
  end
data/lib/typo_checker.rb CHANGED
@@ -3,134 +3,20 @@
3
3
  require 'csv'
4
4
  require 'find'
5
5
  require 'fileutils'
6
+ require_relative 'typo_checker/configuration'
7
+ require_relative 'typo_checker/typos_loader'
8
+ require_relative 'typo_checker/file_scanner'
9
+ require_relative 'typo_checker/repository_scanner'
6
10
 
7
11
  module TypoChecker
8
12
  class Checker
9
- attr_reader :typos, :excludes, :skips, :stdoutput
10
-
11
13
  def initialize(excludes = [], skips = [], stdoutput = true)
12
- @excludes = excludes
13
- @skips = skips.map(&:downcase)
14
- @typos = load_typos
15
- @stdoutput = stdoutput
14
+ @configuration = Configuration.new(excludes, skips, stdoutput)
16
15
  end
17
16
 
18
17
  def scan_repo(repo_path = Dir.pwd)
19
- result = {}
20
- Find.find(repo_path) do |path|
21
- next if exclude_path?(path)
22
-
23
- scan_file(path, result) if File.file?(path) && text_file?(path)
24
- end
25
-
26
- result.map do |path, data|
27
- data[:typos].map do |entry|
28
- { path: path, line: entry[:line], typos: entry[:typos] }
29
- end
30
- end.flatten
31
- end
32
-
33
- private
34
-
35
- def exclude_path?(path)
36
- exclude_patterns.any? { |pattern| path.match?(pattern) }
37
- end
38
-
39
- def exclude_patterns
40
- @exclude_patterns ||= excludes + [
41
- %r{\.git/.*}, # Skip all files and directories inside .git
42
- %r{node_modules/.*}, # Skip all files and directories inside node_modules
43
- %r{vendor/.*}, # Skip all files and directories inside vendor
44
- %r{tmp/.*} # Skip all files and directories inside tmp
45
- ]
46
- end
47
-
48
- def load_typos
49
- typos = {}
50
- csv_file = File.expand_path('data/typos.csv', __dir__)
51
- CSV.foreach(csv_file, headers: false) do |row|
52
- next if skips.include?(row[0])
53
-
54
- typos[row[0]] = row[1]
55
- end
56
- typos
57
- end
58
-
59
- def text_file?(path)
60
- excluded_extensions = %w[.log]
61
-
62
- return false if excluded_extensions.include?(File.extname(path))
63
-
64
- %w[
65
- .rb .txt .md .html .css .js .py .java .php .go .swift .ts .scala .c .cpp .csharp .h .lua .pl .rs .kt
66
- .d .r .m .sh .bash .bat .json .yaml .xml .scss .tsv .vb .ps1 .clj .elixir .f# .vhdl .verilog
67
- .ada .ml .lisp .prolog .tcl .rexx .awk .sed .coffee .groovy .dart .haxe .zig .nim .crystal .reason .ocaml
68
- .forth .v .xhtml .julia .racket .scheme .rust .graphql
69
- ].include? File.extname(path)
70
- end
71
-
72
- def scan_file(path, result)
73
- File.foreach(path).with_index do |line, line_number|
74
- words = line.split(/[^a-zA-Z0-9']+/)
75
- check_words = words.map { |word| split_function_name(word) }.flatten
76
- check_words.each do |word|
77
- clean_word = word.gsub(/^[^\w]+|[^\w]+$/, '')
78
- char_index = line.index(clean_word)
79
- check_word(clean_word, path, line_number, char_index, result)
80
- end
81
- end
82
- end
83
-
84
- def check_word(word, file, line_num, char_index, result)
85
- return unless typos.key?(word.downcase)
86
-
87
- corrected_word = corrected_word(word, typos[word.downcase])
88
- typo_details = { incorrect_word: word, correct_word: corrected_word }
89
- typo_path = "#{file}:#{line_num + 1}:#{char_index + 1}"
90
- path = file.sub(%r{^./}, '')
91
-
92
- result[path] ||= {}
93
- result[path][:typos] ||= []
94
- line_entry = result[path][:typos].find { |entry| entry[:line] == line_num + 1 }
95
-
96
- if line_entry
97
- line_entry[:typos] << typo_details
98
- else
99
- result[path][:typos] << { line: line_num + 1, typos: [typo_details] }
100
- end
101
-
102
- stdout(typo_path, word, corrected_word) if stdoutput
103
- end
104
-
105
- def split_function_name(name)
106
- name.gsub(/([a-z])([A-Z])/, '\1 \2').split(/[\s_]+/)
107
- end
108
-
109
- def corrected_word(word, typo_correct_word)
110
- if word == word.capitalize
111
- typo_correct_word.capitalize
112
- elsif word == word.upcase
113
- typo_correct_word.upcase
114
- else
115
- typo_correct_word
116
- end
117
- end
118
-
119
- def stdout(typo_path, word, corrected_word)
120
- puts "Typo found in #{colorize_light_blue(typo_path)}: " \
121
- "#{colorize_red(word)} -> #{colorize_green(corrected_word)}"
122
- end
123
-
124
- def colorize_red(text)
125
- "\e[31m#{text}\e[0m"
126
- end
127
-
128
- def colorize_green(text)
129
- "\e[32m#{text}\e[0m"
130
- end
131
-
132
- def colorize_light_blue(text)
133
- "\e[94m#{text}\e[0m"
18
+ repository_scanner = RepositoryScanner.new(repo_path, @configuration)
19
+ repository_scanner.scan
134
20
  end
135
21
  end
136
22
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typo_checker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - datpmt
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-06 00:00:00.000000000 Z
10
+ date: 2025-01-17 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: thor
@@ -39,6 +39,10 @@ files:
39
39
  - lib/data/typos.csv
40
40
  - lib/typo_checker.rb
41
41
  - lib/typo_checker/cli.rb
42
+ - lib/typo_checker/configuration.rb
43
+ - lib/typo_checker/file_scanner.rb
44
+ - lib/typo_checker/repository_scanner.rb
45
+ - lib/typo_checker/typos_loader.rb
42
46
  - lib/typo_checker/version.rb
43
47
  homepage: https://rubygems.org/gems/typo_checker
44
48
  licenses: