react_on_rails 1.2.2 → 2.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. metadata +5 -126
  3. data/.babelrc +0 -3
  4. data/.coveralls.yml +0 -1
  5. data/.dockerignore +0 -2
  6. data/.eslintignore +0 -5
  7. data/.eslintrc +0 -48
  8. data/.gitignore +0 -26
  9. data/.jscsrc +0 -26
  10. data/.rspec +0 -2
  11. data/.rubocop.yml +0 -70
  12. data/.scss-lint.yml +0 -205
  13. data/.travis.yml +0 -41
  14. data/CHANGELOG.md +0 -42
  15. data/Dockerfile_tests +0 -12
  16. data/Gemfile +0 -38
  17. data/README.md +0 -363
  18. data/Rakefile +0 -5
  19. data/app/assets/javascripts/react_on_rails.js +0 -241
  20. data/app/helpers/react_on_rails_helper.rb +0 -224
  21. data/docker-compose.yml +0 -11
  22. data/docs/LICENSE +0 -21
  23. data/docs/additional_reading/heroku_deployment.md +0 -23
  24. data/docs/additional_reading/manual_installation.md +0 -142
  25. data/docs/additional_reading/node_dependencies_and_npm.md +0 -29
  26. data/docs/additional_reading/optional_configuration.md +0 -34
  27. data/docs/additional_reading/react-and-redux.md +0 -36
  28. data/docs/additional_reading/react_router.md +0 -45
  29. data/docs/additional_reading/server_rendering_tips.md +0 -16
  30. data/docs/additional_reading/tips.md +0 -10
  31. data/docs/additional_reading/webpack.md +0 -46
  32. data/docs/code_of_conduct.md +0 -13
  33. data/docs/coding-style/linters.md +0 -64
  34. data/docs/coding-style/style.md +0 -42
  35. data/docs/contributing.md +0 -62
  36. data/docs/generator_testing.md +0 -20
  37. data/docs/install_and_releasing.md +0 -24
  38. data/docs/sample_generated_js/README.md +0 -4
  39. data/docs/sample_generated_js/client-generated.js +0 -12
  40. data/docs/sample_generated_js/server-generated.js +0 -25
  41. data/lib/generators/USAGE +0 -99
  42. data/lib/generators/react_on_rails/base_generator.rb +0 -198
  43. data/lib/generators/react_on_rails/bootstrap_generator.rb +0 -91
  44. data/lib/generators/react_on_rails/dev_tests_generator.rb +0 -30
  45. data/lib/generators/react_on_rails/generator_errors.rb +0 -15
  46. data/lib/generators/react_on_rails/generator_helper.rb +0 -58
  47. data/lib/generators/react_on_rails/heroku_deployment_generator.rb +0 -30
  48. data/lib/generators/react_on_rails/install_generator.rb +0 -111
  49. data/lib/generators/react_on_rails/js_linters_generator.rb +0 -19
  50. data/lib/generators/react_on_rails/react_no_redux_generator.rb +0 -41
  51. data/lib/generators/react_on_rails/react_with_redux_generator.rb +0 -52
  52. data/lib/generators/react_on_rails/ruby_linters_generator.rb +0 -33
  53. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +0 -4
  54. data/lib/generators/react_on_rails/templates/base/base/REACT_ON_RAILS.md +0 -16
  55. data/lib/generators/react_on_rails/templates/base/base/app/controllers/hello_world_controller.rb +0 -5
  56. data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +0 -5
  57. data/lib/generators/react_on_rails/templates/base/base/client/.babelrc +0 -3
  58. data/lib/generators/react_on_rails/templates/base/base/client/REACT_ON_RAILS_CLIENT_README.md +0 -3
  59. data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/startup/globals.jsx.tt +0 -5
  60. data/lib/generators/react_on_rails/templates/base/base/client/index.jade +0 -15
  61. data/lib/generators/react_on_rails/templates/base/base/client/npm-shrinkwrap.json +0 -2907
  62. data/lib/generators/react_on_rails/templates/base/base/client/package.json.tt +0 -98
  63. data/lib/generators/react_on_rails/templates/base/base/client/server.js +0 -64
  64. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.base.config.js.tt +0 -67
  65. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.hot.config.js.tt +0 -67
  66. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.rails.config.js +0 -41
  67. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +0 -28
  68. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/assets.rake.tt +0 -26
  69. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/linters.rake.tt +0 -88
  70. data/lib/generators/react_on_rails/templates/base/base/package.json +0 -31
  71. data/lib/generators/react_on_rails/templates/base/server_rendering/client/app/bundles/HelloWorld/startup/serverGlobals.jsx +0 -3
  72. data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +0 -40
  73. data/lib/generators/react_on_rails/templates/bootstrap/app/assets/stylesheets/_bootstrap-custom.scss +0 -63
  74. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_post-bootstrap.scss +0 -10
  75. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_pre-bootstrap.scss +0 -8
  76. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_react-on-rails-sass-helper.scss +0 -19
  77. data/lib/generators/react_on_rails/templates/bootstrap/client/bootstrap-sass.config.js +0 -89
  78. data/lib/generators/react_on_rails/templates/dev_tests/.rspec +0 -2
  79. data/lib/generators/react_on_rails/templates/dev_tests/spec/features/hello_world_spec.rb +0 -25
  80. data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +0 -57
  81. data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +0 -21
  82. data/lib/generators/react_on_rails/templates/dev_tests/spec/spec_helper.rb +0 -95
  83. data/lib/generators/react_on_rails/templates/heroku_deployment/.buildpacks +0 -2
  84. data/lib/generators/react_on_rails/templates/heroku_deployment/Procfile +0 -1
  85. data/lib/generators/react_on_rails/templates/heroku_deployment/config/puma.rb +0 -15
  86. data/lib/generators/react_on_rails/templates/js_linters/client/.eslintignore +0 -1
  87. data/lib/generators/react_on_rails/templates/js_linters/client/.eslintrc +0 -48
  88. data/lib/generators/react_on_rails/templates/js_linters/client/.jscsrc +0 -18
  89. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +0 -39
  90. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +0 -33
  91. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx.tt +0 -12
  92. data/lib/generators/react_on_rails/templates/no_redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +0 -11
  93. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx +0 -8
  94. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +0 -48
  95. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx +0 -8
  96. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +0 -43
  97. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx +0 -21
  98. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/index.jsx +0 -14
  99. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx.tt +0 -21
  100. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/store/helloWorldStore.jsx +0 -35
  101. data/lib/generators/react_on_rails/templates/redux/base/client/app/lib/middlewares/loggerMiddleware.js +0 -20
  102. data/lib/generators/react_on_rails/templates/redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +0 -21
  103. data/lib/generators/react_on_rails/templates/ruby_linters/.rubocop.yml +0 -26
  104. data/lib/generators/react_on_rails/templates/ruby_linters/.scss-lint.yml +0 -205
  105. data/lib/generators/react_on_rails/templates/ruby_linters/lib/tasks/brakeman.rake +0 -17
  106. data/lib/generators/react_on_rails/templates/ruby_linters/lib/tasks/ci.rake +0 -33
  107. data/lib/generators/react_on_rails/templates/ruby_linters/ruby-lint.yml +0 -20
  108. data/lib/react_on_rails.rb +0 -6
  109. data/lib/react_on_rails/configuration.rb +0 -53
  110. data/lib/react_on_rails/engine.rb +0 -7
  111. data/lib/react_on_rails/prerender_error.rb +0 -31
  112. data/lib/react_on_rails/server_rendering_pool.rb +0 -111
  113. data/lib/react_on_rails/version.rb +0 -3
  114. data/rakelib/docker.rake +0 -33
  115. data/rakelib/dummy_apps.rake +0 -29
  116. data/rakelib/example_type.rb +0 -160
  117. data/rakelib/examples.rake +0 -103
  118. data/rakelib/examples_config.yml +0 -19
  119. data/rakelib/lint.rake +0 -37
  120. data/rakelib/run_rspec.rake +0 -65
  121. data/rakelib/task_helpers.rb +0 -44
  122. data/react_on_rails.gemspec +0 -31
  123. data/ruby-lint.yml +0 -24
