bunch 0.2.2 → 1.0.0pre1
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.
- checksums.yaml +7 -0
 - data/.gitignore +15 -6
 - data/Gemfile +3 -1
 - data/Guardfile +5 -0
 - data/LICENSE.txt +22 -0
 - data/Rakefile +7 -12
 - data/bin/bunch +2 -5
 - data/bunch.gemspec +30 -23
 - data/lib/bunch.rb +37 -81
 - data/lib/bunch/cli.rb +40 -74
 - data/lib/bunch/combiner.rb +121 -0
 - data/lib/bunch/compiler.rb +52 -0
 - data/lib/bunch/compilers/coffee_script.rb +23 -0
 - data/lib/bunch/compilers/ejs.rb +28 -0
 - data/lib/bunch/compilers/jade.rb +28 -0
 - data/lib/bunch/compilers/jst.rb +38 -0
 - data/lib/bunch/compilers/null.rb +19 -0
 - data/lib/bunch/compilers/sass.rb +55 -0
 - data/lib/bunch/content_hash.rb +37 -0
 - data/lib/bunch/css_minifier.rb +121 -0
 - data/lib/bunch/file.rb +18 -0
 - data/lib/bunch/file_cache.rb +159 -0
 - data/lib/bunch/file_tree.rb +153 -0
 - data/lib/bunch/ignorer.rb +38 -0
 - data/lib/bunch/js_minifier.rb +38 -0
 - data/lib/bunch/middleware.rb +16 -67
 - data/lib/bunch/pipeline.rb +30 -0
 - data/lib/bunch/server.rb +56 -0
 - data/lib/bunch/simple_cache.rb +36 -0
 - data/lib/bunch/tree_merge.rb +29 -0
 - data/lib/bunch/version.rb +3 -1
 - data/spec/bunch/cli_spec.rb +85 -0
 - data/spec/bunch/combiner_spec.rb +107 -0
 - data/spec/bunch/compiler_spec.rb +73 -0
 - data/spec/bunch/compilers/coffee_script_spec.rb +23 -0
 - data/spec/bunch/compilers/ejs_spec.rb +27 -0
 - data/spec/bunch/compilers/jade_spec.rb +28 -0
 - data/spec/bunch/compilers/sass_spec.rb +120 -0
 - data/spec/bunch/css_minifier_spec.rb +31 -0
 - data/spec/bunch/file_cache_spec.rb +151 -0
 - data/spec/bunch/file_tree_spec.rb +127 -0
 - data/spec/bunch/ignorer_spec.rb +26 -0
 - data/spec/bunch/js_minifier_spec.rb +35 -0
 - data/spec/bunch/middleware_spec.rb +41 -0
 - data/spec/bunch/pipeline_spec.rb +31 -0
 - data/spec/bunch/server_spec.rb +90 -0
 - data/spec/bunch/simple_cache_spec.rb +55 -0
 - data/spec/bunch/tree_merge_spec.rb +30 -0
 - data/spec/bunch_spec.rb +6 -0
 - data/spec/example_tree/directory/_combine +2 -0
 - data/{example/js/test1.js → spec/example_tree/directory/file1} +0 -0
 - data/{example/js/test2/test2a.js → spec/example_tree/directory/file2} +0 -0
 - data/{example/js/test2/test2c.js → spec/example_tree/file3} +0 -0
 - data/spec/spec_helper.rb +38 -0
 - metadata +224 -102
 - data/.yardopts +0 -1
 - data/README.md +0 -4
 - data/config.ru +0 -6
 - data/example/config.ru +0 -6
 - data/example/css/test1.css +0 -1
 - data/example/css/test2/test2a.scss +0 -1
 - data/example/css/test2/test2b.css +0 -1
 - data/example/js/.bunchignore +0 -1
 - data/example/js/test2/_.yml +0 -2
 - data/example/js/test2/foo.js +0 -1
 - data/example/js/test2/test2b.js +0 -1
 - data/example/js/test3/test3a.js +0 -1
 - data/example/js/test3/test3b/_.yml +0 -1
 - data/example/js/test3/test3b/test3bi.js +0 -1
 - data/example/js/test3/test3b/test3bii.js +0 -1
 - data/example/js/test4/_.yml +0 -1
 - data/example/js/test4/test4a.js +0 -1
 - data/example/js/test4/test4b.coffee +0 -1
 - data/example/js/test4/test4c.coffee +0 -1
 - data/example/js/test5/test5a.jst.ejs +0 -1
 - data/lib/bunch/abstract_node.rb +0 -25
 - data/lib/bunch/cache.rb +0 -40
 - data/lib/bunch/coffee_node.rb +0 -39
 - data/lib/bunch/directory_node.rb +0 -82
 - data/lib/bunch/ejs_node.rb +0 -50
 - data/lib/bunch/file_node.rb +0 -25
 - data/lib/bunch/jade_node.rb +0 -50
 - data/lib/bunch/null_node.rb +0 -11
 - data/lib/bunch/rack.rb +0 -38
 - data/lib/bunch/sass_node.rb +0 -39
 - data/test/middleware_test.rb +0 -26
 - data/test/rack_test.rb +0 -93
 - data/test/test_helper.rb +0 -21
 
