bunch 0.2.2 → 1.0.0pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -6
  3. data/Gemfile +3 -1
  4. data/Guardfile +5 -0
  5. data/LICENSE.txt +22 -0
  6. data/Rakefile +7 -12
  7. data/bin/bunch +2 -5
  8. data/bunch.gemspec +30 -23
  9. data/lib/bunch.rb +37 -81
  10. data/lib/bunch/cli.rb +40 -74
  11. data/lib/bunch/combiner.rb +121 -0
  12. data/lib/bunch/compiler.rb +52 -0
  13. data/lib/bunch/compilers/coffee_script.rb +23 -0
  14. data/lib/bunch/compilers/ejs.rb +28 -0
  15. data/lib/bunch/compilers/jade.rb +28 -0
  16. data/lib/bunch/compilers/jst.rb +38 -0
  17. data/lib/bunch/compilers/null.rb +19 -0
  18. data/lib/bunch/compilers/sass.rb +55 -0
  19. data/lib/bunch/content_hash.rb +37 -0
  20. data/lib/bunch/css_minifier.rb +121 -0
  21. data/lib/bunch/file.rb +18 -0
  22. data/lib/bunch/file_cache.rb +159 -0
  23. data/lib/bunch/file_tree.rb +153 -0
  24. data/lib/bunch/ignorer.rb +38 -0
  25. data/lib/bunch/js_minifier.rb +38 -0
  26. data/lib/bunch/middleware.rb +16 -67
  27. data/lib/bunch/pipeline.rb +30 -0
  28. data/lib/bunch/server.rb +56 -0
  29. data/lib/bunch/simple_cache.rb +36 -0
  30. data/lib/bunch/tree_merge.rb +29 -0
  31. data/lib/bunch/version.rb +3 -1
  32. data/spec/bunch/cli_spec.rb +85 -0
  33. data/spec/bunch/combiner_spec.rb +107 -0
  34. data/spec/bunch/compiler_spec.rb +73 -0
  35. data/spec/bunch/compilers/coffee_script_spec.rb +23 -0
  36. data/spec/bunch/compilers/ejs_spec.rb +27 -0
  37. data/spec/bunch/compilers/jade_spec.rb +28 -0
  38. data/spec/bunch/compilers/sass_spec.rb +120 -0
  39. data/spec/bunch/css_minifier_spec.rb +31 -0
  40. data/spec/bunch/file_cache_spec.rb +151 -0
  41. data/spec/bunch/file_tree_spec.rb +127 -0
  42. data/spec/bunch/ignorer_spec.rb +26 -0
  43. data/spec/bunch/js_minifier_spec.rb +35 -0
  44. data/spec/bunch/middleware_spec.rb +41 -0
  45. data/spec/bunch/pipeline_spec.rb +31 -0
  46. data/spec/bunch/server_spec.rb +90 -0
  47. data/spec/bunch/simple_cache_spec.rb +55 -0
  48. data/spec/bunch/tree_merge_spec.rb +30 -0
  49. data/spec/bunch_spec.rb +6 -0
  50. data/spec/example_tree/directory/_combine +2 -0
  51. data/{example/js/test1.js → spec/example_tree/directory/file1} +0 -0
  52. data/{example/js/test2/test2a.js → spec/example_tree/directory/file2} +0 -0
  53. data/{example/js/test2/test2c.js → spec/example_tree/file3} +0 -0
  54. data/spec/spec_helper.rb +38 -0
  55. metadata +224 -102
  56. data/.yardopts +0 -1
  57. data/README.md +0 -4
  58. data/config.ru +0 -6
  59. data/example/config.ru +0 -6
  60. data/example/css/test1.css +0 -1
  61. data/example/css/test2/test2a.scss +0 -1
  62. data/example/css/test2/test2b.css +0 -1
  63. data/example/js/.bunchignore +0 -1
  64. data/example/js/test2/_.yml +0 -2
  65. data/example/js/test2/foo.js +0 -1
  66. data/example/js/test2/test2b.js +0 -1
  67. data/example/js/test3/test3a.js +0 -1
  68. data/example/js/test3/test3b/_.yml +0 -1
  69. data/example/js/test3/test3b/test3bi.js +0 -1
  70. data/example/js/test3/test3b/test3bii.js +0 -1
  71. data/example/js/test4/_.yml +0 -1
  72. data/example/js/test4/test4a.js +0 -1
  73. data/example/js/test4/test4b.coffee +0 -1
  74. data/example/js/test4/test4c.coffee +0 -1
  75. data/example/js/test5/test5a.jst.ejs +0 -1
  76. data/lib/bunch/abstract_node.rb +0 -25
  77. data/lib/bunch/cache.rb +0 -40
  78. data/lib/bunch/coffee_node.rb +0 -39
  79. data/lib/bunch/directory_node.rb +0 -82
  80. data/lib/bunch/ejs_node.rb +0 -50
  81. data/lib/bunch/file_node.rb +0 -25
  82. data/lib/bunch/jade_node.rb +0 -50
  83. data/lib/bunch/null_node.rb +0 -11
  84. data/lib/bunch/rack.rb +0 -38
  85. data/lib/bunch/sass_node.rb +0 -39
  86. data/test/middleware_test.rb +0 -26
  87. data/test/rack_test.rb +0 -93
  88. data/test/test_helper.rb +0 -21
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: efebcfd36e823c3ec86e0442561e0dae5b269992
4
+ data.tar.gz: a5e89ce41f38db3a0b6b1bb0b93ac19f4778ad6c
5
+ SHA512:
6
+ metadata.gz: 3f66c4238a91ea23234ff00fa0b3dadfaa6a304f6e5c144e10d3388cda68a45228edf3e280ed932a5f66804ae4760541d80fe4cc8c35986efca9ee1165a906f6
7
+ data.tar.gz: 37d71071cd267674130898cd31856e47d788e26ebf765ddba3e34c888fdd040d6bfd0b5122bb9c8ba04f8e0ba6ef5a59cc3967755d221d02abc8c18f2d375481
data/.gitignore CHANGED
@@ -1,10 +1,19 @@
1
1
  *.gem
