middleman 0.5.5 → 0.9.0.pre

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 (147) hide show
  1. data/.document +1 -2
  2. data/.gitignore +3 -2
  3. data/LICENSE +0 -0
  4. data/README.rdoc +4 -0
  5. data/Rakefile +28 -36
  6. data/VERSION +1 -1
  7. data/bin/mm-build +7 -113
  8. data/bin/mm-init +11 -5
  9. data/bin/mm-server +56 -3
  10. data/features/asset_host.feature +12 -0
  11. data/features/automatic_image_sizes.feature +14 -0
  12. data/features/cache_buster.feature +22 -0
  13. data/features/generator.feature +8 -0
  14. data/features/minify_css.feature +22 -0
  15. data/features/minify_javascript.feature +12 -0
  16. data/features/page_alias_and_layouts.feature +12 -0
  17. data/features/relative_assets.feature +12 -0
  18. data/features/step_definitions/asset_host_steps.rb +7 -0
  19. data/features/step_definitions/env.rb +3 -0
  20. data/features/step_definitions/generator_steps.rb +24 -0
  21. data/features/step_definitions/middleman_steps.rb +28 -0
  22. data/features/step_definitions/page_layout_steps.rb +13 -0
  23. data/lib/middleman.rb +6 -132
  24. data/lib/middleman/assets.rb +33 -0
  25. data/lib/middleman/base.rb +147 -0
  26. data/lib/middleman/builder.rb +59 -0
  27. data/lib/middleman/config.ru +2 -0
  28. data/lib/middleman/features.rb +39 -0
  29. data/lib/middleman/features/asset_host.rb +21 -0
  30. data/lib/middleman/features/automatic_image_sizes.rb +31 -0
  31. data/lib/middleman/features/automatic_image_sizes/fastimage.rb +282 -0
  32. data/lib/middleman/features/cache_buster.rb +43 -0
  33. data/lib/middleman/features/default_helpers.rb +68 -0
  34. data/lib/middleman/features/livereload.rb +19 -0
  35. data/lib/middleman/features/minify_css.rb +9 -0
  36. data/lib/middleman/features/minify_javascript.rb +20 -0
  37. data/lib/middleman/features/minify_javascript/rack.rb +31 -0
  38. data/lib/middleman/features/relative_assets.rb +35 -0
  39. data/lib/middleman/features/slickmap.rb +118 -0
  40. data/lib/middleman/features/smush_pngs.rb +38 -0
  41. data/lib/middleman/features/ugly_haml.rb +7 -0
  42. data/lib/middleman/renderers.rb +26 -0
  43. data/lib/middleman/renderers/coffee.rb +28 -0
  44. data/lib/middleman/renderers/haml.rb +47 -0
  45. data/lib/middleman/renderers/sass.rb +67 -0
  46. data/lib/middleman/template/init.rbt +57 -0
  47. data/lib/middleman/template/views/index.html.haml +4 -0
  48. data/lib/middleman/template/views/layout.haml +11 -4
  49. data/lib/middleman/template/views/stylesheets/site.css.sass +27 -0
  50. data/lib/middleman/templater+dynamic_renderer.rb +26 -0
  51. data/middleman.gemspec +121 -107
  52. data/spec/builder_spec.rb +17 -16
  53. data/spec/fixtures/sample/init.rb +28 -2
  54. data/spec/fixtures/sample/public/images/blank.gif +0 -0
  55. data/spec/fixtures/sample/public/static.html +0 -0
  56. data/{vendor/sinatra-maruku/examples/public/javascripts/application.js → spec/fixtures/sample/public/stylesheets/auto-css.css} +0 -0
  57. data/spec/fixtures/sample/public/stylesheets/static.css +0 -0
  58. data/{vendor/sinatra-maruku/examples/public/stylesheets/print.css → spec/fixtures/sample/public/stylesheets/sub1/auto-css.css} +0 -0
  59. data/spec/fixtures/sample/public/stylesheets/sub1/sub2/auto-css.css +0 -0
  60. data/spec/fixtures/sample/views/_partial.haml +0 -0
  61. data/spec/fixtures/sample/views/asset_host.html.haml +1 -0
  62. data/spec/fixtures/sample/views/auto-css.html.haml +1 -0
  63. data/spec/fixtures/sample/views/auto-image-sizes.html.haml +1 -0
  64. data/spec/fixtures/sample/views/cache-buster.html.haml +2 -0
  65. data/spec/fixtures/sample/views/{index.haml → custom-layout.html.haml} +0 -0
  66. data/spec/fixtures/sample/views/custom.haml +5 -0
  67. data/spec/fixtures/sample/views/index.html.haml +1 -0
  68. data/spec/fixtures/sample/views/inline-css.html.haml +4 -0
  69. data/spec/fixtures/sample/views/{inline-js.haml → inline-js.html.haml} +0 -0
  70. data/spec/fixtures/sample/views/layout.haml +1 -1
  71. data/spec/fixtures/sample/views/{maruku.maruku → maruku.html.maruku} +0 -0
  72. data/spec/fixtures/sample/views/page-classes.html.haml +1 -0
  73. data/spec/fixtures/sample/views/services/{index.haml → index.html.haml} +0 -0
  74. data/spec/fixtures/sample/views/stylesheets/asset_host.css.sass +3 -0
  75. data/spec/fixtures/sample/views/stylesheets/relative_assets.css.sass +3 -0
  76. data/spec/fixtures/sample/views/stylesheets/site.css.sass +1 -0
  77. data/spec/fixtures/sample/views/stylesheets/site_scss.css.scss +1 -0
  78. data/spec/fixtures/sample/views/stylesheets/test_less.css.less +5 -0
  79. data/spec/helpers_spec.rb +43 -0
  80. data/spec/spec_helper.rb +3 -5
  81. metadata +298 -127
  82. data/lib/middleman/helpers.rb +0 -131
  83. data/lib/middleman/markaby.rb +0 -4
  84. data/lib/middleman/maruku.rb +0 -4
  85. data/lib/middleman/sprockets_ext.rb +0 -29
  86. data/lib/middleman/template/init.rb +0 -22
  87. data/lib/middleman/template/views/index.haml +0 -1
  88. data/lib/middleman/template/views/stylesheets/site.sass +0 -1
  89. data/spec/fixtures/sample/views/markaby.mab +0 -5
  90. data/spec/fixtures/sample/views/stylesheets/site.sass +0 -1
  91. data/spec/generator_spec.rb +0 -34
  92. data/vendor/rack-test/History.txt +0 -64
  93. data/vendor/rack-test/MIT-LICENSE.txt +0 -19
  94. data/vendor/rack-test/README.rdoc +0 -57
  95. data/vendor/rack-test/Rakefile +0 -62
  96. data/vendor/rack-test/lib/rack/mock_session.rb +0 -57
  97. data/vendor/rack-test/lib/rack/test.rb +0 -246
  98. data/vendor/rack-test/lib/rack/test/cookie_jar.rb +0 -169
  99. data/vendor/rack-test/lib/rack/test/methods.rb +0 -73
  100. data/vendor/rack-test/lib/rack/test/mock_digest_request.rb +0 -27
  101. data/vendor/rack-test/lib/rack/test/uploaded_file.rb +0 -36
  102. data/vendor/rack-test/lib/rack/test/utils.rb +0 -75
  103. data/vendor/rack-test/spec/fixtures/config.ru +0 -3
  104. data/vendor/rack-test/spec/fixtures/fake_app.rb +0 -109
  105. data/vendor/rack-test/spec/fixtures/foo.txt +0 -1
  106. data/vendor/rack-test/spec/rack/test/cookie_spec.rb +0 -176
  107. data/vendor/rack-test/spec/rack/test/digest_auth_spec.rb +0 -48
  108. data/vendor/rack-test/spec/rack/test/multipart_spec.rb +0 -85
  109. data/vendor/rack-test/spec/rack/test/utils_spec.rb +0 -44
  110. data/vendor/rack-test/spec/rack/test_spec.rb +0 -363
  111. data/vendor/rack-test/spec/rcov.opts +0 -1
  112. data/vendor/rack-test/spec/spec.opts +0 -1
  113. data/vendor/rack-test/spec/spec_helper.rb +0 -48
  114. data/vendor/sinatra-content-for/LICENSE +0 -22
  115. data/vendor/sinatra-content-for/README.rdoc +0 -49
  116. data/vendor/sinatra-content-for/Rakefile +0 -33
  117. data/vendor/sinatra-content-for/lib/sinatra/content_for.rb +0 -58
  118. data/vendor/sinatra-content-for/sinatra-content-for.gemspec +0 -34
  119. data/vendor/sinatra-content-for/test/content_for_test.rb +0 -156
  120. data/vendor/sinatra-markaby/CHANGES +0 -7
  121. data/vendor/sinatra-markaby/LICENSE +0 -20
  122. data/vendor/sinatra-markaby/README.rdoc +0 -33
  123. data/vendor/sinatra-markaby/Rakefile +0 -45
  124. data/vendor/sinatra-markaby/TODO +0 -3
  125. data/vendor/sinatra-markaby/VERSION.yml +0 -4
  126. data/vendor/sinatra-markaby/lib/sinatra/markaby.rb +0 -31
  127. data/vendor/sinatra-markaby/sinatra-markaby.gemspec +0 -49
  128. data/vendor/sinatra-markaby/test/sinatra_markaby_test.rb +0 -72
  129. data/vendor/sinatra-markaby/test/test_helper.rb +0 -19
  130. data/vendor/sinatra-markaby/test/views/hello.mab +0 -1
  131. data/vendor/sinatra-markaby/test/views/html.mab +0 -4
  132. data/vendor/sinatra-maruku/LICENSE +0 -22
  133. data/vendor/sinatra-maruku/README.markdown +0 -85
  134. data/vendor/sinatra-maruku/Rakefile +0 -34
  135. data/vendor/sinatra-maruku/VERSION.yml +0 -4
  136. data/vendor/sinatra-maruku/examples/app.rb +0 -8
  137. data/vendor/sinatra-maruku/examples/config.ru +0 -4
  138. data/vendor/sinatra-maruku/examples/mapp.rb +0 -15
  139. data/vendor/sinatra-maruku/examples/public/stylesheets/application.css +0 -23
  140. data/vendor/sinatra-maruku/examples/views/index.maruku +0 -32
  141. data/vendor/sinatra-maruku/examples/views/layout.maruku +0 -9
  142. data/vendor/sinatra-maruku/lib/sinatra/maruku.rb +0 -25
  143. data/vendor/sinatra-maruku/sinatra-maruku.gemspec +0 -70
  144. data/vendor/sinatra-maruku/test/sinatra_maruku_test.rb +0 -91
  145. data/vendor/sinatra-maruku/test/test_helper.rb +0 -21
  146. data/vendor/sinatra-maruku/test/views/hello.maruku +0 -1
  147. data/vendor/sinatra-maruku/test/views/layout2.maruku +0 -2
