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.
Files changed (33) hide show
  1. data/features/asset_hash.feature +24 -24
  2. data/features/ignore_already_minified.feature +39 -4
  3. data/features/markdown.feature +3 -12
  4. data/features/markdown_redcarpet.feature +37 -0
  5. data/features/minify_css.feature +72 -10
  6. data/features/minify_javascript.feature +108 -10
  7. data/features/slim.feature +15 -1
  8. data/fixtures/markdown-app/config.rb +0 -9
  9. data/lib/middleman-more.rb +1 -74
  10. data/lib/middleman-more/core_extensions/compass.rb +49 -48
  11. data/lib/middleman-more/core_extensions/sprockets.rb +10 -2
  12. data/lib/middleman-more/extensions/asset_hash.rb +9 -23
  13. data/lib/middleman-more/extensions/cache_buster.rb +51 -53
  14. data/lib/middleman-more/extensions/gzip.rb +14 -0
  15. data/lib/middleman-more/extensions/minify_css.rb +60 -70
  16. data/lib/middleman-more/extensions/minify_javascript.rb +70 -77
  17. data/lib/middleman-more/extensions/relative_assets.rb +47 -47
  18. data/lib/middleman-more/register_extensions.rb +82 -0
  19. data/lib/middleman-more/renderers/coffee_script.rb +22 -0
  20. data/lib/middleman-more/renderers/haml.rb +24 -19
  21. data/lib/middleman-more/renderers/liquid.rb +28 -23
  22. data/lib/middleman-more/renderers/markdown.rb +50 -42
  23. data/lib/middleman-more/renderers/sass.rb +70 -63
  24. data/lib/middleman-more/renderers/slim.rb +27 -19
  25. data/middleman-more.gemspec +6 -7
  26. metadata +34 -43
  27. data/fixtures/already-minified-app/config.rb +0 -2
  28. data/fixtures/already-minified-app/source/javascripts/test.min.js +0 -10
  29. data/fixtures/already-minified-app/source/stylesheets/test.min.css +0 -10
  30. data/fixtures/minify-css-app/config.rb +0 -0
  31. data/fixtures/passthrough-app/config.rb +0 -17
  32. data/fixtures/slim-app/config.rb +0 -1
  33. data/fixtures/slim-app/source/slim.html.slim +0 -7
@@ -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 the Server is running at "slim-app"
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>"
@@ -1,9 +0,0 @@
1
- set :markdown, :smartypants => true,
2
- :no_intra_emphasis => true,
3
- :tables => true,
4
- :fenced_code_blocks => true,
5
- :autolink => true,
6
- :strikethrough => true,
7
- :lax_html_blocks => true,
8
- :space_after_headers => true,
9
- :superscript => true
@@ -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
- # Forward the settings on config.rb and the result of registered extensions
2
- # to Compass
3
- module Middleman::CoreExtensions::Compass
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
- # Extension registered
6
- class << self
8
+ # Extension registered
9
+ class << self
7
10
 
8
- # Once registered
9
- def registered(app)
10
- require "compass"
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
- # Where to look for fonts
13
- app.set :fonts_dir, "fonts"
14
- app.define_hook :compass_config
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
- app.after_configuration do
18
- ::Compass.configuration do |config|
19
- config.project_path = source_dir
20
- config.environment = :development
21
- config.cache_path = File.join(root, ".sass-cache")
22
- config.sass_dir = css_dir
23
- config.css_dir = css_dir
24
- config.javascripts_dir = js_dir
25
- config.fonts_dir = fonts_dir
26
- config.images_dir = images_dir
27
- config.http_path = http_prefix
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
- config.asset_cache_buster :none
39
- config.relative_assets = false
40
- config.output_style = :nested
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
- if respond_to?(:asset_host) && asset_host.is_a?(Proc)
43
- config.asset_host(&asset_host)
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
- alias :included :registered
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(.ico .manifest .jpg .jpeg .png .gif .js .css)
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.ext
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::Extensions
2
+ module Middleman
3
+ module Extensions
3
4
 
4
- # The Cache Buster extension
5
- module CacheBuster
5
+ # The Cache Buster extension
6
+ module CacheBuster
6
7
 
7
- # Setup extension
8
- class << self
8
+ # Setup extension
9
+ class << self
9
10
 
10
- # Once registered
11
- def registered(app)
12
- # Add instance methods to context
13
- app.send :include, InstanceMethods
11
+ # Once registered
12
+ def registered(app)
13
+ # Add instance methods to context
14
+ app.send :include, InstanceMethods
14
15
 
15
- # After compass is setup, make it use the registered cache buster
16
- app.compass_config do |config|
17
- config.asset_cache_buster do |path, real_path|
18
- real_path = real_path.path if real_path.is_a? File
19
- real_path = real_path.gsub(File.join(root, build_dir), source)
20
- if File.readable?(real_path)
21
- File.mtime(real_path).strftime("%s")
22
- else
23
- $stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
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
- # Cache buster instance methods
32
- module InstanceMethods
32
+ # Cache buster instance methods
33
+ module InstanceMethods
33
34
 
34
- # asset_url override if we're using cache busting
35
- # @param [String] path
36
- # @param [String] prefix
37
- def asset_url(path, prefix="")
38
- http_path = super
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
- if http_path.include?("://") || !%w(.css .png .jpg .jpeg .svg .svgz .js .gif).include?(File.extname(http_path))
41
- http_path
42
- else
43
- begin
44
- prefix = images_dir if prefix == http_images_path
45
- rescue
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
- real_path_static = File.join(prefix, path)
48
+ real_path_static = File.join(prefix, path)
49
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 know when
59
- # it's updated, so generate fresh cache buster every time durin
60
- # developement
61
- http_path << "?" + Time.now.strftime("%s")
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
- http_path
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