beans-middleman 1.0.5

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.
Files changed (85) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +15 -0
  3. data/Rakefile +9 -0
  4. data/bin/mm-build +15 -0
  5. data/bin/mm-init +37 -0
  6. data/bin/mm-preview +12 -0
  7. data/bin/mm-server +67 -0
  8. data/features/builder.feature +16 -0
  9. data/features/coffee-script.feature +7 -0
  10. data/features/generator.feature +8 -0
  11. data/features/helpers_auto_stylesheet_link_tag.feature +17 -0
  12. data/features/helpers_page_classes.feature +17 -0
  13. data/features/less-css.feature +7 -0
  14. data/features/minify_css.feature +22 -0
  15. data/features/minify_javascript.feature +12 -0
  16. data/features/padrino_helpers.feature +10 -0
  17. data/features/page_alias_and_layouts.feature +12 -0
  18. data/features/scss-support.feature +7 -0
  19. data/features/step_definitions/asset_host_steps.rb +7 -0
  20. data/features/step_definitions/builder_steps.rb +23 -0
  21. data/features/step_definitions/env.rb +3 -0
  22. data/features/step_definitions/generator_steps.rb +30 -0
  23. data/features/step_definitions/middleman_steps.rb +29 -0
  24. data/features/step_definitions/page_layout_steps.rb +13 -0
  25. data/features/w_asset_host.feature +12 -0
  26. data/features/x_automatic_image_sizes.feature +14 -0
  27. data/features/y_cache_buster.feature +22 -0
  28. data/features/z_relative_assets.feature +12 -0
  29. data/fixtures/test-app/config.rb +28 -0
  30. data/fixtures/test-app/public/images/blank.gif +0 -0
  31. data/fixtures/test-app/public/static.html +1 -0
  32. data/fixtures/test-app/public/stylesheets/auto-css.css +0 -0
  33. data/fixtures/test-app/public/stylesheets/static.css +2 -0
  34. data/fixtures/test-app/public/stylesheets/sub1/auto-css.css +0 -0
  35. data/fixtures/test-app/public/stylesheets/sub1/sub2/auto-css.css +0 -0
  36. data/fixtures/test-app/views/_partial.haml +1 -0
  37. data/fixtures/test-app/views/asset_host.html.haml +1 -0
  38. data/fixtures/test-app/views/auto-css.html.haml +1 -0
  39. data/fixtures/test-app/views/auto-image-sizes.html.haml +1 -0
  40. data/fixtures/test-app/views/cache-buster.html.haml +2 -0
  41. data/fixtures/test-app/views/custom-layout.html.haml +1 -0
  42. data/fixtures/test-app/views/index.html.haml +1 -0
  43. data/fixtures/test-app/views/inline-css.html.haml +4 -0
  44. data/fixtures/test-app/views/inline-js.html.haml +7 -0
  45. data/fixtures/test-app/views/javascripts/coffee_test.js.coffee +3 -0
  46. data/fixtures/test-app/views/layout.haml +6 -0
  47. data/fixtures/test-app/views/layouts/custom.haml +5 -0
  48. data/fixtures/test-app/views/padrino_test.html.haml +5 -0
  49. data/fixtures/test-app/views/page-classes.html.haml +1 -0
  50. data/fixtures/test-app/views/services/index.html.haml +1 -0
  51. data/fixtures/test-app/views/stylesheets/asset_host.css.sass +3 -0
  52. data/fixtures/test-app/views/stylesheets/relative_assets.css.sass +3 -0
  53. data/fixtures/test-app/views/stylesheets/site.css.sass +1 -0
  54. data/fixtures/test-app/views/stylesheets/site_scss.css.scss +1 -0
  55. data/fixtures/test-app/views/stylesheets/test_less.css.less +5 -0
  56. data/lib/middleman/assets.rb +33 -0
  57. data/lib/middleman/builder.rb +60 -0
  58. data/lib/middleman/config.ru +2 -0
  59. data/lib/middleman/features/asset_host.rb +22 -0
  60. data/lib/middleman/features/automatic_image_sizes/fastimage.rb +287 -0
  61. data/lib/middleman/features/automatic_image_sizes.rb +33 -0
  62. data/lib/middleman/features/cache_buster.rb +44 -0
  63. data/lib/middleman/features/code_ray.rb +12 -0
  64. data/lib/middleman/features/default_helpers.rb +61 -0
  65. data/lib/middleman/features/live_reload.rb +21 -0
  66. data/lib/middleman/features/minify_css.rb +10 -0
  67. data/lib/middleman/features/minify_javascript/rack.rb +31 -0
  68. data/lib/middleman/features/minify_javascript.rb +21 -0
  69. data/lib/middleman/features/partials.rb +15 -0
  70. data/lib/middleman/features/relative_assets.rb +36 -0
  71. data/lib/middleman/features/slickmap/template.html.haml +27 -0
  72. data/lib/middleman/features/slickmap.rb +89 -0
  73. data/lib/middleman/features/smush_pngs.rb +38 -0
  74. data/lib/middleman/features/ugly_haml.rb +8 -0
  75. data/lib/middleman/features.rb +37 -0
  76. data/lib/middleman/renderers/haml.rb +42 -0
  77. data/lib/middleman/renderers/sass.rb +70 -0
  78. data/lib/middleman/server.rb +165 -0
  79. data/lib/middleman/template/config.rbt +64 -0
  80. data/lib/middleman/template/views/index.html.haml +4 -0
  81. data/lib/middleman/template/views/layout.haml +13 -0
  82. data/lib/middleman/template/views/stylesheets/site.css.sass +27 -0
  83. data/lib/middleman/templater+dynamic_renderer.rb +26 -0
  84. data/lib/middleman.rb +15 -0
  85. metadata +452 -0
