roda-sprockets 1.1.0.rc1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +32 -0
- data/.gitignore +2 -1
- data/.rspec +1 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +13 -0
- data/README.md +66 -13
- data/Rakefile +4 -0
- data/examples/opal-doc/app.rb +2 -3
- data/examples/opal-exception/Gemfile +8 -0
- data/examples/opal-exception/README.md +1 -0
- data/examples/opal-exception/Rakefile +6 -0
- data/examples/opal-exception/app/application.rb +16 -0
- data/examples/opal-exception/app.rb +26 -0
- data/examples/opal-exception/config.ru +3 -0
- data/examples/sass/Gemfile +6 -0
- data/examples/sass/Rakefile +6 -0
- data/examples/sass/app.rb +23 -0
- data/examples/sass/assets/css/application.scss +3 -0
- data/examples/sass/config.ru +3 -0
- data/lib/roda/plugins/sprockets.rb +17 -5
- data/lib/roda/plugins/sprockets_task.rb +9 -5
- data/roda-sprockets.gemspec +1 -1
- data/spec/assets/css/scss_css.scss +7 -0
- data/spec/assets/css/scss_css_with_erb.scss.erb +13 -0
- data/spec/assets/css/scss_css_with_imports.scss +1 -0
- data/spec/assets/css/simple_css.css +1 -0
- data/spec/assets/js/opal_js.rb +4 -0
- data/spec/assets/js/opal_js_with_erb.rb.erb +10 -0
- data/spec/assets/js/opal_js_with_requires.rb +1 -0
- data/spec/assets/js/simple_js.js +1 -0
- data/spec/examples_spec.rb +141 -0
- data/spec/plugin_spec.rb +237 -0
- data/spec/server_helper.rb +68 -0
- data/spec/spec_helper.rb +59 -0
- metadata +42 -6
- data/examples/opal-doc/Gemfile.lock +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd58a6b5449b9ba795b8a6d89873786092742e2fc5e747801c7050725a838dfd
|
4
|
+
data.tar.gz: 2fd13d4132906fb1d2bb84b614b3abcb8a25075d16764adcb1368b4fd224c199
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68c501fc657c52cffe278758acd7fb855ffd83a90eb5a3eb1defdf39c111be43857e75be41a18123cb68a42c22058ee4d94f52fd3bd5d6689f75695251b83d18
|
7
|
+
data.tar.gz: 8835e128d39fd716d6de20e9404ff1a0ef01a5b256bc159aa090cd4e1bea8d34f8d77442ea1867fb6c8976de383f2a986e886c7700aeaaa3610bfff02a6e2336
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: rake
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
- "*-stable"
|
8
|
+
- "*/ci-check"
|
9
|
+
pull_request: {}
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
rspec:
|
13
|
+
strategy:
|
14
|
+
fail-fast: false
|
15
|
+
matrix:
|
16
|
+
ruby-version: ['2.6', '2.7', '3.0']
|
17
|
+
os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
|
18
|
+
|
19
|
+
runs-on: ${{ matrix.os }}
|
20
|
+
|
21
|
+
env:
|
22
|
+
CI: 'true'
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- name: Set up Ruby
|
27
|
+
uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
30
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
31
|
+
- name: Run tests
|
32
|
+
run: bundle exec rake
|
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
v2.0.0
|
2
|
+
|
3
|
+
- :debug argument now defaults to true, if RACK_ENV is development or test,
|
4
|
+
false otherwise - also false in rake tasks (#10)
|
5
|
+
- add sprockets_env class method, so you can shorten code like
|
6
|
+
`App.sprockets_options[:sprockets]` to just `App.sprockets_env` (#11)
|
7
|
+
|
1
8
|
v1.1.0
|
2
9
|
|
3
10
|
- Fix the Rack::Lint issue (#1)
|
data/Gemfile
CHANGED
@@ -2,3 +2,16 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in roda-sprocket_assets.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
# For rspec:
|
7
|
+
gem "rspec"
|
8
|
+
gem "opal"
|
9
|
+
gem "opal-sprockets"
|
10
|
+
gem "sassc"
|
11
|
+
gem "uglifier"
|
12
|
+
# Until janbiedermann's Windows paths patch is released, we are using git ref:
|
13
|
+
# https://github.com/rubycdp/ferrum/commit/5beca76588d1544026eb8b8ee841f305803c67e5
|
14
|
+
# Also, my patch that captures stacktraces should be merged:
|
15
|
+
# https://github.com/hmdne/ferrum/commit/fbc74b7ca7b670d29cc53a2d779470a05c60ef9d
|
16
|
+
gem "ferrum", github: "hmdne/ferrum", ref: "capture-stacktrace"
|
17
|
+
gem "puma"
|
data/README.md
CHANGED
@@ -22,36 +22,44 @@ And then execute:
|
|
22
22
|
```ruby
|
23
23
|
class App < Roda
|
24
24
|
plugin :sprockets, precompile: %w(site.js site.css),
|
25
|
-
public_path: 'public/assets/',
|
26
25
|
opal: true,
|
27
|
-
debug: true
|
28
26
|
plugin :public
|
29
27
|
|
30
28
|
route do |r|
|
31
29
|
r.public
|
32
|
-
r.sprockets
|
33
|
-
end
|
30
|
+
r.sprockets if %w[development test].include? ENV['RACK_ENV']
|
31
|
+
end
|
34
32
|
end
|
35
33
|
```
|
36
34
|
|
37
35
|
### Parameters for the plugin:
|
38
36
|
|
39
37
|
* `precompile` - an array of files that you want to precompile
|
40
|
-
* `prefix` (relative to the `root`, which is `app.opts[:root]` by default
|
41
|
-
|
42
|
-
|
43
|
-
*
|
38
|
+
* `prefix` (relative to the `root`, which is `app.opts[:root]` by default) -
|
39
|
+
an array of directories where your assets are located, by default:
|
40
|
+
`%w(assets vendor/assets)`.
|
41
|
+
* Here, an element of the array can be an absolute path instead of relative.
|
42
|
+
* If an element ends with `/`, it will use assets directly in a given
|
43
|
+
subdirectory.
|
44
|
+
* If it doesn't end with `/` (which is by default) if will be equivalent to
|
45
|
+
`value/*`, which means, that assets will be loaded for instance from
|
46
|
+
`assets/javascripts` and `assets/stylesheets`, but not directly from `assets`.
|
47
|
+
* An element can contain glob characters.
|
48
|
+
* `root` - a filesystem root directory of your app. By default, same as
|
49
|
+
`app.opts[:root]`, that is: `Dir.pwd`.
|
44
50
|
* `public_path` - filesystem path to a place, where precompiled assets will be
|
45
51
|
stored, by default: `public/assets` (it should be a directory from which `:public`
|
46
52
|
plugin takes files + `path_prefix`)
|
47
53
|
* `path_prefix` - a Roda prefix of your assets directory. By default: `/assets`
|
48
54
|
* `protocol` - either :http (default) or :https.
|
49
|
-
* `css_compressor`, `js_compressor` - pick a compressor of your choice
|
55
|
+
* `css_compressor`, `js_compressor` - pick a compressor of your choice (respected
|
56
|
+
only if `debug` is false)
|
50
57
|
* `host` - for hosting your assets on a different server
|
51
58
|
* `digest` (bool) - digest your assets for unique filenames, default: true
|
52
59
|
* `opal` (bool) - Opal support, default: false
|
53
|
-
* `debug` (bool) - debug mode, default:
|
54
|
-
|
60
|
+
* `debug` (bool) - debug mode, default: true if RACK_ENV is development or test,
|
61
|
+
false otherwise (in rake tasks it's false too)
|
62
|
+
* `cache` - a `Sprockets::Cache` instance, default: nil (no cache)
|
55
63
|
|
56
64
|
### Templates:
|
57
65
|
|
@@ -89,15 +97,39 @@ $document.body << DOM {
|
|
89
97
|
```
|
90
98
|
|
91
99
|
You will need to tell Opal to load this file. Add this in your template
|
92
|
-
after everything has been loaded
|
100
|
+
after everything has been loaded (after your `javascript_tag` call, it is
|
101
|
+
needed too!):
|
93
102
|
|
94
|
-
```
|
103
|
+
```erb
|
95
104
|
<%= opal_require 'site' %>
|
96
105
|
```
|
97
106
|
|
98
107
|
Note that it won't be needed for plain Javascript use, only Opal needs that
|
99
108
|
line.
|
100
109
|
|
110
|
+
### Caching:
|
111
|
+
|
112
|
+
To speed up page loads during development, you can enable cache. Be warned,
|
113
|
+
there are some caveats with how Sprockets cache works. This will improve your
|
114
|
+
experience, but be prepared for some rough edges.
|
115
|
+
|
116
|
+
To enable memory cache, add an argument to your plugin config:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
cache: Sprockets::Cache::MemoryStore.new(65536)
|
120
|
+
```
|
121
|
+
|
122
|
+
To enable filesystem cache, for it to persist across application restarts,
|
123
|
+
add an argument to your plugin config:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
cache: Sprockets::Cache::FileStore.new("var/cache/")
|
127
|
+
```
|
128
|
+
|
129
|
+
Remember: with filesystem cache problems may happen if you, for instance,
|
130
|
+
update your Gems. You will then have to remove the cache for it to get
|
131
|
+
repopulated.
|
132
|
+
|
101
133
|
### Rake precompilation tasks:
|
102
134
|
|
103
135
|
In your Rakefile:
|
@@ -111,6 +143,27 @@ Roda::RodaPlugins::Sprockets::Task.define!(App)
|
|
111
143
|
|
112
144
|
And launch: `rake assets:precompile` or `rake assets:clean`
|
113
145
|
|
146
|
+
### Sprockets extended configuration:
|
147
|
+
|
148
|
+
You can configure your environment directly by accessing a method `sprockets_env`
|
149
|
+
(which is a `Sprockets::Environment`) on your `App` class.
|
150
|
+
|
151
|
+
For instance, to enable Brotli with [sprockets-exporters_pack](https://github.com/hansottowirtz/sprockets-exporters_pack)
|
152
|
+
you will need to either add this code inside your `App` class:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
sprockets_env.register_exporter %w(text/css application/javascript image/svg+xml), Sprockets::ExportersPack::BrotliExporter
|
156
|
+
```
|
157
|
+
|
158
|
+
Or at some other point:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
App.sprockets_env.register_exporter %w(text/css application/javascript image/svg+xml), Sprockets::ExportersPack::BrotliExporter
|
162
|
+
```
|
163
|
+
|
164
|
+
Do note, that some extensions, like for example [opal-optimizer](https://github.com/hmdne/opal-optimizer)
|
165
|
+
won't need any configuration at all beside `require "opal/optimizer/sprockets"`.
|
166
|
+
|
114
167
|
## Contributing
|
115
168
|
|
116
169
|
1. Fork it ( https://github.com/hmdne/roda-sprockets/fork )
|
data/Rakefile
CHANGED
data/examples/opal-doc/app.rb
CHANGED
@@ -3,13 +3,12 @@ require 'roda'
|
|
3
3
|
class App < Roda
|
4
4
|
plugin :sprockets, precompile: %w(application.js),
|
5
5
|
prefix: %w(app/),
|
6
|
-
opal: true
|
7
|
-
debug: ENV['RACK_ENV'] != 'production'
|
6
|
+
opal: true
|
8
7
|
plugin :public
|
9
8
|
|
10
9
|
route do |r|
|
11
10
|
r.public
|
12
|
-
r.sprockets
|
11
|
+
r.sprockets if %w[development test].include? ENV['RACK_ENV']
|
13
12
|
|
14
13
|
r.root do
|
15
14
|
<<~END
|
@@ -0,0 +1 @@
|
|
1
|
+
This example drops an exception. It's for a test of source maps.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'roda'
|
2
|
+
|
3
|
+
class App < Roda
|
4
|
+
plugin :sprockets, precompile: %w(application.js),
|
5
|
+
prefix: %w(app/),
|
6
|
+
js_compressor: :uglify,
|
7
|
+
opal: true
|
8
|
+
plugin :public
|
9
|
+
|
10
|
+
route do |r|
|
11
|
+
r.public
|
12
|
+
r.sprockets if %w[development test].include? ENV['RACK_ENV']
|
13
|
+
|
14
|
+
r.root do
|
15
|
+
<<~END
|
16
|
+
<!doctype html>
|
17
|
+
<html>
|
18
|
+
<head>
|
19
|
+
#{ javascript_tag 'application' }
|
20
|
+
#{ opal_require 'application' }
|
21
|
+
</head>
|
22
|
+
</html>
|
23
|
+
END
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'roda'
|
2
|
+
|
3
|
+
class App < Roda
|
4
|
+
plugin :sprockets, precompile: %w(application.css)
|
5
|
+
plugin :public
|
6
|
+
|
7
|
+
route do |r|
|
8
|
+
r.public
|
9
|
+
r.sprockets if %w[development test].include? ENV['RACK_ENV']
|
10
|
+
|
11
|
+
r.root do
|
12
|
+
<<~END
|
13
|
+
<!doctype html>
|
14
|
+
<html>
|
15
|
+
<head>
|
16
|
+
#{ stylesheet_tag 'application' }
|
17
|
+
</head>
|
18
|
+
</html>
|
19
|
+
END
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -18,7 +18,7 @@ class Roda
|
|
18
18
|
host: nil,
|
19
19
|
digest: true,
|
20
20
|
opal: false,
|
21
|
-
debug:
|
21
|
+
debug: nil,
|
22
22
|
cache: nil,
|
23
23
|
}.freeze
|
24
24
|
|
@@ -28,13 +28,21 @@ class Roda
|
|
28
28
|
else
|
29
29
|
app.opts[:sprockets] = plugin_options.dup
|
30
30
|
end
|
31
|
-
options = app.opts[:sprockets]
|
31
|
+
options = app.opts[:sprockets]
|
32
32
|
DEFAULTS.each { |k, v| options[k] = v unless options.key?(k) }
|
33
33
|
|
34
34
|
if !options[:root]
|
35
35
|
options[:root] = app.opts[:root] || Dir.pwd
|
36
36
|
end
|
37
37
|
|
38
|
+
if options[:debug].nil?
|
39
|
+
if %w[development test].include? ENV['RACK_ENV']
|
40
|
+
options[:debug] = true
|
41
|
+
else
|
42
|
+
options[:debug] = false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
38
46
|
# opal-sprockets registers engines when required, but if we create Sprockets::Environment before
|
39
47
|
# requiring that, they don't get registered
|
40
48
|
require 'opal/sprockets' if options[:opal]
|
@@ -76,12 +84,12 @@ class Roda
|
|
76
84
|
|
77
85
|
options[:sprockets_helpers].environment = options[:sprockets]
|
78
86
|
options[:sprockets_helpers].digest = options[:digest]
|
79
|
-
options[:sprockets_helpers].prefix = options[:path_prefix]
|
87
|
+
options[:sprockets_helpers].prefix = options[:path_prefix]
|
80
88
|
options[:sprockets_helpers].debug = options[:debug]
|
81
89
|
|
82
90
|
unless options[:debug]
|
83
91
|
options[:sprockets].css_compressor = options[:css_compressor] unless options[:css_compressor].nil?
|
84
|
-
options[:sprockets].js_compressor = options[:js_compressor] unless options[:js_compressor].nil?
|
92
|
+
options[:sprockets].js_compressor = options[:js_compressor] unless options[:js_compressor].nil?
|
85
93
|
|
86
94
|
options[:sprockets_helpers].manifest = ::Sprockets::Manifest.new(options[:sprockets], options[:public_path])
|
87
95
|
options[:sprockets_helpers].protocol = options[:protocol]
|
@@ -94,6 +102,10 @@ class Roda
|
|
94
102
|
opts[:sprockets]
|
95
103
|
end
|
96
104
|
|
105
|
+
def sprockets_env
|
106
|
+
sprockets_options[:sprockets]
|
107
|
+
end
|
108
|
+
|
97
109
|
def sprockets_regexp
|
98
110
|
%r{#{sprockets_options[:sprockets_helpers].prefix[1..-1]}/(.*)}
|
99
111
|
end
|
@@ -142,7 +154,7 @@ class Roda
|
|
142
154
|
# (See: https://github.com/hmdne/roda-sprockets/issues/1)
|
143
155
|
nil
|
144
156
|
when Array
|
145
|
-
response.join
|
157
|
+
response.join
|
146
158
|
else
|
147
159
|
response.to_s
|
148
160
|
end
|
@@ -7,6 +7,14 @@ class Roda
|
|
7
7
|
module Sprockets
|
8
8
|
class Task < Rake::SprocketsTask
|
9
9
|
def initialize(app_klass)
|
10
|
+
if app_klass.class != Class
|
11
|
+
raise "#{app_klass} is not a Class"
|
12
|
+
elsif !app_klass.ancestors.map(&:name).include? "Roda"
|
13
|
+
raise "#{app_klass} doesn't inherit Roda"
|
14
|
+
elsif !app_klass.respond_to? :sprockets_options
|
15
|
+
raise "#{app_klass} doesn't load 'plugin :sprockets` - we can build nothing from it"
|
16
|
+
end
|
17
|
+
|
10
18
|
@app_klass = app_klass
|
11
19
|
super() { update_values }
|
12
20
|
end
|
@@ -18,11 +26,7 @@ class Roda
|
|
18
26
|
end
|
19
27
|
|
20
28
|
def sprockets_options
|
21
|
-
@
|
22
|
-
opts = @app_klass.sprockets_options.dup
|
23
|
-
opts[:debug] = false
|
24
|
-
opts
|
25
|
-
end
|
29
|
+
@app_klass.sprockets_options
|
26
30
|
end
|
27
31
|
|
28
32
|
def define
|
data/roda-sprockets.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "roda-sprockets"
|
7
|
-
spec.version = '
|
7
|
+
spec.version = '2.0.0'
|
8
8
|
spec.authors = ["cj", "hmdne"]
|
9
9
|
spec.email = ["cjlazell@gmail.com"]
|
10
10
|
spec.summary = %q{Use sprockets to serve assets in roda.}
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "scss_css";
|
@@ -0,0 +1 @@
|
|
1
|
+
body { content: "Simple CSS"; }
|
@@ -0,0 +1 @@
|
|
1
|
+
require "opal_js"
|
@@ -0,0 +1 @@
|
|
1
|
+
alert("Simple JS");
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require "ferrum"
|
2
|
+
|
3
|
+
def sigterm(pid)
|
4
|
+
if Gem.win_platform?
|
5
|
+
system("taskkill /F /pid #{pid}")
|
6
|
+
else
|
7
|
+
Process.kill("TERM", pid)
|
8
|
+
Process.wait(pid)
|
9
|
+
end
|
10
|
+
rescue Errno::ECHILD
|
11
|
+
# Ignore
|
12
|
+
end
|
13
|
+
|
14
|
+
def free_port
|
15
|
+
$free_port ||= 19900
|
16
|
+
$free_port += 1
|
17
|
+
$free_port
|
18
|
+
end
|
19
|
+
|
20
|
+
browser_options = {
|
21
|
+
timeout: 15,
|
22
|
+
process_timeout: 20,
|
23
|
+
js_errors: true,
|
24
|
+
browser_options: {
|
25
|
+
'no-sandbox': nil,
|
26
|
+
'auto-open-devtools-for-tabs': nil
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
RSpec.describe "Example" do
|
31
|
+
Dir[__dir__+"/../examples/*"].each do |example|
|
32
|
+
example_name = File.basename(example)
|
33
|
+
|
34
|
+
example_specific = proc do |browser, debug, error|
|
35
|
+
case example_name
|
36
|
+
when "opal-doc"
|
37
|
+
browser.evaluate("typeof(Opal.Kernel.$puts)").should be == "function"
|
38
|
+
when "opal-exception"
|
39
|
+
error.should_not be_nil
|
40
|
+
functions = error.stack_trace["callFrames"].map { |i| i["functionName"] }
|
41
|
+
if debug
|
42
|
+
functions.should include "$$a"
|
43
|
+
functions.should include "$$b"
|
44
|
+
functions.should include "$$c"
|
45
|
+
else
|
46
|
+
# We minify this example, so functions should be mangled
|
47
|
+
functions.should_not include "$$a"
|
48
|
+
functions.should_not include "$$b"
|
49
|
+
functions.should_not include "$$c"
|
50
|
+
end
|
51
|
+
# Nevertheless, "Opal.modules.application" should stay unmangled.
|
52
|
+
functions.should include "Opal.modules.application"
|
53
|
+
# How can we now test that source maps work? The browser doesn't help us...
|
54
|
+
when "sass"
|
55
|
+
browser.evaluate("window.getComputedStyle(document.body).backgroundColor").should be == "rgb(0, 128, 0)"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context example_name do
|
60
|
+
it "works in development mode" do
|
61
|
+
Dir.chdir example do
|
62
|
+
Bundler.with_unbundled_env do
|
63
|
+
if ENV.key? 'CI'
|
64
|
+
# Ensure we will reuse the cached gems
|
65
|
+
system("bundle config --local path #{__dir__+"/../vendor/bundle"}")
|
66
|
+
end
|
67
|
+
|
68
|
+
system("bundle install").should be true
|
69
|
+
|
70
|
+
begin
|
71
|
+
port = free_port
|
72
|
+
pid = spawn("bundle exec rackup -p#{port}")
|
73
|
+
sleep 1
|
74
|
+
|
75
|
+
begin
|
76
|
+
browser = Ferrum::Browser.new(**browser_options)
|
77
|
+
browser.go_to("http://localhost:#{port}/")
|
78
|
+
browser.network.wait_for_idle
|
79
|
+
|
80
|
+
# Sometimes we need to wait a little bit longer for the exception to appear.
|
81
|
+
sleep 3 if example_name == "opal-exception"
|
82
|
+
|
83
|
+
instance_exec(browser, true, nil, &example_specific)
|
84
|
+
rescue Ferrum::JavaScriptError => e
|
85
|
+
instance_exec(browser, true, e, &example_specific)
|
86
|
+
ensure
|
87
|
+
browser.quit if browser
|
88
|
+
end
|
89
|
+
ensure
|
90
|
+
sigterm(pid)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "works in production mode" do
|
97
|
+
Dir.chdir example do
|
98
|
+
Bundler.with_unbundled_env do
|
99
|
+
if ENV.key? 'CI'
|
100
|
+
system("bundle config --local path #{__dir__+"/../vendor/bundle"}")
|
101
|
+
end
|
102
|
+
|
103
|
+
system("bundle install").should be true
|
104
|
+
|
105
|
+
system("bundle exec rake assets:clean").should be true
|
106
|
+
-> { Dir.children(example + "/public/assets") }.should raise_error Errno::ENOENT
|
107
|
+
system("bundle exec rake assets:precompile").should be true
|
108
|
+
Dir.children(example + "/public/assets").length.should be == 3
|
109
|
+
|
110
|
+
ENV['RACK_ENV'] = 'production'
|
111
|
+
|
112
|
+
begin
|
113
|
+
port = free_port
|
114
|
+
pid = spawn("bundle exec rackup -p#{port}")
|
115
|
+
sleep 1
|
116
|
+
|
117
|
+
begin
|
118
|
+
browser = Ferrum::Browser.new(**browser_options)
|
119
|
+
browser.go_to("http://localhost:#{port}/")
|
120
|
+
browser.network.wait_for_idle
|
121
|
+
|
122
|
+
instance_exec(browser, false, nil, &example_specific)
|
123
|
+
rescue Ferrum::JavaScriptError => e
|
124
|
+
instance_exec(browser, false, e, &example_specific)
|
125
|
+
ensure
|
126
|
+
browser.quit if browser
|
127
|
+
end
|
128
|
+
ensure
|
129
|
+
system("bundle exec rake assets:clean").should be true
|
130
|
+
-> { Dir.children(example + "/public/assets") }.should raise_error Errno::ENOENT
|
131
|
+
|
132
|
+
sigterm(pid)
|
133
|
+
end
|
134
|
+
ensure
|
135
|
+
ENV.delete('RACK_ENV')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/spec/plugin_spec.rb
ADDED
@@ -0,0 +1,237 @@
|
|
1
|
+
require "time"
|
2
|
+
require "roda/plugins/sprockets"
|
3
|
+
|
4
|
+
RSpec.shared_examples("basic checks") do
|
5
|
+
it "returns a OK result" do
|
6
|
+
req = app.req
|
7
|
+
req.should be_ok
|
8
|
+
end
|
9
|
+
|
10
|
+
it "generates the necessary tags" do
|
11
|
+
req = app.req
|
12
|
+
if debug
|
13
|
+
req.body.should include %'<script src="/assets/#{js_name}.debug.js" type="text/javascript"'
|
14
|
+
req.body.should include %'<link rel="stylesheet" type="text/css" href="/assets/#{css_name}.debug.css">'
|
15
|
+
else
|
16
|
+
req.body.should include %'<script src="/assets/#{js_name}-'
|
17
|
+
req.body.should include %'<link rel="stylesheet" type="text/css" href="/assets/#{css_name}-'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "generates the necessary files" do
|
22
|
+
req = app.req
|
23
|
+
req_css = app.req(req.css_path)
|
24
|
+
req_js = app.req(req.js_path)
|
25
|
+
|
26
|
+
req_css.should be_ok
|
27
|
+
req_css.body.should include css_value
|
28
|
+
|
29
|
+
req_js.should be_ok
|
30
|
+
req_js.body.should include js_value
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns a not modified status if the assets haven't been modified" do
|
34
|
+
req = app.req
|
35
|
+
|
36
|
+
etag_css = app.req(req.css_path).headers["ETag"]
|
37
|
+
etag_js = app.req(req.js_path).headers["ETag"]
|
38
|
+
|
39
|
+
req_css = app.req(req.css_path, "HTTP_IF_NONE_MATCH" => etag_css)
|
40
|
+
req_js = app.req(req.js_path, "HTTP_IF_NONE_MATCH" => etag_js)
|
41
|
+
|
42
|
+
req_css.should be_not_modified
|
43
|
+
req_js.should be_not_modified
|
44
|
+
end
|
45
|
+
|
46
|
+
it "appropriately includes source maps or not" do
|
47
|
+
req = app.req
|
48
|
+
req_css = app.req(req.css_path)
|
49
|
+
req_js = app.req(req.js_path)
|
50
|
+
|
51
|
+
if debug
|
52
|
+
req_css.body.should include "/*# sourceMappingURL="
|
53
|
+
req_js.body.should include "//# sourceMappingURL="
|
54
|
+
else
|
55
|
+
req_css.body.should_not include "/*# sourceMappingURL="
|
56
|
+
req_js.body.should_not include "//# sourceMappingURL="
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
RSpec.describe Roda::RodaPlugins::Sprockets do
|
62
|
+
context "simple app" do
|
63
|
+
let(:css_name) { "simple_css" }
|
64
|
+
let(:js_name) { "simple_js" }
|
65
|
+
let(:css_value) { "Simple CSS" }
|
66
|
+
let(:js_value) { "Simple JS" }
|
67
|
+
|
68
|
+
context "in debug mode" do
|
69
|
+
simple_debug_app = Server.gen("simple_css", "simple_js", debug: true)
|
70
|
+
|
71
|
+
let(:app) { simple_debug_app }
|
72
|
+
let(:debug) { true }
|
73
|
+
|
74
|
+
include_examples "basic checks"
|
75
|
+
end
|
76
|
+
|
77
|
+
context "in production mode" do
|
78
|
+
simple_prod_app = Server.gen("simple_css", "simple_js", debug: false)
|
79
|
+
|
80
|
+
let(:app) { simple_prod_app }
|
81
|
+
let(:debug) { false }
|
82
|
+
|
83
|
+
include_examples "basic checks"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "opal + scss app" do
|
88
|
+
let(:css_name) { "scss_css" }
|
89
|
+
let(:js_name) { "opal_js" }
|
90
|
+
let(:css_value) { "This is SCSS" }
|
91
|
+
let(:js_value) { "$$($nesting, 'Test').$new();" }
|
92
|
+
|
93
|
+
context "in debug mode" do
|
94
|
+
opalscss_debug_app = Server.gen("scss_css", "opal_js", opal: true, debug: true)
|
95
|
+
|
96
|
+
let(:app) { opalscss_debug_app }
|
97
|
+
let(:debug) { true }
|
98
|
+
|
99
|
+
include_examples "basic checks"
|
100
|
+
end
|
101
|
+
|
102
|
+
context "in production mode" do
|
103
|
+
opalscss_prod_app = Server.gen("scss_css", "opal_js", opal: true, debug: false)
|
104
|
+
|
105
|
+
let(:app) { opalscss_prod_app }
|
106
|
+
let(:debug) { false }
|
107
|
+
|
108
|
+
include_examples "basic checks"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "opal with requires + scss with imports app" do
|
113
|
+
let(:css_name) { "scss_css_with_imports" }
|
114
|
+
let(:js_name) { "opal_js_with_requires" }
|
115
|
+
let(:css_value) { "This is SCSS" }
|
116
|
+
let(:js_value) { "$$($nesting, 'Test').$new();" }
|
117
|
+
|
118
|
+
context "in debug mode" do
|
119
|
+
opalscssreq_debug_app = Server.gen("scss_css_with_imports", "opal_js_with_requires", opal: true, debug: true)
|
120
|
+
|
121
|
+
let(:app) { opalscssreq_debug_app }
|
122
|
+
let(:debug) { true }
|
123
|
+
|
124
|
+
include_examples "basic checks"
|
125
|
+
end
|
126
|
+
|
127
|
+
context "in production mode" do
|
128
|
+
opalscssreq_prod_app = Server.gen("scss_css_with_imports", "opal_js_with_requires", opal: true, debug: false)
|
129
|
+
|
130
|
+
let(:app) { opalscssreq_prod_app }
|
131
|
+
let(:debug) { false }
|
132
|
+
|
133
|
+
include_examples "basic checks"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "opal with erb + scss with erb app" do
|
138
|
+
let(:css_name) { "scss_css_with_erb" }
|
139
|
+
let(:js_name) { "opal_js_with_erb" }
|
140
|
+
let(:css_value) { "This is ERBSCSS" }
|
141
|
+
let(:js_value) { "$$($nesting, 'TestERB').$new();" }
|
142
|
+
|
143
|
+
context "in debug mode" do
|
144
|
+
opalscsserb_debug_app = Server.gen("scss_css_with_erb", "opal_js_with_erb", opal: true, debug: true)
|
145
|
+
|
146
|
+
let(:app) { opalscsserb_debug_app }
|
147
|
+
let(:debug) { true }
|
148
|
+
|
149
|
+
include_examples "basic checks"
|
150
|
+
end
|
151
|
+
|
152
|
+
context "in production mode" do
|
153
|
+
opalscsserb_prod_app = Server.gen("scss_css_with_erb", "opal_js_with_erb", opal: true, debug: false)
|
154
|
+
|
155
|
+
let(:app) { opalscsserb_prod_app }
|
156
|
+
let(:debug) { false }
|
157
|
+
|
158
|
+
include_examples "basic checks"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "opal + scss app with compressor" do
|
163
|
+
let(:css_name) { "scss_css" }
|
164
|
+
let(:js_name) { "opal_js" }
|
165
|
+
let(:css_value) { "This is SCSS" }
|
166
|
+
let(:js_value) { "Test" }
|
167
|
+
|
168
|
+
context "in debug mode" do
|
169
|
+
opalscsscomp_debug_app = Server.gen("scss_css", "opal_js",
|
170
|
+
css_compressor: :sassc, js_compressor: :uglify,
|
171
|
+
opal: true, debug: true
|
172
|
+
)
|
173
|
+
|
174
|
+
let(:app) { opalscsscomp_debug_app }
|
175
|
+
let(:debug) { true }
|
176
|
+
|
177
|
+
include_examples "basic checks"
|
178
|
+
|
179
|
+
it "should run uglifier" do
|
180
|
+
req = app.req
|
181
|
+
req_js = app.req(req.js_path)
|
182
|
+
|
183
|
+
req_js.body.should include "$$($nesting, 'Test').$new();"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "in production mode" do
|
188
|
+
opalscsscomp_prod_app = Server.gen("scss_css", "opal_js",
|
189
|
+
css_compressor: :sassc, js_compressor: :uglify,
|
190
|
+
opal: true, debug: false
|
191
|
+
)
|
192
|
+
|
193
|
+
let(:app) { opalscsscomp_prod_app }
|
194
|
+
let(:debug) { false }
|
195
|
+
|
196
|
+
include_examples "basic checks"
|
197
|
+
|
198
|
+
it "should not run uglifier" do
|
199
|
+
req = app.req
|
200
|
+
req_js = app.req(req.js_path)
|
201
|
+
|
202
|
+
req_js.body.should_not include "$$($nesting, 'Test').$new();"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "opal + scss app with cache" do
|
208
|
+
let(:css_name) { "scss_css" }
|
209
|
+
let(:js_name) { "opal_js" }
|
210
|
+
let(:css_value) { "This is SCSS" }
|
211
|
+
let(:js_value) { "$$($nesting, 'Test').$new();" }
|
212
|
+
|
213
|
+
context "in debug mode" do
|
214
|
+
opalscsscache_debug_app = Server.gen("scss_css", "opal_js",
|
215
|
+
opal: true, debug: true,
|
216
|
+
cache: Sprockets::Cache::MemoryStore.new(65536)
|
217
|
+
)
|
218
|
+
|
219
|
+
let(:app) { opalscsscache_debug_app }
|
220
|
+
let(:debug) { true }
|
221
|
+
|
222
|
+
include_examples "basic checks"
|
223
|
+
end
|
224
|
+
|
225
|
+
context "in production mode" do
|
226
|
+
opalscsscache_prod_app = Server.gen("scss_css", "opal_js",
|
227
|
+
opal: true, debug: false,
|
228
|
+
cache: Sprockets::Cache::MemoryStore.new(65536)
|
229
|
+
)
|
230
|
+
|
231
|
+
let(:app) { opalscsscache_prod_app }
|
232
|
+
let(:debug) { false }
|
233
|
+
|
234
|
+
include_examples "basic checks"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "roda"
|
2
|
+
|
3
|
+
class Server < Roda
|
4
|
+
class << self
|
5
|
+
def gen(css=nil, js=nil, **kwargs, &block)
|
6
|
+
Class.new Server do |c|
|
7
|
+
unless kwargs.empty?
|
8
|
+
c.plugin :sprockets, root: __dir__, **kwargs
|
9
|
+
end
|
10
|
+
|
11
|
+
if css || js
|
12
|
+
c.route do |r|
|
13
|
+
r.sprockets
|
14
|
+
|
15
|
+
r.root do
|
16
|
+
out = ""
|
17
|
+
out += stylesheet_tag(css) if css
|
18
|
+
out += javascript_tag(js) if js
|
19
|
+
out
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
yield(c) if block_given?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Slightly adapted from https://github.com/jeremyevans/roda/blob/master/spec/spec_helper.rb
|
29
|
+
def req(path = '/', env = {})
|
30
|
+
env['PATH_INFO'] = path.dup
|
31
|
+
env = {"REQUEST_METHOD" => "GET", "PATH_INFO" => "/", "SCRIPT_NAME" => ""}.merge(env)
|
32
|
+
Response.new(*self.call(env))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Response
|
37
|
+
def initialize(status, headers, body)
|
38
|
+
@status, @headers, @body = status, headers, body
|
39
|
+
end
|
40
|
+
|
41
|
+
def ok?
|
42
|
+
status == 200
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :status, :headers
|
46
|
+
|
47
|
+
def body
|
48
|
+
@body&.join
|
49
|
+
end
|
50
|
+
|
51
|
+
def js_path
|
52
|
+
body =~ /<script src="(.*?)"/
|
53
|
+
$1
|
54
|
+
end
|
55
|
+
|
56
|
+
def css_path
|
57
|
+
body =~ /<link rel="stylesheet" type="text\/css" href="(.*?)"/
|
58
|
+
$1
|
59
|
+
end
|
60
|
+
|
61
|
+
def not_modified?
|
62
|
+
status == 304 &&
|
63
|
+
(body.nil? || body.empty?) &&
|
64
|
+
!headers.key?("Content-Length") &&
|
65
|
+
!headers.key?("Content-Type")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.expect_with :rspec do |expectations|
|
3
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
4
|
+
# and `failure_message` of custom matchers include text for helper methods
|
5
|
+
# defined using `chain`, e.g.:
|
6
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
7
|
+
# # => "be bigger than 2 and smaller than 4"
|
8
|
+
# ...rather than:
|
9
|
+
# # => "be bigger than 2"
|
10
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
11
|
+
expectations.syntax = :should
|
12
|
+
end
|
13
|
+
|
14
|
+
config.mock_with :rspec do |mocks|
|
15
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
16
|
+
# a real object. This is generally recommended, and will default to
|
17
|
+
# `true` in RSpec 4.
|
18
|
+
mocks.verify_partial_doubles = true
|
19
|
+
end
|
20
|
+
|
21
|
+
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
|
22
|
+
# have no way to turn it off -- the option exists only for backwards
|
23
|
+
# compatibility in RSpec 3). It causes shared context metadata to be
|
24
|
+
# inherited by the metadata hash of host groups and examples, rather than
|
25
|
+
# triggering implicit auto-inclusion in groups with matching metadata.
|
26
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
27
|
+
|
28
|
+
# This allows you to limit a spec run to individual examples or groups
|
29
|
+
# you care about by tagging them with `:focus` metadata. When nothing
|
30
|
+
# is tagged with `:focus`, all examples get run. RSpec also provides
|
31
|
+
# aliases for `it`, `describe`, and `context` that include `:focus`
|
32
|
+
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
33
|
+
config.filter_run_when_matching :focus
|
34
|
+
|
35
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
36
|
+
# be too noisy due to issues in dependencies.
|
37
|
+
config.warnings = true
|
38
|
+
|
39
|
+
# Print the 10 slowest examples and example groups at the
|
40
|
+
# end of the spec run, to help surface which specs are running
|
41
|
+
# particularly slow.
|
42
|
+
config.profile_examples = 10
|
43
|
+
|
44
|
+
# Run specs in random order to surface order dependencies. If you find an
|
45
|
+
# order dependency and want to debug it, you can fix the order by providing
|
46
|
+
# the seed, which is printed after each run.
|
47
|
+
# --seed 1234
|
48
|
+
config.order = :random
|
49
|
+
|
50
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
51
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
52
|
+
# test failures related to randomization by passing the same `--seed` value
|
53
|
+
# as the one that triggered the failure.
|
54
|
+
Kernel.srand config.seed
|
55
|
+
end
|
56
|
+
|
57
|
+
require "bundler/setup"
|
58
|
+
|
59
|
+
require_relative "server_helper"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda-sprockets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cj
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-09-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: roda
|
@@ -88,23 +88,47 @@ executables: []
|
|
88
88
|
extensions: []
|
89
89
|
extra_rdoc_files: []
|
90
90
|
files:
|
91
|
+
- ".github/workflows/rake.yml"
|
91
92
|
- ".gitignore"
|
93
|
+
- ".rspec"
|
92
94
|
- CHANGELOG.md
|
93
95
|
- Gemfile
|
94
96
|
- LICENSE.txt
|
95
97
|
- README.md
|
96
98
|
- Rakefile
|
97
99
|
- examples/opal-doc/Gemfile
|
98
|
-
- examples/opal-doc/Gemfile.lock
|
99
100
|
- examples/opal-doc/README.md
|
100
101
|
- examples/opal-doc/Rakefile
|
101
102
|
- examples/opal-doc/app.rb
|
102
103
|
- examples/opal-doc/app/application.rb
|
103
104
|
- examples/opal-doc/config.ru
|
105
|
+
- examples/opal-exception/Gemfile
|
106
|
+
- examples/opal-exception/README.md
|
107
|
+
- examples/opal-exception/Rakefile
|
108
|
+
- examples/opal-exception/app.rb
|
109
|
+
- examples/opal-exception/app/application.rb
|
110
|
+
- examples/opal-exception/config.ru
|
111
|
+
- examples/sass/Gemfile
|
112
|
+
- examples/sass/Rakefile
|
113
|
+
- examples/sass/app.rb
|
114
|
+
- examples/sass/assets/css/application.scss
|
115
|
+
- examples/sass/config.ru
|
104
116
|
- lib/roda/plugins/sprockets.rb
|
105
117
|
- lib/roda/plugins/sprockets_task.rb
|
106
118
|
- lib/roda/sprockets.rb
|
107
119
|
- roda-sprockets.gemspec
|
120
|
+
- spec/assets/css/scss_css.scss
|
121
|
+
- spec/assets/css/scss_css_with_erb.scss.erb
|
122
|
+
- spec/assets/css/scss_css_with_imports.scss
|
123
|
+
- spec/assets/css/simple_css.css
|
124
|
+
- spec/assets/js/opal_js.rb
|
125
|
+
- spec/assets/js/opal_js_with_erb.rb.erb
|
126
|
+
- spec/assets/js/opal_js_with_requires.rb
|
127
|
+
- spec/assets/js/simple_js.js
|
128
|
+
- spec/examples_spec.rb
|
129
|
+
- spec/plugin_spec.rb
|
130
|
+
- spec/server_helper.rb
|
131
|
+
- spec/spec_helper.rb
|
108
132
|
homepage: https://github.com/hmdne/roda-sprockets
|
109
133
|
licenses:
|
110
134
|
- MIT
|
@@ -120,12 +144,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
120
144
|
version: '0'
|
121
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
146
|
requirements:
|
123
|
-
- - "
|
147
|
+
- - ">="
|
124
148
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
149
|
+
version: '0'
|
126
150
|
requirements: []
|
127
151
|
rubygems_version: 3.2.22
|
128
152
|
signing_key:
|
129
153
|
specification_version: 4
|
130
154
|
summary: Use sprockets to serve assets in roda.
|
131
|
-
test_files:
|
155
|
+
test_files:
|
156
|
+
- spec/assets/css/scss_css.scss
|
157
|
+
- spec/assets/css/scss_css_with_erb.scss.erb
|
158
|
+
- spec/assets/css/scss_css_with_imports.scss
|
159
|
+
- spec/assets/css/simple_css.css
|
160
|
+
- spec/assets/js/opal_js.rb
|
161
|
+
- spec/assets/js/opal_js_with_erb.rb.erb
|
162
|
+
- spec/assets/js/opal_js_with_requires.rb
|
163
|
+
- spec/assets/js/simple_js.js
|
164
|
+
- spec/examples_spec.rb
|
165
|
+
- spec/plugin_spec.rb
|
166
|
+
- spec/server_helper.rb
|
167
|
+
- spec/spec_helper.rb
|
@@ -1,47 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ../..
|
3
|
-
specs:
|
4
|
-
roda-sprockets (1.0.2)
|
5
|
-
roda (~> 3)
|
6
|
-
sprockets (>= 2.2)
|
7
|
-
sprockets-helpers (>= 1.4.0)
|
8
|
-
|
9
|
-
GEM
|
10
|
-
remote: https://rubygems.org/
|
11
|
-
specs:
|
12
|
-
ast (2.4.2)
|
13
|
-
concurrent-ruby (1.1.9)
|
14
|
-
nio4r (2.5.7)
|
15
|
-
opal (1.2.0)
|
16
|
-
ast (>= 2.3.0)
|
17
|
-
parser (~> 3.0)
|
18
|
-
opal-sprockets (1.0.1)
|
19
|
-
opal (>= 1.0, < 2.0)
|
20
|
-
sprockets (~> 4.0)
|
21
|
-
tilt (>= 1.4)
|
22
|
-
parser (3.0.2.0)
|
23
|
-
ast (~> 2.4.1)
|
24
|
-
puma (5.4.0)
|
25
|
-
nio4r (~> 2.0)
|
26
|
-
rack (2.2.3)
|
27
|
-
rake (13.0.6)
|
28
|
-
roda (3.46.0)
|
29
|
-
rack
|
30
|
-
sprockets (4.0.2)
|
31
|
-
concurrent-ruby (~> 1.0)
|
32
|
-
rack (> 1, < 3)
|
33
|
-
sprockets-helpers (1.4.0)
|
34
|
-
sprockets (>= 2.2)
|
35
|
-
tilt (2.0.10)
|
36
|
-
|
37
|
-
PLATFORMS
|
38
|
-
ruby
|
39
|
-
|
40
|
-
DEPENDENCIES
|
41
|
-
opal-sprockets
|
42
|
-
puma
|
43
|
-
rake
|
44
|
-
roda-sprockets!
|
45
|
-
|
46
|
-
BUNDLED WITH
|
47
|
-
2.1.4
|