assets_include 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +9 -0
- data/Gemfile +9 -0
- data/History.md +9 -0
- data/LICENSE +19 -0
- data/README.md +76 -0
- data/Rakefile +43 -0
- data/assets_include.gemspec +15 -0
- data/examples/sinatra/Gemfile +4 -0
- data/examples/sinatra/Gemfile.lock +23 -0
- data/examples/sinatra/README.md +32 -0
- data/examples/sinatra/app.rb +43 -0
- data/examples/sinatra/assets.yml +10 -0
- data/examples/sinatra/package.json +9 -0
- data/examples/sinatra/public/javascripts/inline.js +7 -0
- data/examples/sinatra/public/javascripts/main.js +5 -0
- data/examples/sinatra/public/javascripts/vendor/hex-rgb.src.js +64 -0
- data/examples/sinatra/public/javascripts/vendor/microajax.js +66 -0
- data/examples/sinatra/public/stylesheets/base.css +7 -0
- data/examples/sinatra/public/stylesheets/normalize.css +91 -0
- data/lib/assets_include.rb +10 -0
- data/lib/assets_include/base.rb +120 -0
- data/lib/assets_include/cache.rb +23 -0
- data/lib/assets_include/proxy.rb +15 -0
- data/lib/assets_include/version.rb +7 -0
- data/test/assets_include/base_test.rb +235 -0
- data/test/assets_include/cache_test.rb +55 -0
- data/test/assets_include/proxy_test.rb +37 -0
- data/test/fixtures/assets.yml +4 -0
- data/test/fixtures/package.json +9 -0
- data/test/fixtures/public/stylesheets/bundled/all.css +1 -0
- data/test/fixtures/public/stylesheets/one.css +3 -0
- data/test/fixtures/public/stylesheets/two.css +3 -0
- data/test/test_helper.rb +13 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8f31bd237abed00c9d7a4c13f7dccd4175f7f47d
|
4
|
+
data.tar.gz: 10cade04984960cfc65857d6b97b603287d0c916
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9bb76bb165e7d40c5f1d7e279457a8de9843011b6f72b2d6b946cc9bbf3cc09ad4e43402f735f6417f0897b122f20f83e957c68a1ecd5afd696b2e7e2462cfc2
|
7
|
+
data.tar.gz: 616792110b62b0bb624d8306aab8c8eea65ad497401f76d68c7bdd643ca42655adb7256ef2ef1b3ffcae343b085265a365c4170d5aa6f28df2ef532a42bce17e
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/History.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
1.0.0 / 2014-03-15
|
2
|
+
==================
|
3
|
+
|
4
|
+
* Provides 1:1 mapping with `assetsinc` 1.1 API.
|
5
|
+
* Provides Sinatra helpers providing the same features as node version.
|
6
|
+
* Provides Sinatra examples.
|
7
|
+
* Provides a #reset option to empty includer's cache.
|
8
|
+
* Defaults to bundled mode if RACK_ENV variable is set to production.
|
9
|
+
* Defaults cache_boosters to true as it is a more sane option.
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2011-2014 GoalSmashers.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is furnished
|
8
|
+
to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
14
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
15
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
16
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
17
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
18
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
19
|
+
DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
[![Build Status](https://secure.travis-ci.org/GoalSmashers/assets-include-ruby.png)](https://travis-ci.org/GoalSmashers/assets-include-ruby)
|
2
|
+
[![Code Climate](https://codeclimate.com/github/GoalSmashers/assets-include-ruby.png)](https://codeclimate.com/github/GoalSmashers/assets-include-ruby)
|
3
|
+
[![Code Climate](https://codeclimate.com/github/GoalSmashers/assets-include-ruby/coverage.png)](https://codeclimate.com/github/GoalSmashers/assets-include-ruby)
|
4
|
+
|
5
|
+
## What is assets-include-ruby?
|
6
|
+
|
7
|
+
Assets-include is a Ruby wrapper around [Assets-Include](https://github.com/GoalSmashers/assets-include) for including your assets in HTML views.
|
8
|
+
|
9
|
+
See [example apps](https://github.com/GoalSmashers/assets-include-ruby/tree/master/examples) for real-world use cases.
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
### What are the requirements?
|
14
|
+
|
15
|
+
```
|
16
|
+
Ruby 1.9.3+
|
17
|
+
Node.js 0.8.0+
|
18
|
+
```
|
19
|
+
|
20
|
+
### How to install assets-include-ruby?
|
21
|
+
|
22
|
+
```
|
23
|
+
gem install assets_include
|
24
|
+
```
|
25
|
+
|
26
|
+
### How to use assets-include-ruby?
|
27
|
+
|
28
|
+
With [Sinatra](https://github.com/sinatra/sinatra):
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
require 'sinatra'
|
32
|
+
require 'assets_include'
|
33
|
+
|
34
|
+
# Adds assets.(group|list|inline) helpers
|
35
|
+
helpers AssetsInclude.helpers
|
36
|
+
|
37
|
+
get '/' do
|
38
|
+
erb :index
|
39
|
+
end
|
40
|
+
|
41
|
+
__END__
|
42
|
+
|
43
|
+
@@ layout
|
44
|
+
<html>
|
45
|
+
<head>
|
46
|
+
<%= assets.group('stylesheets/all.css') %>
|
47
|
+
</head>
|
48
|
+
<body>
|
49
|
+
<%= yield %>
|
50
|
+
<%= assets.group('javascripts/all.js') %>
|
51
|
+
</body>
|
52
|
+
</html>
|
53
|
+
|
54
|
+
@@ index
|
55
|
+
<h1>Yay, all assets are in</h1>
|
56
|
+
```
|
57
|
+
|
58
|
+
AssetsInclude.helpers accepts an options hash, i.e.,
|
59
|
+
|
60
|
+
* `bundled` - whether to serve bundled (production) or expanded (development) assets. Defaults based on ENV['RACK_ENV'] value.
|
61
|
+
* `config` - path to configuration file, defaults to ./assets.yml
|
62
|
+
* `root` - root path of all assets, defaults to ./public under config's path
|
63
|
+
* `cache_boosters` - `true` for cache boosters (timestamp in dev mode, md5 for bundled, production files)
|
64
|
+
* `asset_hosts` - prefixes all paths with given asset host(s)
|
65
|
+
* `loading_mode` - `async` or `defer` for JavaScript assets' loading mode
|
66
|
+
|
67
|
+
and adds the following methods to your views:
|
68
|
+
|
69
|
+
* `assets.group(locator)` - returns a list of `<script>` or `<link>` tags for JavaScript or CSS assets respectively
|
70
|
+
* `assets.inline(locator)` - returns inlined JavaScript or CSS assets. In development mode works the same way as `#group`.
|
71
|
+
* `assets.list(locator)` - returns an array of assets files to easily embed them into JavaScript or data attributes.
|
72
|
+
* `assets.reset` - empties includer's cache
|
73
|
+
|
74
|
+
## License
|
75
|
+
|
76
|
+
Assets-include-ruby is released under the [MIT License](https://github.com/GoalSmashers/assets-include-ruby/blob/master/LICENSE).
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
task default: :test
|
6
|
+
task spec: :test
|
7
|
+
|
8
|
+
task :test_setup do
|
9
|
+
`cd test/fixtures && npm install`
|
10
|
+
end
|
11
|
+
|
12
|
+
Rake::TestTask.new(test: :test_setup) do |t|
|
13
|
+
t.test_files = FileList['test/**/*_test.rb']
|
14
|
+
t.ruby_opts = ['-rubygems'] if defined? Gem
|
15
|
+
t.ruby_opts << '-Ilib:test'
|
16
|
+
t.warning = true
|
17
|
+
end
|
18
|
+
|
19
|
+
if defined?(Gem)
|
20
|
+
directory('pkg/')
|
21
|
+
|
22
|
+
def spec
|
23
|
+
require 'rubygems' unless defined? Gem::Specification
|
24
|
+
@spec ||= eval(File.read('assets_include.gemspec'))
|
25
|
+
end
|
26
|
+
|
27
|
+
def package
|
28
|
+
%{pkg/assets_include-#{spec.version}.gem}
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Build packages'
|
32
|
+
task package: package
|
33
|
+
|
34
|
+
desc 'Build and install as a local gem'
|
35
|
+
task install: package do
|
36
|
+
sh %{gem install #{package}}
|
37
|
+
end
|
38
|
+
|
39
|
+
file package => %w[pkg/ assets_include.gemspec] do |f|
|
40
|
+
sh 'gem build assets_include.gemspec'
|
41
|
+
mv File.basename(f.name), f.name
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
require 'assets_include/version'
|
3
|
+
|
4
|
+
Gem::Specification.new('assets_include', AssetsInclude::VERSION) do |s|
|
5
|
+
s.description = 'Include assets in your views with a single line of code.'
|
6
|
+
s.summary = 'Ruby bindings for assets-include node.js library.'
|
7
|
+
s.authors = ['Jakub Pawlowicz']
|
8
|
+
s.email = 'jakub.pawlowicz@goalsmashers.com'
|
9
|
+
s.homepage = 'https://github.com/GoalSmashers/assets-include-ruby'
|
10
|
+
s.license = 'MIT'
|
11
|
+
s.files = `git ls-files`.split("\n") - %w(.gitignore)
|
12
|
+
|
13
|
+
s.add_development_dependency 'minitest', '~> 4.7.0'
|
14
|
+
s.add_development_dependency 'flexmock', '~> 1.3.0'
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../..
|
3
|
+
specs:
|
4
|
+
assets_include (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
rack (1.5.2)
|
10
|
+
rack-protection (1.5.2)
|
11
|
+
rack
|
12
|
+
sinatra (1.4.4)
|
13
|
+
rack (~> 1.4)
|
14
|
+
rack-protection (~> 1.4)
|
15
|
+
tilt (~> 1.3, >= 1.3.4)
|
16
|
+
tilt (1.4.1)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
assets_include!
|
23
|
+
sinatra (~> 1.4.0)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
## Example of how to include assets in a Sintra app
|
2
|
+
|
3
|
+
### What are the requirements?
|
4
|
+
|
5
|
+
* Ruby 1.9.3+
|
6
|
+
* node.js 0.8+
|
7
|
+
|
8
|
+
### How to set it up?
|
9
|
+
|
10
|
+
Given you have Ruby and node.js available run:
|
11
|
+
|
12
|
+
```bash
|
13
|
+
bundle install
|
14
|
+
npm install
|
15
|
+
```
|
16
|
+
|
17
|
+
### How to run in in development mode?
|
18
|
+
|
19
|
+
```
|
20
|
+
ruby app.rb
|
21
|
+
```
|
22
|
+
|
23
|
+
and point your browser to [localhost:4567](http://localhost:4567)
|
24
|
+
|
25
|
+
### How to run in in production mode?
|
26
|
+
|
27
|
+
```bash
|
28
|
+
./node_modules/.bin/assetspkg -b -c assets.yml
|
29
|
+
RACK_ENV=production ruby app.rb
|
30
|
+
```
|
31
|
+
|
32
|
+
and point your browser to [localhost:4567](http://localhost:4567)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require 'sinatra'
|
5
|
+
require 'assets_include'
|
6
|
+
|
7
|
+
helpers AssetsInclude.helpers
|
8
|
+
|
9
|
+
get '/' do
|
10
|
+
erb :index
|
11
|
+
end
|
12
|
+
|
13
|
+
__END__
|
14
|
+
|
15
|
+
@@ layout
|
16
|
+
<html>
|
17
|
+
<head>
|
18
|
+
<title>Showcase</title>
|
19
|
+
<%= assets.group('stylesheets/all.css') %>
|
20
|
+
</head>
|
21
|
+
<body>
|
22
|
+
<%= yield %>
|
23
|
+
<%= assets.group('javascripts/all.js') %>
|
24
|
+
</body>
|
25
|
+
</html>
|
26
|
+
|
27
|
+
@@ index
|
28
|
+
<h1>Assets-includer-ruby showcase</h1>
|
29
|
+
<p>CSS and JavaScript are included via <span class="pre">assets.group</span> calls (see source in app.rb)</p>
|
30
|
+
<p>Here's a list of all CSS assets (you can get it programaticaly):</p>
|
31
|
+
<ol>
|
32
|
+
<% assets.list('stylesheets/all.css').each do |asset| %>
|
33
|
+
<li><%= asset %></li>
|
34
|
+
<% end %>
|
35
|
+
</ol>
|
36
|
+
<p>and a list of all JavaScript ones:</p>
|
37
|
+
<ol>
|
38
|
+
<% assets.list('javascripts/all.js').each do |asset| %>
|
39
|
+
<li><%= asset %></li>
|
40
|
+
<% end %>
|
41
|
+
</ol>
|
42
|
+
<p class="js-inline-placeholder"></p>
|
43
|
+
<%= assets.inline('javascripts/inline.js') %>
|
@@ -0,0 +1,64 @@
|
|
1
|
+
/*!
|
2
|
+
* HEX <=> RGB Conversion
|
3
|
+
* Copyright(c) 2011 Daniel Lamb <daniellmb.com>
|
4
|
+
* MIT Licensed
|
5
|
+
*/
|
6
|
+
|
7
|
+
(function (context) {
|
8
|
+
|
9
|
+
context['toRGB'] = function (/* String */ color) {
|
10
|
+
// summary:
|
11
|
+
// Converts a 6 digit Hexadecimal string value to an RGB integer array.
|
12
|
+
// Important! input must be a 6 digit Hexadecimal string "bad" will
|
13
|
+
// not convert correctly but "bbaadd" will. To keep the function as
|
14
|
+
// light as possible there is no idiot-proofing, if you pass in bad
|
15
|
+
// data I'm not fixing it for you :-)
|
16
|
+
//
|
17
|
+
// color: String
|
18
|
+
// 6 digit Hexadecimal string value
|
19
|
+
//
|
20
|
+
// returns: Array
|
21
|
+
// An array containing the RGB integers in the following format [red, green, blue]
|
22
|
+
//
|
23
|
+
// example:
|
24
|
+
// Convert the Hexadecimal value "c0ffee" (blue color) to RGB integers.
|
25
|
+
// The variable "rgb" will be equal to [192, 255, 238]
|
26
|
+
//
|
27
|
+
// var rgb = toRGB("c0ffee");
|
28
|
+
|
29
|
+
//convert string to base 16 number
|
30
|
+
var num = parseInt(color, 16);
|
31
|
+
|
32
|
+
//return the red, green and blue values as a new array
|
33
|
+
return [num >> 16, num >> 8 & 255, num & 255];
|
34
|
+
};
|
35
|
+
|
36
|
+
context['toHex'] = function (/* Number */ red, /* Number */ green, /* Number */ blue) {
|
37
|
+
// summary:
|
38
|
+
// Converts 3 RGB integer values into a Hexadecimal string.
|
39
|
+
// Important! input must be integers with a range of 0 to 255.
|
40
|
+
// To keep the function as light as possible there is no idiot-proofing,
|
41
|
+
// if you pass in bad data I'm not fixing it for you :-)
|
42
|
+
//
|
43
|
+
// red: Number
|
44
|
+
// number ranging from 0 to 255 indicating the amount of red
|
45
|
+
// green: Number
|
46
|
+
// number ranging from 0 to 255 indicating the amount of green
|
47
|
+
// blue: Number
|
48
|
+
// number ranging from 0 to 255 indicating the amount of blue
|
49
|
+
//
|
50
|
+
// returns: String
|
51
|
+
// 6 digit Hexadecimal string value
|
52
|
+
//
|
53
|
+
// example:
|
54
|
+
// Convert the RGB values [192, 255, 238] (blue color) to Hexadecimal string.
|
55
|
+
// The variable "hex" will be equal to "c0ffee"
|
56
|
+
//
|
57
|
+
// var hex = toHex(192, 255, 238);
|
58
|
+
|
59
|
+
//return 6 digit Hexadecimal string
|
60
|
+
return ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1);
|
61
|
+
};
|
62
|
+
|
63
|
+
})(this);
|
64
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2008 Stefan Lange-Hegermann
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
6
|
+
in the Software without restriction, including without limitation the rights
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
9
|
+
furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in
|
12
|
+
all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
THE SOFTWARE.
|
21
|
+
*/
|
22
|
+
|
23
|
+
function microAjax(url, callbackFunction)
|
24
|
+
{
|
25
|
+
this.bindFunction = function (caller, object) {
|
26
|
+
return function() {
|
27
|
+
return caller.apply(object, [object]);
|
28
|
+
};
|
29
|
+
};
|
30
|
+
|
31
|
+
this.stateChange = function (object) {
|
32
|
+
if (this.request.readyState==4)
|
33
|
+
this.callbackFunction(this.request.responseText);
|
34
|
+
};
|
35
|
+
|
36
|
+
this.getRequest = function() {
|
37
|
+
if (window.ActiveXObject)
|
38
|
+
return new ActiveXObject('Microsoft.XMLHTTP');
|
39
|
+
else if (window.XMLHttpRequest)
|
40
|
+
return new XMLHttpRequest();
|
41
|
+
return false;
|
42
|
+
};
|
43
|
+
|
44
|
+
this.postBody = (arguments[2] || "");
|
45
|
+
|
46
|
+
this.callbackFunction=callbackFunction;
|
47
|
+
this.url=url;
|
48
|
+
this.request = this.getRequest();
|
49
|
+
|
50
|
+
if(this.request) {
|
51
|
+
var req = this.request;
|
52
|
+
req.onreadystatechange = this.bindFunction(this.stateChange, this);
|
53
|
+
|
54
|
+
if (this.postBody!=="") {
|
55
|
+
req.open("POST", url, true);
|
56
|
+
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
57
|
+
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
58
|
+
req.setRequestHeader('Connection', 'close');
|
59
|
+
} else {
|
60
|
+
req.open("GET", url, true);
|
61
|
+
}
|
62
|
+
|
63
|
+
req.send(this.postBody);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
|
2
|
+
|
3
|
+
/* ==========================================================================
|
4
|
+
HTML5 display definitions
|
5
|
+
========================================================================== */
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Correct `block` display not defined in IE 8/9.
|
9
|
+
*/
|
10
|
+
|
11
|
+
article,
|
12
|
+
aside,
|
13
|
+
details,
|
14
|
+
figcaption,
|
15
|
+
figure,
|
16
|
+
footer,
|
17
|
+
header,
|
18
|
+
hgroup,
|
19
|
+
main,
|
20
|
+
nav,
|
21
|
+
section,
|
22
|
+
summary {
|
23
|
+
display: block;
|
24
|
+
}
|
25
|
+
|
26
|
+
/* ==========================================================================
|
27
|
+
Base
|
28
|
+
========================================================================== */
|
29
|
+
|
30
|
+
/**
|
31
|
+
* 1. Set default font family to sans-serif.
|
32
|
+
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
33
|
+
* user zoom.
|
34
|
+
*/
|
35
|
+
|
36
|
+
html {
|
37
|
+
font-family: sans-serif; /* 1 */
|
38
|
+
-ms-text-size-adjust: 100%; /* 2 */
|
39
|
+
-webkit-text-size-adjust: 100%; /* 2 */
|
40
|
+
}
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Remove default margin.
|
44
|
+
*/
|
45
|
+
|
46
|
+
body {
|
47
|
+
margin: 0;
|
48
|
+
}
|
49
|
+
|
50
|
+
/* ==========================================================================
|
51
|
+
Links
|
52
|
+
========================================================================== */
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Remove the gray background color from active links in IE 10.
|
56
|
+
*/
|
57
|
+
|
58
|
+
a {
|
59
|
+
background: transparent;
|
60
|
+
}
|
61
|
+
|
62
|
+
/**
|
63
|
+
* Address `outline` inconsistency between Chrome and other browsers.
|
64
|
+
*/
|
65
|
+
|
66
|
+
a:focus {
|
67
|
+
outline: thin dotted;
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* Improve readability when focused and also mouse hovered in all browsers.
|
72
|
+
*/
|
73
|
+
|
74
|
+
a:active,
|
75
|
+
a:hover {
|
76
|
+
outline: 0;
|
77
|
+
}
|
78
|
+
|
79
|
+
/* ==========================================================================
|
80
|
+
Typography
|
81
|
+
========================================================================== */
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Address variable `h1` font-size and margin within `section` and `article`
|
85
|
+
* contexts in Firefox 4+, Safari 5, and Chrome.
|
86
|
+
*/
|
87
|
+
|
88
|
+
h1 {
|
89
|
+
font-size: 2em;
|
90
|
+
margin: 0.67em 0;
|
91
|
+
}
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require_relative 'cache'
|
2
|
+
|
3
|
+
module AssetsInclude
|
4
|
+
|
5
|
+
class Base
|
6
|
+
attr_accessor :bundled, :asset_hosts, :root, :config, :cache_boosters
|
7
|
+
attr_accessor :binary
|
8
|
+
|
9
|
+
def initialize(&block)
|
10
|
+
@cache = Cache.new
|
11
|
+
@config = default_assets_location
|
12
|
+
@bundled = production?
|
13
|
+
@cache_boosters = true
|
14
|
+
|
15
|
+
yield(self) if block_given?
|
16
|
+
end
|
17
|
+
|
18
|
+
def group(locator, options = {})
|
19
|
+
assets(locator, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def list(locator)
|
23
|
+
assets(locator, list: true).strip.split(',')
|
24
|
+
end
|
25
|
+
|
26
|
+
def inline(locator)
|
27
|
+
assets(locator, inline: true)
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset
|
31
|
+
cache.empty
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :cache
|
37
|
+
|
38
|
+
def assets(locator, options)
|
39
|
+
cache.empty unless bundled
|
40
|
+
|
41
|
+
cache.add("#{locator}-#{options.to_s.hash}") do
|
42
|
+
IO.popen(command(locator, options).join(' ')).read
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_assets_location
|
47
|
+
File.join(Dir.pwd, 'assets.yml')
|
48
|
+
end
|
49
|
+
|
50
|
+
def production?
|
51
|
+
ENV['RACK_ENV'] == 'production'
|
52
|
+
end
|
53
|
+
|
54
|
+
def command(locator, options = {})
|
55
|
+
parts = []
|
56
|
+
parts << includer_binary
|
57
|
+
parts << root_switch
|
58
|
+
parts << config_switch
|
59
|
+
parts << bundled_switch
|
60
|
+
parts << cache_boosters_switch
|
61
|
+
parts << list_switch(options)
|
62
|
+
parts << inline_switch(options)
|
63
|
+
parts << asset_hosts_switch
|
64
|
+
parts << loading_mode_switch(options)
|
65
|
+
parts << locator
|
66
|
+
parts.compact
|
67
|
+
end
|
68
|
+
|
69
|
+
def includer_binary
|
70
|
+
@binary ||= binary_locations.find { |path|
|
71
|
+
IO.popen("which #{path}")
|
72
|
+
$?.to_i == 0
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def binary_locations
|
77
|
+
[
|
78
|
+
File.join(implicit_root, '..', 'node_modules', '.bin', 'assetsinc'),
|
79
|
+
File.join(implicit_root, 'node_modules', '.bin', 'assetsinc'),
|
80
|
+
'assetsinc'
|
81
|
+
]
|
82
|
+
end
|
83
|
+
|
84
|
+
def implicit_root
|
85
|
+
root || File.join(Dir.pwd, 'public')
|
86
|
+
end
|
87
|
+
|
88
|
+
def root_switch
|
89
|
+
root ? "-r #{root}" : nil
|
90
|
+
end
|
91
|
+
|
92
|
+
def config_switch
|
93
|
+
"-c #{config}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def bundled_switch
|
97
|
+
bundled ? '-b' : nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def cache_boosters_switch
|
101
|
+
cache_boosters ? '-s' : nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def list_switch(options = {})
|
105
|
+
options[:list] ? '-l' : nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def inline_switch(options = {})
|
109
|
+
options[:inline] ? '-i' : nil
|
110
|
+
end
|
111
|
+
|
112
|
+
def asset_hosts_switch
|
113
|
+
asset_hosts ? "-a #{asset_hosts}" : nil
|
114
|
+
end
|
115
|
+
|
116
|
+
def loading_mode_switch(options = {})
|
117
|
+
options[:loading_mode] ? "-m #{options[:loading_mode]}" : nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module AssetsInclude
|
2
|
+
class Cache
|
3
|
+
def initialize
|
4
|
+
@store = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def add(key, &block)
|
8
|
+
store[key] ||= yield
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(key)
|
12
|
+
store[key]
|
13
|
+
end
|
14
|
+
|
15
|
+
def empty
|
16
|
+
store.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :store
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'assets_include/base'
|
4
|
+
|
5
|
+
describe AssetsInclude::Base do
|
6
|
+
include FlexMock::TestCase
|
7
|
+
|
8
|
+
def after
|
9
|
+
flexmock_teardown
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#initialize' do
|
15
|
+
it 'should make binary customizable' do
|
16
|
+
flexmock(IO)
|
17
|
+
.should_receive(:popen)
|
18
|
+
.once
|
19
|
+
.with(['assetsinc', "-r #{root}", "-c #{config}", '-b', group].join(' '))
|
20
|
+
.and_return(flexmock(read: ''))
|
21
|
+
|
22
|
+
includer(binary: 'assetsinc').group(group)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should default `root` and `config`' do
|
26
|
+
flexmock(IO)
|
27
|
+
.should_receive(:popen)
|
28
|
+
.once
|
29
|
+
.with([binary, "-c #{File.join(Dir.pwd, 'assets.yml')}", group].join(' '))
|
30
|
+
.and_return(flexmock(read: ''))
|
31
|
+
|
32
|
+
described_class.new { |inc|
|
33
|
+
inc.binary = binary
|
34
|
+
inc.cache_boosters = false
|
35
|
+
}.group(group)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should set `cache_boosters` to true by default' do
|
39
|
+
described_class.new.cache_boosters.must_equal true
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should set `bundled` to false by default' do
|
43
|
+
described_class.new.bundled.must_equal false
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should set `bundled` to true on production' do
|
47
|
+
begin
|
48
|
+
ENV['RACK_ENV'] = 'production'
|
49
|
+
|
50
|
+
described_class.new.bundled.must_equal true
|
51
|
+
ensure
|
52
|
+
ENV['RACK_ENV'] = 'test'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#group' do
|
58
|
+
it 'should proxy a call to assetsinc and return correct result' do
|
59
|
+
should_run_includer_with(options: ['-b', group])
|
60
|
+
|
61
|
+
includer.group(group).must_equal(:assets)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should cache any subsequent calls' do
|
65
|
+
should_run_includer_with(options: ['-b', group])
|
66
|
+
|
67
|
+
includer.group(group)
|
68
|
+
includer.group(group).must_equal(:assets)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should cache results based on passed locator' do
|
72
|
+
should_run_includer_with(
|
73
|
+
options: ['-b', group],
|
74
|
+
output: :assets_1
|
75
|
+
)
|
76
|
+
|
77
|
+
should_run_includer_with(
|
78
|
+
options: ['-b', group('page')],
|
79
|
+
output: :assets_2
|
80
|
+
)
|
81
|
+
|
82
|
+
includer.group(group).must_equal(:assets_1)
|
83
|
+
includer.group(group('page')).must_equal(:assets_2)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should empty cache if not bundled' do
|
87
|
+
should_run_includer_with(
|
88
|
+
options: [group],
|
89
|
+
repeat: 2
|
90
|
+
)
|
91
|
+
|
92
|
+
2.times do
|
93
|
+
includer(bundled: false).group(group)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should use cache boosters' do
|
98
|
+
should_run_includer_with(options: ['-b', '-s', group])
|
99
|
+
|
100
|
+
includer(cache_boosters: true).group(group)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should use asset hosts' do
|
104
|
+
should_run_includer_with(options: ['-b', '-a goalsmashers.com', group])
|
105
|
+
|
106
|
+
includer(asset_hosts: 'goalsmashers.com').group(group)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should use loading mode' do
|
110
|
+
should_run_includer_with(options: ['-b', '-m async', group])
|
111
|
+
|
112
|
+
includer.group(group, loading_mode: 'async')
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should do a real call and get a list of tags' do
|
116
|
+
assets = [
|
117
|
+
%{<link href="#{file_with_timestamp('one.css')}" media="screen" rel="stylesheet"/>},
|
118
|
+
%{<link href="#{file_with_timestamp('two.css')}" media="screen" rel="stylesheet"/>}
|
119
|
+
]
|
120
|
+
|
121
|
+
includer(bundled: false).group(group).strip.must_equal(assets.join)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#list' do
|
126
|
+
it 'should proxy a call to assetsinc and return correct result' do
|
127
|
+
should_run_includer_with(
|
128
|
+
options: ['-b', '-l', group],
|
129
|
+
output: 'list'
|
130
|
+
)
|
131
|
+
|
132
|
+
includer.list(group).must_equal(['list'])
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should do a real call and get a list of assets' do
|
136
|
+
assets = [
|
137
|
+
file_with_timestamp('one.css'),
|
138
|
+
file_with_timestamp('two.css')
|
139
|
+
]
|
140
|
+
|
141
|
+
includer(bundled: false).list(group).must_equal(assets)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe '#inline' do
|
146
|
+
it 'should proxy a call to assetsinc and return correct result' do
|
147
|
+
should_run_includer_with(
|
148
|
+
options: ['-b', '-i', group],
|
149
|
+
output: :inline
|
150
|
+
)
|
151
|
+
|
152
|
+
includer.inline(group).must_equal(:inline)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should do a real call and get an inline style' do
|
156
|
+
inline = '<style type="text/css">.one,.two{color:red}</style>'
|
157
|
+
|
158
|
+
includer(bundled: true).inline(group).strip.must_equal(inline)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '#reset' do
|
163
|
+
it 'should empty cache' do
|
164
|
+
should_run_includer_with(
|
165
|
+
options: ['-b', group],
|
166
|
+
repeat: 2
|
167
|
+
)
|
168
|
+
|
169
|
+
includer.group(group)
|
170
|
+
includer.reset
|
171
|
+
includer.group(group)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def includer(options = {})
|
178
|
+
@includer ||= described_class.new do |inc|
|
179
|
+
inc.root = root
|
180
|
+
inc.config = config
|
181
|
+
inc.bundled = true
|
182
|
+
inc.cache_boosters = false
|
183
|
+
inc.binary = binary
|
184
|
+
|
185
|
+
options.each do |key, value|
|
186
|
+
inc.public_send("#{key}=", value)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def should_run_includer_with(opts = {})
|
192
|
+
flexmock(IO)
|
193
|
+
.should_receive(:popen)
|
194
|
+
.times(opts[:repeat] || 1)
|
195
|
+
.with(command(opts[:options]).join(' '))
|
196
|
+
.and_return(flexmock(read: opts[:output] || :assets))
|
197
|
+
end
|
198
|
+
|
199
|
+
def command(options = {})
|
200
|
+
[
|
201
|
+
binary,
|
202
|
+
"-r #{root}",
|
203
|
+
"-c #{config}",
|
204
|
+
options
|
205
|
+
].flatten.compact.uniq
|
206
|
+
end
|
207
|
+
|
208
|
+
def file_with_timestamp(name)
|
209
|
+
local_path = File.join('stylesheets', name)
|
210
|
+
absolute_path = File.join(root, local_path)
|
211
|
+
relative_path = absolute_path.sub(root, '')
|
212
|
+
|
213
|
+
"#{relative_path}?#{File.mtime(absolute_path).to_i * 1000}"
|
214
|
+
end
|
215
|
+
|
216
|
+
def group(name = 'all')
|
217
|
+
"stylesheets/#{name}.css"
|
218
|
+
end
|
219
|
+
|
220
|
+
def binary
|
221
|
+
File.join(root, '..', 'node_modules', '.bin', 'assetsinc')
|
222
|
+
end
|
223
|
+
|
224
|
+
def root
|
225
|
+
File.join(Dir.pwd, 'test', 'fixtures', 'public')
|
226
|
+
end
|
227
|
+
|
228
|
+
def config
|
229
|
+
File.join(root, '..', 'assets.yml')
|
230
|
+
end
|
231
|
+
|
232
|
+
def described_class
|
233
|
+
AssetsInclude::Base
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'assets_include/cache'
|
4
|
+
|
5
|
+
describe AssetsInclude::Cache do
|
6
|
+
describe 'initialize' do
|
7
|
+
it 'is empty by default' do
|
8
|
+
cache.get(:key).must_equal nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#add' do
|
13
|
+
it 'adds an item to cache' do
|
14
|
+
cache.add(:key) { :value }
|
15
|
+
|
16
|
+
cache.get(:key).must_equal :value
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'does not overwrite item in cache' do
|
20
|
+
2.times do |i|
|
21
|
+
cache.add(:key) { i }
|
22
|
+
end
|
23
|
+
|
24
|
+
cache.get(:key).must_equal 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#get' do
|
29
|
+
it 'does not remove item from cache' do
|
30
|
+
cache.add(:key) { :value }
|
31
|
+
|
32
|
+
cache.get(:key).must_equal :value
|
33
|
+
cache.get(:key).must_equal :value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#empty' do
|
38
|
+
it 'empties the cache' do
|
39
|
+
cache.add(:key) { :value }
|
40
|
+
|
41
|
+
cache.empty
|
42
|
+
cache.get(:key).must_equal nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def cache
|
49
|
+
@cache ||= described_class.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def described_class
|
53
|
+
AssetsInclude::Cache
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'assets_include/proxy'
|
4
|
+
|
5
|
+
describe AssetsInclude::Proxy do
|
6
|
+
describe '#module' do
|
7
|
+
it 'should be a module' do
|
8
|
+
proxy.class.must_equal(Module)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should be a Proxy module' do
|
12
|
+
proxy.is_a?(described_class).must_equal true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should expose Base via assets' do
|
16
|
+
proxy.assets.class.must_equal(AssetsInclude::Base)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'AssetsInclude.helpers' do
|
21
|
+
it 'should yield the Proxy module' do
|
22
|
+
AssetsInclude.helpers.is_a?(described_class).must_equal true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def proxy
|
29
|
+
described_class.tap do |p|
|
30
|
+
p.assets = AssetsInclude::Base.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def described_class
|
35
|
+
AssetsInclude::Proxy
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
.one,.two{color:red}
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'codeclimate-test-reporter'
|
2
|
+
CodeClimate::TestReporter.start
|
3
|
+
|
4
|
+
ENV['RACK_ENV'] = 'test'
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'bundler/setup'
|
8
|
+
Bundler.setup
|
9
|
+
Bundler.require(:default, :test)
|
10
|
+
|
11
|
+
gem 'minitest'
|
12
|
+
require 'minitest/autorun'
|
13
|
+
require 'flexmock'
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: assets_include
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jakub Pawlowicz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.7.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.7.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: flexmock
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.3.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.3.0
|
41
|
+
description: Include assets in your views with a single line of code.
|
42
|
+
email: jakub.pawlowicz@goalsmashers.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- .travis.yml
|
48
|
+
- Gemfile
|
49
|
+
- History.md
|
50
|
+
- LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- assets_include.gemspec
|
54
|
+
- examples/sinatra/Gemfile
|
55
|
+
- examples/sinatra/Gemfile.lock
|
56
|
+
- examples/sinatra/README.md
|
57
|
+
- examples/sinatra/app.rb
|
58
|
+
- examples/sinatra/assets.yml
|
59
|
+
- examples/sinatra/package.json
|
60
|
+
- examples/sinatra/public/javascripts/inline.js
|
61
|
+
- examples/sinatra/public/javascripts/main.js
|
62
|
+
- examples/sinatra/public/javascripts/vendor/hex-rgb.src.js
|
63
|
+
- examples/sinatra/public/javascripts/vendor/microajax.js
|
64
|
+
- examples/sinatra/public/stylesheets/base.css
|
65
|
+
- examples/sinatra/public/stylesheets/normalize.css
|
66
|
+
- lib/assets_include.rb
|
67
|
+
- lib/assets_include/base.rb
|
68
|
+
- lib/assets_include/cache.rb
|
69
|
+
- lib/assets_include/proxy.rb
|
70
|
+
- lib/assets_include/version.rb
|
71
|
+
- test/assets_include/base_test.rb
|
72
|
+
- test/assets_include/cache_test.rb
|
73
|
+
- test/assets_include/proxy_test.rb
|
74
|
+
- test/fixtures/assets.yml
|
75
|
+
- test/fixtures/package.json
|
76
|
+
- test/fixtures/public/stylesheets/bundled/all.css
|
77
|
+
- test/fixtures/public/stylesheets/one.css
|
78
|
+
- test/fixtures/public/stylesheets/two.css
|
79
|
+
- test/test_helper.rb
|
80
|
+
homepage: https://github.com/GoalSmashers/assets-include-ruby
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.0.3
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Ruby bindings for assets-include node.js library.
|
104
|
+
test_files: []
|