react-manifest-rails 0.2.6 → 0.2.8

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: e9e734e50556ce1fafb042b8c906a2d8207080a79e5c82f6fa3088e6d3b0b1b9
4
- data.tar.gz: 2e7f5e2ab8142287c150c31befcb47318c71f62f3620a3099930dcc323e33410
3
+ metadata.gz: 3d0636de70da440909d01ca2748f51e9b73533a2c787b59984d906bac001b34c
4
+ data.tar.gz: d5a1c1982d5e875b0794c0645b07391edfff54f210f3dc394c0650ab0929d76d
5
5
  SHA512:
6
- metadata.gz: a7190fdd1cb329ec7c6a4012a681bdbfba92d2f2f787f876048c0052d120c600e4ca532fa504c82c54c1e3a24490cfc69c9e4c42482c1bbfa890dfff88739fad
7
- data.tar.gz: 54b9869d89a3d658838895cb172429c996da94e3365271e6194f1c2be53ae5427f3d28399a93251f106ead4b15872dbe828cb65a66f75a33e384fab38a902fb7
6
+ metadata.gz: fd86d54537b980dfff2ad4a7ab620b483716a8df735fed7cb4a6f0cc92c65297552c2295f2eda81017bb5fe290e2fc9500c91e04e2ff1700637162749609f2e8
7
+ data.tar.gz: 3bad752f3e4404f33a01fabd28c35b4dea27216b8adb8f4e312a0d3748bdbba85e06250866adc166bb9d49a723c1846163b2b8f8a0d75c50aa589ff461eb34dd
data/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.8] - 2026-04-15
9
+
10
+ ### Fixed
11
+ - Prevented duplicate bundle conflicts by removing legacy root `ux_*.js` files when an equivalent generated manifest already exists in the manifest directory.
12
+ - Ensured generated manifest directory has deterministic Sprockets precedence by prepending it in assets paths.
13
+
14
+ ### Changed
15
+ - Added regression coverage for duplicate legacy-manifest cleanup behavior.
16
+
17
+ ## [0.2.7] - 2026-04-15
18
+
19
+ ### Added
20
+ - Generated manifests now live in a dedicated folder (`app/assets/javascripts/ux_manifests` by default) to keep `app/assets/javascripts` tidy.
21
+ - Automatic migration of legacy `ux_*.js` files from `output_dir` root into the manifest folder during generation.
22
+
23
+ ### Changed
24
+ - Added `config.manifest_subdir` (default: `ux_manifests`) for explicit control over generated manifest placement.
25
+ - `react_manifest:clean` now removes auto-generated manifests from both the dedicated manifest folder and legacy root location.
26
+ - README and inline configuration docs updated to explain the clean manifest directory behavior.
27
+
8
28
  ## [0.2.6] - 2026-04-15
9
29
 
10
30
  ### Fixed
data/README.md CHANGED
@@ -42,6 +42,7 @@ ReactManifest.configure do |config|
42
42
  config.ux_root = "app/assets/javascripts/ux"
43
43
  config.app_dir = "app"
44
44
  config.output_dir = "app/assets/javascripts"
45
+ config.manifest_subdir = "ux_manifests"
45
46
  config.shared_bundle = "ux_shared"
46
47
  config.always_include = []
47
48
  config.ignore = []
@@ -107,6 +108,8 @@ In development:
107
108
 
108
109
  - `ux_shared.js`: shared files outside `ux/app/`
109
110
  - `ux_<controller>.js`: one bundle per directory under `ux/app/`
111
+ - Generated manifests are written to `app/assets/javascripts/ux_manifests/` by default.
112
+ - Existing legacy `app/assets/javascripts/ux_*.js` files are moved automatically on generation.
110
113
 
111
114
  Example:
112
115
  - `ux/app/users/...` -> `ux_users.js`
@@ -17,6 +17,10 @@ module ReactManifest
17
17
  # Where generated ux_*.js manifests are written (relative to Rails.root)
18
18
  attr_accessor :output_dir
19
19
 
20
+ # Subdirectory under output_dir that holds generated ux_*.js manifests.
21
+ # Keeping generated files out of output_dir root avoids clutter.
22
+ attr_accessor :manifest_subdir
23
+
20
24
  # Bundle name for auto-generated shared bundle (all non-app/ dirs)
21
25
  attr_accessor :shared_bundle
22
26
 