| 
         @@ -0,0 +1,121 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Combiner
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(tree)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @input  = tree
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @output = FileTree.new
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def result
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @path = []
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @contexts = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @input.accept(self)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @output
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def enter_tree(tree)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  if tree.name
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @path << tree.name
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    combine_file = tree.get("_combine")
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    if combine_file || combining?
         
     | 
| 
      
 24 
     | 
    
         
            +
                      ordering = combine_file ? combine_file.content : ""
         
     | 
| 
      
 25 
     | 
    
         
            +
                      push_context Context.new(@path, ordering)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def leave_tree(tree)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  if tree.name
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @path.pop
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  if combining?
         
     | 
| 
      
 36 
     | 
    
         
            +
                    this_context = pop_context
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    if this_context.empty?
         
     | 
| 
      
 39 
     | 
    
         
            +
                      # do nothing
         
     | 
| 
      
 40 
     | 
    
         
            +
                    elsif combining?
         
     | 
| 
      
 41 
     | 
    
         
            +
                      context.add tree.path, this_context.content, this_context.extension
         
     | 
| 
      
 42 
     | 
    
         
            +
                    else
         
     | 
| 
      
 43 
     | 
    
         
            +
                      write_file tree.path, this_context.content, this_context.extension
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def visit_file(file)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  return if file.path == "_combine"
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  if combining?
         
     | 
| 
      
 52 
     | 
    
         
            +
                    context.add file.path, file.content, file.extension
         
     | 
| 
      
 53 
     | 
    
         
            +
                  else
         
     | 
| 
      
 54 
     | 
    
         
            +
                    write_file file.path, file.content
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                private
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def write_file(relative_path, content, extension = "")
         
     | 
| 
      
 61 
     | 
    
         
            +
                  path = absolute_path(relative_path) + extension
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @output.write path, content
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def absolute_path(relative_path)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  [*@path, relative_path].join("/")
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def push_context(hash)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  @contexts.push hash
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def pop_context
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @contexts.pop
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def context
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @contexts.last
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def combining?
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @contexts.any?
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                class Context
         
     | 
| 
      
 86 
     | 
    
         
            +
                  attr_accessor :ordering, :extension
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  def initialize(path, ordering_file_contents)
         
     | 
| 
      
 89 
     | 
    
         
            +
                    @path = path.join("/")
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @content = {}
         
     | 
| 
      
 91 
     | 
    
         
            +
                    @ordering = ordering_file_contents.split("\n")
         
     | 
| 
      
 92 
     | 
    
         
            +
                    @extension = nil
         
     | 
| 
      
 93 
     | 
    
         
            +
                    @empty = true
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  def add(path, content, extension)
         
     | 
| 
      
 97 
     | 
    
         
            +
                    @content[path.chomp(extension)] = content
         
     | 
| 
      
 98 
     | 
    
         
            +
                    @extension ||= extension
         
     | 
| 
      
 99 
     | 
    
         
            +
                    @empty = false
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                    if @extension != extension
         
     | 
| 
      
 102 
     | 
    
         
            +
                      message = "Incompatible types ('#{extension}' vs '#{@path}/#{path}')"
         
     | 
| 
      
 103 
     | 
    
         
            +
                      message << "\n  #{@content.keys.join(', ')}"
         
     | 
| 
      
 104 
     | 
    
         
            +
                      raise message
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  def content
         
     | 
| 
      
 109 
     | 
    
         
            +
                    ordered, unordered = \
         
     | 
| 
      
 110 
     | 
    
         
            +
                      @content.partition { |fn, _| @ordering.include?(fn) }
         
     | 
| 
      
 111 
     | 
    
         
            +
                    ordered.sort_by!   { |fn, _| @ordering.index(fn) }
         
     | 
| 
      
 112 
     | 
    
         
            +
                    unordered.sort_by! { |fn, _| fn }
         
     | 
