bunch 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,8 +19,9 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ['lib']
20
20
 
21
21
  s.add_runtime_dependency 'mime-types'
22
- s.add_runtime_dependency 'slop'
23
22
 
24
23
  s.add_development_dependency 'yard'
25
24
  s.add_development_dependency 'rdiscount'
25
+ s.add_development_dependency 'shoulda-context'
26
+ s.add_development_dependency 'mocha'
26
27
  end
@@ -1,9 +1,9 @@
1
1
  require 'fileutils'
2
+ require 'optparse'
2
3
  require 'pathname'
3
4
  require 'yaml'
4
5
 
5
6
  require 'mime/types'
6
- require 'slop'
7
7
 
8
8
  begin
9
9
  require 'v8'
@@ -45,40 +45,54 @@ module Bunch
45
45
 
46
46
  class << CLI
47
47
  def process!
48
- opts = Slop.parse! do
49
- banner 'Usage: bunch [options] INPUT_PATH [OUTPUT_PATH]'
50
-
51
- on :s, :server, 'Instead of creating files, use WEBrick to serve files from INPUT_PATH'
52
- on :i, :individual, 'Create one output file for each file or directory in the input path (default)', :default => true
53
- on :a, :all, 'Create an all.[extension] file combining all inputs'
54
- on :h, :help, 'Show this message' do
55
- puts self
48
+ CLI.new(*parse_opts)
49
+ rescue => e
50
+ if ENV['BUNCH_DEBUG']
51
+ raise
52
+ else
53
+ $stderr.puts "ERROR: #{e.message}"
54
+ exit 1
55
+ end
56
+ end
57
+
58
+ def parse_opts
59
+ options = {:individual => true}
60
+
61
+ opts = OptionParser.new do |opts|
62
+ opts.banner = 'Usage: bunch [options] INPUT_PATH [OUTPUT_PATH]'
63
+
64
+ opts.on '-s', '--server', 'Instead of creating files, use WEBrick to serve files from INPUT_PATH.' do
65
+ options[:server] = true
66
+ end
67
+
68
+ opts.on '-i', '--[no-]individual', 'Create one output file for each file or directory in the input path (default).' do |i|
69
+ options[:individual] = i
70
+ end
71
+
72
+ opts.on '-a', '--all', 'Create an all.[extension] file combining all inputs.' do
73
+ options[:all] = true
74
+ end
75
+
76
+ opts.on_tail '-h', '--help', 'Show this message.' do
77
+ puts opts
56
78
  exit
57
79
  end
58
80
  end
59
81
 
82
+ opts.parse!
83
+
60
84
  if ARGV.count < 1
61
- display_help = true
62
- raise "Must give an input path."
85
+ raise "Must give an input path.\n\n#{opts}"
63
86
  end
64
87
 
65
- if ARGV.count < 2 && opts[:individual] && !opts[:server]
66
- display_help = true
88
+ if ARGV.count < 2 && options[:individual] && !options[:server]
67
89
  raise "Must give an output path unless --no-individual or --server is provided."
68
90
  end
69
91
 
70
92
  input = ARGV.shift
71
93
  output = ARGV.shift
72
94
 
73
- CLI.new(input, output, opts)
74
- rescue => e
75
- if ENV['BUNCH_DEBUG']
76
- raise
77
- else
78
- $stderr.puts "ERROR: #{e.message}"
79
- $stderr.puts "\n#{opts}" if display_help
80
- exit 1
81
- end
95
+ [input, output, options]
82
96
  end
83
97
  end
84
98
  end
@@ -1,17 +1,15 @@
1
1
  module Bunch
2
2
  class CoffeeNode < FileNode
3
3
  def initialize(fn)
4
- unless defined?(@@coffee_required)
5
- require 'coffee-script'
6
- @@coffee_required = true
7
- end
4
+ CoffeeNode.require_coffee
8
5
  @filename = fn
9
- rescue LoadError
10
- raise "'gem install coffee-script' to compile .coffee files."
11
6
  end
12
7
 
13
8
  def content
14
- @content ||= fetch(@filename) { CoffeeScript.compile(File.read(@filename), :bare => false) }
9
+ @content ||= fetch(@filename) { CoffeeScript.compile(File.read(@filename), :bare => CoffeeNode.bare) }
10
+ rescue => e
11
+ e.message = "processing #{@filename}: #{e.message}"
12
+ raise e
15
13
  end
16
14
 
17
15
  def name
@@ -22,4 +20,21 @@ module Bunch
22
20
  '.js'
23
21
  end
24
22
  end
