react_on_rails 11.1.8 → 12.0.0.pre.beta.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.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +320 -0
  3. data/.eslintignore +2 -1
  4. data/.eslintrc +30 -2
  5. data/.github/FUNDING.yml +1 -0
  6. data/.gitignore +3 -1
  7. data/.prettierignore +10 -0
  8. data/.prettierrc +23 -0
  9. data/.release-it.json +3 -0
  10. data/.rubocop.yml +37 -11
  11. data/.travis.yml +10 -20
  12. data/CHANGELOG.md +89 -3
  13. data/CONTRIBUTING.md +61 -80
  14. data/Gemfile +3 -5
  15. data/{COMM-LICENSE → REACT-ON-RAILS-PRO-LICENSE} +6 -9
  16. data/README.md +121 -71
  17. data/Rakefile +0 -7
  18. data/SUMMARY.md +10 -12
  19. data/book.json +5 -5
  20. data/docs/additional-reading/asset-pipeline.md +8 -16
  21. data/docs/additional-reading/images.md +1 -1
  22. data/docs/additional-reading/rails_view_rendering_from_inline_javascript.md +2 -1
  23. data/docs/additional-reading/react-helmet.md +30 -10
  24. data/docs/additional-reading/react-router.md +52 -75
  25. data/docs/additional-reading/server-rendering-tips.md +12 -7
  26. data/docs/additional-reading/upgrade-webpacker-v3-to-v4.md +10 -0
  27. data/docs/api/javascript-api.md +3 -3
  28. data/docs/api/redux-store-api.md +4 -2
  29. data/docs/api/view-helpers-api.md +17 -14
  30. data/docs/basics/configuration.md +64 -61
  31. data/docs/basics/deployment.md +1 -2
  32. data/docs/basics/i18n.md +44 -22
  33. data/docs/basics/installation-into-an-existing-rails-app.md +2 -2
  34. data/docs/basics/minitest-configuration.md +31 -0
  35. data/docs/basics/react-server-rendering.md +1 -1
  36. data/docs/basics/recommended-project-structure.md +1 -1
  37. data/docs/basics/{generator-functions-and-railscontext.md → render-functions-and-railscontext.md} +59 -21
  38. data/docs/basics/rspec-configuration.md +2 -2
  39. data/docs/basics/upgrading-react-on-rails.md +61 -3
  40. data/docs/basics/webpack-configuration.md +15 -1
  41. data/docs/contributor-info/errors-with-hooks.md +45 -0
  42. data/docs/contributor-info/pull-requests.md +44 -0
  43. data/docs/misc/doctrine.md +1 -1
  44. data/docs/{misc-pending → outdated}/code-splitting.md +13 -9
  45. data/docs/{additional-reading → outdated}/heroku-deployment.md +0 -6
  46. data/docs/{basics → outdated}/how-react-on-rails-works.md +3 -3
  47. data/docs/{misc-pending → outdated}/manual-installation-overview.md +5 -5
  48. data/docs/{additional-reading → outdated}/rails-assets-relative-paths.md +3 -3
  49. data/docs/{misc-pending → outdated}/rails-assets.md +4 -7
  50. data/docs/{misc → outdated}/rails3.md +0 -0
  51. data/docs/testimonials/hvmn.md +3 -3
  52. data/docs/testimonials/resortpass.md +13 -0
  53. data/docs/testimonials/testimonials.md +11 -1
  54. data/docs/tutorial.md +69 -28
  55. data/jest.config.js +4 -0
  56. data/lib/generators/react_on_rails/base_generator.rb +2 -2
  57. data/lib/generators/react_on_rails/dev_tests_generator.rb +2 -1
  58. data/lib/generators/react_on_rails/generator_helper.rb +4 -6
  59. data/lib/generators/react_on_rails/install_generator.rb +2 -0
  60. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +3 -1
  61. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hmr +18 -0
  62. data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +20 -40
  63. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +4 -8
  64. data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/store/helloWorldStore.js +1 -3
  65. data/lib/react_on_rails.rb +4 -1
  66. data/lib/react_on_rails/configuration.rb +15 -23
  67. data/lib/react_on_rails/error.rb +2 -0
  68. data/lib/react_on_rails/git_utils.rb +2 -0
  69. data/lib/react_on_rails/helper.rb +111 -162
  70. data/lib/react_on_rails/json_output.rb +1 -1
  71. data/lib/react_on_rails/json_parse_error.rb +2 -0
  72. data/lib/react_on_rails/locales/base.rb +142 -0
  73. data/lib/react_on_rails/locales/to_js.rb +37 -0
  74. data/lib/react_on_rails/locales/to_json.rb +27 -0
  75. data/lib/react_on_rails/prerender_error.rb +11 -15
  76. data/lib/react_on_rails/react_component/render_options.rb +4 -0
  77. data/lib/react_on_rails/server_rendering_js_code.rb +42 -0
  78. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +71 -51
  79. data/lib/react_on_rails/test_helper/ensure_assets_compiled.rb +7 -8
  80. data/lib/react_on_rails/utils.rb +15 -20
  81. data/lib/react_on_rails/version.rb +1 -1
  82. data/lib/react_on_rails/version_checker.rb +5 -1
  83. data/lib/react_on_rails/webpacker_utils.rb +16 -2
  84. data/lib/tasks/assets.rake +5 -45
  85. data/lib/tasks/locale.rake +8 -2
  86. data/package-scripts.yml +49 -0
  87. data/package.json +41 -31
  88. data/rakelib/dummy_apps.rake +1 -9
  89. data/rakelib/example_type.rb +3 -1
  90. data/rakelib/examples.rake +3 -0
  91. data/rakelib/lint.rake +2 -7
  92. data/rakelib/node_package.rake +2 -2
  93. data/rakelib/release.rake +3 -8
  94. data/rakelib/run_rspec.rake +5 -18
  95. data/react_on_rails.gemspec +3 -5
  96. data/tsconfig.json +14 -0
  97. data/webpackConfigLoader.js +5 -4
  98. data/yarn.lock +7042 -2327
  99. metadata +39 -57
  100. data/Gemfile.rails32 +0 -74
  101. data/docs/additional-reading/babel.md +0 -5
  102. data/docs/additional-reading/hot-reloading-rails-development-asset-pipeline.md +0 -47
  103. data/docs/api/ruby-api-hot-reload-view-helpers.md +0 -44
  104. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-server +0 -12
  105. data/lib/react_on_rails/assets_precompile.rb +0 -150
  106. data/lib/react_on_rails/locales_to_js.rb +0 -136
