react_on_rails 16.6.0.rc.0 → 16.6.0.rc.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2294c0aab02fdb0995b81b139099a0585b25ee39ebe903d6238e91a40e2a0341
4
- data.tar.gz: 76c6b154c56c639566069a5840496e4ba142b6130429f38ab7580f6bb33bbc29
3
+ metadata.gz: 5c525aa58afae47bf65f4118b11472b00b06649b2b3eba698fa6f7b82a6a6050
4
+ data.tar.gz: 2fe64e5d5ce2306b56408b26ffef471177ed33319732336f2f4d203b4917b742
5
5
  SHA512:
6
- metadata.gz: 0521bd2c98262935f0f7bac35e779aec25a6cb8a8039906141ab7e560d27deade2c3b1601d389d4e362ead52ed64b4be0e851ae22a07cb61e15948407e925a69
7
- data.tar.gz: bd80ca64b259c5e303111d7f46aeaa2b1e1bcda60af3fcc1873db9e51b39db2bf42bb4f846b9678ea9b8d6b5d4dac0b70183ce6fa30b7953ad2d0a65ee6d7dc4
6
+ metadata.gz: 8e580e7e342ed62b643a5d89a8b8b9f145a3edb2e51089c240575445824b1b7c5b8d82286e477a6a8457d54ed26d64fb4a05f6a42a9cbca229e3512bfdbeddc8
7
+ data.tar.gz: 95539a4061db5f32a57c0e0d0e4665ba2fea563de45686ff0fecc10d94ce28f5f043348d29af748acee96f078c9337fd805677f388c903b34b1562c90571c22d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- react_on_rails (16.6.0.rc.0)
4
+ react_on_rails (16.6.0.rc.1)
5
5
  addressable
6
6
  connection_pool
7
7
  execjs (~> 2.5)
@@ -147,28 +147,25 @@ module ReactOnRails
147
147
 
148
148
  base_gem_entry_found = true
149
149
 
150
+ declaration = consume_non_parenthesized_base_gem_declaration(
151
+ gemfile_lines,
152
+ line_index,
153
+ match.end(0)
154
+ )
155
+
150
156
  unless pro_entry_added
151
157
  indentation = match[1]
152
158
  quote = match[2]
153
159
  updated_lines << build_pro_gem_replacement_line(
154
160
  indentation: indentation,
155
161
  quote: quote,
156
- suffix: line[match.end(0)..],
162
+ suffix: declaration[:trailing_suffix],
157
163
  parenthesized_gem_call: match[0].include?("(")
158
164
  )
159
165
  pro_entry_added = true
160
166
  end
161
167
 
162
- # Consume multiline gem declarations that continue with trailing commas.
163
- line_index += 1
164
- current_line = line
165
- while line_index < gemfile_lines.length &&
166
- line_continues_with_comma?(current_line) &&
167
- gem_declaration_continues_on_next_line?(gemfile_lines[line_index])
168
- next_line = gemfile_lines[line_index]
169
- current_line = next_line unless comment_or_blank_line?(next_line)
170
- line_index += 1
171
- end
168
+ line_index = declaration[:next_index]
172
169
  end
173
170
 
174
171
  updated_content = updated_lines.join
@@ -476,17 +473,18 @@ module ReactOnRails
476
473
  pending_multiline_static_import_specifier
477
474
  ) { |line_fragment| yield line_fragment }
478
475
  in_multiline_template_literal = updated_template_literal_state
479
- in_block_comment = true if unclosed_block_comment_starts?(rewritten_line)
476
+ in_block_comment = unclosed_block_comment_starts?(rewritten_line)
480
477
  rewritten_line
481
478
  elsif line_contains_unescaped_backtick
482
479
  rewritten_line, pending_multiline_module_call_depth, pending_multiline_static_import_specifier =
483
480
  rewrite_line_before_template_literal_open(
484
481
  line,
485
482
  pending_multiline_module_call_depth,
486
- pending_multiline_static_import_specifier
483
+ pending_multiline_static_import_specifier,
484
+ in_block_comment: in_block_comment
487
485
  ) { |line_fragment| yield line_fragment }
