├── .bookignore ├── .coveralls.yml ├── .dockerignore ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── actionlint-matcher.json └── workflows │ ├── examples.yml │ ├── lint-js-and-ruby.yml │ ├── main.yml │ ├── package-js-tests.yml │ └── rspec-package-specs.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .rspec ├── .rubocop.yml ├── .scss-lint.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile_tests ├── Gemfile ├── Gemfile.development_dependencies ├── Gemfile.lock ├── KUDOS.md ├── LICENSE.md ├── NEWS.md ├── PROJECTS.md ├── REACT-ON-RAILS-PRO-LICENSE ├── README.md ├── Rakefile ├── SUMMARY.md ├── app └── helpers │ └── react_on_rails_helper.rb ├── book.json ├── docker-compose.yml ├── docs ├── additional-details │ ├── generator-details.md │ ├── manual-installation-overview.md │ ├── migrating-from-react-rails.md │ ├── recommended-project-structure.md │ ├── tips-for-usage-with-sp6.md │ ├── updating-dependencies.md │ └── upgrade-webpacker-v3-to-v4.md ├── api │ ├── javascript-api.md │ ├── redux-store-api.md │ └── view-helpers-api.md ├── contributor-info │ ├── errors-with-hooks.md │ ├── generator-testing.md │ ├── linters.md │ ├── pull-requests.md │ └── releasing.md ├── deployment │ ├── elastic-beanstalk.md │ └── heroku-deployment.md ├── getting-started.md ├── guides │ ├── client-vs-server-rendering.md │ ├── configuration.md │ ├── deployment.md │ ├── file-system-based-automated-bundle-generation.md │ ├── hmr-and-hot-reloading-with-the-webpack-dev-server.md │ ├── how-react-on-rails-works.md │ ├── how-to-conditionally-server-render-based-on-device-type.md │ ├── how-to-use-different-files-for-client-and-server-rendering.md │ ├── i18n.md │ ├── installation-into-an-existing-rails-app.md │ ├── minitest-configuration.md │ ├── rails-webpacker-react-integration-options.md │ ├── react-on-rails-overview.md │ ├── react-server-rendering.md │ ├── render-functions-and-railscontext.md │ ├── rspec-configuration.md │ ├── streaming-server-rendering.md │ ├── tutorial.md │ ├── upgrading-react-on-rails.md │ └── webpack-configuration.md ├── home.md ├── javascript │ ├── angular-js-integration-migration.md │ ├── asset-pipeline.md │ ├── capistrano-deployment.md │ ├── code-splitting.md │ ├── converting-from-custom-webpack-config-to-rails-webpacker-config.md │ ├── credits.md │ ├── foreman-issues.md │ ├── images.md │ ├── node-dependencies-and-npm.md │ ├── react-and-redux.md │ ├── react-helmet.md │ ├── react-router.md │ ├── render-functions.md │ ├── server-rendering-tips.md │ ├── troubleshooting-when-using-shakapacker.md │ ├── troubleshooting-when-using-webpacker.md │ └── webpack.md ├── misc │ ├── articles.md │ ├── code_of_conduct.md │ ├── doctrine.md │ ├── style.md │ └── tips.md ├── outdated │ ├── deferred-rendering.md │ ├── rails-assets-relative-paths.md │ ├── rails-assets.md │ ├── rails3.md │ └── webpack-v1-notes.md ├── rails │ ├── convert-rails-5-api-only-app.md │ ├── rails-engine-integration.md │ ├── rails_view_rendering_from_inline_javascript.md │ └── turbolinks.md ├── react-on-rails-pro │ └── react-on-rails-pro.md ├── release-notes │ └── 15.0.0.md └── testimonials │ ├── hvmn.md │ ├── resortpass.md │ └── testimonials.md ├── eslint.config.ts ├── jest.config.js ├── knip.ts ├── lib ├── generators │ ├── USAGE │ └── react_on_rails │ │ ├── adapt_for_older_shakapacker_generator.rb │ │ ├── base_generator.rb │ │ ├── bin │ │ ├── dev │ │ └── dev-static │ │ ├── dev_tests_generator.rb │ │ ├── generator_helper.rb │ │ ├── generator_messages.rb │ │ ├── install_generator.rb │ │ ├── react_no_redux_generator.rb │ │ ├── react_with_redux_generator.rb │ │ └── templates │ │ ├── .eslintrc │ │ ├── base │ │ └── base │ │ │ ├── Procfile.dev-static.tt │ │ │ ├── Procfile.dev.tt │ │ │ ├── app │ │ │ ├── controllers │ │ │ │ └── hello_world_controller.rb │ │ │ ├── javascript │ │ │ │ ├── bundles │ │ │ │ │ └── HelloWorld │ │ │ │ │ │ └── components │ │ │ │ │ │ ├── HelloWorld.jsx │ │ │ │ │ │ ├── HelloWorld.module.css │ │ │ │ │ │ └── HelloWorldServer.js │ │ │ │ └── packs │ │ │ │ │ ├── registration.js.tt │ │ │ │ │ └── server-bundle.js │ │ │ └── views │ │ │ │ ├── hello_world │ │ │ │ └── index.html.erb.tt │ │ │ │ └── layouts │ │ │ │ └── hello_world.html.erb │ │ │ ├── babel.config.js.tt │ │ │ └── config │ │ │ ├── initializers │ │ │ └── react_on_rails.rb.tt │ │ │ ├── shakapacker.yml │ │ │ └── webpack │ │ │ ├── clientWebpackConfig.js.tt │ │ │ ├── commonWebpackConfig.js.tt │ │ │ ├── development.js.tt │ │ │ ├── production.js.tt │ │ │ ├── serverWebpackConfig.js.tt │ │ │ ├── test.js.tt │ │ │ ├── webpack.config.js.tt │ │ │ └── webpackConfig.js.tt │ │ ├── dev_tests │ │ ├── .eslintrc │ │ ├── .rspec │ │ └── spec │ │ │ ├── rails_helper.rb │ │ │ ├── simplecov_helper.rb │ │ │ ├── spec_helper.rb │ │ │ └── system │ │ │ └── hello_world_spec.rb │ │ └── redux │ │ └── base │ │ └── app │ │ └── javascript │ │ └── bundles │ │ └── HelloWorld │ │ ├── actions │ │ └── helloWorldActionCreators.js │ │ ├── components │ │ └── HelloWorld.jsx │ │ ├── constants │ │ └── helloWorldConstants.js │ │ ├── containers │ │ └── HelloWorldContainer.js │ │ ├── reducers │ │ └── helloWorldReducer.js │ │ ├── startup │ │ └── HelloWorldApp.jsx │ │ └── store │ │ └── helloWorldStore.js ├── react_on_rails.rb ├── react_on_rails │ ├── configuration.rb │ ├── controller.rb │ ├── engine.rb │ ├── error.rb │ ├── git_utils.rb │ ├── helper.rb │ ├── json_output.rb │ ├── json_parse_error.rb │ ├── locales │ │ ├── base.rb │ │ ├── to_js.rb │ │ └── to_json.rb │ ├── packer_utils.rb │ ├── packs_generator.rb │ ├── prerender_error.rb │ ├── react_component │ │ └── render_options.rb │ ├── server_rendering_js_code.rb │ ├── server_rendering_pool.rb │ ├── server_rendering_pool │ │ └── ruby_embedded_java_script.rb │ ├── test_helper.rb │ ├── test_helper │ │ ├── ensure_assets_compiled.rb │ │ ├── webpack_assets_compiler.rb │ │ └── webpack_assets_status_checker.rb │ ├── utils.rb │ ├── version.rb │ ├── version_checker.rb │ └── version_syntax_converter.rb └── tasks │ ├── assets.rake │ ├── generate_packs.rake │ └── locale.rake ├── node_package ├── babel.config.js ├── scripts │ ├── release │ └── symlink-node-package ├── src │ ├── Authenticity.ts │ ├── CallbackRegistry.ts │ ├── ClientSideRenderer.ts │ ├── ComponentRegistry.ts │ ├── RSCClientRoot.ts │ ├── ReactDOMServer.cts │ ├── ReactOnRails.client.ts │ ├── ReactOnRails.full.ts │ ├── ReactOnRails.node.ts │ ├── ReactOnRailsRSC.ts │ ├── RenderUtils.ts │ ├── StoreRegistry.ts │ ├── buildConsoleReplay.ts │ ├── clientStartup.ts │ ├── context.ts │ ├── createReactOutput.ts │ ├── handleError.ts │ ├── isRenderFunction.ts │ ├── isServerRenderResult.ts │ ├── loadReactClientManifest.ts │ ├── pageLifecycle.ts │ ├── reactApis.cts │ ├── reactHydrateOrRender.ts │ ├── registerServerComponent │ │ ├── client.ts │ │ └── server.ts │ ├── scriptSanitizedVal.ts │ ├── serverRenderReactComponent.ts │ ├── serverRenderUtils.ts │ ├── streamServerRenderedReactComponent.ts │ ├── transformRSCStreamAndReplayConsoleLogs.ts │ ├── turbolinksUtils.ts │ ├── types │ │ └── index.ts │ └── utils.ts └── tests │ ├── Authenticity.test.js │ ├── ComponentRegistry.test.js │ ├── RSCClientRoot.test.jsx │ ├── ReactOnRails.test.jsx │ ├── StoreRegistry.test.js │ ├── buildConsoleReplay.test.js │ ├── emptyForTesting.js │ ├── fixtures │ └── rsc-payloads │ │ └── simple-shell-with-async-component │ │ ├── chunk1.json │ │ └── chunk2.json │ ├── jest.setup.js │ ├── renderFunction.test.jsx │ ├── scriptSanitizedVal.test.js │ ├── serverRenderReactComponent.test.ts │ ├── streamServerRenderedReactComponent.test.jsx │ ├── testUtils.js │ └── utils.test.js ├── package-scripts.yml ├── package.json ├── rakelib ├── docker.rake ├── dummy_apps.rake ├── example_type.rb ├── examples_config.yml ├── lint.rake ├── node_package.rake ├── release.rake ├── run_rspec.rake ├── shakapacker_examples.rake ├── task_helpers.rb ├── update_changelog.rake └── webpacker_examples.rake ├── react_on_rails.gemspec ├── script ├── bootstrap ├── convert ├── release ├── setup └── test ├── spec ├── dummy │ ├── .browserslistrc │ ├── .rspec │ ├── .rubocop.yml │ ├── Gemfile │ ├── Gemfile.lock │ ├── Procfile │ ├── Procfile.dev │ ├── Procfile.dev-static │ ├── Procfile.dev.no.turbolinks │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── assets │ │ │ ├── config │ │ │ │ └── manifest.js │ │ │ ├── javascripts │ │ │ │ └── application_non_webpack.js.erb │ │ │ └── stylesheets │ │ │ │ └── application_non_webpack.scss │ │ ├── controllers │ │ │ ├── application_controller.rb │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ ├── pages_controller.rb │ │ │ └── react_router_controller.rb │ │ ├── helpers │ │ │ └── application_helper.rb │ │ ├── mailers │ │ │ ├── .keep │ │ │ └── dummy_mailer.rb │ │ ├── models │ │ │ ├── .keep │ │ │ └── concerns │ │ │ │ └── .keep │ │ └── views │ │ │ ├── dummy_mailer │ │ │ └── hello_email.html.erb │ │ │ ├── layouts │ │ │ └── application.html.erb │ │ │ ├── pages │ │ │ ├── _xhr_refresh_partial.html.erb │ │ │ ├── broken_app.html.erb │ │ │ ├── client_side_hello_world.html.erb │ │ │ ├── client_side_hello_world_shared_store.html.erb │ │ │ ├── client_side_hello_world_shared_store_controller.html.erb │ │ │ ├── client_side_hello_world_shared_store_defer.html.erb │ │ │ ├── client_side_log_throw.html.erb │ │ │ ├── client_side_manual_render.html.erb │ │ │ ├── client_side_rescript_hello_world.html.erb │ │ │ ├── context_function_return_jsx.html.erb │ │ │ ├── css_modules_images_fonts_example.html.erb │ │ │ ├── image_example.erb │ │ │ ├── index.html.erb │ │ │ ├── pure_component.html.erb │ │ │ ├── pure_component_wrapped_in_function.html.erb │ │ │ ├── react_helmet.erb │ │ │ ├── react_helmet_broken.erb │ │ │ ├── render_js.html.erb │ │ │ ├── rendered_html.erb │ │ │ ├── server_side_hello_world.html.erb │ │ │ ├── server_side_hello_world_es5.html.erb │ │ │ ├── server_side_hello_world_hooks.html.erb │ │ │ ├── server_side_hello_world_props.html.erb │ │ │ ├── server_side_hello_world_shared_store.html.erb │ │ │ ├── server_side_hello_world_shared_store_controller.html.erb │ │ │ ├── server_side_hello_world_shared_store_defer.html.erb │ │ │ ├── server_side_hello_world_with_options.html.erb │ │ │ ├── server_side_log_throw.html.erb │ │ │ ├── server_side_log_throw_plain_js.html.erb │ │ │ ├── server_side_log_throw_raise.html.erb │ │ │ ├── server_side_log_throw_raise_invoker.html.erb │ │ │ ├── server_side_redux_app.html.erb │ │ │ ├── server_side_redux_app_cached.html.erb │ │ │ ├── turbo_frame_tag_hello_world.html.erb │ │ │ ├── turbo_stream_send_hello_world.turbo_stream.erb │ │ │ ├── turbolinks_cache_disabled.erb │ │ │ ├── xhr_refresh.html.erb │ │ │ └── xhr_refresh.js.erb │ │ │ ├── react_router │ │ │ ├── index.html.erb │ │ │ └── second_page.html.erb │ │ │ └── shared │ │ │ └── _header.erb │ ├── babel.config.js │ ├── bin │ │ ├── bootsnap │ │ ├── bundle │ │ ├── byebug │ │ ├── coderay │ │ ├── coveralls │ │ ├── dev │ │ ├── htmldiff │ │ ├── kill-pry-rescue │ │ ├── launchy │ │ ├── ldiff │ │ ├── listen │ │ ├── nokogiri │ │ ├── pry │ │ ├── puma │ │ ├── pumactl │ │ ├── racc │ │ ├── rackup │ │ ├── rails │ │ ├── rake │ │ ├── rdoc │ │ ├── rescue │ │ ├── ri │ │ ├── rspec │ │ ├── rubocop │ │ ├── ruby-parse │ │ ├── ruby-rewrite │ │ ├── sass │ │ ├── sass-convert │ │ ├── scss │ │ ├── scss-lint │ │ ├── sdoc │ │ ├── sdoc-merge │ │ ├── setup │ │ ├── shakapacker │ │ ├── shakapacker-dev-server │ │ ├── spring │ │ ├── sprockets │ │ ├── term_cdiff │ │ ├── term_colortab │ │ ├── term_decolor │ │ ├── term_display │ │ ├── term_mandel │ │ ├── term_snow │ │ ├── thor │ │ ├── tilt │ │ ├── webpacker │ │ ├── webpacker-dev-server │ │ ├── yard │ │ ├── yardoc │ │ ├── yarn │ │ └── yri │ ├── client │ │ ├── README.md │ │ ├── app-react16 │ │ │ └── startup │ │ │ │ ├── ManualRenderApp.jsx │ │ │ │ ├── ReduxApp.client.jsx │ │ │ │ └── ReduxSharedStoreApp.client.jsx │ │ └── app │ │ │ ├── actions │ │ │ └── HelloWorldActions.jsx │ │ │ ├── assets │ │ │ ├── fonts │ │ │ │ └── OpenSans-Light.ttf │ │ │ ├── images │ │ │ │ ├── 256egghead.png │ │ │ │ ├── bg_lego_icon.svg │ │ │ │ ├── guest-list-accepted.png │ │ │ │ ├── hookipa-beach.png │ │ │ │ ├── lego_icon.svg │ │ │ │ ├── logos │ │ │ │ │ └── railsonmaui.png │ │ │ │ └── section-title-bg.png │ │ │ └── styles │ │ │ │ └── app-variables.scss │ │ │ ├── components │ │ │ ├── CssModulesImagesFontsExample.module.scss │ │ │ ├── EchoProps.jsx │ │ │ ├── HelloWorld.module.scss │ │ │ ├── HelloWorldContainer.jsx │ │ │ ├── HelloWorldReScript.res │ │ │ ├── HelloWorldRedux.jsx │ │ │ ├── ImageExample │ │ │ │ ├── ImageExample.module.scss │ │ │ │ ├── bg-Google-Logo.svg │ │ │ │ ├── bg-hero.png │ │ │ │ ├── blueprint_icon.svg │ │ │ │ └── bower.png │ │ │ ├── RailsContext.jsx │ │ │ ├── ReactHelmet.jsx │ │ │ ├── RouterFirstPage.jsx │ │ │ ├── RouterLayout.jsx │ │ │ └── RouterSecondPage.jsx │ │ │ ├── constants │ │ │ └── HelloWorldConstants.jsx │ │ │ ├── non_react │ │ │ └── HelloString.js │ │ │ ├── packs │ │ │ ├── client-bundle.js │ │ │ ├── rescript-components.js │ │ │ └── server-bundle.js │ │ │ ├── reducers │ │ │ ├── HelloWorldReducer.jsx │ │ │ ├── nullReducer.jsx │ │ │ └── reducersIndex.jsx │ │ │ ├── routes │ │ │ └── routes.jsx │ │ │ ├── startup │ │ │ ├── BrokenApp.jsx │ │ │ ├── CacheDisabled.jsx │ │ │ ├── ContextFunctionReturnInvalidJSX.jsx │ │ │ ├── CssModulesImagesFontsExample.jsx │ │ │ ├── HelloTurboStream.jsx │ │ │ ├── HelloWorld.jsx │ │ │ ├── HelloWorldApp.jsx │ │ │ ├── HelloWorldES5.jsx │ │ │ ├── HelloWorldHooks.jsx │ │ │ ├── HelloWorldHooksContext.jsx │ │ │ ├── HelloWorldProps.jsx │ │ │ ├── HelloWorldReScript.jsx │ │ │ ├── HelloWorldRehydratable.jsx │ │ │ ├── HelloWorldWithLogAndThrow.jsx │ │ │ ├── ImageExample.jsx │ │ │ ├── ManualRenderApp.jsx │ │ │ ├── PureComponent.jsx │ │ │ ├── PureComponentWrappedInFunction.jsx │ │ │ ├── ReactHelmetApp.client.jsx │ │ │ ├── ReactHelmetApp.server.jsx │ │ │ ├── ReactHelmetAppBroken.client.jsx │ │ │ ├── ReactHelmetAppBroken.server.jsx │ │ │ ├── ReduxApp.client.jsx │ │ │ ├── ReduxApp.server.jsx │ │ │ ├── ReduxSharedStoreApp.client.jsx │ │ │ ├── ReduxSharedStoreApp.server.jsx │ │ │ ├── RenderedHtml.client.jsx │ │ │ ├── RenderedHtml.server.jsx │ │ │ ├── RouterApp.client.jsx │ │ │ └── RouterApp.server.jsx │ │ │ ├── store │ │ │ └── composeInitialState.js │ │ │ └── stores │ │ │ └── SharedReduxStore.jsx │ ├── config.ru │ ├── config │ │ ├── application.rb │ │ ├── boot.rb │ │ ├── cable.yml │ │ ├── credentials.yml.enc │ │ ├── database.yml │ │ ├── environment.rb │ │ ├── environments │ │ │ ├── development.rb │ │ │ ├── production.rb │ │ │ └── test.rb │ │ ├── initializers │ │ │ ├── assets.rb │ │ │ ├── content_security_policy.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── inflections.rb │ │ │ ├── permissions_policy.rb │ │ │ └── react_on_rails.rb │ │ ├── locales │ │ │ └── en.yml │ │ ├── master.key │ │ ├── puma.rb │ │ ├── routes.rb │ │ ├── shakapacker.yml │ │ ├── storage.yml │ │ └── webpack │ │ │ ├── DEBUGGING.md │ │ │ ├── alias.js │ │ │ ├── clientWebpackConfig.js │ │ │ ├── commonWebpackConfig.js │ │ │ ├── development.js │ │ │ ├── production.js │ │ │ ├── serverWebpackConfig.js │ │ │ ├── test.js │ │ │ ├── webpack-notes.md │ │ │ ├── webpack.config.js │ │ │ └── webpackConfig.js │ ├── db │ │ ├── schema.rb │ │ └── seeds.rb │ ├── lib │ │ ├── assets │ │ │ └── .keep │ │ └── tasks │ │ │ └── .keep │ ├── log │ │ └── .keep │ ├── package.json │ ├── public │ │ ├── 404.html │ │ ├── 422.html │ │ ├── 500.html │ │ ├── favicon.ico │ │ └── robots.txt │ ├── rescript.json │ ├── spec │ │ ├── .rubocop.yml │ │ ├── fixtures │ │ │ └── automated_packs_generation │ │ │ │ ├── components │ │ │ │ ├── ComponentWithClientAndCommon │ │ │ │ │ └── ror_components │ │ │ │ │ │ ├── ComponentWithClientAndCommon.client.jsx │ │ │ │ │ │ └── ComponentWithClientAndCommon.jsx │ │ │ │ ├── ComponentWithClientOnly │ │ │ │ │ └── ror_components │ │ │ │ │ │ └── ComponentWithClientOnly.client.jsx │ │ │ │ ├── ComponentWithCommonClientAndServer │ │ │ │ │ └── ror_components │ │ │ │ │ │ ├── ComponentWithCommonClientAndServer.client.jsx │ │ │ │ │ │ ├── ComponentWithCommonClientAndServer.jsx │ │ │ │ │ │ └── ComponentWithCommonClientAndServer.server.jsx │ │ │ │ ├── ComponentWithCommonOnly │ │ │ │ │ └── ror_components │ │ │ │ │ │ └── ComponentWithCommonOnly.jsx │ │ │ │ ├── ComponentWithServerAndCommon │ │ │ │ │ └── ror_components │ │ │ │ │ │ ├── ComponentWithServerAndCommon.jsx │ │ │ │ │ │ └── ComponentWithServerAndCommon.server.jsx │ │ │ │ ├── ComponentWithServerOnly │ │ │ │ │ └── ror_components │ │ │ │ │ │ └── ComponentWithServerOnly.server.jsx │ │ │ │ └── ReactServerComponents │ │ │ │ │ └── ror_components │ │ │ │ │ ├── ReactClientComponent.jsx │ │ │ │ │ ├── ReactClientComponentWithClientAndServer.client.jsx │ │ │ │ │ ├── ReactClientComponentWithClientAndServer.server.jsx │ │ │ │ │ ├── ReactServerComponent.jsx │ │ │ │ │ ├── ReactServerComponentWithClientAndServer.client.jsx │ │ │ │ │ └── ReactServerComponentWithClientAndServer.server.jsx │ │ │ │ └── packs │ │ │ │ └── server-bundle.js │ │ ├── helpers │ │ │ └── react_on_rails_helper_spec.rb │ │ ├── packs_generator_spec.rb │ │ ├── rails_helper.rb │ │ ├── rake │ │ │ ├── assets_precompile_rake_spec.rb │ │ │ └── assets_rake_spec.rb │ │ ├── requests │ │ │ ├── console_logging_spec.rb │ │ │ └── server_render_check_spec.rb │ │ ├── simplecov_helper.rb │ │ ├── spec_helper.rb │ │ ├── support │ │ │ ├── script_tag_utils.rb │ │ │ └── selenium_logger.rb │ │ └── system │ │ │ ├── integration_spec.rb │ │ │ └── rails_context_spec.rb │ ├── tests │ │ ├── react-on-rails.import.test.js │ │ └── react-on-rails.require.test.js │ ├── vendor │ │ └── assets │ │ │ ├── javascripts │ │ │ └── .keep │ │ │ └── stylesheets │ │ │ └── .keep │ └── yarn.lock ├── empty_spec.rb └── react_on_rails │ ├── .rubocop.yml │ ├── binstubs │ ├── dev_spec.rb │ └── dev_static_spec.rb │ ├── configuration_spec.rb │ ├── fixtures │ ├── absolute_path_package.json │ ├── beta_package.json │ ├── git_package.json │ ├── i18n │ │ ├── locales │ │ │ ├── de.yml │ │ │ └── en.yml │ │ └── locales_symbols │ │ │ ├── de.yml │ │ │ └── en.yml │ ├── normal_package.json │ ├── relative_path_package.json │ ├── semver_caret_package.json │ ├── semver_range_package.json │ ├── semver_tilde_package.json │ ├── webpack_assets │ │ ├── assets_exist │ │ │ ├── client │ │ │ │ └── myApp.jsx │ │ │ └── compiled_js │ │ │ │ ├── client-bundle.js │ │ │ │ └── server-bundle.js │ │ ├── assets_exist_only_server_bundle │ │ │ ├── client │ │ │ │ └── myApp.jsx │ │ │ └── compiled_js │ │ │ │ └── server-bundle.js │ │ ├── assets_no_exist │ │ │ ├── client │ │ │ │ └── myApp.jsx │ │ │ └── compiled_js │ │ │ │ └── .keep │ │ ├── assets_outdated │ │ │ ├── client │ │ │ │ └── myApp.jsx │ │ │ ├── compiled │ │ │ │ └── client-bundle.js │ │ │ └── compiled_sass │ │ │ │ └── vendor-bundle.sass │ │ ├── assets_with_manifest_exist │ │ │ ├── client │ │ │ │ └── myApp.jsx │ │ │ └── compiled_js │ │ │ │ ├── client-bundle-6bc530d039d96709b68d.js │ │ │ │ ├── manifest.json │ │ │ │ └── server-bundle-6bc530d039d96702268d.js │ │ ├── assets_with_manifest_exist_server_bundle_separate │ │ │ ├── client │ │ │ │ └── myApp.jsx │ │ │ └── compiled_js │ │ │ │ ├── client-bundle-6bc530d039d96709b68d.js │ │ │ │ └── manifest.json │ │ └── assets_with_missing_manifest │ │ │ └── client │ │ │ └── myApp.jsx │ └── yalc_package.json │ ├── generators │ ├── dev_tests_generator_spec.rb │ ├── generator_messages_spec.rb │ └── install_generator_spec.rb │ ├── git_utils_spec.rb │ ├── json_output_spec.rb │ ├── locales_spec.rb │ ├── locales_to_js_spec.rb │ ├── packer_utils_spec.rb │ ├── prender_error_spec.rb │ ├── react_component │ └── render_options_spec.rb │ ├── react_on_rails_spec.rb │ ├── simplecov_helper.rb │ ├── spec_helper.rb │ ├── support │ ├── fixtures_helper.rb │ ├── generator_spec_helper.rb │ ├── shared_examples │ │ ├── base_generator_examples.rb │ │ ├── react_no_redux_generator_examples.rb │ │ └── react_with_redux_generator_examples.rb │ └── version_test_helpers.rb │ ├── test_helper │ ├── ensure_assets_compiled_spec.rb │ ├── webpack_assets_compiler_spec.rb │ └── webpack_assets_status_checker_spec.rb │ ├── utils_spec.rb │ ├── version_checker_spec.rb │ └── version_syntax_converter_spec.rb ├── tsconfig.eslint.json ├── tsconfig.json └── yarn.lock /.bookignore: -------------------------------------------------------------------------------- 1 | # Directories to ignore 2 | app/* 3 | gen-examples/* 4 | lib/* 5 | node_package/" 6 | rakelib/* 7 | script/* 8 | spec/* 9 | 10 | # files in repo root to ignore 11 | Gemfile 12 | package.json 13 | Rakefile 14 | react_on_rails.gemspec 15 | ruby-lint.yml 16 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-ci 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | docker-compose.yml 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [shakacode] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | A bug is a crash or incorrect behavior. If you have a debugging or troubleshooting question, please open [a discussion](https://github.com/shakacode/react_on_rails/discussions). 10 | 11 | ## Environment 12 | 13 | 1. Ruby version: 14 | 2. Rails version: 15 | 3. Shakapacker/Webpacker version: 16 | 4. React on Rails version: 17 | 18 | ## Expected behavior 19 | 20 | ## Actual behavior 21 | 22 | ## Small, reproducible repo 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Summary 2 | 3 | _Remove this paragraph and provide a general description of the code changes in your pull 4 | request... were there any bugs you had fixed? If so, mention them. If 5 | these bugs have open GitHub issues, be sure to tag them here as well, 6 | to keep the conversation linked together._ 7 | 8 | ### Pull Request checklist 9 | 10 | _Remove this line after checking all the items here. If the item is not applicable to the PR, both check it out and wrap it by `~`._ 11 | 12 | - [ ] Add/update test to cover these changes 13 | - [ ] Update documentation 14 | - [ ] Update CHANGELOG file 15 | 16 | _Add the CHANGELOG entry at the top of the file._ 17 | 18 | ### Other Information 19 | 20 | _Remove this paragraph and mention any other important and relevant information such as benchmarks._ 21 | -------------------------------------------------------------------------------- /.github/actionlint-matcher.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "actionlint", 5 | "pattern": [ 6 | { 7 | "regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$", 8 | "file": 1, 9 | "line": 2, 10 | "column": 3, 11 | "message": 4, 12 | "code": 5 13 | } 14 | ] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | *.gem 10 | /vendor/ 11 | 12 | /spec/examples.txt 13 | /spec/react_on_rails/dummy-for-generators/ 14 | 15 | tmp/ 16 | 17 | # RVM 18 | .ruby-version 19 | .ruby-gemset 20 | 21 | node_modules 22 | 23 | /node_package/lib 24 | 25 | yarn-debug.* 26 | yarn-error.* 27 | npm-debug.* 28 | .yarn-integrity 29 | 30 | /gen-examples 31 | 32 | .DS_Store 33 | 34 | .yalc 35 | yalc.lock 36 | 37 | .byebug_history 38 | 39 | # IDE 40 | .idea/ 41 | .vscode/ 42 | 43 | # TypeScript 44 | *.tsbuildinfo 45 | 46 | # Dummy app 47 | /spec/dummy/vendor/bundle 48 | /spec/dummy/db/*.sqlite3* 49 | /spec/dummy/log/**/* 50 | !/spec/dummy/log/.keep 51 | /spec/dummy/public/assets/ 52 | /spec/dummy/public/webpack/ 53 | /spec/dummy/spec/examples.txt 54 | 55 | # ReScript build files 56 | /spec/dummy/.merlin 57 | /spec/dummy/lib/bs/ 58 | /spec/dummy/.bsb.lock 59 | /spec/dummy/**/*.res.js 60 | 61 | # Generated by ROR FS-based Registry 62 | generated 63 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | Gemfile 3 | README.md 4 | app 5 | coverage 6 | docs 7 | examples 8 | node_modules 9 | react_on_rails.gemspec 10 | Dockerfile_tests 11 | Gemfile.lock 12 | Rakefile 13 | bin 14 | docker-compose.yml 15 | etc 16 | lib 17 | rakelib 18 | ruby-lint.yml 19 | spec 20 | node_modules 21 | tmp 22 | gen-examples 23 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package.json 3 | tmp/ 4 | coverage/ 5 | **/app/assets/webpack/ 6 | gen-examples/examples/* 7 | node_package/lib/* 8 | spec/react_on_rails/dummy-for-generators/app/javascript/bundles/HelloWorld/* 9 | bundle/ 10 | spec/dummy/lib/bs/** 11 | spec/dummy/public 12 | **/.yalc/** 13 | **/*generated* 14 | *.res.js 15 | 16 | # Prettier doesn't understand ERB syntax in YAML files 17 | .rubocop.yml 18 | # Intentionally invalid 19 | spec/react_on_rails/fixtures/i18n/locales_symbols/ 20 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | printWidth: 110 2 | tabWidth: 2 3 | useTabs: false 4 | semi: true 5 | singleQuote: true 6 | trailingComma: all 7 | bracketSpacing: true 8 | bracketSameLine: false 9 | 10 | overrides: 11 | - files: '*.@(css|scss)' 12 | options: 13 | singleQuote: false 14 | printWidth: 120 15 | - files: '*.@(json)' 16 | options: 17 | printWidth: 100 18 | - files: '.*rc' 19 | excludeFiles: 20 | # Direnv file, not YAML 21 | - '.envrc' 22 | options: 23 | parser: yaml 24 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /Dockerfile_tests: -------------------------------------------------------------------------------- 1 | FROM dylangrafmyre/docker-ci 2 | 3 | WORKDIR /app/ 4 | 5 | COPY ["/lib/react_on_rails/version.rb", "/app/lib/react_on_rails/"] 6 | COPY ["Gemfile", "Gemfile.lock", "react_on_rails.gemspec", "rakelib/", "/app/"] 7 | COPY ["/spec/dummy/Gemfile", "/spec/dummy/Gemfile.lock", "/app/spec/dummy/"] 8 | RUN bundle install --gemfile=spec/dummy/Gemfile 9 | 10 | ENV DISPLAY :99 11 | ENTRYPOINT service xvfd start \ 12 | && rake 13 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Specify your gem"s dependencies in react_on_rails.gemspec 6 | gemspec 7 | 8 | eval_gemfile File.expand_path("./Gemfile.development_dependencies", __dir__) 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Rake will automatically load any *.rake files inside of the "rakelib" folder 4 | # See rakelib/ 5 | 6 | tasks = %w[lint run_rspec] 7 | prepare_for_ci = %w[node_package dummy_apps] 8 | 9 | if ENV["USE_COVERALLS"] == "TRUE" 10 | require "coveralls/rake/task" 11 | Coveralls::RakeTask.new 12 | tasks << "coveralls:push" 13 | end 14 | 15 | desc "Run all tests and linting" 16 | task default: tasks 17 | 18 | desc "All actions but no examples, good for local developer run." 19 | task all_but_examples: ["run_rspec:all_but_examples", "lint"] 20 | 21 | desc "Prepare for ci, including node_package, dummy app, and generator examples" 22 | task prepare_for_ci: prepare_for_ci 23 | 24 | desc "Runs prepare_for_ci and tasks" 25 | task ci: [:prepare_for_ci, *tasks] 26 | -------------------------------------------------------------------------------- /app/helpers/react_on_rails_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ReactOnRailsHelper 4 | include ReactOnRails::Helper 5 | end 6 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "gitbook": "3.1.1", 3 | "title": "React on Rails Documentation", 4 | "plugins": ["prism", "-highlight", "github"], 5 | "pluginsConfig": { 6 | "github": { 7 | "url": "https://github.com/shakacode/react_on_rails/" 8 | }, 9 | "sharing": { 10 | "facebook": true, 11 | "twitter": true, 12 | "google": true, 13 | "weibo": true, 14 | "instapaper": true, 15 | "vk": true 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | lint: 2 | image: dylangrafmyre/docker-lint:latest 3 | working_dir: /app/ 4 | volumes: 5 | - '.:/app/' 6 | tests: 7 | build: . 8 | dockerfile: Dockerfile_tests 9 | working_dir: /app/ 10 | volumes: 11 | - '.:/app/' 12 | -------------------------------------------------------------------------------- /docs/additional-details/tips-for-usage-with-sp6.md: -------------------------------------------------------------------------------- 1 | # Tips for usage with Shakapacker 6 2 | 3 | As mentioned earlier in the documentation, we assume you install ReactOnRails in a project with Shakapacker 7+ installed and configured. If you still use Shakapacker 6, we encourage you to check the upgrade to the version 7 guide. Otherwise, you need to consider the following: 4 | 5 | 1. The install generator tries to take the necessary steps to adapt the installed files to match the file structure and configurations for Shakapacker 6. So you don't need to be worried about the ReactOnRails installation process. 6 | 7 | 2. Check the following table to map the references in the documentation to the relevant ones in Shakapacker 6: 8 | 9 | | Usage in Shakapacker 7 | Equivalent in Shakapacker 6 | 10 | | ---------------------------- | --------------------------- | 11 | | `config/shakapacker.yml` | `config/webpacker.yml` | 12 | | `bin/shakapacker` | `bin/webpacker` | 13 | | `bin/shakapacker-dev-server` | `bin/webpacker-dev-server` | 14 | 15 | 3. Any environment variables starting with `SHAKAPACKER_*` should be changed to `WEBPACKER_*`. 16 | -------------------------------------------------------------------------------- /docs/additional-details/updating-dependencies.md: -------------------------------------------------------------------------------- 1 | # Updating Dependencies 2 | 3 | If you frequently update dependencies in small batches, you will avoid large and painful updates later. Then again, if you don't have good test coverage, it's hazardous to update dependencies at any time. 4 | 5 | ## Ruby 6 | 7 | Delete any unwanted version constraints from your Gemfile and run: 8 | 9 | ```bash 10 | bundle update 11 | ``` 12 | 13 | ## NPM 14 | 15 | 1. Install [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) 16 | 1. Run `yarn outdated` and read CHANGELOGs of major updated packages before you update. You might not be ready for some updates. 17 | 1. Run these commands. You may or may not need to `rm -rf` your `node_modules` directory. 18 | 19 | ```bash 20 | cd client 21 | ncu -u -a 22 | yarn 23 | ``` 24 | 25 | Some combinations that I often run: 26 | 27 | - remove old installed `node_modules` so you only get what corresponds to `package.json`: 28 | 29 | ```bash 30 | ncu -u -a && rm -rf node_modules && yarn 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/additional-details/upgrade-webpacker-v3-to-v4.md: -------------------------------------------------------------------------------- 1 | # Upgrading rails/webpacker v3.5 to v4 2 | 3 | The following steps can be followed to update a Webpacker v3.5 app to v4. 4 | 5 | 1. Update the gem `webpacker` and the package `@rails/webpacker` 6 | 1. Merge changes from the new default [.babelrc](https://github.com/shakacode/react_on_rails/tree/master/lib/install/config/.babelrc) to your `/.babelrc`. If you are using React, you need to add `"@babel/preset-react"`, to the list of `presets`. 7 | 1. Copy the file [.browserslistrc](https://github.com/shakacode/react_on_rails/tree/master/lib/install/config/.browserslistrc) to `/`. 8 | 1. Merge any differences between [config/webpacker.yml](https://github.com/shakacode/react_on_rails/tree/master/lib/install/config/webpacker.yml) and your `/config/webpacker.yml`. 9 | 10 | Here is an [example commit of these changes](https://github.com/shakacode/react_on_rails-tutorial-v11/pull/1/files). 11 | -------------------------------------------------------------------------------- /docs/guides/deployment.md: -------------------------------------------------------------------------------- 1 | # Deployment 2 | 3 | Shakapacker puts the necessary precompile steps automatically in the rake precompile step. 4 | 5 | See the [Heroku Deployment](https://www.shakacode.com/react-on-rails/docs/deployment/heroku-deployment/) doc for specifics regarding Heroku. The information for Heroku may apply to other deployments. 6 | -------------------------------------------------------------------------------- /docs/guides/minitest-configuration.md: -------------------------------------------------------------------------------- 1 | # Minitest Configuration 2 | 3 | The setup for minitest is the same as for rspec with the following difference. 4 | 5 | Rather than calling `ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)`, instead you will do something like this: 6 | 7 | ```ruby 8 | class ActiveSupport::TestCase 9 | setup do 10 | ReactOnRails::TestHelper.ensure_assets_compiled 11 | end 12 | end 13 | ``` 14 | 15 | Or maybe something like this, from the [minitest docs](https://github.com/seattlerb/minitest/blob/master/lib/minitest/test.rb#L119): 16 | 17 | ```ruby 18 | module MyMinitestPlugin 19 | def before_setup 20 | super 21 | ReactOnRails::TestHelper.ensure_assets_compiled 22 | end 23 | end 24 | 25 | class MiniTest::Test 26 | include MyMinitestPlugin 27 | end 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/javascript/asset-pipeline.md: -------------------------------------------------------------------------------- 1 | # Asset Pipeline with React on Rails 2 | 3 | In general, you should not be mixing the asset pipeline with Shakapacker and React on Rails. 4 | 5 | If you're using React, then all of your CSS and images should be under either `/app/javascript` or 6 | `/client` or wherever you want your client-side application. 7 | 8 | If you are incrementally migrating a large application, your main concern will be how to minimize 9 | duplication of styles and images between your old application and the new one. 10 | 11 | Please email [justin@shakacode.com](mailto:justin@shakacode.com) if you would be interested in helping 12 | to migrate a larger application. 13 | -------------------------------------------------------------------------------- /docs/javascript/capistrano-deployment.md: -------------------------------------------------------------------------------- 1 | # Capistrano Deployment 2 | 3 | First, make sure ReactOnRails is working in the development environment. 4 | 5 | Add the following to your Gemfile: 6 | 7 | ```ruby 8 | group :development do 9 | gem 'capistrano-yarn' 10 | end 11 | ``` 12 | 13 | Then run Bundler to ensure Capistrano is downloaded and installed: 14 | 15 | ```sh 16 | bundle install 17 | ``` 18 | 19 | Add the following to your Capfile: 20 | 21 | ```ruby 22 | require 'capistrano/yarn' 23 | ``` 24 | 25 | If the deployment is taking too long or getting stuck at `assets:precompile` stage, it is probably because of memory. Webpack consumes a lot of memory, so if possible, try increasing the RAM of your server. 26 | -------------------------------------------------------------------------------- /docs/javascript/converting-from-custom-webpack-config-to-rails-webpacker-config.md: -------------------------------------------------------------------------------- 1 | # Converting from Custom Webpack Config to Rails Shakapacker Config 2 | 3 | 1. Compare your `package.json` and the dependencies in https://github.com/shakacode/shakapacker/blob/master/package.json 4 | and avoid any duplicates. We don't want different versions of the same packages. 5 | We want the versions from `shakacode/shakapacker` unless we specifically want to override them. 6 | 2. Search the `shakacode/shakapacker` repo for anything you're not sure about in terms of package names. 7 | 3. Run `bin/shakapacker` and make sure there are zero errors 8 | 4. Update Webpack plugins and loaders to current or close to current 9 | 5. Make sure that your `bin/shakapacker` and `bin/shakapacker` match the latest on 10 | https://github.com/shakacode/shakapacker/tree/master/lib/install/bin 11 | -------------------------------------------------------------------------------- /docs/javascript/credits.md: -------------------------------------------------------------------------------- 1 | ## Authors 2 | 3 | [The Shaka Code team!](http://www.shakacode.com/about/) 4 | 5 | The origins of the project began with the need to do a rich JavaScript interface for a ShakaCode's client. The choice to use Webpack and Rails is described in [Fast Rich Client Rails Development With Webpack and the ES6 Transpiler](http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/). 6 | 7 | The gem project started with [Justin Gordon](https://github.com/justin808/) pairing with [Samnang Chhun](https://github.com/samnang) to figure out how to do server rendering with Webpack plus Rails. [Alex Fedoseev](https://github.com/alexfedoseev) then joined in. [Rob Wise](https://github.com/robwise), [Aaron Van Bokhoven](https://github.com/aaronvb), and [Andy Wang](https://github.com/yorzi) did the bulk of the generators. Many others have [contributed](https://github.com/shakacode/react_on_rails/graphs/contributors). 8 | 9 | The gem was initially inspired by the [react-rails gem](https://github.com/reactjs/react-rails). 10 | -------------------------------------------------------------------------------- /docs/javascript/foreman-issues.md: -------------------------------------------------------------------------------- 1 | # Foreman Issues 2 | 3 | ## It is not recommended to include foreman into Gemfile 4 | 5 | See: https://github.com/ddollar/foreman 6 | 7 | > Ruby users should take care not to install foreman in their project's Gemfile. 8 | 9 | ## Known issues 10 | 11 | - With `foreman 0.82.0`, the NPM package `react-s3-uploader` was failing to finish uploading a file to S3 when the server was started by `foreman -f Procfile.dev`. 12 | At the same time, the same code works fine when the Ruby server is started by `bundle exec rails s`. 13 | 14 | - The same Procfile with different versions of `foreman` in combination with different versions of `bundler` may produce different output of `ps aux`. 15 | This may break Bash tools which rely on `ps` output. 16 | -------------------------------------------------------------------------------- /docs/javascript/node-dependencies-and-npm.md: -------------------------------------------------------------------------------- 1 | # Node Dependencies, NPM, and Yarn 2 | 3 | ## Updating 4 | 5 | You can check for outdated versions of packages with `yarn outdated` in your `client` directory. 6 | 7 | To upgrade package version, use `yarn upgrade [package]`. To update all dependencies, use `yarn upgrade`. 8 | 9 | Confirm that the hot replacement dev server and the Rails server both work. 10 | 11 | ## Adding New Dependencies 12 | 13 | Typically, you can add your Node dependencies as you normally would. 14 | 15 | ```bash 16 | cd client 17 | yarn add module_name@version 18 | # or 19 | # yarn add --dev module_name@version 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/outdated/rails3.md: -------------------------------------------------------------------------------- 1 | # Rails 3 2 | 3 | - Please let us know if you find any issues with Rails 3. 4 | - Rails 3 is confirmed to work up with versions up to 6.8.x. 5 | - We are not testing it for new releases. If you find an issue, you will have to submit a PR to get it fixed. 6 | 7 | ## Known Issues 8 | 9 | 1. If you do not skip bootstrap for the generator, you cannot generate a working app, as bootstrap-sass does not support Rails 3, or at least the version we're using. 10 | -------------------------------------------------------------------------------- /docs/rails/convert-rails-5-api-only-app.md: -------------------------------------------------------------------------------- 1 | # Convert Rails 5 API only app to a Rails app 2 | 3 | 1. Go to the directory where you created your app 4 | 5 | ```bash 6 | $ rails new your-current-app-name 7 | ``` 8 | 9 | Rails will start creating the app and will skip the files you have already created. If there is some conflict then it will stop and you need to resolve it manually. be careful at this step as it might replace you current code in conflicted files. 10 | 11 | 2. Resolve conflicts 12 | 13 | ``` 14 | 1. Press "d" to see the difference 15 | 2. If it is only adding lines then press "y" to continue 16 | 3. If it is removeing some of your code then press "n" and add all additions manually 17 | ``` 18 | 19 | 3. Run `bundle install` and follow [the instructions for installing into an existing Rails app](https://www.shakacode.com/react-on-rails/docs/guides/installation-into-an-existing-rails-app/) 20 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | import { createJsWithTsPreset } from 'ts-jest'; 2 | 3 | const nodeVersion = parseInt(process.version.slice(1), 10); 4 | 5 | export default { 6 | ...createJsWithTsPreset({ 7 | tsconfig: { 8 | // Relative imports in our TS code include `.ts` extensions. 9 | // When compiling the package, TS rewrites them to `.js`, 10 | // but ts-jest runs on the original code where the `.js` files don't exist, 11 | // so this setting needs to be disabled here. 12 | rewriteRelativeImportExtensions: false, 13 | }, 14 | }), 15 | testEnvironment: 'jsdom', 16 | setupFiles: ['/node_package/tests/jest.setup.js'], 17 | // React Server Components tests are compatible with React 19 18 | // That only run with node version 18 and above 19 | moduleNameMapper: 20 | nodeVersion < 18 21 | ? { 22 | 'react-on-rails-rsc/client': '/node_package/tests/emptyForTesting.js', 23 | '^@testing-library/dom$': '/node_package/tests/emptyForTesting.js', 24 | '^@testing-library/react$': '/node_package/tests/emptyForTesting.js', 25 | } 26 | : {}, 27 | }; 28 | -------------------------------------------------------------------------------- /lib/generators/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | 3 | The react_on_rails:install generator integrates Webpack with Rails with ease. You 4 | can pass the redux option if you'd like to have redux setup for you automatically. 5 | 6 | * Redux 7 | 8 | Passing the --redux generator option causes the generated Hello World example 9 | to integrate the Redux state container framework. The necessary node modules 10 | will be automatically included for you. 11 | 12 | ******************************************************************************* 13 | 14 | After running the generator, you will want to: 15 | 16 | bundle && yarn 17 | 18 | Then you may run 19 | 20 | foreman start -f Procfile.dev 21 | 22 | More Details: 23 | 24 | `https://github.com/shakacode/react_on_rails/blob/master/docs/additional-details/generator-details.md` 25 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | def installed?(process) 5 | IO.popen "#{process} -v" 6 | rescue Errno::ENOENT 7 | false 8 | end 9 | 10 | def run(process) 11 | system "#{process} start -f Procfile.dev" 12 | rescue Errno::ENOENT 13 | warn <<~MSG 14 | ERROR: 15 | Please ensure `Procfile.dev` exists in your project! 16 | MSG 17 | exit! 18 | end 19 | 20 | if installed? "overmind" 21 | run "overmind" 22 | elsif installed? "foreman" 23 | run "foreman" 24 | else 25 | warn <<~MSG 26 | NOTICE: 27 | For this script to run, you need either 'overmind' or 'foreman' installed on your machine. Please try this script after installing one of them. 28 | MSG 29 | exit! 30 | end 31 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/bin/dev-static: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | def installed?(process) 5 | IO.popen "#{process} -v" 6 | rescue Errno::ENOENT 7 | false 8 | end 9 | 10 | def run(process) 11 | system "#{process} start -f Procfile.dev-static" 12 | rescue Errno::ENOENT 13 | warn <<~MSG 14 | ERROR: 15 | Please ensure `Procfile.dev-static` exists in your project! 16 | MSG 17 | exit! 18 | end 19 | 20 | if installed? "overmind" 21 | run "overmind" 22 | elsif installed? "foreman" 23 | run "foreman" 24 | else 25 | warn <<~MSG 26 | NOTICE: 27 | For this script to run, you need either 'overmind' or 'foreman' installed on your machine. Please try this script after installing one of them. 28 | MSG 29 | exit! 30 | end 31 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: 3 | - eslint-config-shakacode 4 | - prettier 5 | 6 | plugins: 7 | - react 8 | 9 | globals: 10 | __DEBUG_SERVER_ERRORS__: true 11 | __SERVER_ERRORS__: true 12 | 13 | env: 14 | browser: true 15 | node: true 16 | mocha: true 17 | 18 | rules: 19 | no-console: 0 20 | 21 | # https://github.com/benmosher/eslint-plugin-import/issues/340 22 | import/no-extraneous-dependencies: 0 23 | 24 | # because template cannot find react-on-rails 25 | import/no-unresolved: 0 26 | 27 | semi: 0 28 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/Procfile.dev-static.tt: -------------------------------------------------------------------------------- 1 | # You can run these commands in separate shells 2 | web: rails s -p 3000 3 | 4 | # Next line runs a watch process with webpack to compile the changed files. 5 | # When making frequent changes to client side assets, you will prefer building webpack assets 6 | # upon saving rather than when you refresh your browser page. 7 | # Note, if using React on Rails localization you will need to run 8 | # `bundle exec rake react_on_rails:locale` before you run bin/<%= config[:packer_type] %> 9 | webpack: sh -c 'rm -rf public/packs/* || true && bin/<%= config[:packer_type] %> -w' 10 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt: -------------------------------------------------------------------------------- 1 | # Procfile for development using HMR 2 | # You can run these commands in separate shells 3 | rails: bundle exec rails s -p 3000 4 | wp-client: bin/<%= config[:packer_type] %>-dev-server 5 | wp-server: SERVER_BUNDLE_ONLY=yes bin/<%= config[:packer_type] %> --watch 6 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/controllers/hello_world_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HelloWorldController < ApplicationController 4 | layout "hello_world" 5 | 6 | def index 7 | @hello_world_props = { name: "Stranger" } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React, { useState } from 'react'; 3 | import * as style from './HelloWorld.module.css'; 4 | 5 | const HelloWorld = (props) => { 6 | const [name, setName] = useState(props.name); 7 | 8 | return ( 9 |
10 |

