react-rails 2.7.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +85 -42
- data/lib/assets/javascripts/react_ujs.js +1 -1
- data/lib/assets/react-source/development/react-server.js +333 -10
- data/lib/assets/react-source/development/react.js +19 -28
- data/lib/assets/react-source/production/react-server.js +1 -1
- data/lib/assets/react-source/production/react.js +1 -1
- data/lib/generators/react/component_generator.rb +126 -121
- data/lib/generators/react/install_generator.rb +50 -72
- data/lib/generators/templates/component.es6.jsx +8 -8
- data/lib/generators/templates/component.js.jsx +14 -14
- data/lib/generators/templates/react_server_rendering.rb +3 -1
- data/lib/react/jsx/babel_transformer.rb +12 -6
- data/lib/react/jsx/jsx_transformer.rb +7 -5
- data/lib/react/jsx/processor.rb +3 -1
- data/lib/react/jsx/sprockets_strategy.rb +17 -11
- data/lib/react/jsx/template.rb +7 -6
- data/lib/react/jsx.rb +9 -7
- data/lib/react/rails/asset_variant.rb +7 -6
- data/lib/react/rails/component_mount.rb +37 -29
- data/lib/react/rails/controller_lifecycle.rb +2 -0
- data/lib/react/rails/controller_renderer.rb +3 -1
- data/lib/react/rails/railtie.rb +19 -22
- data/lib/react/rails/test_helper.rb +3 -1
- data/lib/react/rails/version.rb +3 -1
- data/lib/react/rails/view_helper.rb +3 -1
- data/lib/react/rails.rb +9 -7
- data/lib/react/server_rendering/bundle_renderer.rb +34 -39
- data/lib/react/server_rendering/environment_container.rb +2 -0
- data/lib/react/server_rendering/exec_js_renderer.rb +15 -6
- data/lib/react/server_rendering/manifest_container.rb +6 -2
- data/lib/react/server_rendering/separate_server_bundle_container.rb +19 -0
- data/lib/react/server_rendering/yaml_manifest_container.rb +4 -2
- data/lib/react/server_rendering.rb +11 -9
- data/lib/react-rails.rb +8 -6
- data/lib/react.rb +2 -0
- metadata +5 -47
- data/lib/react/server_rendering/webpacker_manifest_container.rb +0 -96
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Generators
|
3
5
|
class ComponentGenerator < ::Rails::Generators::NamedBase
|
4
|
-
source_root File.expand_path
|
6
|
+
source_root File.expand_path "../templates", __dir__
|
5
7
|
desc <<-DESC.strip_heredoc
|
6
8
|
Description:
|
7
|
-
Scaffold a React component into `components/` of your
|
9
|
+
Scaffold a React component into `components/` of your Shakapacker source or asset pipeline.
|
8
10
|
The generated component will include a basic render function and a PropTypes
|
9
11
|
hash to help with development.
|
10
12
|
|
@@ -46,110 +48,101 @@ module React
|
|
46
48
|
DESC
|
47
49
|
|
48
50
|
argument :attributes,
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
51
|
+
type: :array,
|
52
|
+
default: [],
|
53
|
+
banner: "field[:type] field[:type] ..."
|
52
54
|
|
53
55
|
class_option :es6,
|
54
56
|
type: :boolean,
|
55
57
|
default: false,
|
56
|
-
desc:
|
58
|
+
desc: "Output es6 class based component"
|
57
59
|
|
58
60
|
class_option :ts,
|
59
61
|
type: :boolean,
|
60
62
|
default: false,
|
61
|
-
desc:
|
63
|
+
desc: "Output tsx class based component"
|
62
64
|
|
63
65
|
class_option :coffee,
|
64
66
|
type: :boolean,
|
65
67
|
default: false,
|
66
|
-
desc:
|
68
|
+
desc: "Output coffeescript based component"
|
67
69
|
|
68
70
|
REACT_PROP_TYPES = {
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
71
|
+
"node" => "PropTypes.node",
|
72
|
+
"bool" => "PropTypes.bool",
|
73
|
+
"boolean" => "PropTypes.bool",
|
74
|
+
"string" => "PropTypes.string",
|
75
|
+
"number" => "PropTypes.number",
|
76
|
+
"object" => "PropTypes.object",
|
77
|
+
"array" => "PropTypes.array",
|
78
|
+
"shape" => "PropTypes.shape({})",
|
79
|
+
"element" => "PropTypes.element",
|
80
|
+
"func" => "PropTypes.func",
|
81
|
+
"function" => "PropTypes.func",
|
82
|
+
"any" => "PropTypes.any",
|
83
|
+
|
84
|
+
"instanceOf" => lambda { |type|
|
85
|
+
"PropTypes.instanceOf(#{type.to_s.camelize})"
|
84
86
|
},
|
85
87
|
|
86
|
-
|
87
|
-
enums = options.map{ |k| "'#{k
|
88
|
-
|
88
|
+
"oneOf" => lambda { |*options|
|
89
|
+
enums = options.map { |k| "'#{k}'" }.join(",")
|
90
|
+
"PropTypes.oneOf([#{enums}])"
|
89
91
|
},
|
90
92
|
|
91
|
-
|
92
|
-
types = options.map{ |k|
|
93
|
-
|
93
|
+
"oneOfType" => lambda { |*options|
|
94
|
+
types = options.map { |k| lookup(k.to_s, k.to_s).to_s }.join(",")
|
95
|
+
"PropTypes.oneOfType([#{types}])"
|
94
96
|
}
|
95
|
-
}
|
97
|
+
}.freeze
|
96
98
|
|
97
99
|
TYPESCRIPT_TYPES = {
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
100
|
+
"node" => "React.ReactNode",
|
101
|
+
"bool" => "boolean",
|
102
|
+
"boolean" => "boolean",
|
103
|
+
"string" => "string",
|
104
|
+
"number" => "number",
|
105
|
+
"object" => "object",
|
106
|
+
"array" => "Array<any>",
|
107
|
+
"shape" => "object",
|
108
|
+
"element" => "object",
|
109
|
+
"func" => "object",
|
110
|
+
"function" => "object",
|
111
|
+
"any" => "any",
|
112
|
+
|
113
|
+
"instanceOf" => lambda { |type|
|
112
114
|
type.to_s.camelize
|
113
115
|
},
|
114
116
|
|
115
|
-
|
116
|
-
opts.map{ |k| "'#{k
|
117
|
+
"oneOf" => lambda { |*opts|
|
118
|
+
opts.map { |k| "'#{k}'" }.join(" | ")
|
117
119
|
},
|
118
120
|
|
119
|
-
|
120
|
-
opts.map{ |k|
|
121
|
+
"oneOfType" => lambda { |*opts|
|
122
|
+
opts.map { |k| ts_lookup(k.to_s, k.to_s).to_s }.join(" | ")
|
121
123
|
}
|
122
|
-
}
|
124
|
+
}.freeze
|
123
125
|
|
124
126
|
def create_component_file
|
125
|
-
template_extension =
|
126
|
-
|
127
|
-
|
128
|
-
'js.jsx.tsx'
|
129
|
-
elsif options[:es6] || webpacker?
|
130
|
-
'es6.jsx'
|
131
|
-
else
|
132
|
-
'js.jsx'
|
133
|
-
end
|
134
|
-
|
135
|
-
# Prefer webpacker to sprockets:
|
136
|
-
if webpacker?
|
127
|
+
template_extension = detect_template_extension
|
128
|
+
# Prefer Shakapacker to Sprockets:
|
129
|
+
if shakapacker?
|
137
130
|
new_file_name = file_name.camelize
|
138
131
|
extension = if options[:coffee]
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
132
|
+
"coffee"
|
133
|
+
elsif options[:ts]
|
134
|
+
"tsx"
|
135
|
+
else
|
136
|
+
"js"
|
137
|
+
end
|
145
138
|
target_dir = webpack_configuration.source_path
|
146
|
-
|
147
|
-
|
148
|
-
|
139
|
+
.join("components")
|
140
|
+
.relative_path_from(::Rails.root)
|
141
|
+
.to_s
|
149
142
|
else
|
150
143
|
new_file_name = file_name
|
151
144
|
extension = template_extension
|
152
|
-
target_dir =
|
145
|
+
target_dir = "app/assets/javascripts/components"
|
153
146
|
end
|
154
147
|
|
155
148
|
file_path = File.join(target_dir, class_path, "#{new_file_name}.#{extension}")
|
@@ -159,7 +152,7 @@ module React
|
|
159
152
|
private
|
160
153
|
|
161
154
|
def webpack_configuration
|
162
|
-
|
155
|
+
Shakapacker.respond_to?(:config) ? Shakapacker.config : Shakapacker::Configuration
|
163
156
|
end
|
164
157
|
|
165
158
|
def component_name
|
@@ -167,68 +160,68 @@ module React
|
|
167
160
|
end
|
168
161
|
|
169
162
|
def file_header
|
170
|
-
if
|
171
|
-
return
|
172
|
-
|
163
|
+
if shakapacker?
|
164
|
+
return %(import * as React from "react"\n) if options[:ts]
|
165
|
+
|
166
|
+
<<~JS
|
167
|
+
import React from "react"
|
168
|
+
import PropTypes from "prop-types"
|
169
|
+
JS
|
173
170
|
else
|
174
|
-
|
171
|
+
""
|
175
172
|
end
|
176
173
|
end
|
177
174
|
|
178
175
|
def file_footer
|
179
|
-
if
|
180
|
-
|
176
|
+
if shakapacker?
|
177
|
+
%(export default #{component_name})
|
181
178
|
else
|
182
|
-
|
179
|
+
""
|
183
180
|
end
|
184
181
|
end
|
185
182
|
|
186
|
-
def
|
187
|
-
defined?(
|
183
|
+
def shakapacker?
|
184
|
+
defined?(Shakapacker)
|
188
185
|
end
|
189
186
|
|
190
187
|
def parse_attributes!
|
191
188
|
self.attributes = (attributes || []).map do |attr|
|
192
|
-
|
193
|
-
type = ''
|
194
|
-
args = ''
|
189
|
+
args = ""
|
195
190
|
args_regex = /(?<args>{.*})/
|
196
191
|
|
197
|
-
name, type = attr.split(
|
192
|
+
name, type = attr.split(":")
|
198
193
|
|
199
|
-
if matchdata = args_regex.match(type)
|
194
|
+
if (matchdata = args_regex.match(type))
|
200
195
|
args = matchdata[:args]
|
201
|
-
type = type.gsub(args_regex,
|
196
|
+
type = type.gsub(args_regex, "")
|
202
197
|
end
|
203
198
|
|
204
199
|
if options[:ts]
|
205
|
-
{ :
|
200
|
+
{ name: name, type: ts_lookup(name, type, args), union: union?(args) }
|
206
201
|
else
|
207
|
-
{ :
|
202
|
+
{ name: name, type: lookup(type, args) }
|
208
203
|
end
|
209
204
|
end
|
210
205
|
end
|
211
206
|
|
212
|
-
def union?(args =
|
213
|
-
|
207
|
+
def union?(args = "")
|
208
|
+
args.to_s.gsub(/[{}]/, "").split(",").count > 1
|
214
209
|
end
|
215
210
|
|
216
|
-
def self.ts_lookup(
|
211
|
+
def self.ts_lookup(_name, type = "node", args = "")
|
217
212
|
ts_type = TYPESCRIPT_TYPES[type]
|
218
213
|
if ts_type.blank?
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
214
|
+
ts_type = if /^[[:upper:]]/.match?(type)
|
215
|
+
TYPESCRIPT_TYPES["instanceOf"]
|
216
|
+
else
|
217
|
+
TYPESCRIPT_TYPES["node"]
|
218
|
+
end
|
224
219
|
end
|
225
220
|
|
226
|
-
args = args.to_s.gsub(/[{}]/,
|
221
|
+
args = args.to_s.gsub(/[{}]/, "").split(",")
|
227
222
|
|
228
223
|
if ts_type.respond_to? :call
|
229
|
-
if args.blank?
|
230
|
-
return ts_type.call(type)
|
231
|
-
end
|
224
|
+
return ts_type.call(type) if args.blank?
|
232
225
|
|
233
226
|
ts_type = ts_type.call(*args)
|
234
227
|
end
|
@@ -236,29 +229,41 @@ module React
|
|
236
229
|
ts_type
|
237
230
|
end
|
238
231
|
|
239
|
-
def ts_lookup(name, type =
|
232
|
+
def ts_lookup(name, type = "node", args = "")
|
240
233
|
self.class.ts_lookup(name, type, args)
|
241
234
|
end
|
242
235
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
236
|
+
def self.lookup(type = "node", options = "")
|
237
|
+
react_prop_type = REACT_PROP_TYPES[type]
|
238
|
+
if react_prop_type.blank?
|
239
|
+
react_prop_type = if /^[[:upper:]]/.match?(type)
|
240
|
+
REACT_PROP_TYPES["instanceOf"]
|
241
|
+
else
|
242
|
+
REACT_PROP_TYPES["node"]
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
options = options.to_s.gsub(/[{}]/, "").split(",")
|
247
|
+
|
248
|
+
react_prop_type = react_prop_type.call(*options) if react_prop_type.respond_to? :call
|
249
|
+
react_prop_type
|
250
|
+
end
|
251
|
+
|
252
|
+
def lookup(type = "node", options = "")
|
253
|
+
self.class.lookup(type, options)
|
254
|
+
end
|
255
|
+
|
256
|
+
def detect_template_extension
|
257
|
+
if options[:coffee]
|
258
|
+
"js.jsx.coffee"
|
259
|
+
elsif options[:ts]
|
260
|
+
"js.jsx.tsx"
|
261
|
+
elsif options[:es6] || shakapacker?
|
262
|
+
"es6.jsx"
|
263
|
+
else
|
264
|
+
"js.jsx"
|
265
|
+
end
|
266
|
+
end
|
262
267
|
end
|
263
268
|
end
|
264
269
|
end
|
@@ -1,51 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module React
|
2
4
|
module Generators
|
3
5
|
class InstallGenerator < ::Rails::Generators::Base
|
4
|
-
source_root File.expand_path
|
6
|
+
source_root File.expand_path "../templates", __dir__
|
5
7
|
|
6
|
-
desc
|
8
|
+
desc "Create default react.js folder layout and prep application.js"
|
7
9
|
|
8
10
|
class_option :skip_git,
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
type: :boolean,
|
12
|
+
aliases: "-g",
|
13
|
+
default: false,
|
14
|
+
desc: "Skip Git keeps"
|
13
15
|
|
14
16
|
class_option :skip_server_rendering,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# For Shakapacker below version 7, we need to set relative path for source_entry_path
|
20
|
-
def modify_webpacker_yml
|
21
|
-
webpacker_yml_path = 'config/webpacker.yml'
|
22
|
-
if webpacker? && Pathname.new(webpacker_yml_path).exist?
|
23
|
-
gsub_file(
|
24
|
-
webpacker_yml_path,
|
25
|
-
"source_entry_path: /\n",
|
26
|
-
"source_entry_path: packs\n"
|
27
|
-
)
|
28
|
-
reloaded_webpacker_config
|
29
|
-
end
|
30
|
-
end
|
17
|
+
type: :boolean,
|
18
|
+
default: false,
|
19
|
+
desc: "Don't generate server_rendering.js or config/initializers/react_server_rendering.rb"
|
31
20
|
|
32
21
|
# Make an empty `components/` directory in the right place:
|
33
22
|
def create_directory
|
34
|
-
components_dir = if
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
empty_directory File.join(components_dir,
|
40
|
-
|
41
|
-
|
42
|
-
|
23
|
+
components_dir = if shakapacker?
|
24
|
+
Pathname.new(javascript_dir).parent.to_s
|
25
|
+
else
|
26
|
+
javascript_dir
|
27
|
+
end
|
28
|
+
empty_directory File.join(components_dir, "components")
|
29
|
+
return if options[:skip_git]
|
30
|
+
|
31
|
+
create_file File.join(components_dir, "components/.keep")
|
43
32
|
end
|
44
33
|
|
45
34
|
# Add requires, setup UJS
|
46
35
|
def setup_react
|
47
|
-
if
|
48
|
-
|
36
|
+
if shakapacker?
|
37
|
+
setup_react_shakapacker
|
49
38
|
else
|
50
39
|
setup_react_sprockets
|
51
40
|
end
|
@@ -53,36 +42,36 @@ module React
|
|
53
42
|
|
54
43
|
def create_server_rendering
|
55
44
|
if options[:skip_server_rendering]
|
56
|
-
|
57
|
-
elsif
|
58
|
-
ssr_manifest_path = File.join(javascript_dir,
|
59
|
-
template(
|
45
|
+
nil
|
46
|
+
elsif shakapacker?
|
47
|
+
ssr_manifest_path = File.join(javascript_dir, "server_rendering.js")
|
48
|
+
template("server_rendering_pack.js", ssr_manifest_path)
|
60
49
|
else
|
61
|
-
ssr_manifest_path = File.join(javascript_dir,
|
62
|
-
template(
|
63
|
-
initializer_path =
|
64
|
-
template(
|
50
|
+
ssr_manifest_path = File.join(javascript_dir, "server_rendering.js")
|
51
|
+
template("server_rendering.js", ssr_manifest_path)
|
52
|
+
initializer_path = "config/initializers/react_server_rendering.rb"
|
53
|
+
template("react_server_rendering.rb", initializer_path)
|
65
54
|
end
|
66
55
|
end
|
67
56
|
|
68
57
|
private
|
69
58
|
|
70
|
-
def
|
71
|
-
!!defined?(
|
59
|
+
def shakapacker?
|
60
|
+
!!defined?(Shakapacker)
|
72
61
|
end
|
73
62
|
|
74
63
|
def javascript_dir
|
75
|
-
if
|
76
|
-
|
64
|
+
if shakapacker?
|
65
|
+
shakapacker_source_path
|
77
66
|
.relative_path_from(::Rails.root)
|
78
67
|
.to_s
|
79
68
|
else
|
80
|
-
|
69
|
+
"app/assets/javascripts"
|
81
70
|
end
|
82
71
|
end
|
83
72
|
|
84
73
|
def manifest
|
85
|
-
Pathname.new(destination_root).join(javascript_dir,
|
74
|
+
Pathname.new(destination_root).join(javascript_dir, "application.js")
|
86
75
|
end
|
87
76
|
|
88
77
|
def setup_react_sprockets
|
@@ -91,9 +80,9 @@ module React
|
|
91
80
|
if manifest.exist?
|
92
81
|
manifest_contents = File.read(manifest)
|
93
82
|
|
94
|
-
if match = manifest_contents.match(
|
83
|
+
if (match = manifest_contents.match(%r{//=\s+require\s+turbolinks\s+\n}))
|
95
84
|
inject_into_file manifest, require_react, { after: match[0] }
|
96
|
-
elsif match = manifest_contents.match(
|
85
|
+
elsif (match = manifest_contents.match(%r{//=\s+require_tree[^\n]*}))
|
97
86
|
inject_into_file manifest, require_react, { before: match[0] }
|
98
87
|
else
|
99
88
|
append_file manifest, require_react
|
@@ -103,39 +92,28 @@ module React
|
|
103
92
|
end
|
104
93
|
|
105
94
|
components_js = "//= require_tree ./components\n"
|
106
|
-
components_file = File.join(javascript_dir,
|
95
|
+
components_file = File.join(javascript_dir, "components.js")
|
107
96
|
create_file components_file, components_js
|
108
97
|
end
|
109
98
|
|
110
|
-
|
111
|
-
// Support component names relative to this directory:
|
112
|
-
var componentRequireContext = require.context("components", true);
|
113
|
-
var ReactRailsUJS = require("react_ujs");
|
114
|
-
ReactRailsUJS.useContext(componentRequireContext);
|
115
|
-
JS
|
99
|
+
SHAKAPACKER_SETUP_UJS = <<~JS
|
100
|
+
// Support component names relative to this directory:
|
101
|
+
var componentRequireContext = require.context("components", true);
|
102
|
+
var ReactRailsUJS = require("react_ujs");
|
103
|
+
ReactRailsUJS.useContext(componentRequireContext);
|
104
|
+
JS
|
116
105
|
|
117
|
-
def
|
106
|
+
def setup_react_shakapacker
|
118
107
|
`yarn add react_ujs`
|
119
108
|
if manifest.exist?
|
120
|
-
append_file(manifest,
|
121
|
-
else
|
122
|
-
create_file(manifest, WEBPACKER_SETUP_UJS)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
private
|
127
|
-
|
128
|
-
def webpack_source_path
|
129
|
-
if Webpacker.respond_to?(:config)
|
130
|
-
Webpacker.config.source_entry_path # Webpacker >3
|
109
|
+
append_file(manifest, SHAKAPACKER_SETUP_UJS)
|
131
110
|
else
|
132
|
-
|
111
|
+
create_file(manifest, SHAKAPACKER_SETUP_UJS)
|
133
112
|
end
|
134
113
|
end
|
135
114
|
|
136
|
-
def
|
137
|
-
|
138
|
-
Webpacker.config
|
115
|
+
def shakapacker_source_path
|
116
|
+
Shakapacker.config.source_entry_path
|
139
117
|
end
|
140
118
|
end
|
141
119
|
end
|
@@ -1,13 +1,12 @@
|
|
1
|
-
<%= file_header %>
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
<%= file_header %>
|
2
|
+
const <%= component_name %> = (props) => {
|
3
|
+
return (
|
4
|
+
<React.Fragment>
|
5
5
|
<% attributes.each do |attribute| -%>
|
6
|
-
|
6
|
+
<%= attribute[:name].titleize %>: {props.<%= attribute[:name].camelize(:lower) %>}
|
7
7
|
<% end -%>
|
8
|
-
|
9
|
-
|
10
|
-
}
|
8
|
+
</React.Fragment>
|
9
|
+
)
|
11
10
|
}
|
12
11
|
|
13
12
|
<% if attributes.size > 0 -%>
|
@@ -17,4 +16,5 @@
|
|
17
16
|
<% end -%>
|
18
17
|
};
|
19
18
|
<% end -%>
|
19
|
+
|
20
20
|
<%= file_footer %>
|
@@ -1,20 +1,20 @@
|
|
1
|
-
<%= file_header %>
|
1
|
+
<%= file_header %>
|
2
|
+
function <%= component_name %>(props) {
|
3
|
+
return (
|
4
|
+
<React.Fragment>
|
5
|
+
<% attributes.each do |attribute| -%>
|
6
|
+
<%= attribute[:name].titleize %>: {props.<%= attribute[:name].camelize(:lower) %>}
|
7
|
+
<% end -%>
|
8
|
+
</React.Fragment>
|
9
|
+
);
|
10
|
+
}
|
11
|
+
|
2
12
|
<% if attributes.size > 0 -%>
|
3
|
-
|
13
|
+
<%= file_name.camelize %>.propTypes = {
|
4
14
|
<% attributes.each_with_index do |attribute, idx| -%>
|
5
|
-
|
15
|
+
<%= attribute[:name].camelize(:lower) %>: <%= attribute[:type] %><% if (idx < attributes.length-1) %>,<% end %>
|
6
16
|
<% end -%>
|
7
|
-
|
17
|
+
};
|
8
18
|
<% end -%>
|
9
19
|
|
10
|
-
render: function() {
|
11
|
-
return (
|
12
|
-
<React.Fragment>
|
13
|
-
<% attributes.each do |attribute| -%>
|
14
|
-
<%= attribute[:name].titleize %>: {this.props.<%= attribute[:name].camelize(:lower) %>}
|
15
|
-
<% end -%>
|
16
|
-
</React.Fragment>
|
17
|
-
);
|
18
|
-
}
|
19
|
-
});
|
20
20
|
<%= file_footer %>
|
@@ -1,21 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "babel/transpiler"
|
2
4
|
module React
|
3
5
|
module JSX
|
4
6
|
# A {React::JSX}-compliant transformer which uses `Babel::Transpiler` to transform JSX.
|
5
7
|
class BabelTransformer
|
6
|
-
DEPRECATED_OPTIONS = [
|
7
|
-
DEFAULT_TRANSFORM_OPTIONS = { blacklist: [
|
8
|
+
DEPRECATED_OPTIONS = %i[harmony strip_types asset_path].freeze
|
9
|
+
DEFAULT_TRANSFORM_OPTIONS = { blacklist: ["spec.functionName", "validation.react", "strict"] }.freeze
|
8
10
|
def initialize(options)
|
9
11
|
if (options.keys & DEPRECATED_OPTIONS).any?
|
10
|
-
ActiveSupport::Deprecation.warn(
|
11
|
-
|
12
|
+
ActiveSupport::Deprecation.warn(
|
13
|
+
<<-MSG
|
14
|
+
Setting config.react.jsx_transform_options for :harmony, :strip_types, and :asset_path keys is now deprecated and has no effect with the default Babel Transformer.
|
15
|
+
Please use new Babel Transformer options :whitelist, :plugin instead.
|
16
|
+
MSG
|
17
|
+
)
|
12
18
|
end
|
13
19
|
|
14
20
|
@transform_options = DEFAULT_TRANSFORM_OPTIONS.merge(options)
|
15
21
|
end
|
16
22
|
|
17
23
|
def transform(code)
|
18
|
-
Babel::Transpiler.transform(code, @transform_options)[
|
24
|
+
Babel::Transpiler.transform(code, @transform_options)["code"]
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|