@@ -0,0 +1,3 @@
1
+ @import "compass"
2
+ h1
3
+ background: image-url("blank.gif")
@@ -0,0 +1 @@
1
+ @import "compass/reset"
@@ -0,0 +1 @@
1
+ @import "compass/reset";
@@ -0,0 +1,5 @@
1
+ @brand_color: #666666;
2
+
3
+ #header {
4
+ color: @brand_color;
5
+ }
@@ -0,0 +1,33 @@
1
+ module Middleman
2
+ module Assets
3
+ @@asset_handler_map = []
4
+ @@asset_handler_stack = []
5
+
6
+ def self.register(handler_name, &block)
7
+ if block_given?
8
+ @@asset_handler_stack << block
9
+ @@asset_handler_map << handler_name
10
+ end
11
+ end
12
+
13
+ def self.get_url(path, prefix="", request=nil)
14
+ @@asset_handler_stack.last.call(path, prefix, request)
15
+ end
16
+
17
+ def self.before(position, *args)
18
+ current_index = @@asset_handler_map.index(position)
19
+ return nil unless current_index
20
+
21
+ previous = current_index - 1
22
+ if (previous >= 0) && (previous < @@asset_handler_map.length)
23
+ @@asset_handler_stack[previous].call(*args)
24
+ else
25
+ nil
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ Middleman::Assets.register :base do |path, prefix, request|
32
+ path.include?("://") ? path : File.join(Middleman::Server.http_prefix || "/", prefix, path)
33
+ end
@@ -0,0 +1,60 @@
1
+ require 'middleman/server'
2
+ require 'templater'
3
+ require 'middleman/templater+dynamic_renderer.rb'
4
+
5
+ # Placeholder for any methods the builder needs to abstract to allow feature integration
6
+ module Middleman
7
+ class Builder < ::Templater::Generator
8
+
9
+ # Support all Tilt-enabled templates and treat js like a template
10
+ @@template_extensions = ::Tilt.mappings.keys << "js"
11
+
12
+ # Define source and desintation
13
+ def self.source_root; Dir.pwd; end
14
+ def destination_root; File.join(Dir.pwd, Middleman::Server.build_dir); end
15
+
16
+ # Override template to ask middleman for the correct extension to output
17
+ def self.template(name, *args, &block)
18
+ return if args[0].include?('layout')
19
+
20
+ args.first.split('/').each do |part|
21
+ return if part[0,1] == '_'
22
+ end
23
+
24
+ if (args[0] === args[1])
25
+ args[1] = args[0].gsub("#{File.basename(Middleman::Server.views)}/", "").gsub("#{File.basename(Middleman::Server.public)}/", "")
26
+ if File.extname(args[1]) != ".js"
27
+ args[1] = args[1].gsub!(File.extname(args[1]), "") if File.basename(args[1]).split('.').length > 2
28
+ end
29
+ end
30
+
31
+ super(name, *args, &block)
32
+ end
33
+
34
+ def self.file(name, *args, &block)
35
+ file_ext = File.extname(args[0])
36
+
37
+ return unless ::Tilt[file_ext].nil?
38
+
39
+ if (args[0] === args[1])
40
+ args[1] = args[0].gsub("#{File.basename(Middleman::Server.views)}/", "").gsub("#{File.basename(Middleman::Server.public)}/", "")
41
+ end
42
+ super(name, *args, &block)
43
+ end
44
+
45
+ def self.init!
46
+ glob! File.basename(Middleman::Server.public), @@template_extensions
47
+ glob! File.basename(Middleman::Server.views), @@template_extensions
48
+ end
49
+
50
+ def after_run
51
+ end
52
+ end
53
+
54
+ module Generators
55
+ extend ::Templater::Manifold
56
+ desc "Build a static site"
57
+
58
+ add :build, ::Middleman::Builder
59
+ end
60
+ end
@@ -0,0 +1,2 @@
1
+ require 'middleman'
2
+ run Middleman::Server
@@ -0,0 +1,22 @@
1
+ module Middleman::Features::AssetHost
2
+ class << self
3
+ def registered(app)
4
+ app.after_feature_init do
5
+ if Middleman::Server.asset_host.is_a?(Proc)
6
+ ::Compass.configuration.asset_host(&Middleman::Server.asset_host)
7
+ end
8
+ end
9
+
10
+ Middleman::Assets.register :asset_host do |path, prefix, request|
11
+ original_output = Middleman::Assets.before(:asset_host, path, prefix, request)
12
+
13
+ valid_extensions = %w(.png .gif .jpg .jpeg .js .css)
14
+
15
+ asset_prefix = Middleman::Server.asset_host.call(original_output)
16
+
17
+ File.join(asset_prefix, original_output)
18
+ end
19
+ end
20
+ alias :included :registered
21
+ end
22
+ end
@@ -0,0 +1,287 @@
1
+ # FastImage finds the size or type of an image given its uri.
2
+ # It is careful to only fetch and parse as much of the image as is needed to determine the result.
3
+ # It does this by using a feature of Net::HTTP that yields strings from the resource being fetched
4
+ # as soon as the packets arrive.
5
+ #
6
+ # No external libraries such as ImageMagick are used here, this is a very lightweight solution to
7
+ # finding image information.
8
+ #
9
+ # FastImage knows about GIF, JPEG, BMP and PNG files.
10
+ #
11
+ # FastImage can also read files from the local filesystem by supplying the path instead of a uri.
12
+ # In this case FastImage uses the open-uri library to read the file in chunks of 256 bytes until
13
+ # it has enough. This is possibly a useful bandwidth-saving feature if the file is on a network
14
+ # attached disk rather than truly local.
15
+ #
16
+ # === Examples
17
+ # require 'fastimage'
18
+ #
19
+ # FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
20
+ # => [266, 56]
21
+ # FastImage.type("http://stephensykes.com/images/pngimage")
22
+ # => :png
23
+ # FastImage.type("/some/local/file.gif")
24
+ # => :gif
25
+ #
26
+ # === References
27
+ # * http://snippets.dzone.com/posts/show/805
28
+ # * http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-without-loading-the-entire-file/
29
+ # * http://pennysmalls.com/2008/08/19/find-jpeg-dimensions-fast-in-ruby/
30
+ # * http://imagesize.rubyforge.org/
31
+ #
32
+ require 'net/https'
33
+ require 'open-uri'
34
+
35
+ class FastImage
36
+ attr_reader :size, :type
37
+
38
+ class FastImageException < StandardError # :nodoc:
39
+ end
40
+ class MoreCharsNeeded < FastImageException # :nodoc:
41
+ end
42
+ class UnknownImageType < FastImageException # :nodoc:
43
+ end
44
+ class ImageFetchFailure < FastImageException # :nodoc:
45
+ end
46
+ class SizeNotFound < FastImageException # :nodoc:
47
+ end
48
+
49
+ DefaultTimeout = 2
50
+
51
+ LocalFileChunkSize = 256
52
+
53
+ # Returns an array containing the width and height of the image.
54
+ # It will return nil if the image could not be fetched, or if the image type was not recognised.
55
+ #
56
+ # By default there is a timeout of 2 seconds for opening and reading from a remote server.
57
+ # This can be changed by passing a :timeout => number_of_seconds in the options.
58
+ #
59
+ # If you wish FastImage to raise if it cannot size the image for any reason, then pass
60
+ # :raise_on_failure => true in the options.
61
+ #
62
+ # FastImage knows about GIF, JPEG, BMP and PNG files.
63
+ #
64
+ # === Example
65
+ #
66
+ # require 'fastimage'
67
+ #
68
+ # FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
69
+ # => [266, 56]
70
+ # FastImage.size("http://stephensykes.com/images/pngimage")
71
+ # => [16, 16]
72
+ # FastImage.size("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
73
+ # => [500, 375]
74
+ # FastImage.size("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
75
+ # => [512, 512]
76
+ # FastImage.size("test/fixtures/test.jpg")
77
+ # => [882, 470]
78
+ # FastImage.size("http://pennysmalls.com/does_not_exist")
79
+ # => nil
80
+ # FastImage.size("http://pennysmalls.com/does_not_exist", :raise_on_failure=>true)
81
+ # => raises FastImage::ImageFetchFailure
82
+ # FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true)
83
+ # => raises FastImage::UnknownImageType
84
+ # FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true, :timeout=>0.01)
85
+ # => raises FastImage::ImageFetchFailure
86
+ # FastImage.size("http://stephensykes.com/images/faulty.jpg", :raise_on_failure=>true)
87
+ # => raises FastImage::SizeNotFound
88
+ #
89
+ # === Supported options
90
+ # [:timeout]
91
+ # Overrides the default timeout of 2 seconds. Applies both to reading from and opening the http connection.
92
+ # [:raise_on_failure]
93
+ # If set to true causes an exception to be raised if the image size cannot be found for any reason.
94
+ #
95
+ def self.size(uri, options={})
96
+ new(uri, options).size
97
+ end
98
+
99
+ # Returns an symbol indicating the image type fetched from a uri.
100
+ # It will return nil if the image could not be fetched, or if the image type was not recognised.
101
+ #
102
+ # By default there is a timeout of 2 seconds for opening and reading from a remote server.
103
+ # This can be changed by passing a :timeout => number_of_seconds in the options.
104
+ #
105
+ # If you wish FastImage to raise if it cannot find the type of the image for any reason, then pass
106
+ # :raise_on_failure => true in the options.
107
+ #
108
+ # === Example
109
+ #
110
+ # require 'fastimage'
111
+ #
112
+ # FastImage.type("http://stephensykes.com/images/ss.com_x.gif")
113
+ # => :gif
114
+ # FastImage.type("http://stephensykes.com/images/pngimage")
115
+ # => :png
116
+ # FastImage.type("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
117
+ # => :jpeg
118
+ # FastImage.type("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
119
+ # => :bmp
120
+ # FastImage.type("test/fixtures/test.jpg")
121
+ # => :jpeg
122
+ # FastImage.type("http://pennysmalls.com/does_not_exist")
123
+ # => nil
124
+ #
125
+ # === Supported options
126
+ # [:timeout]
127
+ # Overrides the default timeout of 2 seconds. Applies both to reading from and opening the http connection.
128
+ # [:raise_on_failure]
129
+ # If set to true causes an exception to be raised if the image type cannot be found for any reason.
130
+ #
131
+ def self.type(uri, options={})
132
+ new(uri, options.merge(:type_only=>true)).type
133
+ end
134
+
135
+ def initialize(uri, options={})
136
+ @property = options[:type_only] ? :type : :size
137
+ @timeout = options[:timeout] || DefaultTimeout
138
+ @uri = uri
139
+ begin
140
+ @parsed_uri = URI.parse(uri)
141
+ rescue URI::InvalidURIError
142
+ fetch_using_open_uri
143
+ else
144
+ if @parsed_uri.scheme == "http" || @parsed_uri.scheme == "https"
145
+ fetch_using_http
146
+ else
147
+ fetch_using_open_uri
148
+ end
149
+ end
150
+ raise SizeNotFound if options[:raise_on_failure] && @property == :size && !@size
151
+ rescue Timeout::Error, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET,
152
+ ImageFetchFailure, Net::HTTPBadResponse, EOFError, Errno::ENOENT
153
+ raise ImageFetchFailure if options[:raise_on_failure]
154
+ rescue NoMethodError # 1.8.7p248 can raise this due to a net/http bug
155
+ raise ImageFetchFailure if options[:raise_on_failure]
156
+ rescue UnknownImageType
157
+ raise UnknownImageType if options[:raise_on_failure]
158
+ end
159
+
160
+ private
161
+
162
+ def fetch_using_http
163
+ setup_http
164
+ @http.request_get(@parsed_uri.request_uri) do |res|
165
+ raise ImageFetchFailure unless res.is_a?(Net::HTTPSuccess)
166
+ res.read_body do |str|
167
+ break if parse_packet(str)
168
+ end
169
+ end
170
+ end
171
+
172
+ def setup_http
173
+ @http = Net::HTTP.new(@parsed_uri.host, @parsed_uri.port)
174
+ @http.use_ssl = (@parsed_uri.scheme == "https")
175
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
176
+ @http.open_timeout = @timeout
177
+ @http.read_timeout = @timeout
178
+ end
179
+
180
+ def fetch_using_open_uri
181
+ open(@uri) do |s|
182
+ while str = s.read(LocalFileChunkSize)
183
+ break if parse_packet(str)
184
+ end
185
+ end
186
+ end
187
+
188
+ # returns true once result is achieved
189
+ #
190
+ def parse_packet(str)
191
+ @str = (@unused_str || "") + str
192
+ @strpos = 0
193
+ begin
194
+ result = send("parse_#{@property}")
195
+ if result
196
+ instance_variable_set("@#{@property}", result)
197
+ true
198
+ end
199
+ rescue MoreCharsNeeded
200
+ false
201
+ end
202
+ end
203
+
204
+ def parse_size
205
+ @type = parse_type unless @type
206
+ @strpos = 0
207
+ send("parse_size_for_#{@type}")
208
+ end
209
+
210
+ def get_chars(n)
211
+ if @strpos + n - 1 >= @str.size
212
+ @unused_str = @str[@strpos..-1]
213
+ raise MoreCharsNeeded
214
+ else
215
+ result = @str[@strpos..(@strpos + n - 1)]
216
+ @strpos += n
217
+ result
218
+ end
219
+ end
220
+
221
+ def get_byte
222
+ get_chars(1).unpack("C")[0]
223
+ end
224
+
225
+ def read_int(str)
226
+ size_bytes = str.unpack("CC")
227
+ (size_bytes[0] << 8) + size_bytes[1]
228
+ end
229
+
230
+ def parse_type
231
+ case get_chars(2)
232
+ when "BM"
233
+ :bmp
234
+ when "GI"
235
+ :gif
236
+ when 0xff.chr + 0xd8.chr
237
+ :jpeg
238
+ when 0x89.chr + "P"
239
+ :png
240
+ else
241
+ raise UnknownImageType
242
+ end
243
+ end
244
+
245
+ def parse_size_for_gif
246
+ get_chars(11)[6..10].unpack('SS')
247
+ end
248
+
249
+ def parse_size_for_png
250
+ get_chars(25)[16..24].unpack('NN')
251
+ end
252
+
253
+ def parse_size_for_jpeg
254
+ loop do
255
+ @state = case @state
256
+ when nil
257
+ get_chars(2)
258
+ :started
259
+ when :started
260
+ get_byte == 0xFF ? :sof : :started
261
+ when :sof
262
+ c = get_byte
263
+ if (0xe0..0xef).include?(c)
264
+ :skipframe
265
+ elsif [0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF].detect {|r| r.include? c}
266
+ :readsize
267
+ else
268
+ :skipframe
269
+ end
270
+ when :skipframe
271
+ @skip_chars = read_int(get_chars(2)) - 2
272
+ :do_skip
273
+ when :do_skip
274
+ get_chars(@skip_chars)
275
+ :started
276
+ when :readsize
277
+ s = get_chars(7)
278
+ return [read_int(s[5..6]), read_int(s[3..4])]
279
+ end
280
+ end
281
+ end
282
+
283
+ def parse_size_for_bmp
284
+ d = get_chars(29)[14..28]
285
+ d.unpack("C")[0] == 40 ? d[4..-1].unpack('LL') : d[4..8].unpack('SS')
286
+ end
287
+ end
@@ -0,0 +1,33 @@
1
+ module Middleman::Features::AutomaticImageSizes
2
+ class << self
3
+ def registered(app)
4
+ require "middleman/features/automatic_image_sizes/fastimage"
5
+
6
+ app.helpers Helpers
7
+ end
8
+ alias :included :registered
9
+ end
10
+
11
+ module Helpers
12
+ def image_tag(path, params={})
13
+ if (!params[:width] || !params[:height]) && !path.include?("://")
14
+ params[:alt] ||= ""
15
+ http_prefix = settings.http_images_path rescue settings.images_dir
16
+
17
+ begin
18
+ real_path = File.join(settings.public, settings.images_dir, path)
19
+ if File.exists? real_path
20
+ dimensions = ::FastImage.size(real_path, :raise_on_failure => true)
21
+ params[:width] ||= dimensions[0]
22
+ params[:height] ||= dimensions[1]
23
+ end
24
+ rescue
25
+ end
26
+
27
+ super(asset_url(path, http_prefix), params)
28
+ else
29
+ super(path, params)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,44 @@
1
+ module Middleman::Features::CacheBuster
2
+ class << self
3
+ def registered(app)
4
+ Middleman::Assets.register :cache_buster do |path, prefix, request|
5
+ http_path = Middleman::Assets.before(:cache_buster, path, prefix, request)
6
+
7
+ if http_path.include?("://") || !%w(.css .png .jpg .js .gif).include?(File.extname(http_path))
8
+ http_path
9
+ else
10
+ begin
11
+ prefix = Middleman::Server.images_dir if prefix == Middleman::Server.http_images_path
12
+ rescue
13
+ end
14
+
15
+ real_path_static = File.join(Middleman::Server.public, prefix, path)
16
+
17
+ if File.readable?(real_path_static)
18
+ http_path << "?" + File.mtime(real_path_static).strftime("%s")
19
+ elsif Middleman::Server.environment == :build
20
+ real_path_dynamic = File.join(Middleman::Server.root, Middleman::Server.build_dir, prefix, path)
21
+ http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
22
+ end
23
+
24
+ http_path
25
+ end
26
+ end
27
+
28
+ app.after_feature_init do
29
+ ::Compass.configuration do |config|
30
+ config.asset_cache_buster do |path, real_path|
31
+ real_path = real_path.path if real_path.is_a? File
32
+ real_path = real_path.gsub(File.join(Middleman::Server.root, Middleman::Server.build_dir), Middleman::Server.public)
33
+ if File.readable?(real_path)
34
+ File.mtime(real_path).strftime("%s")
35
+ else
36
+ $stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ alias :included :registered
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ module Middleman::Features::CodeRay
2
+ class << self
3
+ def registered(app)
4
+ begin
5
+ require 'haml-coderay'
6
+ rescue LoadError
7
+ puts "CodeRay not available. Install it with: gem install haml-coderay"
8
+ end
9
+ end
10
+ alias :included :registered
11
+ end
12
+ end
@@ -0,0 +1,61 @@
1
+ module Middleman::Features::DefaultHelpers
2
+ class << self
3
+ def registered(app)
4
+ app.helpers Middleman::Features::DefaultHelpers::Helpers
5
+ end
6
+ alias :included :registered
7
+ end
8
+
9
+ module Helpers
10
+ def auto_stylesheet_link_tag(separator="/")
11
+ path = request.path_info.dup
12
+ path << self.class.index_file if path.match(%r{/$})
13
+ path = path.gsub(%r{^/}, '')
14
+ path = path.gsub(File.extname(path), '')
15
+ path = path.gsub("/", separator)
16
+
17
+ css_file = File.join(self.class.public, self.class.css_dir, "#{path}.css")
18
+ sass_file = File.join(self.class.views, self.class.css_dir, "#{path}.css.sass")
19
+ scss_file = File.join(self.class.views, self.class.css_dir, "#{path}.css.scss")
20
+ less_file = File.join(self.class.views, self.class.css_dir, "#{path}.css.less")
21
+
22
+ if File.exists?(css_file) || File.exists?(sass_file) || File.exists?(scss_file) || File.exists?(less_file)
23
+ stylesheet_link_tag "#{path}.css"
24
+ end
25
+ end
26
+
27
+ def page_classes
28
+ path = request.path_info.dup
29
+ path << settings.index_file if path.match(%r{/$})
30
+ path = path.gsub(%r{^/}, '')
31
+
32
+ classes = []
33
+ parts = path.split('.')[0].split('/')
34
+ parts.each_with_index { |path, i| classes << parts.first(i+1).join('_') }
35
+
36
+ classes.join(' ')
37
+ end
38
+
39
+ def asset_url(path, prefix="")
40
+ Middleman::Assets.get_url(path, prefix, request)
41
+ end
42
+
43
+ # Padrino's asset handling needs to pass through ours
44
+ def asset_path(kind, source)
45
+ return source if source =~ /^http/
46
+ asset_folder = case kind
47
+ when :css then settings.css_dir
48
+ when :js then settings.js_dir
49
+ when :images then settings.images_dir
50
+ else kind.to_s
51
+ end
52
+ source = source.to_s.gsub(/\s/, '')
53
+ ignore_extension = (asset_folder.to_s == kind.to_s) # don't append extension
54
+ source << ".#{kind}" unless ignore_extension or source =~ /\.#{kind}/
55
+ result_path = source if source =~ %r{^/} # absolute path
56
+ result_path ||= asset_url(source, asset_folder)
57
+ timestamp = asset_timestamp(result_path)
58
+ "#{result_path}#{timestamp}"
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,21 @@
1
+ module Middleman::Features::LiveReload
2
+ class << self
3
+ def registered(app)
4
+ return unless Middleman::Server.environment == :development
5
+
6
+ begin
7
+ require 'livereload'
8
+ rescue LoadError
9
+ puts "Livereload not available. Install it with: gem install livereload"
10
+ end
11
+
12
+ new_config = ::LiveReload::Config.new do |config|
13
+ config.exts = ::Tilt.mappings.keys
14
+ end
15
+
16
+ # Middleman::Server.public
17
+ ::LiveReload.run [Middleman::Server.views], new_config
18
+ end
19
+ alias :included :registered
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ module Middleman::Features::MinifyCss
2
+ class << self
3
+ def registered(app)
4
+ app.after_feature_init do
5
+ ::Compass.configuration.output_style = :compressed
6
+ end
7
+ end
8
+ alias :included :registered
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ begin
2
+ require "yui/compressor"
3
+ rescue LoadError
4
+ puts "YUI-Compressor not available. Install it with: gem install yui-compressor"
5
+ end
6
+
7
+ module Middleman
8
+ module Rack
9
+
10
+ class MinifyJavascript
11
+ def initialize(app, options={})
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ status, headers, response = @app.call(env)
17
+
18
+ if env["PATH_INFO"].match(/\.js$/)
19
+ compressor = ::YUI::JavaScriptCompressor.new(:munge => true)
20
+
21
+ uncompressed_source = response.is_a?(::Rack::File) ? File.read(response.path) : response
22
+ response = compressor.compress(uncompressed_source)
23
+ headers["Content-Length"] = ::Rack::Utils.bytesize(response).to_s
24
+ end
25
+
26
+ [status, headers, response]
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ module Middleman::Features::MinifyJavascript
2
+ class << self
3
+ def registered(app)
4
+ Middleman::Features::MinifyJavascript::Haml::Javascript.send :include, ::Haml::Filters::Base
5
+
6
+ require "middleman/features/minify_javascript/rack"
7
+ app.use Middleman::Rack::MinifyJavascript
8
+ end
9
+ alias :included :registered
10
+ end
11
+
12
+ module Haml
13
+ module Javascript
14
+ def render_with_options(text, options)
15
+ compressor = ::YUI::JavaScriptCompressor.new(:munge => true)
16
+ data = compressor.compress(text)
17
+ %Q{<script type=#{options[:attr_wrapper]}text/javascript#{options[:attr_wrapper]}>#{data.chomp}</script>}
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ def partial(template, *args)
2
+ options = args.last.is_a?(Hash) ? args.pop : { }
3
+ options.merge!(:layout => false)
4
+ if collection = options.delete(:collection) then
5
+ haml_concat(collection.inject([]) do |buffer, member|
6
+ buffer << haml(template, options.merge(
7
+ :layout => false,
8
+ :locals => {template.to_sym => member}
9
+ )
10
+ )
11
+ end.join("\n"))
12
+ else
13
+ haml_concat(haml(template, options))
14
+ end
15
+ end