Hello, {name}!

11 |
12 |
13 | 17 |
18 |
19 | ); 20 | }; 21 | 22 | HelloWorld.propTypes = { 23 | name: PropTypes.string.isRequired, // this is passed from the Rails view 24 | }; 25 | 26 | export default HelloWorld; 27 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css: -------------------------------------------------------------------------------- 1 | .bright { 2 | color: green; 3 | font-weight: bold; 4 | } 5 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js: -------------------------------------------------------------------------------- 1 | import HelloWorld from './HelloWorld'; 2 | // This could be specialized for server rendering 3 | // For example, if using React Router, we'd have the SSR setup here. 4 | 5 | export default HelloWorld; 6 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt: -------------------------------------------------------------------------------- 1 | import ReactOnRails from 'react-on-rails/client'; 2 | 3 | import <%= config[:component_name] %> from '<%= config[:app_relative_path] %>'; 4 | 5 | // This is how react_on_rails can see the HelloWorld in the browser. 6 | ReactOnRails.register({ 7 | <%= config[:component_name] %>, 8 | }); 9 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js: -------------------------------------------------------------------------------- 1 | import ReactOnRails from 'react-on-rails'; 2 | 3 | import HelloWorld from '../bundles/HelloWorld/components/HelloWorldServer'; 4 | 5 | // This is how react_on_rails can see the HelloWorld in the browser. 6 | ReactOnRails.register({ 7 | HelloWorld, 8 | }); 9 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt: -------------------------------------------------------------------------------- 1 |

Hello World

2 | <%%= react_component("<%= config[:component_name] %>", props: @hello_world_props, prerender: false) %> 3 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ReactOnRailsWithShakapacker 5 | <%= csrf_meta_tags %> 6 | <%= javascript_pack_tag 'hello-world-bundle' %> 7 | <%= stylesheet_pack_tag 'hello-world-bundle' %> 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/babel.config.js.tt: -------------------------------------------------------------------------------- 1 | <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/blob/master/babel.config.js") %> 2 | 3 | module.exports = function (api) { 4 | const defaultConfigFunc = require('shakapacker/package/babel/preset.js') 5 | const resultConfig = defaultConfigFunc(api) 6 | const isProductionEnv = api.env('production') 7 | 8 | const changesOnDefault = { 9 | presets: [ 10 | [ 11 | '@babel/preset-react', 12 | { 13 | development: !isProductionEnv, 14 | useBuiltIns: true 15 | } 16 | ] 17 | ].filter(Boolean), 18 | plugins: [ 19 | process.env.WEBPACK_SERVE && 'react-refresh/babel', 20 | isProductionEnv && ['babel-plugin-transform-react-remove-prop-types', 21 | { 22 | removeImport: true 23 | } 24 | ] 25 | ].filter(Boolean), 26 | } 27 | 28 | resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets] 29 | resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins ] 30 | 31 | return resultConfig 32 | } 33 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/config/webpack/clientWebpackConfig.js.tt: -------------------------------------------------------------------------------- 1 | <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/blob/master/config/webpack/clientWebpackConfig.js") %> 2 | 3 | const commonWebpackConfig = require('./commonWebpackConfig'); 4 | 5 | const configureClient = () => { 6 | const clientConfig = commonWebpackConfig(); 7 | 8 | // server-bundle is special and should ONLY be built by the serverConfig 9 | // In case this entry is not deleted, a very strange "window" not found 10 | // error shows referring to window["webpackJsonp"]. That is because the 11 | // client config is going to try to load chunks. 12 | delete clientConfig.entry['server-bundle']; 13 | 14 | return clientConfig; 15 | }; 16 | 17 | module.exports = configureClient; 18 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt: -------------------------------------------------------------------------------- 1 | <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/blob/master/config/webpack/commonWebpackConfig.js") %> 2 | 3 | // Common configuration applying to client and server configuration 4 | const { generateWebpackConfig, merge } = require('shakapacker'); 5 | 6 | const baseClientWebpackConfig = generateWebpackConfig(); 7 | 8 | const commonOptions = { 9 | resolve: { 10 | extensions: ['.css', '.ts', '.tsx'], 11 | }, 12 | }; 13 | 14 | // Copy the object using merge b/c the baseClientWebpackConfig and commonOptions are mutable globals 15 | const commonWebpackConfig = () => merge({}, baseClientWebpackConfig, commonOptions); 16 | 17 | module.exports = commonWebpackConfig; 18 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt: -------------------------------------------------------------------------------- 1 | <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/blob/master/config/webpack/development.js") %> 2 | 3 | const { devServer, inliningCss } = require('shakapacker'); 4 | 5 | const webpackConfig = require('./webpackConfig'); 6 | 7 | const developmentEnvOnly = (clientWebpackConfig, _serverWebpackConfig) => { 8 | // plugins 9 | if (inliningCss) { 10 | // Note, when this is run, we're building the server and client bundles in separate processes. 11 | // Thus, this plugin is not applied to the server bundle. 12 | 13 | // eslint-disable-next-line global-require 14 | const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); 15 | clientWebpackConfig.plugins.push( 16 | new ReactRefreshWebpackPlugin({ 17 | overlay: { 18 | sockPort: devServer.port, 19 | }, 20 | }), 21 | ); 22 | } 23 | }; 24 | 25 | module.exports = webpackConfig(developmentEnvOnly); 26 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt: -------------------------------------------------------------------------------- 1 | <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/blob/master/config/webpack/production.js") %> 2 | 3 | const webpackConfig = require('./webpackConfig'); 4 | 5 | const productionEnvOnly = (_clientWebpackConfig, _serverWebpackConfig) => { 6 | // place any code here that is for production only 7 | }; 8 | 9 | module.exports = webpackConfig(productionEnvOnly); 10 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/config/webpack/test.js.tt: -------------------------------------------------------------------------------- 1 | <%= add_documentation_reference(config[:message], "// https://github.com/shakacode/react_on_rails_demo_ssr_hmr/blob/master/config/webpack/test.js") %> 2 | 3 | const webpackConfig = require('./webpackConfig') 4 | 5 | const testOnly = (_clientWebpackConfig, _serverWebpackConfig) => { 6 | // place any code here that is for test only 7 | } 8 | 9 | module.exports = webpackConfig(testOnly) 10 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/base/base/config/webpack/webpack.config.js.tt: -------------------------------------------------------------------------------- 1 | const { env } = require('shakapacker') 2 | const { existsSync } = require('fs') 3 | const { resolve } = require('path') 4 | 5 | const envSpecificConfig = () => { 6 | const path = resolve(__dirname, `${env.nodeEnv}.js`) 7 | if (existsSync(path)) { 8 | console.log(`Loading ENV specific webpack configuration file ${path}`) 9 | return require(path) 10 | } else { 11 | throw new Error(`Could not find file to load ${path}, based on NODE_ENV`) 12 | } 13 | } 14 | 15 | module.exports = envSpecificConfig() 16 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/dev_tests/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: eslint-config-shakacode 3 | 4 | plugins: 5 | - react 6 | 7 | globals: 8 | __DEBUG_SERVER_ERRORS__: true 9 | __SERVER_ERRORS__: true 10 | 11 | env: 12 | browser: true 13 | node: true 14 | mocha: true 15 | 16 | rules: 17 | no-console: 0 18 | 19 | # https://github.com/benmosher/eslint-plugin-import/issues/340 20 | import/no-extraneous-dependencies: 0 21 | 22 | # because template cannot find react-on-rails 23 | import/no-unresolved: 0 24 | 25 | semi: 0 26 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/dev_tests/.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Starts SimpleCov for code coverage. 4 | 5 | if ENV["COVERAGE"] == "true" 6 | require "simplecov" 7 | 8 | # Using a command name prevents results from getting clobbered by other test suites 9 | example_name = File.basename(File.expand_path("../..", __dir__)) 10 | SimpleCov.command_name(example_name) 11 | 12 | SimpleCov.start("rails") do 13 | # Consider the entire gem project as the root 14 | # (typically this will be the folder named "react_on_rails") 15 | gem_root_path = File.expand_path("../../../..", __dir__) 16 | root gem_root_path 17 | 18 | # Don't report anything that has "spec" in the path 19 | add_filter do |src| 20 | src.filename.include?("/spec/") 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/dev_tests/spec/system/hello_world_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../rails_helper" 4 | 5 | describe "Hello World", :js do 6 | it "the hello world example works" do 7 | visit "/hello_world" 8 | expect(heading).to have_text("Hello World") 9 | expect(message).to have_text("Stranger") 10 | name_input.set("John Doe") 11 | expect(message).to have_text("John Doe") 12 | end 13 | end 14 | 15 | private 16 | 17 | def name_input 18 | page.first("input") 19 | end 20 | 21 | def message 22 | page.first(:css, "h3") 23 | end 24 | 25 | def heading 26 | page.first(:css, "h1") 27 | end 28 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/actions/helloWorldActionCreators.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | 3 | import { HELLO_WORLD_NAME_UPDATE } from '../constants/helloWorldConstants'; 4 | 5 | export const updateName = (text) => ({ 6 | type: HELLO_WORLD_NAME_UPDATE, 7 | text, 8 | }); 9 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import * as style from './HelloWorld.module.css'; 4 | 5 | const HelloWorld = ({ name, updateName }) => ( 6 |
7 |

8 | Hello, 9 | {name}! 10 |

11 |
12 |
13 | 17 |
18 |
19 | ); 20 | 21 | HelloWorld.propTypes = { 22 | name: PropTypes.string.isRequired, 23 | updateName: PropTypes.func.isRequired, 24 | }; 25 | 26 | export default HelloWorld; 27 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/constants/helloWorldConstants.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | 3 | export const HELLO_WORLD_NAME_UPDATE = 'HELLO_WORLD_NAME_UPDATE'; 4 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/containers/HelloWorldContainer.js: -------------------------------------------------------------------------------- 1 | // Simple example of a React "smart" component 2 | 3 | import { connect } from 'react-redux'; 4 | import HelloWorld from '../components/HelloWorld'; 5 | import * as actions from '../actions/helloWorldActionCreators'; 6 | 7 | // Which part of the Redux global state does our component want to receive as props? 8 | const mapStateToProps = (state) => ({ name: state.name }); 9 | 10 | // Don't forget to actually use connect! 11 | // Note that we don't export HelloWorld, but the redux "connected" version of it. 12 | // See https://github.com/reactjs/react-redux/blob/master/docs/api.md#examples 13 | export default connect(mapStateToProps, actions)(HelloWorld); 14 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/reducers/helloWorldReducer.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { HELLO_WORLD_NAME_UPDATE } from '../constants/helloWorldConstants'; 3 | 4 | const name = (state = '', action = {}) => { 5 | switch (action.type) { 6 | case HELLO_WORLD_NAME_UPDATE: 7 | return action.text; 8 | default: 9 | return state; 10 | } 11 | }; 12 | 13 | const helloWorldReducer = combineReducers({ name }); 14 | 15 | export default helloWorldReducer; 16 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/HelloWorldApp.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Provider } from 'react-redux'; 3 | 4 | import configureStore from '../store/helloWorldStore'; 5 | import HelloWorldContainer from '../containers/HelloWorldContainer'; 6 | 7 | // See documentation for https://github.com/reactjs/react-redux. 8 | // This is how you get props from the Rails view into the redux store. 9 | // This code here binds your smart component to the redux store. 10 | const HelloWorldApp = (props) => ( 11 | 12 | 13 | 14 | ); 15 | 16 | export default HelloWorldApp; 17 | -------------------------------------------------------------------------------- /lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/store/helloWorldStore.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'redux'; 2 | import helloWorldReducer from '../reducers/helloWorldReducer'; 3 | 4 | const configureStore = (railsProps) => createStore(helloWorldReducer, railsProps); 5 | 6 | export default configureStore; 7 | -------------------------------------------------------------------------------- /lib/react_on_rails/controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ReactOnRails 4 | module Controller 5 | # Separate initialization of store from react_component allows multiple react_component calls to 6 | # use the same Redux store. 7 | # 8 | # store_name: name of the store, corresponding to your call to ReactOnRails.registerStores in your 9 | # JavaScript code. 10 | # props: Named parameter props which is a Ruby Hash or JSON string which contains the properties 11 | # to pass to the redux store. 12 | # 13 | # Be sure to include view helper `redux_store_hydration_data` at the end of your layout or view 14 | # or else there will be no client side hydration of your stores. 15 | def redux_store(store_name, props: {}, force_load: nil) 16 | force_load = ReactOnRails.configuration.force_load if force_load.nil? 17 | redux_store_data = { store_name: store_name, 18 | props: props, 19 | force_load: force_load } 20 | @registered_stores_defer_render ||= [] 21 | @registered_stores_defer_render << redux_store_data 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/react_on_rails/engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails/railtie" 4 | 5 | module ReactOnRails 6 | class Engine < ::Rails::Engine 7 | config.to_prepare do 8 | VersionChecker.build.log_if_gem_and_node_package_versions_differ 9 | ReactOnRails::ServerRenderingPool.reset_pool 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/react_on_rails/error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ReactOnRails 4 | class Error < StandardError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/react_on_rails/git_utils.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "English" 4 | 5 | module ReactOnRails 6 | module GitUtils 7 | def self.uncommitted_changes?(message_handler, git_installed: true) 8 | return false if ENV["COVERAGE"] == "true" 9 | 10 | status = `git status --porcelain` 11 | return false if git_installed && status&.empty? 12 | 13 | error = if git_installed 14 | "You have uncommitted code. Please commit or stash your changes before continuing" 15 | else 16 | "You do not have Git installed. Please install Git, and commit your changes before continuing" 17 | end 18 | message_handler.add_error(error) 19 | true 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/react_on_rails/json_output.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "active_support/core_ext/string/output_safety" 4 | 5 | module ReactOnRails 6 | class JsonOutput 7 | def self.escape(json) 8 | ERB::Util.json_escape(json) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/react_on_rails/json_parse_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ReactOnRails 4 | class JsonParseError < ::ReactOnRails::Error 5 | attr_reader :json 6 | 7 | def initialize(parse_error:, json:) 8 | @json = json 9 | @original_error = parse_error 10 | super(parse_error.message) 11 | end 12 | 13 | def to_honeybadger_context 14 | to_error_context 15 | end 16 | 17 | def raven_context 18 | to_error_context 19 | end 20 | 21 | def to_error_context 22 | { 23 | original_error: @original_error, 24 | json: @json 25 | } 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/react_on_rails/locales/to_js.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "erb" 4 | 5 | module ReactOnRails 6 | module Locales 7 | class ToJs < Base 8 | private 9 | 10 | def file_format 11 | "js" 12 | end 13 | 14 | def template_translations 15 | <<-JS.strip_heredoc 16 | export const translations = #{@translations}; 17 | JS 18 | end 19 | 20 | def template_default 21 | <<-JS.strip_heredoc 22 | import { defineMessages } from 'react-intl'; 23 | 24 | const defaultLocale = '#{default_locale}'; 25 | 26 | const defaultMessages = defineMessages(#{@defaults}); 27 | 28 | export { defaultMessages, defaultLocale }; 29 | JS 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/react_on_rails/locales/to_json.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "erb" 4 | 5 | module ReactOnRails 6 | module Locales 7 | class ToJson < Base 8 | private 9 | 10 | def file_format 11 | "json" 12 | end 13 | 14 | def template_translations 15 | @translations 16 | end 17 | 18 | def template_default 19 | @defaults 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/react_on_rails/server_rendering_pool.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "connection_pool" 4 | require_relative "server_rendering_pool/ruby_embedded_java_script" 5 | 6 | # Based on the react-rails gem. 7 | # None of these methods should be called directly. 8 | module ReactOnRails 9 | module ServerRenderingPool 10 | class << self 11 | def pool 12 | @pool ||= if ReactOnRails::Utils.react_on_rails_pro? 13 | ReactOnRailsPro::ServerRenderingPool::ProRendering 14 | else 15 | ReactOnRails::ServerRenderingPool::RubyEmbeddedJavaScript 16 | end 17 | end 18 | 19 | delegate :reset_pool_if_server_bundle_was_modified, :reset_pool, to: :pool 20 | 21 | def server_render_js_with_console_logging(js_code, render_options) 22 | pool.exec_server_render_js(js_code, render_options) 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/react_on_rails/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ReactOnRails 4 | VERSION = "15.0.0.alpha.2" 5 | end 6 | -------------------------------------------------------------------------------- /lib/react_on_rails/version_syntax_converter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "version" 4 | 5 | module ReactOnRails 6 | class VersionSyntaxConverter 7 | def rubygem_to_npm(rubygem_version = ReactOnRails::VERSION) 8 | regex_match = rubygem_version.match(/(\d+\.\d+\.\d+)[.\-]?(.+)?/) 9 | return "#{regex_match[1]}-#{regex_match[2]}" if regex_match[2] 10 | 11 | regex_match[1].to_s 12 | end 13 | 14 | def npm_to_rubygem(npm_version) 15 | match = npm_version 16 | .tr("-", ".") 17 | .strip 18 | .match(/(\d.*)/) 19 | match.present? ? match[0] : nil 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/tasks/generate_packs.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | namespace :react_on_rails do 4 | desc <<~DESC 5 | If there is a file inside any directory matching config.components_subdirectory, this command generates corresponding packs. 6 | DESC 7 | 8 | task generate_packs: :environment do 9 | ReactOnRails::PacksGenerator.instance.generate_packs_if_stale 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/tasks/locale.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "react_on_rails/locales/base" 4 | require "react_on_rails/locales/to_js" 5 | require "react_on_rails/locales/to_json" 6 | 7 | namespace :react_on_rails do 8 | desc <<~DESC 9 | Generate i18n javascript files 10 | This task generates javascript locale files: `translations.js` & `default.js` and places them in 11 | the "ReactOnRails.configuration.i18n_dir". 12 | DESC 13 | task locale: :environment do 14 | ReactOnRails::Locales.compile 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /node_package/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', { targets: { node: 'current' } }]], 3 | }; 4 | -------------------------------------------------------------------------------- /node_package/scripts/release: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | yarn version $1 -m "Bump version to %s" 4 | git push -u origin master 5 | git push --tags 6 | yarn publish 7 | -------------------------------------------------------------------------------- /node_package/scripts/symlink-node-package: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Update the example rails node packages 3 | 4 | yarn run clean 5 | yarn run build 6 | 7 | # Ensure the paths will work no matter where we run the script from 8 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | root_path=${DIR}/../.. 10 | 11 | # Set up link 12 | (cd $root_path && yarn link) 13 | 14 | # Link the example apps to use react_on_rails node_package 15 | examplesDir=${root_path}/gen-examples/examples 16 | if [ -d $examplesDir ] ; then 17 | for type in $( ls $examplesDir ); do 18 | d=$examplesDir/${type} 19 | (cd $d && yalc link react-on-rails) 20 | done 21 | fi 22 | -------------------------------------------------------------------------------- /node_package/src/Authenticity.ts: -------------------------------------------------------------------------------- 1 | import type { AuthenticityHeaders } from './types/index.ts'; 2 | 3 | export function authenticityToken(): string | null { 4 | const token = document.querySelector('meta[name="csrf-token"]'); 5 | if (token instanceof HTMLMetaElement) { 6 | return token.content; 7 | } 8 | return null; 9 | } 10 | 11 | export const authenticityHeaders = (otherHeaders: Record = {}): AuthenticityHeaders => 12 | Object.assign(otherHeaders, { 13 | 'X-CSRF-Token': authenticityToken(), 14 | 'X-Requested-With': 'XMLHttpRequest', 15 | }); 16 | -------------------------------------------------------------------------------- /node_package/src/ReactDOMServer.cts: -------------------------------------------------------------------------------- 1 | // Depending on react-dom version, proper ESM import can be react-dom/server or react-dom/server.js 2 | // but since we have a .cts file, it supports both. 3 | // Remove this file and replace by imports directly from 'react-dom/server' when we drop React 16/17 support. 4 | export { renderToPipeableStream, renderToString, type PipeableStream } from 'react-dom/server'; 5 | -------------------------------------------------------------------------------- /node_package/src/ReactOnRails.full.ts: -------------------------------------------------------------------------------- 1 | import handleError from './handleError.ts'; 2 | import serverRenderReactComponent from './serverRenderReactComponent.ts'; 3 | import type { RenderParams, RenderResult, ErrorOptions } from './types/index.ts'; 4 | 5 | import Client from './ReactOnRails.client.ts'; 6 | 7 | if (typeof window !== 'undefined') { 8 | // warn to include a collapsed stack trace 9 | console.warn( 10 | 'Optimization opportunity: "react-on-rails" includes ~14KB of server-rendering code. Browsers may not need it. See https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352 (Requires creating a free account). Click this for the stack trace.', 11 | ); 12 | } 13 | 14 | Client.handleError = (options: ErrorOptions): string | undefined => handleError(options); 15 | 16 | Client.serverRenderReactComponent = (options: RenderParams): null | string | Promise => 17 | serverRenderReactComponent(options); 18 | 19 | export * from './types/index.ts'; 20 | export default Client; 21 | -------------------------------------------------------------------------------- /node_package/src/ReactOnRails.node.ts: -------------------------------------------------------------------------------- 1 | import ReactOnRails from './ReactOnRails.full.ts'; 2 | import streamServerRenderedReactComponent from './streamServerRenderedReactComponent.ts'; 3 | 4 | ReactOnRails.streamServerRenderedReactComponent = streamServerRenderedReactComponent; 5 | 6 | export * from './ReactOnRails.full.ts'; 7 | // eslint-disable-next-line no-restricted-exports -- see https://github.com/eslint/eslint/issues/15617 8 | export { default } from './ReactOnRails.full.ts'; 9 | -------------------------------------------------------------------------------- /node_package/src/RenderUtils.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/prefer-default-export -- only one export for now, but others may be added later 2 | export function wrapInScriptTags(scriptId: string, scriptBody: string): string { 3 | if (!scriptBody) { 4 | return ''; 5 | } 6 | 7 | return ` 8 | `; 11 | } 12 | -------------------------------------------------------------------------------- /node_package/src/isRenderFunction.ts: -------------------------------------------------------------------------------- 1 | // See discussion: 2 | // https://discuss.reactjs.org/t/how-to-determine-if-js-object-is-react-component/2825/2 3 | import { ReactComponentOrRenderFunction, RenderFunction } from './types/index.ts'; 4 | 5 | /** 6 | * Used to determine we'll call be calling React.createElement on the component of if this is a 7 | * Render-Function used return a function that takes props to return a React element 8 | * @param component 9 | * @returns {boolean} 10 | */ 11 | export default function isRenderFunction( 12 | component: ReactComponentOrRenderFunction, 13 | ): component is RenderFunction { 14 | // No for es5 or es6 React Component 15 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access 16 | if ((component as RenderFunction).prototype?.isReactComponent) { 17 | return false; 18 | } 19 | 20 | if ((component as RenderFunction).renderFunction) { 21 | return true; 22 | } 23 | 24 | // If zero or one args, then we know that this is a regular function that will 25 | // return a React component 26 | if ((component as RenderFunction).length >= 2) { 27 | return true; 28 | } 29 | 30 | return false; 31 | } 32 | -------------------------------------------------------------------------------- /node_package/src/isServerRenderResult.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | CreateReactOutputResult, 3 | ServerRenderResult, 4 | RenderFunctionResult, 5 | RenderStateHtml, 6 | } from './types/index.ts'; 7 | 8 | export function isServerRenderHash( 9 | testValue: CreateReactOutputResult | RenderFunctionResult, 10 | ): testValue is ServerRenderResult { 11 | return !!( 12 | (testValue as ServerRenderResult).renderedHtml || 13 | (testValue as ServerRenderResult).redirectLocation || 14 | (testValue as ServerRenderResult).routeError || 15 | (testValue as ServerRenderResult).error 16 | ); 17 | } 18 | 19 | export function isPromise( 20 | testValue: CreateReactOutputResult | RenderFunctionResult | Promise | RenderStateHtml | string | null, 21 | ): testValue is Promise { 22 | return !!(testValue as Promise | null)?.then; 23 | } 24 | -------------------------------------------------------------------------------- /node_package/src/loadReactClientManifest.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs/promises'; 3 | 4 | type ClientManifest = Record; 5 | const loadedReactClientManifests = new Map(); 6 | 7 | export default async function loadReactClientManifest(reactClientManifestFileName: string) { 8 | // React client manifest is uploaded to node renderer as an asset. 9 | // Renderer copies assets to the same place as the server-bundle.js and rsc-bundle.js. 10 | // Thus, the __dirname of this code is where we can find the manifest file. 11 | const manifestPath = path.resolve(__dirname, reactClientManifestFileName); 12 | const loadedReactClientManifest = loadedReactClientManifests.get(manifestPath); 13 | if (loadedReactClientManifest) { 14 | return loadedReactClientManifest; 15 | } 16 | 17 | try { 18 | const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8')) as ClientManifest; 19 | loadedReactClientManifests.set(manifestPath, manifest); 20 | return manifest; 21 | } catch (error) { 22 | throw new Error(`Failed to load React client manifest from ${manifestPath}: ${error}`); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /node_package/src/reactHydrateOrRender.ts: -------------------------------------------------------------------------------- 1 | import type { ReactElement } from 'react'; 2 | import type { RenderReturnType } from './types/index.ts'; 3 | import { reactHydrate, reactRender } from './reactApis.cts'; 4 | 5 | export default function reactHydrateOrRender( 6 | domNode: Element, 7 | reactElement: ReactElement, 8 | hydrate: boolean, 9 | ): RenderReturnType { 10 | return hydrate ? reactHydrate(domNode, reactElement) : reactRender(domNode, reactElement); 11 | } 12 | -------------------------------------------------------------------------------- /node_package/src/scriptSanitizedVal.ts: -------------------------------------------------------------------------------- 1 | export default (val: string): string => { 2 | // Replace closing 3 | const re = /<\/\W*script/gi; 4 | return val.replace(re, '(/script'); 5 | }; 6 | -------------------------------------------------------------------------------- /node_package/src/turbolinksUtils.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace Turbolinks { 3 | interface TurbolinksStatic { 4 | controller?: unknown; 5 | } 6 | } 7 | } 8 | 9 | /** 10 | * Formats a message if the `traceTurbolinks` option is enabled. 11 | * Multiple arguments can be passed like to `console.log`, 12 | * except format specifiers aren't substituted (because it isn't used as the first argument). 13 | */ 14 | export function debugTurbolinks(...msg: unknown[]): void { 15 | if (!window) { 16 | return; 17 | } 18 | 19 | if (globalThis.ReactOnRails?.option('traceTurbolinks')) { 20 | console.log('TURBO:', ...msg); 21 | } 22 | } 23 | 24 | export function turbolinksInstalled(): boolean { 25 | return typeof Turbolinks !== 'undefined'; 26 | } 27 | 28 | export function turboInstalled() { 29 | return globalThis.ReactOnRails?.option('turbo') === true; 30 | } 31 | 32 | export function turbolinksVersion5(): boolean { 33 | return typeof Turbolinks.controller !== 'undefined'; 34 | } 35 | 36 | export function turbolinksSupported(): boolean { 37 | return Turbolinks.supported; 38 | } 39 | -------------------------------------------------------------------------------- /node_package/src/utils.ts: -------------------------------------------------------------------------------- 1 | // Override the fetch function to make it easier to test 2 | // The default fetch implementation in jest returns Node's Readable stream 3 | // In jest.setup.js, we configure this fetch to return a web-standard ReadableStream instead, 4 | // which matches browser behavior where fetch responses have ReadableStream bodies 5 | // See jest.setup.js for the implementation details 6 | const customFetch = (...args: Parameters) => { 7 | const res = fetch(...args); 8 | return res; 9 | }; 10 | 11 | // eslint-disable-next-line import/prefer-default-export 12 | export { customFetch as fetch }; 13 | -------------------------------------------------------------------------------- /node_package/tests/Authenticity.test.js: -------------------------------------------------------------------------------- 1 | import ReactOnRails from '../src/ReactOnRails.client.ts'; 2 | 3 | const testToken = 'TEST_CSRF_TOKEN'; 4 | 5 | const meta = document.createElement('meta'); 6 | meta.name = 'csrf-token'; 7 | meta.content = testToken; 8 | document.head.appendChild(meta); 9 | 10 | describe('authenticityToken', () => { 11 | it('exists in ReactOnRails API', () => { 12 | expect(typeof ReactOnRails.authenticityToken).toBe('function'); 13 | }); 14 | 15 | it('can read Rails CSRF token from ', () => { 16 | const realToken = ReactOnRails.authenticityToken(); 17 | expect(realToken).toEqual(testToken); 18 | }); 19 | }); 20 | 21 | describe('authenticityHeaders', () => { 22 | it('exists in ReactOnRails API', () => { 23 | expect(typeof ReactOnRails.authenticityHeaders).toBe('function'); 24 | }); 25 | 26 | it('returns valid header with CSRF token', () => { 27 | const realHeader = ReactOnRails.authenticityHeaders(); 28 | expect(realHeader).toEqual({ 'X-CSRF-Token': testToken, 'X-Requested-With': 'XMLHttpRequest' }); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /node_package/tests/emptyForTesting.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /node_package/tests/fixtures/rsc-payloads/simple-shell-with-async-component/chunk1.json: -------------------------------------------------------------------------------- 1 | { 2 | "html": "3:\"$Sreact.suspense\"\n1:{\"name\":\"SimpleComponentForTesting\",\"env\":\"Server\",\"key\":null,\"owner\":null,\"props\":{\"helloWorldData\":{\"name\":\"Mr. Server Side Rendering\",\"\u003cscript\u003ewindow.alert('xss1');\u003c/script\u003e\":\"\u003cscript\u003ewindow.alert(\\\"xss2\\\");\u003c/script\u003e\"}}}\n0:D\"$1\"\n2:W[\"log\",[[\"SimpleComponentForTesting\",\"webpack://react_on_rails_pro_dummy/./client/app/ror-auto-load-components/SimpleComponentForTesting.jsx?\",35,11]],\"$1\",\"Server\",\"Console log at first chunk\"]\n5:{\"name\":\"AsyncComponent\",\"env\":\"Server\",\"key\":null,\"owner\":\"$1\",\"props\":{}}\n4:D\"$5\"\n0:[\"$\",\"div\",null,{\"children\":[[\"$\",\"h1\",null,{\"children\":\"StaticServerComponent\"},\"$1\"],[\"$\",\"p\",null,{\"children\":\"This is a static server component\"},\"$1\"],[\"$\",\"$3\",null,{\"fallback\":[\"$\",\"div\",null,{\"children\":\"Loading AsyncComponent...\"},\"$1\"],\"children\":\"$L4\"},\"$1\"]]},\"$1\"]\n", 3 | "consoleReplayScript": "", 4 | "hasErrors": false, 5 | "isShellReady": true 6 | } 7 | -------------------------------------------------------------------------------- /node_package/tests/fixtures/rsc-payloads/simple-shell-with-async-component/chunk2.json: -------------------------------------------------------------------------------- 1 | { 2 | "html": "6:W[\"log\",[[\"AsyncComponent\",\"webpack://react_on_rails_pro_dummy/./client/app/ror-auto-load-components/SimpleComponentForTesting.jsx?\",24,11]],\"$5\",\"Server\",\"Console log at second chunk\"]\n4:[\"$\",\"div\",null,{\"children\":\"AsyncComponent\"},\"$5\"]\n", 3 | "consoleReplayScript": "", 4 | "hasErrors": false, 5 | "isShellReady": true 6 | } 7 | -------------------------------------------------------------------------------- /node_package/tests/testUtils.js: -------------------------------------------------------------------------------- 1 | import { Readable } from 'stream'; 2 | 3 | /** 4 | * Creates a Node.js Readable stream with external push capability. 5 | * Pusing a null or undefined chunk will end the stream. 6 | * @returns {{ 7 | * stream: Readable, 8 | * push: (chunk: any) => void 9 | * }} Object containing the stream and push function 10 | */ 11 | export const createNodeReadableStream = () => { 12 | const pendingChunks = []; 13 | let pushFn; 14 | const stream = new Readable({ 15 | read() { 16 | pushFn = this.push.bind(this); 17 | if (pendingChunks.length > 0) { 18 | pushFn(pendingChunks.shift()); 19 | } 20 | }, 21 | }); 22 | 23 | const push = (chunk) => { 24 | if (pushFn) { 25 | pushFn(chunk); 26 | } else { 27 | pendingChunks.push(chunk); 28 | } 29 | }; 30 | 31 | return { stream, push }; 32 | }; 33 | 34 | export const getNodeVersion = () => parseInt(process.version.slice(1), 10); 35 | -------------------------------------------------------------------------------- /rakelib/docker.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | namespace :docker do 4 | desc "Run Rubocop linter from docker" 5 | task :rubocop do 6 | sh "docker-compose run lint rake lint:rubocop" 7 | end 8 | 9 | desc "Run scss-lint linter from docker" 10 | task :scss do 11 | sh "docker-compose run lint rake lint:scss" 12 | end 13 | 14 | desc "Run eslint linter from docker" 15 | task :eslint do 16 | sh "docker-compose run lint rake lint:eslint" 17 | end 18 | 19 | desc "Run all linting from docker" 20 | task :lint do 21 | sh "docker-compose run lint rake lint" 22 | end 23 | end 24 | 25 | desc "Runs all linters from docker. Run `rake -D docker` to see all available lint options" 26 | task docker: ["docker:lint"] 27 | -------------------------------------------------------------------------------- /rakelib/dummy_apps.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "task_helpers" 4 | 5 | namespace :dummy_apps do 6 | include ReactOnRails::TaskHelpers 7 | 8 | task :yarn_install do 9 | yarn_install_cmd = "yarn install --mutex network" 10 | sh_in_dir(dummy_app_dir, yarn_install_cmd) 11 | sh_in_dir(dummy_app_dir, "yalc link react-on-rails") 12 | end 13 | 14 | task dummy_app: [:yarn_install] do 15 | dummy_app_dir = File.join(gem_root, "spec/dummy") 16 | bundle_install_in(dummy_app_dir) 17 | end 18 | 19 | task :generate_packs do 20 | dummy_app_dir = File.join(gem_root, "spec/dummy") 21 | sh_in_dir(dummy_app_dir, "bundle exec rake react_on_rails:generate_packs") 22 | end 23 | 24 | task dummy_apps: %i[dummy_app node_package generate_packs] do 25 | puts "Prepared all Dummy Apps" 26 | end 27 | end 28 | 29 | desc "Prepares all dummy apps by installing dependencies" 30 | task dummy_apps: ["dummy_apps:dummy_apps"] 31 | -------------------------------------------------------------------------------- /rakelib/examples_config.yml: -------------------------------------------------------------------------------- 1 | example_type_data: 2 | - name: basic 3 | generator_options: '' 4 | - name: basic-server-rendering 5 | generator_options: --example-server-rendering 6 | - name: redux 7 | generator_options: --redux 8 | - name: redux-server-rendering 9 | generator_options: --redux --example-server-rendering 10 | -------------------------------------------------------------------------------- /rakelib/lint.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "task_helpers" 4 | 5 | namespace :lint do 6 | include ReactOnRails::TaskHelpers 7 | 8 | desc "Run Rubocop as shell" 9 | task :rubocop do 10 | sh_in_dir(gem_root, "bundle exec rubocop --version", "bundle exec rubocop .") 11 | end 12 | 13 | desc "Run scss-lint as shell" 14 | task :scss do 15 | sh_in_dir(gem_root, "bundle exec scss-lint spec/dummy/app/assets/stylesheets/") 16 | end 17 | 18 | desc "Run eslint as shell" 19 | task :eslint do 20 | sh_in_dir(gem_root, "yarn run eslint --version", "yarn run eslint .") 21 | end 22 | 23 | desc "Run all eslint & rubocop linters. Skip scss" 24 | task lint: %i[eslint rubocop] do 25 | puts "Completed all linting" 26 | end 27 | end 28 | 29 | desc "Runs all linters. Run `rake -D lint` to see all available lint options" 30 | task lint: ["lint:lint"] 31 | -------------------------------------------------------------------------------- /rakelib/node_package.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "task_helpers" 4 | 5 | namespace :node_package do 6 | include ReactOnRails::TaskHelpers 7 | 8 | task :build do 9 | puts "Building Node Package and running 'yalc publish'" 10 | sh "yarn run build && yalc publish" 11 | end 12 | end 13 | 14 | desc "Prepares node_package by building and symlinking any example/dummy apps present" 15 | task node_package: "node_package:build" 16 | -------------------------------------------------------------------------------- /script/bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # script/bootstrap: Resolve all dependencies that the application requires to 4 | # run. 5 | 6 | set -e 7 | 8 | cd "$(dirname "$0")/.." 9 | 10 | if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then 11 | brew update 12 | 13 | brew bundle check 2>&1 >/dev/null || { 14 | echo "==> Installing Homebrew dependencies…" 15 | brew bundle 16 | } 17 | fi 18 | 19 | if [ -f ".ruby-version" ] && [ -z "$(rbenv version-name 2>/dev/null)" ]; then 20 | echo "==> Installing Ruby…" 21 | rbenv install --skip-existing 22 | which bundle 2>&1 >/dev/null || { 23 | gem install bundler 24 | rbenv rehash 25 | } 26 | fi 27 | 28 | if [ -f "Gemfile" ]; then 29 | echo "==> Installing gem dependencies…" 30 | bundle check --path vendor/gems 2>&1 >/dev/null || { 31 | bundle install --path vendor/gems --quiet --without production 32 | } 33 | fi 34 | -------------------------------------------------------------------------------- /script/release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "See `rake -D release`" 4 | -------------------------------------------------------------------------------- /script/setup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # script/setup: Set up application for the first time after cloning, or set it 4 | # back to the initial first unused state. 5 | 6 | set -e 7 | 8 | cd "$(dirname "$0")/.." 9 | 10 | script/bootstrap 11 | 12 | echo "===> Setting up DB..." 13 | # reset database to a fresh state. 14 | bin/rake db:create db:reset 15 | 16 | if [ -z "$RAILS_ENV" ] && [ -z "$RACK_ENV" ]; then 17 | # Only things for a development environment will run inside here 18 | # Do things that need to be done to the application to set up for the first 19 | # time. Or things needed to be run to to reset the application back to first 20 | # use experience. These things are scoped to the application's domain. 21 | fi 22 | 23 | echo "==> App is now ready to go!" 24 | -------------------------------------------------------------------------------- /spec/dummy/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults 2 | -------------------------------------------------------------------------------- /spec/dummy/.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /spec/dummy/.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: 2 | - ../../.rubocop.yml 3 | 4 | AllCops: 5 | Exclude: 6 | - 'Procfile.*' 7 | - 'bin/*' 8 | - 'bin/**/*' 9 | - 'client/**/*' 10 | - 'db/schema.rb' 11 | - 'node_modules/react-on-rails' 12 | - 'node_modules/**/*' 13 | - 'public/webpack/**/*' 14 | 15 | Metrics/BlockLength: 16 | Exclude: 17 | - 'config/routes.rb' 18 | -------------------------------------------------------------------------------- /spec/dummy/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | eval_gemfile File.expand_path("../../Gemfile.development_dependencies", __dir__) 6 | 7 | gem "react_on_rails", path: "../.." 8 | -------------------------------------------------------------------------------- /spec/dummy/Procfile: -------------------------------------------------------------------------------- 1 | rails: rails s -b 0.0.0.0 2 | -------------------------------------------------------------------------------- /spec/dummy/Procfile.dev: -------------------------------------------------------------------------------- 1 | # Procfile for development using HMR 2 | # You can run these commands in separate shells 3 | rails: bundle exec rails s -p 3000 4 | wp-client: bin/shakapacker-dev-server 5 | wp-server: SERVER_BUNDLE_ONLY=true bin/shakapacker --watch 6 | 7 | # Bundle ReScript .res files 8 | rescript: yarn build:rescript:dev 9 | -------------------------------------------------------------------------------- /spec/dummy/Procfile.dev-static: -------------------------------------------------------------------------------- 1 | # You can run these commands in separate shells 2 | web: rails s -p 3000 3 | 4 | # Next line runs a watch process with Webpack to compile the changed files. 5 | # When making frequent changes to client side assets, you will prefer building Webpack assets 6 | # upon saving rather than when you refresh your browser page. 7 | # Note, if using React on Rails localization you will need to run 8 | # `bundle exec rake react_on_rails:locale` before you run bin/shakapacker 9 | webpack: sh -c 'rm -rf public/packs/* || true && bin/shakapacker -w' 10 | -------------------------------------------------------------------------------- /spec/dummy/Procfile.dev.no.turbolinks: -------------------------------------------------------------------------------- 1 | # Same as Procfile.dev, but disable turbolinks. 2 | rails: DISABLE_TURBOLINKS=TRUE bin/rails s -p 3000 3 | # Build client and server assets, watching for changes. 4 | webpack: sh -c 'rm -rf public/webpack/development/*' || true && bin/shakapacker --watch 5 | -------------------------------------------------------------------------------- /spec/dummy/README.md: -------------------------------------------------------------------------------- 1 | Using NPM for React on Rails 2 | 3 | - Use `yalc link` to hook up the spec/dummy/client/node_modules to the top level 4 | - Be sure to install Yarn dependencies in spec/dummy/client 5 | 6 | ## Initial setup 7 | 8 | Read [Dev Initial Setup in Tips for Contributors](/CONTRIBUTING.md#dev-initial-setup). 9 | 10 | ## Set up yalc 11 | 12 | ```sh 13 | cd react_on_rails 14 | bundle install 15 | yalc publish 16 | cd spec/dummy 17 | bundle install 18 | yalc link react-on-rails 19 | ``` 20 | 21 | ## Run yarn if not done yet 22 | 23 | ```sh 24 | cd react_on_rails 25 | yarn run dummy:install 26 | cd spec/dummy 27 | yarn build:rescript 28 | ``` 29 | 30 | # Starting the Sample App 31 | 32 | ## Hot Reloading of Rails Assets 33 | 34 | ```sh 35 | foreman start -f Procfile.dev 36 | ``` 37 | 38 | ## Static Loading of Rails Assets 39 | 40 | ```sh 41 | foreman start -f Procfile.dev-static 42 | ``` 43 | 44 | ## Creating Assets for Tests 45 | 46 | ```sh 47 | foreman start -f Procfile.spec 48 | ``` 49 | -------------------------------------------------------------------------------- /spec/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake, 4 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 5 | 6 | require File.expand_path("config/application", __dir__) 7 | 8 | Rails.application.load_tasks 9 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/javascripts/application_non_webpack.js.erb: -------------------------------------------------------------------------------- 1 | // All Webpack assets in development will be loaded via webpack-dev-server 2 | // It's important to include them in layout view above this asset 3 | // because it exposes jQuery for turbolinks and other non-Webpack JS (if any) 4 | 5 | // NOTE: We've got this in the /spec/dummy app because our CI supports testing with and 6 | // without Turbolinks. 7 | 8 | <% if ENV["DISABLE_TURBOLINKS"].blank? %> 9 | <% require_asset "turbolinks" %> 10 | <% end %> 11 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/stylesheets/application_non_webpack.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any styles 10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new 11 | * file per style scope. 12 | * 13 | */ 14 | 15 | input[type="text"] { 16 | min-width: 400px; 17 | } 18 | 19 | .flash.error { 20 | color: beige; 21 | background: red; 22 | padding: 20px; 23 | } 24 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationController < ActionController::Base 4 | # Prevent CSRF attacks by raising an exception. 5 | # For APIs, you may want to use :null_session instead. 6 | protect_from_forgery with: :exception 7 | 8 | rescue_from ReactOnRails::PrerenderError do |err| 9 | raise err if err.err.is_a?(ReactOnRails::JsonParseError) 10 | 11 | Rails.logger.error("Caught ReactOnRails::PrerenderError in ApplicationController error handler.") 12 | Rails.logger.error(err.message) 13 | Rails.logger.error(err.backtrace.join("\n")) 14 | msg = <<~MSG 15 | Error prerendering in react_on_rails. 16 | Redirected back to '/server_side_log_throw_raise_invoker'. 17 | See server logs for output. 18 | MSG 19 | redirect_to server_side_log_throw_raise_invoker_path, 20 | flash: { error: msg } 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /spec/dummy/app/controllers/react_router_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ReactRouterController < ApplicationController 4 | before_action :data 5 | 6 | rescue_from ReactOnRails::PrerenderError do |err| 7 | Rails.logger.error(err.message) 8 | Rails.logger.error(err.backtrace.join("\n")) 9 | redirect_to client_side_hello_world_path, flash: { error: "Error prerendering in react_on_rails. See server logs." } 10 | end 11 | 12 | private 13 | 14 | def data 15 | # This is the props used by the React component. 16 | @app_props_server_render = { 17 | helloWorldData: { 18 | name: "Mr. Server Side Rendering" 19 | } 20 | } 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | end 5 | -------------------------------------------------------------------------------- /spec/dummy/app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/app/mailers/.keep -------------------------------------------------------------------------------- /spec/dummy/app/mailers/dummy_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DummyMailer < ActionMailer::Base 4 | helper ReactOnRailsHelper 5 | default from: "nobody@nope.com" 6 | 7 | def hello_email 8 | mail(to: "otherperson@nope.com", subject: "you've got mail") 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/dummy/app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/app/models/.keep -------------------------------------------------------------------------------- /spec/dummy/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/app/models/concerns/.keep -------------------------------------------------------------------------------- /spec/dummy/app/views/dummy_mailer/hello_email.html.erb: -------------------------------------------------------------------------------- 1 | Someone emailed this to you: 2 | 3 | <%= react_component("HelloWorld", props: { 4 | helloWorldData: { 5 | name: "Mr. Mailing Server Side Rendering" 6 | } 7 | }, prerender: true) %> 8 | -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <% if content_for?(:title) %> 5 | <%= yield(:title) %> 6 | <% else %> 7 | Dummy 8 | <% end %> 9 | 10 | <%= yield :head %> 11 | 12 | 13 | <%= javascript_pack_tag('client-bundle', 'data-turbolinks-track': true) %> 14 | 15 | <%= csrf_meta_tags %> 16 | 17 | 18 | <% flash.each do |key, value| %> 19 | <%= content_tag :div, value, class: "flash #{key}" %> 20 | <% end %> 21 | <%= render "shared/header" %> 22 | 23 | <%= yield %> 24 | 25 | 27 | <%= redux_store_hydration_data %> 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/_xhr_refresh_partial.html.erb: -------------------------------------------------------------------------------- 1 | <%= react_component('HelloWorld', props: { helloWorldData: { name: 'HelloWorld' } }, 2 | prerender: true, 3 | trace: true, 4 | id: "HelloWorld-react-component-0") %> 5 | 6 | <%= react_component('HelloWorldRehydratable', props: { helloWorldData: { name: 'HelloWorldRehydratable' } }, 7 | prerender: true, 8 | trace: true, 9 | id: 'HelloWorldRehydratable-react-component-1') %> 10 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/broken_app.html.erb: -------------------------------------------------------------------------------- 1 | <%= react_component_hash("BrokenApp")['componentHtml'] %> 2 | 3 |
4 | 5 | This page demonstrates a component that suffers a prerendering error but still returns a hash. 6 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/client_side_log_throw.html.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= react_component("HelloWorldWithLogAndThrow", props: @app_props_server_render, 3 | prerender: false, trace: true, id: "HelloWorldWithLogAndThrow-react-component-0") %> 4 |
5 | 6 |