2
+ *.rbc
2
3
  .bundle
4
+ .config
5
+ .yardoc
3
6
  Gemfile.lock
4
- pkg/*
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
5
18
  .sass-cache
6
- .yardoc
7
- doc/*
8
- *.sublime-workspace
9
- *.sublime-project
10
- *.DS_Store
19
+ .bunch-cache
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rb-fsevent'
2
4
 
3
5
  # Specify your gem's dependencies in bunch.gemspec
4
6
  gemspec
@@ -0,0 +1,5 @@
1
+ guard 'minitest' do
2
+ watch(%r|^spec/(.*)_spec\.rb|)
3
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
4
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
5
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Academia.edu
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/Rakefile CHANGED
@@ -1,18 +1,13 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
2
3
 
3
- begin
4
- require 'yard'
5
- YARD::Rake::YardocTask.new
6
- rescue LoadError
4
+ Rake::TestTask.new do |t|
5
+ t.libs.concat %w(bunch spec)
6
+ t.pattern = "spec/**/*_spec.rb"
7
7
  end
8
8
 
9
- require 'rake/testtask'
10
-
11
- Rake::TestTask.new(:test) do |t|
12
- t.libs << 'lib'
13
- t.libs << 'test'
14
- t.pattern = 'test/**/*_test.rb'
15
- t.verbose = false
9
+ task :pry do
10
+ system "pry -Ilib -rbunch"
16
11
  end
17
12
 
18
- task :default => :test
13
+ task :default => [:test]
data/bin/bunch CHANGED
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift File.expand_path('../../lib', __FILE__)
4
- require 'bunch'
5
- require 'bunch/cli'
6
-
7
- Bunch::CLI.process!
3
+ require "bunch"
4
+ Bunch::CLI.run!(ARGV)
@@ -1,31 +1,38 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
4
  require 'bunch/version'
