middleman-more 3.0.0.beta.2 → 3.0.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- data/features/asset_hash.feature +24 -24
- data/features/ignore_already_minified.feature +39 -4
- data/features/markdown.feature +3 -12
- data/features/markdown_redcarpet.feature +37 -0
- data/features/minify_css.feature +72 -10
- data/features/minify_javascript.feature +108 -10
- data/features/slim.feature +15 -1
- data/fixtures/markdown-app/config.rb +0 -9
- data/lib/middleman-more.rb +1 -74
- data/lib/middleman-more/core_extensions/compass.rb +49 -48
- data/lib/middleman-more/core_extensions/sprockets.rb +10 -2
- data/lib/middleman-more/extensions/asset_hash.rb +9 -23
- data/lib/middleman-more/extensions/cache_buster.rb +51 -53
- data/lib/middleman-more/extensions/gzip.rb +14 -0
- data/lib/middleman-more/extensions/minify_css.rb +60 -70
- data/lib/middleman-more/extensions/minify_javascript.rb +70 -77
- data/lib/middleman-more/extensions/relative_assets.rb +47 -47
- data/lib/middleman-more/register_extensions.rb +82 -0
- data/lib/middleman-more/renderers/coffee_script.rb +22 -0
- data/lib/middleman-more/renderers/haml.rb +24 -19
- data/lib/middleman-more/renderers/liquid.rb +28 -23
- data/lib/middleman-more/renderers/markdown.rb +50 -42
- data/lib/middleman-more/renderers/sass.rb +70 -63
- data/lib/middleman-more/renderers/slim.rb +27 -19
- data/middleman-more.gemspec +6 -7
- metadata +34 -43
- data/fixtures/already-minified-app/config.rb +0 -2
- data/fixtures/already-minified-app/source/javascripts/test.min.js +0 -10
- data/fixtures/already-minified-app/source/stylesheets/test.min.css +0 -10
- data/fixtures/minify-css-app/config.rb +0 -0
- data/fixtures/passthrough-app/config.rb +0 -17
- data/fixtures/slim-app/config.rb +0 -1
- data/fixtures/slim-app/source/slim.html.slim +0 -7
data/features/slim.feature
CHANGED
@@ -2,6 +2,20 @@ Feature: Support slim templating language
|
|
2
2
|
In order to offer an alternative to Haml
|
3
3
|
|
4
4
|
Scenario: Rendering Slim
|
5
|
-
Given
|
5
|
+
Given an empty app
|
6
|
+
And a file named "config.rb" with:
|
7
|
+
"""
|
8
|
+
"""
|
9
|
+
And a file named "source/slim.html.slim" with:
|
10
|
+
"""
|
11
|
+
doctype 5
|
12
|
+
html lang='en'
|
13
|
+
head
|
14
|
+
meta charset="utf-8"
|
15
|
+
|
16
|
+
body
|
17
|
+
h1 Welcome to Slim
|
18
|
+
"""
|
19
|
+
And the Server is running at "empty_app"
|
6
20
|
When I go to "/slim.html"
|
7
21
|
Then I should see "<h1>Welcome to Slim</h1>"
|
data/lib/middleman-more.rb
CHANGED
@@ -3,77 +3,4 @@ libdir = File.expand_path(File.dirname(__FILE__))
|
|
3
3
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
4
4
|
|
5
5
|
require "middleman-core"
|
6
|
-
|
7
|
-
# Top-level Middleman object
|
8
|
-
module Middleman
|
9
|
-
|
10
|
-
# Custom Renderers
|
11
|
-
module Renderers
|
12
|
-
autoload :Haml, "middleman-more/renderers/haml"
|
13
|
-
autoload :Sass, "middleman-more/renderers/sass"
|
14
|
-
autoload :Markdown, "middleman-more/renderers/markdown"
|
15
|
-
autoload :Liquid, "middleman-more/renderers/liquid"
|
16
|
-
autoload :Slim, "middleman-more/renderers/slim"
|
17
|
-
end
|
18
|
-
|
19
|
-
# Core (automatic) extensions
|
20
|
-
module CoreExtensions
|
21
|
-
# Compass framework for Sass
|
22
|
-
autoload :Compass, "middleman-more/core_extensions/compass"
|
23
|
-
|
24
|
-
# Sprockets 2
|
25
|
-
autoload :Sprockets, "middleman-more/core_extensions/sprockets"
|
26
|
-
end
|
27
|
-
|
28
|
-
# User-activatable extensions
|
29
|
-
module Extensions
|
30
|
-
# RelativeAssets allow any asset path in dynamic templates to be either
|
31
|
-
# relative to the root of the project or use an absolute URL.
|
32
|
-
autoload :RelativeAssets, "middleman-more/extensions/relative_assets"
|
33
|
-
|
34
|
-
# CacheBuster adds a query string to assets in dynamic templates to avoid
|
35
|
-
# browser caches failing to update to your new content.
|
36
|
-
autoload :CacheBuster, "middleman-more/extensions/cache_buster"
|
37
|
-
|
38
|
-
# AssetHash appends a hash of the file contents to the assets filename
|
39
|
-
# to avoid browser caches failing to update to your new content.
|
40
|
-
autoload :AssetHash, "middleman-more/extensions/asset_hash"
|
41
|
-
|
42
|
-
# MinifyCss uses the YUI compressor to shrink CSS files
|
43
|
-
autoload :MinifyCss, "middleman-more/extensions/minify_css"
|
44
|
-
|
45
|
-
# MinifyJavascript uses the YUI compressor to shrink JS files
|
46
|
-
autoload :MinifyJavascript, "middleman-more/extensions/minify_javascript"
|
47
|
-
|
48
|
-
# GZIP assets and pages during build
|
49
|
-
autoload :Gzip, "middleman-more/extensions/gzip"
|
50
|
-
end
|
51
|
-
|
52
|
-
# Setup renderers
|
53
|
-
require "coffee_script"
|
54
|
-
Application.register Middleman::Renderers::Haml
|
55
|
-
Application.register Middleman::Renderers::Sass
|
56
|
-
Application.register Middleman::Renderers::Markdown
|
57
|
-
Application.register Middleman::Renderers::Liquid
|
58
|
-
Application.register Middleman::Renderers::Slim
|
59
|
-
|
60
|
-
# Compass framework
|
61
|
-
Application.register Middleman::CoreExtensions::Compass
|
62
|
-
|
63
|
-
# Sprockets asset handling
|
64
|
-
Application.register Middleman::CoreExtensions::Sprockets
|
65
|
-
|
66
|
-
# Register the optional extensions
|
67
|
-
Extensions.register(:cache_buster) {
|
68
|
-
::Middleman::Extensions::CacheBuster }
|
69
|
-
Extensions.register(:minify_css) {
|
70
|
-
::Middleman::Extensions::MinifyCss }
|
71
|
-
Extensions.register(:minify_javascript) {
|
72
|
-
::Middleman::Extensions::MinifyJavascript }
|
73
|
-
Extensions.register(:relative_assets) {
|
74
|
-
::Middleman::Extensions::RelativeAssets }
|
75
|
-
Extensions.register(:gzip) {
|
76
|
-
::Middleman::Extensions::Gzip }
|
77
|
-
Extensions.register(:asset_hash) {
|
78
|
-
::Middleman::Extensions::AssetHash }
|
79
|
-
end
|
6
|
+
require "middleman-more/register_extensions"
|
@@ -1,60 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Middleman
|
2
|
+
module CoreExtensions
|
3
|
+
|
4
|
+
# Forward the settings on config.rb and the result of registered
|
5
|
+
# extensions to Compass
|
6
|
+
module Compass
|
4
7
|
|
5
|
-
|
6
|
-
|
8
|
+
# Extension registered
|
9
|
+
class << self
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
+
# Once registered
|
12
|
+
def registered(app)
|
13
|
+
# Require the library
|
14
|
+
require "compass"
|
15
|
+
|
16
|
+
# Where to look for fonts
|
17
|
+
app.set :fonts_dir, "fonts"
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
app.define_hook :after_compass_config
|
19
|
+
# Hooks to manually update the compass config after we're
|
20
|
+
# done with it
|
21
|
+
app.define_hook :compass_config
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# Correctly support HTTP paths with generated sprites
|
30
|
-
# if config.respond_to? :http_generated_images_path
|
31
|
-
# config.http_generated_images_path = if app.respond_to? :http_generated_images_path
|
32
|
-
# app.http_generated_images_path
|
33
|
-
# else
|
34
|
-
# File.join(app.http_prefix || "/", app.images_dir)
|
35
|
-
# end
|
36
|
-
# end
|
23
|
+
app.after_configuration do
|
24
|
+
::Compass.configuration do |config|
|
25
|
+
config.project_path = source_dir
|
26
|
+
config.environment = :development
|
27
|
+
config.cache_path = File.join(root, ".sass-cache")
|
28
|
+
config.sass_dir = css_dir
|
29
|
+
config.css_dir = css_dir
|
30
|
+
config.javascripts_dir = js_dir
|
31
|
+
config.fonts_dir = fonts_dir
|
32
|
+
config.images_dir = images_dir
|
33
|
+
config.http_path = http_prefix
|
37
34
|
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
# Disable this initially, the cache_buster extension will
|
36
|
+
# re-enable it if requested.
|
37
|
+
config.asset_cache_buster :none
|
38
|
+
|
39
|
+
# Disable this initially, the relative_assets extension will
|
40
|
+
# re-enable it if requested.
|
41
|
+
config.relative_assets = false
|
42
|
+
|
43
|
+
# Default output style
|
44
|
+
config.output_style = :nested
|
41
45
|
|
42
|
-
|
43
|
-
|
46
|
+
if respond_to?(:asset_host) && asset_host.is_a?(Proc)
|
47
|
+
config.asset_host(&asset_host)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Call hook
|
52
|
+
run_hook :compass_config, ::Compass.configuration
|
44
53
|
end
|
45
54
|
end
|
46
|
-
|
47
|
-
# if build?
|
48
|
-
# ::Compass.configuration do |config|
|
49
|
-
# config.environment = :production
|
50
|
-
# config.project_path = File.join(root, build_dir)
|
51
|
-
# end
|
52
|
-
# end
|
53
|
-
|
54
|
-
run_hook :compass_config, ::Compass.configuration
|
55
|
-
run_hook :after_compass_config
|
55
|
+
alias :included :registered
|
56
56
|
end
|
57
|
+
|
57
58
|
end
|
58
|
-
|
59
|
+
|
59
60
|
end
|
60
61
|
end
|
@@ -52,8 +52,6 @@ module Middleman::CoreExtensions::Sprockets
|
|
52
52
|
@app = app
|
53
53
|
super app.source_dir
|
54
54
|
|
55
|
-
digest = Digest::SHA1
|
56
|
-
|
57
55
|
# Make the app context available to Sprockets
|
58
56
|
context_class.send(:define_method, :app) { app }
|
59
57
|
context_class.class_eval do
|
@@ -75,6 +73,16 @@ module Middleman::CoreExtensions::Sprockets
|
|
75
73
|
append_path app.css_dir
|
76
74
|
end
|
77
75
|
|
76
|
+
# Override Sprockets' default digest function to *not*
|
77
|
+
# change depending on the exact Sprockets version. It still takes
|
78
|
+
# into account "version" which is a user-suppliable version
|
79
|
+
# number that can be used to force assets to have a new
|
80
|
+
# hash.
|
81
|
+
def digest
|
82
|
+
@digest ||= Digest::SHA1.new.update(version.to_s)
|
83
|
+
@digest.dup
|
84
|
+
end
|
85
|
+
|
78
86
|
# During development, don't use the asset cache
|
79
87
|
def find_asset(path, options = {})
|
80
88
|
expire_index! if @app.development?
|
@@ -3,14 +3,16 @@ module Middleman::Extensions
|
|
3
3
|
module AssetHash
|
4
4
|
class << self
|
5
5
|
def registered(app, options)
|
6
|
-
exts = options[:exts] || %w(.
|
6
|
+
exts = options[:exts] || %w(.jpg .jpeg .png .gif .js .css)
|
7
|
+
|
8
|
+
# Allow specifying regexes to ignore, plus always ignore apple touch icons
|
9
|
+
ignore = Array(options[:ignore]) << /^apple-touch-icon/
|
7
10
|
|
8
11
|
app.ready do
|
9
12
|
sitemap.register_resource_list_manipulator(
|
10
13
|
:asset_hash,
|
11
|
-
AssetHashManager.new(self, exts)
|
14
|
+
AssetHashManager.new(self, exts, ignore)
|
12
15
|
)
|
13
|
-
|
14
16
|
use Middleware, :exts => exts, :middleman_app => self
|
15
17
|
end
|
16
18
|
end
|
@@ -18,16 +20,17 @@ module Middleman::Extensions
|
|
18
20
|
end
|
19
21
|
|
20
22
|
class AssetHashManager
|
21
|
-
def initialize(app, exts)
|
23
|
+
def initialize(app, exts, ignore)
|
22
24
|
@app = app
|
23
25
|
@exts = exts
|
26
|
+
@ignore = ignore
|
24
27
|
end
|
25
28
|
|
26
29
|
# Update the main sitemap resource list
|
27
30
|
# @return [void]
|
28
31
|
def manipulate_resource_list(resources)
|
29
32
|
resources.each do |resource|
|
30
|
-
if @exts.include? resource.
|
33
|
+
if @exts.include?(resource.ext) && @ignore.none? {|ignore| resource.path =~ ignore }
|
31
34
|
# figure out the path Sprockets would use for this asset
|
32
35
|
if resource.ext == '.js'
|
33
36
|
sprockets_path = resource.path.sub(@app.js_dir,'').sub(/^\//,'')
|
@@ -69,7 +72,7 @@ module Middleman::Extensions
|
|
69
72
|
dirpath = Pathname.new(File.dirname(path))
|
70
73
|
|
71
74
|
if path =~ /(^\/$)|(\.(htm|html|php|css|js)$)/
|
72
|
-
body = extract_response_text(response)
|
75
|
+
body = ::Middleman::Util.extract_response_text(response)
|
73
76
|
|
74
77
|
if body
|
75
78
|
# TODO: This regex will change some paths in plan HTML (not in a tag) - is that OK?
|
@@ -94,23 +97,6 @@ module Middleman::Extensions
|
|
94
97
|
end
|
95
98
|
[status, headers, response]
|
96
99
|
end
|
97
|
-
|
98
|
-
private
|
99
|
-
|
100
|
-
def extract_response_text(response)
|
101
|
-
case(response)
|
102
|
-
when String
|
103
|
-
response
|
104
|
-
when Array
|
105
|
-
response.join
|
106
|
-
when Rack::Response
|
107
|
-
response.body.join
|
108
|
-
when Rack::File
|
109
|
-
File.read(response.path)
|
110
|
-
else
|
111
|
-
response.to_s
|
112
|
-
end
|
113
|
-
end
|
114
100
|
end
|
115
101
|
end
|
116
102
|
|
@@ -1,73 +1,71 @@
|
|
1
1
|
# Extension namespace
|
2
|
-
module Middleman
|
2
|
+
module Middleman
|
3
|
+
module Extensions
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
# The Cache Buster extension
|
6
|
+
module CacheBuster
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
# Setup extension
|
9
|
+
class << self
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
# Once registered
|
12
|
+
def registered(app)
|
13
|
+
# Add instance methods to context
|
14
|
+
app.send :include, InstanceMethods
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
+
$stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
29
|
+
alias :included :registered
|
27
30
|
end
|
28
|
-
alias :included :registered
|
29
|
-
end
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
# Cache buster instance methods
|
33
|
+
module InstanceMethods
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
# asset_url override if we're using cache busting
|
36
|
+
# @param [String] path
|
37
|
+
# @param [String] prefix
|
38
|
+
def asset_url(path, prefix="")
|
39
|
+
http_path = super
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
41
|
+
if http_path.include?("://") || !%w(.css .png .jpg .jpeg .svg .svgz .js .gif).include?(File.extname(http_path))
|
42
|
+
http_path
|
43
|
+
else
|
44
|
+
if respond_to?(:http_images_path) && prefix == http_images_path
|
45
|
+
prefix = images_dir
|
46
|
+
end
|
47
47
|
|
48
|
-
|
48
|
+
real_path_static = File.join(prefix, path)
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
62
63
|
end
|
63
|
-
end
|
64
64
|
|
65
|
-
|
65
|
+
http_path
|
66
|
+
end
|
66
67
|
end
|
67
68
|
end
|
68
69
|
end
|
69
70
|
end
|
70
|
-
|
71
|
-
# Register the extension
|
72
|
-
# register :cache_buster, CacheBuster
|
73
|
-
end
|
71
|
+
end
|
@@ -39,12 +39,26 @@ module Middleman::Extensions
|
|
39
39
|
def gzip_file(path, builder)
|
40
40
|
input_file = File.open(path, 'r').read
|
41
41
|
output_filename = path + '.gz'
|
42
|
+
input_file_time = File.mtime(path)
|
43
|
+
|
44
|
+
# Check if the right file's already there
|
45
|
+
if File.exist?(output_filename) && File.mtime(output_filename) == input_file_time
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
42
49
|
File.open(output_filename, 'w') do |f|
|
43
50
|
gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
|
51
|
+
gz.mtime = input_file_time.to_i
|
44
52
|
gz.write input_file
|
45
53
|
gz.close
|
46
54
|
end
|
47
55
|
|
56
|
+
# Make the file times match, both for Nginx's gzip_static extension
|
57
|
+
# and so we can ID existing files. Also, so even if the GZ files are
|
58
|
+
# wiped out by build --clean and recreated, we won't rsync them over
|
59
|
+
# again because they'll end up with the same mtime.
|
60
|
+
File.utime(File.atime(output_filename), input_file_time, output_filename)
|
61
|
+
|
48
62
|
old_size = File.size(path)
|
49
63
|
new_size = File.size(output_filename)
|
50
64
|
|