@@ -54,6 +58,7 @@ module ReactManifest
54
58
  @ux_root = "app/assets/javascripts/ux"
55
59
  @app_dir = "app"
56
60
  @output_dir = "app/assets/javascripts"
61
+ @manifest_subdir = "ux_manifests"
57
62
  @shared_bundle = "ux_shared"
58
63
  @always_include = []
59
64
  @ignore = []
@@ -99,5 +104,16 @@ module ReactManifest
99
104
  def abs_output_dir
100
105
  Rails.root.join(output_dir).to_s
101
106
  end
107
+
108
+ def abs_manifest_dir
109
+ subdir = normalized_manifest_subdir
110
+ return abs_output_dir if subdir.empty?
111
+
112
+ File.join(abs_output_dir, subdir)
113
+ end
114
+
115
+ def normalized_manifest_subdir
116
+ manifest_subdir.to_s.gsub(%r{\A/+|/+\z}, "")
117
+ end
102
118
  end
103
119
  end
@@ -48,6 +48,8 @@ module ReactManifest
48
48
  manifests << build_shared(classification.shared_dirs)
49
49
  classification.controller_dirs.each { |ctrl| manifests << build_controller(ctrl) }
50
50
 
51
+ migrate_legacy_manifests!
52
+
51
53
  # Phase 2: write — each write is atomic (tmp + rename).
52
54
  results = manifests.map { |m| write_manifest(m[:filename], m[:content]) }
53
55
 
@@ -96,7 +98,7 @@ module ReactManifest
96
98
  # --------------------------------------------------------------- write
97
99
 
98
100
  def write_manifest(filename, content)
99
- dest = File.join(@config.abs_output_dir, filename)
101
+ dest = File.join(@config.abs_manifest_dir, filename)
100
102
 
101
103
  # Safety: never touch files not bearing our AUTO-GENERATED header
102
104
  # (unless they don't exist yet)
@@ -131,6 +133,36 @@ module ReactManifest
131
133
  { path: dest, status: :written }
132
134
  end
133
135
 
136
+ def migrate_legacy_manifests!
137
+ legacy_dir = @config.abs_output_dir
138
+ manifest_dir = @config.abs_manifest_dir
139
+ return if legacy_dir == manifest_dir
140
+
141
+ legacy_files = Dir.glob(File.join(legacy_dir, "ux_*.js"))
142
+ return if legacy_files.empty?
143
+
144
+ if @config.dry_run?
145
+ legacy_files.each do |legacy|
146
+ target = File.join(manifest_dir, File.basename(legacy))
147
+ $stdout.puts "[ReactManifest] DRY-RUN: would move #{legacy} -> #{target}"
148
+ end
149
+ return
150
+ end
151
+
152
+ FileUtils.mkdir_p(manifest_dir)
153
+ legacy_files.each do |legacy|
154
+ target = File.join(manifest_dir, File.basename(legacy))
155
+ if File.exist?(target)
156
+ # Prevent double-definition conflicts: if a legacy root manifest is
157
+ # auto-generated and a manifest-dir equivalent exists, drop the legacy file.
158
+ FileUtils.rm_f(legacy) if auto_generated?(legacy)
159
+ next
160
+ end
161
+
162
+ FileUtils.mv(legacy, target)
163
+ end
164
+ end
165
+
134
166
  # ----------------------------------------------------------- helpers
135
167
 
136
168
  def header_lines
@@ -35,6 +35,16 @@ module ReactManifest
35
35
  # Expose config as Rails.application.config.react_manifest
36
36
  config.react_manifest = ReactManifest.configuration
37
37
 
38
+ # Keep generated manifests in a dedicated folder while preserving logical
39
+ # asset names (ux_shared, ux_users, etc.) via an explicit Sprockets path.
40
+ initializer "react_manifest.assets_path" do |app|
41
+ next unless app.config.respond_to?(:assets)
42
+
43
+ manifest_dir = ReactManifest.configuration.abs_manifest_dir
44
+ app.config.assets.paths.delete(manifest_dir)
45
+ app.config.assets.paths.unshift(manifest_dir)
46
+ end
47
+
38
48
  # ----------------------------------------------------------------
39
49
  # Start the file watcher in development
40
50
  # ----------------------------------------------------------------
@@ -78,9 +88,9 @@ module ReactManifest
78
88
  private
79
89
 
80
90
  def missing_manifest_bundles(config)
81
- output_dir = config.abs_output_dir
82
91
  expected_manifest_bundles(config).reject do |bundle_name|
