gumbo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ *.swp
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ examples/**/public
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.3@gumbo --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gumbo.gemspec
4
+ gemspec
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.
@@ -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/
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/TODO ADDED
@@ -0,0 +1,3 @@
1
+ * non-css, non-js
2
+ * liquid rendering
3
+ * write the asset_manifest.json to the public dir
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "gumbo"
4
+
5
+ Gumbo::CLI.run(ARGV)
@@ -0,0 +1,3 @@
1
+ body {
2
+ margin: 10px auto;
3
+ }
@@ -0,0 +1,3 @@
1
+ p {
2
+ padding: 10px 0;
3
+ }
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <title>Gumbo</title>
4
+ <script type="text/javascript" src="{% asset_package "application.js" %}"></script>
5
+ </head>
6
+ <body>
7
+ <h1>Gumbo</h1>
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ bar = -> "bar!"
@@ -0,0 +1 @@
1
+ foo = -> "foo"
@@ -0,0 +1 @@
1
+ <h1><%= @title %></h1>
@@ -0,0 +1,13 @@
1
+ js:
2
+ application:
3
+ - foo.coffee
4
+ - bar.coffee
5
+
6
+ fancy:
7
+ - foo.coffee
8
+ - templates/home.eco
9
+
10
+ css:
11
+ application:
12
+ - bar.css
13
+ - foo.css
@@ -0,0 +1,5 @@
1
+ guard :shell do
2
+ watch /assets\/.*/ do
3
+ `../../bin/gumbo`
4
+ end
5
+ end
@@ -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,7 @@
1
+ body {
2
+ margin: 25px auto;
3
+ }
4
+
5
+ #container {
6
+ width: 800px;
7
+ }
@@ -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>
@@ -0,0 +1,7 @@
1
+ $ =>
2
+ $('#add-todo').submit (e) ->
3
+ e.preventDefault()
4
+ e.stopPropagation()
5
+ $('#todos').append(JST["templates/todo"](name: $('#todo').val()))
6
+ false
7
+
@@ -0,0 +1,9 @@
1
+ js:
2
+ todo:
3
+ - todo.coffee
4
+ - templates/todo.eco
5
+
6
+ css:
7
+ todo:
8
+ - reset.css
9
+ - style.css
@@ -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
@@ -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
@@ -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,8 @@
1
+ require 'coffee_script'
2
+
3
+ module Gumbo
4
+ class CoffeeScriptFile < CompileToJavaScriptFile
5
+ ext ".coffee"
6
+ compiler CoffeeScript
7
+ end
8
+ 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,11 @@
1
+ require 'eco'
2
+
3
+ module Gumbo
4
+ class EcoFile < CompileToJavaScriptFile
5
+ ext ".eco"
6
+
7
+ def compile(src)
8
+ "this.JST || (this.JST = {}); this.JST['#{name.sub(/.eco$/,'')}'] = #{Eco.compile(src)};"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module Gumbo
2
+ class JavaScriptFile < PackageFile
3
+ ext ".js"
4
+ end
5
+ 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
@@ -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,5 @@
1
+ module Gumbo
2
+ class StyleSheetFile < PackageFile
3
+ ext ".css"
4
+ end
5
+ 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: []