React Rails Client Rendering

7 |

8 | This example demonstrates client side logging and error handling.
9 | Open up your browser console and see the messages.
10 |
11 | What you see in your console is the result of running the JS code found in spec/dummy/client/app/components/HelloWorldWithLogAndThrow.jsx (reproduced below):
12 |

13 |     console.log("console.log in HelloWorld")
14 |     console.warn("console.warn in HelloWorld")
15 |     console.error("console.error in HelloWorld");
16 |     throw new Error("throw in HelloWorldContainer");
17 |   
18 |

19 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/client_side_rescript_hello_world.html.erb: -------------------------------------------------------------------------------- 1 | <%= react_component("HelloWorldReScript", props: @app_props_server_render, prerender: false, trace: true, id: "HelloWorld-rescript-react-component-0") %> 2 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/context_function_return_jsx.html.erb: -------------------------------------------------------------------------------- 1 | <%= react_component("ContextFunctionReturnInvalidJSX", props: @app_props_hello, prerender: false, trace: true, id: "HelloWorld-react-component-0") %> 2 |
3 | 4 |

Example of Console.error from failing to wrap the result in a function.

5 | 6 | See console log for expected error. 7 | 8 | Note, the component still rendered. In the next version, this should just error. 9 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/css_modules_images_fonts_example.html.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= react_component("CssModulesImagesFontsExample", prerender: true, trace: true) %> 3 | 4 |
5 | 6 |

