react-manifest-rails 0.2.34 → 0.3.1
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/CHANGELOG.md +87 -0
- data/README.md +7 -2
- data/lib/react_manifest/ast_extractor.rb +11 -0
- data/lib/react_manifest/component_index.rb +136 -0
- data/lib/react_manifest/configuration.rb +19 -0
- data/lib/react_manifest/generator.rb +477 -83
- data/lib/react_manifest/gitignore_patcher.rb +81 -0
- data/lib/react_manifest/railtie.rb +6 -0
- data/lib/react_manifest/symbol_extractor.rb +27 -0
- data/lib/react_manifest/vendor/ast_extractor.js +11 -11
- data/lib/react_manifest/vendor/build/entry.js +32 -0
- data/lib/react_manifest/version.rb +1 -1
- data/lib/react_manifest/view_helpers.rb +42 -5
- data/lib/react_manifest.rb +31 -75
- data/tasks/react_manifest.rake +37 -0
- metadata +17 -15
|
@@ -52,6 +52,31 @@ function definitionsFromAst(ast) {
|
|
|
52
52
|
return [...new Set(defs)];
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// Top-level const/let/class binding names of any casing, including destructured
|
|
56
|
+
// ones. Only these throw "Identifier already declared" when two classic scripts
|
|
57
|
+
// share a global lexical scope; var/function redeclaration is legal, so skipped.
|
|
58
|
+
function lexicalBindingsFromAst(ast) {
|
|
59
|
+
const names = [];
|
|
60
|
+
const collect = (p) => {
|
|
61
|
+
if (!p) return;
|
|
62
|
+
switch (p.type) {
|
|
63
|
+
case "Identifier": names.push(p.name); break;
|
|
64
|
+
case "ObjectPattern": p.properties.forEach((prop) => collect(prop.type === "RestElement" ? prop.argument : prop.value)); break;
|
|
65
|
+
case "ArrayPattern": p.elements.forEach(collect); break;
|
|
66
|
+
case "AssignmentPattern": collect(p.left); break;
|
|
67
|
+
case "RestElement": collect(p.argument); break;
|
|
68
|
+
default: break;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
for (const node of ast.body) {
|
|
72
|
+
const decl = node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" ? node.declaration : node;
|
|
73
|
+
if (!decl) continue;
|
|
74
|
+
if (decl.type === "VariableDeclaration" && decl.kind !== "var") decl.declarations.forEach((d) => collect(d.id));
|
|
75
|
+
else if (decl.type === "ClassDeclaration") collect(decl.id);
|
|
76
|
+
}
|
|
77
|
+
return [...new Set(names)];
|
|
78
|
+
}
|
|
79
|
+
|
|
55
80
|
// Real reference positions only: JSX element names, call/new callees, and
|
|
56
81
|
// generic identifier references (prop values, array elements, assignments,
|
|
57
82
|
// arguments) — explicitly excluding JSXText and StringLiteral content. This
|
|
@@ -124,6 +149,13 @@ globalThis.__astExtractor = {
|
|
|
124
149
|
return { success: false, error: errorInfo(e) };
|
|
125
150
|
}
|
|
126
151
|
},
|
|
152
|
+
extractLexicalBindings(content) {
|
|
153
|
+
try {
|
|
154
|
+
return { success: true, bindings: lexicalBindingsFromAst(parse(content)) };
|
|
155
|
+
} catch (e) {
|
|
156
|
+
return { success: false, error: errorInfo(e) };
|
|
157
|
+
}
|
|
158
|
+
},
|
|
127
159
|
extractUsages(content) {
|
|
128
160
|
try {
|
|
129
161
|
const ast = parse(content);
|
|
@@ -10,25 +10,36 @@ module ReactManifest
|
|
|
10
10
|
# 3. For namespaced controllers (admin/users): checks ux_admin_users, then ux_admin
|
|
11
11
|
# 4. Returns "" for pure ERB/HAML pages with no matching bundle, or when
|
|
12
12
|
# called outside a controller context (mailers, engines, etc.)
|
|
13
|
+
#
|
|
14
|
+
# Rails renders the action template before the layout, so react_component
|
|
15
|
+
# tags land in the body first. react_bundle_tag hoists them into its own
|
|
16
|
+
# output (the layout's <head>) so Turbolinks never re-evaluates a body script.
|
|
13
17
|
module ViewHelpers
|
|
18
|
+
INLINE_BUNDLE_TAG = %r{<script\b[^>]*\sdata-react-manifest="([^"]*)"[^>]*></script>}
|
|
19
|
+
|
|
14
20
|
def react_bundle_tag(**html_options)
|
|
15
21
|
# controller_path is not available in all view contexts (mailers, engines,
|
|
16
22
|
# views rendered outside a request). Fall back gracefully rather than raising.
|
|
17
23
|
ctrl = respond_to?(:controller_path, true) ? controller_path : nil
|
|
18
24
|
return "".html_safe if ctrl.nil?
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
emitted = emitted_bundles
|
|
27
|
+
hoisted = hoist_inline_bundle_tags
|
|
28
|
+
emitted.reject! { |e| hoisted.any? { |h| canonical_bundle_name(h) == canonical_bundle_name(e) } }
|
|
29
|
+
|
|
30
|
+
bundles = (ReactManifest.resolve_bundles(ctrl) + hoisted).uniq { |b| canonical_bundle_name(b) }
|
|
21
31
|
return "".html_safe if bundles.empty?
|
|
22
32
|
|
|
23
33
|
# Record emitted bundles so react_component doesn't re-emit them.
|
|
24
|
-
emitted = emitted_bundles
|
|
25
34
|
fresh_bundles = bundles.reject { |b| emitted_bundle?(emitted, b) }
|
|
26
35
|
return "".html_safe if fresh_bundles.empty?
|
|
27
36
|
|
|
28
37
|
fresh_bundles.each { |b| emitted << b }
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
tags = fresh_bundles.map do |bundle|
|
|
40
|
+
javascript_include_tag("#{bundle}.js", extname: false, **bundle_tag_options(bundle, html_options))
|
|
41
|
+
end
|
|
42
|
+
safe_join(tags, "\n")
|
|
32
43
|
end
|
|
33
44
|
|
|
34
45
|
# react-rails integration:
|
|
@@ -48,7 +59,7 @@ module ReactManifest
|
|
|
48
59
|
next if emitted_bundle?(emitted, bundle)
|
|
49
60
|
|
|
50
61
|
emitted << bundle
|
|
51
|
-
javascript_include_tag("#{bundle}.js", extname: false)
|
|
62
|
+
javascript_include_tag("#{bundle}.js", extname: false, data: { react_manifest: bundle })
|
|
52
63
|
end
|
|
53
64
|
|
|
54
65
|
return html if new_tags.empty?
|
|
@@ -58,6 +69,32 @@ module ReactManifest
|
|
|
58
69
|
|
|
59
70
|
private
|
|
60
71
|
|
|
72
|
+
# Turbolinks 5 full-reloads when the tracked head elements differ between pages.
|
|
73
|
+
# ux_shared is identical on every page, so tracking it forces one reload per deploy;
|
|
74
|
+
# tracking controller bundles would reload on every cross-controller visit.
|
|
75
|
+
def bundle_tag_options(bundle, html_options)
|
|
76
|
+
shared = canonical_bundle_name(ReactManifest.configuration.shared_bundle)
|
|
77
|
+
return html_options unless canonical_bundle_name(bundle) == shared
|
|
78
|
+
|
|
79
|
+
html_options.merge(data: (html_options[:data] || {}).merge(turbolinks_track: "reload"))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Strips the inline tags react_component already wrote into the rendered
|
|
83
|
+
# template (and content_for) buffers; returns their bundle names in order.
|
|
84
|
+
def hoist_inline_bundle_tags
|
|
85
|
+
return [] unless respond_to?(:view_flow, true) && view_flow
|
|
86
|
+
|
|
87
|
+
names = []
|
|
88
|
+
view_flow.content.each_key do |key|
|
|
89
|
+
html = view_flow.get(key).to_s
|
|
90
|
+
next unless html.include?("data-react-manifest")
|
|
91
|
+
|
|
92
|
+
names.concat(html.scan(INLINE_BUNDLE_TAG).flatten)
|
|
93
|
+
view_flow.set(key, html.gsub(INLINE_BUNDLE_TAG, "").html_safe)
|
|
94
|
+
end
|
|
95
|
+
names
|
|
96
|
+
end
|
|
97
|
+
|
|
61
98
|
def emitted_bundle?(emitted, bundle)
|
|
62
99
|
canonical = canonical_bundle_name(bundle)
|
|
63
100
|
emitted.any? { |existing| canonical_bundle_name(existing) == canonical }
|
data/lib/react_manifest.rb
CHANGED
|
@@ -7,6 +7,7 @@ require "react_manifest/configuration"
|
|
|
7
7
|
require "react_manifest/path_utils"
|
|
8
8
|
require "react_manifest/tree_classifier"
|
|
9
9
|
require "react_manifest/symbol_extractor"
|
|
10
|
+
require "react_manifest/component_index"
|
|
10
11
|
require "react_manifest/scanner"
|
|
11
12
|
require "react_manifest/dependency_map"
|
|
12
13
|
require "react_manifest/generator"
|
|
@@ -14,11 +15,11 @@ require "react_manifest/application_analyzer"
|
|
|
14
15
|
require "react_manifest/application_migrator"
|
|
15
16
|
require "react_manifest/layout_patcher"
|
|
16
17
|
require "react_manifest/sprockets_manifest_patcher"
|
|
18
|
+
require "react_manifest/gitignore_patcher"
|
|
17
19
|
require "react_manifest/watcher"
|
|
18
20
|
require "react_manifest/reporter"
|
|
19
21
|
require "react_manifest/view_helpers"
|
|
20
22
|
|
|
21
|
-
# rubocop:disable Metrics/ModuleLength
|
|
22
23
|
module ReactManifest
|
|
23
24
|
class << self
|
|
24
25
|
def configuration
|
|
@@ -55,10 +56,7 @@ module ReactManifest
|
|
|
55
56
|
bundles << shared if shared
|
|
56
57
|
|
|
57
58
|
# 2. always_include bundles (e.g. ux_main)
|
|
58
|
-
config
|
|
59
|
-
resolved = resolve_bundle_reference(config, b)
|
|
60
|
-
bundles << resolved if resolved && !bundles.include?(resolved)
|
|
61
|
-
end
|
|
59
|
+
append_always_include(config, bundles)
|
|
62
60
|
|
|
63
61
|
# 3. Controller-specific bundle
|
|
64
62
|
# Try fully-namespaced first: admin/users → ux_admin_users
|
|
@@ -74,6 +72,18 @@ module ReactManifest
|
|
|
74
72
|
bundles
|
|
75
73
|
end
|
|
76
74
|
|
|
75
|
+
# Ensure the manifest dir is gitignored (and .keep present). Honors
|
|
76
|
+
# config.manage_gitignore. Returns true if it appended the .gitignore entry.
|
|
77
|
+
# Best-effort: a filesystem error is logged and swallowed (never breaks boot).
|
|
78
|
+
def reconcile_gitignore!(config = configuration)
|
|
79
|
+
return false unless config.manage_gitignore?
|
|
80
|
+
|
|
81
|
+
GitignorePatcher.new(config).reconcile!
|
|
82
|
+
rescue StandardError => e
|
|
83
|
+
Rails.logger&.warn("[ReactManifest] gitignore reconcile skipped: #{e.message}")
|
|
84
|
+
false
|
|
85
|
+
end
|
|
86
|
+
|
|
77
87
|
# Resolve a controller bundle from a React component symbol.
|
|
78
88
|
#
|
|
79
89
|
# This is primarily used to support react-rails `react_component` calls,
|
|
@@ -102,6 +112,12 @@ module ReactManifest
|
|
|
102
112
|
shared = resolve_bundle_reference(config, config.shared_bundle)
|
|
103
113
|
bundles << shared if shared
|
|
104
114
|
|
|
115
|
+
# always_include bundles are delivered on every page. react_component does
|
|
116
|
+
# NOT go through resolve_bundles, so it must emit them here too — this is
|
|
117
|
+
# what makes always_include symbols available without inlining them into
|
|
118
|
+
# controller manifests (which would double-declare, see Generator).
|
|
119
|
+
append_always_include(config, bundles)
|
|
120
|
+
|
|
105
121
|
root = resolve_bundle_reference(config, root_bundle)
|
|
106
122
|
bundles << root if root && !bundles.include?(root)
|
|
107
123
|
|
|
@@ -142,6 +158,15 @@ module ReactManifest
|
|
|
142
158
|
|
|
143
159
|
private
|
|
144
160
|
|
|
161
|
+
# Append each configured always_include bundle (deduped) to +bundles+.
|
|
162
|
+
def append_always_include(config, bundles)
|
|
163
|
+
config.always_include.each do |b|
|
|
164
|
+
resolved = resolve_bundle_reference(config, b)
|
|
165
|
+
bundles << resolved if resolved && !bundles.include?(resolved)
|
|
166
|
+
end
|
|
167
|
+
bundles
|
|
168
|
+
end
|
|
169
|
+
|
|
145
170
|
def component_bundle_map(config)
|
|
146
171
|
component_maps(config)[:symbol_to_bundle]
|
|
147
172
|
end
|
|
@@ -153,79 +178,11 @@ module ReactManifest
|
|
|
153
178
|
return cached_maps if cached_key == key
|
|
154
179
|
end
|
|
155
180
|
|
|
156
|
-
|
|
157
|
-
symbol_to_bundle = {}
|
|
158
|
-
bundle_own_symbols = Hash.new { |h, k| h[k] = Set.new }
|
|
159
|
-
bundle_files = Hash.new { |h, k| h[k] = [] }
|
|
160
|
-
bundle_dependencies = Hash.new { |h, k| h[k] = Set.new }
|
|
161
|
-
|
|
162
|
-
controller_dirs.each do |ctrl|
|
|
163
|
-
bundle_name = ctrl[:bundle_name]
|
|
164
|
-
files = js_files_in_controller(ctrl[:path], config)
|
|
165
|
-
bundle_files[bundle_name].concat(files)
|
|
166
|
-
isolated = config.isolated_app_dirs.include?(ctrl[:name])
|
|
167
|
-
|
|
168
|
-
files.each do |file_path|
|
|
169
|
-
extract_defined_symbols(file_path).each do |symbol|
|
|
170
|
-
next unless symbol.match?(/\A[A-Z][A-Za-z0-9_]*\z/)
|
|
171
|
-
|
|
172
|
-
# Keep first writer to ensure deterministic behavior if a symbol is duplicated.
|
|
173
|
-
# Isolated dirs never register into the shared symbol index (see
|
|
174
|
-
# Generator#build_controller_context for the full rationale).
|
|
175
|
-
symbol_to_bundle[symbol] ||= bundle_name unless isolated
|
|
176
|
-
bundle_own_symbols[bundle_name] << symbol
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
bundle_files.each do |bundle_name, files|
|
|
182
|
-
own_symbols = bundle_own_symbols[bundle_name]
|
|
183
|
-
|
|
184
|
-
files.each do |file_path|
|
|
185
|
-
extract_used_component_symbols(file_path).each do |symbol|
|
|
186
|
-
# A symbol the bundle defines itself is always satisfied locally —
|
|
187
|
-
# never attribute it to another bundle just because that symbol
|
|
188
|
-
# name happens to collide with something defined elsewhere.
|
|
189
|
-
next if own_symbols.include?(symbol)
|
|
190
|
-
|
|
191
|
-
dep_bundle = symbol_to_bundle[symbol]
|
|
192
|
-
next unless dep_bundle && dep_bundle != bundle_name
|
|
193
|
-
|
|
194
|
-
bundle_dependencies[bundle_name] << dep_bundle
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
maps = {
|
|
200
|
-
symbol_to_bundle: symbol_to_bundle,
|
|
201
|
-
bundle_dependencies: bundle_dependencies
|
|
202
|
-
}
|
|
181
|
+
maps = ComponentIndex.maps(config)
|
|
203
182
|
@component_maps_cache = [key, maps]
|
|
204
183
|
maps
|
|
205
184
|
end
|
|
206
185
|
|
|
207
|
-
def js_files_in_controller(dir, config)
|
|
208
|
-
return [] unless Dir.exist?(dir)
|
|
209
|
-
|
|
210
|
-
Dir.glob(File.join(dir, "**", config.extensions_glob))
|
|
211
|
-
.reject { |f| File.directory?(f) }
|
|
212
|
-
.sort
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def extract_defined_symbols(file_path)
|
|
216
|
-
content = File.read(file_path, encoding: "utf-8")
|
|
217
|
-
SymbolExtractor.extract_definitions(content, file_path: file_path)
|
|
218
|
-
rescue Errno::ENOENT, Errno::EACCES, Encoding::InvalidByteSequenceError
|
|
219
|
-
[]
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def extract_used_component_symbols(file_path)
|
|
223
|
-
content = File.read(file_path, encoding: "utf-8")
|
|
224
|
-
SymbolExtractor.extract_usages(content, file_path: file_path)
|
|
225
|
-
rescue Errno::ENOENT, Errno::EACCES, Encoding::InvalidByteSequenceError
|
|
226
|
-
[]
|
|
227
|
-
end
|
|
228
|
-
|
|
229
186
|
def resolve_bundle_reference(config, bundle_name)
|
|
230
187
|
subdir = config.normalized_manifest_subdir
|
|
231
188
|
manifest_path = File.join(config.abs_manifest_dir, "#{bundle_name}.js")
|
|
@@ -261,4 +218,3 @@ module ReactManifest
|
|
|
261
218
|
end
|
|
262
219
|
end
|
|
263
220
|
end
|
|
264
|
-
# rubocop:enable Metrics/ModuleLength
|
data/tasks/react_manifest.rake
CHANGED
|
@@ -80,6 +80,22 @@ namespace :react_manifest do
|
|
|
80
80
|
puts " ✓ #{written} written, #{unchanged} unchanged"
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# 6. Ensure generated manifests are gitignored
|
|
84
|
+
puts "\n6) Gitignoring generated manifests..."
|
|
85
|
+
if config.manage_gitignore?
|
|
86
|
+
patcher = ReactManifest::GitignorePatcher.new(config)
|
|
87
|
+
result = patcher.patch!
|
|
88
|
+
if result.appended
|
|
89
|
+
puts " ✓ added #{patcher.pattern} to .gitignore"
|
|
90
|
+
puts " → one-time cleanup for previously-committed manifests:"
|
|
91
|
+
puts " git rm --cached #{File.dirname(patcher.pattern)}/*.js"
|
|
92
|
+
else
|
|
93
|
+
puts " ✓ #{patcher.pattern} already ignored"
|
|
94
|
+
end
|
|
95
|
+
else
|
|
96
|
+
puts " (skipped — config.manage_gitignore is false)"
|
|
97
|
+
end
|
|
98
|
+
|
|
83
99
|
# Done
|
|
84
100
|
puts "\n=== Setup #{'(dry-run) ' if config.dry_run?}complete ==="
|
|
85
101
|
puts "Start your Rails server — react_bundle_tag will serve the right JS per controller." unless config.dry_run?
|
|
@@ -120,6 +136,19 @@ namespace :react_manifest do
|
|
|
120
136
|
end
|
|
121
137
|
end
|
|
122
138
|
|
|
139
|
+
desc "Fail (exit 1, warnings on stderr) if any bundle declares the same top-level binding twice; writes nothing"
|
|
140
|
+
task check: :environment do
|
|
141
|
+
config = ReactManifest.configuration
|
|
142
|
+
next unless Dir.exist?(config.abs_ux_root)
|
|
143
|
+
|
|
144
|
+
clashes = ReactManifest::Generator.new(config).check
|
|
145
|
+
next if clashes.empty?
|
|
146
|
+
|
|
147
|
+
clashes.each { |message| warn "[ReactManifest] #{message}" }
|
|
148
|
+
warn "[ReactManifest] #{clashes.size} declaration clash(es) found."
|
|
149
|
+
exit 1
|
|
150
|
+
end
|
|
151
|
+
|
|
123
152
|
desc "Print the JSX dependency map and warnings without writing any files"
|
|
124
153
|
task analyze: :environment do
|
|
125
154
|
config = ReactManifest.configuration
|
|
@@ -130,6 +159,14 @@ namespace :react_manifest do
|
|
|
130
159
|
scan_result = scanner.scan(classification)
|
|
131
160
|
dep_map = ReactManifest::DependencyMap.new(scan_result)
|
|
132
161
|
dep_map.print_report
|
|
162
|
+
|
|
163
|
+
reasons = ReactManifest::Generator.new(config).promotion_reasons
|
|
164
|
+
unless reasons.empty?
|
|
165
|
+
puts "\nPromotions (app/ components emitted into #{config.shared_bundle}):"
|
|
166
|
+
reasons.sort.each do |req, bundles|
|
|
167
|
+
puts " #{req} <- used by: #{bundles.sort.join(', ')}"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
133
170
|
end
|
|
134
171
|
|
|
135
172
|
desc "Analyze application*.js files — show what migrate_application would change"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: react-manifest-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oliver Noonan
|
|
@@ -29,6 +29,20 @@ dependencies:
|
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '9'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: mini_racer
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '0.2'
|
|
39
|
+
type: :runtime
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0.2'
|
|
32
46
|
- !ruby/object:Gem::Dependency
|
|
33
47
|
name: minitest
|
|
34
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -119,20 +133,6 @@ dependencies:
|
|
|
119
133
|
- - "~>"
|
|
120
134
|
- !ruby/object:Gem::Version
|
|
121
135
|
version: '3.0'
|
|
122
|
-
- !ruby/object:Gem::Dependency
|
|
123
|
-
name: mini_racer
|
|
124
|
-
requirement: !ruby/object:Gem::Requirement
|
|
125
|
-
requirements:
|
|
126
|
-
- - ">="
|
|
127
|
-
- !ruby/object:Gem::Version
|
|
128
|
-
version: '0'
|
|
129
|
-
type: :development
|
|
130
|
-
prerelease: false
|
|
131
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
132
|
-
requirements:
|
|
133
|
-
- - ">="
|
|
134
|
-
- !ruby/object:Gem::Version
|
|
135
|
-
version: '0'
|
|
136
136
|
description: |
|
|
137
137
|
react-manifest-rails automatically generates per-controller Sprockets manifest
|
|
138
138
|
files for Rails applications using react-rails + Sprockets. It eliminates the
|
|
@@ -152,9 +152,11 @@ files:
|
|
|
152
152
|
- lib/react_manifest/application_analyzer.rb
|
|
153
153
|
- lib/react_manifest/application_migrator.rb
|
|
154
154
|
- lib/react_manifest/ast_extractor.rb
|
|
155
|
+
- lib/react_manifest/component_index.rb
|
|
155
156
|
- lib/react_manifest/configuration.rb
|
|
156
157
|
- lib/react_manifest/dependency_map.rb
|
|
157
158
|
- lib/react_manifest/generator.rb
|
|
159
|
+
- lib/react_manifest/gitignore_patcher.rb
|
|
158
160
|
- lib/react_manifest/layout_patcher.rb
|
|
159
161
|
- lib/react_manifest/logging.rb
|
|
160
162
|
- lib/react_manifest/path_utils.rb
|