| 
      
 113 
     | 
    
         
            +
                    (ordered + unordered).map(&:last).join("\n")
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  def empty?
         
     | 
| 
      
 117 
     | 
    
         
            +
                    @empty
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Compiler
         
     | 
| 
      
 5 
     | 
    
         
            +
                def self.register(extension, klass)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  compilers[extension] = klass
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def self.compilers
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @compilers ||= {}
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def initialize(tree)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @input  = tree
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @output = FileTree.new
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def result
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @path = []
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @input.accept(self)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @output
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def enter_tree(tree)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @path << tree.name if tree.name
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def leave_tree(tree)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @path.pop if tree.name
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def visit_file(file)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  compiler = compiler_for file
         
     | 
| 
      
 34 
     | 
    
         
            +
                  write_file compiler.path, compiler.content
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                private
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def compiler_for(file)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  klass = self.class.compilers.fetch file.extension, Compilers::Null
         
     | 
| 
      
 41 
     | 
    
         
            +
                  klass.new file, @input, absolute_path(file.path)
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def write_file(relative_path, content)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @output.write absolute_path(relative_path), content
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def absolute_path(relative_path)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  (@path + [relative_path]).join("/")
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Compilers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class CoffeeScript
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(file, *)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    require "coffee-script"
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @file = file
         
     | 
| 
      
 9 
     | 
    
         
            +
                  rescue LoadError => e
         
     | 
| 
      
 10 
     | 
    
         
            +
                    raise "'gem install coffee-script' to compile .coffee files."
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def path
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @file.path.chomp(".coffee") + ".js"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def content
         
     | 
| 
      
 18 
     | 
    
         
            +
                    ::CoffeeScript.compile(@file.content)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
              Compiler.register ".coffee", Compilers::CoffeeScript
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "bunch/compilers/jst"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Compilers
         
     | 
| 
      
 7 
     | 
    
         
            +
                class EJS < JST
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(*)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    super
         
     | 
| 
      
 10 
     | 
    
         
            +
                    require "ejs"
         
     | 
| 
      
 11 
     | 
    
         
            +
                  rescue LoadError => e
         
     | 
| 
      
 12 
     | 
    
         
            +
                    raise "'gem install ejs' to compile .ejs files."
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  private
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def compile(content)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    ::EJS.compile content
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def extension
         
     | 
| 
      
 22 
     | 
    
         
            +
                    ".ejs"
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
              Compiler.register ".jst.ejs", Compilers::EJS
         
     | 
| 
      
 27 
     | 
    
         
            +
              Compiler.register ".ejs", Compilers::EJS
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "bunch/compilers/jst"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Compilers
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Jade < JST
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(*)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    require "ruby-jade"
         
     | 
| 
      
 10 
     | 
    
         
            +
                    super
         
     | 
| 
      
 11 
     | 
    
         
            +
                  rescue LoadError => e
         
     | 
| 
      
 12 
     | 
    
         
            +
                    raise "'gem install ruby-jade' to compile .jade files."
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  private
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def compile(content)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    ::Jade.compile content
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def extension
         
     | 
| 
      
 22 
     | 
    
         
            +
                    ".jade"
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
              Compiler.register ".jst.jade", Compilers::Jade
         
     | 
| 
      
 27 
     | 
    
         
            +
              Compiler.register ".jade", Compilers::Jade
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Compilers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class JST
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(file, _, path)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @file, @path = file, path
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def path
         
     | 
| 
      
 11 
     | 
    
         
            +
                    "#{template_name}.js"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def content
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @content ||= <<-JAVASCRIPT
         
     | 
| 
      
 16 
     | 
    
         
            +
                      (function() {
         
     | 
| 
      
 17 
     | 
    
         
            +
                        this.JST || (this.JST = {});
         
     | 
| 
      
 18 
     | 
    
         
            +
                        this.JST['#{template_name}'] = #{compile(@file.content)};
         
     | 
| 
      
 19 
     | 
    
         
            +
                      })();
         
     | 
| 
      
 20 
     | 
    
         
            +
                    JAVASCRIPT
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  private
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def compile(content)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    # override in subclasses
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def extension
         
     | 
| 
      
 30 
     | 
    
         
            +
                    # override in subclasses
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def template_name
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @path.chomp(extension).chomp(".jst")
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Compilers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Sass
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(file, tree, path)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    require "sass"
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @file, @tree, @abs_path = file, tree, path
         
     | 
| 
      
 9 
     | 
    
         
            +
                  rescue LoadError => e
         
     | 
| 
      
 10 
     | 
    
         
            +
                    raise "'gem install sass' to compile .sass and .scss files."
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def path
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @file.path.sub(/\.s[ca]ss$/, "") + ".css"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def content
         
     | 