4
5
 
5
- Gem::Specification.new do |s|
6
- s.name = 'bunch'
7
- s.version = Bunch::VERSION
8
- s.authors = ['Ryan Fitzgerald']
9
- s.email = ['rfitz@academia.edu']
10
- s.homepage = ''
11
- s.summary = %q{Directory-structure-based asset bundling.}
12
- s.description = %q{Directory-structure-based asset bundling.}
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "bunch"
8
+ gem.version = Bunch::VERSION
9
+ gem.authors = ["Ryan Fitzgerald"]
10
+ gem.email = ["rwfitzge@gmail.com"]
11
+ gem.summary = %q{Directory-structure-based asset bundling.}
12
+ gem.description = gem.summary
13
+ gem.homepage = "https://github.com/academia-edu/bunch"
13
14
 
14
- s.rubyforge_project = 'bunch'
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
15
19
 
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
+ gem.add_dependency "mime-types", "~> 1.16"
20
21
 
21
- s.add_runtime_dependency 'mime-types'
22
+ gem.add_development_dependency "yard", "~> 0.8.3"
23
+ gem.add_development_dependency "minitest", "~> 4.3.3"
24
+ gem.add_development_dependency "mocha", "~> 0.13.1"
25
+ gem.add_development_dependency "rdiscount"
26
+ gem.add_development_dependency "rake"
27
+ gem.add_development_dependency "guard"
28
+ gem.add_development_dependency "guard-minitest"
29
+ gem.add_development_dependency "pry"
30
+ gem.add_development_dependency "simplecov"
31
+ gem.add_development_dependency "rack"
22
32
 
23
- s.add_development_dependency 'yard'
24
- s.add_development_dependency 'rdiscount'
25
- s.add_development_dependency 'shoulda-context'
26
- s.add_development_dependency 'mocha'
27
-
28
- s.add_development_dependency 'coffee-script'
29
- s.add_development_dependency 'sass'
30
- s.add_development_dependency 'ejs'
33
+ gem.add_development_dependency "coffee-script"
34
+ gem.add_development_dependency "sass"
35
+ gem.add_development_dependency "ejs"
36
+ gem.add_development_dependency "ruby-jade"
37
+ gem.add_development_dependency "uglifier"
31
38
  end
@@ -1,94 +1,50 @@
1
- require 'fileutils'
2
- require 'optparse'
3
- require 'pathname'
4
- require 'yaml'
5
-
6
- require 'mime/types'
7
-
8
- begin
9
- require 'v8'
10
- rescue LoadError
11
- $stderr.puts "WARNING: 'gem install therubyracer' for much faster CoffeeScript compilation."
1
+ # encoding: utf-8
2
+
3
+ require "bunch/version"
4
+ require "bunch/cli"
5
+ require "bunch/combiner"
6
+ require "bunch/compiler"
7
+ require "bunch/content_hash"
8
+ require "bunch/css_minifier"
9
+ require "bunch/file"
10
+ require "bunch/file_cache"
11
+ require "bunch/file_tree"
12
+ require "bunch/ignorer"
13
+ require "bunch/js_minifier"
14
+ require "bunch/middleware"
15
+ require "bunch/server"
16
+ require "bunch/simple_cache"
17
+ require "bunch/pipeline"
18
+ require "bunch/tree_merge"
19
+
20
+ Dir.glob(File.expand_path("../bunch/compilers/*.rb", __FILE__)) do |compiler|
21
+ require compiler
12
22
  end
13
23
 
14
- require 'bunch/version'
15
- require 'bunch/rack'
16
- require 'bunch/middleware'
17
- require 'bunch/cache'
18
-
19
- require 'bunch/abstract_node'
20
- require 'bunch/directory_node'
21
- require 'bunch/file_node'
22
- require 'bunch/coffee_node'
23
- require 'bunch/sass_node'
24
- require 'bunch/null_node'
25
- require 'bunch/ejs_node'
26
- require 'bunch/jade_node'
27
-
28
24
  module Bunch