React Rails Server CSS Modules with Images and Fonts

7 |

Used to test digests of images and fonts

8 |
9 |
10 | <%%= react_component("CssModulesImagesFontsExample",
11 |   prerender: true,
12 |   trace: true %>
13 | 
14 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/image_example.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= react_component("ImageExample", prerender: true, trace: true) %> 3 | 4 |
5 | 6 | This page demonstrates using images, both as background images and with img tags. 7 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/pure_component.html.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= react_component("PureComponent", props: { title: "This is a Pure Component!" }, prerender: true, trace: true, id: "PureComponent-react-component-0") %> 3 | 4 |
5 | 6 |

React Rails Server Rendering of Pure Component

7 |
 8 | <%%= react_component("PureComponent",
 9 |   { title: "This is a Pure Component!" },
10 |   prerender: true,
11 |   trace: true,
12 |   id: "PureComponent-react-component-0") %>
13 | 
14 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/pure_component_wrapped_in_function.html.erb: -------------------------------------------------------------------------------- 1 | <%= react_component("PureComponentWrappedInFunction", props: @app_props_server_render, prerender: false, trace: true, id: "HelloWorld-react-component-0") %> 2 | 3 |
4 | 5 |

Example of placing a pure component function in an unnecessary wrapper.

6 | 7 |

8 | You will not see the component render and you will see this warning: 9 |

10 | 11 |
12 |   Warning: Functions are not valid as a React child. This may happen if you return
13 |   a Component instead of  from render. Or maybe you meant to call this
14 |   function rather than return it.
15 | 
16 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/react_helmet.erb: -------------------------------------------------------------------------------- 1 | 2 | <% react_helmet_app = react_component_hash("ReactHelmetApp", 3 | props: { helloWorldData: { name: "Mr. Server Side Rendering"}}, 4 | id: "react-helmet-0", 5 | trace: true) %> 6 | 7 | 8 | <% content_for :title do %> 9 | <%= react_helmet_app['title'] %> 10 | <% end %> 11 | 12 | <%= react_helmet_app["componentHtml"] %> 13 | 14 |
15 | 16 | This page demonstrates a Render-Function that returns htmlResult as an object 17 | with HTML strings on the server side. It is useful to manipulating <head> 18 | content. Check out the page title! 19 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/react_helmet_broken.erb: -------------------------------------------------------------------------------- 1 | 2 | <% react_helmet_app = react_component_hash("ReactHelmetAppBroken", 3 | props: { helloWorldData: { name: "Mr. Server Side Rendering"}}, 4 | id: "react-helmet-0", 5 | trace: true) %> 6 | 7 | 8 | <% content_for :title do %> 9 | <%= react_helmet_app['title'] %> 10 | <% end %> 11 | 12 | <%= react_helmet_app["componentHtml"] %> 13 | 14 |
15 | 16 | This page demonstrates an improperly defined Render-Function. 17 | 18 |

Here's the error message when you forget to mark the function as a Render-Function:

19 | 20 |
21 |   Objects are not valid as a React child (found: object with keys {renderedHtml}). If you meant to render a collection of children, use an array instead.\n    in Unknown
22 | 
23 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/render_js.html.erb: -------------------------------------------------------------------------------- 1 |

Non-React Component

2 |

For example, Suppose you have some JavaScript that generates a string of HTML:

3 |
 4 |   <%%= server_render_js("(function() { var x = ReactOnRails.getComponent('HelloString').component.world(); console.warn('ran console.warn on the server()'); return x;})()") %>
 5 | 
6 |

7 | That will generate this: 8 |

9 | 10 |
11 |
12 | <%= server_render_js("(function() { var x = ReactOnRails.getComponent('HelloString').component.world(); console.warn('ran console.warn on the server()'); return x;})()") %>
13 | 
14 | 15 |
16 | And be sure to check your console for the server side warn message.
17 | Note, unlike calling react_component, there's no client side code. It's just server 18 | rendering. 19 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/rendered_html.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= react_component("RenderedHtml", prerender: true, props: { hello: "world" }, trace: true) %> 3 | 4 |
5 | 6 | This page demonstrates a component that returns renderToString on the server side. 7 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/server_side_hello_world_hooks.html.erb: -------------------------------------------------------------------------------- 1 | <%= react_component("HelloWorldHooks", props: @app_props_server_render, prerender: true, trace: true, id: "HelloWorldHooks-react-component-0") %> 2 |
3 | 4 |

React Rails Server Rendering with Hooks

5 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/server_side_hello_world_props.html.erb: -------------------------------------------------------------------------------- 1 | <%= react_component("HelloWorldProps", props: @app_props_server_render, prerender: true, trace: true, id: "HelloWorldProps-react-component-0") %> 2 |
3 | 4 |

React Rails Server Rendering with different props for server & client

5 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/server_side_log_throw_plain_js.html.erb: -------------------------------------------------------------------------------- 1 | 2 |

React Rails Server Rendering of Plain JS with an Error

3 | 4 |

Suppose you have some JavaScript that generates a string of HTML, but throws this error:

5 |
 6 |   <%%= server_render_js("(function() {
 7 |     var x = ReactOnRails.getComponent('HelloString').world();
 8 |     console.warn('ran console.warn on the server()');
 9 |     throw new Error('Error thrown on server');
10 |     return x;
11 |   })()") %>
12 | 
13 | 
14 | 15 | This is what will get generated: 16 | 17 |
18 | 19 |
20 | <%= server_render_js("(function() {
21 |     var x = ReactOnRails.getComponent('HelloString').world();
22 |     console.warn('ran console.warn on the server()');
23 |     throw new Error('Error thrown on server');
24 |     return x;
25 |   })()") %>
26 | 
27 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/server_side_log_throw_raise.html.erb: -------------------------------------------------------------------------------- 1 | 2 | Next line will throw on the server side because raise_on_prerender_error is true. 3 | This page is never visible because the exception is caught by pages_controller: 4 | 5 | <%= react_component("HelloWorldWithLogAndThrow", props: @app_props_server_render, prerender: true, 6 | trace: true, raise_on_prerender_error: true, id: "HelloWorldWithLogAndThrow-react-component-0") %> 7 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/server_side_log_throw_raise_invoker.html.erb: -------------------------------------------------------------------------------- 1 | 2 |