23
+
24
+ class << CoffeeNode
25
+ attr_writer :bare
26
+
27
+ def require_coffee
28
+ unless @required
29
+ require 'coffee-script'
30
+ @required = true
31
+ end
32
+ rescue LoadError
33
+ raise "'gem install coffee-script' to compile .coffee files."
34
+ end
35
+
36
+ def bare
37
+ defined?(@bare) ? @bare : (@bare = false)
38
+ end
39
+ end
25
40
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Bunch
4
4
  class Middleware
5
- attr_accessor :app
5
+ attr_accessor :app, :endpoint
6
6
 
7
7
  def initialize(app, options={})
8
8
  unless options[:root_url] && options[:path]
@@ -16,7 +16,7 @@ module Bunch
16
16
 
17
17
  def call(env)
18
18
  path = env['PATH_INFO'].to_s
19
- script_name = env['SCRIPT_NAME']
19
+ script_name = env['SCRIPT_NAME'].to_s
20
20
 
21
21
  if path =~ root_regexp &&
22
22
  (rest = $1) &&
@@ -1,23 +1,15 @@
1
1
  module Bunch
2
2
  class SassNode < FileNode
3
3
  def initialize(fn)
4
- unless defined?(@@sass_required)
5
- require 'sass'
6
- @@sass_required = true
7
- end
8
-
9
- unless defined?(@@sass_style)
10
- @@sass_style = ENV['SASS_STYLE'] || 'nested'
11
- puts @@sass_style.inspect
12
- end
13
-
4
+ SassNode.require_sass
14
5
  @filename = fn
15
- rescue LoadError
16
- raise "'gem install sass' to compile .sass and .scss files."
17
6
  end
18
7
 
19
8
  def content
20
- @content ||= fetch(@filename) { Sass::Engine.for_file(@filename, :style => @@sass_style.to_sym).render }
9
+ @content ||= fetch(@filename) { Sass::Engine.for_file(@filename, :style => SassNode.style).render }
10
+ rescue => e
11
+ e.message = "processing #{@filename}: #{e.message}"
12
+ raise e
21
13
  end
22
14
 
23
15
  def name
@@ -28,4 +20,21 @@ module Bunch
28
20
  '.css'
29
21
  end
30
22
  end
23
+
24
+ class << SassNode
25
+ attr_writer :style
26
+
27
+ def require_sass
28
+ unless @required
29
+ require 'sass'
30
+ @required = true
31
+ end
32
+ rescue LoadError
33
+ raise "'gem install sass' to compile .sass and .scss files."
34
+ end
35
+
36
+ def style
37
+ @style ||= (env = ENV['SASS_STYLE']) ? env.to_sym : :nested
38
+ end
39
+ end
31
40
  end
@@ -1,3 +1,3 @@
1
1
  module Bunch
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ class MiddlewareTest < Test::Unit::TestCase
4
+ context 'the Middleware class' do
5
+ setup do
6
+ @app = Bunch::Middleware.new(nil,
7
+ :root_url => '/javascripts',
8
+ :path => '/example/js'
9
+ )
10
+ @mock = mock
11
+ @mock.expects(:call).returns([200, {}, ['hello']])
12
+ end
13
+
14
+ should 'ignore requests without the correct url' do
15
+ @app.app = @mock
16
+ perform_request('/not_javascripts/hello.html')
17
+ assert_equal @body, 'hello'
18
+ end
19
+
20
+ should 'pass on requests with the correct url' do
21
+ @app.endpoint = @mock
22
+ perform_request('/javascripts/hello.js')
23
+ assert_equal @body, 'hello'
24
+ end
25
+ end
26
+ end
@@ -1,4 +1,83 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class RackTest < Test::Unit::TestCase
4
+ context 'given a tree of js and coffee files' do
5
+ setup do
6
+ @app = Bunch::Rack.new('example/js')
7
+ Bunch::CoffeeNode.bare = true
8
+ end
9
+
10
+ context 'when / is requested' do
11
+ setup do
12
+ perform_request
13
+ end
14
+
15
+ should 'combine everything' do
16
+ assert_equal "1 2 3 4 5 6 7 8 9 10", squeeze(@body)
17
+ end
18
+
19
+ should 'have text/plain content type' do
20
+ assert_equal 'text/plain', @headers['Content-Type']
21
+ end
22
+ end
23
+
24
+ context 'when /all.js is requested' do
25
+ setup do
26
+ perform_request('/.js')
27
+ end
28
+
29
+ should 'combine everything in the correct order' do
30
+ assert_equal "1 2 3 4 5 6 7 8 9 10", squeeze(@body)
31
+ end
32
+
33
+ should 'have application/javascript content type' do
34
+ assert_equal "application/javascript", @headers['Content-Type']
35
+ end
36
+ end
37
+
38
+ context 'with a subfolder of js files' do
39
+ setup do
40
+ perform_request('/test2.js')
41
+ end
42
+
43
+ should 'combine everything in that folder and nothing else' do
44
+ assert_equal "2 3 4", squeeze(@body)
45
+ assert %w(1 5 6 7 8 9 10).all? { |n| !@body.include?(n) }
46
+ end
47
+ end
48
+
49
+ context 'with a subfolder containing another folder' do
50
+ context 'when the outer folder is requested' do
51
+ setup do
52
+ perform_request('/test3.js')
53
+ end
54
+
55
+ should 'combine the contents of both folders in the correct order' do
56
+ assert_equal "5 6 7", squeeze(@body)
57
+ end
58
+ end
59
+
60
+ context 'when the inner folder is requested' do
61
+ setup do
62
+ perform_request('/test3/test3b.js')
63
+ end
64
+
65
+ should 'only render the inner folder' do
66
+ assert_equal "6 7", squeeze(@body)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'given a tree of scss files' do
73
+ setup do
74
+ @app = Bunch::Rack.new('example/css')
75
+ perform_request('/all.css')
76
+ end
77
+
78
+ should 'work' do
79
+ assert_equal "body { a: 1 } body { b: 2 } body { c: 3 }", squeeze(@body)
80
+ assert_equal "text/css", @headers['Content-Type']
81
+ end
82
+ end
4
83
  end
