bunch 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .sass-cache
6
+ .yardoc
7
+ doc/*
@@ -0,0 +1 @@
1
+ --markup markdown --private
@@ -0,0 +1,4 @@
1
+ Bunch: (Almost) configuration-free asset bundling.
2
+ ==================================================
3
+
4
+ <img src="http://i.imgur.com/QqufL.png">
data/Rakefile CHANGED
@@ -1 +1,18 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'yard'
5
+ YARD::Rake::YardocTask.new
6
+ rescue LoadError
7
+ end
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
16
+ end
17
+
18
+ task :default => :test
@@ -1,23 +1,26 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "bunch/version"
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'bunch/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.name = "bunch"
6
+ s.name = 'bunch'
7
7
  s.version = Bunch::VERSION
8
- s.authors = ["Ryan Fitzgerald"]
9
- s.email = ["rfitz@academia.edu"]
10
- s.homepage = ""
8
+ s.authors = ['Ryan Fitzgerald']
9
+ s.email = ['rfitz@academia.edu']
10
+ s.homepage = ''
11
11
  s.summary = %q{Directory-structure-based asset bundling.}
12
12
  s.description = %q{Directory-structure-based asset bundling.}
13
13
 
14
- s.rubyforge_project = "bunch"
14
+ s.rubyforge_project = 'bunch'
15
15
 
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ["lib"]
19
+ s.require_paths = ['lib']
20
20
 
21
- s.add_runtime_dependency "mime-types"
22
- s.add_runtime_dependency "slop"
21
+ s.add_runtime_dependency 'mime-types'
22
+ s.add_runtime_dependency 'slop'
23
+
24
+ s.add_development_dependency 'yard'
25
+ s.add_development_dependency 'rdiscount'
23
26
  end
@@ -14,7 +14,9 @@ end
14
14
  require 'bunch/version'
15
15
  require 'bunch/rack'
16
16
  require 'bunch/middleware'
17
- require 'bunch/caching'
17
+ require 'bunch/cache'
18
+
19
+ require 'bunch/abstract_node'
18
20
  require 'bunch/directory_node'
19
21
  require 'bunch/file_node'
20
22
  require 'bunch/coffee_node'
@@ -41,7 +43,7 @@ class << Bunch
41
43
  end
42
44
  end
43
45
 
44
- private
46
+ protected
45
47
  def normalized_path(path)
46
48
  case
47
49
  when File.exist?(path)
@@ -57,14 +59,3 @@ class << Bunch
57
59
  end
58
60
  end
59
61
  end
60
-
61
- #class Module
62
- # def benchmark(meth)
63
- # alias_method "#{meth}_old", meth
64
- # define_method meth do |*args, &blk|
65
- # t = Time.now
66
- # send "#{meth}_old", *args, &blk
67
- # STDERR.puts "Called #{meth} in #{Time.now - t}."
68
- # end
69
- # end
70
- #end
@@ -0,0 +1,23 @@
1
+ module Bunch
2
+ class AbstractNode
3
+ def content
4
+ raise NotImplementedError
5
+ end
6
+ alias name content
7
+ alias target_extension content
8
+
9
+ def write_to_dir(dir)
10
+ write_to_file(File.join(dir, name))
11
+ end
12
+
13
+ def write_to_file(fn)
14
+ out_file = "#{fn}#{target_extension}"
15
+ File.open(out_file, 'w') { |f| f.write(content) }
16
+ end
17
+
18
+ protected
19
+ def fetch(fn, &blk)
20
+ Cache.fetch(fn, &blk)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module Bunch
2
+ module Cache
3
+ end
4
+
5
+ class << Cache
6
+ def initialize
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.initialize
40
+ end
@@ -5,10 +5,6 @@ module Bunch
5
5
  @output = output ? Pathname.new(output) : nil
6
6
  @opts = opts
7
7
 
8
- if @opts[:profile]
9
- require 'profile'
10
- end
11
-
12
8
  if @opts[:server]
13
9
  run_server
14
10
  else
@@ -33,7 +29,7 @@ module Bunch
33
29
 
34
30
  if @opts[:all]
35
31
  if @output
36
- write("all.#{tree.target_extension}", tree.content)
32
+ tree.write_to_file(@output.join('all'))
37
33
  else
38
34
  puts tree.content
39
35
  end
@@ -41,15 +37,10 @@ module Bunch
41
37
 
42
38
  if @opts[:individual]
43
39
  tree.children.each do |child|
44
- write("#{child.name}.#{child.target_extension}", child.content)
40
+ child.write_to_dir(@output)
45
41
  end
46
42
  end
47
43
  end
48
-
49
- private
50
- def write(fn, content)
51
- File.open(@output.join(fn), 'w') { |f| f.write(content) }
52
- end
53
44
  end
54
45
 
55
46
  class << CLI
@@ -60,7 +51,6 @@ module Bunch
60
51
  on :s, :server, 'Instead of creating files, use WEBrick to serve files from INPUT_PATH'
61
52
  on :i, :individual, 'Create one output file for each file or directory in the input path (default)', :default => true
62
53
  on :a, :all, 'Create an all.[extension] file combining all inputs'
63
- on :p, :profile
64
54
  on :h, :help, 'Show this message' do
65
55
  puts self
66
56
  exit
@@ -1,7 +1,5 @@
1
1
  module Bunch
2
- class CoffeeNode
3
- include Caching
4
-
2
+ class CoffeeNode < FileNode
5
3
  def initialize(fn)
6
4
  unless defined?(@@coffee_required)
7
5
  require 'coffee-script'
@@ -21,11 +19,7 @@ module Bunch
21
19
  end
22
20
 
23
21
  def target_extension
24
- 'js'
25
- end
26
-
27
- def inspect
28
- @filename.inspect
22
+ '.js'
29
23
  end
30
24
  end
31
25
  end
@@ -1,5 +1,5 @@
1
1
  module Bunch
2
- class DirectoryNode
2
+ class DirectoryNode < AbstractNode
3
3
  attr_reader :root
4
4
 
5
5
  def initialize(fn)
@@ -30,8 +30,10 @@ module Bunch
30
30
  exts = children.map(&:target_extension).compact.uniq
31
31
  if exts.count == 1
32
32
  exts.first
33
+ elsif exts.count > 1
34
+ raise "Directory #{name} contains non-homogeneous nodes: #{exts.inspect}"
33
35
  else
34
- raise "Directory contains non-homogeneous nodes: #{exts.inspect}"
36
+ nil
35
37
  end
36
38
  end
37
39
  end
@@ -44,6 +46,11 @@ module Bunch
44
46
  File.basename(@root)
45
47
  end
46
48
 
49
+ def write_to_file(dir)
50
+ return if filenames.count == 0
51
+ super
52
+ end
53
+
47
54
  def inspect
48
55
  "#<DirectoryNode @root=#{@root.inspect} @children=#{children.inspect}>"
49
56
  end
@@ -1,15 +1,16 @@
1
1
  module Bunch
2
- class FileNode
3
- attr_reader :name, :target_extension
2
+ class FileNode < AbstractNode
3
+ attr_accessor :name, :target_extension
4
4
 
5
5
  def initialize(fn)
6
6
  @filename = fn
7
7
 
8
- if fn =~ %r(\.([^.]*)$)
8
+ if fn =~ /\.[^.]*$/
9
9
  @name = File.basename($`)
10
- @target_extension = $1
10
+ @target_extension = $&
11
11
  else
12
12
  @name = File.basename(@filename)
13
+ @target_extension = nil
13
14
  end
14
15
  end
15
16
 
@@ -33,9 +33,47 @@ module Bunch
33
33
  end
34
34
  end
35
35
 
36
- private
36
+ protected
37
37
  def root_regexp
38
38
  Regexp.new("^#{Regexp.quote(@root_url).gsub('/', '/+')}(.*)")
39
39
  end
40
40
  end
41
+
42
+ class << Middleware
43
+ # Binds an instance of `Bunch::Middleware` in front of any instance
44
+ # of the given middleware class. Whenever `klass` is instantiated,
45
+ # any calls to `klass#call` will first pass through the single
46
+ # instance of `Middleware` created by this method.
47
+ #
48
+ # You can compose any number of `Middleware` instances in front
49
+ # of the same class.
50
+ #
51
+ # In practice, the purpose of this is to allow Bunch to take
52
+ # precedence over `Rails::Rack::Static` in a Rails 2 context.
53
+ # Since the server's instance of `Rails::Rack::Static` isn't part of
54
+ # the `ActionController` stack, it isn't possible to use
55
+ # Rails' normal middleware tools to insert Bunch in front of it,
56
+ # which means any files in `public` would be served preferentially.
57
+ #
58
+ # @param [Class] klass Any Rack middleware class.
59
+ # @param [Hash] options The options that would normally be passed to
60
+ # `Bunch::Middleware#initialize`.
61
+ #
62
+ # @example
63
+ # if Rails.env.development?
64
+ # Bunch::Middleware.insert_before Rails::Rack::Static,
65
+ # root_url: '/javascripts', path: 'app/scripts', no_cache: true
66
+ # end
67
+ def insert_before(klass, options={})
68
+ instance = new(nil, options)
69
+
70
+ klass.class_eval do
71
+ unbound_call = instance_method(:call)
72
+ define_method(:call) do |env|
73
+ instance.app = unbound_call.bind(self)
74
+ instance.call(env)
75
+ end
76
+ end
77
+ end
78
+ end
41
79
  end
@@ -20,11 +20,6 @@ module Bunch
20
20
  [500, headers('text/plain'), [error_log(e)]]
21
21
  end
22
22
 
23
- private
24
- def headers(mime_type)
25
- @headers.merge('Content-Type' => mime_type.to_s)
26
- end
27
-
28
23
  private
29
24
  def content_for(path)
30
25
  Bunch.content_for(path)
@@ -1,19 +1,23 @@
1
1
  module Bunch
2
- class SassNode
3
- include Caching
4
-
2
+ class SassNode < FileNode
5
3
  def initialize(fn)
6
4
  unless defined?(@@sass_required)
7
5
  require 'sass'
8
6
  @@sass_required = true
9
7
  end
8
+
9
+ unless defined?(@@sass_style)
10
+ @@sass_style = ENV['SASS_STYLE'] || 'nested'
11
+ puts @@sass_style.inspect
12
+ end
13
+
10
14
  @filename = fn
11
15
  rescue LoadError
12
16
  raise "'gem install sass' to compile .sass and .scss files."
13
17
  end
14
18
 
15
19
  def content
16
- @content ||= fetch(@filename) { Sass::Engine.for_file(@filename, {}).render }
20
+ @content ||= fetch(@filename) { Sass::Engine.for_file(@filename, :style => @@sass_style.to_sym).render }
17
21
  end
18
22
 
19
23
  def name
@@ -21,11 +25,7 @@ module Bunch
21
25
  end
22
26
 
23
27
  def target_extension
24
- 'css'
25
- end
26
-
27
- def inspect
28
- @filename.inspect
28
+ '.css'
29
29
  end
30
30
  end
31
31
  end
@@ -1,3 +1,3 @@
1
1
  module Bunch
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class RackTest < Test::Unit::TestCase
4
+ end
@@ -0,0 +1,4 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'bunch'
4
+ require 'test/unit'
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.6
4
+ version: 0.0.7
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-03 00:00:00.000000000 Z
12
+ date: 2012-01-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mime-types
16
- requirement: &70177706384580 !ruby/object:Gem::Requirement
16
+ requirement: &70318786120460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70177706384580
24
+ version_requirements: *70318786120460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: slop
27
- requirement: &70177706384160 !ruby/object:Gem::Requirement
27
+ requirement: &70318786100960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,29 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70177706384160
35
+ version_requirements: *70318786100960
36
+ - !ruby/object:Gem::Dependency
37
+ name: yard
38
+ requirement: &70318786099000 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70318786099000
47
+ - !ruby/object:Gem::Dependency
48
+ name: rdiscount
49
+ requirement: &70318786097560 !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: *70318786097560
36
58
  description: Directory-structure-based asset bundling.
37
59
  email:
38
60
  - rfitz@academia.edu
@@ -42,7 +64,9 @@ extensions: []
42
64
  extra_rdoc_files: []
43
65
  files:
44
66
  - .gitignore
67
+ - .yardopts
45
68
  - Gemfile
69
+ - README.md
46
70
  - Rakefile
47
71
  - bin/bunch
48
72
  - bunch.gemspec
@@ -65,7 +89,8 @@ files:
65
89
  - example/js/test4/test4b.coffee
66
90
  - example/js/test4/test4c.coffee
67
91
  - lib/bunch.rb
68
- - lib/bunch/caching.rb
92
+ - lib/bunch/abstract_node.rb
93
+ - lib/bunch/cache.rb
69
94
  - lib/bunch/cli.rb
70
95
  - lib/bunch/coffee_node.rb
71
96
  - lib/bunch/directory_node.rb
@@ -74,6 +99,8 @@ files:
74
99
  - lib/bunch/rack.rb
75
100
  - lib/bunch/sass_node.rb
76
101
  - lib/bunch/version.rb
102
+ - test/rack_test.rb
103
+ - test/test_helper.rb
77
104
  homepage: ''
78
105
  licenses: []
79
106
  post_install_message:
@@ -98,5 +125,7 @@ rubygems_version: 1.8.10
98
125
  signing_key:
99
126
  specification_version: 3
100
127
  summary: Directory-structure-based asset bundling.
101
- test_files: []
128
+ test_files:
129
+ - test/rack_test.rb
130
+ - test/test_helper.rb
102
131
  has_rdoc:
@@ -1,42 +0,0 @@
1
- module Bunch
2
- module Caching
3
- class << self
4
- def initialize_cache
5
- @cache = Hash.new { |h, k| h[k] = {} }
6
- end
7
-
8
- def stored?(fn)
9
- @cache.keys.include?(fn)
10
- end
11
-
12
- def read(fn)
13
- @cache[fn][:content]
14
- end
15
-
16
- def mtime(fn)
17
- @cache[fn][:mtime]
18
- end
19
-
20
- def write(fn, mtime, content)
21
- @cache[fn] = {:mtime => mtime, :content => content}
22
- end
23
-
24
- def fetch(fn, &blk)
25
- current_mtime = File.mtime(fn)
26
-
27
- if stored?(fn) && mtime(fn) == current_mtime
28
- read(fn)
29
- else
30
- content = blk.call
31
- write(fn, current_mtime, content)
32
- content
33
- end
34
- end
35
- end
36
- initialize_cache
37
-
38
- def fetch(filename, &blk)
39
- Bunch::Caching.fetch(filename, &blk)
40
- end
41
- end
42
- end