Server Logging and Throw Error Handling, raise on server error, redirects

3 | 4 |

5 | Click on the link to try to navigate to /server_side_log_throw_raise_invoker. That will redirect back to this page 6 | because of the error handler in application.rb. 7 |

8 | 9 |
    10 |
  1. You will see a flash message at the top of the screen.
  2. 11 |
  3. Be sure to see the messages in the server logs.
  4. 12 |
13 | 14 | Click this link: 15 | <%= link_to "Server Logging and Throw Error Handling, raise on server error, redirects ", 16 | server_side_log_throw_raise_path %> 17 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/turbo_frame_tag_hello_world.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_frame_tag 'hello-turbo-stream' do %> 2 | <%= button_to "send me hello-turbo-stream component", turbo_stream_send_hello_world_path %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/turbo_stream_send_hello_world.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.update 'hello-turbo-stream' do %> 2 | <%= react_component("HelloTurboStream", props: @app_props_hello_from_turbo_stream, force_load: true) %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/turbolinks_cache_disabled.erb: -------------------------------------------------------------------------------- 1 | <% content_for(:head) do %> 2 | 3 | <% end %> 4 | 5 | 6 | <%= react_component("CacheDisabled") %> 7 |
8 | 9 | This page demonstrates that components are still unmounted when the Turbolinks cache is disabled. 10 | -------------------------------------------------------------------------------- /spec/dummy/app/views/pages/xhr_refresh.js.erb: -------------------------------------------------------------------------------- 1 | var container = document.getElementById('component-container'); 2 | container.innerHTML = "<%= escape_javascript(render partial: 'xhr_refresh_partial') %>"; 3 | 4 | var event = document.createEvent('Event'); 5 | event.initEvent('hydrate', true, true); 6 | document.dispatchEvent(event); 7 | -------------------------------------------------------------------------------- /spec/dummy/app/views/react_router/index.html.erb: -------------------------------------------------------------------------------- 1 |