29
- class CompileError < StandardError
30
- def initialize(exception, filename)
31
- @exception = exception
32
- @filename = filename
33
- end
34
-
35
- def message
36
- "#{@filename}: #{@exception.message}"
25
+ def self.load_default_config_if_possible
26
+ if ::File.exist?("config/bunch.rb")
27
+ load "config/bunch.rb"
37
28
  end
38
29
  end
39
- end
40
-
41
- class << Bunch
42
- IGNORED_PATTERNS = []
43
30
 
44
- def load_ignores(path='.')
45
- fn = File.join(path, '.bunchignore')
46
- if File.exist?(fn)
47
- IGNORED_PATTERNS.concat File.readlines(fn).map { |f| Regexp.new(f.chomp) }
48
- IGNORED_PATTERNS.uniq!
31
+ def self.load_config_files(config_files)
32
+ config_files.each do |config_file|
33
+ load config_file
49
34
  end
50
35
  end
51
36
 
52
- def content_for(path, options = {})
53
- tree_for(normalized_path(path), options).content
37
+ Pipeline.define :development do |config|
38
+ [Ignorer,
39
+ SimpleCache(Compiler),
40
+ Combiner]
54
41
  end
55
42
 
56
- def tree_for(path, options)
57
- node = case
58
- when IGNORED_PATTERNS.any? { |p| File.basename(path) =~ p }
59
- Bunch::NullNode.new(path)
60
- when File.directory?(path)
61
- Bunch::DirectoryNode.new(path)
62
- when path =~ /\.coffee$/
63
- Bunch::CoffeeNode.new(path)
64
- when path =~ /\.s(a|c)ss$/
65
- Bunch::SassNode.new(path)
66
- when path =~ /\.ejs$/
67
- Bunch::EJSNode.new(path)
68
- when path =~ /\.jade/
69
- Bunch::JadeNode.new(path)
70
- else
71
- Bunch::FileNode.new(path)
72
- end
73
- node.options = options
74
- node
43
+ Pipeline.define :production do |config|
44
+ [Ignorer,
45
+ SimpleCache(Compiler),
46
+ Combiner,
47
+ FileCache(JsMinifier, config[:root]),
48
+ FileCache(CssMinifier, config[:root])]
75
49
  end
76
-
77
- protected
78
- def normalized_path(path)
79
- case
80
- when File.exist?(path)
81
- path
82
- when File.exist?(chopped_path = path.sub(%r(\.[^.]*$), ''))
83
- chopped_path
84
- when File.basename(path).start_with?('all.') && File.exist?(dir_path = File.dirname(path))
85
- dir_path
86
- when (path_w_different_extension = Dir["#{chopped_path}.*"].first)
87
- path_w_different_extension
88
- else
89
- raise Errno::ENOENT, path.to_s
90
- end
91
- end
92
50
  end
93
-
94
- Bunch.load_ignores
@@ -1,103 +1,69 @@
1
+ # encoding: UTF-8
2
+
3
+ require "optparse"
4
+
1
5
  module Bunch
2
6
  class CLI
3
- def initialize(input, output, opts)
4
- @input = Pathname.new(input)
5
- @output = output ? Pathname.new(output) : nil
6
- @opts = opts
7
-
8
- if @opts[:server]
9
- run_server
10
- else
11
- generate_files
12
- end
7
+ def self.run!(args)
8
+ new(args).run!
13
9
  end
14
10
 
15
- def run_server
16
- require 'rack'
17
- ::Rack::Handler::WEBrick.run(Bunch::Rack.new(@input), :Port => 3001)
18
- rescue LoadError
19
- $stderr.puts "ERROR: 'gem install rack' to run Bunch in server mode."
20
- exit 1
11
+ def initialize(args, out = $stdout)
12
+ @args, @out = args, out
21
13
  end
22
14
 
