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