data/Rakefile DELETED
@@ -1,5 +0,0 @@
1
- # Rake will automatically load any *.rake files inside of the "rakelib" folder
2
- # See rakelib/
3
-
4
- desc "Run all tests and linting"
5
- task default: ["run_rspec", "docker:lint"]
@@ -1,241 +0,0 @@
1
- (function() {
2
- this.ReactOnRails = {};
3
- var turbolinksInstalled = (typeof Turbolinks !== 'undefined');
4
-
5
- ReactOnRails.serverRenderReactComponent = function(options) {
6
- var componentName = options.componentName;
7
- var domId = options.domId;
8
- var props = options.props;
9
- var trace = options.trace;
10
- var generatorFunction = options.generatorFunction;
11
- var location = options.location;
12
- var htmlResult = '';
13
- var consoleReplay = '';
14
- var hasErrors = false;
15
-
16
- try {
17
- var reactElementOrRouterResult = createReactElementOrRouterResult(componentName, props,
18
- domId, trace, generatorFunction, location);
19
- if (isRouterResult(reactElementOrRouterResult)) {
20
-
21
- // We let the client side handle any redirect
22
- // Set hasErrors in case we want to throw a Rails exception
23
- hasErrors = !!reactElementOrRouterResult.routeError;
24
- if (hasErrors) {
25
- console.error('React Router ERROR: ' +
26
- JSON.stringify(reactElementOrRouterResult.routeError));
27
- } else {
28
- if (trace) {
29
- redirectLocation = reactElementOrRouterResult.redirectLocation;
30
- redirectPath = redirectLocation.pathname + redirectLocation.search;
31
- console.log('ROUTER REDIRECT: ' + componentName + ' to dom node with id: ' + domId +
32
- ', redirect to ' + redirectPath);
33
- }
34
- }
35
- } else {
36
- htmlResult = provideServerReact().renderToString(reactElementOrRouterResult);
37
- }
38
- }
39
- catch (e) {
40
- hasErrors = true;
41
- htmlResult = ReactOnRails.handleError({
42
- e: e,
43
- componentName: componentName,
44
- serverSide: true,
45
- });
46
- }
47
-
48
- consoleReplayScript = ReactOnRails.buildConsoleReplay();
49
-
50
- return JSON.stringify({
51
- html: htmlResult,
52
- consoleReplayScript: consoleReplayScript,
53
- hasErrors: hasErrors,
54
- });
55
- };
56
-
57
- // Passing either componentName or jsCode
58
- ReactOnRails.handleError = function(options) {
59
- var e = options.e;
60
- var componentName = options.componentName;
61
- var jsCode = options.jsCode;
62
- var serverSide = options.serverSide;
63
-
64
- var lineOne =
65
- 'ERROR: You specified the option generator_function (could be in your defaults) to be\n';
66
- var lastLine =
67
- 'A generator function takes a single arg of props and returns a ReactElement.';
68
-
69
- console.error('Exception in rendering!');
70
-
71
- var msg = '';
72
- if (componentName) {
73
- var shouldBeGeneratorError = lineOne +
74
- 'false, but the React component \'' + componentName + '\' seems to be a generator function.\n' +
75
- lastLine;
76
- var reMatchShouldBeGeneratorError = /Can't add property context, object is not extensible/;
77
- if (reMatchShouldBeGeneratorError.test(e.message)) {
78
- msg += shouldBeGeneratorError + '\n\n';
79
- console.error(shouldBeGeneratorError);
80
- }
81
-
82
- var shouldBeGeneratorError = lineOne +
83
- 'true, but the React component \'' + componentName + '\' is not a generator function.\n' +
84
- lastLine;
85
- var reMatchShouldNotBeGeneratorError = /Cannot call a class as a function/;
86
- if (reMatchShouldNotBeGeneratorError.test(e.message)) {
87
- msg += shouldBeGeneratorError + '\n\n';
88
- console.error(shouldBeGeneratorError);
89
- }
90
- }
91
-
92
- if (jsCode) {
93
- console.error('JS code was: ' + jsCode);
94
- }
95
-
96
- if (e.fileName) {
97
- console.error('location: ' + e.fileName + ':' + e.lineNumber);
98
- }
99
-
100
- console.error('message: ' + e.message);
101
- console.error('stack: ' + e.stack);
102
- if (serverSide) {
103
- msg += 'Exception in rendering!\n' +
104
- (e.fileName ? '\nlocation: ' + e.fileName + ':' + e.lineNumber : '') +
105
- '\nMessage: ' + e.message + '\n\n' + e.stack;
106
- var reactElement = React.createElement('pre', null, msg);
107
- return provideServerReact().renderToString(reactElement);
108
- }
109
- };
110
-
111
- ReactOnRails.wrapInScriptTags = function(scriptBody) {
112
- if (!scriptBody) {
113
- return '';
114
- }
115
-
116
- return '\n<script>' + scriptBody + '\n</script>';
117
- };
118
-
119
- ReactOnRails.buildConsoleReplay = function() {
120
- var consoleReplay = '';
121
-
122
- var history = console.history;
123
- if (history && history.length > 0) {
124
- history.forEach(function(msg) {
125
- consoleReplay += '\nconsole.' + msg.level + '.apply(console, ' +
126
- JSON.stringify(msg.arguments) + ');';
127
- });
128
- }
129
-
130
- return ReactOnRails.wrapInScriptTags(consoleReplay);
131
- };
132
-
133
- function forEachComponent(fn) {
134
- var els = document.getElementsByClassName('js-react-on-rails-component');
135
- for (var i = 0; i < els.length; i++) {
136
- fn(els[i]);
137
- };
138
- }
139
-
140
- function reactOnRailsPageLoaded() {
141
- forEachComponent(render);
142
- }
143
-
144
- function reactOnRailsPageUnloaded() {
145
- forEachComponent(unmount);
146
- }
147
-
148
- function unmount(el) {
149
- var domId = el.getAttribute('data-dom-id');
150
- var domNode = document.getElementById(domId);
151
- provideClientReact().unmountComponentAtNode(domNode);
152
- }
153
-
154
- function render(el) {
155
- var componentName = el.getAttribute('data-component-name');
156
- var domId = el.getAttribute('data-dom-id');
157
- var props = JSON.parse(el.getAttribute('data-props'));
158
- var trace = JSON.parse(el.getAttribute('data-trace'));
159
- var generatorFunction = JSON.parse(el.getAttribute('data-generator-function'));
160
- var expectTurboLinks = JSON.parse(el.getAttribute('data-expect-turbo-links'));
161
-
162
- if (!turbolinksInstalled && expectTurboLinks) {
163
- console.warn('WARNING: NO TurboLinks detected in JS, but it is in your Gemfile');
164
- }
165
-
166
- try {
167
- var domNode = document.getElementById(domId);
168
- if (domNode) {
169
- var reactElementOrRouterResult = createReactElementOrRouterResult(componentName, props,
170
- domId, trace, generatorFunction);
171
- if (isRouterResult(reactElementOrRouterResult)) {
172
- throw new Error('You returned a server side type of react-router error: ' +
173
- JSON.stringify(reactElementOrRouterResult) +
174
- '\nYou should return a React.Component always for the client side entry point.');
175
- } else {
176
- provideClientReact().render(reactElementOrRouterResult, domNode);
177
- }
178
- }
179
- }
180
- catch (e) {
181
- ReactOnRails.handleError({
182
- e: e,
183
- componentName: componentName,
184
- serverSide: false,
185
- });
186
- }
187
- };
188
-
189
- function createReactElementOrRouterResult(componentName, props, domId, trace, generatorFunction, location) {
190
- if (trace) {
191
- console.log('RENDERED ' + componentName + ' to dom node with id: ' + domId);
192
- }
193
-
194
- if (generatorFunction) {
195
- return this[componentName](props, location);
196
- } else {
197
- return React.createElement(this[componentName], props);
198
- }
199
- }
200
-
201
- function provideClientReact() {
202
- if (typeof ReactDOM === 'undefined') {
203
- if (React.version >= '0.14') {
204
- console.warn('WARNING: ReactDOM is not configured in webpack.server.rails.config.js file as an entry.\n' +
205
- 'See: https://github.com/shakacode/react_on_rails/blob/master/docs/webpack.md for more detailed hints.');
206
- }
207
-
208
- return React;
209
- }
210
-
211
- return ReactDOM;
212
- }
213
-
214
- function provideServerReact() {
215
- if (typeof ReactDOMServer === 'undefined') {
216
- if (React.version >= '0.14') {
217
- console.warn('WARNING: `react-dom/server` is not configured in webpack.server.rails.config.js file as an entry.\n' +
218
- 'See: https://github.com/shakacode/react_on_rails/blob/master/docs/webpack.md for more detailed hints.');
219
- }
220
-
221
- return React;
222
- }
223
-
224
- return ReactDOMServer;
225
- }
226
-
227
- function isRouterResult(reactElementOrRouterResult) {
228
- return !!(reactElementOrRouterResult.redirectLocation ||
229
- reactElementOrRouterResult.error);
230
- }
231
-
232
- // Install listeners when running on the client.
233
- if (typeof document !== 'undefined') {
234
- if (!turbolinksInstalled) {
235
- document.addEventListener('DOMContentLoaded', reactOnRailsPageLoaded);
236
- } else {
237
- document.addEventListener('page:before-unload', reactOnRailsPageUnloaded);
238
- document.addEventListener('page:change', reactOnRailsPageLoaded);
239
- }
240
- }
241
- }.call(this));
@@ -1,224 +0,0 @@
1
- # NOTE:
2
- # For any heredoc JS:
3
- # 1. The white spacing in this file matters!
4
- # 2. Keep all #{some_var} fully to the left so that all indentation is done evenly in that var
5
- require "react_on_rails/prerender_error"
6
-
7
- module ReactOnRailsHelper
8
- # react_component_name: can be a React component, created using a ES6 class, or
9
- # React.createClass, or a
10
- # `generator function` that returns a React component
11
- # using ES6
12
- # let MyReactComponentApp = (props) => <MyReactComponent {...props}/>;
13
- # or using ES5
14
- # var MyReactComponentApp = function(props) { return <YourReactComponent {...props}/>; }
15
- # Exposing the react_component_name is necessary to both a plain ReactComponent as well as
16
- # a generator:
17
- # For client rendering, expose the react_component_name on window:
18
- # window.MyReactComponentApp = MyReactComponentApp;
19
- # For server rendering, export the react_component_name on global:
20
- # global.MyReactComponentApp = MyReactComponentApp;
21
- # See spec/dummy/client/app/startup/serverGlobals.jsx and
22
- # spec/dummy/client/app/startup/ClientApp.jsx for examples of this
23
- # props: Ruby Hash or JSON string which contains the properties to pass to the react object
24
- #
25
- # options:
26
- # generator_function: <true/false> default is false, set to true if you want to use a
27
- # generator function rather than a React Component.
28
- # prerender: <true/false> set to false when debugging!
29
- # trace: <true/false> set to true to print additional debugging information in the browser
30
- # default is true for development, off otherwise
31
- # replay_console: <true/false> Default is true. False will disable echoing server rendering
32
- # logs to browser. While this can make troubleshooting server rendering difficult,
33
- # so long as you have the default configuration of logging_on_server set to
34
- # true, you'll still see the errors on the server.
35
- # raise_on_prerender_error: <true/false> Default to false. True will raise exception on server
36
- # if the JS code throws
37
- # Any other options are passed to the content tag, including the id.
38
- def react_component(component_name, props = {}, options = {})
39
- # Create the JavaScript and HTML to allow either client or server rendering of the
40
- # react_component.
41
- #
42
- # Create the JavaScript setup of the global to initialize the client rendering
43
- # (re-hydrate the data). This enables react rendered on the client to see that the
44
- # server has already rendered the HTML.
45
- # We use this react_component_index in case we have the same component multiple times on the page.
46
- react_component_index = next_react_component_index
47
- react_component_name = component_name.camelize # Not sure if we should be doing this (JG)
48
- if options[:id].nil?
49
- dom_id = "#{component_name}-react-component-#{react_component_index}"
50
- else
51
- dom_id = options[:id]
52
- end
53
-
54
- # Setup the page_loaded_js, which is the same regardless of prerendering or not!
55
- # The reason is that React is smart about not doing extra work if the server rendering did its job.
56
- turbolinks_loaded = Object.const_defined?(:Turbolinks)
57
-
58
- component_specification_tag =
59
- content_tag(:div,
60
- "",
61
- class: "js-react-on-rails-component",
62
- style: "display:none",
63
- data: {
64
- component_name: react_component_name,
65
- props: props,
66
- trace: trace(options),
67
- generator_function: generator_function(options),
68
- expect_turbolinks: turbolinks_loaded,
69
- dom_id: dom_id
70
- })
71
-
72
- # Create the HTML rendering part
73
- result = server_rendered_react_component_html(options, props, react_component_name, dom_id)
74
-
75
- server_rendered_html = result["html"]
76
- console_script = result["consoleReplayScript"]
77
-
78
- content_tag_options = options.except(:generator_function, :prerender, :trace,
79
- :replay_console, :id, :react_component_name,
80
- :server_side, :raise_on_prerender_error)
81
- content_tag_options[:id] = dom_id
82
-
83
- rendered_output = content_tag(:div,
84
- server_rendered_html.html_safe,
85
- content_tag_options)
86
-
87
- # IMPORTANT: Ensure that we mark string as html_safe to avoid escaping.
88
- <<-HTML.html_safe
89
- #{component_specification_tag}
90
- #{rendered_output}
91
- #{replay_console(options) ? console_script : ''}
92
- HTML
93
- end
94
-
95
- def sanitized_props_string(props)
96
- props.is_a?(String) ? json_escape(props) : props.to_json
97
- end
98
-
99
- # Helper method to take javascript expression and returns the output from evaluating it.
100
- # If you have more than one line that needs to be executed, wrap it in an IIFE.
101
- # JS exceptions are caught and console messages are handled properly.
102
- def server_render_js(js_expression, options = {})
103
- wrapper_js = <<-JS
104
- (function() {
105
- var htmlResult = '';
106
- var consoleReplayScript = '';
107
- var hasErrors = false;
108
-
109
- try {
110
- htmlResult =
111
- (function() {
112
- return #{js_expression};
113
- })();
114
- } catch(e) {
115
- htmlResult = ReactOnRails.handleError({e: e, componentName: null,
116
- jsCode: '#{escape_javascript(js_expression)}', serverSide: true});
117
- hasErrors = true;
118
- }
119
-
120
- consoleReplayScript = ReactOnRails.buildConsoleReplay();
121
-
122
- return JSON.stringify({
123
- html: htmlResult,
124
- consoleReplayScript: consoleReplayScript,
125
- hasErrors: hasErrors
126
- });
127
-
128
- })()
129
- JS
130
-
131
- result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(wrapper_js)
132
-
133
- # IMPORTANT: To ensure that Rails doesn't auto-escape HTML tags, use the 'raw' method.
134
- html = result["html"]
135
- console_log_script = result["consoleLogScript"]
136
- raw("#{html}#{replay_console(options) ? console_log_script : ''}")
137
- rescue ExecJS::ProgramError => err
138
- # rubocop:disable Style/RaiseArgs
139
- raise ReactOnRails::PrerenderError.new(component_name: "N/A (server_render_js called)",
140
- err: err,
141
- js_code: wrapper_js)
142
- # rubocop:enable Style/RaiseArgs
143
- end
144
-
145
- private
146
-
147
- def next_react_component_index
148
- @react_component_index ||= -1
149
- @react_component_index += 1
150
- end
151
-
152
- # Returns Array [0]: html, [1]: script to console log
153
- # NOTE, these are NOT html_safe!
154
- def server_rendered_react_component_html(options, props, react_component_name, dom_id)
155
- return { "html" => "", "consoleReplayScript" => "" } unless prerender(options)
156
-
157
- # On server `location` option is added (`location = request.fullpath`)
158
- # React Router needs this to match the current route
159
-
160
- # Make sure that we use up-to-date server-bundle
161
- ReactOnRails::ServerRenderingPool.reset_pool_if_server_bundle_was_modified
162
-
163
- # Since this code is not inserted on a web page, we don't need to escape.
164
- props_string = props.is_a?(String) ? props : props.to_json
165
-
166
- wrapper_js = <<-JS
167
- (function() {
168
- var props = #{props_string};
169
- return ReactOnRails.serverRenderReactComponent({
170
- componentName: '#{react_component_name}',
171
- domId: '#{dom_id}',
172
- props: props,
173
- trace: #{trace(options)},
174
- generatorFunction: #{generator_function(options)},
175
- location: '#{request.fullpath}'
176
- });
177
- })()
178
- JS
179
-
180
- result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(wrapper_js)
181
-
182
- if result["hasErrors"] && raise_on_prerender_error(options)
183
- # We caught this exception on our backtrace handler
184
- # rubocop:disable Style/RaiseArgs
185
- fail ReactOnRails::PrerenderError.new(component_name: react_component_name,
186
- # Sanitize as this might be browser logged
187
- props: sanitized_props_string(props),
188
- err: nil,
189
- js_code: wrapper_js,
190
- console_messages: result["consoleReplayScript"])
191
- # rubocop:enable Style/RaiseArgs
192
- end
193
- result
194
- rescue ExecJS::ProgramError => err
195
- # This error came from execJs
196
- # rubocop:disable Style/RaiseArgs
197
- raise ReactOnRails::PrerenderError.new(component_name: react_component_name,
198
- # Sanitize as this might be browser logged
199
- props: sanitized_props_string(props),
200
- err: err,
201
- js_code: wrapper_js)
202
- # rubocop:enable Style/RaiseArgs
203
- end
204
-
205
- def raise_on_prerender_error(options)
206
- options.fetch(:raise_on_prerender_error) { ReactOnRails.configuration.raise_on_prerender_error }
207
- end
208
-
209
- def trace(options)
210
- options.fetch(:trace) { ReactOnRails.configuration.trace }
211
- end
212
-
213
- def generator_function(options)
214
- options.fetch(:generator_function) { ReactOnRails.configuration.generator_function }
215
- end
216
-
217
- def prerender(options)
218
- options.fetch(:prerender) { ReactOnRails.configuration.prerender }
219
- end
220
-
221
- def replay_console(options)
222
- options.fetch(:replay_console) { ReactOnRails.configuration.replay_console }
223
- end
224
- end