488
486
  in_multiline_template_literal = updated_template_literal_state
489
- in_block_comment = true if unclosed_block_comment_starts?(rewritten_line)
487
+ in_block_comment = unclosed_block_comment_starts?(rewritten_line)
490
488
  rewritten_line
491
489
  else
492
490
  in_multiline_template_literal = updated_template_literal_state
@@ -648,7 +646,7 @@ module ReactOnRails
648
646
 
649
647
  rewritten_line = yield line_without_inline_templates
650
648
  template_placeholders.each do |placeholder, template_literal|
651
- rewritten_line = rewritten_line.sub(placeholder, template_literal)
649
+ rewritten_line = rewritten_line.sub(placeholder) { template_literal }
652
650
  end
653
651
  rewritten_line
654
652
  end
@@ -742,8 +740,13 @@ module ReactOnRails
742
740
  ["#{template_literal_prefix}#{rewritten_fragment}", pending_depth, pending_multiline_static_import_specifier]
743
741
  end
744
742
 
745
- def rewrite_line_before_template_literal_open(line, pending_depth, pending_multiline_static_import_specifier)
746
- opening_index = first_unescaped_backtick_index(line)
743
+ def rewrite_line_before_template_literal_open(
744
+ line,
745
+ pending_depth,
746
+ pending_multiline_static_import_specifier,
747
+ in_block_comment: false
748
+ )
749
+ opening_index = opening_backtick_index_for_multiline_start(line, in_block_comment: in_block_comment)
747
750
  return [line, pending_depth, pending_multiline_static_import_specifier] unless opening_index&.positive?
748
751
 
749
752
  line_prefix = line[0, opening_index]
@@ -757,17 +760,56 @@ module ReactOnRails
757
760
  end
758
761
 
759
762
  def first_unescaped_backtick_index(line)
763
+ unescaped_backtick_indexes(line, skip_comments: true).first
764
+ end
765
+
766
+ def opening_backtick_index_for_multiline_start(line, in_block_comment: false)
767
+ backtick_indexes = unescaped_backtick_indexes(line, in_block_comment: in_block_comment)
768
+ return nil if backtick_indexes.empty? || backtick_indexes.length.even?
769
+
770
+ backtick_indexes.last
771
+ end
772
+
773
+ # rubocop:disable Metrics/CyclomaticComplexity
774
+ def unescaped_backtick_indexes(line, in_block_comment: false, skip_comments: false)
760
775
  quote_state = nil
776
+ backtick_indexes = []
777
+
778
+ scan_index = 0
779
+ while scan_index < line.length
780
+ if in_block_comment
781
+ closing_index = line.index("*/", scan_index)
782
+ break unless closing_index
783
+
784
+ in_block_comment = false
785
+ scan_index = closing_index + 2
786
+ next
787
+ end
761
788
 
762
- line.each_char.with_index do |char, index|
763
- quote_state = next_quote_state(quote_state, char, line, index)
764
- next if quote_state
765
- return nil if line[index, 2] == "//"
789
+ char = line[scan_index]
790
+ quote_state = next_quote_state(quote_state, char, line, scan_index)
791
+ if quote_state
792
+ scan_index += 1
793
+ next
794
+ end
795
+
796
+ unless skip_comments
797
+ break if line[scan_index, 2] == "//"
798
+
799
+ if line[scan_index, 2] == "/*"
800
+ in_block_comment = true
801
+ scan_index += 2
802
+ next
803
+ end
804
+ end
766
805
 
767
- return index if char == "`" && !character_escaped?(line, index)
806
+ backtick_indexes << scan_index if char == "`" && !character_escaped?(line, scan_index)
807
+ scan_index += 1
768
808
  end
769
- nil
809
+
810
+ backtick_indexes
770
811
  end
812
+ # rubocop:enable Metrics/CyclomaticComplexity
771
813
 
772
814
  def next_quote_state(current_state, char, line, index)
773
815
  if current_state
@@ -830,13 +872,36 @@ module ReactOnRails
830
872
  end
831
873
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
832
874
 