React Router Home

2 | 3 | <%= react_component("RouterApp", props: @app_props_server_render, prerender: true, 4 | raise_on_prerender_error: true, trace: true) %> 5 | -------------------------------------------------------------------------------- /spec/dummy/app/views/react_router/second_page.html.erb: -------------------------------------------------------------------------------- 1 |

React Router: Second Page

2 | 3 | <%= react_component("RouterApp", props: @app_props_server_render, prerender: true, 4 | raise_on_prerender_error: true, trace: true) %> 5 | -------------------------------------------------------------------------------- /spec/dummy/babel.config.js: -------------------------------------------------------------------------------- 1 | const defaultConfigFunc = require('shakapacker/package/babel/preset'); 2 | 3 | module.exports = function createBabelConfig(api) { 4 | const resultConfig = defaultConfigFunc(api); 5 | const isProductionEnv = api.env('production'); 6 | const isDevelopmentEnv = api.env('development'); 7 | 8 | const changesOnDefault = { 9 | presets: [ 10 | [ 11 | '@babel/preset-react', 12 | { 13 | development: !isProductionEnv, 14 | runtime: 'automatic', 15 | useBuiltIns: true, 16 | }, 17 | ], 18 | ].filter(Boolean), 19 | plugins: [ 20 | process.env.WEBPACK_SERVE && 'react-refresh/babel', 21 | !isDevelopmentEnv && [ 22 | 'babel-plugin-transform-react-remove-prop-types', 23 | { 24 | removeImport: true, 25 | }, 26 | ], 27 | ].filter(Boolean), 28 | }; 29 | 30 | resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets]; 31 | resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins]; 32 | 33 | return resultConfig; 34 | }; 35 | -------------------------------------------------------------------------------- /spec/dummy/bin/bootsnap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bootsnap' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("bootsnap", "bootsnap") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/byebug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'byebug' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("byebug", "byebug") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/coderay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'coderay' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("coderay", "coderay") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/coveralls: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'coveralls' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("coveralls", "coveralls") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if ! command -v foreman &> /dev/null 4 | then 5 | echo "Installing foreman..." 6 | gem install foreman 7 | fi 8 | 9 | foreman start -f Procfile.dev 10 | -------------------------------------------------------------------------------- /spec/dummy/bin/htmldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'htmldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("diff-lcs", "htmldiff") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/kill-pry-rescue: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kill-pry-rescue' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("pry-rescue", "kill-pry-rescue") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/launchy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'launchy' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("launchy", "launchy") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/ldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("diff-lcs", "ldiff") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/listen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'listen' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("listen", "listen") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/nokogiri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'nokogiri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("nokogiri", "nokogiri") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/pry: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pry' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("pry", "pry") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/puma: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'puma' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("puma", "puma") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/pumactl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pumactl' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("puma", "pumactl") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/racc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'racc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("racc", "racc") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/rackup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rackup' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rack", "rackup") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /spec/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /spec/dummy/bin/rdoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rdoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rdoc", "rdoc") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/rescue: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rescue' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("pry-rescue", "rescue") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/ri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rdoc", "ri") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rspec' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rspec-core", "rspec") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rubocop' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rubocop", "rubocop") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/ruby-parse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-parse' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("parser", "ruby-parse") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/ruby-rewrite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-rewrite' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("parser", "ruby-rewrite") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/sass: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sass' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sass", "sass") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/sass-convert: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sass-convert' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sass", "sass-convert") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/scss: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'scss' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sass", "scss") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/scss-lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'scss-lint' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("scss_lint", "scss-lint") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/sdoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sdoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sdoc", "sdoc") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/sdoc-merge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sdoc-merge' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sdoc", "sdoc-merge") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/shakapacker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "pathname" 4 | require "bundler/setup" 5 | require "shakapacker" 6 | require "shakapacker/webpack_runner" 7 | 8 | ENV["RAILS_ENV"] ||= "development" 9 | ENV["NODE_ENV"] ||= ENV["RAILS_ENV"] 10 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) 11 | 12 | require "rake" 13 | 14 | # Recommendation is to generate packs before compilation. 15 | # SERVER_BUNDLE_ONLY is true when also running the bin/shakapacker-dev-server, 16 | # so no need to run twice. 17 | unless ENV["SERVER_BUNDLE_ONLY"] == "true" 18 | Rake.application.load_rakefile 19 | Rake::Task["react_on_rails:generate_packs"].invoke 20 | end 21 | 22 | APP_ROOT = File.expand_path("..", __dir__) 23 | Dir.chdir(APP_ROOT) do 24 | Shakapacker::WebpackRunner.run(ARGV) 25 | end 26 | -------------------------------------------------------------------------------- /spec/dummy/bin/shakapacker-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= "development" 4 | ENV["NODE_ENV"] ||= ENV["RAILS_ENV"] 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | require "rake" 12 | require "shakapacker" 13 | require "shakapacker/dev_server_runner" 14 | 15 | # Recommendation is to generate packs before compilation 16 | Rake.application.load_rakefile 17 | Rake::Task["react_on_rails:generate_packs"].invoke 18 | 19 | APP_ROOT = File.expand_path("..", __dir__) 20 | Dir.chdir(APP_ROOT) do 21 | Shakapacker::DevServerRunner.run(ARGV) 22 | end 23 | -------------------------------------------------------------------------------- /spec/dummy/bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'spring' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("spring", "spring") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/sprockets: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sprockets' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sprockets", "sprockets") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/term_cdiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'term_cdiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("term-ansicolor", "term_cdiff") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/term_colortab: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'term_colortab' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("term-ansicolor", "term_colortab") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/term_decolor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'term_decolor' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("term-ansicolor", "term_decolor") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/term_display: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'term_display' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("term-ansicolor", "term_display") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/term_mandel: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'term_mandel' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("term-ansicolor", "term_mandel") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/term_snow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'term_snow' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("term-ansicolor", "term_snow") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/thor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'thor' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("thor", "thor") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/tilt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'tilt' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("tilt", "tilt") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/webpacker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "pathname" 4 | require "bundler/setup" 5 | require "webpacker" 6 | require "webpacker/webpack_runner" 7 | 8 | ENV["RAILS_ENV"] ||= "development" 9 | ENV["NODE_ENV"] ||= ENV["RAILS_ENV"] 10 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) 11 | 12 | require "rake" 13 | 14 | # Recommendation is to generate packs before compilation. 15 | # SERVER_BUNDLE_ONLY is true when also running the bin/webpacker-dev-server, 16 | # so no need to run twice. 17 | unless ENV["SERVER_BUNDLE_ONLY"] == "true" 18 | Rake.application.load_rakefile 19 | Rake::Task["react_on_rails:generate_packs"].invoke 20 | end 21 | 22 | APP_ROOT = File.expand_path("..", __dir__) 23 | Dir.chdir(APP_ROOT) do 24 | Webpacker::WebpackRunner.run(ARGV) 25 | end 26 | -------------------------------------------------------------------------------- /spec/dummy/bin/webpacker-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= "development" 4 | ENV["NODE_ENV"] ||= ENV["RAILS_ENV"] 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | require "rake" 12 | require "webpacker" 13 | require "webpacker/dev_server_runner" 14 | 15 | # Recommendation is to generate packs before compilation 16 | Rake.application.load_rakefile 17 | Rake::Task["react_on_rails:generate_packs"].invoke 18 | 19 | APP_ROOT = File.expand_path("..", __dir__) 20 | Dir.chdir(APP_ROOT) do 21 | Webpacker::DevServerRunner.run(ARGV) 22 | end 23 | -------------------------------------------------------------------------------- /spec/dummy/bin/yard: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yard' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yard") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/yardoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yardoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yardoc") 30 | -------------------------------------------------------------------------------- /spec/dummy/bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file will be removed soon. 4 | 5 | APP_ROOT = File.expand_path("..", __dir__) 6 | Dir.chdir(APP_ROOT) do 7 | yarn = ENV["PATH"].split(File::PATH_SEPARATOR). 8 | select { |dir| File.expand_path(dir) != __dir__ }. 9 | product(["yarn", "yarnpkg", "yarn.cmd", "yarn.ps1"]). 10 | map { |dir, file| File.expand_path(file, dir) }. 11 | find { |file| File.executable?(file) } 12 | 13 | if yarn 14 | exec yarn, *ARGV 15 | else 16 | $stderr.puts "Yarn executable was not detected in the system." 17 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 18 | exit 1 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /spec/dummy/bin/yri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yri") 30 | -------------------------------------------------------------------------------- /spec/dummy/client/app-react16/startup/ManualRenderApp.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | export default (props, _railsContext, domNodeId) => { 5 | const reactElement = ( 6 |
7 |

Manual Render Example

8 |

If you can see this, you can register renderer functions.

