middleman-more 3.1.0.beta.1 → 3.1.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/features/asset_hash.feature +3 -3
- data/features/asset_host.feature +52 -3
- data/features/minify_javascript.feature +3 -3
- data/fixtures/asset-host-app/config.rb +0 -6
- data/lib/middleman-more/core_extensions/compass.rb +67 -84
- data/lib/middleman-more/core_extensions/default_helpers.rb +206 -215
- data/lib/middleman-more/core_extensions/i18n.rb +121 -145
- data/lib/middleman-more/extensions/asset_hash.rb +76 -96
- data/lib/middleman-more/extensions/asset_host.rb +37 -36
- data/lib/middleman-more/extensions/automatic_image_sizes.rb +33 -49
- data/lib/middleman-more/extensions/cache_buster.rb +44 -59
- data/lib/middleman-more/extensions/directory_indexes.rb +21 -51
- data/lib/middleman-more/extensions/gzip.rb +54 -57
- data/lib/middleman-more/extensions/lorem.rb +151 -172
- data/lib/middleman-more/extensions/minify_css.rb +59 -71
- data/lib/middleman-more/extensions/minify_javascript.rb +64 -75
- data/lib/middleman-more/extensions/relative_assets.rb +22 -38
- data/lib/middleman-more.rb +24 -45
- data/middleman-more.gemspec +2 -2
- metadata +19 -46
- data/features/asset_host_compass.feature +0 -7
@@ -1,58 +1,42 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
module Extensions
|
1
|
+
# Automatic Image Sizes extension
|
2
|
+
class Middleman::Extensions::AutomaticImageSizes < ::Middleman::Extension
|
4
3
|
|
5
|
-
|
6
|
-
|
4
|
+
def initialize(app, options_hash={}, &block)
|
5
|
+
super
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# Once registered
|
12
|
-
def registered(app)
|
13
|
-
# Include 3rd-party fastimage library
|
14
|
-
require "middleman-more/extensions/automatic_image_sizes/fastimage"
|
15
|
-
|
16
|
-
# Include methods
|
17
|
-
app.send :include, InstanceMethods
|
18
|
-
end
|
19
|
-
|
20
|
-
alias :included :registered
|
21
|
-
end
|
22
|
-
|
23
|
-
# Automatic Image Sizes Instance Methods
|
24
|
-
module InstanceMethods
|
25
|
-
|
26
|
-
# Override default image_tag helper to automatically calculate and include
|
27
|
-
# image dimensions.
|
28
|
-
#
|
29
|
-
# @param [String] path
|
30
|
-
# @param [Hash] params
|
31
|
-
# @return [String]
|
32
|
-
def image_tag(path, params={})
|
33
|
-
if !params.has_key?(:width) && !params.has_key?(:height) && !path.include?("://")
|
34
|
-
params[:alt] ||= ""
|
35
|
-
|
36
|
-
real_path = path
|
37
|
-
real_path = File.join(images_dir, real_path) unless real_path.start_with?('/')
|
38
|
-
full_path = File.join(source_dir, real_path)
|
7
|
+
# Include 3rd-party fastimage library
|
8
|
+
require "middleman-more/extensions/automatic_image_sizes/fastimage"
|
9
|
+
end
|
39
10
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
11
|
+
helpers do
|
12
|
+
# Override default image_tag helper to automatically calculate and include
|
13
|
+
# image dimensions.
|
14
|
+
#
|
15
|
+
# @param [String] path
|
16
|
+
# @param [Hash] params
|
17
|
+
# @return [String]
|
18
|
+
def image_tag(path, params={})
|
19
|
+
if !params.has_key?(:width) && !params.has_key?(:height) && !path.include?("://")
|
20
|
+
params[:alt] ||= ""
|
21
|
+
|
22
|
+
real_path = path
|
23
|
+
real_path = File.join(images_dir, real_path) unless real_path.start_with?('/')
|
24
|
+
full_path = File.join(source_dir, real_path)
|
25
|
+
|
26
|
+
if File.exists?(full_path)
|
27
|
+
begin
|
28
|
+
width, height = ::FastImage.size(full_path, :raise_on_failure => true)
|
29
|
+
params[:width] = width
|
30
|
+
params[:height] = height
|
31
|
+
rescue FastImage::UnknownImageType
|
32
|
+
# No message, it's just not supported
|
33
|
+
rescue
|
34
|
+
warn "Couldn't determine dimensions for image #{path}: #{$!.message}"
|
51
35
|
end
|
52
|
-
|
53
|
-
super(path, params)
|
54
36
|
end
|
55
37
|
end
|
38
|
+
|
39
|
+
super(path, params)
|
56
40
|
end
|
57
41
|
end
|
58
42
|
end
|
@@ -1,70 +1,55 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
# After compass is setup, make it use the registered cache buster
|
17
|
-
app.compass_config do |config|
|
18
|
-
config.asset_cache_buster do |path, real_path|
|
19
|
-
real_path = real_path.path if real_path.is_a? File
|
20
|
-
real_path = real_path.gsub(File.join(root, build_dir), source)
|
21
|
-
if File.readable?(real_path)
|
22
|
-
File.mtime(real_path).strftime("%s")
|
23
|
-
else
|
24
|
-
logger.warn "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
1
|
+
# The Cache Buster extension
|
2
|
+
class Middleman::Extensions::CacheBuster < ::Middleman::Extension
|
3
|
+
|
4
|
+
def initialize(app, options_hash={}, &block)
|
5
|
+
super
|
6
|
+
|
7
|
+
# After compass is setup, make it use the registered cache buster
|
8
|
+
app.compass_config do |config|
|
9
|
+
config.asset_cache_buster do |path, real_path|
|
10
|
+
real_path = real_path.path if real_path.is_a? File
|
11
|
+
real_path = real_path.gsub(File.join(root, build_dir), source)
|
12
|
+
if File.readable?(real_path)
|
13
|
+
File.mtime(real_path).strftime("%s")
|
14
|
+
else
|
15
|
+
logger.warn "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
|
28
16
|
end
|
29
|
-
alias :included :registered
|
30
17
|
end
|
18
|
+
end
|
19
|
+
end
|
31
20
|
|
32
|
-
|
33
|
-
|
21
|
+
helpers do
|
22
|
+
# asset_url override if we're using cache busting
|
23
|
+
# @param [String] path
|
24
|
+
# @param [String] prefix
|
25
|
+
def asset_url(path, prefix="")
|
26
|
+
http_path = super
|
27
|
+
|
28
|
+
if http_path.include?("://") || !%w(.css .png .jpg .jpeg .svg .svgz .js .gif).include?(File.extname(http_path))
|
29
|
+
http_path
|
30
|
+
else
|
31
|
+
if respond_to?(:http_images_path) && prefix == http_images_path
|
32
|
+
prefix = images_dir
|
33
|
+
end
|
34
34
|
|
35
|
-
|
36
|
-
# @param [String] path
|
37
|
-
# @param [String] prefix
|
38
|
-
def asset_url(path, prefix="")
|
39
|
-
http_path = super
|
35
|
+
real_path_static = File.join(prefix, path)
|
40
36
|
|
41
|
-
|
42
|
-
|
37
|
+
if build?
|
38
|
+
real_path_dynamic = File.join(build_dir, prefix, path)
|
39
|
+
real_path_dynamic = File.expand_path(real_path_dynamic, root)
|
40
|
+
http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
|
41
|
+
elsif resource = sitemap.find_resource_by_path(real_path_static)
|
42
|
+
if !resource.template?
|
43
|
+
http_path << "?" + File.mtime(resource.source_file).strftime("%s")
|
43
44
|
else
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
real_path_static = File.join(prefix, path)
|
49
|
-
|
50
|
-
if build?
|
51
|
-
real_path_dynamic = File.join(build_dir, prefix, path)
|
52
|
-
real_path_dynamic = File.expand_path(real_path_dynamic, root)
|
53
|
-
http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
|
54
|
-
elsif resource = sitemap.find_resource_by_path(real_path_static)
|
55
|
-
if !resource.template?
|
56
|
-
http_path << "?" + File.mtime(resource.source_file).strftime("%s")
|
57
|
-
else
|
58
|
-
# It's a template, possible with partials. We can't really
|
59
|
-
# know when it's updated, so generate fresh cache buster every
|
60
|
-
# time during developement
|
61
|
-
http_path << "?" + Time.now.strftime("%s")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
http_path
|
45
|
+
# It's a template, possible with partials. We can't really
|
46
|
+
# know when it's updated, so generate fresh cache buster every
|
47
|
+
# time during developement
|
48
|
+
http_path << "?" + Time.now.strftime("%s")
|
66
49
|
end
|
67
50
|
end
|
51
|
+
|
52
|
+
http_path
|
68
53
|
end
|
69
54
|
end
|
70
55
|
end
|
@@ -1,54 +1,24 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
# Central class for managing the directory indexes extension
|
25
|
-
class DirectoryIndexManager
|
26
|
-
def initialize(app)
|
27
|
-
@app = app
|
28
|
-
end
|
29
|
-
|
30
|
-
# Update the main sitemap resource list
|
31
|
-
# @return [void]
|
32
|
-
def manipulate_resource_list(resources)
|
33
|
-
index_file = @app.index_file
|
34
|
-
new_index_path = "/#{index_file}"
|
35
|
-
|
36
|
-
resources.each do |resource|
|
37
|
-
# Check if it would be pointless to reroute
|
38
|
-
next if resource.destination_path == index_file ||
|
39
|
-
resource.destination_path.end_with?(new_index_path) ||
|
40
|
-
File.extname(index_file) != resource.ext
|
41
|
-
|
42
|
-
# Check if frontmatter turns directory_index off
|
43
|
-
next if resource.data[:directory_index] == false
|
44
|
-
|
45
|
-
# Check if file metadata (options set by "page" in config.rb) turns directory_index off
|
46
|
-
next if resource.metadata[:options][:directory_index] == false
|
47
|
-
|
48
|
-
resource.destination_path = resource.destination_path.chomp(File.extname(index_file)) + new_index_path
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
1
|
+
# Directory Indexes extension
|
2
|
+
class Middleman::Extensions::DirectoryIndexes < ::Middleman::Extension
|
3
|
+
# Update the main sitemap resource list
|
4
|
+
# @return [void]
|
5
|
+
def manipulate_resource_list(resources)
|
6
|
+
index_file = app.index_file
|
7
|
+
new_index_path = "/#{index_file}"
|
8
|
+
|
9
|
+
resources.each do |resource|
|
10
|
+
# Check if it would be pointless to reroute
|
11
|
+
next if resource.destination_path == index_file ||
|
12
|
+
resource.destination_path.end_with?(new_index_path) ||
|
13
|
+
File.extname(index_file) != resource.ext
|
14
|
+
|
15
|
+
# Check if frontmatter turns directory_index off
|
16
|
+
next if resource.data[:directory_index] == false
|
17
|
+
|
18
|
+
# Check if file metadata (options set by "page" in config.rb) turns directory_index off
|
19
|
+
next if resource.metadata[:options][:directory_index] == false
|
20
|
+
|
21
|
+
resource.destination_path = resource.destination_path.chomp(File.extname(index_file)) + new_index_path
|
52
22
|
end
|
53
23
|
end
|
54
24
|
end
|
@@ -1,73 +1,70 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# This extension Gzips assets and pages when building.
|
2
|
+
# Gzipped assets and pages can be served directly by Apache or
|
3
|
+
# Nginx with the proper configuration, and pre-zipping means that we
|
4
|
+
# can use a more agressive compression level at no CPU cost per request.
|
5
|
+
#
|
6
|
+
# Use Nginx's gzip_static directive, or AddEncoding and mod_rewrite in Apache
|
7
|
+
# to serve your Gzipped files whenever the normal (non-.gz) filename is requested.
|
8
|
+
#
|
9
|
+
# Pass the :exts options to customize which file extensions get zipped (defaults
|
10
|
+
# to .html, .htm, .js and .css.
|
11
|
+
#
|
12
|
+
class Middleman::Extensions::Gzip < ::Middleman::Extension
|
13
|
+
option :exts, %w(.js .css .html .htm), 'File extensions to Gzip when building.'
|
4
14
|
|
5
|
-
|
15
|
+
def initialize(app, options_hash={})
|
16
|
+
super
|
17
|
+
|
18
|
+
require 'zlib'
|
19
|
+
require 'stringio'
|
20
|
+
require 'find'
|
6
21
|
|
7
|
-
|
8
|
-
# Gzipped assets and pages can be served directly by Apache or
|
9
|
-
# Nginx with the proper configuration, and pre-zipping means that we
|
10
|
-
# can use a more agressive compression level at no CPU cost per request.
|
11
|
-
#
|
12
|
-
# Use Nginx's gzip_static directive, or AddEncoding and mod_rewrite in Apache
|
13
|
-
# to serve your Gzipped files whenever the normal (non-.gz) filename is requested.
|
14
|
-
#
|
15
|
-
# Pass the :exts options to customize which file extensions get zipped (defaults
|
16
|
-
# to .html, .htm, .js and .css.
|
17
|
-
#
|
18
|
-
class Gzip < ::Middleman::Extension
|
19
|
-
option :exts, %w(.js .css .html .htm), 'File extensions to Gzip when building.'
|
22
|
+
gzip_ext = self
|
20
23
|
|
21
|
-
|
22
|
-
|
24
|
+
app.after_build do |builder|
|
25
|
+
paths = ::Middleman::Util.all_files_under(self.class.inst.build_dir)
|
26
|
+
paths.each do |path|
|
27
|
+
next unless gzip_ext.options.exts.include? path.extname
|
23
28
|
|
24
|
-
|
29
|
+
output_filename, old_size, new_size = gzip_ext.gzip_file(path.to_s)
|
25
30
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
if output_filename
|
34
|
-
size_change_word = (old_size - new_size) > 0 ? 'smaller' : 'larger'
|
35
|
-
old_locale = I18n.locale
|
36
|
-
I18n.locale = :en # use the english localizations for printing out file sizes to make sure the localizations exist
|
37
|
-
builder.say_status :gzip, "#{output_filename} (#{number_to_human_size((old_size - new_size).abs)} #{size_change_word})"
|
38
|
-
I18n.locale = old_locale
|
39
|
-
end
|
31
|
+
if output_filename
|
32
|
+
size_change_word = (old_size - new_size) > 0 ? 'smaller' : 'larger'
|
33
|
+
old_locale = I18n.locale
|
34
|
+
I18n.locale = :en # use the english localizations for printing out file sizes to make sure the localizations exist
|
35
|
+
builder.say_status :gzip, "#{output_filename} (#{number_to_human_size((old_size - new_size).abs)} #{size_change_word})"
|
36
|
+
I18n.locale = old_locale
|
40
37
|
end
|
41
38
|
end
|
42
39
|
end
|
40
|
+
end
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
def gzip_file(path)
|
43
|
+
input_file = File.open(path, 'rb').read
|
44
|
+
output_filename = path + '.gz'
|
45
|
+
input_file_time = File.mtime(path)
|
48
46
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
# Check if the right file's already there
|
48
|
+
if File.exist?(output_filename) && File.mtime(output_filename) == input_file_time
|
49
|
+
return
|
50
|
+
end
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
52
|
+
File.open(output_filename, 'wb') do |f|
|
53
|
+
gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
|
54
|
+
gz.mtime = input_file_time.to_i
|
55
|
+
gz.write input_file
|
56
|
+
gz.close
|
57
|
+
end
|
60
58
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
59
|
+
# Make the file times match, both for Nginx's gzip_static extension
|
60
|
+
# and so we can ID existing files. Also, so even if the GZ files are
|
61
|
+
# wiped out by build --clean and recreated, we won't rsync them over
|
62
|
+
# again because they'll end up with the same mtime.
|
63
|
+
File.utime(File.atime(output_filename), input_file_time, output_filename)
|
66
64
|
|
67
|
-
|
68
|
-
|
65
|
+
old_size = File.size(path)
|
66
|
+
new_size = File.size(output_filename)
|
69
67
|
|
70
|
-
|
71
|
-
end
|
68
|
+
[output_filename, old_size, new_size]
|
72
69
|
end
|
73
70
|
end
|