bunch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .sass-cache
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bunch.gemspec
4
+ gemspec
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../../lib', __FILE__)
4
+ require 'bunch'
5
+ require 'bunch/cli'
6
+
7
+ Bunch::CLI.process!
@@ -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
@@ -0,0 +1,6 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+ require 'bunch'
3
+
4
+ run Rack::URLMap.new \
5
+ "/stylesheets" => Bunch::Rack.new('example/css'),
6
+ "/javascripts" => Bunch::Rack.new('example/js')
@@ -0,0 +1,6 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'bunch'
3
+
4
+ run Rack::URLMap.new \
5
+ "/stylesheets" => Bunch::Rack.new('example/css'),
6
+ "/javascripts" => Bunch::Rack.new('example/js')
@@ -0,0 +1 @@
1
+ body { a: 1; }
@@ -0,0 +1 @@
1
+ body { b: 2; }
@@ -0,0 +1 @@
1
+ body { c: 3; }
@@ -0,0 +1 @@
1
+ 1
@@ -0,0 +1,2 @@
1
+ - test2a
2
+ - test2c
@@ -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
+ - test4c
@@ -0,0 +1 @@
1
+ 9
@@ -0,0 +1 @@
1
+ 10
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Bunch
2
+ VERSION = "0.0.1"
3
+ 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: