diff --git a/README.md b/README.md index 8ba38f2e..7d2b686d 100644 --- a/README.md +++ b/README.md @@ -268,6 +268,14 @@ For example: rails generate react:component Label label:string --es6 ``` +**--coffee** : Generate the component using CoffeeScript syntax + +For example: + +```shell +rails generate react:component Label label:string --coffee +``` + #### Arguments The generator can use the following arguments to create basic propTypes: diff --git a/lib/generators/react/component_generator.rb b/lib/generators/react/component_generator.rb index f585c2f5..22fdf1de 100644 --- a/lib/generators/react/component_generator.rb +++ b/lib/generators/react/component_generator.rb @@ -51,9 +51,14 @@ class ComponentGenerator < ::Rails::Generators::NamedBase :banner => "field[:type] field[:type] ..." class_option :es6, - type: :boolean, - default: false, - desc: 'Output es6 class based component' + type: :boolean, + default: false, + desc: 'Output es6 class based component' + + class_option :coffee, + type: :boolean, + default: false, + desc: 'Output coffeescript based component' REACT_PROP_TYPES = { "node" => 'React.PropTypes.node', @@ -85,7 +90,15 @@ class ComponentGenerator < ::Rails::Generators::NamedBase } def create_component_file - extension = options[:es6] ? "es6.jsx" : "js.jsx" + extension = case + when options[:es6] + 'es6.jsx' + when options[:coffee] + 'js.jsx.coffee' + else + 'js.jsx' + end + file_path = File.join('app/assets/javascripts/components', "#{file_name}.#{extension}") template("component.#{extension}", file_path) end diff --git a/lib/generators/templates/component.js.jsx.coffee b/lib/generators/templates/component.js.jsx.coffee new file mode 100644 index 00000000..71f76c02 --- /dev/null +++ b/lib/generators/templates/component.js.jsx.coffee @@ -0,0 +1,18 @@ +class @<%= file_name.camelize %> extends React.Component +<% if attributes.size > 0 -%> + @propTypes = +<% attributes.each do |attribute| -%> + <%= attribute[:name].camelize(:lower) %>: <%= attribute[:type] %> +<% end -%> + +<% end -%> + render: -> +<% if attributes.size > 0 -%> + `
+<% attributes.each do |attribute| -%> +
<%= attribute[:name].titleize %>: {this.props.<%= attribute[:name].camelize(:lower) %>}
+<% end -%> +
` +<% else -%> + `
` +<% end -%> \ No newline at end of file diff --git a/test/generators/coffee_component_generator_test.rb b/test/generators/coffee_component_generator_test.rb new file mode 100644 index 00000000..de101f8c --- /dev/null +++ b/test/generators/coffee_component_generator_test.rb @@ -0,0 +1,40 @@ +require 'test_helper' +require 'generators/react/component_generator' + +class CoffeeComponentGeneratorTest < Rails::Generators::TestCase + destination File.join(Rails.root, 'tmp', 'component_generator_test_output') + setup :prepare_destination + tests React::Generators::ComponentGenerator + + def filename + 'app/assets/javascripts/components/generated_component.js.jsx.coffee' + end + + def class_name + 'GeneratedComponent' + end + + test 'that it the uses CoffeeScript syntax' do + run_generator %w(GeneratedComponent name --coffee) + + assert_file filename, /^class @#{class_name}\sextends\sReact\.Component/ + end + + test 'that propTypes get assigned' do + run_generator %w(GeneratedComponent name --coffee) + + assert_file filename, /@propTypes\s=/ + assert_file filename, /React.PropTypes/ + end + + test 'that it generates working jsx' do + expected_name_div = /React\.createElement\(\s*"div",\s*null,\s*"Name:\s*",\s*this\.props\.name\s*\)/x + expected_shape_div = /React\.createElement\(\s*"div",\s*null,\s*"Address:\s*",\s*this\.props\.address\s*\)/x + + run_generator %w(GeneratedComponent name:string address:shape --coffee) + jsx = React::JSX.transform(CoffeeScript.compile(File.read(File.join(destination_root, filename)))) + + assert_match(Regexp.new(expected_name_div), jsx) + assert_match(Regexp.new(expected_shape_div), jsx) + end +end