cat_herder 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/MIT-LICENSE +20 -0
- data/README.md +78 -0
- data/Rakefile +13 -0
- data/lib/cat_herder.rb +15 -0
- data/lib/cat_herder/asset_not_found.rb +9 -0
- data/lib/cat_herder/asset_not_public.rb +9 -0
- data/lib/cat_herder/assets.rb +84 -0
- data/lib/cat_herder/assets/asset.rb +89 -0
- data/lib/cat_herder/assets/erb_asset.rb +68 -0
- data/lib/cat_herder/assets/verbatim_asset.rb +23 -0
- data/lib/cat_herder/current.rb +19 -0
- data/lib/cat_herder/helper.rb +9 -0
- data/lib/cat_herder/railtie.rb +38 -0
- data/lib/cat_herder/version.rb +3 -0
- data/lib/tasks/cat_herder_tasks.rake +8 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 479a2393cf3c34ee5fca8210d9e642232ab012b6475a5204811e913cfbb9a4df
|
4
|
+
data.tar.gz: 461262ce3786120921eadfb1b082a4e494a6aacf7bb5806e0b569c3dbfd0c47b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d44bbb630714a52bbed16ed50f5c107e50212ddadcc28d830acd50864ae68c64cf320140fc1103c5ccd7c90ece4acf083c786f5279ac0a478a17377ce15e0d89
|
7
|
+
data.tar.gz: cda8936e2835e4e8635317da66c5611ff745799c02e91ac6c150e7dc85d835c3425b1ecfb3b5e8c23228b815fcc358cf00169a83bd8d55dde230e58b9268c973
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2021 Jonathan Hefner
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# cat_herder
|
2
|
+
|
3
|
+
Minimal Rails asset pipeline experiment:
|
4
|
+
|
5
|
+
* Assets are fingerprinted and copied to `public/assets` in development, just
|
6
|
+
like `rails assets:precompile`. Thus they are served directly, without any
|
7
|
+
special routes or middleware.
|
8
|
+
|
9
|
+
* ERB assets are evaluated; all other assets are copied verbatim.
|
10
|
+
|
11
|
+
* ERB assets can call `asset_path` and all other [`AssetUrlHelper`][] helpers.
|
12
|
+
|
13
|
+
* Currently, `*_url` helpers always return a path instead of a full URL (the
|
14
|
+
same as `*_path` helpers). Assuming these helpers are primarily used for
|
15
|
+
import statements (e.g. `@import url(...)`), this shouldn't pose a problem,
|
16
|
+
because the browser resolves such partial URLs to the asset host rather than
|
17
|
+
the page host. The benefit of the current implementation is that it
|
18
|
+
sidesteps the issue of cache invalidation when `config.asset_host` changes.
|
19
|
+
|
20
|
+
* ERB assets can call `render` to render the content of another asset inline.
|
21
|
+
|
22
|
+
* ERB assets can call `glob` to iterate over other assets. Using a given
|
23
|
+
pattern, `glob` will search all load paths. With a combination of `glob` and
|
24
|
+
`render`, assets can perform their own bundling.
|
25
|
+
|
26
|
+
* ERB assets can call `resolve` to get an absolute path to an asset file. This
|
27
|
+
can be used to pass the asset to an external command, e.g.:
|
28
|
+
|
29
|
+
```erb
|
30
|
+
<%# styles.css.erb %>
|
31
|
+
<%= `sass #{resolve "styles.sass"}` %>
|
32
|
+
```
|
33
|
+
|
34
|
+
* All calls to `asset_path` / `compute_asset_path`, `render`, and `resolve` will
|
35
|
+
add the resulting asset to the current asset's dependencies, so that the
|
36
|
+
current asset will be recompiled when any of its dependencies are.
|
37
|
+
|
38
|
+
* Partial assets are prefixed with an underscore (like view partials), and are
|
39
|
+
not copied to `public/assets` by `rails assets:precompile`. They can be
|
40
|
+
referenced using their logical path without the underscore (like view
|
41
|
+
partials). This allows "private" files, such as raw input files or config
|
42
|
+
files, to be placed in any of the asset load paths and be evaluated like other
|
43
|
+
assets. (Calls to `compute_asset_path` that resolve to a partial asset will
|
44
|
+
raise an error to prevent broken URLs.)
|
45
|
+
|
46
|
+
[`AssetUrlHelper`]: https://api.rubyonrails.org/classes/ActionView/Helpers/AssetUrlHelper.html
|
47
|
+
|
48
|
+
|
49
|
+
## Installation
|
50
|
+
|
51
|
+
Add this line to your application's Gemfile:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
gem "cat_herder"
|
55
|
+
```
|
56
|
+
|
57
|
+
And run:
|
58
|
+
|
59
|
+
```bash
|
60
|
+
$ bundle install
|
61
|
+
```
|
62
|
+
|
63
|
+
Then disable Sprockets, and require *cat_herder* in your `config/application.rb`
|
64
|
+
file:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
require "cat_herder/railtie"
|
68
|
+
```
|
69
|
+
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
Run `bin/test` to run the tests.
|
74
|
+
|
75
|
+
|
76
|
+
## License
|
77
|
+
|
78
|
+
[MIT License](MIT-LICENSE)
|
data/Rakefile
ADDED
data/lib/cat_herder.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cat_herder/version"
|
4
|
+
|
5
|
+
module CatHerder
|
6
|
+
extend ActiveSupport::Autoload
|
7
|
+
|
8
|
+
autoload :AssetNotFound
|
9
|
+
autoload :AssetNotPublic
|
10
|
+
autoload :Assets
|
11
|
+
autoload :Current
|
12
|
+
autoload :Helper
|
13
|
+
|
14
|
+
EMPTY_ARRAY = [].freeze
|
15
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "active_support/core_ext/enumerable"
|
5
|
+
|
6
|
+
module CatHerder
|
7
|
+
module Assets
|
8
|
+
extend ActiveSupport::Autoload
|
9
|
+
|
10
|
+
autoload :ErbAsset
|
11
|
+
autoload :VerbatimAsset
|
12
|
+
|
13
|
+
mattr_accessor :load_paths, default: []
|
14
|
+
mattr_accessor :public_subpath, default: "assets"
|
15
|
+
mattr_accessor :cache_store
|
16
|
+
mattr_accessor :precompiled, default: false
|
17
|
+
singleton_class.alias_method :precompiled?, :precompiled
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def cache
|
21
|
+
@cache ||= ActiveSupport::Cache.lookup_store(*cache_store)
|
22
|
+
end
|
23
|
+
|
24
|
+
def public_path
|
25
|
+
@public_path ||= Rails.public_path.join(public_subpath)
|
26
|
+
end
|
27
|
+
|
28
|
+
def public_files
|
29
|
+
public_path.glob("**/*").select(&:file?)
|
30
|
+
end
|
31
|
+
|
32
|
+
def public_file_logical_path(public_file)
|
33
|
+
public_file.dirname.relative_path_from(public_path).to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def resolve_logical_path(logical_path)
|
37
|
+
Current.resolved_paths[logical_path] ||= begin
|
38
|
+
logical_dirname, logical_basename = File.split(logical_path)
|
39
|
+
basename_pattern = /\A_?#{Regexp.escape logical_basename}(?:\.erb)?\z/
|
40
|
+
load_paths.find do |load_path|
|
41
|
+
dirname = File.expand_path(logical_dirname, load_path)
|
42
|
+
basename = Current.dir_children(dirname).find { |name| basename_pattern.match?(name) }
|
43
|
+
break File.join(dirname, basename) if basename
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def [](logical_path)
|
49
|
+
source_path = resolve_logical_path(logical_path) or raise AssetNotFound, logical_path
|
50
|
+
(@assets ||= {})[source_path] ||= (source_path.end_with?(".erb") ? ErbAsset : VerbatimAsset).new(logical_path, source_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def glob(*logical_patterns, &block)
|
54
|
+
logical_patterns.map! { |pattern| "#{pattern}{,.erb}" }
|
55
|
+
load_paths.flat_map { |load_path| Dir.glob(*logical_patterns, base: load_path) }.
|
56
|
+
each { |path| path.sub!(%r"_?([^/]+?)(?:\.erb)?\z", '\1') }.uniq.
|
57
|
+
tap { |logical_paths| logical_paths.each(&block) if block }
|
58
|
+
end
|
59
|
+
|
60
|
+
def precompile
|
61
|
+
public_path.rmtree if public_path.exist?
|
62
|
+
glob("**/[^_]*") { |logical_path| self[logical_path].compile }
|
63
|
+
@assets&.each_value { |asset| asset.public_file.dirname.rmtree if asset.partial? && asset.public_file.exist? }
|
64
|
+
cache.clear
|
65
|
+
end
|
66
|
+
|
67
|
+
def precompiled_asset_paths
|
68
|
+
@precompiled_asset_paths ||= public_files.index_by { |file| public_file_logical_path(file) }.
|
69
|
+
transform_values! { |file| "/#{file.relative_path_from(Rails.public_path)}" }
|
70
|
+
end
|
71
|
+
|
72
|
+
def precompiled_asset_path(logical_path)
|
73
|
+
precompiled_asset_paths[logical_path] or raise AssetNotFound, logical_path
|
74
|
+
end
|
75
|
+
|
76
|
+
def clean
|
77
|
+
public_files.each do |file|
|
78
|
+
logical_path = public_file_logical_path(file)
|
79
|
+
file.delete unless resolve_logical_path(logical_path) && file == self[logical_path].public_file
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CatHerder
|
4
|
+
module Assets
|
5
|
+
class Asset
|
6
|
+
attr_reader :logical_path, :source_path, :partial
|
7
|
+
alias :partial? :partial
|
8
|
+
|
9
|
+
def initialize(logical_path, source_path)
|
10
|
+
@logical_path = logical_path
|
11
|
+
@source_path = source_path
|
12
|
+
@partial = File.basename(source_path).start_with?("_")
|
13
|
+
@metadata = Assets.cache.read([self, "metadata"]) || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def cache_key
|
17
|
+
source_path.delete_prefix(Rails.root.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def digest_class
|
21
|
+
ActiveSupport::Digest.hash_digest_class
|
22
|
+
end
|
23
|
+
|
24
|
+
def digest
|
25
|
+
@metadata[:digest]
|
26
|
+
end
|
27
|
+
|
28
|
+
def dependencies
|
29
|
+
@metadata[:dependencies]&.map { |logical_path| Assets[logical_path] } || EMPTY_ARRAY
|
30
|
+
end
|
31
|
+
|
32
|
+
def dependency_digests
|
33
|
+
@metadata[:dependency_digests] || EMPTY_ARRAY
|
34
|
+
end
|
35
|
+
|
36
|
+
def mtime
|
37
|
+
@metadata[:mtime] || Float::NAN
|
38
|
+
end
|
39
|
+
|
40
|
+
def source_mtime
|
41
|
+
Current.mtime(source_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
def stale?
|
45
|
+
mtime != source_mtime || dependency_digests != dependencies.map(&:digest) || dependencies.any?(&:stale?)
|
46
|
+
end
|
47
|
+
|
48
|
+
def public_subpath
|
49
|
+
File.join(Assets.public_subpath, logical_path, "#{digest}#{File.extname(logical_path)}")
|
50
|
+
end
|
51
|
+
|
52
|
+
def public_file
|
53
|
+
Rails.public_path.join(public_subpath)
|
54
|
+
end
|
55
|
+
|
56
|
+
def written?
|
57
|
+
Current.mtime(public_file.to_s) > 0
|
58
|
+
end
|
59
|
+
|
60
|
+
def compile
|
61
|
+
write if !written? || stale?
|
62
|
+
end
|
63
|
+
|
64
|
+
def write_metadata(digest:, dependencies: nil)
|
65
|
+
@metadata = {
|
66
|
+
mtime: source_mtime,
|
67
|
+
digest: digest,
|
68
|
+
dependencies: dependencies&.map(&:logical_path),
|
69
|
+
dependency_digests: dependencies&.map(&:digest),
|
70
|
+
}
|
71
|
+
Assets.cache.write([self, "metadata"], @metadata)
|
72
|
+
end
|
73
|
+
|
74
|
+
def asset_path
|
75
|
+
raise AssetNotPublic, self if partial?
|
76
|
+
compile
|
77
|
+
File.join("/", public_subpath)
|
78
|
+
end
|
79
|
+
|
80
|
+
def render
|
81
|
+
compile
|
82
|
+
read
|
83
|
+
end
|
84
|
+
|
85
|
+
def write; raise NotImplementedError; end
|
86
|
+
def read; raise NotImplementedError; end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_view/helpers/asset_url_helper"
|
4
|
+
require "cat_herder/assets/asset"
|
5
|
+
|
6
|
+
module CatHerder
|
7
|
+
module Assets
|
8
|
+
class ErbAsset < Asset
|
9
|
+
def write
|
10
|
+
result, dependencies = evaluate_erb
|
11
|
+
write_metadata(digest: digest_class.hexdigest(result), dependencies: dependencies)
|
12
|
+
public_file.tap { |file| file.dirname.mkpath }.write(result)
|
13
|
+
end
|
14
|
+
|
15
|
+
def read
|
16
|
+
public_file.read
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def evaluate_erb
|
21
|
+
ruby = Assets.cache.fetch([self, "ruby"], version: source_mtime) do
|
22
|
+
require "erubi"
|
23
|
+
Erubi::Engine.new(File.read(source_path), filename: source_path).src
|
24
|
+
end
|
25
|
+
context = ErbContext.new(logical_path)
|
26
|
+
[context.instance_eval(ruby), context._dependencies]
|
27
|
+
end
|
28
|
+
|
29
|
+
class ErbContext
|
30
|
+
include ActionView::Helpers::AssetUrlHelper
|
31
|
+
|
32
|
+
attr_reader :_dependencies
|
33
|
+
|
34
|
+
def initialize(logical_path)
|
35
|
+
@_logical_path = logical_path
|
36
|
+
@_dependencies = []
|
37
|
+
end
|
38
|
+
|
39
|
+
def compute_asset_path(logical_path, *)
|
40
|
+
_dependency(logical_path).asset_path
|
41
|
+
end
|
42
|
+
|
43
|
+
def resolve(logical_path)
|
44
|
+
_dependency(logical_path).source_path
|
45
|
+
end
|
46
|
+
|
47
|
+
def render(logical_path)
|
48
|
+
_dependency(logical_path).render
|
49
|
+
end
|
50
|
+
|
51
|
+
def glob(*logical_patterns, &block)
|
52
|
+
Assets.glob(*logical_patterns.map { |pattern| _expand_logical_path(pattern) }, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def _dependency(logical_path)
|
57
|
+
dependency = Assets[_expand_logical_path(logical_path)]
|
58
|
+
@_dependencies << dependency unless @_dependencies.include?(dependency)
|
59
|
+
dependency
|
60
|
+
end
|
61
|
+
|
62
|
+
def _expand_logical_path(logical_path)
|
63
|
+
logical_path.start_with?("./", "../") ? Pathname(@_logical_path).dirname.join(logical_path).to_s : logical_path
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "cat_herder/assets/asset"
|
5
|
+
|
6
|
+
module CatHerder
|
7
|
+
module Assets
|
8
|
+
class VerbatimAsset < Asset
|
9
|
+
def write
|
10
|
+
write_metadata(digest: digest_class.file(source_path).hexdigest)
|
11
|
+
FileUtils.cp(source_path, public_file.tap { |file| file.dirname.mkpath }) unless partial?
|
12
|
+
end
|
13
|
+
|
14
|
+
def written?
|
15
|
+
partial? || super
|
16
|
+
end
|
17
|
+
|
18
|
+
def read
|
19
|
+
File.read(source_path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CatHerder
|
4
|
+
class Current < ActiveSupport::CurrentAttributes
|
5
|
+
attribute :resolved_paths, :mtime_cache, :dir_children_cache
|
6
|
+
|
7
|
+
def resolved_paths
|
8
|
+
super || (self.resolved_paths = {})
|
9
|
+
end
|
10
|
+
|
11
|
+
def mtime(path)
|
12
|
+
(self.mtime_cache ||= {})[path] ||= File.file?(path) ? File.mtime(path).to_f : Float::NAN
|
13
|
+
end
|
14
|
+
|
15
|
+
def dir_children(path)
|
16
|
+
(self.dir_children_cache ||= {})[path] ||= File.directory?(path) ? Dir.children(path) : EMPTY_ARRAY
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
require "cat_herder"
|
5
|
+
|
6
|
+
module CatHerder
|
7
|
+
class Railtie < ::Rails::Railtie
|
8
|
+
config.assets = ActiveSupport::OrderedOptions.new
|
9
|
+
|
10
|
+
initializer "assets.configure" do |app|
|
11
|
+
Assets.load_paths = [
|
12
|
+
*app.paths["app/assets"].existent_directories,
|
13
|
+
*app.paths["lib/assets"].existent_directories,
|
14
|
+
*app.paths["vendor/assets"].existent_directories,
|
15
|
+
*app.config.assets.paths,
|
16
|
+
]
|
17
|
+
Assets.public_subpath = app.config.assets.prefix.delete_prefix("/") if app.config.assets.prefix
|
18
|
+
Assets.cache_store = app.config.assets.cache_store || [:file_store, app.root.join("tmp/assets.cache")]
|
19
|
+
Assets.precompiled = app.config.assets.compile == false
|
20
|
+
end
|
21
|
+
|
22
|
+
server do
|
23
|
+
if Assets.precompiled?
|
24
|
+
Assets.precompiled_asset_paths # warm up
|
25
|
+
else
|
26
|
+
Assets.clean
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ActiveSupport.on_load(:action_view) do
|
31
|
+
include Helper
|
32
|
+
end
|
33
|
+
|
34
|
+
rake_tasks do
|
35
|
+
load "tasks/cat_herder_tasks.rake"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cat_herder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jonathan Hefner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-03-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.1'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
- jonathan@hefner.pro
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- MIT-LICENSE
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- lib/cat_herder.rb
|
38
|
+
- lib/cat_herder/asset_not_found.rb
|
39
|
+
- lib/cat_herder/asset_not_public.rb
|
40
|
+
- lib/cat_herder/assets.rb
|
41
|
+
- lib/cat_herder/assets/asset.rb
|
42
|
+
- lib/cat_herder/assets/erb_asset.rb
|
43
|
+
- lib/cat_herder/assets/verbatim_asset.rb
|
44
|
+
- lib/cat_herder/current.rb
|
45
|
+
- lib/cat_herder/helper.rb
|
46
|
+
- lib/cat_herder/railtie.rb
|
47
|
+
- lib/cat_herder/version.rb
|
48
|
+
- lib/tasks/cat_herder_tasks.rake
|
49
|
+
homepage: https://github.com/jonathanhefner/cat_herder
|
50
|
+
licenses:
|
51
|
+
- MIT
|
52
|
+
metadata:
|
53
|
+
homepage_uri: https://github.com/jonathanhefner/cat_herder
|
54
|
+
source_code_uri: https://github.com/jonathanhefner/cat_herder
|
55
|
+
changelog_uri: https://github.com/jonathanhefner/cat_herder/blob/master/CHANGELOG.md
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubygems_version: 3.1.4
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: Minimal Rails asset pipeline experiment
|
75
|
+
test_files: []
|