@@ -1,150 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ReactOnRails
4
- class AssetsPrecompile
5
- class SymlinkTargetDoesNotExistException < StandardError
6
- end
7
-
8
- # Used by the rake task
9
- def default_asset_path
10
- dir = File.join(Rails.configuration.paths["public"].first,
11
- Rails.configuration.assets.prefix)
12
- Pathname.new(dir)
13
- end
14
-
15
- # assets_path should be a Pathname object
16
- def initialize(assets_path: nil,
17
- symlink_non_digested_assets_regex: nil,
18
- generated_assets_dir: nil)
19
- @assets_path = ReactOnRails::Utils.truthy_presence(assets_path) || default_asset_path
20
- @symlink_non_digested_assets_regex =
21
- ReactOnRails::Utils.truthy_presence(symlink_non_digested_assets_regex) ||
22
- ReactOnRails.configuration.symlink_non_digested_assets_regex
23
- @generated_assets_dir = ReactOnRails::Utils.truthy_presence(generated_assets_dir) ||
24
- ReactOnRails.configuration.generated_assets_dir
25
- end
26
-
27
- # target and symlink are relative to the assets directory
28
- def symlink_file(target, symlink)
29
- target_path = @assets_path.join(target)
30
- symlink_path = @assets_path.join(symlink)
31
-
32
- target_exists = File.exist?(target_path)
33
- raise SymlinkTargetDoesNotExistException, "Target Path was: #{target_path}" unless target_exists
34
-
35
- if symlink_and_points_to_existing_file?(symlink_path)
36
- puts "React On Rails: Digested version of #{symlink} already exists indicating #{target} did not change."
37
- return
38
- end
39
-
40
- if file_or_symlink_exists_at_path?(symlink_path)
41
- puts "React On Rails: Removing existing invalid symlink or file #{symlink_path}"
42
- FileUtils.remove_file(symlink_path, true)
43
- end
44
-
45
- # Might be like:
46
- # "images/5cf5db49df178f9357603f945752a1ef.png":
47
- # "images/5cf5db49df178f9357603f945752a1ef-033650e1d6193b70d59bb60e773f47b6d9aefdd56abc7cc.png"
48
- # need to cd to directory and then symlink
49
- target_sub_path, _divider, target_filename = target.rpartition("/")
50
- _symlink_sub_path, _divider, symlink_filename = symlink.rpartition("/")
51
- dest_path = File.join(@assets_path, target_sub_path)
52
-
53
- puts "React On Rails: Symlinking \"#{target}\" to \"#{symlink}\""
54
- FileUtils.chdir(dest_path) do
55
- File.symlink(target_filename, symlink_filename)
56
- end
57
- end
58
-
59
- def symlink_non_digested_assets
60
- # digest ==> means that the file has a unique sha so the browser will load a new copy.
61
- # Webpack's CSS extract-text-plugin copies digested asset files over to directory where we put
62
- # we deploy the webpack compiled JS file. Since Rails will deploy the image files in this
63
- # directory with a digest, then the files are essentially "double-digested" and the CSS
64
- # references from webpack's CSS would be invalid. The fix is to symlink the double-digested
65
- # file back to the original digested name, and make a similar symlink for the gz version.
66
- return unless @symlink_non_digested_assets_regex
67
- manifest_glob = Dir.glob(@assets_path.join(".sprockets-manifest-*.json")) +
68
- Dir.glob(@assets_path.join("manifest-*.json")) +
69
- Dir.glob(@assets_path.join("manifest.yml"))
70
- if manifest_glob.empty?
71
- puts "Warning: React On Rails: expected to find .sprockets-manifest-*.json, manifest-*.json "\
72
- "or manifest.yml at #{@assets_path}, but found none. Canceling symlinking tasks."
73
- return -1
74
- end
75
- manifest_path = take_most_recent_manifest_path(manifest_glob)
76
- manifest_file = File.new(manifest_path)
77
- manifest_data = if File.extname(manifest_file) == ".json"
78
- manifest_file_data = File.read(manifest_path)
79
- JSON.parse(manifest_file_data)["assets"]
80
- else
81
- YAML.safe_load(manifest_file)
82
- end
83
-
84
- # We realize that we're copying other Rails assets that match the regexp, but this just
85
- # means that we'd be exposing the original, undigested names.
86
- manifest_data.each do |original_filename, rails_digested_filename|
87
- # TODO: we should remove any original_filename that is NOT in the webpack deploy folder.
88
- next unless original_filename =~ @symlink_non_digested_assets_regex
89
- # We're symlinking from the digested filename back to the original filename which has
90
- # already been symlinked by Webpack
91
- symlink_file(rails_digested_filename, original_filename)
92
-
93
- # We want the gz ones as well if they exist
94
- if File.exist?(@assets_path.join("#{rails_digested_filename}.gz"))
95
- symlink_file("#{rails_digested_filename}.gz", "#{original_filename}.gz")
96
- end
97
- end
98
- end
99
-
100
- def delete_broken_symlinks
101
- Dir.glob(@assets_path.join("*")).each do |filename|
102
- next unless File.lstat(filename).symlink?
103
- begin
104
- target = File.readlink(filename)
105
- rescue StandardError
106
- puts "React on Rails: Warning: your platform doesn't support File::readlink method." \
107
- "Skipping broken link check."
108
- break
109
- end
110
- path = Pathname.new(File.dirname(filename))
111
- target_path = path.join(target)
112
- unless File.exist?(target_path)
113
- puts "React on Rails: Deleting broken link: #{filename}"
114
- File.delete(filename)
115
- end
116
- end
117
- end
118
-
119
- def clobber
120
- dir = Rails.root.join(@generated_assets_dir)
121
- if dir.present? && File.directory?(dir)
122
- puts "Deleting files in directory #{dir}"
123
- FileUtils.rm_r(Dir.glob(Rails.root.join("#{@generated_assets_dir}/*")))
124
- else
125
- puts "Could not find generated_assets_dir #{dir} defined in react_on_rails initializer: "
126
- end
127
- end
128
-
129
- private
130
-
131
- def take_most_recent_manifest_path(manifest_glob)
132
- manifest_glob.max_by { |name| File.mtime(name) }
133
- end
134
-
135
- def symlink_and_points_to_existing_file?(symlink_path)
136
- # File.exist?(symlink_path) will check the file the sym is pointing to is existing
137
- # File.lstat(symlink_path).symlink? confirms that this is a symlink
138
- File.exist?(symlink_path) && File.lstat(symlink_path).symlink?
139
- end
140
-
141
- def file_or_symlink_exists_at_path?(path)
142
- # We use lstat and not stat, we we don't want to visit the file that the symlink maybe
143
- # pointing to. We can't use File.exist?, as that would check the file pointed at by the symlink.
144
- File.lstat(path)
145
- true
146
- rescue StandardError
147
- false
148
- end
149
- end
150
- end
@@ -1,136 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "erb"
4
-
5
- module ReactOnRails
6
- class LocalesToJs
7
- def initialize
8
- return if i18n_dir.nil?
9
- return unless obsolete?
10
- @translations, @defaults = generate_translations
11
- convert
12
- end
13
-
14
- private
15
-
16
- def obsolete?
17
- return true if exist_js_files.empty?
18
- js_files_are_outdated
19
- end
20
-
21
- def exist_js_files
22
- @exist_js_files ||= js_files.select(&File.method(:exist?))
23
- end
24
-
25
- def js_files_are_outdated
26
- latest_yml = locale_files.map(&File.method(:mtime)).max
27
- earliest_js = exist_js_files.map(&File.method(:mtime)).min
28
- latest_yml > earliest_js
29
- end
30
-
31
- def js_file_names
32
- %w[translations default]
33
- end
34
-
35
- def js_files
36
- @js_files ||= js_file_names.map { |n| js_file(n) }
37
- end
38
-
39
- def js_file(name)
40
- "#{i18n_dir}/#{name}.js"
41
- end
42
-
43
- def locale_files
44
- @locale_files ||= begin
45
- if i18n_yml_dir.present?
46
- Dir["#{i18n_yml_dir}/**/*.yml"]
47
- else
48
- ReactOnRails::Utils.truthy_presence(
49
- Rails.application && Rails.application.config.i18n.load_path
50
- ).presence
51
- end
52
- end
53
- end
54
-
55
- def i18n_dir
56
- @i18n_dir ||= ReactOnRails.configuration.i18n_dir
57
- end
58
-
59
- def i18n_yml_dir
60
- @i18n_yml_dir ||= ReactOnRails.configuration.i18n_yml_dir
61
- end
62
-
63
- def default_locale
64
- @default_locale ||= I18n.default_locale.to_s || "en"
65
- end
66
-
67
- def convert
68
- js_file_names.each do |name|
69
- template = send("template_#{name}")
70
- path = js_file(name)
71
- generate_js_file(template, path)
72
- end
73
- end
74
-
75
- def generate_js_file(template, path)
76
- result = ERB.new(template).result()
77
- File.open(path, "w") do |f|
78
- f.write(result)
79
- end
80
- end
81
-
82
- def generate_translations
83
- translations = {}
84
- defaults = {}
85
- locale_files.each do |f|
86
- translation = YAML.safe_load(File.open(f))
87
- key = translation.keys[0]
88
- val = flatten(translation[key])
89
- translations = translations.deep_merge(key => val)
90
- defaults = defaults.deep_merge(flatten_defaults(val)) if key == default_locale
91
- end
92
- [translations.to_json, defaults.to_json]
93
- end
94
-
95
- def format(input)
96
- input.to_s.tr(".", "_").camelize(:lower).to_sym
97
- end
98
-
99
- def flatten_defaults(val)
100
- flatten(val).each_with_object({}) do |(k, v), h|
101
- key = format(k)
102
- h[key] = { id: k, defaultMessage: v }
103
- end
104
- end
105
-
106
- def flatten(translations)
107
- translations.each_with_object({}) do |(k, v), h|
108
- if v.is_a? Hash
109
- flatten(v).map { |hk, hv| h["#{k}.#{hk}".to_sym] = hv }
110
- elsif v.is_a?(String)
111
- h[k] = v.gsub("%{", "{")
112
- elsif !v.is_a?(Array)
113
- h[k] = v
114
- end
115
- end
116
- end
117
-
118
- def template_translations
119
- <<-JS.strip_heredoc
120
- export const translations = #{@translations};
121
- JS
122
- end
123
-
124
- def template_default
125
- <<-JS.strip_heredoc
126
- import { defineMessages } from 'react-intl';
127
-
128
- const defaultLocale = \'#{default_locale}\';
129
-
130
- const defaultMessages = defineMessages(#{@defaults});
131
-
132
- export { defaultMessages, defaultLocale };
133
- JS
134
- end
135
- end
136
- end