big_band 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/LICENSE +27 -0
  2. data/README.rdoc +303 -0
  3. data/README.rdoc.erb +39 -0
  4. data/Rakefile +129 -0
  5. data/big_band.gemspec +29 -0
  6. data/example/example.rb +13 -0
  7. data/example/views/index.haml +8 -0
  8. data/example/views/layout.haml +2 -0
  9. data/example/views/stylesheets/_base.sass +1 -0
  10. data/example/views/stylesheets/screen.sass +12 -0
  11. data/lib/big_band/advanced_routes.rb +184 -0
  12. data/lib/big_band/basic_extensions.rb +176 -0
  13. data/lib/big_band/compass/big_band.rb +4 -0
  14. data/lib/big_band/compass/stylesheets/_big_band.sass +1 -0
  15. data/lib/big_band/compass/stylesheets/big_band/_blueprint.sass +1 -0
  16. data/lib/big_band/compass/stylesheets/big_band/_utilities.sass +6 -0
  17. data/lib/big_band/compass/stylesheets/big_band/blueprint/_html5.sass +4 -0
  18. data/lib/big_band/compass/stylesheets/big_band/layouts/_inspector.sass +103 -0
  19. data/lib/big_band/compass/stylesheets/big_band/utilities/_border_radius.sass +27 -0
  20. data/lib/big_band/compass/stylesheets/big_band/utilities/_css3_prefix.sass +14 -0
  21. data/lib/big_band/compass/stylesheets/big_band/utilities/_fancy_buttons.sass +62 -0
  22. data/lib/big_band/compass/stylesheets/big_band/utilities/_html5.sass +3 -0
  23. data/lib/big_band/compass.rb +94 -0
  24. data/lib/big_band/files/overlay-button.png +0 -0
  25. data/lib/big_band/integration/bacon.rb +10 -0
  26. data/lib/big_band/integration/monk.rb +26 -0
  27. data/lib/big_band/integration/rake.rb +60 -0
  28. data/lib/big_band/integration/rspec.rb +11 -0
  29. data/lib/big_band/integration/test/spec.rb +2 -0
  30. data/lib/big_band/integration/test/unit.rb +2 -0
  31. data/lib/big_band/integration/test.rb +42 -0
  32. data/lib/big_band/integration/test_spec.rb +8 -0
  33. data/lib/big_band/integration/test_unit.rb +10 -0
  34. data/lib/big_band/integration/yard.rb +104 -0
  35. data/lib/big_band/integration.rb +42 -0
  36. data/lib/big_band/more_helpers.rb +50 -0
  37. data/lib/big_band/more_server/rainbows.rb +13 -0
  38. data/lib/big_band/more_server/unicorn.rb +28 -0
  39. data/lib/big_band/more_server.rb +14 -0
  40. data/lib/big_band/reloader.rb +113 -0
  41. data/lib/big_band/sass.rb +28 -0
  42. data/lib/big_band/version.rb +3 -0
  43. data/lib/big_band/web_inspector.rb +178 -0
  44. data/lib/big_band.rb +239 -0
  45. data/lib/big_bang.rb +6 -0
  46. data/lib/yard-sinatra.rb +2 -0
  47. data/spec/big_band/advanced_routes_spec.rb +70 -0
  48. data/spec/big_band/basic_extensions_spec.rb +39 -0
  49. data/spec/big_band/more_server_spec.rb +7 -0
  50. data/spec/big_band/sass_spec.rb +21 -0
  51. data/spec/spec.opts +5 -0
  52. data/spec/spec_helper.rb +4 -0
  53. data/yard-sinatra.gemspec +24 -0
  54. metadata +167 -0
