bunch 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 +5 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/bin/bunch +7 -0
- data/bunch.gemspec +23 -0
- data/config.ru +6 -0
- data/example/config.ru +6 -0
- data/example/css/test1.css +1 -0
- data/example/css/test2/test2a.scss +1 -0
- data/example/css/test2/test2b.css +1 -0
- data/example/js/test1.js +1 -0
- data/example/js/test2/_.yml +2 -0
- data/example/js/test2/test2a.js +1 -0
- data/example/js/test2/test2b.js +1 -0
- data/example/js/test2/test2c.js +1 -0
- data/example/js/test3/test3a.js +1 -0
- data/example/js/test3/test3b/_.yml +1 -0
- data/example/js/test3/test3b/test3bi.js +1 -0
- data/example/js/test3/test3b/test3bii.js +1 -0
- data/example/js/test4/_.yml +1 -0
- data/example/js/test4/test4a.js +1 -0
- data/example/js/test4/test4b.coffee +1 -0
- data/example/js/test4/test4c.coffee +1 -0
- data/lib/bunch.rb +37 -0
- data/lib/bunch/cli.rb +76 -0
- data/lib/bunch/coffee_node.rb +26 -0
- data/lib/bunch/directory_node.rb +51 -0
- data/lib/bunch/file_node.rb +24 -0
- data/lib/bunch/rack.rb +33 -0
- data/lib/bunch/sass_node.rb +26 -0
- data/lib/bunch/version.rb +3 -0
- metadata +100 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/bunch
ADDED
data/bunch.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bunch/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "bunch"
|
7
|
+
s.version = Bunch::VERSION
|
8
|
+
s.authors = ["Ryan Fitzgerald"]
|
9
|
+
s.email = ["rwfitzge@gmail.com"]
|
10
|
+
s.homepage = "http://rynftz.gr"
|
11
|
+
s.summary = %q{Simple, directory-structure-based asset bundling.}
|
12
|
+
s.description = %q{Simple, directory-structure-based asset bundling.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "bunch"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "mime-types"
|
22
|
+
s.add_runtime_dependency "slop"
|
23
|
+
end
|
data/config.ru
ADDED
data/example/config.ru
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
body { a: 1; }
|
@@ -0,0 +1 @@
|
|
1
|
+
body { b: 2; }
|
@@ -0,0 +1 @@
|
|
1
|
+
body { c: 3; }
|
data/example/js/test1.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1
|
@@ -0,0 +1 @@
|
|
1
|
+
2
|
@@ -0,0 +1 @@
|
|
1
|
+
4
|
@@ -0,0 +1 @@
|
|
1
|
+
3
|
@@ -0,0 +1 @@
|
|
1
|
+
5
|
@@ -0,0 +1 @@
|
|
1
|
+
- test3bii
|
@@ -0,0 +1 @@
|
|
1
|
+
7
|
@@ -0,0 +1 @@
|
|
1
|
+
6
|
@@ -0,0 +1 @@
|
|
1
|
+
- test4c
|
@@ -0,0 +1 @@
|
|
1
|
+
9
|
@@ -0,0 +1 @@
|
|
1
|
+
10
|
@@ -0,0 +1 @@
|
|
1
|
+
8
|
data/lib/bunch.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
require 'mime/types'
|
6
|
+
require 'slop'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'v8'
|
10
|
+
rescue LoadError
|
11
|
+
$stderr.puts "WARNING: 'gem install therubyracer' for much faster CoffeeScript compilation."
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'bunch/version'
|
15
|
+
require 'bunch/directory_node'
|
16
|
+
require 'bunch/file_node'
|
17
|
+
require 'bunch/coffee_node'
|
18
|
+
require 'bunch/sass_node'
|
19
|
+
require 'bunch/rack'
|
20
|
+
|
21
|
+
module Bunch
|
22
|
+
end
|
23
|
+
|
24
|
+
class << Bunch
|
25
|
+
def Tree(fn)
|
26
|
+
case
|
27
|
+
when File.directory?(fn)
|
28
|
+
Bunch::DirectoryNode.new(fn)
|
29
|
+
when fn =~ /\.coffee$/
|
30
|
+
Bunch::CoffeeNode.new(fn)
|
31
|
+
when fn =~ /\.s(a|c)ss$/
|
32
|
+
Bunch::SassNode.new(fn)
|
33
|
+
else
|
34
|
+
Bunch::FileNode.new(fn)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/bunch/cli.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
module Bunch
|
2
|
+
class CLI
|
3
|
+
def initialize(input, output, opts)
|
4
|
+
@input = Pathname.new(input)
|
5
|
+
@output = output ? Pathname.new(output) : nil
|
6
|
+
@opts = opts
|
7
|
+
end
|
8
|
+
|
9
|
+
def process!
|
10
|
+
tree = Bunch::Tree(@input.to_s)
|
11
|
+
|
12
|
+
if @output
|
13
|
+
FileUtils.mkdir_p(@output.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
if @opts[:all]
|
17
|
+
if @output
|
18
|
+
write(@output.join("all.#{tree.target_extension}"), tree.contents)
|
19
|
+
else
|
20
|
+
puts tree.contents
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
if @opts[:individual]
|
25
|
+
tree.children.each do |child|
|
26
|
+
write(@output.join("#{child.name}.#{child.target_extension}"), child.contents)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def write(fn, contents)
|
33
|
+
File.open(fn, 'w') { |f| f.write(contents) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class << CLI
|
38
|
+
def process!
|
39
|
+
opts = Slop.parse! do
|
40
|
+
banner 'Usage: bunch [options] INPUT_PATH [OUTPUT_PATH]'
|
41
|
+
|
42
|
+
on :i, :individual, 'Create one output file for each file or directory in the input path (default)', :default => true
|
43
|
+
on :a, :all, 'Create an all.[extension] file combining all inputs'
|
44
|
+
on :h, :help, 'Show this message' do
|
45
|
+
display_help = true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if ARGV.count < 1
|
50
|
+
$stderr.puts "ERROR: Must give an input path."
|
51
|
+
display_help = true
|
52
|
+
end
|
53
|
+
|
54
|
+
if ARGV.count < 2 && opts[:individual]
|
55
|
+
$stderr.puts "ERROR: Must give an output path unless --no-individual is provided."
|
56
|
+
display_help = true
|
57
|
+
end
|
58
|
+
|
59
|
+
if display_help
|
60
|
+
$stderr.puts "\n#{opts}"
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
|
64
|
+
input = ARGV.shift
|
65
|
+
output = ARGV.shift
|
66
|
+
|
67
|
+
CLI.new(input, output, opts).process!
|
68
|
+
rescue Exception => e
|
69
|
+
if ENV['BUNCH_DEBUG']
|
70
|
+
raise
|
71
|
+
else
|
72
|
+
$stderr.puts "ERROR: #{e.message}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Bunch
|
2
|
+
class CoffeeNode
|
3
|
+
def initialize(fn)
|
4
|
+
require 'coffee-script'
|
5
|
+
@filename = fn
|
6
|
+
rescue LoadError
|
7
|
+
$stderr.puts "ERROR: 'gem install coffee-script' to compile .coffee files."
|
8
|
+
end
|
9
|
+
|
10
|
+
def contents
|
11
|
+
@contents ||= CoffeeScript.compile(File.read(@filename), :bare => false)
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
File.basename(@filename, '.coffee')
|
16
|
+
end
|
17
|
+
|
18
|
+
def target_extension
|
19
|
+
'js'
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
@filename.inspect
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Bunch
|
2
|
+
class DirectoryNode
|
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 &Bunch.method(:Tree)
|
16
|
+
ordering_file = @root.join('_.yml')
|
17
|
+
|
18
|
+
if File.exist?(ordering_file)
|
19
|
+
ordering = YAML.load_file(ordering_file)
|
20
|
+
ordered, unordered = children.partition { |c| ordering.include?(c.name) }
|
21
|
+
ordered.sort_by { |c| ordering.index(c.name) } + unordered.sort_by(&:name)
|
22
|
+
else
|
23
|
+
children.sort_by(&:name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def target_extension
|
29
|
+
@target_extension ||= begin
|
30
|
+
exts = children.map(&:target_extension).compact.uniq
|
31
|
+
if exts.count == 1
|
32
|
+
exts.first
|
33
|
+
else
|
34
|
+
raise "Directory contains non-homogeneous nodes: #{exts.inspect}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def contents
|
40
|
+
@contents ||= children.map(&:contents).join
|
41
|
+
end
|
42
|
+
|
43
|
+
def name
|
44
|
+
File.basename(@root)
|
45
|
+
end
|
46
|
+
|
47
|
+
def inspect
|
48
|
+
"#<Node @root=#{@root.inspect} @children=#{children.inspect}>"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Bunch
|
2
|
+
class FileNode
|
3
|
+
attr_reader :name, :target_extension
|
4
|
+
|
5
|
+
def initialize(fn)
|
6
|
+
@filename = fn
|
7
|
+
|
8
|
+
if fn =~ %r(\.([^/]*?)$)
|
9
|
+
@name = File.basename($`)
|
10
|
+
@target_extension = $1
|
11
|
+
else
|
12
|
+
@name = File.basename(@filename)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def contents
|
17
|
+
File.read(@filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
def inspect
|
21
|
+
@filename.inspect
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/bunch/rack.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bunch
|
2
|
+
class Rack
|
3
|
+
def initialize(path)
|
4
|
+
@root = Pathname.new(path)
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
path = @root.join(env['PATH_INFO'].sub(/^\//, '')).to_s
|
9
|
+
type = MIME::Types.type_for(path).first || 'text/plain'
|
10
|
+
|
11
|
+
[ 200, { 'Content-Type' => type.to_s }, [ generate(path) ] ]
|
12
|
+
rescue => e
|
13
|
+
[ 500, { 'Content-Type' => 'text/plain' }, [ error_log(e) ] ]
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def generate(path)
|
18
|
+
if File.exist?(path)
|
19
|
+
Bunch::Tree(path).contents
|
20
|
+
elsif File.exist?(chopped_path = path.sub(%r(\.[^/]*?$), ''))
|
21
|
+
Bunch::Tree(chopped_path).contents
|
22
|
+
elsif File.basename(path).start_with?('all.')
|
23
|
+
Bunch::Tree(File.dirname(path)).contents
|
24
|
+
else
|
25
|
+
raise Errno::ENOENT, path
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def error_log(e)
|
30
|
+
"#{e.class}: #{e.message}\n #{e.backtrace.join("\n ")}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Bunch
|
2
|
+
class SassNode
|
3
|
+
def initialize(fn)
|
4
|
+
require 'sass'
|
5
|
+
@filename = fn
|
6
|
+
rescue LoadError
|
7
|
+
$stderr.puts "ERROR: 'gem install sass' to compile .coffee files."
|
8
|
+
end
|
9
|
+
|
10
|
+
def contents
|
11
|
+
@contents ||= Sass::Engine.for_file(@filename, {}).render
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
File.basename(@filename).sub(/\.s(c|a)ss$/, '')
|
16
|
+
end
|
17
|
+
|
18
|
+
def target_extension
|
19
|
+
'css'
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
@filename.inspect
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bunch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Fitzgerald
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mime-types
|
16
|
+
requirement: &70324537243860 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70324537243860
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: slop
|
27
|
+
requirement: &70324537243440 !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: *70324537243440
|
36
|
+
description: Simple, directory-structure-based asset bundling.
|
37
|
+
email:
|
38
|
+
- rwfitzge@gmail.com
|
39
|
+
executables:
|
40
|
+
- bunch
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- Rakefile
|
47
|
+
- bin/bunch
|
48
|
+
- bunch.gemspec
|
49
|
+
- config.ru
|
50
|
+
- example/config.ru
|
51
|
+
- example/css/test1.css
|
52
|
+
- example/css/test2/test2a.scss
|
53
|
+
- example/css/test2/test2b.css
|
54
|
+
- example/js/test1.js
|
55
|
+
- example/js/test2/_.yml
|
56
|
+
- example/js/test2/test2a.js
|
57
|
+
- example/js/test2/test2b.js
|
58
|
+
- example/js/test2/test2c.js
|
59
|
+
- example/js/test3/test3a.js
|
60
|
+
- example/js/test3/test3b/_.yml
|
61
|
+
- example/js/test3/test3b/test3bi.js
|
62
|
+
- example/js/test3/test3b/test3bii.js
|
63
|
+
- example/js/test4/_.yml
|
64
|
+
- example/js/test4/test4a.js
|
65
|
+
- example/js/test4/test4b.coffee
|
66
|
+
- example/js/test4/test4c.coffee
|
67
|
+
- lib/bunch.rb
|
68
|
+
- lib/bunch/cli.rb
|
69
|
+
- lib/bunch/coffee_node.rb
|
70
|
+
- lib/bunch/directory_node.rb
|
71
|
+
- lib/bunch/file_node.rb
|
72
|
+
- lib/bunch/rack.rb
|
73
|
+
- lib/bunch/sass_node.rb
|
74
|
+
- lib/bunch/version.rb
|
75
|
+
homepage: http://rynftz.gr
|
76
|
+
licenses: []
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project: bunch
|
95
|
+
rubygems_version: 1.8.10
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Simple, directory-structure-based asset bundling.
|
99
|
+
test_files: []
|
100
|
+
has_rdoc:
|