23
- def generate_files
24
- Bunch.load_ignores(@input)
25
- tree = Bunch.tree_for(@input.to_s, @opts.merge(:root => @input.to_s))
15
+ def run!
16
+ config = parse_options
26
17
 
27
- if @output
28
- FileUtils.mkdir_p(@output.to_s)
29
- end
30
-
31
- if @opts[:all]
32
- if @output
33
- tree.write_to_file(@output.join('all'))
34
- else
35
- puts tree.content
36
- end
37
- end
38
-
39
- if @opts[:individual]
40
- tree.children.each do |child|
41
- child.write_to_dir(@output)
42
- end
18
+ if config && config[:root] && config[:output_path]
19
+ pipeline = Pipeline.for_environment config
20
+ in_tree = FileTree.from_path config[:root]
21
+ out_tree = pipeline.process in_tree
22
+ out_tree.write_to_path config[:output_path]
43
23
  end
44
24
  end
45
- end
46
25
 
47
- class << CLI
48
- def process!
49
- CLI.new(*parse_opts)
50
- rescue => e
51
- if ENV['BUNCH_DEBUG']
52
- raise
53
- else
54
- $stderr.puts "ERROR: #{e.message}"
55
- exit 1
56
- end
57
- end
26
+ private
58
27
 
59
- def parse_opts
60
- options = {:individual => true}
28
+ def parse_options
29
+ config = { environment: "production", config_files: [] }
61
30
 
62
31
  opts = OptionParser.new do |opts|
63
- opts.banner = 'Usage: bunch [options] INPUT_PATH [OUTPUT_PATH]'
64
-
65
- opts.on '-s', '--server', 'Instead of creating files, use WEBrick to serve files from INPUT_PATH.' do
66
- options[:server] = true
67
- end
68
-
69
- opts.on '-i', '--[no-]individual', 'Create one output file for each file or directory in the input path (default).' do |i|
70
- options[:individual] = i
71
- end
32
+ opts.banner = "Usage: bunch [options] INPUT_PATH OUTPUT_PATH"
72
33
 
73
- opts.on '-a', '--all', 'Create an all.[extension] file combining all inputs.' do
74
- options[:all] = true
34
+ opts.on "-e", "--env [ENV]",
35
+ "Specify environment (default: \"production\")" do |env|
36
+ config[:environment] = env.strip
75
37
  end
76
38
 
77
- opts.on '-r', '--recurse', 'Recursively generate one output file for every input file and directory.' do
78
- options[:recurse] = true
39
+ opts.on "-c", "--config [FILE]",
40
+ "File to load (default: \"config/bunch.rb\")" do |f|
41
+ config[:config_files] << f.strip
79
42
  end
80
43
 
81
- opts.on_tail '-h', '--help', 'Show this message.' do
82
- puts opts
83
- exit
44
+ opts.on_tail "-h", "--help", "Show this message" do
45
+ @out.puts opts
46
+ return
84
47
  end
85
48
  end
86
49
 
87
- opts.parse!
50
+ opts.parse!(@args)
88
51
 
89
- if ARGV.count < 1
90
- raise "Must give an input path.\n\n#{opts}"
52
+ if @args.count != 2
53
+ raise "Must provide input and output paths!"
91
54
  end
92
55
 
93
- if ARGV.count < 2 && options[:individual] && !options[:server]
94
- raise "Must give an output path unless --no-individual or --server is provided."
56
+ if config[:config_files].any?
57
+ Bunch.load_config_files(config[:config_files])
58
+ else
59
+ Bunch.load_default_config_if_possible
95
60
  end
96
61
 
97
- input = ARGV.shift
98
- output = ARGV.shift
99
-
100
- [input, output, options]
62
+ config[:root], config[:output_path] = @args
63
+ config
64
+ rescue StandardError, LoadError => e
65
+ @out.puts "Error: #{e.message}\n\n"
66
+ @out.puts opts if opts
101
67
  end
102
68
  end
103
69
  end