public
Fork of rack/rack-contrib
Description: Contributed Rack Middleware and Utilities
Homepage:
Clone URL: git://github.com/peburrows/rack-contrib.git
rack-contrib / lib / rack / contrib / cssvariables.rb
100644 73 lines (60 sloc) 2.639 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
require 'erb'
require 'fileutils'
 
class CSSVariables
  File = ::File
  
  def initialize(app, options={})
    @app = app
    app_env = defined?(RAILS_ENV) ? RAILS_ENV : 'development'
    web_root = defined?(RAILS_ROOT) ? File.join(RAILS_ROOT, 'public') : File.join(File.dirname(__FILE__), '/public')
 
    defaults = {:env => app_env,
                :production => [:production],
                :parser => 'ERB',
                :stylesheets_path => '/stylesheets/',
                :web_root => web_root }
                
    @options = defaults.merge(options)
    @options[:production] = @options[:production].is_a?(Array) ? @options[:production] : [@options[:production]]
  end
  
  def call(env)
    path = env['REQUEST_PATH']
    unless path =~ /\.css$/ && path =~ /^#{@options[:stylesheets_path] || @options[:stylesheet_path]}/
      # this isn't a stylesheet that is in the directory we care about (so, it'll probably raise a 404, but whatever)
      return @app.call(env)
    end
    
    variables_file = File.join(@options[:templates], 'variables.rb')
    if File.exists?(variables_file)
      if @options[:production].include?(@options[:env])
        require variables_file
      else
        load variables_file
      end
    end
  
    template_path = path.sub(/^#{@options[:stylesheets_path] || @options[:stylesheet_path]}/, '')
    @file = File.join(@options[:templates], template_path)
  
    if File.exists?(@file)
      content = eval(@options[:parser]).send(:render, File.read(@file), binding)
      length = content.respond_to?(:bytesize) ? content.bytesize.to_s : content.size.to_s
    
      if @options[:production].include?(@options[:env].to_sym)
        # make sure the directory exists
        new_dir = File.dirname(File.join(@options[:web_root], path))
        puts "the new dir is: #{new_dir}"
        FileUtils.mkdir_p(new_dir) unless File.exists?(new_dir)
        # if we're in production, write the file to the system...
        File.open(File.join(@options[:web_root], path), 'w') do |f|
          puts "[Rack::Middleware - CssVariables] writing #{path} to the public directory"
          f.write(content)
        end
      end
    
      [200, {'Content-Type' => 'text/css', 'Content-Length' => length}, [content]]
    else
      @app.call(env)
    end
  end
  
end
 
 
# give ERB the ability to respond to ERB.render(content), because, to standardize things,
# that's how the CssVariables middleware will call the parser
module ErbRenderHack
  def render(content, _bind=binding)
    new(content, nil, '-').result(_bind)
  end
end
ERB.extend(ErbRenderHack)