bunch 0.2.2 → 1.0.0pre1
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/.gitignore +15 -6
- data/Gemfile +3 -1
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/Rakefile +7 -12
- data/bin/bunch +2 -5
- data/bunch.gemspec +30 -23
- data/lib/bunch.rb +37 -81
- data/lib/bunch/cli.rb +40 -74
- data/lib/bunch/combiner.rb +121 -0
- data/lib/bunch/compiler.rb +52 -0
- data/lib/bunch/compilers/coffee_script.rb +23 -0
- data/lib/bunch/compilers/ejs.rb +28 -0
- data/lib/bunch/compilers/jade.rb +28 -0
- data/lib/bunch/compilers/jst.rb +38 -0
- data/lib/bunch/compilers/null.rb +19 -0
- data/lib/bunch/compilers/sass.rb +55 -0
- data/lib/bunch/content_hash.rb +37 -0
- data/lib/bunch/css_minifier.rb +121 -0
- data/lib/bunch/file.rb +18 -0
- data/lib/bunch/file_cache.rb +159 -0
- data/lib/bunch/file_tree.rb +153 -0
- data/lib/bunch/ignorer.rb +38 -0
- data/lib/bunch/js_minifier.rb +38 -0
- data/lib/bunch/middleware.rb +16 -67
- data/lib/bunch/pipeline.rb +30 -0
- data/lib/bunch/server.rb +56 -0
- data/lib/bunch/simple_cache.rb +36 -0
- data/lib/bunch/tree_merge.rb +29 -0
- data/lib/bunch/version.rb +3 -1
- data/spec/bunch/cli_spec.rb +85 -0
- data/spec/bunch/combiner_spec.rb +107 -0
- data/spec/bunch/compiler_spec.rb +73 -0
- data/spec/bunch/compilers/coffee_script_spec.rb +23 -0
- data/spec/bunch/compilers/ejs_spec.rb +27 -0
- data/spec/bunch/compilers/jade_spec.rb +28 -0
- data/spec/bunch/compilers/sass_spec.rb +120 -0
- data/spec/bunch/css_minifier_spec.rb +31 -0
- data/spec/bunch/file_cache_spec.rb +151 -0
- data/spec/bunch/file_tree_spec.rb +127 -0
- data/spec/bunch/ignorer_spec.rb +26 -0
- data/spec/bunch/js_minifier_spec.rb +35 -0
- data/spec/bunch/middleware_spec.rb +41 -0
- data/spec/bunch/pipeline_spec.rb +31 -0
- data/spec/bunch/server_spec.rb +90 -0
- data/spec/bunch/simple_cache_spec.rb +55 -0
- data/spec/bunch/tree_merge_spec.rb +30 -0
- data/spec/bunch_spec.rb +6 -0
- data/spec/example_tree/directory/_combine +2 -0
- data/{example/js/test1.js → spec/example_tree/directory/file1} +0 -0
- data/{example/js/test2/test2a.js → spec/example_tree/directory/file2} +0 -0
- data/{example/js/test2/test2c.js → spec/example_tree/file3} +0 -0
- data/spec/spec_helper.rb +38 -0
- metadata +224 -102
- data/.yardopts +0 -1
- data/README.md +0 -4
- data/config.ru +0 -6
- data/example/config.ru +0 -6
- data/example/css/test1.css +0 -1
- data/example/css/test2/test2a.scss +0 -1
- data/example/css/test2/test2b.css +0 -1
- data/example/js/.bunchignore +0 -1
- data/example/js/test2/_.yml +0 -2
- data/example/js/test2/foo.js +0 -1
- data/example/js/test2/test2b.js +0 -1
- data/example/js/test3/test3a.js +0 -1
- data/example/js/test3/test3b/_.yml +0 -1
- data/example/js/test3/test3b/test3bi.js +0 -1
- data/example/js/test3/test3b/test3bii.js +0 -1
- data/example/js/test4/_.yml +0 -1
- data/example/js/test4/test4a.js +0 -1
- data/example/js/test4/test4b.coffee +0 -1
- data/example/js/test4/test4c.coffee +0 -1
- data/example/js/test5/test5a.jst.ejs +0 -1
- data/lib/bunch/abstract_node.rb +0 -25
- data/lib/bunch/cache.rb +0 -40
- data/lib/bunch/coffee_node.rb +0 -39
- data/lib/bunch/directory_node.rb +0 -82
- data/lib/bunch/ejs_node.rb +0 -50
- data/lib/bunch/file_node.rb +0 -25
- data/lib/bunch/jade_node.rb +0 -50
- data/lib/bunch/null_node.rb +0 -11
- data/lib/bunch/rack.rb +0 -38
- data/lib/bunch/sass_node.rb +0 -39
- data/test/middleware_test.rb +0 -26
- data/test/rack_test.rb +0 -93
- data/test/test_helper.rb +0 -21
data/.yardopts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--markup markdown --private
|
data/README.md
DELETED
data/config.ru
DELETED
data/example/config.ru
DELETED
data/example/css/test1.css
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
body { a: 1; }
|
@@ -1 +0,0 @@
|
|
1
|
-
body { b: 2; }
|
@@ -1 +0,0 @@
|
|
1
|
-
body { c: 3; }
|
data/example/js/.bunchignore
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
foo
|
data/example/js/test2/_.yml
DELETED
data/example/js/test2/foo.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
foo;
|
data/example/js/test2/test2b.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
4
|
data/example/js/test3/test3a.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
5
|
@@ -1 +0,0 @@
|
|
1
|
-
- test3bii
|
@@ -1 +0,0 @@
|
|
1
|
-
7
|
@@ -1 +0,0 @@
|
|
1
|
-
6
|
data/example/js/test4/_.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
- test4c
|
data/example/js/test4/test4a.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
9
|
@@ -1 +0,0 @@
|
|
1
|
-
10
|
@@ -1 +0,0 @@
|
|
1
|
-
8
|
@@ -1 +0,0 @@
|
|
1
|
-
11
|
data/lib/bunch/abstract_node.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
class AbstractNode
|
3
|
-
attr_accessor :options
|
4
|
-
|
5
|
-
def content
|
6
|
-
raise NotImplementedError
|
7
|
-
end
|
8
|
-
alias name content
|
9
|
-
alias target_extension content
|
10
|
-
|
11
|
-
def write_to_dir(dir)
|
12
|
-
write_to_file(File.join(dir, name))
|
13
|
-
end
|
14
|
-
|
15
|
-
def write_to_file(fn)
|
16
|
-
out_file = "#{fn}#{target_extension}"
|
17
|
-
File.open(out_file, 'w') { |f| f.write(content) }
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
def fetch(fn, &blk)
|
22
|
-
Cache.fetch(fn, &blk)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/bunch/cache.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
module Cache
|
3
|
-
end
|
4
|
-
|
5
|
-
class << Cache
|
6
|
-
def init
|
7
|
-
@cache = Hash.new { |h, k| h[k] = {} }
|
8
|
-
end
|
9
|
-
|
10
|
-
def stored?(fn)
|
11
|
-
@cache.keys.include?(fn)
|
12
|
-
end
|
13
|
-
|
14
|
-
def read(fn)
|
15
|
-
@cache[fn][:content]
|
16
|
-
end
|
17
|
-
|
18
|
-
def mtime(fn)
|
19
|
-
@cache[fn][:mtime]
|
20
|
-
end
|
21
|
-
|
22
|
-
def write(fn, mtime, content)
|
23
|
-
@cache[fn] = {:mtime => mtime, :content => content}
|
24
|
-
end
|
25
|
-
|
26
|
-
def fetch(fn, &blk)
|
27
|
-
current_mtime = File.mtime(fn)
|
28
|
-
|
29
|
-
if stored?(fn) && mtime(fn) == current_mtime
|
30
|
-
read(fn)
|
31
|
-
else
|
32
|
-
content = blk.call
|
33
|
-
write(fn, current_mtime, content)
|
34
|
-
content
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
Cache.init
|
40
|
-
end
|
data/lib/bunch/coffee_node.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
class CoffeeNode < FileNode
|
3
|
-
def initialize(fn)
|
4
|
-
CoffeeNode.require_coffee
|
5
|
-
@filename = fn
|
6
|
-
end
|
7
|
-
|
8
|
-
def content
|
9
|
-
@content ||= fetch(@filename) { CoffeeScript.compile(File.read(@filename), :bare => CoffeeNode.bare) }
|
10
|
-
rescue => e
|
11
|
-
raise CompileError.new(e, @filename)
|
12
|
-
end
|
13
|
-
|
14
|
-
def name
|
15
|
-
File.basename(@filename, '.coffee')
|
16
|
-
end
|
17
|
-
|
18
|
-
def target_extension
|
19
|
-
'.js'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class << CoffeeNode
|
24
|
-
attr_writer :bare
|
25
|
-
|
26
|
-
def require_coffee
|
27
|
-
unless @required
|
28
|
-
require 'coffee-script'
|
29
|
-
@required = true
|
30
|
-
end
|
31
|
-
rescue LoadError
|
32
|
-
raise "'gem install coffee-script' to compile .coffee files."
|
33
|
-
end
|
34
|
-
|
35
|
-
def bare
|
36
|
-
defined?(@bare) ? @bare : (@bare = false)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/lib/bunch/directory_node.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
class DirectoryNode < AbstractNode
|
3
|
-
attr_reader :root
|
4
|
-
|
5
|
-
def initialize(fn)
|
6
|
-
@root = Pathname.new(fn)
|
7
|
-
end
|
8
|
-
|
9
|
-
def filenames
|
10
|
-
Dir[@root.join("*")].select { |f| f !~ /_\.yml$/ }
|
11
|
-
end
|
12
|
-
|
13
|
-
def children
|
14
|
-
@children ||= begin
|
15
|
-
children = filenames.map do |filename|
|
16
|
-
Bunch.tree_for(filename, @options)
|
17
|
-
end
|
18
|
-
|
19
|
-
ordering_file = @root.join('_.yml')
|
20
|
-
|
21
|
-
if File.exist?(ordering_file)
|
22
|
-
ordering = YAML.load_file(ordering_file)
|
23
|
-
ordered, unordered = children.partition { |c| ordering.include?(c.name) }
|
24
|
-
|
25
|
-
(ordering - ordered.map(&:name)).each do |f|
|
26
|
-
$stderr.puts "WARNING: directory #{ full_name } has no object #{ f }"
|
27
|
-
end
|
28
|
-
|
29
|
-
ordered.sort_by { |c| ordering.index(c.name) } + unordered.sort_by(&:name)
|
30
|
-
else
|
31
|
-
children.sort_by(&:name)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def target_extension
|
37
|
-
@target_extension ||= begin
|
38
|
-
exts = children.map(&:target_extension).compact.uniq
|
39
|
-
if exts.count == 1
|
40
|
-
exts.first
|
41
|
-
elsif exts.count > 1
|
42
|
-
raise "Directory #{name} contains non-homogeneous nodes: #{exts.inspect}"
|
43
|
-
else
|
44
|
-
nil
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def content
|
50
|
-
@content ||= children.map(&:content).join
|
51
|
-
end
|
52
|
-
|
53
|
-
def name
|
54
|
-
File.basename(@root)
|
55
|
-
end
|
56
|
-
|
57
|
-
def full_name
|
58
|
-
@root
|
59
|
-
end
|
60
|
-
|
61
|
-
def write_to_file(dir)
|
62
|
-
return if filenames.count == 0
|
63
|
-
super
|
64
|
-
end
|
65
|
-
|
66
|
-
def write_to_dir(dir)
|
67
|
-
super
|
68
|
-
|
69
|
-
if @options[:recurse]
|
70
|
-
directory_name = File.join(dir, name)
|
71
|
-
FileUtils.mkdir(directory_name)
|
72
|
-
children.each do |child|
|
73
|
-
child.write_to_dir(directory_name)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def inspect
|
79
|
-
"#<DirectoryNode @root=#{@root.inspect} @children=#{children.inspect}>"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
data/lib/bunch/ejs_node.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
class EJSNode < FileNode
|
3
|
-
def initialize(fn)
|
4
|
-
EJSNode.require_ejs
|
5
|
-
@filename = fn
|
6
|
-
end
|
7
|
-
|
8
|
-
def content
|
9
|
-
@content ||= fetch(@filename) {
|
10
|
-
<<-JAVASCRIPT
|
11
|
-
(function() {
|
12
|
-
this.JST || (this.JST = {});
|
13
|
-
this.JST['#{template_name}'] = #{EJS.compile(File.read(@filename))};
|
14
|
-
})();
|
15
|
-
JAVASCRIPT
|
16
|
-
}
|
17
|
-
rescue => e
|
18
|
-
raise CompileError.new(e, @filename)
|
19
|
-
end
|
20
|
-
|
21
|
-
def name
|
22
|
-
File.basename(@filename, '.ejs')
|
23
|
-
end
|
24
|
-
|
25
|
-
def template_name
|
26
|
-
name = @filename.sub(/\.jst\.ejs$/, '')
|
27
|
-
|
28
|
-
if @options[:root]
|
29
|
-
name.sub(/^#{Regexp.escape(@options[:root].to_s)}\//, '')
|
30
|
-
else
|
31
|
-
name
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def target_extension
|
36
|
-
'.js'
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class << EJSNode
|
41
|
-
def require_ejs
|
42
|
-
unless @required
|
43
|
-
require 'ejs'
|
44
|
-
@required = true
|
45
|
-
end
|
46
|
-
rescue LoadError
|
47
|
-
raise "'gem install ejs' to compile .ejs files."
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/lib/bunch/file_node.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
class FileNode < AbstractNode
|
3
|
-
attr_accessor :name, :target_extension
|
4
|
-
|
5
|
-
def initialize(fn)
|
6
|
-
@filename = fn
|
7
|
-
|
8
|
-
if fn =~ /\.[^.]*$/
|
9
|
-
@name = File.basename($`)
|
10
|
-
@target_extension = $&
|
11
|
-
else
|
12
|
-
@name = File.basename(@filename)
|
13
|
-
@target_extension = nil
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def content
|
18
|
-
File.read(@filename)
|
19
|
-
end
|
20
|
-
|
21
|
-
def inspect
|
22
|
-
@filename.inspect
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/bunch/jade_node.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
class JadeNode < FileNode
|
3
|
-
def initialize(fn)
|
4
|
-
JadeNode.require_jade
|
5
|
-
@filename = fn
|
6
|
-
end
|
7
|
-
|
8
|
-
def content
|
9
|
-
@content ||= fetch(@filename) {
|
10
|
-
<<-JAVASCRIPT
|
11
|
-
(function() {
|
12
|
-
this.JST || (this.JST = {});
|
13
|
-
this.JST['#{template_name}'] = #{Jade.compile(File.read(@filename))};
|
14
|
-
})();
|
15
|
-
JAVASCRIPT
|
16
|
-
}
|
17
|
-
rescue => e
|
18
|
-
raise CompileError.new(e, @filename)
|
19
|
-
end
|
20
|
-
|
21
|
-
def name
|
22
|
-
File.basename(@filename, '.jade')
|
23
|
-
end
|
24
|
-
|
25
|
-
def template_name
|
26
|
-
name = @filename.sub(/\.jst\.jade/, '')
|
27
|
-
|
28
|
-
if @options[:root]
|
29
|
-
name.sub(/^#{Regexp.escape(@options[:root].to_s)}\//, '')
|
30
|
-
else
|
31
|
-
name
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def target_extension
|
36
|
-
'.js'
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class << JadeNode
|
41
|
-
def require_jade
|
42
|
-
unless @required
|
43
|
-
require 'ruby-jade'
|
44
|
-
@required = true
|
45
|
-
end
|
46
|
-
rescue LoadError
|
47
|
-
raise "'gem install ruby-jade' to compile .jade files."
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/lib/bunch/null_node.rb
DELETED
data/lib/bunch/rack.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Bunch
|
2
|
-
class Rack
|
3
|
-
def initialize(path, opts={})
|
4
|
-
@root = Pathname.new(path)
|
5
|
-
@headers = {}
|
6
|
-
|
7
|
-
if opts.delete(:no_cache)
|
8
|
-
@headers['Cache-Control'] = 'private, max-age=0, must-revalidate'
|
9
|
-
@headers['Pragma'] = 'no-cache'
|
10
|
-
@headers['Expires'] = 'Thu, 01 Dec 1994 16:00:00 GMT'
|
11
|
-
end
|
12
|
-
|
13
|
-
Bunch.load_ignores(@root)
|
14
|
-
end
|
15
|
-
|
16
|
-
def call(env)
|
17
|
-
path = @root.join(env['PATH_INFO'].sub(/^\//, '')).to_s
|
18
|
-
type = MIME::Types.type_for(path).first || 'text/plain'
|
19
|
-
|
20
|
-
[200, headers(type), [content_for(path)]]
|
21
|
-
rescue => e
|
22
|
-
[500, headers('text/plain'), [error_log(e)]]
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
def content_for(path)
|
27
|
-
Bunch.content_for(path, :root => @root)
|
28
|
-
end
|
29
|
-
|
30
|
-
def headers(mime_type)
|
31
|
-
@headers.merge('Content-Type' => mime_type.to_s)
|
32
|
-
end
|
33
|
-
|
34
|
-
def error_log(e)
|
35
|
-
"#{e.class}: #{e.message}\n #{e.backtrace.join("\n ")}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|