9 |
10 | ); 11 | 12 | const domNode = document.getElementById(domNodeId); 13 | if (props.prerender) { 14 | ReactDOM.hydrate(reactElement, domNode); 15 | } else { 16 | ReactDOM.render(reactElement, domNode); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /spec/dummy/client/app/actions/HelloWorldActions.jsx: -------------------------------------------------------------------------------- 1 | import * as actionTypes from '../constants/HelloWorldConstants'; 2 | 3 | /* eslint-disable import/prefer-default-export */ 4 | export function updateName(name) { 5 | return { 6 | type: actionTypes.HELLO_WORLD_NAME_UPDATE, 7 | name, 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /spec/dummy/client/app/assets/fonts/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/assets/fonts/OpenSans-Light.ttf -------------------------------------------------------------------------------- /spec/dummy/client/app/assets/images/256egghead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/assets/images/256egghead.png -------------------------------------------------------------------------------- /spec/dummy/client/app/assets/images/guest-list-accepted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/assets/images/guest-list-accepted.png -------------------------------------------------------------------------------- /spec/dummy/client/app/assets/images/hookipa-beach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/assets/images/hookipa-beach.png -------------------------------------------------------------------------------- /spec/dummy/client/app/assets/images/logos/railsonmaui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/assets/images/logos/railsonmaui.png -------------------------------------------------------------------------------- /spec/dummy/client/app/assets/images/section-title-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/assets/images/section-title-bg.png -------------------------------------------------------------------------------- /spec/dummy/client/app/assets/styles/app-variables.scss: -------------------------------------------------------------------------------- 1 | // Defining application SASS variables in stand-alone file, 2 | // so we can use them in bootstrap-loader and CSS Modules via sass-resources-loader 3 | // It will be used in SASS components imported as CSS Modules 4 | 5 | $bright-color: red; 6 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/EchoProps.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const EchoProps = (props) =>
Props: {JSON.stringify(props)}
; 4 | 5 | export default EchoProps; 6 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/HelloWorld.module.scss: -------------------------------------------------------------------------------- 1 | .brightColor { 2 | color: $bright-color; 3 | } 4 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/HelloWorldContainer.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { bindActionCreators } from 'redux'; 5 | 6 | import HelloWorldRedux from './HelloWorldRedux'; 7 | 8 | import * as helloWorldActions from '../actions/HelloWorldActions'; 9 | 10 | const HelloWorldContainer = ({ actions, data, railsContext }) => ( 11 | 12 | ); 13 | HelloWorldContainer.propTypes = { 14 | actions: PropTypes.object.isRequired, 15 | data: PropTypes.object.isRequired, 16 | railsContext: PropTypes.object.isRequired, 17 | }; 18 | 19 | function mapStateToProps(state) { 20 | return { 21 | data: state.helloWorldData, 22 | railsContext: state.railsContext, 23 | }; 24 | } 25 | 26 | function mapDispatchToProps(dispatch) { 27 | return { actions: bindActionCreators(helloWorldActions, dispatch) }; 28 | } 29 | 30 | // Don't forget to actually use connect! 31 | export default connect(mapStateToProps, mapDispatchToProps)(HelloWorldContainer); 32 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/HelloWorldReScript.res: -------------------------------------------------------------------------------- 1 | // The compiled JavaScript will always extract your props passed to the compiled file from Props, where Props 2 | // is the same hash passed to react_component method on the view. Log the Props in the compiled JS 3 | // and make sure the props passed to the component below match the shape of the prop passed on the view. 4 | 5 | // `let default` is used to make the component the default export 6 | @react.component 7 | let default = (~helloWorldData: {..}) => { 8 | let (nameState, setNameState) = React.useState(_ => helloWorldData["name"]) 9 |
10 |

{"ReScript Component Client Rendered"->React.string}

11 |

{("Hello from ReScript, " ++ nameState ++ ` 🤙`)->React.string}

12 |
13 |
14 | 23 |
24 |
25 | } 26 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/ImageExample/ImageExample.module.scss: -------------------------------------------------------------------------------- 1 | .red { 2 | color: red; 3 | } 4 | 5 | .background { 6 | background-image: url(assets/images/section-title-bg.png); 7 | } 8 | 9 | .backgroundSameDirectory { 10 | color: white; 11 | background-image: url(./bg-hero.png); 12 | padding: 20px; 13 | } 14 | 15 | .googleLogo { 16 | width: 800px; 17 | height: 300px; 18 | background-image: url(./bg-Google-Logo.svg); 19 | } 20 | 21 | .legoIcon { 22 | width: 800px; 23 | height: 300px; 24 | background-image: url(assets/images/bg_lego_icon.svg); 25 | } 26 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/ImageExample/bg-hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/components/ImageExample/bg-hero.png -------------------------------------------------------------------------------- /spec/dummy/client/app/components/ImageExample/bower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/client/app/components/ImageExample/bower.png -------------------------------------------------------------------------------- /spec/dummy/client/app/components/ReactHelmet.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Helmet } from 'react-helmet'; 3 | import HelloWorld from '../startup/HelloWorld'; 4 | 5 | const ReactHelmet = (props) => ( 6 |
7 | 8 | Custom page title 9 | 10 | Props: {JSON.stringify(props)} 11 | 12 |
13 | ); 14 | 15 | export default ReactHelmet; 16 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/RouterFirstPage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const RouterFirstPage = () => ( 4 |
5 |

React Router First Page

6 |

This page brought to you by React Router

7 |
8 | ); 9 | 10 | export default RouterFirstPage; 11 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/RouterLayout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link, Route, Switch } from 'react-router-dom'; 3 | import RouterFirstPage from './RouterFirstPage'; 4 | import RouterSecondPage from './RouterSecondPage'; 5 | 6 | const RouterLayout = () => ( 7 |
8 |

React Router is working!

9 |

10 | Woohoo, we can use react-router here! 11 |

12 |
    13 |
  • 14 | React Router Layout Only 15 |
  • 16 |
  • 17 | Router First Page 18 |
  • 19 |
  • 20 | Router Second Page 21 |
  • 22 |
23 |
24 | 25 | 26 | 27 | 28 |
29 | ); 30 | 31 | export default RouterLayout; 32 | -------------------------------------------------------------------------------- /spec/dummy/client/app/components/RouterSecondPage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const RouterSecondPage = () => ( 4 |
5 |

React Router Second Page

6 |

This page brought to you by React Router

7 |
8 | ); 9 | 10 | export default RouterSecondPage; 11 | -------------------------------------------------------------------------------- /spec/dummy/client/app/constants/HelloWorldConstants.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | export const HELLO_WORLD_NAME_UPDATE = 'HELLO_WORLD_NAME_UPDATE'; 3 | -------------------------------------------------------------------------------- /spec/dummy/client/app/non_react/HelloString.js: -------------------------------------------------------------------------------- 1 | // Super simple example without using React. 2 | // This shows you can server side render any JS code. 3 | 4 | const HelloString = { 5 | world() { 6 | return 'Hello WORLD! Will this work?? YES! Time to visit Maui'; 7 | }, 8 | }; 9 | 10 | export default HelloString; 11 | -------------------------------------------------------------------------------- /spec/dummy/client/app/packs/client-bundle.js: -------------------------------------------------------------------------------- 1 | import 'core-js/stable'; 2 | import 'regenerator-runtime/runtime'; 3 | import 'jquery'; 4 | import 'jquery-ujs'; 5 | import '@hotwired/turbo-rails'; 6 | 7 | import ReactOnRails from 'react-on-rails/client'; 8 | 9 | import HelloTurboStream from '../startup/HelloTurboStream'; 10 | import SharedReduxStore from '../stores/SharedReduxStore'; 11 | 12 | ReactOnRails.setOptions({ 13 | traceTurbolinks: true, 14 | turbo: true, 15 | }); 16 | 17 | ReactOnRails.register({ 18 | HelloTurboStream, 19 | }); 20 | 21 | ReactOnRails.registerStore({ 22 | SharedReduxStore, 23 | }); 24 | -------------------------------------------------------------------------------- /spec/dummy/client/app/packs/rescript-components.js: -------------------------------------------------------------------------------- 1 | // This file is used to import your compiled rescript files 2 | // As per the current configuration, all files are compiled to .res.js 3 | // and they are generated on the same directory as the .res file 4 | 5 | import HelloWorldReScript from '../components/HelloWorldReScript.res.js'; 6 | 7 | export default HelloWorldReScript; 8 | -------------------------------------------------------------------------------- /spec/dummy/client/app/packs/server-bundle.js: -------------------------------------------------------------------------------- 1 | // import statement added by react_on_rails:generate_packs rake task 2 | import './../generated/server-bundle-generated.js'; // eslint-disable-line import/extensions 3 | // Shows the mapping from the exported object to the name used by the server rendering. 4 | import ReactOnRails from 'react-on-rails'; 5 | // Example of server rendering with no React 6 | import HelloString from '../non_react/HelloString'; 7 | 8 | import SharedReduxStore from '../stores/SharedReduxStore'; 9 | 10 | ReactOnRails.register({ 11 | HelloString, 12 | }); 13 | 14 | ReactOnRails.registerStore({ 15 | SharedReduxStore, 16 | }); 17 | -------------------------------------------------------------------------------- /spec/dummy/client/app/reducers/HelloWorldReducer.jsx: -------------------------------------------------------------------------------- 1 | import * as actionTypes from '../constants/HelloWorldConstants'; 2 | 3 | const initialState = { 4 | lastActionType: null, 5 | name: 'Alex', 6 | }; 7 | 8 | // Why name function the same as the reducer? 9 | // https://github.com/gaearon/redux/issues/428#issuecomment-129223274 10 | // Naming the function will help with debugging! 11 | export default function helloWorldReducer(state = initialState, action = {}) { 12 | const { type, name } = action; 13 | switch (type) { 14 | case actionTypes.HELLO_WORLD_NAME_UPDATE: 15 | return { 16 | lastActionType: type, 17 | name, 18 | }; 19 | default: 20 | return state; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /spec/dummy/client/app/reducers/nullReducer.jsx: -------------------------------------------------------------------------------- 1 | // This will always get set 2 | const initialState = {}; 3 | 4 | // Why name function the same as the reducer? 5 | // https://github.com/gaearon/redux/issues/428#issuecomment-129223274 6 | // Naming the function will help with debugging! 7 | export default function railsContextReducer(state = initialState, _action = {}) { 8 | return state; 9 | } 10 | -------------------------------------------------------------------------------- /spec/dummy/client/app/reducers/reducersIndex.jsx: -------------------------------------------------------------------------------- 1 | import helloWorldReducer from './HelloWorldReducer'; 2 | import nullReducer from './nullReducer'; 3 | 4 | // This is how you do a directory of reducers. 5 | // The `import * as reducers` does not work for a directory, but only with a single file 6 | export default { 7 | helloWorldData: helloWorldReducer, 8 | railsContext: nullReducer, 9 | modificationTarget: nullReducer, 10 | }; 11 | -------------------------------------------------------------------------------- /spec/dummy/client/app/routes/routes.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route } from 'react-router-dom'; 3 | 4 | import RouterLayout from '../components/RouterLayout'; 5 | 6 | export default ; 7 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/BrokenApp.jsx: -------------------------------------------------------------------------------- 1 | // Top level component for simple client side only rendering 2 | import React from 'react'; 3 | 4 | /* 5 | * Just an example of what can go wrong while coding. No import. Whoops! 6 | */ 7 | // eslint-disable-next-line react/jsx-no-undef 8 | export default (props) => ; 9 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/CacheDisabled.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class CacheDisabled extends React.Component { 4 | componentWillUnmount() { 5 | console.log('CacheDisabled#componentWillUnmount'); 6 | } 7 | 8 | render() { 9 | return ( 10 |
11 |

Turbolinks cache is disabled

12 |

Must call componentWillUnmount.

13 |
14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/CssModulesImagesFontsExample.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from '../components/CssModulesImagesFontsExample.module.scss'; 4 | 5 | export default (_props) => ( 6 |
7 |

This should be open sans light green.

8 |
9 |

Hookipa Beach image (relative path)

10 |
11 |
12 |
13 |

Check (URL encoded)

14 |
15 |
16 |
17 |

Rails on Maui Logo (absolute path)

18 |
19 |
20 |
21 | ); 22 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/HelloTurboStream.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import RailsContext from '../components/RailsContext'; 4 | 5 | import css from '../components/HelloWorld.module.scss'; 6 | 7 | const HelloTurboStream = ({ helloTurboStreamData, railsContext }) => ( 8 |
9 |

Hello, {helloTurboStreamData.name}!

10 | {railsContext && } 11 |
12 | ); 13 | 14 | HelloTurboStream.propTypes = { 15 | helloTurboStreamData: PropTypes.shape({ 16 | name: PropTypes.string, 17 | }).isRequired, 18 | railsContext: PropTypes.object, 19 | }; 20 | 21 | export default HelloTurboStream; 22 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/HelloWorldApp.jsx: -------------------------------------------------------------------------------- 1 | // Top level component for simple client side only rendering 2 | import React from 'react'; 3 | import HelloWorld from './HelloWorld'; 4 | 5 | /* 6 | * Export a function that takes the props and returns a ReactComponent. 7 | * This is used for the client rendering hook after the page html is rendered. 8 | * React will see that the state is the same and not do anything. 9 | * Note, this is imported as "HelloWorldApp" by "client-bundle.js" 10 | * 11 | * Note, this is a fictional example, as you'd only use a Render-Function if you wanted to run 12 | * some extra code, such as setting up Redux and React Router. 13 | */ 14 | export default (props) => ; 15 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/HelloWorldHooks.jsx: -------------------------------------------------------------------------------- 1 | // Super simple example of the simplest possible React component 2 | import React, { useState } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import css from '../components/HelloWorld.module.scss'; 5 | 6 | // TODO: make more like the HelloWorld.jsx 7 | function HelloWorldHooks({ helloWorldData }) { 8 | const [name, setName] = useState(helloWorldData.name); 9 | return ( 10 |
11 |

Hello, {name}!

12 |

13 | Say hello to: 14 | setName(e.target.value)} /> 15 |

16 |
17 | ); 18 | } 19 | 20 | HelloWorldHooks.propTypes = { 21 | helloWorldData: PropTypes.shape({ 22 | name: PropTypes.string.isRequired, 23 | }).isRequired, 24 | }; 25 | 26 | export default HelloWorldHooks; 27 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/HelloWorldReScript.jsx: -------------------------------------------------------------------------------- 1 | import HelloWorldReScript from '../components/HelloWorldReScript.res.js'; 2 | 3 | export default HelloWorldReScript; 4 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/HelloWorldWithLogAndThrow.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import React from 'react'; 3 | 4 | // Example of logging and throw error handling 5 | 6 | const HelloWorldWithLogAndThrow = (props, context) => { 7 | console.log('console.log in HelloWorld'); 8 | console.warn('console.warn in HelloWorld'); 9 | console.error('console.error in HelloWorld'); 10 | throw new Error('throw in HelloWorldWithLogAndThrow'); 11 | }; 12 | 13 | export default HelloWorldWithLogAndThrow; 14 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/ManualRenderApp.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOMClient from 'react-dom/client'; 3 | 4 | export default (props, _railsContext, domNodeId) => { 5 | const reactElement = ( 6 |
7 |

Manual Render Example

8 |

If you can see this, you can register renderer functions.