875
+ def consume_non_parenthesized_base_gem_declaration(lines, start_index, match_end)
876
+ line_index = start_index
877
+ current_line = lines[line_index]
878
+ declaration_lines = [current_line]
879
+ line_index += 1
880
+
881
+ while line_index < lines.length &&
882
+ line_continues_with_comma?(current_line) &&
883
+ gem_declaration_continues_on_next_line?(lines[line_index])
884
+ next_line = lines[line_index]
885
+ declaration_lines << next_line
886
+ current_line = next_line unless comment_or_blank_line?(next_line)
887
+ line_index += 1
888
+ end
889
+
890
+ trailing_suffix = lines[start_index][match_end..].to_s + declaration_lines.drop(1).join
891
+ { trailing_suffix: trailing_suffix, next_index: line_index }
892
+ end
893
+
833
894
  def build_pro_gem_replacement_line(indentation:, quote:, suffix:, parenthesized_gem_call: false)
834
895
  normalized_suffix = suffix || "\n"
835
896
  normalized_suffix = "#{normalized_suffix}\n" unless normalized_suffix.end_with?("\n")
836
897
  version_arg_pattern = /\A(?<prefix>\s*,(?:\s*#.*\n|\s++)*)["'][^"']*["'](?<trailing_comma>\s*,)?/
837
898
  loop do
838
899
  updated_suffix = normalized_suffix.sub(version_arg_pattern) do
839
- Regexp.last_match[:trailing_comma] ? Regexp.last_match[:prefix] : ""
900
+ if Regexp.last_match[:trailing_comma]
901
+ Regexp.last_match[:prefix].sub(/\n[ \t]*\z/, "")
902
+ else
903
+ ""
904
+ end
840
905
  end
841
906
  break if updated_suffix == normalized_suffix
842
907
 
@@ -170,7 +170,7 @@ module ReactOnRails
170
170
  ⚠️ Procfile.dev not found. Skipping RSC bundle watcher addition.
171
171
 
172
172
  You'll need to add the RSC bundle watcher to your process manager manually:
173
- rsc-bundle: RSC_BUNDLE_ONLY=yes bin/shakapacker-watch --watch
173
+ rsc-bundle: RSC_BUNDLE_ONLY=true bin/shakapacker-watch --watch
174
174
  MSG
175
175
  return
176
176
  end
@@ -185,7 +185,7 @@ module ReactOnRails
185
185
  rsc_watcher_line = <<~PROCFILE
186
186
 
187
187
  # React on Rails Pro - RSC bundle watcher
188
- rsc-bundle: RSC_BUNDLE_ONLY=yes bin/shakapacker-watch --watch
188
+ rsc-bundle: RSC_BUNDLE_ONLY=true bin/shakapacker-watch --watch
189
189
  PROCFILE
190
190
 
191
191
  append_to_file("Procfile.dev", rsc_watcher_line)
@@ -6,4 +6,4 @@
6
6
  # SHAKAPACKER_DEV_SERVER_PORT=3036
7
7
  rails: bundle exec rails s -p ${PORT:-3000}
8
8
  dev-server: bin/shakapacker-dev-server
9
- server-bundle: SERVER_BUNDLE_ONLY=yes bin/shakapacker-watch --watch
9
+ server-bundle: SERVER_BUNDLE_ONLY=true bin/shakapacker-watch --watch
@@ -94,51 +94,6 @@ module ReactOnRails
94
94
  :server_bundle_output_path, :enforce_private_server_bundles,
95
95
  :check_database_on_dev_start
96
96
 
97
- # Class instance variable and mutex to track if deprecation warning has been shown
98
- # Using mutex to ensure thread-safety in multi-threaded environments
99
- @immediate_hydration_warned = false
100
- @immediate_hydration_mutex = Mutex.new
101
-
102
- class << self
103
- attr_accessor :immediate_hydration_warned, :immediate_hydration_mutex
104
- end
105
-
106
- # Deprecated: immediate_hydration configuration has been removed
107
- def immediate_hydration=(value)
108
- warned = false
109
- self.class.immediate_hydration_mutex.synchronize do
110
- warned = self.class.immediate_hydration_warned
111
- self.class.immediate_hydration_warned = true unless warned
112
- end
113
-
114
- return if warned
115
-
116
- Rails.logger.warn <<~WARNING
117
- [REACT ON RAILS] The 'config.immediate_hydration' configuration option is deprecated and no longer used.
118
- Immediate hydration is now automatically enabled for React on Rails Pro users.
119
- Please remove 'config.immediate_hydration = #{value}' from your config/initializers/react_on_rails.rb file.
120
- See CHANGELOG.md for migration instructions.
121
- WARNING
122
- end
123
-
124
- def immediate_hydration
125
- warned = false
126
- self.class.immediate_hydration_mutex.synchronize do
127
- warned = self.class.immediate_hydration_warned
128
- self.class.immediate_hydration_warned = true unless warned
129
- end
130
-
131
- return nil if warned
132
-
133
- Rails.logger.warn <<~WARNING
134
- [REACT ON RAILS] The 'config.immediate_hydration' configuration option is deprecated and no longer used.
135
- Immediate hydration is now automatically enabled for React on Rails Pro users.
136
- Please remove any references to 'config.immediate_hydration' from your config/initializers/react_on_rails.rb file.
137
- See CHANGELOG.md for migration instructions.
138
- WARNING
139
- nil
140
- end
141
-
142
97
  # rubocop:disable Metrics/AbcSize
143
98
  def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
144
99
  replay_console: nil, make_generated_server_bundle_the_entrypoint: nil,
@@ -257,12 +212,14 @@ module ReactOnRails
257
212
  Rails.logger.warn("**WARNING** #{msg}")
258
213
  self.generated_component_packs_loading_strategy = :sync
259
214
  elsif generated_component_packs_loading_strategy == :async
260
- raise ReactOnRails::Error, "**ERROR** #{msg}"
215
+ raise ReactOnRails::Error, "**ERROR** #{msg}\n\n#{ReactOnRails::DOCTOR_RECOMMENDATION}"
261
216
  end
262
217
 
263
218
  return if %i[async defer sync].include?(generated_component_packs_loading_strategy)
264
219
 
265
- raise ReactOnRails::Error, "generated_component_packs_loading_strategy must be either :async, :defer, or :sync"
220
+ raise ReactOnRails::Error,
221
+ "generated_component_packs_loading_strategy must be either :async, :defer, or :sync. " \
222
+ "#{ReactOnRails::DOCTOR_RECOMMENDATION}"
266
223
  end
267
224
 
268
225
  def validate_enforce_private_server_bundles
@@ -272,7 +229,8 @@ module ReactOnRails
272
229
  if server_bundle_output_path.nil?
273
230
  raise ReactOnRails::Error, "enforce_private_server_bundles is set to true, but " \
274
231
  "server_bundle_output_path is nil. Please set server_bundle_output_path " \
275
- "to a directory outside of the public directory."
232
+ "to a directory outside of the public directory. " \
233
+ "#{ReactOnRails::DOCTOR_RECOMMENDATION}"
276
234
  end
277
235
 
278
236
  # Check if server_bundle_output_path is inside public directory
@@ -286,7 +244,8 @@ module ReactOnRails
286
244
 
287
245
  raise ReactOnRails::Error, "enforce_private_server_bundles is set to true, but " \
288
246
  "server_bundle_output_path (#{server_bundle_output_path}) is inside " \
289
- "the public directory. Please set it to a directory outside of public."
247
+ "the public directory. Please set it to a directory outside of public. " \
248
+ "#{ReactOnRails::DOCTOR_RECOMMENDATION}"
290
249
  end
291
250
 
292
251
  # Auto-detect server_bundle_output_path from Shakapacker 9.0+ private_output_path
@@ -401,6 +360,8 @@ module ReactOnRails
401
360
  that does not match the value for public_output_path specified in
402
361
  shakapacker.yml = #{packer_public_output_path}. You should remove the configuration
403
362
  value for "generated_assets_dir" from your config/initializers/react_on_rails.rb file.
363
+
364
+ #{ReactOnRails::DOCTOR_RECOMMENDATION}
404
365
  MSG
405
366
  raise ReactOnRails::Error, msg
406
367
  end
@@ -465,7 +426,9 @@ module ReactOnRails
465
426
  msg = <<~MSG
466
427
  **ERROR** ReactOnRails: auto_load_bundle is set to true, yet components_subdirectory is not configured.\
467
428
  Please set components_subdirectory to the desired directory. For more information, please see \
468
- https://reactonrails.com/docs/core-concepts/auto-bundling-file-system-based-automated-bundle-generation/
429
+ https://reactonrails.com/docs/core-concepts/auto-bundling/
430
+
431
+ #{ReactOnRails::DOCTOR_RECOMMENDATION}
469
432
  MSG
470
433
 
471
434
  raise ReactOnRails::Error, msg
@@ -482,6 +445,7 @@ module ReactOnRails
482
445
  Alternatively, remove the config/react_on_rails.rb config.build_production_command and the
483
446
  default bin/shakapacker script will be used for assets:precompile.
484
447
 
448
+ #{ReactOnRails::DOCTOR_RECOMMENDATION}
485
449
  MSG
486
450
  end
487
451
  end
@@ -9,16 +9,22 @@ module ReactOnRails
9
9
  # JavaScript code.
10
10
  # props: Named parameter props which is a Ruby Hash or JSON string which contains the properties
11
11
  # to pass to the redux store.
12
- # immediate_hydration: React on Rails Pro (licensed) feature. When nil (default), Pro users get
13
- # immediate hydration, non-Pro users don't. Can be explicitly overridden.
14
12
  #
15
13
  # Be sure to include view helper `redux_store_hydration_data` at the end of your layout or view
16
14
  # or else there will be no client side hydration of your stores.
17
- def redux_store(store_name, props: {}, immediate_hydration: nil)
18
- immediate_hydration = ReactOnRails::Utils.normalize_immediate_hydration(immediate_hydration, store_name, "Store")
15
+ def redux_store(store_name, props: {}, **rest)
16
+ immediate_hydration_present = rest.key?(:immediate_hydration)
17
+ unknown_keys = rest.keys - [:immediate_hydration]
18
+ if unknown_keys.any?
19
+ plural = unknown_keys.one? ? "" : "s"
20
+ unknown_options = unknown_keys.map { |key| ":#{key}" }.join(", ")
21
+ raise ArgumentError, "unknown keyword#{plural}: #{unknown_options}"
22
+ end
23
+
24
+ ReactOnRails::Helper.warn_removed_immediate_hydration_option("redux_store") if immediate_hydration_present
25
+
19
26
  redux_store_data = { store_name: store_name,
20
- props: props,
21
- immediate_hydration: immediate_hydration }
27
+ props: props }
22
28
  @registered_stores_defer_render ||= []
23
29
  @registered_stores_defer_render << redux_store_data
24
30
  end
@@ -290,7 +290,7 @@ module ReactOnRails
290
290
 
291
291
  env = { "RAILS_ENV" => "test" }
292
292
  if resolved_mode == "client-only"
293
- env["CLIENT_BUNDLE_ONLY"] = "yes"
293
+ env["CLIENT_BUNDLE_ONLY"] = "true"
294
294
  puts Rainbow("🧪 Starting test watch (client-only mode)...").cyan
295
295
  puts Rainbow(" Reusing server bundle from existing watcher if available.").cyan
296
296
  else
@@ -320,7 +320,9 @@ module ReactOnRails
320
320
  def shakapacker_watch_process_running?
321
321
  # Detect existing shakapacker watcher processes (from either bin/dev or bin/dev static).
322
322
  # If one is already running, client-only test watch avoids duplicate server-bundle rebuilds.
323
- server_only_watchers = find_process_pids("SERVER_BUNDLE_ONLY=yes bin/shakapacker --watch")
323
+ # Also detect legacy =yes convention during transition
324
+ server_only_watchers = find_process_pids("SERVER_BUNDLE_ONLY=true bin/shakapacker --watch")
325
+ server_only_watchers |= find_process_pids("SERVER_BUNDLE_ONLY=yes bin/shakapacker --watch")
324
326
  if server_only_watchers.any?
325
327
  return true if shared_private_output_paths?
326
328