middleman 0.99.0.pre → 0.99.1.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.
- data/LICENSE +1 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/mm-build +1 -1
- data/bin/mm-init +1 -1
- data/bin/mm-server +3 -3
- data/features/step_definitions/asset_host_steps.rb +3 -3
- data/features/step_definitions/middleman_steps.rb +2 -3
- data/features/step_definitions/page_layout_steps.rb +6 -6
- data/lib/middleman.rb +1 -1
- data/lib/middleman/assets.rb +1 -1
- data/lib/middleman/builder.rb +7 -6
- data/lib/middleman/config.ru +1 -1
- data/lib/middleman/features.rb +7 -5
- data/lib/middleman/features/asset_host.rb +5 -5
- data/lib/middleman/features/automatic_image_sizes.rb +4 -4
- data/lib/middleman/features/automatic_image_sizes/fastimage.rb +214 -209
- data/lib/middleman/features/cache_buster.rb +7 -7
- data/lib/middleman/features/default_helpers.rb +2 -2
- data/lib/middleman/features/livereload.rb +3 -3
- data/lib/middleman/features/minify_css.rb +2 -2
- data/lib/middleman/features/minify_javascript.rb +1 -1
- data/lib/middleman/features/relative_assets.rb +3 -3
- data/lib/middleman/features/slickmap.rb +38 -68
- data/lib/middleman/features/slickmap/template.html.haml +27 -0
- data/lib/middleman/features/smush_pngs.rb +6 -6
- data/lib/middleman/features/ugly_haml.rb +2 -2
- data/lib/middleman/renderers/coffee.rb +1 -1
- data/lib/middleman/renderers/haml.rb +1 -1
- data/lib/middleman/renderers/sass.rb +5 -5
- data/lib/middleman/server.rb +168 -0
- data/lib/middleman/template/{init.rbt → config.rbt} +0 -0
- data/lib/middleman/templater+dynamic_renderer.rb +2 -2
- data/middleman.gemspec +9 -8
- data/spec/fixtures/sample/{init.rb → config.rb} +0 -0
- data/spec/helpers_spec.rb +1 -1
- metadata +11 -10
- data/lib/middleman/base.rb +0 -147
data/LICENSE
CHANGED
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ begin
|
|
25
25
|
gem.add_dependency("compass", "~>0.10.0")
|
26
26
|
gem.add_dependency("json_pure", "~>1.4.0")
|
27
27
|
gem.add_dependency("smusher", "~>0.4.5")
|
28
|
-
gem.add_dependency("compass-slickmap", "~>0.
|
28
|
+
gem.add_dependency("compass-slickmap", "~>0.4.0")
|
29
29
|
# gem.add_dependency("livereload", "~>1.4.0")
|
30
30
|
|
31
31
|
gem.add_development_dependency("rspec")
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.99.
|
1
|
+
0.99.1.pre
|
data/bin/mm-build
CHANGED
@@ -6,7 +6,7 @@ ENV['MM_ENV'] = "build"
|
|
6
6
|
require File.join(File.dirname(__FILE__), "..", "lib", "middleman")
|
7
7
|
require 'middleman/builder'
|
8
8
|
|
9
|
-
# Middleman::
|
9
|
+
# Middleman::Server.init!
|
10
10
|
Middleman::Builder.init!
|
11
11
|
|
12
12
|
Middleman::Generators.run_cli(Dir.pwd, 'mm-build', 1, %w(build --force).concat(ARGV))
|
data/bin/mm-init
CHANGED
data/bin/mm-server
CHANGED
@@ -36,7 +36,7 @@ OptionParser.new { |opts|
|
|
36
36
|
env = e
|
37
37
|
}
|
38
38
|
opts.on("--debug", "Debug mode") {
|
39
|
-
::Middleman::
|
39
|
+
::Middleman::Server.set :logging, true
|
40
40
|
}
|
41
41
|
|
42
42
|
opts.parse! ARGV
|
@@ -44,13 +44,13 @@ OptionParser.new { |opts|
|
|
44
44
|
|
45
45
|
ENV['RACK_ENV'] = env
|
46
46
|
|
47
|
-
class Middleman::
|
47
|
+
class Middleman::Server
|
48
48
|
set :root, Dir.pwd
|
49
49
|
end
|
50
50
|
|
51
51
|
require 'shotgun'
|
52
52
|
config = File.join(File.dirname(__FILE__), '..', 'lib', 'middleman', 'config.ru')
|
53
|
-
app = Shotgun.new(config, &lambda { |inner_app| Middleman::
|
53
|
+
app = Shotgun.new(config, &lambda { |inner_app| Middleman::Server })
|
54
54
|
|
55
55
|
require 'rubygems'
|
56
56
|
require 'thin'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Given /^I am using an asset host$/ do
|
2
|
-
Middleman::
|
3
|
-
Middleman::
|
2
|
+
Middleman::Server.enable :asset_host
|
3
|
+
Middleman::Server.set :asset_host do |asset|
|
4
4
|
"http://assets%d.example.com" % (asset.hash % 4)
|
5
5
|
end
|
6
|
-
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::
|
6
|
+
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::Server.new))
|
7
7
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Given /^"([^\"]*)" feature is "([^\"]*)"$/ do |feature, state|
|
2
2
|
enable_or_disable = (state == "enabled") ? :enable : :disable
|
3
|
-
Middleman::
|
4
|
-
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::
|
3
|
+
Middleman::Server.send(enable_or_disable, feature.to_sym)
|
4
|
+
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::Server.new))
|
5
5
|
end
|
6
6
|
|
7
7
|
Given /^generated directory at "([^\"]*)"$/ do |dirname|
|
@@ -23,6 +23,5 @@ Then /^I should not see "([^\"]*)"$/ do |expected|
|
|
23
23
|
end
|
24
24
|
|
25
25
|
Then /^I should see "([^\"]*)" lines$/ do |lines|
|
26
|
-
$stderr.puts @browser.last_response.body
|
27
26
|
@browser.last_response.body.chomp.split($/).length.should == lines.to_i
|
28
27
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
Given /^page "([^\"]*)" has layout "([^\"]*)"$/ do |url, layout|
|
2
|
-
Middleman::
|
3
|
-
Middleman::
|
4
|
-
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::
|
2
|
+
Middleman::Server.set :root, File.join(File.dirname(File.dirname(File.dirname(__FILE__))), "spec", "fixtures", "sample")
|
3
|
+
Middleman::Server.page(url, :layout => layout.to_sym)
|
4
|
+
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::Server.new))
|
5
5
|
end
|
6
6
|
|
7
7
|
Given /^"([^\"]*)" with_layout block has layout "([^\"]*)"$/ do |url, layout|
|
8
|
-
Middleman::
|
9
|
-
Middleman::
|
8
|
+
Middleman::Server.set :root, File.join(File.dirname(File.dirname(File.dirname(__FILE__))), "spec", "fixtures", "sample")
|
9
|
+
Middleman::Server.with_layout(:layout => layout.to_sym) do
|
10
10
|
page(url)
|
11
11
|
end
|
12
|
-
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::
|
12
|
+
@browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::Server.new))
|
13
13
|
end
|
data/lib/middleman.rb
CHANGED
data/lib/middleman/assets.rb
CHANGED
@@ -29,5 +29,5 @@ module Middleman
|
|
29
29
|
end
|
30
30
|
|
31
31
|
Middleman::Assets.register :base do |path, prefix, request|
|
32
|
-
path.include?("://") ? path : File.join(Middleman::
|
32
|
+
path.include?("://") ? path : File.join(Middleman::Server.http_prefix || "/", prefix, path)
|
33
33
|
end
|
data/lib/middleman/builder.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'middleman/
|
1
|
+
require 'middleman/server'
|
2
2
|
require 'templater'
|
3
3
|
require 'middleman/templater+dynamic_renderer.rb'
|
4
4
|
|
@@ -6,11 +6,12 @@ require 'middleman/templater+dynamic_renderer.rb'
|
|
6
6
|
module Middleman
|
7
7
|
class Builder < ::Templater::Generator
|
8
8
|
|
9
|
+
# Support all Tilt-enabled templates and treat js like a template
|
9
10
|
@@template_extensions = ::Tilt.mappings.keys << "js"
|
10
11
|
|
11
12
|
# Define source and desintation
|
12
13
|
def self.source_root; Dir.pwd; end
|
13
|
-
def destination_root; File.join(Dir.pwd, Middleman::
|
14
|
+
def destination_root; File.join(Dir.pwd, Middleman::Server.build_dir); end
|
14
15
|
|
15
16
|
# Override template to ask middleman for the correct extension to output
|
16
17
|
def self.template(name, *args, &block)
|
@@ -21,7 +22,7 @@ module Middleman
|
|
21
22
|
end
|
22
23
|
|
23
24
|
if (args[0] === args[1])
|
24
|
-
args[1] = args[0].gsub("#{File.basename(Middleman::
|
25
|
+
args[1] = args[0].gsub("#{File.basename(Middleman::Server.views)}/", "").gsub("#{File.basename(Middleman::Server.public)}/", "")
|
25
26
|
if File.extname(args[1]) != ".js"
|
26
27
|
args[1] = args[1].gsub!(File.extname(args[1]), "") if File.basename(args[1]).split('.').length > 2
|
27
28
|
end
|
@@ -36,14 +37,14 @@ module Middleman
|
|
36
37
|
return unless ::Tilt[file_ext].nil?
|
37
38
|
|
38
39
|
if (args[0] === args[1])
|
39
|
-
args[1] = args[0].gsub("#{File.basename(Middleman::
|
40
|
+
args[1] = args[0].gsub("#{File.basename(Middleman::Server.views)}/", "").gsub("#{File.basename(Middleman::Server.public)}/", "")
|
40
41
|
end
|
41
42
|
super(name, *args, &block)
|
42
43
|
end
|
43
44
|
|
44
45
|
def self.init!
|
45
|
-
glob! File.basename(Middleman::
|
46
|
-
glob! File.basename(Middleman::
|
46
|
+
glob! File.basename(Middleman::Server.public), @@template_extensions
|
47
|
+
glob! File.basename(Middleman::Server.views), @@template_extensions
|
47
48
|
end
|
48
49
|
|
49
50
|
def after_run
|
data/lib/middleman/config.ru
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'middleman'
|
2
|
-
run Middleman::
|
2
|
+
run Middleman::Server
|
data/lib/middleman/features.rb
CHANGED
@@ -7,14 +7,16 @@ module Middleman
|
|
7
7
|
|
8
8
|
# Default to disabled, unless the class asks to auto-enable
|
9
9
|
activate_method = (options.has_key?(:auto_enable) && options[:auto_enable]) ? :enable : :disable
|
10
|
-
Middleman::
|
10
|
+
Middleman::Server.send(activate_method, feature_name)
|
11
11
|
end
|
12
12
|
|
13
|
-
|
13
|
+
# Initialize a feature
|
14
|
+
def self.run(feature_name, feature_config, scope)
|
14
15
|
feature_class = @@features[feature_name]
|
15
|
-
feature_class.new(scope) unless feature_class.nil?
|
16
|
+
feature_class.new(scope, feature_config) unless feature_class.nil?
|
16
17
|
end
|
17
18
|
|
19
|
+
# Get a list of all features
|
18
20
|
def self.all
|
19
21
|
@@features
|
20
22
|
end
|
@@ -23,10 +25,10 @@ module Middleman
|
|
23
25
|
end
|
24
26
|
|
25
27
|
# livereload
|
26
|
-
%w(
|
28
|
+
%w(default_helpers
|
29
|
+
asset_host
|
27
30
|
automatic_image_sizes
|
28
31
|
cache_buster
|
29
|
-
default_helpers
|
30
32
|
minify_css
|
31
33
|
minify_javascript
|
32
34
|
relative_assets
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class Middleman::Features::AssetHost
|
2
|
-
def initialize(app)
|
3
|
-
Middleman::
|
4
|
-
if Middleman::
|
5
|
-
::Compass.configuration.asset_host(&Middleman::
|
2
|
+
def initialize(app, config)
|
3
|
+
Middleman::Server.after_feature_init do
|
4
|
+
if Middleman::Server.asset_host.is_a?(Proc)
|
5
|
+
::Compass.configuration.asset_host(&Middleman::Server.asset_host)
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
@@ -11,7 +11,7 @@ class Middleman::Features::AssetHost
|
|
11
11
|
|
12
12
|
valid_extensions = %w(.png .gif .jpg .jpeg .js .css)
|
13
13
|
|
14
|
-
asset_prefix = Middleman::
|
14
|
+
asset_prefix = Middleman::Server.asset_host.call(original_output)
|
15
15
|
|
16
16
|
File.join(asset_prefix, original_output)
|
17
17
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class Middleman::Features::AutomaticImageSizes
|
2
|
-
def initialize(app)
|
2
|
+
def initialize(app, config)
|
3
3
|
require "middleman/features/automatic_image_sizes/fastimage"
|
4
4
|
|
5
|
-
Middleman::
|
6
|
-
|
5
|
+
Middleman::Server.helpers do
|
6
|
+
alias_method :pre_automatic_image_tag, :image_tag
|
7
7
|
def image_tag(path, params={})
|
8
8
|
if (!params[:width] || !params[:height]) && !path.include?("://")
|
9
9
|
params[:alt] ||= ""
|
@@ -12,7 +12,7 @@ class Middleman::Features::AutomaticImageSizes
|
|
12
12
|
begin
|
13
13
|
real_path = File.join(settings.public, settings.images_dir, path)
|
14
14
|
if File.exists? real_path
|
15
|
-
dimensions =
|
15
|
+
dimensions = ::FastImage.size(real_path, :raise_on_failure => true)
|
16
16
|
params[:width] ||= dimensions[0]
|
17
17
|
params[:height] ||= dimensions[1]
|
18
18
|
end
|
@@ -32,251 +32,256 @@
|
|
32
32
|
require 'net/https'
|
33
33
|
require 'open-uri'
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
attr_reader :size, :type
|
35
|
+
class FastImage
|
36
|
+
attr_reader :size, :type
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
49
48
|
|
50
|
-
|
49
|
+
DefaultTimeout = 2
|
51
50
|
|
52
|
-
|
51
|
+
LocalFileChunkSize = 256
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
99
98
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
135
134
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
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
|
141
144
|
if @parsed_uri.scheme == "http" || @parsed_uri.scheme == "https"
|
142
145
|
fetch_using_http
|
143
146
|
else
|
144
147
|
fetch_using_open_uri
|
145
148
|
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
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
|
154
159
|
|
155
|
-
|
160
|
+
private
|
156
161
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
end
|
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)
|
164
168
|
end
|
165
169
|
end
|
170
|
+
end
|
166
171
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
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
|
174
179
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
end
|
180
|
+
def fetch_using_open_uri
|
181
|
+
open(@uri) do |s|
|
182
|
+
while str = s.read(LocalFileChunkSize)
|
183
|
+
break if parse_packet(str)
|
180
184
|
end
|
181
185
|
end
|
186
|
+
end
|
182
187
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
194
|
-
rescue MoreCharsNeeded
|
195
|
-
false
|
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
|
196
198
|
end
|
199
|
+
rescue MoreCharsNeeded
|
200
|
+
false
|
197
201
|
end
|
202
|
+
end
|
198
203
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
204
|
+
def parse_size
|
205
|
+
@type = parse_type unless @type
|
206
|
+
@strpos = 0
|
207
|
+
send("parse_size_for_#{@type}")
|
208
|
+
end
|
203
209
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
end
|
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
|
213
218
|
end
|
219
|
+
end
|
214
220
|
|
215
|
-
|
216
|
-
|
217
|
-
|
221
|
+
def get_byte
|
222
|
+
get_chars(1).unpack("C")[0]
|
223
|
+
end
|
218
224
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
225
|
+
def read_int(str)
|
226
|
+
size_bytes = str.unpack("CC")
|
227
|
+
(size_bytes[0] << 8) + size_bytes[1]
|
228
|
+
end
|
223
229
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
end
|
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
|
237
242
|
end
|
243
|
+
end
|
238
244
|
|
239
|
-
|
240
|
-
|
241
|
-
|
245
|
+
def parse_size_for_gif
|
246
|
+
get_chars(11)[6..10].unpack('SS')
|
247
|
+
end
|
242
248
|
|
243
|
-
|
244
|
-
|
245
|
-
|
249
|
+
def parse_size_for_png
|
250
|
+
get_chars(25)[16..24].unpack('NN')
|
251
|
+
end
|
246
252
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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])]
|
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
|
273
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])]
|
274
279
|
end
|
275
280
|
end
|
281
|
+
end
|
276
282
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
end
|
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')
|
281
286
|
end
|
282
287
|
end
|