@@ -2,3 +2,20 @@ $:.unshift File.expand_path('../../lib', __FILE__)
2
2
 
3
3
  require 'bunch'
4
4
  require 'test/unit'
5
+ require 'mocha'
6
+ require 'shoulda-context'
7
+
8
+ # collapse whitespace and remove semicolons
9
+ def squeeze(js)
10
+ js.tr("\n;", ' ').strip.squeeze
11
+ end
12
+
13
+ # perform a request for the given path and set @status, @headers, and @body.
14
+ def perform_request(path='/')
15
+ env = {
16
+ 'REQUEST_METHOD' => 'GET',
17
+ 'PATH_INFO' => path
18
+ }
19
+ out = @app.call(env)
20
+ @status, @headers, @body = out[0], out[1], out[2].join
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-06 00:00:00.000000000 Z
12
+ date: 2012-01-13 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mime-types
16
- requirement: &70318786120460 !ruby/object:Gem::Requirement
16
+ requirement: &70109863646520 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,21 +21,21 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70318786120460
24
+ version_requirements: *70109863646520
25
25
  - !ruby/object:Gem::Dependency
26
- name: slop
27
- requirement: &70318786100960 !ruby/object:Gem::Requirement
26
+ name: yard
27
+ requirement: &70109863645580 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
31
31
  - !ruby/object:Gem::Version
32
32
  version: '0'
33
- type: :runtime
33
+ type: :development
34
34
  prerelease: false
35
- version_requirements: *70318786100960
35
+ version_requirements: *70109863645580
36
36
  - !ruby/object:Gem::Dependency
37
- name: yard
38
- requirement: &70318786099000 !ruby/object:Gem::Requirement
37
+ name: rdiscount
38
+ requirement: &70109863644420 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,21 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70318786099000
46
+ version_requirements: *70109863644420
47
47
  - !ruby/object:Gem::Dependency
48
- name: rdiscount
49
- requirement: &70318786097560 !ruby/object:Gem::Requirement
48
+ name: shoulda-context
49
+ requirement: &70109863643200 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70109863643200
58
+ - !ruby/object:Gem::Dependency
59
+ name: mocha
60
+ requirement: &70109863642720 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,7 +65,7 @@ dependencies:
54
65
  version: '0'
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *70318786097560
68
+ version_requirements: *70109863642720
58
69
  description: Directory-structure-based asset bundling.
59
70
  email:
60
71
  - rfitz@academia.edu
@@ -99,6 +110,7 @@ files:
99
110
  - lib/bunch/rack.rb
100
111
  - lib/bunch/sass_node.rb
101
112
  - lib/bunch/version.rb
113
+ - test/middleware_test.rb
102
114
  - test/rack_test.rb
103
115
  - test/test_helper.rb
104
116
  homepage: ''
@@ -121,11 +133,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
133
  version: '0'
122
134
  requirements: []
123
135
  rubyforge_project: bunch
124
- rubygems_version: 1.8.10
136
+ rubygems_version: 1.8.11
125
137
  signing_key:
126
138
  specification_version: 3
127
139
  summary: Directory-structure-based asset bundling.
128
140
  test_files:
141
+ - test/middleware_test.rb
129
142
  - test/rack_test.rb
130
143
  - test/test_helper.rb
131
144
  has_rdoc: