gumbo 0.0.1
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.
- data/.gitignore +19 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +53 -0
- data/Rakefile +2 -0
- data/TODO +3 -0
- data/bin/gumbo +5 -0
- data/examples/multiple/assets/css/bar.css +3 -0
- data/examples/multiple/assets/css/foo.css +3 -0
- data/examples/multiple/assets/index.html.liquid +9 -0
- data/examples/multiple/assets/js/bar.coffee +1 -0
- data/examples/multiple/assets/js/foo.coffee +1 -0
- data/examples/multiple/assets/js/templates/home.eco +1 -0
- data/examples/multiple/assets/packages.yml +13 -0
- data/examples/todo/Guardfile +5 -0
- data/examples/todo/assets/css/reset.css +48 -0
- data/examples/todo/assets/css/style.css +7 -0
- data/examples/todo/assets/index.html.liquid +20 -0
- data/examples/todo/assets/js/templates/todo.eco +1 -0
- data/examples/todo/assets/js/todo.coffee +7 -0
- data/examples/todo/assets/packages.yml +9 -0
- data/gumbo.gemspec +21 -0
- data/lib/gumbo.rb +13 -0
- data/lib/gumbo/asset_builder.rb +169 -0
- data/lib/gumbo/asset_file.rb +70 -0
- data/lib/gumbo/asset_package.rb +71 -0
- data/lib/gumbo/cli.rb +49 -0
- data/lib/gumbo/coffee_script_file.rb +8 -0
- data/lib/gumbo/compile_to_java_script_file.rb +35 -0
- data/lib/gumbo/eco_file.rb +11 -0
- data/lib/gumbo/java_script_file.rb +5 -0
- data/lib/gumbo/liquid_file.rb +31 -0
- data/lib/gumbo/logger.rb +17 -0
- data/lib/gumbo/package_file.rb +22 -0
- data/lib/gumbo/style_sheet_file.rb +5 -0
- data/lib/gumbo/template_file.rb +26 -0
- metadata +138 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.3@gumbo --create
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Paul Barry
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Gumbo
|
2
|
+
|
3
|
+
Gumbo is a standalone asset packager for creating HTML files that link to a single CSS and single JS file, which includes an MD5 in the file name to make the asset package files cacheable for indefinite amounts of time.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'gumbo'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install gumbo
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
To see an example of how this works, look at `examples/todo`. To build the assets, in that directory, run:
|
22
|
+
|
23
|
+
$ gumbo
|
24
|
+
|
25
|
+
To make changes and have them automatically built, you can install `guard-shell` and run:
|
26
|
+
|
27
|
+
$ guard
|
28
|
+
|
29
|
+
The way is works is that you put your assets in the `assets` directory. In the `assets` directory, there is a `packages.yml` file that looks like:
|
30
|
+
|
31
|
+
js:
|
32
|
+
todo:
|
33
|
+
- todo.coffee
|
34
|
+
- templates/todo.eco
|
35
|
+
|
36
|
+
css:
|
37
|
+
todo:
|
38
|
+
- reset.css
|
39
|
+
- style.css
|
40
|
+
|
41
|
+
What this means is that there is one js package called todo and one css package called todo. When the assets are built, they will be put into a directory called `public` along side `assets`.
|
42
|
+
|
43
|
+
Static HTML files can be generated from dynamic content using the [Liquid][liquid] templating language. In this example, the names of the asset packages with an MD5 timestamp of the contents are included in the resulting HTML file that is created in the `public` directory.
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create new Pull Request
|
52
|
+
|
53
|
+
[liquid]: http://liquidmarkup.org/
|
data/Rakefile
ADDED
data/TODO
ADDED
data/bin/gumbo
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
bar = -> "bar!"
|
@@ -0,0 +1 @@
|
|
1
|
+
foo = -> "foo"
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1><%= @title %></h1>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
/* http://meyerweb.com/eric/tools/css/reset/
|
2
|
+
v2.0 | 20110126
|
3
|
+
License: none (public domain)
|
4
|
+
*/
|
5
|
+
|
6
|
+
html, body, div, span, applet, object, iframe,
|
7
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
8
|
+
a, abbr, acronym, address, big, cite, code,
|
9
|
+
del, dfn, em, img, ins, kbd, q, s, samp,
|
10
|
+
small, strike, strong, sub, sup, tt, var,
|
11
|
+
b, u, i, center,
|
12
|
+
dl, dt, dd, ol, ul, li,
|
13
|
+
fieldset, form, label, legend,
|
14
|
+
table, caption, tbody, tfoot, thead, tr, th, td,
|
15
|
+
article, aside, canvas, details, embed,
|
16
|
+
figure, figcaption, footer, header, hgroup,
|
17
|
+
menu, nav, output, ruby, section, summary,
|
18
|
+
time, mark, audio, video {
|
19
|
+
margin: 0;
|
20
|
+
padding: 0;
|
21
|
+
border: 0;
|
22
|
+
font-size: 100%;
|
23
|
+
font: inherit;
|
24
|
+
vertical-align: baseline;
|
25
|
+
}
|
26
|
+
/* HTML5 display-role reset for older browsers */
|
27
|
+
article, aside, details, figcaption, figure,
|
28
|
+
footer, header, hgroup, menu, nav, section {
|
29
|
+
display: block;
|
30
|
+
}
|
31
|
+
body {
|
32
|
+
line-height: 1;
|
33
|
+
}
|
34
|
+
ol, ul {
|
35
|
+
list-style: none;
|
36
|
+
}
|
37
|
+
blockquote, q {
|
38
|
+
quotes: none;
|
39
|
+
}
|
40
|
+
blockquote:before, blockquote:after,
|
41
|
+
q:before, q:after {
|
42
|
+
content: '';
|
43
|
+
content: none;
|
44
|
+
}
|
45
|
+
table {
|
46
|
+
border-collapse: collapse;
|
47
|
+
border-spacing: 0;
|
48
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Todo</title>
|
5
|
+
<link rel="stylesheet" type="text/css" href="{% asset_package todo.css %}" />
|
6
|
+
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.js"></script>
|
7
|
+
<script type="text/javascript" src="{% asset_package todo.js %}"></script>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<div id="container">
|
11
|
+
<h1>Todo</h1>
|
12
|
+
<form id="add-todo">
|
13
|
+
<label for="todo">Todo</label>
|
14
|
+
<input id="todo" type="text" name="todo" size="50"/>
|
15
|
+
<button type="submit">Add</button>
|
16
|
+
</form>
|
17
|
+
<ul id="todos"></ul>
|
18
|
+
</div>
|
19
|
+
</body>
|
20
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<li><%= @name %></li>
|
data/gumbo.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |gem|
|
3
|
+
gem.authors = ["Paul Barry"]
|
4
|
+
gem.email = ["mail@paulbarry.com"]
|
5
|
+
gem.description = %q{A standalone asset packager}
|
6
|
+
gem.summary = %q{A standalone asset packager}
|
7
|
+
gem.homepage = "http://github.com/pjb3/gumbo"
|
8
|
+
|
9
|
+
gem.files = `git ls-files`.split($\)
|
10
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
11
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
12
|
+
gem.name = "gumbo"
|
13
|
+
gem.require_paths = ["lib"]
|
14
|
+
gem.version = "0.0.1"
|
15
|
+
|
16
|
+
gem.add_runtime_dependency "coffee-script", "~> 2.2.0"
|
17
|
+
gem.add_runtime_dependency "cssmin"
|
18
|
+
gem.add_runtime_dependency "eco"
|
19
|
+
gem.add_runtime_dependency "liquid", "~> 2.4.1"
|
20
|
+
gem.add_runtime_dependency "uglifier"
|
21
|
+
end
|
data/lib/gumbo.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "gumbo/logger"
|
2
|
+
require "gumbo/asset_builder"
|
3
|
+
require "gumbo/asset_file"
|
4
|
+
require "gumbo/asset_package"
|
5
|
+
require "gumbo/package_file"
|
6
|
+
require "gumbo/java_script_file"
|
7
|
+
require "gumbo/style_sheet_file"
|
8
|
+
require "gumbo/compile_to_java_script_file"
|
9
|
+
require "gumbo/coffee_script_file"
|
10
|
+
require "gumbo/eco_file"
|
11
|
+
require "gumbo/template_file"
|
12
|
+
require "gumbo/liquid_file"
|
13
|
+
require "gumbo/cli"
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'json'
|
3
|
+
require 'set'
|
4
|
+
require 'time'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module Gumbo
|
8
|
+
class AssetBuilder
|
9
|
+
DEFAULT_SOURCE_DIR = "assets"
|
10
|
+
DEFAULT_OUTPUT_DIR = "public"
|
11
|
+
DEFAULT_PACKAGES_FILE = "packages.yml"
|
12
|
+
DEFAULT_MANIFEST_FILE = "packages.json"
|
13
|
+
|
14
|
+
attr_accessor :source_dir, :output_dir, :packages_file, :manifest_file, :clean
|
15
|
+
|
16
|
+
def self.build(attrs={})
|
17
|
+
new(attrs).build
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(attrs={})
|
21
|
+
self.clean = !!attrs[:clean]
|
22
|
+
self.source_dir = attrs.fetch(:source_dir, DEFAULT_SOURCE_DIR)
|
23
|
+
self.output_dir = attrs.fetch(:output_dir, DEFAULT_OUTPUT_DIR)
|
24
|
+
self.packages_file = File.join(source_dir, attrs.fetch(:packages_file, DEFAULT_PACKAGES_FILE))
|
25
|
+
self.manifest_file = File.join(output_dir, attrs.fetch(:manifest_file, DEFAULT_MANIFEST_FILE))
|
26
|
+
end
|
27
|
+
|
28
|
+
def build
|
29
|
+
clean_output_dir if clean
|
30
|
+
create_output_dir
|
31
|
+
build_package_files
|
32
|
+
build_packages
|
33
|
+
build_non_package_files
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def clean_output_dir
|
39
|
+
FileUtils.rm_r(output_dir) if File.exists?(output_dir)
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_output_dir
|
43
|
+
FileUtils.mkdir_p(output_dir)
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_package_files
|
47
|
+
file_packages.each do |file, packages|
|
48
|
+
package_files << file.source_file
|
49
|
+
if file.should_be_rebuilt?
|
50
|
+
file.build
|
51
|
+
packages.each{|p| packages_to_rebuild << p }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_packages
|
57
|
+
unless packages_to_rebuild.empty?
|
58
|
+
packages_to_rebuild.each do |package|
|
59
|
+
package.build
|
60
|
+
asset_packages[package.type] ||= {}
|
61
|
+
asset_packages[package.type][package.name] = package.file_name
|
62
|
+
end
|
63
|
+
|
64
|
+
new_manifest = File.exists?(manifest_file)
|
65
|
+
open(manifest_file, "w") do |f|
|
66
|
+
f << JSON.pretty_generate(asset_packages)
|
67
|
+
logger.info "#{new_manifest ? 'Created' : 'Updated'} #{manifest_file}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def build_non_package_files
|
73
|
+
Dir["#{source_dir}/**/*"].each do |file|
|
74
|
+
unless File.directory?(file) || file == packages_file || package_files.include?(file)
|
75
|
+
asset_file = AssetFile.for(
|
76
|
+
:name => file.sub(/^#{source_dir}\//, ''),
|
77
|
+
:source_dir => source_dir,
|
78
|
+
:output_dir => output_dir,
|
79
|
+
:context => {
|
80
|
+
"asset_packages" => asset_packages
|
81
|
+
})
|
82
|
+
if !packages_to_rebuild.empty? || asset_file.should_be_rebuilt?
|
83
|
+
asset_file.build
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# A Set of AssetPackage objects which need to be rebuilt
|
90
|
+
def packages_to_rebuild
|
91
|
+
@packages_to_rebuild ||= Set.new
|
92
|
+
end
|
93
|
+
|
94
|
+
# A Set of file names of all files that are part of at least one package
|
95
|
+
def package_files
|
96
|
+
@package_files ||= Set.new
|
97
|
+
end
|
98
|
+
|
99
|
+
# A Hash of package types to Hashes of package names to package file
|
100
|
+
# Example:
|
101
|
+
# {
|
102
|
+
# "js" => {
|
103
|
+
# "foo" => "foo-cff07015305f5bc4ffc30a216a676df2.js"
|
104
|
+
# }
|
105
|
+
# }
|
106
|
+
def asset_packages
|
107
|
+
@asset_packages ||= if File.exists?(manifest_file)
|
108
|
+
parse_file(manifest_file)
|
109
|
+
else
|
110
|
+
{}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# The definition of which files are in each package
|
115
|
+
# as parsed from the packages_file
|
116
|
+
def package_definitions
|
117
|
+
@package_definitions ||= parse_file(packages_file)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Given a package_type and package_name, this will return
|
121
|
+
# the AssetPackage object representing those values,
|
122
|
+
# returning the same object on successive calls for the same
|
123
|
+
# package_type and package_name
|
124
|
+
def get_package_for(output_dir, package_type, package_name)
|
125
|
+
@packages ||= {}
|
126
|
+
@packages[package_type] ||= {}
|
127
|
+
@packages[package_type][package_name] ||= AssetPackage.new(
|
128
|
+
:output_dir => output_dir,
|
129
|
+
:type => package_type,
|
130
|
+
:name => package_name)
|
131
|
+
end
|
132
|
+
|
133
|
+
# A Hash of AssetFile to an Array of AssetPackage objects,
|
134
|
+
# representing the AssetPackages that an AssetFile belongs to
|
135
|
+
def file_packages
|
136
|
+
@file_packages ||= package_definitions.inject({}) do |file_packages, (package_type, package_definitions)|
|
137
|
+
package_definitions.each do |package_name, file_names|
|
138
|
+
package = get_package_for(output_dir, package_type, package_name)
|
139
|
+
file_names.each do |file_name|
|
140
|
+
file = PackageFile.for(
|
141
|
+
:source_dir => source_dir,
|
142
|
+
:output_dir => output_dir,
|
143
|
+
:type => package_type,
|
144
|
+
:name => file_name)
|
145
|
+
file_packages[file] ||= []
|
146
|
+
file_packages[file] << package
|
147
|
+
package.files << file
|
148
|
+
end
|
149
|
+
end
|
150
|
+
file_packages
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def logger
|
157
|
+
Gumbo.logger
|
158
|
+
end
|
159
|
+
|
160
|
+
def parse_file(file)
|
161
|
+
case File.extname(file)
|
162
|
+
when '.yml', '.yaml' then YAML.load_file(file)
|
163
|
+
when '.json' then JSON.parse(File.read(file))
|
164
|
+
else raise "Unknown file type: #{file}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Gumbo
|
4
|
+
class AssetFile
|
5
|
+
attr_accessor :source_dir, :output_dir, :name, :context
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
def self.for(attrs={})
|
9
|
+
class_for(attrs[:name]).new(attrs)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.ext(*args)
|
13
|
+
@@extension_class_map ||= {}
|
14
|
+
if args.size == 1
|
15
|
+
@ext = args.first
|
16
|
+
@@extension_class_map[@ext] = self
|
17
|
+
end
|
18
|
+
@ext
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.class_for(name)
|
22
|
+
@@extension_class_map[File.extname(name)] || self
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(attrs={})
|
26
|
+
attrs.each do |k,v|
|
27
|
+
send("#{k}=", v)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def source_file
|
32
|
+
@source_file ||= File.join(source_dir, name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def output_file
|
36
|
+
@output_file ||= File.join(output_dir, name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def build
|
40
|
+
logger.info "#{source_file} -> #{output_file}"
|
41
|
+
mkdir_p File.dirname(output_file)
|
42
|
+
cp source_file, output_file
|
43
|
+
end
|
44
|
+
|
45
|
+
def replace_ext(path, ext)
|
46
|
+
parts = path.split('.')
|
47
|
+
parts.pop
|
48
|
+
parts << ext
|
49
|
+
parts.join('.')
|
50
|
+
end
|
51
|
+
|
52
|
+
def should_be_rebuilt?
|
53
|
+
!File.exists?(output_file) || File.mtime(source_file) > File.mtime(output_file)
|
54
|
+
end
|
55
|
+
|
56
|
+
def eql?(o)
|
57
|
+
o.is_a?(self.class) &&
|
58
|
+
o.name == name
|
59
|
+
end
|
60
|
+
alias == eql?
|
61
|
+
|
62
|
+
def hash
|
63
|
+
name.hash
|
64
|
+
end
|
65
|
+
|
66
|
+
def logger
|
67
|
+
Gumbo.logger
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'cssmin'
|
3
|
+
require 'uglifier'
|
4
|
+
|
5
|
+
module Gumbo
|
6
|
+
class AssetPackage
|
7
|
+
attr_accessor :output_dir, :type, :name, :files, :digest
|
8
|
+
|
9
|
+
def initialize(attrs={})
|
10
|
+
attrs.each do |k,v|
|
11
|
+
send("#{k}=", v)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def files
|
16
|
+
@files ||= Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def file_name
|
20
|
+
@file_name ||= "#{name}-#{digest}.#{type}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def output_file
|
24
|
+
@output_file ||= File.join(output_dir, file_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def build
|
28
|
+
out = ""
|
29
|
+
files.each do |file|
|
30
|
+
out << File.read(file.output_file)
|
31
|
+
out << "\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
out = compress(out)
|
35
|
+
|
36
|
+
self.digest = Digest::MD5.hexdigest(out)
|
37
|
+
|
38
|
+
open(output_file, 'w') do |f|
|
39
|
+
f << out
|
40
|
+
end
|
41
|
+
|
42
|
+
logger.info "Created package #{output_file}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def compress(out)
|
46
|
+
case type
|
47
|
+
when 'css'
|
48
|
+
CSSMin.minify(out)
|
49
|
+
when 'js'
|
50
|
+
Uglifier.compile(out, :mangle => true)
|
51
|
+
else
|
52
|
+
raise "Unknown package type '#{type}'"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def eql?(o)
|
57
|
+
o.is_a?(self.class) &&
|
58
|
+
o.type == type &&
|
59
|
+
o.name == name
|
60
|
+
end
|
61
|
+
alias == eql?
|
62
|
+
|
63
|
+
def hash
|
64
|
+
type.hash ^ name.hash
|
65
|
+
end
|
66
|
+
|
67
|
+
def logger
|
68
|
+
Gumbo.logger
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/gumbo/cli.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Gumbo
|
4
|
+
class CLI
|
5
|
+
|
6
|
+
attr_accessor :options
|
7
|
+
|
8
|
+
def self.run(args)
|
9
|
+
new(args).run
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(args)
|
13
|
+
@options = {}
|
14
|
+
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.banner = "Usage: gumbo [options]"
|
17
|
+
|
18
|
+
opts.on("-c", "--clean", "Delete the output directory before running") do |v|
|
19
|
+
@options[:clean] = v
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-h", "--help", "Display this message") do |h|
|
23
|
+
puts opts
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-s", "--source-dir [SOURCE_DIR]", "the source directory, defaults to '#{Gumbo::AssetBuilder::DEFAULT_SOURCE_DIR}'") do |v|
|
28
|
+
@options[:source_dir] = v
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-o", "--output-dir [OUTPUT_DIR]", "the output directory, defaults to '#{Gumbo::AssetBuilder::DEFAULT_OUTPUT_DIR}'") do |v|
|
32
|
+
@options[:output_dir] = v
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-p", "--packages-file [PACKAGES_FILE]", "the packages file, relative to the source directory, defaults to '#{Gumbo::AssetBuilder::DEFAULT_PACKAGES_FILE}'") do |v|
|
36
|
+
@options[:packages_file] = v
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-m", "--manifest-file [MANIFEST_FILE]", "the manifest file, relative to the output directory, defaults to '#{Gumbo::AssetBuilder::DEFAULT_MANIFEST_FILE}'") do |v|
|
40
|
+
@options[:manifest_file] = v
|
41
|
+
end
|
42
|
+
end.parse(args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def run
|
46
|
+
Gumbo::AssetBuilder.build(@options)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Gumbo
|
2
|
+
class CompileToJavaScriptFile < PackageFile
|
3
|
+
def output_file
|
4
|
+
@output_file ||= replace_ext(super, "js")
|
5
|
+
end
|
6
|
+
|
7
|
+
def build
|
8
|
+
logger.info "#{source_file} -> #{output_file}"
|
9
|
+
mkdir_p File.dirname(output_file)
|
10
|
+
open(output_file, 'w') do |out|
|
11
|
+
out << compile(File.read(source_file))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def compile(src)
|
16
|
+
self.class.compile(src)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.compile(src)
|
20
|
+
if compiler
|
21
|
+
compiler.compile(src)
|
22
|
+
else
|
23
|
+
raise "no compiler set for #{name}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.compiler(*args)
|
28
|
+
if args.empty?
|
29
|
+
@compiler
|
30
|
+
else
|
31
|
+
@compiler = args.first
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
|
3
|
+
module Gumbo
|
4
|
+
class LiquidFile < TemplateFile
|
5
|
+
ext ".liquid"
|
6
|
+
|
7
|
+
def parse(src)
|
8
|
+
@template = Liquid::Template.parse(src)
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(context)
|
12
|
+
@template.render(context)
|
13
|
+
end
|
14
|
+
|
15
|
+
class AssetPackageTag < Liquid::Tag
|
16
|
+
def initialize(tag_name, file_name, tokens)
|
17
|
+
super
|
18
|
+
@file_name = file_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(context)
|
22
|
+
parts = @file_name.split('.')
|
23
|
+
ext = parts.pop.strip
|
24
|
+
name = parts.join('.')
|
25
|
+
context["asset_packages"][ext][name]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Liquid::Template.register_tag("asset_package", AssetPackageTag)
|
30
|
+
end
|
31
|
+
end
|
data/lib/gumbo/logger.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Gumbo
|
4
|
+
def self.logger
|
5
|
+
@logger ||= begin
|
6
|
+
logger = Logger.new(STDOUT)
|
7
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
8
|
+
"#{msg}\n"
|
9
|
+
end
|
10
|
+
logger
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.logger=(logger)
|
15
|
+
@logger = logger
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gumbo
|
2
|
+
class PackageFile < AssetFile
|
3
|
+
attr_accessor :type
|
4
|
+
|
5
|
+
def source_file
|
6
|
+
@source_file ||= File.join(source_dir, type, name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def output_file
|
10
|
+
@output_file ||= File.join(output_dir, type, name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def eql?(o)
|
14
|
+
super && o.type == type
|
15
|
+
end
|
16
|
+
alias == eql?
|
17
|
+
|
18
|
+
def hash
|
19
|
+
super ^ type.hash
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Gumbo
|
2
|
+
class TemplateFile < AssetFile
|
3
|
+
|
4
|
+
def output_file
|
5
|
+
@output_file ||= super.sub(/\.liquid$/,'')
|
6
|
+
end
|
7
|
+
|
8
|
+
def build
|
9
|
+
logger.info "#{source_file} -> #{output_file}"
|
10
|
+
mkdir_p File.dirname(output_file)
|
11
|
+
open(output_file, 'w') do |out|
|
12
|
+
parse(File.read(source_file))
|
13
|
+
out << render(context)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse(src)
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(context)
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gumbo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul Barry
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: coffee-script
|
16
|
+
requirement: &70252106829220 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.2.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70252106829220
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: cssmin
|
27
|
+
requirement: &70252106828820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70252106828820
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: eco
|
38
|
+
requirement: &70252106828360 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70252106828360
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: liquid
|
49
|
+
requirement: &70252106827860 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.4.1
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70252106827860
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: uglifier
|
60
|
+
requirement: &70252106827440 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70252106827440
|
69
|
+
description: A standalone asset packager
|
70
|
+
email:
|
71
|
+
- mail@paulbarry.com
|
72
|
+
executables:
|
73
|
+
- gumbo
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- .rvmrc
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- TODO
|
84
|
+
- bin/gumbo
|
85
|
+
- examples/multiple/assets/css/bar.css
|
86
|
+
- examples/multiple/assets/css/foo.css
|
87
|
+
- examples/multiple/assets/index.html.liquid
|
88
|
+
- examples/multiple/assets/js/bar.coffee
|
89
|
+
- examples/multiple/assets/js/foo.coffee
|
90
|
+
- examples/multiple/assets/js/templates/home.eco
|
91
|
+
- examples/multiple/assets/packages.yml
|
92
|
+
- examples/todo/Guardfile
|
93
|
+
- examples/todo/assets/css/reset.css
|
94
|
+
- examples/todo/assets/css/style.css
|
95
|
+
- examples/todo/assets/index.html.liquid
|
96
|
+
- examples/todo/assets/js/templates/todo.eco
|
97
|
+
- examples/todo/assets/js/todo.coffee
|
98
|
+
- examples/todo/assets/packages.yml
|
99
|
+
- gumbo.gemspec
|
100
|
+
- lib/gumbo.rb
|
101
|
+
- lib/gumbo/asset_builder.rb
|
102
|
+
- lib/gumbo/asset_file.rb
|
103
|
+
- lib/gumbo/asset_package.rb
|
104
|
+
- lib/gumbo/cli.rb
|
105
|
+
- lib/gumbo/coffee_script_file.rb
|
106
|
+
- lib/gumbo/compile_to_java_script_file.rb
|
107
|
+
- lib/gumbo/eco_file.rb
|
108
|
+
- lib/gumbo/java_script_file.rb
|
109
|
+
- lib/gumbo/liquid_file.rb
|
110
|
+
- lib/gumbo/logger.rb
|
111
|
+
- lib/gumbo/package_file.rb
|
112
|
+
- lib/gumbo/style_sheet_file.rb
|
113
|
+
- lib/gumbo/template_file.rb
|
114
|
+
homepage: http://github.com/pjb3/gumbo
|
115
|
+
licenses: []
|
116
|
+
post_install_message:
|
117
|
+
rdoc_options: []
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 1.8.17
|
135
|
+
signing_key:
|
136
|
+
specification_version: 3
|
137
|
+
summary: A standalone asset packager
|
138
|
+
test_files: []
|