react-sinatra 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +14 -0
- data/.yardopts +4 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +21 -0
- data/README.md +147 -0
- data/Rakefile +10 -0
- data/lib/react-sinatra.rb +1 -0
- data/lib/react/sinatra.rb +32 -0
- data/lib/react/sinatra/component.rb +97 -0
- data/lib/react/sinatra/configuration.rb +39 -0
- data/lib/react/sinatra/error.rb +11 -0
- data/lib/react/sinatra/helpers.rb +18 -0
- data/lib/react/sinatra/pool.rb +80 -0
- data/lib/react/sinatra/runtime.rb +50 -0
- data/lib/react/sinatra/runtime/execjs.rb +41 -0
- data/lib/react/sinatra/runtime/runtime_based.rb +99 -0
- data/lib/react/sinatra/template.rb +45 -0
- data/lib/react/sinatra/templates/polyfill.js +10 -0
- data/lib/react/sinatra/templates/react-source/development-with-addons/react-server.js +24307 -0
- data/lib/react/sinatra/templates/react-source/development-with-addons/react.js +24156 -0
- data/lib/react/sinatra/templates/react-source/development/react-server.js +20587 -0
- data/lib/react/sinatra/templates/react-source/development/react.js +21462 -0
- data/lib/react/sinatra/templates/react-source/production-with-addons/react-server.js +19 -0
- data/lib/react/sinatra/templates/react-source/production-with-addons/react.js +19 -0
- data/lib/react/sinatra/templates/react-source/production/react-server.js +19 -0
- data/lib/react/sinatra/templates/react-source/production/react.js +19 -0
- data/lib/react/sinatra/templates/runtime.js +4 -0
- data/lib/react/sinatra/templates/variables.js +5 -0
- data/lib/react/sinatra/version.rb +5 -0
- data/react-sinatra.gemspec +27 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5ff3f7ac7e65e474e927285731ff48c025090e88
|
4
|
+
data.tar.gz: f9539bf7704022157a4b16210bb61add72e281a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f361c16cef519f84addbdff5d049de26b08a6f55407971c9ec615e18b506d9a94a458bfb2816ca11fa30e06f26ef29be6b932f364810f59863b660a3eb715fe7
|
7
|
+
data.tar.gz: be72c4dfef7dabce8f939038c4a357d1a8e4cee7d037bd3cabe2289464a764e1eedd78c4ffc17383a62d5d3adab0c074ee0a8d6cad88ea974e82fa830efc7dcf
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 namusyaka
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all 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,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# react-sinatra
|
2
|
+
|
3
|
+
[](https://travis-ci.org/namusyaka/react-sinatra)
|
4
|
+
|
5
|
+
`react-sinatra` makes it easy to use React in your Sinatra and Padrino application.
|
6
|
+
|
7
|
+
Please see [a sample](https://github.com/namusyaka/react-sinatra-sample).
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'react-sinatra'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install react-sinatra
|
24
|
+
|
25
|
+
## Anti-Features
|
26
|
+
|
27
|
+
`react-sinatra` does not:
|
28
|
+
|
29
|
+
- transform `.jsx` files or JSX syntax.
|
30
|
+
- transpile asset using babel.
|
31
|
+
- support asset-pipeline.
|
32
|
+
- have generator for registering this extension.
|
33
|
+
|
34
|
+
I think those features should be solved by using [webpack](https://webpack.github.io/), or other build tools.
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
### Sinatra Plug-in
|
39
|
+
|
40
|
+
It's easy to register `react-sinatra` in your application, next section will describe three steps for introduction.
|
41
|
+
|
42
|
+
#### 1. Add react-sinatra and runtime into your Gemfile
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
source 'https://rubygems.org'
|
46
|
+
|
47
|
+
gem 'react-sinatra'
|
48
|
+
gem 'execjs'
|
49
|
+
gem 'mini_racer' # also `therubyracer` may be available, but mini_racer is simpler and faster.
|
50
|
+
```
|
51
|
+
|
52
|
+
#### 2. Register react-sinatra and configure.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class App < Sinatra::Base
|
56
|
+
register React::Sinatra
|
57
|
+
|
58
|
+
configure do
|
59
|
+
React::Sinatra.configure do |config|
|
60
|
+
# configures for bundled React.js
|
61
|
+
config.use_bundled_react = true
|
62
|
+
config.env = ENV['RACK_ENV'] || :development
|
63
|
+
config.addon = true
|
64
|
+
|
65
|
+
# The asset should be able to be compiled by your server side runtime.
|
66
|
+
# react-sinatra does not transform jsx into js, also ES2015 may not be worked through.
|
67
|
+
config.asset_path = File.join('client', 'dist', 'server.js')
|
68
|
+
config.runtime = :execjs
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
#### 3. Use `react_component` on your view or sinatra application.
|
75
|
+
|
76
|
+
```erb
|
77
|
+
<%= react_component('Hello', { name: 'namusyaka' }, prerender: true) %>
|
78
|
+
```
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
get '/:name' do |name|
|
82
|
+
component = react_component('Hello', { name: name }, prerender: true)
|
83
|
+
# ...
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
The react component **must** be able to be referred from global scope, so you should be careful for your asset javascript.
|
88
|
+
In the above example, you need to provide an asset that puts the component called `Hello` in a state that it can be referred to from the global.
|
89
|
+
|
90
|
+
```javascript
|
91
|
+
class Hello extends React.Component {
|
92
|
+
render() {
|
93
|
+
return (
|
94
|
+
<div className="hello">
|
95
|
+
Hello, {this.props.name}!
|
96
|
+
</div>
|
97
|
+
);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
global.Hello = Hello;
|
102
|
+
```
|
103
|
+
|
104
|
+
### React.js
|
105
|
+
|
106
|
+
#### Bundled React.js
|
107
|
+
|
108
|
+
You can use bundled React.js by specifying configurations.
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
React::Sinatra.configure do |config|
|
112
|
+
config.use_bundled_react = true # Defaults to false
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
You can also specify `addon` and `env` for each environments.
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
React::Sinatra.configure do |config|
|
120
|
+
config.addon = false # Defaults to false
|
121
|
+
config.env = ENV['RACK_ENV'] || :development
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
#### Note
|
126
|
+
|
127
|
+
**If you want to use your own react, you must include React.js and react-server source code in the asset.**
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
React::Sinatra.configure do |config|
|
131
|
+
config.asset_path = 'client/dist/*.js'
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
### TODO
|
136
|
+
|
137
|
+
- Support nodejs as a runtime
|
138
|
+
|
139
|
+
## Contributing
|
140
|
+
|
141
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/namusyaka/react-sinatra.
|
142
|
+
|
143
|
+
|
144
|
+
## License
|
145
|
+
|
146
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
147
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'react/sinatra'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module React
|
2
|
+
# Namespace for the react-sinatra library.
|
3
|
+
#
|
4
|
+
# This module is a Sinatra extension and is used with the `register` keyword.
|
5
|
+
module Sinatra
|
6
|
+
# Method for the `register` keyword hook on your application.
|
7
|
+
# @param [Sinatra::Base] app
|
8
|
+
def self.registered(app)
|
9
|
+
app.helpers Helpers
|
10
|
+
end
|
11
|
+
|
12
|
+
# Configures react-sinatra by using {React::Sinatra::Configuration}.
|
13
|
+
# @see [React::Sinatra::Configuration]
|
14
|
+
# @yieldparam [React::Sinatra::Configuration]
|
15
|
+
def self.configure
|
16
|
+
yield config
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns configuration instance using Singleton module.
|
20
|
+
# @see [React::Sinatra::Configuration]
|
21
|
+
# @return [React::Sinatra::Configuration]
|
22
|
+
def self.config
|
23
|
+
Configuration.instance
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'react/sinatra/version'
|
29
|
+
require 'react/sinatra/configuration'
|
30
|
+
require 'react/sinatra/helpers'
|
31
|
+
require 'react/sinatra/template'
|
32
|
+
require 'react/sinatra/runtime'
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'padrino-helpers'
|
3
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
4
|
+
require 'active_support/core_ext/string/inflections'
|
5
|
+
require 'react/sinatra/pool'
|
6
|
+
|
7
|
+
module React
|
8
|
+
module Sinatra
|
9
|
+
# Class for expressing react component.
|
10
|
+
#
|
11
|
+
# This is main entrypoint for rendering react component
|
12
|
+
# and is referred from {React::Sinatra::Helpers#react_component}.
|
13
|
+
class Component
|
14
|
+
include Padrino::Helpers::OutputHelpers
|
15
|
+
include Padrino::Helpers::TagHelpers
|
16
|
+
|
17
|
+
attr_reader :component, :props, :prerender
|
18
|
+
|
19
|
+
# Renders react component from given arguments.
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# React::Sinatra::Component.render('Hello', { name: 'namusyaka' }, prerender: true)
|
23
|
+
#
|
24
|
+
# @param [String] component The name for component must be able to be referred from asset javascript.
|
25
|
+
# @param [Hash] props The props for rendering react-dom
|
26
|
+
# @param [TrueClass, FalseClass] prerender Whether server side rendering is enabled or not.
|
27
|
+
# @param [TrueClass, FalseClass] camelize_props Whether camelization is enabled or not.
|
28
|
+
# @param [String, Symbol] tag The tag name for rendering react root element. Defaults to :div
|
29
|
+
#
|
30
|
+
# @raise [React::Sinatra::RuntimeError] Raised if server side rendering is enabled and failed
|
31
|
+
# @return [ActiveSupport::SafeBuffer] safe string for rendering in application views
|
32
|
+
def self.render(component, props, prerender: false, **options)
|
33
|
+
new(component, prerender: prerender).render(props, **options)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Camelizes props for enabling {camelize_props} option.
|
37
|
+
#
|
38
|
+
# @param [Hash] props The props for rendering react-dom
|
39
|
+
# @return [Hash] camelized props
|
40
|
+
def self.camelize_props(props)
|
41
|
+
case props
|
42
|
+
when Hash
|
43
|
+
props.each_with_object({}) do |(key, value), new_props|
|
44
|
+
new_key = key.to_s.camelize(:lower)
|
45
|
+
new_value = camelize_props(value)
|
46
|
+
new_props[new_key] = new_value
|
47
|
+
end
|
48
|
+
when Array
|
49
|
+
props.map(&method(:camelize_props))
|
50
|
+
else
|
51
|
+
props
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Constructs an instance of React::Sinatra::Component.
|
56
|
+
#
|
57
|
+
# @param [String] component The name for component must be able to be referred from asset javascript
|
58
|
+
# @param [TrueClass, FalseClass] prerender Whether server side rendering is enabled or not.
|
59
|
+
# @return [React::Sinatra::Component]
|
60
|
+
def initialize(component, prerender: false, **options)
|
61
|
+
@component = component
|
62
|
+
@prerender = prerender
|
63
|
+
end
|
64
|
+
|
65
|
+
# Renders react component from given arguments and component.
|
66
|
+
#
|
67
|
+
# @param [Hash] props The props for rendering react-dom
|
68
|
+
# @param [TrueClass, FalseClass] camelize_props Whether camelization is enabled or not
|
69
|
+
# @param [String, Symbol] tag The tag name for rendering react root element. Defaults to :div
|
70
|
+
# @see https://github.com/padrino/padrino-framework/blob/master/padrino-helpers/lib/padrino-helpers/tag_helpers.rb#L119
|
71
|
+
# @return [ActiveSupport::SafeBuffer] safe string for rendering in application views
|
72
|
+
def render(props, camelize_props: false, tag: :div, **options, &block)
|
73
|
+
props = self.class.camelize_props(props) if camelize_props
|
74
|
+
block = -> {
|
75
|
+
concat React::Sinatra::Pool.render(component, props.to_json)
|
76
|
+
} if prerender?
|
77
|
+
|
78
|
+
options.reverse_merge!(data: {})
|
79
|
+
options[:data].tap do |data|
|
80
|
+
data[:react_class] = component
|
81
|
+
data[:react_props] = props.is_a?(String) ? props : props.to_json
|
82
|
+
end unless prerender == :static
|
83
|
+
|
84
|
+
content_tag(tag, '', options, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns true if the :prerender option is enabled.
|
88
|
+
#
|
89
|
+
# @return [TrueClass, FalseClass]
|
90
|
+
def prerender?
|
91
|
+
!! prerender
|
92
|
+
end
|
93
|
+
|
94
|
+
private :prerender?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'react/sinatra/runtime'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
module React
|
5
|
+
module Sinatra
|
6
|
+
# Class for expressing configuration delegated from classes.
|
7
|
+
#
|
8
|
+
# This #instance entrypoint is referred from application.
|
9
|
+
class Configuration
|
10
|
+
include Singleton
|
11
|
+
|
12
|
+
attr_accessor :pool_size, :pool_timeout, :asset_path, :use_bundled_react, :env, :addon
|
13
|
+
|
14
|
+
# Assigns runtime by given name.
|
15
|
+
#
|
16
|
+
# @param [String, Symbol] name The name of runtime
|
17
|
+
# @see React::Sinatra::Runtime.[]
|
18
|
+
# @return [React::Sinatra::Runtime::RuntimeBased]
|
19
|
+
def runtime=(name)
|
20
|
+
@runtime = Runtime[name.to_sym]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns current runtime.
|
24
|
+
# @return [React::Sinatra::Runtime::RuntimeBased]
|
25
|
+
def runtime
|
26
|
+
@runtime
|
27
|
+
end
|
28
|
+
|
29
|
+
# Assigns default values for use in server-side rendering.
|
30
|
+
instance.pool_size = 5
|
31
|
+
instance.pool_timeout = 10
|
32
|
+
instance.runtime = :execjs
|
33
|
+
|
34
|
+
instance.use_bundled_react = false
|
35
|
+
instance.env = ENV['RACK_ENV'] || :development
|
36
|
+
instance.addon = false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module React
|
2
|
+
module Sinatra
|
3
|
+
class RuntimeError < ::RuntimeError
|
4
|
+
def initialize(component, props, message:, **options)
|
5
|
+
message = ["Encountered error \"#{message}\" when prerendering #{component} with #{props}",
|
6
|
+
message.backtrace.join(?\n)].join(?\n)
|
7
|
+
super(message)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'react/sinatra/component'
|
2
|
+
|
3
|
+
module React
|
4
|
+
module Sinatra
|
5
|
+
# Module for registering Sinatra application.
|
6
|
+
#
|
7
|
+
# This is main entrypoint for integration on Sinatra.
|
8
|
+
module Helpers
|
9
|
+
# Renders react component from given arguments.
|
10
|
+
#
|
11
|
+
# @see {React::Sinatra::Component.render}
|
12
|
+
# @return [ActiveSupport::SafeBuffer] safe string for rendering in application views
|
13
|
+
def react_component(*args)
|
14
|
+
React::Sinatra::Component.render(*args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module React
|
4
|
+
module Sinatra
|
5
|
+
# Class for expressing connection pool.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# pool = React::Sinatra::Pool.new
|
9
|
+
# pool.render('Hello', { name: 'bob' }, prerender: true)
|
10
|
+
# pool.reset
|
11
|
+
#
|
12
|
+
# @!visibility private
|
13
|
+
class Pool
|
14
|
+
# Utility for runtime renderer
|
15
|
+
#
|
16
|
+
# @see {#render}
|
17
|
+
# @!visibility private
|
18
|
+
def self.render(*args, **options)
|
19
|
+
pool.render(*args, **options)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns an instance of React::Sinatra::Pool as a singleton.
|
23
|
+
#
|
24
|
+
# @return [React::Sinatra::Pool]
|
25
|
+
# @!visibility private
|
26
|
+
def self.pool
|
27
|
+
@pool ||= Pool.new
|
28
|
+
end
|
29
|
+
|
30
|
+
extend Forwardable
|
31
|
+
instance_delegate %i[pool_size pool_timeout runtime] => 'React::Sinatra.config'
|
32
|
+
|
33
|
+
# Detects runtime from pool, and its runtime
|
34
|
+
# renders react component by using server side runtime.
|
35
|
+
#
|
36
|
+
# @see React::Sinatra::Runtime::RuntimeBased#render
|
37
|
+
# @!visibility private
|
38
|
+
def render(*args, **options)
|
39
|
+
pool.with { |runtime| runtime.render(*args, **options) }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Resets current connection pool.
|
43
|
+
#
|
44
|
+
# @!visibility private
|
45
|
+
def reset
|
46
|
+
@pool = nil
|
47
|
+
pool
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns an instance of ConnectionPool.
|
51
|
+
#
|
52
|
+
# @see https://github.com/mperham/connection_pool
|
53
|
+
# @return [Connectionpool]
|
54
|
+
# @!visibility private
|
55
|
+
def pool
|
56
|
+
@pool ||= ConnectionPool.new(size: size, timeout: timeout) { runtime.new }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the globally set pool size or default pool size.
|
60
|
+
#
|
61
|
+
# @see React::Sinatra::Configuration#pool_size
|
62
|
+
# @return [Integer]
|
63
|
+
# @!visibility private
|
64
|
+
def size
|
65
|
+
pool_size || 5
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns the globally set pool timeout or default pool timeout.
|
69
|
+
#
|
70
|
+
# @see React::Sinatra::Configuration#pool_timeout
|
71
|
+
# @return [Integer]
|
72
|
+
# @!visibility private
|
73
|
+
def timeout
|
74
|
+
pool_timeout || 10
|
75
|
+
end
|
76
|
+
|
77
|
+
private :pool, :size, :timeout
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|