9 |
10 | ); 11 | 12 | const domNode = document.getElementById(domNodeId); 13 | if (props.prerender) { 14 | ReactDOMClient.hydrateRoot(domNode, reactElement); 15 | } else { 16 | const root = ReactDOMClient.createRoot(domNode); 17 | root.render(reactElement); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/PureComponent.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/prop-types */ 2 | import React from 'react'; 3 | 4 | export default ({ title }) =>

{title}

; 5 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/PureComponentWrappedInFunction.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/prop-types */ 2 | import React from 'react'; 3 | 4 | // The extra function wrapper is unnecessary here 5 | export default (props) => () =>

{props.title}

; 6 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/ReactHelmetApp.client.jsx: -------------------------------------------------------------------------------- 1 | // Top level component for simple client side only rendering 2 | import React from 'react'; 3 | import ReactHelmet from '../components/ReactHelmet'; 4 | 5 | // This works fine, React functional component: 6 | // export default (props) => ; 7 | 8 | export default (props) => ; 9 | 10 | // Note, the server side has to be a Render-Function 11 | 12 | // If you want a renderFunction, return a ReactComponent 13 | // export default (props, _railsContext) => () => ; 14 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx: -------------------------------------------------------------------------------- 1 | // Top level component for simple client side only rendering 2 | import React from 'react'; 3 | import ReactHelmet from '../components/ReactHelmet'; 4 | 5 | // This works fine, React functional component: 6 | // export default (props) => ; 7 | 8 | export default (props) => ; 9 | 10 | // Note, the server side has to be a Render-Function 11 | 12 | // If you want a renderFunction, return a ReactComponent 13 | // export default (props, _railsContext) => () => ; 14 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/ReduxSharedStoreApp.server.jsx: -------------------------------------------------------------------------------- 1 | // Top level component for the server side. 2 | // Compare this to the ./ReduxSharedStoreApp.client.jsx file which is used for client side rendering. 3 | 4 | import React from 'react'; 5 | import ReactOnRails from 'react-on-rails'; 6 | import { Provider } from 'react-redux'; 7 | 8 | import HelloWorldContainer from '../components/HelloWorldContainer'; 9 | 10 | /* 11 | * Export a function that returns a ReactComponent, depending on a store named SharedReduxStore. 12 | * This is used for the server rendering. 13 | * React will see that the state is the same and not do anything. 14 | */ 15 | export default () => { 16 | // This is where we get the existing store. 17 | const store = ReactOnRails.getStore('SharedReduxStore'); 18 | 19 | return ( 20 | 21 | 22 | 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/RenderedHtml.client.jsx: -------------------------------------------------------------------------------- 1 | // Top level component for simple client side only rendering 2 | import React from 'react'; 3 | 4 | import EchoProps from '../components/EchoProps'; 5 | 6 | /* 7 | * Export a function that takes the props and returns a ReactComponent. 8 | * This is used for the client rendering hook after the page html is rendered. 9 | * React will see that the state is the same and not do anything. 10 | * Note, this is imported as "HelloWorldApp" by "client-bundle.js" 11 | * 12 | * Note, this is a fictional example, as you'd only use a Render-Function if you wanted to run 13 | * some extra code, such as setting up Redux and React Router. 14 | */ 15 | 16 | // This will not work: 17 | // export default (props, _railsContext) => () => ; 18 | 19 | // You may do either: 20 | // export default (props, _railsContext) => () => ; 21 | // or 22 | export default (props) => ; 23 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/RenderedHtml.server.jsx: -------------------------------------------------------------------------------- 1 | // Top level component for simple client side only rendering 2 | import React from 'react'; 3 | import { renderToString } from 'react-dom/server'; 4 | import EchoProps from '../components/EchoProps'; 5 | 6 | /* 7 | * Export a function that takes the props and returns an object with { renderedHtml } 8 | * Note, this is imported as "RenderedHtml" by "serverRegistration.jsx" 9 | * 10 | * Note, this is a fictional example, as you'd only use a Render-Function if you wanted to run 11 | * some extra code, such as setting up Redux and React Router. 12 | * 13 | * And the use of renderToString would probably be done with React Router v4 14 | * 15 | */ 16 | export default (props, _railsContext) => { 17 | const renderedHtml = renderToString(); 18 | return { renderedHtml }; 19 | }; 20 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/RouterApp.client.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter } from 'react-router-dom'; 3 | import routes from '../routes/routes'; 4 | 5 | export default (props) => {routes}; 6 | -------------------------------------------------------------------------------- /spec/dummy/client/app/startup/RouterApp.server.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StaticRouter } from 'react-router-dom'; 3 | 4 | import routes from '../routes/routes'; 5 | 6 | export default (props, railsContext) => () => ( 7 | 8 | {routes} 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /spec/dummy/client/app/store/composeInitialState.js: -------------------------------------------------------------------------------- 1 | // Real world is that you'll want to do lots of manipulations of the data you get back from Rails 2 | // to coerce it into exactly what you want your initial redux state. 3 | export default (props, railsContext) => ({ ...props, railsContext }); 4 | -------------------------------------------------------------------------------- /spec/dummy/client/app/stores/SharedReduxStore.jsx: -------------------------------------------------------------------------------- 1 | import { combineReducers, applyMiddleware, createStore } from 'redux'; 2 | import middleware from 'redux-thunk'; 3 | 4 | import reducers from '../reducers/reducersIndex'; 5 | 6 | /* 7 | * Export a function that takes the props and returns a Redux store 8 | * This is used so that 2 components can have the same store. 9 | */ 10 | export default (props, railsContext) => { 11 | // eslint-disable-next-line no-param-reassign 12 | delete props.prerender; 13 | const combinedReducer = combineReducers(reducers); 14 | const newProps = { ...props, railsContext }; 15 | return applyMiddleware(middleware)(createStore)(combinedReducer, newProps); 16 | }; 17 | -------------------------------------------------------------------------------- /spec/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require File.expand_path("config/environment", __dir__) 6 | run Rails.application 7 | -------------------------------------------------------------------------------- /spec/dummy/config/application.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "boot" 4 | 5 | require "rails/all" 6 | 7 | # Require the gems listed in Gemfile, including any gems 8 | # you've limited to :test, :development, or :production. 9 | Bundler.require(*Rails.groups) 10 | 11 | module Temp 12 | class Application < Rails::Application 13 | # Initialize configuration defaults for originally generated Rails version. 14 | config.load_defaults 7.0 15 | 16 | # Configuration for the application, engines, and railties goes here. 17 | # 18 | # These settings can be overridden in specific environments using the files 19 | # in config/environments, which are processed later. 20 | # 21 | # config.time_zone = "Central Time (US & Canada)" 22 | # config.eager_load_paths << Rails.root.join("extras") 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 4 | 5 | require "bundler/setup" # Set up gems listed in the Gemfile. 6 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 7 | -------------------------------------------------------------------------------- /spec/dummy/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: redis 3 | url: redis://localhost:6379/1 4 | 5 | test: 6 | adapter: test 7 | 8 | production: 9 | adapter: redis 10 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 11 | channel_prefix: temp_production 12 | -------------------------------------------------------------------------------- /spec/dummy/config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | SGPCEzTr41Cjv7oecwtA3hQeox+CF5QSTJkOvOZeR7m0WcEiKNqgzNZ7blylzNGTsLUupf0a3uEAzhK+mQ52+BDeiNwtqPP6tvfz0ikL4XIp7zjiWdZi1ovwq9JawWNwGWtZ4jzg1Oj1kjC5KrHX12l4KzpMDqaV8Yk1ywFfFfSnjx5fkgc8+/dLcRr+IyeE7tkxbDLCDgcNVwqy7zZD+WUlU3bHHANAv0oTdDRFzOZaGMNdIfxARHz8wUvZaxNbfiS+W6AUPaeH9S0nOKLM8YWOLmu5PoA28uaVnFLCHMKDP4oNAH+B67UZKI9iewxTpPVlEtwM7YWJG0i+SGtIcDuDsZoGrP1IoqwWwQ3sjQd05y2KhEoLikfUXCIpRyuibh0Y+CO2f0qLIo8M8XuHqb6fzba5KergCnAy--SrDiYEwaWpAjO2G1--8CWGm1XpAQewwCktv1x2/A== -------------------------------------------------------------------------------- /spec/dummy/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem "sqlite3" 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /spec/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load the Rails application. 4 | require_relative "application" 5 | 6 | # Initialize the Rails application. 7 | Rails.application.initialize! 8 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Version of your assets, change this if you want to expire all your assets. 6 | Rails.application.config.assets.version = "1.0" 7 | 8 | # Add additional assets to the asset load path. 9 | # Rails.application.config.assets.paths << Emoji.images_path 10 | 11 | # Precompile additional assets. 12 | # application.js, application.css, and all non-JS/CSS in the app/assets 13 | # folder are already added. 14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 15 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Configure sensitive parameters which will be filtered from the log file. 6 | Rails.application.config.filter_parameters += %i[ 7 | passw secret token _key crypt salt certificate otp ssn 8 | ] 9 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new inflection rules using the following format. Inflections 6 | # are locale specific, and you may define rules for as many different 7 | # locales as you wish. All of these examples are active by default: 8 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 9 | # inflect.plural /^(ox)$/i, "\\1en" 10 | # inflect.singular /^(ox)en/i, "\\1" 11 | # inflect.irregular "person", "people" 12 | # inflect.uncountable %w( fish sheep ) 13 | # end 14 | 15 | # These inflection rules are supported but not enabled by default: 16 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 17 | # inflect.acronym "RESTful" 18 | # end 19 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Define an application-wide HTTP permissions policy. For further 4 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 5 | # 6 | # Rails.application.config.permissions_policy do |f| 7 | # f.camera :none 8 | # f.gyroscope :none 9 | # f.microphone :none 10 | # f.usb :none 11 | # f.fullscreen :self 12 | # f.payment :self, "https://secure.example.com" 13 | # end 14 | -------------------------------------------------------------------------------- /spec/dummy/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t "hello" 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t("hello") %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # "true": "foo" 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: 'Hello world' 34 | -------------------------------------------------------------------------------- /spec/dummy/config/master.key: -------------------------------------------------------------------------------- 1 | 19be4edd26160a9160fadb7c9247381a -------------------------------------------------------------------------------- /spec/dummy/config/webpack/DEBUGGING.md: -------------------------------------------------------------------------------- 1 | # Debugging 2 | 3 | # https://github.com/rails/webpacker/pull/2018 4 | 5 | To debug: 6 | bin/shakapacker --debug 7 | 8 | And put a debugger statement in the file you're editing. 9 | 10 | Here's how to configure the customizations: 11 | 12 | [Webpack Customization](https://github.com/rails/webpacker/blob/master/docs/webpack.md) 13 | -------------------------------------------------------------------------------- /spec/dummy/config/webpack/alias.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path'); 2 | 3 | module.exports = { 4 | resolve: { 5 | alias: { 6 | Assets: resolve(__dirname, '..', '..', 'client', 'app', 'assets'), 7 | }, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /spec/dummy/config/webpack/clientWebpackConfig.js: -------------------------------------------------------------------------------- 1 | const commonWebpackConfig = require('./commonWebpackConfig'); 2 | 3 | const configureClient = () => { 4 | const clientConfig = commonWebpackConfig(); 5 | 6 | // server-bundle is special and should ONLY be built by the serverConfig 7 | // In case this entry is not deleted, a very strange "window" not found 8 | // error shows referring to window["webpackJsonp"]. That is because the 9 | // client config is going to try to load chunks. 10 | delete clientConfig.entry['server-bundle']; 11 | 12 | return clientConfig; 13 | }; 14 | 15 | module.exports = configureClient; 16 | -------------------------------------------------------------------------------- /spec/dummy/config/webpack/development.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'; 2 | 3 | const { devServer, inliningCss } = require('shakapacker'); 4 | 5 | const webpackConfig = require('./webpackConfig'); 6 | 7 | const developmentEnvOnly = (clientWebpackConfig, _serverWebpackConfig) => { 8 | // plugins 9 | if (inliningCss) { 10 | // Note, when this is run, we're building the server and client bundles in separate processes. 11 | // Thus, this plugin is not applied to the server bundle. 12 | 13 | // eslint-disable-next-line global-require 14 | const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); 15 | clientWebpackConfig.plugins.push( 16 | new ReactRefreshWebpackPlugin({ 17 | overlay: { 18 | sockPort: devServer.port, 19 | }, 20 | }), 21 | ); 22 | } 23 | }; 24 | 25 | module.exports = webpackConfig(developmentEnvOnly); 26 | -------------------------------------------------------------------------------- /spec/dummy/config/webpack/production.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production'; 2 | 3 | const webpackConfig = require('./webpackConfig'); 4 | 5 | const productionEnvOnly = (_clientWebpackConfig, _serverWebpackConfig) => { 6 | // place any code here that is for production only 7 | }; 8 | 9 | module.exports = webpackConfig(productionEnvOnly); 10 | -------------------------------------------------------------------------------- /spec/dummy/config/webpack/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'; 2 | 3 | const webpackConfig = require('./webpackConfig'); 4 | 5 | const testOnly = (_clientWebpackConfig, _serverWebpackConfig) => { 6 | // place any code here that is for test only 7 | }; 8 | 9 | module.exports = webpackConfig(testOnly); 10 | -------------------------------------------------------------------------------- /spec/dummy/config/webpack/webpack-notes.md: -------------------------------------------------------------------------------- 1 | 1. Referencing CSS/Sass module files requires specifying the full extension of 2 | '.module.scss'. Otherwise, the file loads, but no CSS modules are applied. 3 | 2. extract_css should be false for development if one wants to use HMR for styles, 4 | which is typically more efficient. 5 | -------------------------------------------------------------------------------- /spec/dummy/config/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const { env, generateWebpackConfig } = require('shakapacker'); 2 | 3 | const { existsSync } = require('fs'); 4 | const { resolve } = require('path'); 5 | 6 | const envSpecificConfig = () => { 7 | const path = resolve(__dirname, `${env.nodeEnv}.js`); 8 | if (existsSync(path)) { 9 | console.log(`Loading ENV specific webpack configuration file ${path}`); 10 | // eslint-disable-next-line import/no-dynamic-require, global-require 11 | return require(path); 12 | } 13 | return generateWebpackConfig(); 14 | }; 15 | 16 | module.exports = envSpecificConfig(); 17 | -------------------------------------------------------------------------------- /spec/dummy/db/schema.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is auto-generated from the current state of the database. Instead 4 | # of editing this file, please use the migrations feature of Active Record to 5 | # incrementally modify your database, and then regenerate this schema definition. 6 | # 7 | # Note that this schema.rb definition is the authoritative source for your 8 | # database schema. If you need to create the application database on another 9 | # system, you should be using db:schema:load, not running all the migrations 10 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 11 | # you'll amass, the slower it'll run and the greater likelihood for issues). 12 | # 13 | # It's strongly recommended that you check this file into your version control system. 14 | 15 | # rubocop:disable Lint/EmptyBlock 16 | ActiveRecord::Schema.define(version: 0) do 17 | end 18 | # rubocop:enable Lint/EmptyBlock 19 | -------------------------------------------------------------------------------- /spec/dummy/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file should contain all the record creation needed to seed the database with its default values. 4 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 5 | # 6 | # Examples: 7 | # 8 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 9 | # Mayor.create(name: 'Emanuel', city: cities.first) 10 | -------------------------------------------------------------------------------- /spec/dummy/lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/lib/assets/.keep -------------------------------------------------------------------------------- /spec/dummy/lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/lib/tasks/.keep -------------------------------------------------------------------------------- /spec/dummy/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/log/.keep -------------------------------------------------------------------------------- /spec/dummy/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/public/favicon.ico -------------------------------------------------------------------------------- /spec/dummy/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /spec/dummy/rescript.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_on_rails", 3 | "sources": [ 4 | { 5 | "dir": "client/app/components", 6 | "subdirs": true 7 | } 8 | ], 9 | "jsx": { "version": 4 }, 10 | "suffix": ".res.js", 11 | "package-specs": [ 12 | { 13 | "module": "esmodule", 14 | "in-source": true 15 | } 16 | ], 17 | "bs-dependencies": ["@rescript/react"] 18 | } 19 | -------------------------------------------------------------------------------- /spec/dummy/spec/.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: 2 | - ../.rubocop.yml 3 | 4 | Metrics/BlockLength: 5 | Max: 200 6 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithClientAndCommon/ror_components/ComponentWithClientAndCommon.client.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithClientAndCommon/ror_components/ComponentWithClientAndCommon.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithClientOnly/ror_components/ComponentWithClientOnly.client.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithCommonClientAndServer/ror_components/ComponentWithCommonClientAndServer.client.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithCommonClientAndServer/ror_components/ComponentWithCommonClientAndServer.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithCommonClientAndServer/ror_components/ComponentWithCommonClientAndServer.server.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithCommonOnly/ror_components/ComponentWithCommonOnly.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithServerAndCommon/ror_components/ComponentWithServerAndCommon.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithServerAndCommon/ror_components/ComponentWithServerAndCommon.server.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ComponentWithServerOnly/ror_components/ComponentWithServerOnly.server.jsx: -------------------------------------------------------------------------------- 1 | // Empty Test Component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ReactServerComponents/ror_components/ReactClientComponent.jsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | // File with "use client" directive which makes it a client component 4 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ReactServerComponents/ror_components/ReactClientComponentWithClientAndServer.client.jsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | // File with "use client" directive which makes it a client component 4 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ReactServerComponents/ror_components/ReactClientComponentWithClientAndServer.server.jsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | // File with "use client" directive which makes it a client component 4 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ReactServerComponents/ror_components/ReactServerComponent.jsx: -------------------------------------------------------------------------------- 1 | // File without "use client" directive which makes it a server component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ReactServerComponents/ror_components/ReactServerComponentWithClientAndServer.client.jsx: -------------------------------------------------------------------------------- 1 | // File without "use client" directive which makes it a server component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/components/ReactServerComponents/ror_components/ReactServerComponentWithClientAndServer.server.jsx: -------------------------------------------------------------------------------- 1 | // File without "use client" directive which makes it a server component 2 | -------------------------------------------------------------------------------- /spec/dummy/spec/fixtures/automated_packs_generation/packs/server-bundle.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/spec/fixtures/automated_packs_generation/packs/server-bundle.js -------------------------------------------------------------------------------- /spec/dummy/spec/rake/assets_precompile_rake_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake" 4 | 5 | require "rails_helper" 6 | require "react_on_rails" 7 | 8 | describe "rake assets:precompile task" do 9 | it "doesn't show deprecation message for using webpacker:clean task", skip: "fixing this spec breaks other specs" do 10 | allow(ENV).to receive(:[]).with(anything).and_call_original 11 | allow(ENV).to receive(:[]).with("SHAKAPACKER_PRECOMPILE").and_return("false") 12 | allow(ENV).to receive(:[]).with("WEBPACKER_PRECOMPILE").and_return("false") 13 | 14 | Rails.application.load_tasks 15 | 16 | ReactOnRails.configure do |config| 17 | config.build_production_command = "RAILS_ENV=production NODE_ENV=production / 18 | bin/#{ReactOnRails::PackerUtils.packer_type}" 19 | end 20 | 21 | expect do 22 | Rake::Task["assets:precompile"].execute 23 | end.not_to output(/Consider using `rake shakapacker:clean`/).to_stdout 24 | 25 | Rake::Task.clear 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/dummy/spec/simplecov_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Starts SimpleCov for code coverage. 4 | 5 | if ENV["COVERAGE"] == "true" 6 | require "simplecov" 7 | 8 | # Using a command name along with the test_env_number prevents results from 9 | # getting clobbered by other test suites 10 | SimpleCov.command_name ENV["TEST_ENV_COMMAND_NAME"] || "dummy-tests" 11 | 12 | SimpleCov.start("rails") do 13 | # Consider the entire gem project as the root 14 | # (typically this will be the folder named "react_on_rails") 15 | gem_root_path = (File.expand_path __FILE__).slice(%r{(^.*)/spec.*/spec}, 1) 16 | root gem_root_path 17 | 18 | # Don't report anything that has "spec" in the path 19 | # NOTE: this excludes the dummy apps! 20 | add_filter do |src| 21 | src.filename.include?("/spec/") 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/dummy/tests/react-on-rails.import.test.js: -------------------------------------------------------------------------------- 1 | import ReactOnRails from 'react-on-rails'; 2 | 3 | test('ReactOnRails', () => { 4 | ReactOnRails.register({}); 5 | }); 6 | -------------------------------------------------------------------------------- /spec/dummy/tests/react-on-rails.require.test.js: -------------------------------------------------------------------------------- 1 | const ReactOnRails = require('react-on-rails').default; 2 | 3 | test('ReactOnRails', () => { 4 | ReactOnRails.register({}); 5 | }); 6 | -------------------------------------------------------------------------------- /spec/dummy/vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /spec/dummy/vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/dummy/vendor/assets/stylesheets/.keep -------------------------------------------------------------------------------- /spec/empty_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used to compel SimpleCov to output a new report based on its 4 | # cached data. Simply run rspec on this file to do so. 5 | require "simplecov" 6 | SimpleCov.command_name "empty_spec" 7 | -------------------------------------------------------------------------------- /spec/react_on_rails/.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: 2 | - ../../.rubocop.yml 3 | 4 | Metrics/BlockLength: 5 | Max: 145 6 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/absolute_path_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "file:///Users/justin/shakacode/react_on_rails", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/beta_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "^14.0.0.beta-2", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/git_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "git://github.com/shakacode/react-on-rails.git", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/i18n/locales/de.yml: -------------------------------------------------------------------------------- 1 | de: 2 | hello: 'Hallo welt' 3 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/i18n/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | hello: 'Hello world' 3 | argument: 'I am %{age} years old.' 4 | day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] 5 | blank: 6 | number: 2 7 | bool: true 8 | float: 2.0 9 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/i18n/locales_symbols/de.yml: -------------------------------------------------------------------------------- 1 | de: 2 | :hello: "Hallo welt" 3 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/i18n/locales_symbols/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | :hello: "Hello world" 3 | :argument: "I am %{age} years old." 4 | :day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] 5 | :blank: 6 | :number: 2 7 | :bool: true 8 | :float: 2.0 9 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/normal_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "0.0.2", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/relative_path_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "../../..", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/semver_caret_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "^1.2.3", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/semver_range_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": ">=1.0.0 <2.0.0", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/semver_tilde_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "~1.2.3", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_exist/client/myApp.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_exist/client/myApp.jsx -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_exist/compiled_js/client-bundle.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_exist/compiled_js/client-bundle.js -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_exist/compiled_js/server-bundle.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_exist/compiled_js/server-bundle.js -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_exist_only_server_bundle/client/myApp.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_exist_only_server_bundle/client/myApp.jsx -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_exist_only_server_bundle/compiled_js/server-bundle.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_exist_only_server_bundle/compiled_js/server-bundle.js -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_no_exist/client/myApp.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_no_exist/client/myApp.jsx -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_no_exist/compiled_js/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_no_exist/compiled_js/.keep -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_outdated/client/myApp.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_outdated/client/myApp.jsx -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_outdated/compiled/client-bundle.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_outdated/compiled/client-bundle.js -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_outdated/compiled_sass/vendor-bundle.sass: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_outdated/compiled_sass/vendor-bundle.sass -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist/client/myApp.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist/client/myApp.jsx -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist/compiled_js/client-bundle-6bc530d039d96709b68d.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist/compiled_js/client-bundle-6bc530d039d96709b68d.js -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist/compiled_js/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "client-bundle.js": "client-bundle-6bc530d039d96709b68d.js", 3 | "server-bundle.js": "server-bundle-6bc530d039d96702268d.js" 4 | } 5 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist/compiled_js/server-bundle-6bc530d039d96702268d.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist/compiled_js/server-bundle-6bc530d039d96702268d.js -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist_server_bundle_separate/client/myApp.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist_server_bundle_separate/client/myApp.jsx -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist_server_bundle_separate/compiled_js/client-bundle-6bc530d039d96709b68d.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist_server_bundle_separate/compiled_js/client-bundle-6bc530d039d96709b68d.js -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_manifest_exist_server_bundle_separate/compiled_js/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "client-bundle.js": "client-bundle-6bc530d039d96709b68d.js" 3 | } 4 | -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/webpack_assets/assets_with_missing_manifest/client/myApp.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakacode/react_on_rails/57938d022b09ae25cbe6f302804fee796d02a0b9/spec/react_on_rails/fixtures/webpack_assets/assets_with_missing_manifest/client/myApp.jsx -------------------------------------------------------------------------------- /spec/react_on_rails/fixtures/yalc_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "babel": "^6.3.26", 4 | "react-on-rails": "file:.yalc/react-on-rails", 5 | "webpack": "^1.12.8" 6 | }, 7 | "devDependencies": { 8 | "babel-eslint": "^5.0.0-beta6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/react_on_rails/generators/generator_messages_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../support/generator_spec_helper" 4 | 5 | describe GeneratorMessages do 6 | it "has an empty messages array" do 7 | expect(described_class.messages).to be_empty 8 | end 9 | 10 | it "has a method that can add errors" do 11 | described_class.add_error "Test error" 12 | expect(described_class.messages) 13 | .to contain_exactly(described_class.format_error("Test error")) 14 | end 15 | 16 | it "has a method that can add warnings" do 17 | described_class.add_warning "Test warning" 18 | expect(described_class.messages) 19 | .to contain_exactly(described_class.format_warning("Test warning")) 20 | end 21 | 22 | it "has a method that can add info messages" do 23 | described_class.add_info "Test info message" 24 | expect(described_class.messages) 25 | .to contain_exactly(described_class.format_info("Test info message")) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/react_on_rails/json_output_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "spec_helper" 4 | require "react_on_rails/json_output" 5 | 6 | module ReactOnRails 7 | describe JsonOutput do 8 | let(:hash_value) do 9 | { 10 | simple: "hello world", 11 | special: '<>&\u2028\u2029' 12 | } 13 | end 14 | 15 | let(:escaped_json) do 16 | '{"simple":"hello world","special":"\\u003c\\u003e\\u0026\\\\u2028\\\\u2029"}' 17 | end 18 | 19 | shared_examples "escaped json" do 20 | it "returns a well-formatted json with escaped characters" do 21 | expect(subject).to eq(escaped_json) 22 | end 23 | end 24 | 25 | describe ".escape" do 26 | subject { described_class.escape(hash_value.to_json) } 27 | 28 | it_behaves_like "escaped json" 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/react_on_rails/react_on_rails_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "spec_helper" 4 | 5 | describe ReactOnRails do 6 | it "has a version number" do 7 | expect(ReactOnRails::VERSION).not_to be_nil 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/react_on_rails/simplecov_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Starts SimpleCov for code coverage. 4 | 5 | if ENV["COVERAGE"] == "true" 6 | require "simplecov" 7 | # Using a command name prevents results from getting clobbered by other test 8 | # suites 9 | SimpleCov.command_name "gem-tests" 10 | SimpleCov.start do 11 | # Don't include coverage reports on files in "spec" folder 12 | add_filter do |src| 13 | src.filename.include?("/spec/") 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/react_on_rails/support/fixtures_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module FixturesHelper 4 | def self.fixtures_dir 5 | File.join(__dir__, "..", "fixtures") 6 | end 7 | 8 | def self.get_file(file) 9 | File.join(fixtures_dir, *Array(file)) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/react_on_rails/support/shared_examples/base_generator_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples "base_generator" do 4 | it "adds a route for get 'hello_world' to 'hello_world#index'" do 5 | match = <<-MATCH.strip_heredoc 6 | Rails.application.routes.draw do 7 | get 'hello_world', to: 'hello_world#index' 8 | end 9 | MATCH 10 | assert_file "config/routes.rb", match 11 | end 12 | 13 | it "creates react directories" do 14 | dirs = %w[components] 15 | dirs.each { |dirname| assert_directory "app/javascript/bundles/HelloWorld/#{dirname}" } 16 | end 17 | 18 | it "copies react files" do 19 | %w[app/controllers/hello_world_controller.rb 20 | app/javascript/bundles/HelloWorld/components/HelloWorld.jsx 21 | config/initializers/react_on_rails.rb 22 | Procfile.dev 23 | Procfile.dev-static].each { |file| assert_file(file) } 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/react_on_rails/support/shared_examples/react_no_redux_generator_examples.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples "no_redux_generator" do 4 | it "creates appropriate templates" do 5 | assert_file("app/javascript/packs/hello-world-bundle.js") do |contents| 6 | expect(contents).to match("import HelloWorld from '../bundles/HelloWorld/components/HelloWorld';") 7 | end 8 | 9 | assert_file("app/views/hello_world/index.html.erb") do |contents| 10 | expect(contents).to match(/"HelloWorld"/) 11 | end 12 | end 13 | 14 | it "does not place react folders in root" do 15 | %w[reducers store middlewares constants actions].each do |dir| 16 | assert_no_directory(dir) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/react_on_rails/support/version_test_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def stub_gem_version(version) 4 | stub_const("ReactOnRails::VERSION", version) 5 | end 6 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node14", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "esModuleInterop": false, 6 | // needed for Jest tests even though we don't use .tsx 7 | "jsx": "react-jsx", 8 | "lib": ["dom", "es2020"], 9 | "noImplicitAny": true, 10 | "outDir": "node_package/lib", 11 | "allowImportingTsExtensions": true, 12 | "rewriteRelativeImportExtensions": true, 13 | "strict": true, 14 | "incremental": true, 15 | "target": "es2020", 16 | "typeRoots": ["./node_modules/@types", "./node_package/types"] 17 | }, 18 | "include": ["node_package/src/**/*", "node_package/types/**/*"] 19 | } 20 | --------------------------------------------------------------------------------