| 
      
 18 
     | 
    
         
            +
                    new_engine(@file.content, @abs_path).render
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def new_engine(content, path)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    syntax = path.end_with?("scss") ? :scss : :sass
         
     | 
| 
      
 23 
     | 
    
         
            +
                    ::Sass::Engine.new(
         
     | 
| 
      
 24 
     | 
    
         
            +
                      content, syntax: syntax, filename: path, importer: self)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  ## Sass importer interface ##
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def find_relative(path, base, options)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    abs = ::File.expand_path("../#{path}", "/#{base}")[1..-1]
         
     | 
| 
      
 31 
     | 
    
         
            +
                    find(abs, options)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def find(path, options)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    path = path.chomp(".scss").chomp(".sass")
         
     | 
| 
      
 36 
     | 
    
         
            +
                    path_with_underscore = path.sub(/(.*)\//, '\1/_')
         
     | 
| 
      
 37 
     | 
    
         
            +
                    file = @tree.get_fuzzy(path) || @tree.get_fuzzy(path_with_underscore)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    if file
         
     | 
| 
      
 39 
     | 
    
         
            +
                      new_engine(file.content, file.path)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    else
         
     | 
| 
      
 41 
     | 
    
         
            +
                      raise "Couldn't find '#{path}' to import! (#{options[:original_filename]}:#{options[:_line]})"
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def mtime(path, options)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def key(path, options)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    ["Bunch:#{::File.dirname(path)}", ::File.basename(path)]
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
              Compiler.register ".sass", Compilers::Sass
         
     | 
| 
      
 54 
     | 
    
         
            +
              Compiler.register ".scss", Compilers::Sass
         
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "digest/md5"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 6 
     | 
    
         
            +
              class ContentHash
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(file_or_tree)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @input = file_or_tree
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def result
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @path = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @hash = 0
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @input.accept(self)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @hash
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def enter_tree(tree)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @path << tree.name if tree.name
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def leave_tree(tree)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @path.pop if tree.name
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def visit_file(file)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  file_path = [*@path, file.path].join("/")
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @hash ^= truncated_md5("#{file_path}:#{file.content}")
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                private
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def truncated_md5(string)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  Digest::MD5.digest(string)[0..4].unpack("L")[0]
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,121 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Includes a copy of CSSMin, written by Ryan Grove and based on work by
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Julien Lecomte and Isaac Schlueter.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # CSSMin License:
         
     | 
| 
      
 7 
     | 
    
         
            +
            # Copyright (c) 2008 Ryan Grove <ryan@wonko.com>
         
     | 
| 
      
 8 
     | 
    
         
            +
            # All rights reserved.
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 11 
     | 
    
         
            +
            # modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            #   * Redistributions of source code must retain the above copyright notice,
         
     | 
| 
      
 14 
     | 
    
         
            +
            #     this list of conditions and the following disclaimer.
         
     | 
| 
      
 15 
     | 
    
         
            +
            #   * Redistributions in binary form must reproduce the above copyright notice,
         
     | 
| 
      
 16 
     | 
    
         
            +
            #     this list of conditions and the following disclaimer in the documentation
         
     | 
| 
      
 17 
     | 
    
         
            +
            #     and/or other materials provided with the distribution.
         
     | 
| 
      
 18 
     | 
    
         
            +
            #   * Neither the name of this project nor the names of its contributors may be
         
     | 
| 
      
 19 
     | 
    
         
            +
            #     used to endorse or promote products derived from this software without
         
     | 
| 
      
 20 
     | 
    
         
            +
            #     specific prior written permission.
         
     | 
| 
      
 21 
     | 
    
         
            +
            #
         
     | 
| 
      
 22 
     | 
    
         
            +
            # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         
     | 
| 
      
 23 
     | 
    
         
            +
            # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         
     | 
| 
      
 24 
     | 
    
         
            +
            # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         
     | 
| 
      
 25 
     | 
    
         
            +
            # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
         
     | 
| 
      
 26 
     | 
    
         
            +
            # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
         
     | 
| 
      
 27 
     | 
    
         
            +
            # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         
     | 
| 
      
 28 
     | 
    
         
            +
            # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
         
     | 
| 
      
 29 
     | 
    
         
            +
            # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
         
     | 
| 
      
 30 
     | 
    
         
            +
            # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         
     | 
| 
      
 31 
     | 
    
         
            +
            # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            module Bunch
         
     | 
| 
      
 34 
     | 
    
         
            +
              class CssMinifier
         
     | 
| 
      
 35 
     | 
    
         
            +
                def initialize(tree)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @input  = tree
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @output = FileTree.new
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def result
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @path = []
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @input.accept(self)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @output
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def enter_tree(tree)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @path << tree.name if tree.name
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def leave_tree(tree)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @path.pop if tree.name
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def visit_file(file)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  file_path = [*@path, file.path].join("/")
         
     | 
| 
      
 56 
     | 
    
         
            +
                  content = (file.extension == ".css") ? minify(file.content) : file.content
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @output.write file_path, content
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                private
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def minify(css)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # Remove comments.
         
     | 
| 
      
 64 
     | 
    
         
            +
                  css.gsub!(/\/\*[\s\S]*?\*\//, '')
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  # Compress all runs of whitespace to a single space to make things easier
         
     | 
| 
      
 67 
     | 
    
         
            +
                  # to work with.
         
     | 
| 
      
 68 
     | 
    
         
            +
                  css.gsub!(/\s+/, ' ')
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  # Replace box model hacks with placeholders.
         
     | 
| 
      
 71 
     | 
    
         
            +
                  css.gsub!(/"\\"\}\\""/, '___BMH___')
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  # Remove unnecessary spaces, but be careful not to turn "p :link {...}"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  # into "p:link{...}".
         
     | 
| 
      
 75 
     | 
    
         
            +
                  css.gsub!(/(?:^|\})[^\{:]+\s+:+[^\{]*\{/) do |match|
         
     | 
| 
      
 76 
     | 
    
         
            +
                    match.gsub(':', '___PSEUDOCLASSCOLON___')
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  css.gsub!(/\s+([!\{\};:>+\(\)\],])/, '\1')
         
     | 
| 
      
 79 
     | 
    
         
            +
                  css.gsub!('___PSEUDOCLASSCOLON___', ':')
         
     | 
| 
      
 80 
     | 
    
         
            +
                  css.gsub!(/([!\{\}:;>+\(\[,])\s+/, '\1')
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  # Add missing semicolons.
         
     | 
| 
      
 83 
     | 
    
         
            +
                  css.gsub!(/([^;\}])\}/, '\1;}')
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  # Replace 0(%, em, ex, px, in, cm, mm, pt, pc) with just 0.
         
     | 
| 
      
 86 
     | 
    
         
            +
                  css.gsub!(/([\s:])([+-]?0)(?:%|em|ex|px|in|cm|mm|pt|pc)/i, '\1\2')
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  # Replace 0 0 0 0; with 0.
         
     | 
| 
      
 89 
     | 
    
         
            +
                  css.gsub!(/:(?:0 )+0;/, ':0;')
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  # Replace background-position:0; with background-position:0 0;
         
     | 
| 
      
 92 
     | 
    
         
            +
                  css.gsub!('background-position:0;', 'background-position:0 0;')
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                  # Replace 0.6 with .6, but only when preceded by : or a space.
         
     | 
| 
      
 95 
     | 
    
         
            +
                  css.gsub!(/(:|\s)0+\.(\d+)/, '\1.\2')
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  # Convert rgb color values to hex values.
         
     | 
| 
      
 98 
     | 
    
         
            +
                  css.gsub!(/rgb\s*\(\s*([0-9,\s]+)\s*\)/) do |match|
         
     | 
| 
      
 99 
     | 
    
         
            +
                    '#' << $1.scan(/\d+/).map{|n| n.to_i.to_s(16).rjust(2, '0') }.join
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  # Compress color hex values, making sure not to touch values used in IE
         
     | 
| 
      
 103 
     | 
    
         
            +
                  # filters, since they would break.
         
     | 
| 
      
 104 
     | 
    
         
            +
                  css.gsub!(/([^"'=\s])(\s?)\s*#([0-9a-f])\3([0-9a-f])\4([0-9a-f])\5/i, '\1\2#\3\4\5')
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                  # Remove empty rules.
         
     | 
| 
      
 107 
     | 
    
         
            +
                  css.gsub!(/[^\}]+\{;\}\n/, '')
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  # Re-insert box model hacks.
         
     | 
| 
      
 110 
     | 
    
         
            +
                  css.gsub!('___BMH___', '"\"}\""')
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  # Put the space back in for media queries
         
     | 
| 
      
 113 
     | 
    
         
            +
                  css.gsub!(/\band\(/, 'and (')
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  # Prevent redundant semicolons.
         
     | 
| 
      
 116 
     | 
    
         
            +
                  css.gsub!(/;+\}/, '}')
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  css.strip
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
            end
         
     |