@@ -0,0 +1,184 @@
1
+ require "sinatra/base"
2
+
3
+ class BigBand < Sinatra::Base
4
+
5
+ # AdvancedRoutes makes routes first class objects in Sinatra:
6
+ #
7
+ # require "sinatra"
8
+ # require "big_band"
9
+ #
10
+ # admin_route = get "/admin" do
11
+ # administrate_stuff
12
+ # end
13
+ #
14
+ # before do
15
+ # # Let's deactivate the route if we have no password file.
16
+ # if File.exists? "admin_password"
17
+ # admin_route.activate
18
+ # else
19
+ # admin_route.deactivate
20
+ # end
21
+ # end
22
+ #
23
+ # first_route = get "/:name" do
24
+ # # stuff
25
+ # end
26
+ #
27
+ # other_route = get "/foo_:name" do
28
+ # # other stuff
29
+ # end
30
+ #
31
+ # # Unfortunatly first_route will catch all the requests other_route would
32
+ # # have gotten, since it has been defined first. But wait, we can fix this!
33
+ # other_route.promote
34
+ module AdvancedRoutes
35
+
36
+ module ArrayMethods
37
+ ::Array.send :include, self
38
+
39
+ def to_route(verb, args = {})
40
+ dup.to_route! verb, args
41
+ end
42
+
43
+ def to_route!(verb, args = {})
44
+ extend BigBand::AdvancedRoutes::Route
45
+ self.verb = verb
46
+ args.each do |key, value|
47
+ send "#{key}=", value
48
+ end
49
+ self
50
+ end
51
+
52
+ def signature
53
+ self
54
+ end
55
+
56
+ end
57
+
58
+ module Route
59
+
60
+ attr_accessor :app, :verb, :file, :line, :path
61
+
62
+ def pattern; self[0]; end
63
+ def keys; self[1]; end
64
+ def conditions; self[2]; end
65
+ def block; self[3]; end
66
+ alias to_proc block
67
+
68
+ def pattern=(value); self[0] = value; end
69
+ def keys=(value); self[1] = value; end
70
+ def conditions=(value); self[2] = value; end
71
+ def block=(value); self[3] = value; end
72
+
73
+ def signature
74
+ [pattern, keys, conditions, block]
75
+ end
76
+
77
+ def active?
78
+ app.routes[verb].include? self
79
+ end
80
+
81
+ def activate(at_top = false)
82
+ also_change.each { |r| r.activate }
83
+ return if active?
84
+ meth = at_top ? :unshift : :push
85
+ (app.routes[verb] ||= []).send(meth, self)
86
+ invoke_hook :route_added, verb, path, block
87
+ invoke_hook :advanced_root_activated, self
88
+ self
89
+ end
90
+
91
+ def deactivate
92
+ also_change.each { |r| r.deactivate }
93
+ return unless active?
94
+ (app.routes[verb] ||= []).delete(signature)
95
+ invoke_hook :route_removed, verb, path, block
96
+ invoke_hook :advanced_root_deactivated, self
97
+ self
98
+ end
99
+
100
+ def promote(upwards = true)
101
+ also_change.each { |r| r.promote(upwards) }
102
+ deactivate
103
+ activate(upwards)
104
+ end
105
+
106
+ def file?
107
+ !!@file
108
+ end
109
+
110
+ def inspect
111
+ "#<BigBand::AdvancedRoutes::Route #{ivar_inspect.join ", "}>"
112
+ end
113
+
114
+ def to_route(verb, args = {})
115
+ args = args.dup
116
+ [:app, :verb, :file, :line, :path].each { |key| args[key] ||= send(key) }
117
+ super(verb, args)
118
+ end
119
+
120
+ def also_change(*other_routes)
121
+ (@also_change ||= []).push(*other_routes)
122
+ end
123
+
124
+ private
125
+
126
+ def ivar_inspect
127
+ [:signature, :verb, :app, :file, :line].map do |var|
128
+ value = send(var)
129
+ "@#{var}=#{value.inspect}" unless value.nil?
130
+ end.compact
131
+ end
132
+
133
+ def invoke_hook(*args)
134
+ app.send(:invoke_hook, *args)
135
+ end
136
+
137
+ end
138
+
139
+ module ClassMethods
140
+
141
+ def get(path, opts={}, &block)
142
+ first_route, *other_routes = capture_routes { super }
143
+ first_route.also_change(*other_routes)
144
+ first_route
145
+ end
146
+
147
+ def route(verb, path, options={}, &block)
148
+ file, line = block.source_location if block.respond_to? :source_location
149
+ file ||= caller_files.first
150
+ route = super(verb, path, options, &block)
151
+ route.to_route! verb, :app => self, :file => file.expand_path, :line => line, :path => path
152
+ invoke_hook :advanced_root_added, route
153
+ @capture_routes << route if @capture_routes
154
+ route
155
+ end
156
+
157
+ def each_route(&block)
158
+ return enum_for(:each_route) if respond_to? :enum_for and not block
159
+ routes.inject([]) { |result, (verb, list)| result.push *list.each(&block) }
160
+ end
161
+
162
+ private
163
+
164
+ def capture_routes
165
+ capture_routes_was, @capture_routes = @capture_routes, []
166
+ yield
167
+ captured, @capture_routes = @capture_routes, capture_routes_was
168
+ captured
169
+ end
170
+
171
+ end
172
+
173
+ def self.registered(klass)
174
+ klass.extend ClassMethods
175
+ klass.routes.each do |verb, routes|
176
+ routes.each do |route|
177
+ route.to_route! verb, :app => klass
178
+ klass.send :invoke_hook, :advanced_root_added, route
179
+ end
180
+ end
181
+ end
182
+
183
+ end
184
+ end
@@ -0,0 +1,176 @@
1
+ require "sinatra/base"
2
+ require "monkey-lib"
3
+
4
+ class BigBand < Sinatra::Base
5
+
6
+ CALLERS_TO_IGNORE = (class << Sinatra::Base; CALLERS_TO_IGNORE; end) unless defined? CALLERS_TO_IGNORE
7
+ Dir.chdir __FILE__.dirname.dirname do
8
+ Dir.glob("**/*.rb") { |file| CALLERS_TO_IGNORE << Regexp.new(Regexp.escape(file)) }
9
+ end
10
+
11
+ # Basic Sinatra extension (mainly extending Sinatra's standard methods, like set or register).
12
+ # Also it features a more advanced path guessing than Sinatra::Base.
13
+ # Normally you do not have to register this module manually, as the other extensions will do so
14
+ # if necessary.
15
+ module BasicExtensions
16
+ module ClassMethods
17
+
18
+ attr_writer :root, :guessed_root
19
+
20
+ # More advanced set:
21
+ # - Adds set_#{key} and set_value hooks to set.
22
+ # - Merges the old value with the new one, if both are hashes:
23
+ # set :haml, :format => :html5, :escape_html => true
24
+ # set :haml, :excape_html => false
25
+ # haml # => { :format => :html5, :escape_html => false }
26
+ # - Allowes passing a block:
27
+ # set(:foo) { Time.now }
28
+ # - Defines a helper to access #{key} and #{key}? unless a helper/method with that name already exists.
29
+ def set(key, value = self, &block)
30
+ # FIXME: refactor, refactor, refactor
31
+ if block_given?
32
+ raise ArgumentError, "both a value and a block given" if value != self
33
+ value = block
34
+ end
35
+ symbolized = (key.to_sym if key.respond_to? :to_sym)
36
+ old_value = (send(symbolized) if symbolized and respond_to? symbolized)
37
+ value = old_value.merge value if value.is_a? Hash and old_value.is_a? Hash
38
+ super(key, value)
39
+ if symbolized
40
+ method_names = instance_methods.map { |m| m.to_s }
41
+ define_method(key) { self.class.send(key) } unless method_names.include? key.to_s
42
+ define_method("#{key}?") { self.class.send("#{key}?") } unless method_names.include? "#{key}?"
43
+ end
44
+ # HACK: Sinatra::Base.set uses recursion and in the final step value always
45
+ # is a Proc. Also, if value is a Proc no step ever follows. I abuse this to
46
+ # invoke the hooks only once per set.
47
+ if value.is_a? Proc
48
+ invoke_hook "set_#{key}", self
49
+ invoke_hook :set_value, self, key
50
+ end
51
+ self
52
+ end
53
+
54
+ # More advacend register:
55
+ # - If an exntesion is registered twice, the registered hook will only be called once.
56
+ def register(*extensions, &block)
57
+ extensions.reject! { |e| self.extensions.include? e }
58
+ super(*extensions, &block)
59
+ end
60
+
61
+ # Short hand so you can skip those ugly File.expand_path(File.join(File.dirname(__FILE__), ...))
62
+ # lines.
63
+ def root_path(*args)
64
+ relative = File.join(*args)
65
+ return relative if relative.expand_path == relative
66
+ root.expand_path / relative
67
+ end
68
+
69
+ # Like root_path, but does return an array instead of a string. Optionally takes a block that will
70
+ # be called for each entry once.
71
+ #
72
+ # Example:
73
+ # class Foo < BigBand
74
+ # root_glob("app", "{models,views,controllers}", "*.rb") { |file| load file }
75
+ # end
76
+ def root_glob(*args, &block)
77
+ Dir.glob(root_path(*args), &block)
78
+ end
79
+
80
+ # Whether or not to start a webserver.
81
+ def run?
82
+ @run ||= true
83
+ @run and !@running and app_file? and $0.expand_path == app_file.expand_path
84
+ end
85
+
86
+ # Disable automatically running this class as soon it is subclassed.
87
+ def inherited
88
+ super
89
+ @run = false
90
+ end
91
+
92
+ # The application's root directory. BigBand will guess if missing.
93
+ def root
94
+ return ".".expand_path unless app_file?
95
+ return @root if @root
96
+ @guessed_root ||= begin
97
+ dir = app_file.expand_path.dirname
98
+ if dir.basename == "lib" and not (dir / "lib").directory?
99
+ dir.dirname
100
+ else
101
+ dir
102
+ end
103
+ end
104
+ end
105
+
106
+ # Returns true if the #root is known.
107
+ def root?
108
+ !!@root || app_file?
109
+ end
110
+
111
+ # Option parser for #run!
112
+ def run_option_parser
113
+ @run_option_parser ||= begin
114
+ require 'optparse'
115
+ OptionParser.new do |op|
116
+ op.on('-x') { set :lock, true }
117
+ op.on('-e env') { |val| set :environment, val.to_sym }
118
+ op.on('-s server') { |val| set :server, val }
119
+ op.on('-p port') { |val| set :port, val.to_i }
120
+ end
121
+ end
122
+ end
123
+
124
+ # Extended #run!, offers an extandable option parser for
125
+ # BigBand with the same standard options as the one of
126
+ # Sinatra#Default (see #run_option_parser).
127
+ def run!(options = {})
128
+ run_option_parser.parse!(ARGV.dup) unless ARGV.empty?
129
+ @running = true
130
+ super(options)
131
+ end
132
+
133
+ end
134
+
135
+ module InstanceMethods
136
+
137
+ # See BigBand::BasicExtentions::ClassMethods#root_path
138
+ def root_path(*args)
139
+ self.class.root_path(*args)
140
+ end
141
+
142
+ # See BigBand::BasicExtentions::ClassMethods#root_path
143
+ def root_glob(*args, &block)
144
+ self.class.root_glob(*args, &block)
145
+ end
146
+
147
+ # See BigBand::BasicExtentions::ClassMethods#root
148
+ def root
149
+ self.class.root
150
+ end
151
+
152
+ # See BigBand::BasicExtentions::ClassMethods#root?
153
+ def root?
154
+ self.class.root
155
+ end
156
+
157
+ end
158
+
159
+ def self.registered(klass)
160
+ klass.set :app_file, klass.caller_files.first.expand_path unless klass.app_file?
161
+ klass.extend ClassMethods
162
+ klass.send :include, InstanceMethods
163
+ klass.set :haml, :format => :html5, :escape_html => true
164
+ klass.use Rack::Session::Cookie
165
+ klass.enable :sessions
166
+ klass.get %r{/__big_band__/([^\.]+(\.[^\.]+)?)} do
167
+ send_file(__FILE__.expand_path.dirname / :files / params[:captures].first)
168
+ end
169
+ end
170
+
171
+ def self.set_app_file(klass)
172
+ klass.guessed_root = nil
173
+ end
174
+
175
+ end
176
+ end
@@ -0,0 +1,4 @@
1
+ require "compass"
2
+ require "big_band/compass"
3
+
4
+ Compass::Frameworks.register 'big_band', File.expand_path(File.dirname(__FILE__))
@@ -0,0 +1 @@
1
+ @import big_band/utilities.sass
@@ -0,0 +1 @@
1
+ @import blueprint/html5.sass
@@ -0,0 +1,6 @@
1
+ @import compass/reset.sass
2
+ @import compass/utilities.sass
3
+ @import utilities/border_radius.sass
4
+ @import utilities/css3_prefix.sass
5
+ @import utilities/fancy_buttons.sass
6
+ @import utilities/html5.sass
@@ -0,0 +1,4 @@
1
+ @import ../utilities/html5.sass
2
+
3
+ =blueprint_html5
4
+ +html5
@@ -0,0 +1,103 @@
1
+ @import ../utilities.sass
2
+ @import blueprint.sass
3
+ @import blueprint/screen.sass
4
+ @import blueprint/modules/fancy_type.sass
5
+ @import blueprint/modules/scaffolding.sass
6
+ @import blueprint/modules/typography.sass
7
+
8
+ =layout_inspector
9
+ +html5
10
+ +blueprint-typography
11
+ +fancy-paragraphs
12
+ body
13
+ padding: 5em 1em
14
+ background-color: #ddd
15
+ color
16
+ header
17
+ +box-shadow(0 2px 15px rgba(0, 0, 0, 0.8))
18
+ padding: 0px 10px
19
+ text-align: right
20
+ font-size: 80%
21
+ background:
22
+ color: rgba(0, 0, 0, 0.5)
23
+ image: url(/__big_band__/overlay-button.png)
24
+ repeat: repeat-x
25
+ border-bottom: solid 2px #333
26
+ color: #333
27
+ position: fixed
28
+ top: 0
29
+ right: 0
30
+ width: 100%
31
+ nav
32
+ a
33
+ +fancy-button-link(#040, 20px, 100px)
34
+ margin: 5px
35
+ h1
36
+ font:
37
+ weight: 500
38
+ size: 40px
39
+ margin: 0px
40
+ float: left
41
+ padding-left: 20px
42
+ color: #333
43
+ text-shadow: 0px 1px 2px rgba(0,0,0,0.8), -1px -1px 3px #eee, 0px 0px 8px rgba(0,0,0,0.7)
44
+ h2
45
+ font:
46
+ weight: bold
47
+ size: 130%
48
+ border-bottom: dotted 1px #bbb
49
+ width: 500px
50
+ table
51
+ +box-shadow(0px 3px 10px rgba(0,0,0,0.7))
52
+ border: solid 1px #555
53
+ background:
54
+ color: #fff
55
+ image: url(/__big_band__/overlay-button.png)
56
+ padding: 0px
57
+ width: 80%
58
+ margin: 0px 10%
59
+ tr
60
+ th, td
61
+ padding:
62
+ bottom: 0
63
+ top: 0
64
+ left: 5px
65
+ right: 20px
66
+ th
67
+ background-color: #555
68
+ color: #fff
69
+ font:
70
+ weight: bold
71
+ size: 90%
72
+ td
73
+ border:
74
+ color: #ddd
75
+ style: solid
76
+ width: 0px
77
+ left-width: 1px
78
+ min-width: 80px
79
+ footer
80
+ margin-top: 20px
81
+ +alt
82
+ a
83
+ color: #040
84
+ text-decoration: none
85
+ &:hover, &:visited
86
+ color: #040
87
+ &:hover
88
+ text-decoration: underline
89
+ .note
90
+ +box-shadow(0px 3px 10px rgba(0,0,0,0.7))
91
+ +border-radius
92
+ margin:
93
+ top: 5px
94
+ left: 10%
95
+ right: 10%
96
+ bottom: 20px
97
+ padding: 2px
98
+ background-color: #eee
99
+ text-align: center
100
+ font-size: 110%
101
+ a
102
+ font-weight: bold
103
+
@@ -0,0 +1,27 @@
1
+ @import "css3_prefix.sass"
2
+
3
+ !default_border_radius = 10px
4
+
5
+ =border-radius(!lt = "auto", !rt = "auto", !rb = "auto", !lb = "auto")
6
+ @if !lt == "auto"
7
+ !lt = !default_border_radius
8
+ @if !rt == "auto"
9
+ !rt = !lt
10
+ @if !rb == "auto"
11
+ !rb = !lt
12
+ @if !lb == "auto"
13
+ !lb = !rt
14
+ min-width = max(!lt + !rt, !lb + !rb)
15
+ min-height = max(!lt + !lb, !rt + !rb)
16
+ +border-radius-no-min-size(!lt, !rt, !rb, !lb)
17
+
18
+ =border-radius-no-min-size(!lt, !rt, !rb, !lb)
19
+ +prefixed("border-top-left-radius", !lt)
20
+ +prefixed("border-top-right-radius", !rt)
21
+ +prefixed("border-bottom-left-radius", !lb)
22
+ +prefixed("border-bottom-right-radius", !rb)
23
+ -moz-border-radius:
24
+ topleft = !lt
25
+ topright = !rt
26
+ bottomright = !rb
27
+ bottomleft = !lb
@@ -0,0 +1,14 @@
1
+ =prefixed(!attribute, !value)
2
+ -moz-#{!attribute} = !value
3
+ -webkit-#{!attribute} = !value
4
+ -khtml-#{!attribute} = !value
5
+ -ms-#{!attribute} = !value
6
+ -o-#{!attribute} = !value
7
+ #{!attribute} = !value
8
+
9
+ =box-shadow(!parameters)
10
+ +prefixed(box-shadow, !parameters)
11
+
12
+ =transition(!property, !duration)
13
+ +prefixed("transition-property", !property)
14
+ +prefixed("transition-duration", !duration)
@@ -0,0 +1,62 @@
1
+ @import border_radius.sass
2
+ @import css3_prefix.sass
3
+
4
+ !fancy_button_color = #222
5
+ !fancy_button_height = 30px
6
+ !fancy_button_width = "auto"
7
+ !fancy_button_radius = "auto"
8
+ !fancy_button_darkening = 0.3
9
+
10
+ =fancy-button(!color = !fancy_button_color, !height = !fancy_button_height, !width = !fancy_button_width, !radius = !fancy_button_radius)
11
+ @if !radius == "auto"
12
+ !radius = !height
13
+ @if !height < !radius * 2
14
+ !radius = !height / 2
15
+ +border-radius(!radius)
16
+ +box-shadow(0 1px 10px rgba(0, 0, 0, 0.6))
17
+ text-shadow = 0 -1px (!height * 0.1) rgba(0,0,0,0.7)
18
+ border-bottom: 1px solid rgba(0, 0, 0, 0.25)
19
+ background:
20
+ color = !color
21
+ image: url(/__big_band__/overlay-button.png)
22
+ repeat: repeat-x
23
+ attachment: scroll
24
+ position:
25
+ top: 0
26
+ left: 0
27
+ display: inline-block
28
+ padding = (!height * 0.1 - 1px) (!height * 0.5)
29
+ color: #fff !important
30
+ text:
31
+ decoration: none
32
+ align: center
33
+ -moz-background:
34
+ clip: border
35
+ inline-policy: continuous
36
+ font:
37
+ family: Arial,Helvetica,Helvetica Neue,Verdana,sans-serif
38
+ weight: bold
39
+ size = !height * 0.8
40
+ height = !height !important
41
+ width = !width
42
+ line-height: 1.2
43
+
44
+ =fancy-button-link(!color = !fancy_button_color, !height = !fancy_button_height, !width = !fancy_button_width, !radius = !fancy_button_radius, !darkening = !fancy_button_darkening)
45
+ !offset = !height * 0.1 + 3px
46
+ +fancy-button(!color, !height, !width, !radius)
47
+ +prefixed("transition-property", "background, left, top, box-shadow, -moz-box-shadow, -webkit-box-shadow")
48
+ +prefixed("transition-duration", "0.5s")
49
+ position: relative
50
+ top: 0
51
+ left: 0
52
+ cursor: pointer
53
+ margin = !offset
54
+ &:hover
55
+ +fancy-button(!color * !darkening, !height, !width, !radius)
56
+ +box-shadow(!offset !offset + 1px !offset + 10px rgba(0, 0, 0, 0.5))
57
+ left = -!offset
58
+ top = -!offset
59
+ &:visited, &:hover
60
+ color = !color
61
+ text-decoration: none
62
+
@@ -0,0 +1,3 @@
1
+ =html5
2
+ header, footer, nav
3
+ display: block
@@ -0,0 +1,94 @@
1
+ require "sinatra/base"
2
+ require "big_band/basic_extensions"
3
+ require "big_band/advanced_routes"
4
+ require "big_band/compass/big_band"
5
+ require "big_band/sass"
6
+
7
+ class BigBand < Sinatra::Base
8
+
9
+ # Integrates the Compass stylesheet framework with Sinatra.
10
+ #
11
+ # Usage without doing something:
12
+ #
13
+ # require "big_band"
14
+ # class Foo < BigBand; end
15
+ #
16
+ # If you create a directory called views/stylesheets and place your
17
+ # sass files in there, there you go. Just call stylesheet(name) form
18
+ # your view to get the correct stylesheet tag. The URL for your
19
+ # stylesheets will be /stylesheets/:name.css.
20
+ #
21
+ # Of course you can use any other setup. Say, you want to store your
22
+ # stylesheets in views/css and want the URL to be /css/:name.css:
23
+ #
24
+ # class Foo < BigBand
25
+ # get_compass("css")
26
+ # end
27
+ #
28
+ # But what about more complex setups?
29
+ #
30
+ # class Foo < BigBand
31
+ # set :compass, :sass_dir => "/foo/bar/blah"
32
+ # get_compass("/foo/:name.css") do
33
+ # compass :one_stylesheet
34
+ # end
35
+ # end
36
+ #
37
+ # Note that already generated routes will be deactivated by calling
38
+ # get_compass again.
39
+ module Compass
40
+
41
+ module ClassMethods
42
+ attr_reader :compass_route
43
+ def get_compass(path, &block)
44
+ block ||= Proc.new do |file|
45
+ content_type 'text/css', :charset => 'utf-8'
46
+ compass :"#{path}/#{params[:name]}"
47
+ end
48
+ set :compass, :sass_dir => klass.views / path unless compass[:sass_dir] && compass[:sass_dir].directory?
49
+ @compass_route.deactivate if @compass_route
50
+ @compass_route = get("/#{path}" / ":name.css", &block)
51
+ end
52
+ end
53
+
54
+ module InstanceMethods
55
+ def compass(file, options = {})
56
+ options.merge! ::Compass.sass_engine_options
57
+ sass file, options
58
+ end
59
+ def stylesheet(*args)
60
+ raise NotImplementedError, "yet to be implemented"
61
+ end
62
+ end
63
+
64
+ def self.registered(klass)
65
+ klass.register BasicExtensions
66
+ klass.register AdvancedRoutes
67
+ klass.extend ClassMethods
68
+ klass.send :include, InstanceMethods
69
+ klass.set :compass,
70
+ :project_path => klass.root_path, :output_style => (klass.development? ? :expanded : :compressed),
71
+ :sass_dir => klass.views / "stylesheets", :line_comments => klass.development?
72
+ set_app_file(klass) if klass.app_file?
73
+ end
74
+
75
+ def self.set_app_file(klass)
76
+ klass.set :compass, :root_path => klass.root_path
77
+ klass.get_compass("stylesheets") if (klass.views / "stylesheets").directory?
78
+ end
79
+
80
+ def self.set_compass(klass)
81
+ ::Compass.configuration do |config|
82
+ config.sass_options ||= {}
83
+ klass.compass.each do |option, value|
84
+ if config.respond_to? option
85
+ config.send "#{option}=", value
86
+ else
87
+ config.sass_options.merge! option.to_sym => value
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ end
94
+ end