partial_inspector 0.1.1 → 1.0.0
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/README.md +38 -0
- data/lib/partial_inspector/reporter.rb +17 -17
- data/lib/partial_inspector/scanner.rb +5 -0
- data/lib/partial_inspector/unused_partials.rb +73 -0
- data/lib/partial_inspector/used_partials.rb +125 -0
- data/lib/partial_inspector/utils.rb +1 -98
- data/lib/partial_inspector/version.rb +1 -1
- data/lib/partial_inspector.rb +0 -1
- metadata +5 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4da9f1dbf7e24e31a2ff0861e6a953077a40c3b8ddf8c32943b25b0dea006bac
|
4
|
+
data.tar.gz: be3e444cc43d7b41bb33806c426adeff4f155dce8d38273eac0a8241b8f52f84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6fea5f0e342ae64204796a40d9e210b3fbc9d61634d837be9f3adc0065d29dbb6c7f3ba70ebc175da071e321f80d453381ab2f17dfe73beec19e40e2e36e634
|
7
|
+
data.tar.gz: aab718cd76499900275cf18c41eba1ee46d6b5bf4d47648998d6b5bd73606265888bc22a8113805beedf32a2f7fc1dee58793422ea37f06d4256125c7e1a7584
|
data/README.md
CHANGED
@@ -1 +1,39 @@
|
|
1
1
|
# Partial Inspector
|
2
|
+
A tiny, developer-focused gem to help you find where your Rails partials are used.
|
3
|
+
|
4
|
+
When working on large Rails projects, it's easy to lose track of where a partial is rendered throughout the codebase. **partial_inspector** scans your project and shows exactly which files render a given partial, making it much easier to refactor, test or remove unused partials confidently.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
```
|
9
|
+
gem install partial_inspector
|
10
|
+
```
|
11
|
+
|
12
|
+
|
13
|
+
## How it works?
|
14
|
+
1. Open irb
|
15
|
+
2. Require the gem:
|
16
|
+
|
17
|
+
```
|
18
|
+
require "partial_inspector"
|
19
|
+
```
|
20
|
+
|
21
|
+
### Find where a partial is used
|
22
|
+
1. Run the scanner:
|
23
|
+
|
24
|
+
```
|
25
|
+
PartialInspector.scanner.inspect_files_rendering_partial('path/to/partial')
|
26
|
+
```
|
27
|
+
2. Example Output
|
28
|
+
|
29
|
+
<img width="803" alt="image" src="https://github.com/user-attachments/assets/9008c2c1-d6ea-4497-945b-1e47823208fc" />
|
30
|
+
|
31
|
+
### Find unused partials
|
32
|
+
1. Run the scanner:
|
33
|
+
|
34
|
+
```
|
35
|
+
PartialInspector.scanner.scan_unused_partials
|
36
|
+
```
|
37
|
+
|
38
|
+
|
39
|
+
|
@@ -1,8 +1,10 @@
|
|
1
|
-
require_relative "
|
1
|
+
require_relative "used_partials"
|
2
|
+
require_relative "unused_partials"
|
2
3
|
|
3
4
|
module PartialInspector
|
4
5
|
class Reporter
|
5
|
-
include PartialInspector::
|
6
|
+
include PartialInspector::UsedPartials
|
7
|
+
include PartialInspector::UnusedPartials
|
6
8
|
|
7
9
|
def report_files_rendering_partial(partial_path)
|
8
10
|
files = base_scanner(partial_path)
|
@@ -27,24 +29,22 @@ module PartialInspector
|
|
27
29
|
return
|
28
30
|
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
files.each do |file|
|
34
|
-
same_files = files.filter { |f| f[:file] == file[:file] }
|
32
|
+
def report_unused_partials
|
33
|
+
partials = inspect_unused_partials
|
34
|
+
unused_partials = partials[:unused_partials]
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
puts "\n\e[36mSEARCH SUMMARY\e[0m"
|
37
|
+
puts "\e[35mTOTAL PARTIALS\e[0m: \e[32m#{partials[:total_partials]}\e[0m"
|
38
|
+
puts "\e[35mUSED PARTIALS\e[0m: \e[32m#{partials[:used_partials]}\e[0m"
|
39
|
+
puts "\e[35mUNUSED PARTIALS\e[0m: \e[32m#{unused_partials.size}\e[0m"
|
40
|
+
|
41
|
+
unless unused_partials.empty?
|
42
|
+
puts "\n\e[36mDETAILS\e[0m"
|
43
|
+
unused_partials.each do |partial|
|
44
|
+
puts partial
|
40
45
|
end
|
41
46
|
end
|
42
|
-
|
43
|
-
files.each do |file|
|
44
|
-
results[file[:file].to_sym] = [{ line_number: file[:line_number], line_content: file[:line_content] }]
|
45
|
-
end
|
46
|
-
|
47
|
-
results
|
47
|
+
return
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative 'utils'
|
2
|
+
|
3
|
+
module PartialInspector
|
4
|
+
module UnusedPartials
|
5
|
+
include PartialInspector::Utils
|
6
|
+
|
7
|
+
private
|
8
|
+
def inspect_unused_partials
|
9
|
+
partials = Dir.glob("app/views/**/_*.*erb")
|
10
|
+
partial_paths_data = format_partial_paths_for_scanning(partials)
|
11
|
+
unused_partials = []
|
12
|
+
puts "\e[32mScanning...\e[0m\n"
|
13
|
+
partial_paths_data.each do |path_data|
|
14
|
+
unless full_path_used(path_data[:full_path]) || partial_name_used(path_data[:full_path])
|
15
|
+
unused_partials << path_data[:partial]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
{
|
20
|
+
total_partials: partials.size,
|
21
|
+
unused_partials: unused_partials,
|
22
|
+
used_partials: partials.size - unused_partials.size
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def format_partial_paths_for_scanning(partials)
|
27
|
+
partial_paths_for_rendering = []
|
28
|
+
partials.each do |partial|
|
29
|
+
partial_paths_for_rendering << extract_complete_partial_path(partial)
|
30
|
+
end
|
31
|
+
|
32
|
+
partial_paths_for_rendering
|
33
|
+
end
|
34
|
+
|
35
|
+
def extract_complete_partial_path(partial)
|
36
|
+
full_path = partial.split('app/views/')[1]
|
37
|
+
formatted_path = ""
|
38
|
+
path_components = full_path.split('/')
|
39
|
+
path_components[-1] = extract_partial_name(path_components[-1])
|
40
|
+
path_components.each do |path_component|
|
41
|
+
formatted_path += "#{path_component}/"
|
42
|
+
end
|
43
|
+
formatted_path = formatted_path[0..-2] if formatted_path[-1] == '/'
|
44
|
+
|
45
|
+
{ partial: partial, full_path: formatted_path, partial_name: path_components[-1] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def full_path_used(partial_path)
|
49
|
+
files = Dir.glob("app/**/*.{rb,html.erb,js.erb,turbo_stream.erb}")
|
50
|
+
files.each do |file|
|
51
|
+
file_content = File.readlines(file)
|
52
|
+
file_content.each do |line|
|
53
|
+
return true if line.include?("'#{partial_path}'") || line.include?("\"#{partial_path}\"")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
|
59
|
+
def partial_name_used(partial_path)
|
60
|
+
partial_dir = build_partial_base_dir_path(partial_path)
|
61
|
+
partial_name = extract_partial_name(partial_path)
|
62
|
+
|
63
|
+
files = Dir.glob("app/views/#{partial_dir}*.*.erb")
|
64
|
+
files.each do |file|
|
65
|
+
file_content = File.readlines(file)
|
66
|
+
file_content.each do |line|
|
67
|
+
return true if line.include?("'#{partial_name}'") || line.include?("\"#{partial_name}\"")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require_relative 'utils'
|
2
|
+
|
3
|
+
module PartialInspector
|
4
|
+
module UsedPartials
|
5
|
+
include PartialInspector::Utils
|
6
|
+
|
7
|
+
private
|
8
|
+
def base_scanner(partial_path)
|
9
|
+
return [] if partial_path.nil? || partial_path == ''
|
10
|
+
lines = []
|
11
|
+
|
12
|
+
files = Dir.glob("app/**/*.{rb,html.erb,js.erb,turbo_stream.erb}")
|
13
|
+
files.each do |file|
|
14
|
+
file_content = File.readlines(file)
|
15
|
+
file_content.each_with_index do |line, index|
|
16
|
+
if (line.include?('render') || line.include?('partial:')) && check_partial_exists(line, partial_path)
|
17
|
+
lines << {
|
18
|
+
file: file,
|
19
|
+
line_number: index + 1,
|
20
|
+
line_content: highlight_partial_form_content(partial_path, line.strip)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
partial_dir = build_partial_base_dir_path(partial_path)
|
27
|
+
partial_name = extract_partial_name(partial_path)
|
28
|
+
|
29
|
+
lines + check_partial_against_name(partial_dir, partial_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_partial_exists(line, partial)
|
33
|
+
partial_path = ""
|
34
|
+
line_content = line.split(' ')
|
35
|
+
line_content.each_with_index do |value, index|
|
36
|
+
if line.include?("render partial:") && value == "render"
|
37
|
+
partial_path = line_content[index + 2]
|
38
|
+
break
|
39
|
+
elsif value == "render"
|
40
|
+
partial_path = line_content[index + 1]
|
41
|
+
break
|
42
|
+
elsif value == "partial:"
|
43
|
+
partial_path = line_content[index + 1]
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
if partial_path[0] == "\""
|
48
|
+
partial_path = partial_path[1..-2]
|
49
|
+
partial_path = partial_path[0..-2] if partial_path[-1] == '"'
|
50
|
+
elsif partial_path[0] == "'"
|
51
|
+
partial_path = partial_path[1..-2]
|
52
|
+
partial_path = partial_path[0..-2] if partial_path[-1] == "'"
|
53
|
+
end
|
54
|
+
|
55
|
+
partial_path == partial
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_path(path_components)
|
59
|
+
path = ''
|
60
|
+
path_components.each do |path_component|
|
61
|
+
path = path+"#{path_component}/"
|
62
|
+
end
|
63
|
+
|
64
|
+
path[0..-2]
|
65
|
+
end
|
66
|
+
|
67
|
+
def check_partial_against_name(partial_dir, partial_name)
|
68
|
+
lines = []
|
69
|
+
|
70
|
+
Dir.glob("app/views/#{partial_dir}*.*.erb").each do |file|
|
71
|
+
file_content = File.readlines(file)
|
72
|
+
file_content.each_with_index do |line, index|
|
73
|
+
if line.include?('render') && check_partial_exists(line, partial_name)
|
74
|
+
lines << {
|
75
|
+
file: file,
|
76
|
+
line_number: index + 1,
|
77
|
+
line_content: highlight_partial_form_content(partial_name, line.strip)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
lines
|
84
|
+
end
|
85
|
+
|
86
|
+
def highlight_partial_form_content(partial_path, content)
|
87
|
+
if content.include?("'#{partial_path}'")
|
88
|
+
content_components = content.split("'#{partial_path}'")
|
89
|
+
result = if content_components.size < 2
|
90
|
+
content_components[0]+"\e[44m\e[32m'#{partial_path}'\e[0m\e[0m"
|
91
|
+
else
|
92
|
+
content_components[0]+"\e[44m\e[32m'#{partial_path}'\e[0m\e[0m"+content_components[1]
|
93
|
+
end
|
94
|
+
return result
|
95
|
+
elsif content.include?("\"#{partial_path}\"")
|
96
|
+
content_components = content.split("\"#{partial_path}\"")
|
97
|
+
result = if content_components.size < 2
|
98
|
+
content_components[0]+"\e[44m\e[32m\"#{partial_path}\"\e[0m\e[0m"
|
99
|
+
else
|
100
|
+
content_components[0]+"\e[44m\e[32m\"#{partial_path}\"\e[0m\e[0m"+content_components[1]
|
101
|
+
end
|
102
|
+
return result
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def combine_unique_files(files)
|
107
|
+
results = {}
|
108
|
+
files.each do |file|
|
109
|
+
same_files = files.filter { |f| f[:file] == file[:file] }
|
110
|
+
|
111
|
+
same_files.each do |same_file|
|
112
|
+
files.delete(same_file)
|
113
|
+
results[same_file[:file].to_sym] = [] if results[same_file[:file].to_sym] == nil
|
114
|
+
results[same_file[:file].to_sym] << { line_number: same_file[:line_number], line_content: file[:line_content] }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
files.each do |file|
|
119
|
+
results[file[:file].to_sym] = [{ line_number: file[:line_number], line_content: file[:line_content] }]
|
120
|
+
end
|
121
|
+
|
122
|
+
results
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -1,30 +1,7 @@
|
|
1
1
|
module PartialInspector
|
2
2
|
module Utils
|
3
|
-
private
|
4
|
-
def base_scanner(partial_path)
|
5
|
-
return [] if partial_path.nil? || partial_path == ''
|
6
|
-
lines = []
|
7
|
-
|
8
|
-
files = Dir.glob("app/**/*.{rb,html.erb,js.erb,turbo_stream.erb}")
|
9
|
-
files.each do |file|
|
10
|
-
file_content = File.readlines(file)
|
11
|
-
file_content.each_with_index do |line, index|
|
12
|
-
if (line.include?('render') || line.include?('partial:')) && check_partial_exists(line, partial_path)
|
13
|
-
lines << {
|
14
|
-
file: file,
|
15
|
-
line_number: index + 1,
|
16
|
-
line_content: highlight_partial_form_content(partial_path, line.strip)
|
17
|
-
}
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
partial_dir = build_partial_base_dir_path(partial_path)
|
23
|
-
partial_name = extract_partial_name(partial_path)
|
24
|
-
|
25
|
-
lines + check_partial_against_name(partial_dir, partial_name)
|
26
|
-
end
|
27
3
|
|
4
|
+
private
|
28
5
|
def extract_partial_file_name(partial_path)
|
29
6
|
file_name = partial_path.split('/').last
|
30
7
|
file_name
|
@@ -37,41 +14,6 @@ module PartialInspector
|
|
37
14
|
partial_name
|
38
15
|
end
|
39
16
|
|
40
|
-
def check_partial_exists(line, partial)
|
41
|
-
partial_path = ""
|
42
|
-
line_content = line.split(' ')
|
43
|
-
line_content.each_with_index do |value, index|
|
44
|
-
if line.include?("render partial:") && value == "render"
|
45
|
-
partial_path = line_content[index + 2]
|
46
|
-
break
|
47
|
-
elsif value == "render"
|
48
|
-
partial_path = line_content[index + 1]
|
49
|
-
break
|
50
|
-
elsif value == "partial:"
|
51
|
-
partial_path = line_content[index + 1]
|
52
|
-
break
|
53
|
-
end
|
54
|
-
end
|
55
|
-
if partial_path[0] == "\""
|
56
|
-
partial_path = partial_path[1..-2]
|
57
|
-
partial_path = partial_path[0..-2] if partial_path[-1] == '"'
|
58
|
-
elsif partial_path[0] == "'"
|
59
|
-
partial_path = partial_path[1..-2]
|
60
|
-
partial_path = partial_path[0..-2] if partial_path[-1] == "'"
|
61
|
-
end
|
62
|
-
|
63
|
-
partial_path == partial
|
64
|
-
end
|
65
|
-
|
66
|
-
def build_path(path_components)
|
67
|
-
path = ''
|
68
|
-
path_components.each do |path_component|
|
69
|
-
path = path+"#{path_component}/"
|
70
|
-
end
|
71
|
-
|
72
|
-
path[0..-2]
|
73
|
-
end
|
74
|
-
|
75
17
|
def build_partial_base_dir_path(partial_path)
|
76
18
|
path_components = partial_path.split('/')
|
77
19
|
path = ''
|
@@ -82,44 +24,5 @@ module PartialInspector
|
|
82
24
|
|
83
25
|
path
|
84
26
|
end
|
85
|
-
|
86
|
-
def check_partial_against_name(partial_dir, partial_name)
|
87
|
-
lines = []
|
88
|
-
|
89
|
-
Dir.glob("app/views/#{partial_dir}*.*.erb").each do |file|
|
90
|
-
file_content = File.readlines(file)
|
91
|
-
file_content.each_with_index do |line, index|
|
92
|
-
if line.include?('render') && check_partial_exists(line, partial_name)
|
93
|
-
lines << {
|
94
|
-
file: file,
|
95
|
-
line_number: index + 1,
|
96
|
-
line_content: highlight_partial_form_content(partial_name, line.strip)
|
97
|
-
}
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
lines
|
103
|
-
end
|
104
|
-
|
105
|
-
def highlight_partial_form_content(partial_path, content)
|
106
|
-
if content.include?("'#{partial_path}'")
|
107
|
-
content_components = content.split("'#{partial_path}'")
|
108
|
-
result = if content_components.size < 2
|
109
|
-
content_components[0]+"\e[44m\e[32m'#{partial_path}'\e[0m\e[0m"
|
110
|
-
else
|
111
|
-
content_components[0]+"\e[44m\e[32m'#{partial_path}'\e[0m\e[0m"+content_components[1]
|
112
|
-
end
|
113
|
-
return result
|
114
|
-
elsif content.include?("\"#{partial_path}\"")
|
115
|
-
content_components = content.split("\"#{partial_path}\"")
|
116
|
-
result = if content_components.size < 2
|
117
|
-
content_components[0]+"\e[44m\e[32m\"#{partial_path}\"\e[0m\e[0m"
|
118
|
-
else
|
119
|
-
content_components[0]+"\e[44m\e[32m\"#{partial_path}\"\e[0m\e[0m"+content_components[1]
|
120
|
-
end
|
121
|
-
return result
|
122
|
-
end
|
123
|
-
end
|
124
27
|
end
|
125
28
|
end
|
data/lib/partial_inspector.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: partial_inspector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SalihaShahid
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
|
-
description:
|
14
12
|
email:
|
15
13
|
- salihashahid1102@gmail.com
|
16
14
|
executables: []
|
@@ -22,6 +20,8 @@ files:
|
|
22
20
|
- lib/partial_inspector.rb
|
23
21
|
- lib/partial_inspector/reporter.rb
|
24
22
|
- lib/partial_inspector/scanner.rb
|
23
|
+
- lib/partial_inspector/unused_partials.rb
|
24
|
+
- lib/partial_inspector/used_partials.rb
|
25
25
|
- lib/partial_inspector/utils.rb
|
26
26
|
- lib/partial_inspector/version.rb
|
27
27
|
- sig/partial_inspector.rbs
|
@@ -29,7 +29,6 @@ homepage: https://github.com/SalihaShahid/partial_inspector
|
|
29
29
|
licenses:
|
30
30
|
- MIT
|
31
31
|
metadata: {}
|
32
|
-
post_install_message:
|
33
32
|
rdoc_options: []
|
34
33
|
require_paths:
|
35
34
|
- lib
|
@@ -44,8 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
43
|
- !ruby/object:Gem::Version
|
45
44
|
version: '0'
|
46
45
|
requirements: []
|
47
|
-
rubygems_version: 3.
|
48
|
-
signing_key:
|
46
|
+
rubygems_version: 3.6.7
|
49
47
|
specification_version: 4
|
50
48
|
summary: Partial Inspector
|
51
49
|
test_files: []
|