react-manifest-rails 0.2.16 → 0.2.18
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/lib/react_manifest/scanner.rb +57 -4
- data/lib/react_manifest/version.rb +1 -1
- data/lib/react_manifest/view_helpers.rb +4 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d200b72fea50e032cb2b8d812482ae6c65550029e129455d0ef7b81ff14b1077
|
|
4
|
+
data.tar.gz: 4a22e1b28aef9c55e8a081b7874bc70104cd4dabec4a236f168b909bd2bebeb8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7e065d309bd9ad9e3f8ebeb25dbb22b6cea11771d27283efafd85fe9f16d5ee186753118906fa38f20e86441e334540bb332e2aea31c48e4d537ecf3f1748fe0
|
|
7
|
+
data.tar.gz: 6d094eb1f61e1f3b67929b64fb1a7c99e0fa9e9386db1dcaabcb010f9a88b143508af4e4ffc36870cee4c7fc175460bf6d29ba9c2bbd07b60a35a06708621cb6
|
|
@@ -15,6 +15,7 @@ module ReactManifest
|
|
|
15
15
|
# and produces per-controller lists of referenced shared files.
|
|
16
16
|
#
|
|
17
17
|
# Phase 3 — emits non-fatal warnings.
|
|
18
|
+
# rubocop:disable Metrics/ClassLength
|
|
18
19
|
class Scanner
|
|
19
20
|
# Patterns to detect symbol definitions (CommonJS and ES module style)
|
|
20
21
|
DEFINITION_PATTERNS = [
|
|
@@ -56,21 +57,24 @@ module ReactManifest
|
|
|
56
57
|
Object Array String Number Boolean Symbol Map Set WeakMap
|
|
57
58
|
].freeze
|
|
58
59
|
|
|
59
|
-
Result = Struct.new(:symbol_index, :controller_usages, :warnings, keyword_init: true)
|
|
60
|
+
Result = Struct.new(:symbol_index, :controller_usages, :warnings, :shared_violations, keyword_init: true)
|
|
60
61
|
|
|
61
62
|
def initialize(config = ReactManifest.configuration)
|
|
62
63
|
@config = config
|
|
63
64
|
end
|
|
64
65
|
|
|
66
|
+
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/PerceivedComplexity
|
|
65
67
|
def scan(classification)
|
|
66
68
|
warnings = []
|
|
67
69
|
symbol_index = {}
|
|
68
70
|
|
|
69
71
|
# Phase 1a: index symbols from shared dirs
|
|
72
|
+
shared_file_paths = {} # file_path => relative_require_path for all shared files
|
|
70
73
|
classification.shared_dirs.each do |shared_dir|
|
|
71
74
|
js_files_in(shared_dir[:path]).each do |file_path|
|
|
72
75
|
relative = relative_require_path(file_path)
|
|
73
|
-
|
|
76
|
+
shared_file_paths[file_path] = relative
|
|
77
|
+
symbols = extract_definitions(file_path)
|
|
74
78
|
symbols.each do |sym|
|
|
75
79
|
if symbol_index.key?(sym)
|
|
76
80
|
warnings << "Duplicate symbol '#{sym}' in #{relative} (already from #{symbol_index[sym]})"
|
|
@@ -98,8 +102,24 @@ module ReactManifest
|
|
|
98
102
|
symbol_index[sym] = require_path
|
|
99
103
|
end
|
|
100
104
|
|
|
105
|
+
# Phase 1d: build controller (app-dir) symbol index for violation detection
|
|
106
|
+
controller_symbol_index = {}
|
|
107
|
+
classification.controller_dirs.each do |ctrl|
|
|
108
|
+
js_files_in(ctrl[:path]).each do |file_path|
|
|
109
|
+
extract_definitions(file_path).each do |sym|
|
|
110
|
+
controller_symbol_index[sym] ||= {
|
|
111
|
+
file: relative_require_path(file_path),
|
|
112
|
+
controller: ctrl[:name]
|
|
113
|
+
}
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
101
118
|
$stdout.puts "[ReactManifest] Shared symbol index: #{symbol_index.size} symbols indexed" if @config.verbose?
|
|
102
119
|
|
|
120
|
+
# Phase 1e: detect shared files that use app-dir (controller) symbols
|
|
121
|
+
shared_violations = detect_shared_violations(shared_file_paths, controller_symbol_index, warnings)
|
|
122
|
+
|
|
103
123
|
# Phase 2: scan controller dirs for usage
|
|
104
124
|
controller_usages = {}
|
|
105
125
|
|
|
@@ -126,9 +146,11 @@ module ReactManifest
|
|
|
126
146
|
Result.new(
|
|
127
147
|
symbol_index: symbol_index,
|
|
128
148
|
controller_usages: controller_usages,
|
|
129
|
-
warnings: warnings
|
|
149
|
+
warnings: warnings,
|
|
150
|
+
shared_violations: shared_violations
|
|
130
151
|
)
|
|
131
152
|
end
|
|
153
|
+
# rubocop:enable Metrics/MethodLength,Metrics/AbcSize,Metrics/PerceivedComplexity
|
|
132
154
|
|
|
133
155
|
private
|
|
134
156
|
|
|
@@ -177,8 +199,38 @@ module ReactManifest
|
|
|
177
199
|
"'#{ctrl_name}_<action>.js.jsx' naming convention"
|
|
178
200
|
end
|
|
179
201
|
|
|
202
|
+
def detect_shared_violations(shared_file_paths, controller_symbol_index, warnings)
|
|
203
|
+
violations = []
|
|
204
|
+
shared_file_paths.each do |file_path, relative|
|
|
205
|
+
content = begin
|
|
206
|
+
File.read(file_path, encoding: "utf-8")
|
|
207
|
+
rescue Errno::ENOENT, Errno::EACCES, Encoding::InvalidByteSequenceError
|
|
208
|
+
next
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
local_syms = Set.new
|
|
212
|
+
DEFINITION_PATTERNS.each { |p| content.scan(p) { |m| local_syms << m[0] } }
|
|
213
|
+
|
|
214
|
+
[PASCAL_TOKEN_PATTERN, HOOK_TOKEN_PATTERN].each do |pattern|
|
|
215
|
+
content.scan(pattern) do |match|
|
|
216
|
+
sym = match[0]
|
|
217
|
+
next if local_syms.include?(sym)
|
|
218
|
+
next unless controller_symbol_index.key?(sym)
|
|
219
|
+
|
|
220
|
+
info = controller_symbol_index[sym]
|
|
221
|
+
violations << { shared_file: relative, symbol: sym,
|
|
222
|
+
controller: info[:controller], app_file: info[:file] }
|
|
223
|
+
warnings << "Shared file '#{relative}' uses app-dir symbol '#{sym}' " \
|
|
224
|
+
"(from ux/app/#{info[:controller]}). " \
|
|
225
|
+
"Move '#{sym}' to a shared dir or the shared file will be incomplete."
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
violations
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Count how many controllers use each shared file
|
|
180
233
|
def emit_fanout_warnings(controller_usages, warnings)
|
|
181
|
-
# Count how many controllers use each shared file
|
|
182
234
|
fanout = Hash.new(0)
|
|
183
235
|
controller_usages.each_value do |files|
|
|
184
236
|
files.each { |f| fanout[f] += 1 }
|
|
@@ -270,4 +322,5 @@ module ReactManifest
|
|
|
270
322
|
Rails.root.join(path).to_s
|
|
271
323
|
end
|
|
272
324
|
end
|
|
325
|
+
# rubocop:enable Metrics/ClassLength
|
|
273
326
|
end
|
|
@@ -21,6 +21,10 @@ module ReactManifest
|
|
|
21
21
|
bundles = ReactManifest.resolve_bundles(ctrl)
|
|
22
22
|
return "".html_safe if bundles.empty?
|
|
23
23
|
|
|
24
|
+
# Record emitted bundles so react_component doesn't re-emit them.
|
|
25
|
+
emitted = (@_react_manifest_emitted_bundles ||= [])
|
|
26
|
+
bundles.each { |b| emitted << b unless emitted.include?(b) }
|
|
27
|
+
|
|
24
28
|
asset_names = bundles.map { |bundle| "#{bundle}.js" }
|
|
25
29
|
javascript_include_tag(*asset_names, extname: false, **html_options)
|
|
26
30
|
end
|