middleman 2.0.9.pre-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/.gitignore +13 -0
- data/.travis.yml +4 -0
- data/CHANGELOG +47 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +19 -0
- data/Rakefile +15 -0
- data/bin/middleman +73 -0
- data/bin/mm-build +9 -0
- data/bin/mm-init +9 -0
- data/bin/mm-server +9 -0
- data/features/asset_host.feature +14 -0
- data/features/automatic_image_sizes.feature +16 -0
- data/features/builder.feature +23 -0
- data/features/cache_buster.feature +26 -0
- data/features/coffee-script.feature +17 -0
- data/features/data.feature +12 -0
- data/features/directory_index.feature +29 -0
- data/features/dynamic_pages.feature +33 -0
- data/features/front-matter.feature +7 -0
- data/features/generator.feature +8 -0
- data/features/helpers_auto_javascript_include_tag.feature +27 -0
- data/features/helpers_auto_stylesheet_link_tag.feature +27 -0
- data/features/helpers_page_classes.feature +17 -0
- data/features/liquid.feature +6 -0
- data/features/markdown.feature +7 -0
- data/features/minify_css.feature +24 -0
- data/features/minify_javascript.feature +23 -0
- data/features/padrino_helpers.feature +10 -0
- data/features/page_alias_and_layouts.feature +44 -0
- data/features/relative_assets.feature +44 -0
- data/features/scss-support.feature +12 -0
- data/features/sinatra.feature +6 -0
- data/features/slim.feature +7 -0
- data/features/sprockets.feature +21 -0
- data/features/sprockets_gems.feature +7 -0
- data/features/step_definitions/asset_host_steps.rb +8 -0
- data/features/step_definitions/builder_steps.rb +40 -0
- data/features/step_definitions/generator_steps.rb +30 -0
- data/features/step_definitions/middleman_steps.rb +46 -0
- data/features/step_definitions/page_layout_steps.rb +13 -0
- data/features/support/env.rb +3 -0
- data/features/tiny_src.feature +15 -0
- data/fixtures/indexable-app/config.rb +2 -0
- data/fixtures/indexable-app/source/a_folder/needs_index.html +1 -0
- data/fixtures/indexable-app/source/leave_me_alone.html +1 -0
- data/fixtures/indexable-app/source/needs_index.html +1 -0
- data/fixtures/indexable-app/source/regular/index.html +1 -0
- data/fixtures/relative-app/config.rb +0 -0
- data/fixtures/relative-app/source/images/blank.gif +0 -0
- data/fixtures/relative-app/source/stylesheets/relative_assets.css.sass +3 -0
- data/fixtures/sprockets-app/config.rb +1 -0
- data/fixtures/sprockets-app/source/jquery_include.js +1 -0
- data/fixtures/sprockets-app/source/library/javascripts/sprockets_base.js +5 -0
- data/fixtures/sprockets-app/source/library/javascripts/sprockets_sub.js +3 -0
- data/fixtures/test-app/config.rb +51 -0
- data/fixtures/test-app/data/test.yml +4 -0
- data/fixtures/test-app/source/_liquid_partial.liquid +1 -0
- data/fixtures/test-app/source/_partial.haml +1 -0
- data/fixtures/test-app/source/a_folder/needs_index.html +1 -0
- data/fixtures/test-app/source/asset_host.html.haml +1 -0
- data/fixtures/test-app/source/auto-css.html.haml +1 -0
- data/fixtures/test-app/source/auto-css/auto-css.html.haml +1 -0
- data/fixtures/test-app/source/auto-css/index.html.haml +1 -0
- data/fixtures/test-app/source/auto-css/sub/auto-css.html.haml +1 -0
- data/fixtures/test-app/source/auto-image-sizes.html.haml +1 -0
- data/fixtures/test-app/source/auto-js.html.haml +1 -0
- data/fixtures/test-app/source/auto-js/auto-js.html.haml +1 -0
- data/fixtures/test-app/source/auto-js/index.html.haml +1 -0
- data/fixtures/test-app/source/auto-js/sub/auto-js.html.haml +1 -0
- data/fixtures/test-app/source/cache-buster.html.haml +2 -0
- data/fixtures/test-app/source/custom-layout-dir/index.html.haml +1 -0
- data/fixtures/test-app/source/custom-layout.html.haml +1 -0
- data/fixtures/test-app/source/data.html.erb +1 -0
- data/fixtures/test-app/source/data2.html.liquid +2 -0
- data/fixtures/test-app/source/front-matter.html.erb +6 -0
- data/fixtures/test-app/source/images/Child folder/regular_file(example).txt +1 -0
- data/fixtures/test-app/source/images/Read me (example).txt +1 -0
- data/fixtures/test-app/source/images/blank.gif +0 -0
- data/fixtures/test-app/source/img/blank.gif +0 -0
- data/fixtures/test-app/source/index.html.haml +6 -0
- data/fixtures/test-app/source/inline-coffeescript.html.haml +3 -0
- data/fixtures/test-app/source/inline-css.html.haml +4 -0
- data/fixtures/test-app/source/inline-js.html.haml +7 -0
- data/fixtures/test-app/source/javascripts/auto-js.js +1 -0
- data/fixtures/test-app/source/javascripts/auto-js/auto-js.js +1 -0
- data/fixtures/test-app/source/javascripts/auto-js/index.js +1 -0
- data/fixtures/test-app/source/javascripts/auto-js/sub/auto-js.js +1 -0
- data/fixtures/test-app/source/javascripts/broken-coffee.js.coffee +3 -0
- data/fixtures/test-app/source/javascripts/coffee_test.js.coffee +3 -0
- data/fixtures/test-app/source/javascripts/jquery.plugin.with.dots.js +1 -0
- data/fixtures/test-app/source/javascripts/jquery_base.js +5 -0
- data/fixtures/test-app/source/javascripts/multiple_engines.js.coffee.erb +1 -0
- data/fixtures/test-app/source/javascripts/sprockets_base.js +5 -0
- data/fixtures/test-app/source/javascripts/sprockets_sub.js +3 -0
- data/fixtures/test-app/source/layout.haml +6 -0
- data/fixtures/test-app/source/layouts/custom.haml +5 -0
- data/fixtures/test-app/source/liquid_master.html.liquid +1 -0
- data/fixtures/test-app/source/markdown.html.markdown +1 -0
- data/fixtures/test-app/source/needs_index.html +1 -0
- data/fixtures/test-app/source/padrino_test.html.haml +5 -0
- data/fixtures/test-app/source/page-classes.html.haml +1 -0
- data/fixtures/test-app/source/real.html +1 -0
- data/fixtures/test-app/source/real/index.html.erb +5 -0
- data/fixtures/test-app/source/relative_image.html.erb +1 -0
- data/fixtures/test-app/source/services/index.html.haml +1 -0
- data/fixtures/test-app/source/should_be_ignored.html +1 -0
- data/fixtures/test-app/source/should_be_ignored2.html +1 -0
- data/fixtures/test-app/source/should_be_ignored3.html +1 -0
- data/fixtures/test-app/source/slim.html.slim +7 -0
- data/fixtures/test-app/source/spaces in file.html.erb +1 -0
- data/fixtures/test-app/source/static.html +1 -0
- data/fixtures/test-app/source/stylesheets/asset_host.css.sass +3 -0
- data/fixtures/test-app/source/stylesheets/auto-css.css +3 -0
- data/fixtures/test-app/source/stylesheets/auto-css/auto-css.css +3 -0
- data/fixtures/test-app/source/stylesheets/auto-css/index.css +0 -0
- data/fixtures/test-app/source/stylesheets/auto-css/sub/auto-css.css +3 -0
- data/fixtures/test-app/source/stylesheets/layout.css.sass +2 -0
- data/fixtures/test-app/source/stylesheets/relative_assets.css.sass +3 -0
- data/fixtures/test-app/source/stylesheets/site.css.sass +1 -0
- data/fixtures/test-app/source/stylesheets/site_scss.css.scss +1 -0
- data/fixtures/test-app/source/stylesheets/static.css +2 -0
- data/fixtures/test-app/source/sub1/page-classes.html.haml +1 -0
- data/fixtures/test-app/source/sub1/sub2/page-classes.html.haml +1 -0
- data/fixtures/test-app/source/tiny_src.html.haml +1 -0
- data/lib/middleman.rb +202 -0
- data/lib/middleman/base.rb +198 -0
- data/lib/middleman/builder.rb +163 -0
- data/lib/middleman/cli.rb +87 -0
- data/lib/middleman/config.ru +2 -0
- data/lib/middleman/core_extensions/assets.rb +57 -0
- data/lib/middleman/core_extensions/builder.rb +41 -0
- data/lib/middleman/core_extensions/compass.rb +102 -0
- data/lib/middleman/core_extensions/data.rb +120 -0
- data/lib/middleman/core_extensions/default_helpers.rb +77 -0
- data/lib/middleman/core_extensions/features.rb +102 -0
- data/lib/middleman/core_extensions/front_matter.rb +116 -0
- data/lib/middleman/core_extensions/rack_map.rb +35 -0
- data/lib/middleman/core_extensions/rendering.rb +19 -0
- data/lib/middleman/core_extensions/routing.rb +87 -0
- data/lib/middleman/core_extensions/sprockets.rb +102 -0
- data/lib/middleman/features/asset_host.rb +22 -0
- data/lib/middleman/features/automatic_image_sizes.rb +31 -0
- data/lib/middleman/features/automatic_image_sizes/fastimage.rb +287 -0
- data/lib/middleman/features/cache_buster.rb +42 -0
- data/lib/middleman/features/directory_indexes.rb +56 -0
- data/lib/middleman/features/lorem.rb +126 -0
- data/lib/middleman/features/minify_css.rb +10 -0
- data/lib/middleman/features/minify_javascript.rb +43 -0
- data/lib/middleman/features/relative_assets.rb +38 -0
- data/lib/middleman/features/tiny_src.rb +11 -0
- data/lib/middleman/guard.rb +71 -0
- data/lib/middleman/renderers/coffee_script.rb +8 -0
- data/lib/middleman/renderers/haml.rb +31 -0
- data/lib/middleman/renderers/liquid.rb +29 -0
- data/lib/middleman/renderers/markdown.rb +34 -0
- data/lib/middleman/renderers/sass.rb +63 -0
- data/lib/middleman/renderers/slim.rb +8 -0
- data/lib/middleman/templates.rb +53 -0
- data/lib/middleman/templates/default.rb +17 -0
- data/lib/middleman/templates/default/source/index.html.erb +5 -0
- data/lib/middleman/templates/default/source/layout.erb +19 -0
- data/lib/middleman/templates/default/source/stylesheets/site.css.scss +32 -0
- data/lib/middleman/templates/html5.rb +16 -0
- data/lib/middleman/templates/html5/source/404.html +38 -0
- data/lib/middleman/templates/html5/source/README.md +388 -0
- data/lib/middleman/templates/html5/source/apple-touch-icon-114x114-precomposed.png +0 -0
- data/lib/middleman/templates/html5/source/apple-touch-icon-57x57-precomposed.png +0 -0
- data/lib/middleman/templates/html5/source/apple-touch-icon-72x72-precomposed.png +0 -0
- data/lib/middleman/templates/html5/source/apple-touch-icon-precomposed.png +0 -0
- data/lib/middleman/templates/html5/source/apple-touch-icon.png +0 -0
- data/lib/middleman/templates/html5/source/crossdomain.xml +25 -0
- data/lib/middleman/templates/html5/source/css/style.css +293 -0
- data/lib/middleman/templates/html5/source/favicon.ico +0 -0
- data/lib/middleman/templates/html5/source/humans.txt +43 -0
- data/lib/middleman/templates/html5/source/img/.gitignore +2 -0
- data/lib/middleman/templates/html5/source/index.html +79 -0
- data/lib/middleman/templates/html5/source/js/libs/jquery-1.6.2.js +8981 -0
- data/lib/middleman/templates/html5/source/js/libs/jquery-1.6.2.min.js +18 -0
- data/lib/middleman/templates/html5/source/js/libs/modernizr-2.0.6.min.js +4 -0
- data/lib/middleman/templates/html5/source/js/mylibs/.gitignore +2 -0
- data/lib/middleman/templates/html5/source/js/plugins.js +20 -0
- data/lib/middleman/templates/html5/source/js/script.js +8 -0
- data/lib/middleman/templates/html5/source/robots.txt +5 -0
- data/lib/middleman/templates/html5/source/test/index.html +31 -0
- data/lib/middleman/templates/html5/source/test/qunit/qunit.css +148 -0
- data/lib/middleman/templates/html5/source/test/qunit/qunit.js +1265 -0
- data/lib/middleman/templates/html5/source/test/tests.js +24 -0
- data/lib/middleman/templates/local.rb +20 -0
- data/lib/middleman/templates/shared/Gemfile.tt +3 -0
- data/lib/middleman/templates/shared/config.ru +4 -0
- data/lib/middleman/templates/shared/config.tt +104 -0
- data/lib/middleman/version.rb +3 -0
- data/middleman.gemspec +79 -0
- metadata +826 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "tilt"
|
3
|
+
|
4
|
+
module Middleman::CoreExtensions::FrontMatter
|
5
|
+
class << self
|
6
|
+
def registered(app)
|
7
|
+
app.extend ClassMethods
|
8
|
+
|
9
|
+
::Tilt::register RDiscountTemplate, 'markdown', 'mkd', 'md'
|
10
|
+
::Tilt::register RedcarpetTemplate, 'markdown', 'mkd', 'md'
|
11
|
+
::Tilt::register MarukuTemplate, 'markdown', 'mkd', 'md'
|
12
|
+
::Tilt::register KramdownTemplate, 'markdown', 'mkd', 'md'
|
13
|
+
app.set :markdown_engine_prefix, ::Middleman::CoreExtensions::FrontMatter
|
14
|
+
|
15
|
+
::Tilt::register RedClothTemplate, 'textile'
|
16
|
+
::Tilt.prefer(RedClothTemplate)
|
17
|
+
|
18
|
+
::Tilt::register ERBTemplate, 'erb', 'rhtml'
|
19
|
+
::Tilt.prefer(ERBTemplate)
|
20
|
+
|
21
|
+
::Tilt::register LiquidTemplate, 'liquid'
|
22
|
+
::Tilt.prefer(LiquidTemplate)
|
23
|
+
|
24
|
+
::Tilt::register SlimTemplate, 'slim'
|
25
|
+
::Tilt.prefer(SlimTemplate)
|
26
|
+
|
27
|
+
::Tilt::register HamlTemplate, 'haml'
|
28
|
+
::Tilt.prefer(HamlTemplate)
|
29
|
+
|
30
|
+
app.after_configuration do
|
31
|
+
app.before_processing(:front_matter) do |result|
|
32
|
+
if result && Tilt.mappings.has_key?(result[1].to_s)
|
33
|
+
extensionless_path, template_engine = result
|
34
|
+
full_file_path = "#{extensionless_path}.#{template_engine}"
|
35
|
+
system_path = File.join(settings.views, full_file_path)
|
36
|
+
data, content = app.parse_front_matter(File.read(system_path))
|
37
|
+
|
38
|
+
request['custom_options'] = {}
|
39
|
+
%w(layout layout_engine).each do |opt|
|
40
|
+
if data.has_key?(opt)
|
41
|
+
request['custom_options'][opt.to_sym] = data.delete(opt)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Forward remaining data to helpers
|
46
|
+
app.data_content("page", data)
|
47
|
+
end
|
48
|
+
|
49
|
+
true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
alias :included :registered
|
54
|
+
|
55
|
+
def parse_front_matter(content)
|
56
|
+
yaml_regex = /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
57
|
+
if content =~ yaml_regex
|
58
|
+
begin
|
59
|
+
data = YAML.load($1)
|
60
|
+
rescue => e
|
61
|
+
puts "YAML Exception: #{e.message}"
|
62
|
+
end
|
63
|
+
|
64
|
+
content = content.split(yaml_regex).last
|
65
|
+
end
|
66
|
+
|
67
|
+
data ||= {}
|
68
|
+
[data, content]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
module ClassMethods
|
73
|
+
def parse_front_matter(content)
|
74
|
+
Middleman::CoreExtensions::FrontMatter.parse_front_matter(content)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module YamlAware
|
79
|
+
def prepare
|
80
|
+
@frontmatter, @data = Middleman::CoreExtensions::FrontMatter.parse_front_matter(@data)
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class RDiscountTemplate < ::Tilt::RDiscountTemplate
|
86
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
87
|
+
end
|
88
|
+
class RedcarpetTemplate < ::Tilt::RedcarpetTemplate
|
89
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
90
|
+
end
|
91
|
+
class MarukuTemplate < ::Tilt::MarukuTemplate
|
92
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
93
|
+
end
|
94
|
+
class RedClothTemplate < ::Tilt::RedClothTemplate
|
95
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
96
|
+
end
|
97
|
+
class KramdownTemplate < ::Tilt::KramdownTemplate
|
98
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
99
|
+
end
|
100
|
+
|
101
|
+
class ERBTemplate < ::Tilt::ERBTemplate
|
102
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
103
|
+
end
|
104
|
+
|
105
|
+
class LiquidTemplate < ::Tilt::LiquidTemplate
|
106
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
107
|
+
end
|
108
|
+
|
109
|
+
class HamlTemplate < ::Tilt::HamlTemplate
|
110
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
111
|
+
end
|
112
|
+
|
113
|
+
class SlimTemplate < ::Slim::Template
|
114
|
+
include Middleman::CoreExtensions::FrontMatter::YamlAware
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Middleman::CoreExtensions::RackMap
|
2
|
+
class << self
|
3
|
+
def registered(app)
|
4
|
+
app.extend ClassMethods
|
5
|
+
end
|
6
|
+
alias :included :registered
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def map(path, &block)
|
11
|
+
@maps ||= []
|
12
|
+
@maps << [path, block]
|
13
|
+
end
|
14
|
+
|
15
|
+
def maps
|
16
|
+
@maps || []
|
17
|
+
end
|
18
|
+
|
19
|
+
# Creates a Rack::Builder instance with all the middleware set up and
|
20
|
+
# an instance of this class as end point.
|
21
|
+
def build(*args, &bk)
|
22
|
+
builder = ::Rack::Builder.new
|
23
|
+
builder.use ::Sinatra::ShowExceptions if show_exceptions?
|
24
|
+
builder.use ::Rack::CommonLogger if logging?
|
25
|
+
builder.use ::Rack::Head
|
26
|
+
middleware.each { |c,a,b| builder.use(c, *a, &b) }
|
27
|
+
maps.each { |p,b| builder.map(p, &b) }
|
28
|
+
app = self
|
29
|
+
builder.map "/" do
|
30
|
+
run app.new!(*args, &bk)
|
31
|
+
end
|
32
|
+
builder
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "padrino-core/application/rendering"
|
2
|
+
|
3
|
+
module Middleman::CoreExtensions::Rendering
|
4
|
+
class << self
|
5
|
+
def registered(app)
|
6
|
+
# Tilt-aware renderer
|
7
|
+
app.register Padrino::Rendering
|
8
|
+
|
9
|
+
# Activate custom renderers
|
10
|
+
app.register Middleman::Renderers::Slim
|
11
|
+
app.register Middleman::Renderers::Haml
|
12
|
+
app.register Middleman::Renderers::Sass
|
13
|
+
app.register Middleman::Renderers::Markdown
|
14
|
+
app.register Middleman::Renderers::CoffeeScript
|
15
|
+
app.register Middleman::Renderers::Liquid
|
16
|
+
end
|
17
|
+
alias :included :registered
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Middleman::CoreExtensions::Routing
|
2
|
+
class << self
|
3
|
+
def registered(app)
|
4
|
+
app.extend ClassMethods
|
5
|
+
|
6
|
+
app.set :proxied_paths, {}
|
7
|
+
app.set :excluded_paths, []
|
8
|
+
|
9
|
+
app.build_reroute do |destination, request_path|
|
10
|
+
throw if app.settings.excluded_paths.include?(request_path)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
alias :included :registered
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def path_to_index(path)
|
18
|
+
parts = path ? path.split('/') : []
|
19
|
+
if parts.last.nil? || parts.last.split('.').length == 1
|
20
|
+
path = File.join(path, settings.index_file)
|
21
|
+
end
|
22
|
+
path.gsub(%r{^/}, '')
|
23
|
+
end
|
24
|
+
|
25
|
+
# Takes a block which allows many pages to have the same layout
|
26
|
+
# with_layout :admin do
|
27
|
+
# page "/admin/"
|
28
|
+
# page "/admin/login.html"
|
29
|
+
# end
|
30
|
+
def with_layout(layout_name, &block)
|
31
|
+
old_layout = settings.layout
|
32
|
+
|
33
|
+
set :layout, layout_name
|
34
|
+
class_eval(&block) if block_given?
|
35
|
+
ensure
|
36
|
+
set :layout, old_layout
|
37
|
+
end
|
38
|
+
|
39
|
+
def paths_for_url(url)
|
40
|
+
url = url.gsub(%r{\/#{settings.index_file}$}, "")
|
41
|
+
url = url.gsub(%r{(\/)$}, "") if url.length > 1
|
42
|
+
|
43
|
+
paths = [url]
|
44
|
+
paths << "#{url}/" if url.length > 1 && url.split("/").last.split('.').length <= 1
|
45
|
+
paths << "/#{path_to_index(url)}"
|
46
|
+
paths
|
47
|
+
end
|
48
|
+
|
49
|
+
# Keep a path from building
|
50
|
+
def ignore(path)
|
51
|
+
settings.excluded_paths << paths_for_url(path)
|
52
|
+
settings.excluded_paths.flatten!
|
53
|
+
settings.excluded_paths.uniq!
|
54
|
+
end
|
55
|
+
|
56
|
+
# The page method allows the layout to be set on a specific path
|
57
|
+
# page "/about.html", :layout => false
|
58
|
+
# page "/", :layout => :homepage_layout
|
59
|
+
def page(url, options={}, &block)
|
60
|
+
has_block = block_given?
|
61
|
+
options[:layout] = settings.layout if options[:layout].nil?
|
62
|
+
|
63
|
+
if options.has_key?(:proxy)
|
64
|
+
settings.proxied_paths[url] = options[:proxy]
|
65
|
+
if options.has_key?(:ignore) && options[:ignore]
|
66
|
+
settings.ignore(options[:proxy])
|
67
|
+
end
|
68
|
+
else
|
69
|
+
if options.has_key?(:ignore) && options[:ignore]
|
70
|
+
settings.ignore(url)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
paths_for_url(url).each do |p|
|
75
|
+
get(p) do
|
76
|
+
if settings.proxied_paths.has_key?(url)
|
77
|
+
request["is_proxy"] = true
|
78
|
+
request.path_info = settings.proxied_paths[url]
|
79
|
+
end
|
80
|
+
|
81
|
+
instance_eval(&block) if has_block
|
82
|
+
process_request(options)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rbconfig'
|
3
|
+
require "sprockets"
|
4
|
+
|
5
|
+
module Middleman::CoreExtensions::Sprockets
|
6
|
+
class << self
|
7
|
+
def registered(app)
|
8
|
+
app.set :js_compressor, false
|
9
|
+
|
10
|
+
# Cut off every extension after .js (which sprockets eats up)
|
11
|
+
app.build_reroute do |destination, request_path|
|
12
|
+
if !request_path.match(/\.js\./i)
|
13
|
+
false
|
14
|
+
else
|
15
|
+
[
|
16
|
+
destination.gsub(/\.js(\..*)$/, ".js"),
|
17
|
+
request_path.gsub(/\.js(\..*)$/, ".js")
|
18
|
+
]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
app.after_configuration do
|
23
|
+
js_env = Middleman::CoreExtensions::Sprockets::JavascriptEnvironment.new(app)
|
24
|
+
|
25
|
+
js_dir = File.join("vendor", "assets", "javascripts")
|
26
|
+
gems_with_js = ::Middleman.rubygems_latest_specs.select do |spec|
|
27
|
+
::Middleman.spec_has_file?(spec, js_dir)
|
28
|
+
end.each do |spec|
|
29
|
+
js_env.append_path File.join(spec.full_gem_path, js_dir)
|
30
|
+
end
|
31
|
+
|
32
|
+
# add paths to js_env (vendor/assets/javascripts)
|
33
|
+
app.map "/#{app.js_dir}" do
|
34
|
+
run js_env
|
35
|
+
end
|
36
|
+
|
37
|
+
# app.map "/#{app.css_dir}" do
|
38
|
+
# run Middleman::CoreExtensions::Sprockets::StylesheetEnvironment.new(app)
|
39
|
+
# end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias :included :registered
|
43
|
+
end
|
44
|
+
|
45
|
+
class MiddlemanEnvironment < ::Sprockets::Environment
|
46
|
+
def initialize(app)
|
47
|
+
full_path = app.views
|
48
|
+
full_path = File.join(app.root, app.views) unless app.views.include?(app.root)
|
49
|
+
|
50
|
+
super File.expand_path(full_path)
|
51
|
+
|
52
|
+
# Make the app context available to Sprockets
|
53
|
+
context_class.send(:define_method, :app) { app }
|
54
|
+
context_class.class_eval do
|
55
|
+
def method_missing(name)
|
56
|
+
if app.respond_to?(name)
|
57
|
+
app.send(name)
|
58
|
+
else
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class JavascriptEnvironment < MiddlemanEnvironment
|
67
|
+
def initialize(app)
|
68
|
+
super
|
69
|
+
|
70
|
+
# Disable css
|
71
|
+
unregister_processor "text/css", ::Sprockets::DirectiveProcessor
|
72
|
+
|
73
|
+
self.js_compressor = app.settings.js_compressor
|
74
|
+
|
75
|
+
# configure search paths
|
76
|
+
append_path app.js_dir
|
77
|
+
end
|
78
|
+
|
79
|
+
def javascript_exception_response(exception)
|
80
|
+
expire_index!
|
81
|
+
super(exception)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# class StylesheetEnvironment < MiddlemanEnvironment
|
86
|
+
# def initialize(app)
|
87
|
+
# super
|
88
|
+
#
|
89
|
+
# # Disable js
|
90
|
+
# unregister_processor "application/javascript", ::Sprockets::DirectiveProcessor
|
91
|
+
#
|
92
|
+
# # configure search paths
|
93
|
+
# stylesheets_path = File.join(File.expand_path(app.views), app.css_dir)
|
94
|
+
# append_path stylesheets_path
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# def css_exception_response(exception)
|
98
|
+
# expire_index!
|
99
|
+
# super(exception)
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Middleman::Features::AssetHost
|
2
|
+
class << self
|
3
|
+
def registered(app)
|
4
|
+
app.compass_config do |config|
|
5
|
+
if app.asset_host.is_a?(Proc)
|
6
|
+
config.asset_host(&app.asset_host)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
app.register_asset_handler :asset_host do |path, prefix, request|
|
11
|
+
original_output = app.before_asset_handler(:asset_host, path, prefix, request)
|
12
|
+
|
13
|
+
valid_extensions = %w(.png .gif .jpg .jpeg .js .css)
|
14
|
+
|
15
|
+
asset_prefix = app.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,31 @@
|
|
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.views, 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
|
+
end
|
27
|
+
|
28
|
+
super(path, params)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
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
|