beans-middleman 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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