├── fixtures └── app │ ├── config.rb │ └── source │ └── assets │ └── javascripts │ ├── plain_jsx.js.jsx │ └── coffeescript.js.jsx.coffee ├── script ├── spec └── bootstrap ├── .travis.yml ├── Gemfile ├── lib ├── middleman-react.rb └── middleman-react │ ├── version.rb │ ├── jsx │ └── template.rb │ ├── extension.rb │ └── jsx.rb ├── spec └── features │ ├── support │ └── env.rb │ ├── jsx.feature │ └── coffeescript.feature ├── .gitignore ├── LICENSE ├── middleman-react.gemspec ├── README.md └── Gemfile.lock /fixtures/app/config.rb: -------------------------------------------------------------------------------- 1 | activate :react 2 | -------------------------------------------------------------------------------- /fixtures/app/source/assets/javascripts/plain_jsx.js.jsx: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 |
; 3 | -------------------------------------------------------------------------------- /script/spec: -------------------------------------------------------------------------------- 1 | #!/bin/sh -xe 2 | 3 | bundle --binstubs --quiet 4 | 5 | bin/rubocop lib 6 | bin/cucumber spec/features 7 | -------------------------------------------------------------------------------- /script/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ `which bundle` ] || gem install bundler 4 | 5 | bundle --binstubs --quiet 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | bundler_args: --binstubs 3 | rvm: 4 | - 2.1.0 5 | - 2.0.0 6 | - 1.9.3 7 | script: 8 | - script/spec 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | group :development do 6 | gem "rake", "~> 0.9.2" 7 | gem "rdoc", "~> 3.9" 8 | gem "yard", "~> 0.8.0" 9 | end 10 | -------------------------------------------------------------------------------- /lib/middleman-react.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | require 'middleman-core' 4 | 5 | ::Middleman::Extensions.register(:react) do 6 | require 'middleman-react/extension' 7 | ::Middleman::React::Extension 8 | end 9 | -------------------------------------------------------------------------------- /lib/middleman-react/version.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | module Middleman 4 | # Gem packaging constants 5 | module React 6 | PACKAGE = 'middleman-react' 7 | VERSION = '0.11.1' 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /fixtures/app/source/assets/javascripts/coffeescript.js.jsx.coffee: -------------------------------------------------------------------------------- 1 | ###* @jsx React.DOM ### 2 | 3 | @app.components.test = React.createClass 4 | render: -> 5 | `
6 | 7 |
` 8 | -------------------------------------------------------------------------------- /spec/features/support/env.rb: -------------------------------------------------------------------------------- 1 | ENV["TEST"] = "true" 2 | 3 | PROJECT_ROOT_PATH = File.join(File.dirname(__FILE__), '../../../') 4 | 5 | require "middleman-core" 6 | require "middleman-core/step_definitions" 7 | require File.join(PROJECT_ROOT_PATH, 'lib', 'middleman-react') 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | coverage 6 | InstalledFiles 7 | lib/bundler/man 8 | pkg 9 | rdoc 10 | spec/reports 11 | test/tmp 12 | test/version_tmp 13 | tmp 14 | bin 15 | fixtures/build 16 | 17 | # YARD artifacts 18 | .yardoc 19 | _yardoc 20 | doc/ 21 | -------------------------------------------------------------------------------- /lib/middleman-react/jsx/template.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | require 'tilt' 4 | 5 | module Middleman 6 | module React 7 | # Tilt Tempalte for handling JSX files 8 | class Template < Tilt::Template 9 | self.default_mime_type = 'application/javascript' 10 | 11 | def prepare; end 12 | 13 | def evaluate(scope, locals, &block) 14 | @output ||= JSX.transform(data) 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/middleman-react/extension.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | require 'middleman-core' 4 | require 'middleman-react/jsx' 5 | require 'middleman-react/jsx/template' 6 | 7 | module Middleman 8 | module React 9 | # Middleman extension entry point 10 | class Extension < Middleman::Extension 11 | def initialize(app, options_hash = {}, &block) 12 | ::Tilt.register 'jsx', Middleman::React::Template 13 | ::Sprockets.register_engine 'jsx', Middleman::React::Template 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/features/jsx.feature: -------------------------------------------------------------------------------- 1 | Feature: Transforming JSX into Javascript 2 | Background: 3 | Given a fixture app "app" 4 | Given a successfully built app at "app" 5 | 6 | Scenario: A simple JSX file 7 | When I cd to "build" 8 | Then the following files should exist: 9 | | assets/javascripts/plain_jsx.js | 10 | When I run `cat assets/javascripts/plain_jsx.js` 11 | Then the stdout from "cat assets/javascripts/plain_jsx.js" should contain exactly: 12 | """ 13 | /** @jsx React.DOM */ 14 | React.DOM.div(null); 15 | 16 | """ 17 | And the exit status should be 0 18 | -------------------------------------------------------------------------------- /lib/middleman-react/jsx.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | require 'execjs' 4 | require 'react/source' 5 | 6 | module Middleman 7 | module React 8 | # Methods for invoking the JSXTransformer via ExecJS 9 | module JSX 10 | def self.context 11 | contents = 12 | # If execjs uses therubyracer, there is no 'global'. Make sure 13 | # we have it so JSX script can work properly. 14 | 'var global = global || this;' + 15 | File.read(::React::Source.bundled_path_for('JSXTransformer.js')) 16 | @context ||= ExecJS.compile(contents) 17 | end 18 | 19 | def transform(code) 20 | context.call('JSXTransformer.transform', code)['code'] 21 | end 22 | module_function :transform 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/features/coffeescript.feature: -------------------------------------------------------------------------------- 1 | Feature: Transforming JSX into Javascript when it is written in Coffeescript 2 | Background: 3 | Given a fixture app "app" 4 | Given a successfully built app at "app" 5 | 6 | Scenario: A JSX file written in coffeescript 7 | When I cd to "build" 8 | Then the following files should exist: 9 | | assets/javascripts/coffeescript.js | 10 | When I run `cat assets/javascripts/coffeescript.js` 11 | Then the stdout from "cat assets/javascripts/coffeescript.js" should contain exactly: 12 | """ 13 | 14 | /** @jsx React.DOM */ 15 | 16 | (function() { 17 | this.app.components.test = React.createClass({displayName: 'test', 18 | render: function() { 19 | return React.DOM.div(null, 20 | TestComponent({data: this.props.someData}) 21 | ); 22 | } 23 | }); 24 | 25 | }).call(this); 26 | 27 | """ 28 | And the exit status should be 0 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Justin Morris 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /middleman-react.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require File.expand_path('../lib/middleman-react/version', __FILE__) 4 | 5 | Gem::Specification.new do |gem| 6 | gem.name = Middleman::React::PACKAGE 7 | gem.version = Middleman::React::VERSION 8 | gem.platform = Gem::Platform::RUBY 9 | gem.authors = ["Justin Morris"] 10 | gem.email = ["desk@pixelbloom.com"] 11 | gem.homepage = "https://github.com/plasticine/middleman-react" 12 | gem.summary = %q{Ruby gem for automatically transforming JSX and using React in Middleman.} 13 | gem.description = %q{Ruby gem for automatically transforming JSX and using React in Middleman.} 14 | gem.license = 'MIT' 15 | gem.files = `git ls-files`.split("\n") 16 | gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 17 | gem.require_paths = ["lib"] 18 | 19 | gem.add_dependency "middleman-core", [">= 3.0"] 20 | gem.add_dependency "execjs" 21 | gem.add_dependency "react-source", "~> 0.11.1" 22 | 23 | gem.add_development_dependency "aruba" 24 | gem.add_development_dependency "cane" 25 | gem.add_development_dependency "cucumber" 26 | gem.add_development_dependency "middleman", '~> 3.2' 27 | gem.add_development_dependency "pry" 28 | gem.add_development_dependency "rake" 29 | gem.add_development_dependency "rspec" 30 | gem.add_development_dependency "rubocop" 31 | end 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | middleman-react [![Gem Version](https://badge.fury.io/rb/middleman-react.svg)](http://badge.fury.io/rb/middleman-react) [![Build Status](https://travis-ci.org/plasticine/middleman-react.png?branch=master)](https://travis-ci.org/plasticine/middleman-react) [![Code Climate](https://codeclimate.com/github/plasticine/middleman-react.png)](https://codeclimate.com/github/plasticine/middleman-react) 2 | =============== 3 | 4 | ### Use [React] JSX transformations with [Middleman]. 5 | 6 | Inspired (and pretty much a clone of really) the [react-rails] gem for Middleman. This gem allows you to write and use `*.jsx` assets inside Middleman. 7 | 8 | #### Usage 9 | 1. `gem install middleman-react` 10 | 2. `activate :react` in `config.rb` 11 | 12 | 13 | #### Sprockets loading react-source 14 | 15 | In your Middleman `config.rb` add the following: 16 | 17 | ``` ruby 18 | after_configuration do 19 | sprockets.append_path File.dirname(::React::Source.bundled_path_for('react.js')) 20 | end 21 | ``` 22 | 23 | Now you can Sprockets include React: 24 | 25 | ``` 26 | //= require react 27 | ``` 28 | 29 | Or with addons: 30 | 31 | ``` 32 | //= require react-with-addons 33 | ``` 34 | 35 | #### Developing / Contributing 36 | 1. Fork it! 37 | 2. Get set up: `./script/bootstrap` 38 | 3. ...? 39 | 4. Run specs: `./script/spec` 40 | 5. Pull request! 41 | 42 | [React]: http://facebook.github.io/react/ 43 | [Middleman]: http://middlemanapp.com 44 | [react-rails]: https://github.com/facebook/react-rails 45 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | middleman-react (0.11.1) 5 | execjs 6 | middleman-core (>= 3.0) 7 | react-source (~> 0.11.1) 8 | 9 | GEM 10 | remote: https://rubygems.org/ 11 | specs: 12 | activesupport (3.2.16) 13 | i18n (~> 0.6, >= 0.6.4) 14 | multi_json (~> 1.0) 15 | aruba (0.5.4) 16 | childprocess (>= 0.3.6) 17 | cucumber (>= 1.1.1) 18 | rspec-expectations (>= 2.7.0) 19 | ast (1.1.0) 20 | builder (3.2.2) 21 | cane (2.6.1) 22 | parallel 23 | childprocess (0.4.0) 24 | ffi (~> 1.0, >= 1.0.11) 25 | chunky_png (1.2.9) 26 | coderay (1.1.0) 27 | coffee-script (2.2.0) 28 | coffee-script-source 29 | execjs 30 | coffee-script-source (1.7.0) 31 | compass (0.12.2) 32 | chunky_png (~> 1.2) 33 | fssm (>= 0.2.7) 34 | sass (~> 3.1) 35 | cucumber (1.3.10) 36 | builder (>= 2.1.2) 37 | diff-lcs (>= 1.1.3) 38 | gherkin (~> 2.12) 39 | multi_json (>= 1.7.5, < 2.0) 40 | multi_test (>= 0.0.2) 41 | diff-lcs (1.2.5) 42 | execjs (1.4.0) 43 | multi_json (~> 1.0) 44 | ffi (1.9.3) 45 | fssm (0.2.10) 46 | gherkin (2.12.2) 47 | multi_json (~> 1.3) 48 | haml (4.0.5) 49 | tilt 50 | hike (1.2.3) 51 | i18n (0.6.9) 52 | json (1.8.1) 53 | kramdown (1.3.1) 54 | listen (1.3.1) 55 | rb-fsevent (>= 0.9.3) 56 | rb-inotify (>= 0.9) 57 | rb-kqueue (>= 0.2) 58 | method_source (0.8.2) 59 | middleman (3.2.2) 60 | coffee-script (~> 2.2.0) 61 | compass (>= 0.12.2) 62 | execjs (~> 1.4.0) 63 | haml (>= 3.1.6) 64 | kramdown (~> 1.2) 65 | middleman-core (= 3.2.2) 66 | middleman-sprockets (>= 3.1.2) 67 | sass (>= 3.1.20) 68 | uglifier (~> 2.4.0) 69 | middleman-core (3.2.2) 70 | activesupport (~> 3.2.6) 71 | bundler (~> 1.1) 72 | i18n (~> 0.6.9) 73 | listen (~> 1.1) 74 | rack (>= 1.4.5) 75 | rack-test (~> 0.6.1) 76 | thor (>= 0.15.2, < 2.0) 77 | tilt (~> 1.4.1) 78 | middleman-sprockets (3.2.0) 79 | middleman-core (~> 3.2) 80 | sprockets (~> 2.1) 81 | sprockets-helpers (~> 1.0.0) 82 | sprockets-sass (~> 1.0.0) 83 | multi_json (1.8.4) 84 | multi_test (0.0.3) 85 | parallel (0.9.2) 86 | parser (2.1.4) 87 | ast (~> 1.1) 88 | slop (~> 3.4, >= 3.4.5) 89 | powerpack (0.0.9) 90 | pry (0.9.12.6) 91 | coderay (~> 1.0) 92 | method_source (~> 0.8) 93 | slop (~> 3.4) 94 | rack (1.5.2) 95 | rack-test (0.6.2) 96 | rack (>= 1.0) 97 | rainbow (2.0.0) 98 | rake (0.9.6) 99 | rb-fsevent (0.9.4) 100 | rb-inotify (0.9.3) 101 | ffi (>= 0.5.0) 102 | rb-kqueue (0.2.0) 103 | ffi (>= 0.5.0) 104 | rdoc (3.12.2) 105 | json (~> 1.4) 106 | react-source (0.11.1) 107 | rspec (2.14.1) 108 | rspec-core (~> 2.14.0) 109 | rspec-expectations (~> 2.14.0) 110 | rspec-mocks (~> 2.14.0) 111 | rspec-core (2.14.7) 112 | rspec-expectations (2.14.5) 113 | diff-lcs (>= 1.1.3, < 2.0) 114 | rspec-mocks (2.14.5) 115 | rubocop (0.18.1) 116 | json (>= 1.7.7, < 2) 117 | parser (~> 2.1.3) 118 | powerpack (~> 0.0.6) 119 | rainbow (>= 1.99.1, < 3.0) 120 | sass (3.2.14) 121 | slop (3.4.7) 122 | sprockets (2.10.1) 123 | hike (~> 1.2) 124 | multi_json (~> 1.0) 125 | rack (~> 1.0) 126 | tilt (~> 1.1, != 1.3.0) 127 | sprockets-helpers (1.0.1) 128 | sprockets (~> 2.0) 129 | sprockets-sass (1.0.2) 130 | sprockets (~> 2.0) 131 | tilt (~> 1.1) 132 | thor (0.18.1) 133 | tilt (1.4.1) 134 | uglifier (2.4.0) 135 | execjs (>= 0.3.0) 136 | json (>= 1.8.0) 137 | yard (0.8.7.3) 138 | 139 | PLATFORMS 140 | ruby 141 | 142 | DEPENDENCIES 143 | aruba 144 | cane 145 | cucumber 146 | middleman (~> 3.2) 147 | middleman-react! 148 | pry 149 | rake (~> 0.9.2) 150 | rdoc (~> 3.9) 151 | rspec 152 | rubocop 153 | yard (~> 0.8.0) 154 | --------------------------------------------------------------------------------