83
- File.exist?(File.join(output_dir, "#{bundle_name}.js"))
92
+ File.exist?(File.join(config.abs_manifest_dir, "#{bundle_name}.js")) ||
93
+ File.exist?(File.join(config.abs_output_dir, "#{bundle_name}.js"))
84
94
  end
85
95
  end
86
96
 
@@ -1,3 +1,3 @@
1
1
  module ReactManifest
2
- VERSION = "0.2.6".freeze
2
+ VERSION = "0.2.8".freeze
3
3
  end
@@ -30,23 +30,25 @@ module ReactManifest
30
30
  # Used by the react_bundle_tag view helper.
31
31
  def resolve_bundles(ctrl_name)
32
32
  config = configuration
33
- output = config.abs_output_dir
34
33
  bundles = []
35
34
 
36
35
  # 1. Shared bundle always first
37
- bundles << config.shared_bundle if bundle_exists?(output, config.shared_bundle)
36
+ shared = resolve_bundle_reference(config, config.shared_bundle)
37
+ bundles << shared if shared
38
38
 
39
39
  # 2. always_include bundles (e.g. ux_main)
40
40
  config.always_include.each do |b|
41
- bundles << b if bundle_exists?(output, b) && !bundles.include?(b)
41
+ resolved = resolve_bundle_reference(config, b)
42
+ bundles << resolved if resolved && !bundles.include?(resolved)
42
43
  end
43
44
 
44
45
  # 3. Controller-specific bundle
45
46
  # Try fully-namespaced first: admin/users → ux_admin_users
46
47
  # Then drop segments: ux_admin
47
48
  controller_candidates(ctrl_name).each do |candidate|
48
- if bundle_exists?(output, candidate) && !bundles.include?(candidate)
49
- bundles << candidate
49
+ resolved = resolve_bundle_reference(config, candidate)
50
+ if resolved && !bundles.include?(resolved)
51
+ bundles << resolved
50
52
  break
51
53
  end
52
54
  end
@@ -56,8 +58,15 @@ module ReactManifest
56
58
 
57
59
  private
58
60
 
59
- def bundle_exists?(output_dir, bundle_name)
60
- File.exist?(File.join(output_dir, "#{bundle_name}.js"))
61
+ def resolve_bundle_reference(config, bundle_name)
62
+ manifest_path = File.join(config.abs_manifest_dir, "#{bundle_name}.js")
63
+ return bundle_name if File.exist?(manifest_path)
64
+
65
+ # Backward compatibility for apps still holding legacy manifests in output_dir root.
66
+ legacy_path = File.join(config.abs_output_dir, "#{bundle_name}.js")
67
+ return bundle_name if File.exist?(legacy_path)
68
+
69
+ nil
61
70
  end
62
71
 
63
72
  def controller_candidates(ctrl_name)
@@ -68,19 +68,21 @@ namespace :react_manifest do
68
68
  desc "Remove all AUTO-GENERATED ux_*.js manifests"
69
69
  task clean: :environment do
70
70
  config = ReactManifest.configuration
71
- output = config.abs_output_dir
71
+ targets = [config.abs_manifest_dir, config.abs_output_dir].uniq
72
72
  removed = 0
73
73
  skipped = 0
74
74
 
75
- Dir.glob(File.join(output, "ux_*.js")).each do |file|
76
- first_line = File.foreach(file).first.to_s
77
- if first_line.include?("AUTO-GENERATED")
78
- File.delete(file)
79
- puts "[ReactManifest] Removed: #{file.sub("#{Rails.root}/", '')}"
80
- removed += 1
81
- else
82
- puts "[ReactManifest] Skipped (not auto-generated): #{file.sub("#{Rails.root}/", '')}"
83
- skipped += 1
75
+ targets.each do |dir|
76
+ Dir.glob(File.join(dir, "ux_*.js")).each do |file|
77
+ first_line = File.foreach(file).first.to_s
78
+ if first_line.include?("AUTO-GENERATED")
79
+ File.delete(file)
80
+ puts "[ReactManifest] Removed: #{file.sub("#{Rails.root}/", '')}"
81
+ removed += 1
82
+ else
83
+ puts "[ReactManifest] Skipped (not auto-generated): #{file.sub("#{Rails.root}/", '')}"
84
+ skipped += 1
85
+ end
84
86
  end
85
87
  end
86
88
 
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.2.6
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oliver Noonan