@@ -0,0 +1,2 @@
1
+ require 'middleman'
2
+ run Middleman::Base
@@ -0,0 +1,39 @@
1
+ module Middleman
2
+ module Features
3
+ # Top-level method to register a new feature
4
+ @@features = {}
5
+ def self.register(feature_name, feature_class=nil, options={})
6
+ @@features[feature_name] = feature_class
7
+
8
+ # Default to disabled, unless the class asks to auto-enable
9
+ activate_method = (options.has_key?(:auto_enable) && options[:auto_enable]) ? :enable : :disable
10
+ Middleman::Base.send(activate_method, feature_name)
11
+ end
12
+
13
+ def self.run(feature_name, scope)
14
+ feature_class = @@features[feature_name]
15
+ feature_class.new(scope) unless feature_class.nil?
16
+ end
17
+
18
+ def self.all
19
+ @@features
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+ # livereload
26
+ %w(asset_host
27
+ automatic_image_sizes
28
+ cache_buster
29
+ default_helpers
30
+ minify_css
31
+ minify_javascript
32
+ relative_assets
33
+ slickmap
34
+ smush_pngs
35
+ ugly_haml).each do |feature|
36
+
37
+ require File.join("middleman/features", feature)
38
+
39
+ end
@@ -0,0 +1,21 @@
1
+ class Middleman::Features::AssetHost
2
+ def initialize(app)
3
+ Middleman::Base.after_feature_init do
4
+ if Middleman::Base.asset_host.is_a?(Proc)
5
+ ::Compass.configuration.asset_host(&Middleman::Base.asset_host)
6
+ end
7
+ end
8
+
9
+ Middleman::Assets.register :asset_host do |path, prefix, request|
10
+ original_output = Middleman::Assets.before(:asset_host, path, prefix, request)
11
+
12
+ valid_extensions = %w(.png .gif .jpg .jpeg .js .css)
13
+
14
+ asset_prefix = Middleman::Base.asset_host.call(original_output)
15
+
16
+ File.join(asset_prefix, original_output)
17
+ end
18
+ end
19
+ end
20
+
21
+ Middleman::Features.register :asset_host, Middleman::Features::AssetHost
@@ -0,0 +1,31 @@
1
+ class Middleman::Features::AutomaticImageSizes
2
+ def initialize(app)
3
+ require "middleman/features/automatic_image_sizes/fastimage"
4
+
5
+ Middleman::Base.send :alias_method, :pre_automatic_image_tag, :image_tag
6
+ Middleman::Base.helpers do
7
+ def image_tag(path, params={})
8
+ if (!params[:width] || !params[:height]) && !path.include?("://")
9
+ params[:alt] ||= ""
10
+ http_prefix = settings.http_images_path rescue settings.images_dir
11
+
12
+ begin
13
+ real_path = File.join(settings.public, settings.images_dir, path)
14
+ if File.exists? real_path
15
+ dimensions = Middleman::FastImage.size(real_path, :raise_on_failure => true)
16
+ params[:width] ||= dimensions[0]
17
+ params[:height] ||= dimensions[1]
18
+ end
19
+ rescue
20
+ end
21
+
22
+ capture_haml { haml_tag(:img, params.merge(:src => asset_url(path, http_prefix))) }
23
+ else
24
+ pre_automatic_image_tag(path, params)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ Middleman::Features.register :automatic_image_sizes, Middleman::Features::AutomaticImageSizes
@@ -0,0 +1,282 @@
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
+ module Middleman
36
+ class FastImage
37
+ attr_reader :size, :type
38
+
39
+ class FastImageException < StandardError # :nodoc:
40
+ end
41
+ class MoreCharsNeeded < FastImageException # :nodoc:
42
+ end
43
+ class UnknownImageType < FastImageException # :nodoc:
44
+ end
45
+ class ImageFetchFailure < FastImageException # :nodoc:
46
+ end
47
+ class SizeNotFound < FastImageException # :nodoc:
48
+ end
49
+
50
+ DefaultTimeout = 2
51
+
52
+ LocalFileChunkSize = 256
53
+
54
+ # Returns an array containing the width and height of the image.
55
+ # It will return nil if the image could not be fetched, or if the image type was not recognised.
56
+ #
57
+ # By default there is a timeout of 2 seconds for opening and reading from a remote server.
58
+ # This can be changed by passing a :timeout => number_of_seconds in the options.
59
+ #
60
+ # If you wish FastImage to raise if it cannot size the image for any reason, then pass
61
+ # :raise_on_failure => true in the options.
62
+ #
63
+ # FastImage knows about GIF, JPEG, BMP and PNG files.
64
+ #
65
+ # === Example
66
+ #
67
+ # require 'fastimage'
68
+ #
69
+ # FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
70
+ # => [266, 56]
71
+ # FastImage.size("http://stephensykes.com/images/pngimage")
72
+ # => [16, 16]
73
+ # FastImage.size("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
74
+ # => [500, 375]
75
+ # FastImage.size("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
76
+ # => [512, 512]
77
+ # FastImage.size("test/fixtures/test.jpg")
78
+ # => [882, 470]
79
+ # FastImage.size("http://pennysmalls.com/does_not_exist")
80
+ # => nil
81
+ # FastImage.size("http://pennysmalls.com/does_not_exist", :raise_on_failure=>true)
82
+ # => raises FastImage::ImageFetchFailure
83
+ # FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true)
84
+ # => raises FastImage::UnknownImageType
85
+ # FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true, :timeout=>0.01)
86
+ # => raises FastImage::ImageFetchFailure
87
+ # FastImage.size("http://stephensykes.com/images/faulty.jpg", :raise_on_failure=>true)
88
+ # => raises FastImage::SizeNotFound
89
+ #
90
+ # === Supported options
91
+ # [:timeout]
92
+ # Overrides the default timeout of 2 seconds. Applies both to reading from and opening the http connection.
93
+ # [:raise_on_failure]
94
+ # If set to true causes an exception to be raised if the image size cannot be found for any reason.
95
+ #
96
+ def self.size(uri, options={})
97
+ new(uri, options).size
98
+ end
99
+
100
+ # Returns an symbol indicating the image type fetched from a uri.
101
+ # It will return nil if the image could not be fetched, or if the image type was not recognised.
102
+ #
103
+ # By default there is a timeout of 2 seconds for opening and reading from a remote server.
104
+ # This can be changed by passing a :timeout => number_of_seconds in the options.
105
+ #
106
+ # If you wish FastImage to raise if it cannot find the type of the image for any reason, then pass
107
+ # :raise_on_failure => true in the options.
108
+ #
109
+ # === Example
110
+ #
111
+ # require 'fastimage'
112
+ #
113
+ # FastImage.type("http://stephensykes.com/images/ss.com_x.gif")
114
+ # => :gif
115
+ # FastImage.type("http://stephensykes.com/images/pngimage")
116
+ # => :png
117
+ # FastImage.type("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
118
+ # => :jpeg
119
+ # FastImage.type("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
120
+ # => :bmp
121
+ # FastImage.type("test/fixtures/test.jpg")
122
+ # => :jpeg
123
+ # FastImage.type("http://pennysmalls.com/does_not_exist")
124
+ # => nil
125
+ #
126
+ # === Supported options
127
+ # [:timeout]
128
+ # Overrides the default timeout of 2 seconds. Applies both to reading from and opening the http connection.
129
+ # [:raise_on_failure]
130
+ # If set to true causes an exception to be raised if the image type cannot be found for any reason.
131
+ #
132
+ def self.type(uri, options={})
133
+ new(uri, options.merge(:type_only=>true)).type
134
+ end
135
+
136
+ def initialize(uri, options={})
137
+ @property = options[:type_only] ? :type : :size
138
+ @timeout = options[:timeout] || DefaultTimeout
139
+ @uri = uri
140
+ @parsed_uri = URI.parse(uri.gsub(/\s/, "%20"))
141
+ if @parsed_uri.scheme == "http" || @parsed_uri.scheme == "https"
142
+ fetch_using_http
143
+ else
144
+ fetch_using_open_uri
145
+ end
146
+ raise SizeNotFound if options[:raise_on_failure] && @property == :size && !@size
147
+ rescue Timeout::Error, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET, ImageFetchFailure
148
+ raise ImageFetchFailure if options[:raise_on_failure]
149
+ rescue Errno::ENOENT
150
+ raise ImageFetchFailure if options[:raise_on_failure]
151
+ rescue UnknownImageType
152
+ raise UnknownImageType if options[:raise_on_failure]
153
+ end
154
+
155
+ private
156
+
157
+ def fetch_using_http
158
+ setup_http
159
+ @http.request_get(@parsed_uri.request_uri) do |res|
160
+ raise ImageFetchFailure unless res.is_a?(Net::HTTPSuccess)
161
+ res.read_body do |str|
162
+ break if parse_packet(str)
163
+ end
164
+ end
165
+ end
166
+
167
+ def setup_http
168
+ @http = Net::HTTP.new(@parsed_uri.host, @parsed_uri.port)
169
+ @http.use_ssl = (@parsed_uri.scheme == "https")
170
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
171
+ @http.open_timeout = @timeout
172
+ @http.read_timeout = @timeout
173
+ end
174
+
175
+ def fetch_using_open_uri
176
+ open(@uri) do |s|
177
+ while str = s.read(LocalFileChunkSize)
178
+ break if parse_packet(str)
179
+ end
180
+ end
181
+ end
182
+
183
+ # returns true once result is achieved
184
+ #
185
+ def parse_packet(str)
186
+ @str = (@unused_str || "") + str
187
+ @strpos = 0
188
+ begin
189
+ result = send("parse_#{@property}")
190
+ if result
191
+ instance_variable_set("@#{@property}", result)
192
+ true
193
+ end
194
+ rescue MoreCharsNeeded
195
+ false
196
+ end
197
+ end
198
+
199
+ def parse_size
200
+ @type = parse_type unless @type
201
+ send("parse_size_for_#{@type}")
202
+ end
203
+
204
+ def get_chars(n)
205
+ if @strpos + n - 1 >= @str.size
206
+ @unused_str = @str[@strpos..-1]
207
+ raise MoreCharsNeeded
208
+ else
209
+ result = @str[@strpos..(@strpos + n - 1)]
210
+ @strpos += n
211
+ result
212
+ end
213
+ end
214
+
215
+ def get_byte
216
+ get_chars(1).unpack("C")[0]
217
+ end
218
+
219
+ def read_int(str)
220
+ size_bytes = str.unpack("CC")
221
+ (size_bytes[0] << 8) + size_bytes[1]
222
+ end
223
+
224
+ def parse_type
225
+ case get_chars(2)
226
+ when "BM"
227
+ :bmp
228
+ when "GI"
229
+ :gif
230
+ when 0xff.chr + 0xd8.chr
231
+ :jpeg
232
+ when 0x89.chr + "P"
233
+ :png
234
+ else
235
+ raise UnknownImageType
236
+ end
237
+ end
238
+
239
+ def parse_size_for_gif
240
+ get_chars(9)[4..8].unpack('SS')
241
+ end
242
+
243
+ def parse_size_for_png
244
+ get_chars(23)[14..22].unpack('NN')
245
+ end
246
+
247
+ def parse_size_for_jpeg
248
+ loop do
249
+ @state = case @state
250
+ when nil
251
+ get_chars(2)
252
+ :started
253
+ when :started
254
+ get_byte == 0xFF ? :sof : :started
255
+ when :sof
256
+ c = get_byte
257
+ if (0xe0..0xef).include?(c)
258
+ :skipframe
259
+ elsif [0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF].detect {|r| r.include? c}
260
+ :readsize
261
+ else
262
+ :skipframe
263
+ end
264
+ when :skipframe
265
+ @skip_chars = read_int(get_chars(2)) - 2
266
+ :do_skip
267
+ when :do_skip
268
+ get_chars(@skip_chars)
269
+ :started
270
+ when :readsize
271
+ s = get_chars(7)
272
+ return [read_int(s[5..6]), read_int(s[3..4])]
273
+ end
274
+ end
275
+ end
276
+
277
+ def parse_size_for_bmp
278
+ d = get_chars(27)[12..26]
279
+ d[0] == 40 ? d[4..-1].unpack('LL') : d[4..8].unpack('SS')
280
+ end
281
+ end
282
+ end
@@ -0,0 +1,43 @@
1
+ class Middleman::Features::CacheBuster
2
+ def initialize(app)
3
+ Middleman::Assets.register :cache_buster do |path, prefix, request|
4
+ http_path = Middleman::Assets.before(:cache_buster, path, prefix, request)
5
+
6
+ if http_path.include?("://") || !%w(.css .png .jpg .js .gif).include?(File.extname(http_path))
7
+ http_path
8
+ else
9
+ begin
10
+ prefix = Middleman::Base.images_dir if prefix == Middleman::Base.http_images_path
11
+ rescue
12
+ end
13
+
14
+ real_path_static = File.join(Middleman::Base.public, prefix, path)
15
+
16
+ if File.readable?(real_path_static)
17
+ http_path << "?" + File.mtime(real_path_static).strftime("%s")
18
+ elsif Middleman::Base.environment == "build"
19
+ real_path_dynamic = File.join(Middleman::Base.root, Middleman::Base.build_dir, prefix, path)
20
+ http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
21
+ end
22
+
23
+ http_path
24
+ end
25
+ end
26
+
27
+ Middleman::Base.after_feature_init do
28
+ ::Compass.configuration do |config|
29
+ config.asset_cache_buster do |path, real_path|
30
+ real_path = real_path.path if real_path.is_a? File
31
+ real_path = real_path.gsub(File.join(Middleman::Base.root, Middleman::Base.build_dir), Middleman::Base.public)
32
+ if File.readable?(real_path)
33
+ File.mtime(real_path).strftime("%s")
34
+ else
35
+ $stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ Middleman::Features.register :cache_buster, Middleman::Features::CacheBuster
@@ -0,0 +1,68 @@
1
+ class Middleman::Features::DefaultHelpers
2
+ def initialize(app)
3
+ Middleman::Base.helpers Helpers
4
+ end
5
+
6
+ module Helpers
7
+ def auto_stylesheet_link_tag(separator="/")
8
+ path = request.path_info.dup
9
+ path << self.class.index_file if path.match(%r{/$})
10
+ path = path.gsub(%r{^/}, '')
11
+ path = path.gsub(File.extname(path), '')
12
+ path = path.gsub("/", separator)
13
+
14
+ css_file = File.join(self.class.public, self.class.css_dir, "#{path}.css")
15
+ sass_file = File.join(self.class.views, self.class.css_dir, "#{path}.css.sass")
16
+ scss_file = File.join(self.class.views, self.class.css_dir, "#{path}.css.scss")
17
+
18
+ if File.exists?(css_file) || File.exists?(sass_file) || File.exists?(scss_file)
19
+ stylesheet_link_tag "#{path}.css"
20
+ end
21
+ end
22
+
23
+ def page_classes
24
+ path = request.path_info.dup
25
+ path << settings.index_file if path.match(%r{/$})
26
+ path = path.gsub(%r{^/}, '')
27
+
28
+ classes = []
29
+ parts = path.split('.')[0].split('/')
30
+ parts.each_with_index { |path, i| classes << parts.first(i+1).join('_') }
31
+
32
+ classes.join(' ')
33
+ end
34
+
35
+ def asset_url(path, prefix="")
36
+ Middleman::Assets.get_url(path, prefix, request)
37
+ end
38
+
39
+ def link_to(title, url="#", params={})
40
+ params.merge!(:href => url)
41
+ params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ')
42
+ %Q{<a #{params}>#{title}</a>}
43
+ end
44
+
45
+ def image_tag(path, params={})
46
+ params[:alt] ||= ""
47
+ prefix = settings.http_images_path rescue settings.images_dir
48
+ params = params.merge(:src => asset_url(path, prefix))
49
+ params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ')
50
+ "<img #{params} />"
51
+ end
52
+
53
+ def javascript_include_tag(path, params={})
54
+ params = params.merge(:src => asset_url(path, settings.js_dir), :type => "text/javascript")
55
+ params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ')
56
+ "<script #{params}></script>"
57
+ end
58
+
59
+ def stylesheet_link_tag(path, params={})
60
+ params[:rel] ||= "stylesheet"
61
+ params = params.merge(:href => asset_url(path, settings.css_dir), :type => "text/css")
62
+ params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ')
63
+ "<link #{params} />"
64
+ end
65
+ end
66
+ end
67
+
68
+ Middleman::Features.register :default_helpers, Middleman::Features::DefaultHelpers, { :auto_enable => true }