middleman-more 3.0.0.alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. data/Rakefile +5 -0
  2. data/features/asset_host_compass.feature +7 -0
  3. data/features/cache_buster.feature +26 -0
  4. data/features/coffee-script.feature +17 -0
  5. data/features/content_for.feature +11 -0
  6. data/features/fonts.feature +13 -0
  7. data/features/ignore_already_minified.features +12 -0
  8. data/features/liquid.feature +11 -0
  9. data/features/markdown.feature +27 -0
  10. data/features/minify_css.feature +19 -0
  11. data/features/minify_javascript.feature +55 -0
  12. data/features/relative_assets.feature +50 -0
  13. data/features/sass_partials.feature +83 -0
  14. data/features/scss-support.feature +12 -0
  15. data/features/slim.feature +7 -0
  16. data/features/sprockets.feature +52 -0
  17. data/features/sprockets_gems.feature +10 -0
  18. data/features/support/env.rb +7 -0
  19. data/fixtures/already-minified-app/config.rb +2 -0
  20. data/fixtures/already-minified-app/source/javascripts/test.min.js +10 -0
  21. data/fixtures/already-minified-app/source/stylesheets/test.min.css +10 -0
  22. data/fixtures/asset-host-app/config.rb +6 -0
  23. data/fixtures/asset-host-app/source/.htaccess +1 -0
  24. data/fixtures/asset-host-app/source/images/blank.gif +0 -0
  25. data/fixtures/asset-host-app/source/stylesheets/asset_host.css.sass +3 -0
  26. data/fixtures/cache-buster-app/config.rb +0 -0
  27. data/fixtures/cache-buster-app/source/cache-buster.html.erb +2 -0
  28. data/fixtures/cache-buster-app/source/images/blank.gif +0 -0
  29. data/fixtures/cache-buster-app/source/stylesheets/relative_assets.css.sass +3 -0
  30. data/fixtures/cache-buster-app/source/stylesheets/site.css.sass +1 -0
  31. data/fixtures/coffeescript-app/config.rb +1 -0
  32. data/fixtures/coffeescript-app/source/inline-coffeescript.html.haml +3 -0
  33. data/fixtures/coffeescript-app/source/javascripts/broken-coffee.js.coffee +3 -0
  34. data/fixtures/coffeescript-app/source/javascripts/coffee_test.js.coffee +3 -0
  35. data/fixtures/content-for-app/config.rb +6 -0
  36. data/fixtures/content-for-app/source/content_for_haml.html.haml +4 -0
  37. data/fixtures/content-for-app/source/content_for_slim.html.slim +4 -0
  38. data/fixtures/content-for-app/source/layouts/content_for.erb +4 -0
  39. data/fixtures/fonts-app/config.rb +0 -0
  40. data/fixtures/fonts-app/source/fonts/StMarie-Thin.otf +0 -0
  41. data/fixtures/fonts-app/source/stylesheets/fonts.css.sass +3 -0
  42. data/fixtures/liquid-app/config.rb +0 -0
  43. data/fixtures/liquid-app/data/test.yml +4 -0
  44. data/fixtures/liquid-app/data/test2.json +4 -0
  45. data/fixtures/liquid-app/source/_liquid_partial.liquid +1 -0
  46. data/fixtures/liquid-app/source/data2.html.liquid +2 -0
  47. data/fixtures/liquid-app/source/liquid_master.html.liquid +1 -0
  48. data/fixtures/markdown-app/config.rb +9 -0
  49. data/fixtures/markdown-app/source/autolink.html.markdown +5 -0
  50. data/fixtures/markdown-app/source/fenced_code_blocks.html.markdown +7 -0
  51. data/fixtures/markdown-app/source/index.html.markdown +4 -0
  52. data/fixtures/markdown-app/source/no_intra_emphasis.html.markdown +5 -0
  53. data/fixtures/markdown-app/source/smarty_pants.html.markdown +5 -0
  54. data/fixtures/markdown-app/source/space_after_headers.html.markdown +5 -0
  55. data/fixtures/markdown-app/source/strikethrough.html.markdown +5 -0
  56. data/fixtures/markdown-app/source/superscript.html.markdown +5 -0
  57. data/fixtures/markdown-app/source/tables.html.markdown +8 -0
  58. data/fixtures/minify-css-app/config.rb +0 -0
  59. data/fixtures/minify-css-app/source/stylesheets/site.css.sass +1 -0
  60. data/fixtures/minify-js-app/config.rb +1 -0
  61. data/fixtures/minify-js-app/source/inline-coffeescript.html.haml +3 -0
  62. data/fixtures/minify-js-app/source/inline-js.html.haml +7 -0
  63. data/fixtures/minify-js-app/source/javascripts/coffee_test.js.coffee +3 -0
  64. data/fixtures/minify-js-app/source/javascripts/js_test.js +8 -0
  65. data/fixtures/passthrough-app/config.rb +17 -0
  66. data/fixtures/passthrough-app/source/.htaccess +1 -0
  67. data/fixtures/passthrough-app/source/inline-coffeescript.html.haml +3 -0
  68. data/fixtures/passthrough-app/source/inline-css.html.haml +4 -0
  69. data/fixtures/passthrough-app/source/inline-js.html.haml +7 -0
  70. data/fixtures/passthrough-app/source/javascripts/coffee_test.js.coffee +3 -0
  71. data/fixtures/passthrough-app/source/javascripts/js_test.js +8 -0
  72. data/fixtures/passthrough-app/source/stylesheets/site.css.sass +1 -0
  73. data/fixtures/preview-app/config.rb +0 -0
  74. data/fixtures/preview-app/source/content.html.erb +1 -0
  75. data/fixtures/preview-app/source/layout.erb +1 -0
  76. data/fixtures/preview-app/source/stylesheets/_partial.sass +2 -0
  77. data/fixtures/preview-app/source/stylesheets/_partial2.css.sass +2 -0
  78. data/fixtures/preview-app/source/stylesheets/main.css.sass +4 -0
  79. data/fixtures/preview-app/source/stylesheets/main2.css.sass +4 -0
  80. data/fixtures/preview-app/source/stylesheets/plain.css.sass +2 -0
  81. data/fixtures/relative-app/config.rb +0 -0
  82. data/fixtures/relative-app/source/images/blank.gif +0 -0
  83. data/fixtures/relative-app/source/stylesheets/relative_assets.css.sass +3 -0
  84. data/fixtures/relative-assets-app/config.rb +0 -0
  85. data/fixtures/relative-assets-app/source/images/blank.gif +0 -0
  86. data/fixtures/relative-assets-app/source/img/blank.gif +0 -0
  87. data/fixtures/relative-assets-app/source/relative_image.html.erb +1 -0
  88. data/fixtures/relative-assets-app/source/stylesheets/relative_assets.css.sass +3 -0
  89. data/fixtures/scss-app/config.rb +0 -0
  90. data/fixtures/scss-app/source/stylesheets/layout.css.sass +2 -0
  91. data/fixtures/scss-app/source/stylesheets/site_scss.css.scss +1 -0
  92. data/fixtures/slim-app/config.rb +1 -0
  93. data/fixtures/slim-app/source/slim.html.slim +7 -0
  94. data/fixtures/sprockets-app/config.rb +2 -0
  95. data/fixtures/sprockets-app/source/library/css/bootstrap_include.css.scss +1 -0
  96. data/fixtures/sprockets-app/source/library/css/plain.css +3 -0
  97. data/fixtures/sprockets-app/source/library/css/sprockets_base1.css.scss +1 -0
  98. data/fixtures/sprockets-app/source/library/css/sprockets_base2.css.scss +1 -0
  99. data/fixtures/sprockets-app/source/library/css/sprockets_sub.css.scss +1 -0
  100. data/fixtures/sprockets-app/source/library/js/jquery_include.js +1 -0
  101. data/fixtures/sprockets-app/source/library/js/plain.js +3 -0
  102. data/fixtures/sprockets-app/source/library/js/sprockets_base.js +5 -0
  103. data/fixtures/sprockets-app/source/library/js/sprockets_sub.js +3 -0
  104. data/fixtures/sprockets-app2/config.rb +0 -0
  105. data/fixtures/sprockets-app2/data/test.yml +4 -0
  106. data/fixtures/sprockets-app2/data/test2.json +4 -0
  107. data/fixtures/sprockets-app2/source/javascripts/multiple_engines.js.coffee.erb +1 -0
  108. data/fixtures/sprockets-app2/source/javascripts/sprockets_base.js +5 -0
  109. data/fixtures/sprockets-app2/source/javascripts/sprockets_sub.js +3 -0
  110. data/fixtures/sprockets-app2/source/stylesheets/sprockets_base1.css.scss +1 -0
  111. data/fixtures/sprockets-app2/source/stylesheets/sprockets_base2.css.scss +1 -0
  112. data/fixtures/sprockets-app2/source/stylesheets/sprockets_sub.css.scss +1 -0
  113. data/lib/middleman-more.rb +64 -0
  114. data/lib/middleman-more/core_extensions/compass.rb +75 -0
  115. data/lib/middleman-more/core_extensions/sprockets.rb +142 -0
  116. data/lib/middleman-more/extensions/cache_buster.rb +59 -0
  117. data/lib/middleman-more/extensions/minify_css.rb +17 -0
  118. data/lib/middleman-more/extensions/minify_css/cssmin.rb +55 -0
  119. data/lib/middleman-more/extensions/minify_javascript.rb +56 -0
  120. data/lib/middleman-more/extensions/relative_assets.rb +46 -0
  121. data/lib/middleman-more/renderers/haml.rb +13 -0
  122. data/lib/middleman-more/renderers/liquid.rb +21 -0
  123. data/lib/middleman-more/renderers/markdown.rb +28 -0
  124. data/lib/middleman-more/renderers/sass.rb +53 -0
  125. data/lib/middleman-more/renderers/slim.rb +15 -0
  126. data/middleman-more.gemspec +32 -0
  127. metadata +468 -0
@@ -0,0 +1 @@
1
+ hello { world: "hi"; }
@@ -0,0 +1 @@
1
+ //= require "jquery"
@@ -0,0 +1,3 @@
1
+ function hellowWorld() {
2
+
3
+ }
@@ -0,0 +1,5 @@
1
+ //= require "sprockets_sub"
2
+
3
+ function base() {
4
+
5
+ }
@@ -0,0 +1,3 @@
1
+ function sprockets_sub_function() {
2
+
3
+ }
File without changes
@@ -0,0 +1,4 @@
1
+ -
2
+ title: "One"
3
+ -
4
+ title: "Two"
@@ -0,0 +1,4 @@
1
+ [
2
+ { "title": "One" },
3
+ { "title": "Two" }
4
+ ]
@@ -0,0 +1 @@
1
+ alert "Hello <%= data.test[0].title %>"
@@ -0,0 +1,5 @@
1
+ //= require "sprockets_sub"
2
+
3
+ function base() {
4
+
5
+ }
@@ -0,0 +1,3 @@
1
+ function sprockets_sub_function() {
2
+
3
+ }
@@ -0,0 +1 @@
1
+ //= require "sprockets_sub"
@@ -0,0 +1 @@
1
+ @import "sprockets_sub";
@@ -0,0 +1 @@
1
+ hello { world: "hi"; }
@@ -0,0 +1,64 @@
1
+ # Setup our load paths
2
+ libdir = File.expand_path(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
4
+
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
+ module CoreExtensions
20
+ # Compass framework for Sass
21
+ autoload :Compass, "middleman-more/core_extensions/compass"
22
+
23
+ # Sprockets 2
24
+ autoload :Sprockets, "middleman-more/core_extensions/sprockets"
25
+ end
26
+
27
+ module Extensions
28
+ # RelativeAssets allow any asset path in dynamic templates to be either
29
+ # relative to the root of the project or use an absolute URL.
30
+ autoload :RelativeAssets, "middleman-more/extensions/relative_assets"
31
+
32
+ # CacheBuster adds a query string to assets in dynamic templates to avoid
33
+ # browser caches failing to update to your new content.
34
+ autoload :CacheBuster, "middleman-more/extensions/cache_buster"
35
+
36
+ # MinifyCss uses the YUI compressor to shrink CSS files
37
+ autoload :MinifyCss, "middleman-more/extensions/minify_css"
38
+
39
+ # MinifyJavascript uses the YUI compressor to shrink JS files
40
+ autoload :MinifyJavascript, "middleman-more/extensions/minify_javascript"
41
+ end
42
+
43
+ require "coffee_script"
44
+ Base.register Middleman::Renderers::Haml
45
+ Base.register Middleman::Renderers::Sass
46
+ Base.register Middleman::Renderers::Markdown
47
+ Base.register Middleman::Renderers::Liquid
48
+ Base.register Middleman::Renderers::Slim
49
+
50
+ # Compass framework
51
+ Base.register Middleman::CoreExtensions::Compass
52
+
53
+ # Sprockets asset handling
54
+ Base.register Middleman::CoreExtensions::Sprockets
55
+
56
+ Extensions.register(:cache_buster) {
57
+ ::Middleman::Extensions::CacheBuster }
58
+ Extensions.register(:minify_css) {
59
+ ::Middleman::Extensions::MinifyCss }
60
+ Extensions.register(:minify_javascript) {
61
+ ::Middleman::Extensions::MinifyJavascript }
62
+ Extensions.register(:relative_assets) {
63
+ ::Middleman::Extensions::RelativeAssets }
64
+ end
@@ -0,0 +1,75 @@
1
+ # Forward the settings on config.rb and the result of registered extensions
2
+ # to Compass
3
+ module Middleman::CoreExtensions::Compass
4
+
5
+ # Extension registered
6
+ class << self
7
+ # @private
8
+ def registered(app)
9
+ require "compass"
10
+
11
+ # Where to look for fonts
12
+ app.set :fonts_dir, "fonts"
13
+ app.define_hook :compass_config
14
+ app.define_hook :after_compass_config
15
+
16
+ app.after_configuration do
17
+ ::Compass.configuration do |config|
18
+ config.project_path = root
19
+ config.environment = :development
20
+ config.cache_path = File.join(root, ".sass-cache")
21
+ config.sass_dir = File.join(source, css_dir)
22
+ config.css_dir = File.join(source, css_dir)
23
+ config.javascripts_dir = File.join(source, js_dir)
24
+ config.fonts_dir = File.join(source, fonts_dir)
25
+ config.images_dir = File.join(source, images_dir)
26
+
27
+ config.http_images_path = if respond_to? :http_images_path
28
+ http_images_path
29
+ else
30
+ File.join(http_prefix, images_dir)
31
+ end
32
+
33
+ config.http_stylesheets_path = if respond_to? :http_css_path
34
+ http_css_path
35
+ else
36
+ File.join(http_prefix, css_dir)
37
+ end
38
+
39
+ config.http_javascripts_path = if respond_to? :http_js_path
40
+ http_js_path
41
+ else
42
+ File.join(http_prefix, js_dir)
43
+ end
44
+
45
+ config.http_fonts_path = if respond_to? :http_fonts_path
46
+ http_fonts_path
47
+ else
48
+ File.join(http_prefix, fonts_dir)
49
+ end
50
+
51
+ config.asset_cache_buster :none
52
+ config.output_style = :nested
53
+
54
+ if respond_to?(:asset_host) && asset_host.is_a?(Proc)
55
+ config.asset_host(&asset_host)
56
+ end
57
+ end
58
+
59
+ # Change paths when in build mode. Required for relative paths
60
+ configure :build do
61
+ ::Compass.configuration do |config|
62
+ config.environment = :production
63
+ config.css_dir = File.join(build_dir, css_dir)
64
+ config.images_dir = File.join(build_dir, images_dir)
65
+ config.fonts_dir = File.join(build_dir, fonts_dir)
66
+ end
67
+ end
68
+
69
+ run_hook :compass_config, ::Compass.configuration
70
+ run_hook :after_compass_config
71
+ end
72
+ end
73
+ alias :included :registered
74
+ end
75
+ end
@@ -0,0 +1,142 @@
1
+ require 'pathname'
2
+ require "sprockets"
3
+
4
+ module Middleman::CoreExtensions::Sprockets
5
+ class << self
6
+ def registered(app)
7
+ app.set :js_compressor, false
8
+ app.set :css_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.ready do
23
+ js_env = Middleman::CoreExtensions::Sprockets::JavascriptEnvironment.new(self)
24
+
25
+ vendor_dir = File.join("vendor", "assets", "javascripts")
26
+ gems_with_js = ::Middleman.rubygems_latest_specs.select do |spec|
27
+ ::Middleman.spec_has_file?(spec, vendor_dir)
28
+ end.each do |spec|
29
+ js_env.append_path File.join(spec.full_gem_path, vendor_dir)
30
+ end
31
+
32
+ app_dir = File.join("app", "assets", "javascripts")
33
+ gems_with_js = ::Middleman.rubygems_latest_specs.select do |spec|
34
+ ::Middleman.spec_has_file?(spec, app_dir)
35
+ end.each do |spec|
36
+ js_env.append_path File.join(spec.full_gem_path, app_dir)
37
+ end
38
+
39
+ # add paths to js_env (vendor/assets/javascripts)
40
+ map "/#{js_dir}" do
41
+ run js_env
42
+ end
43
+
44
+ sass.each { |k, v| ::Sprockets::Sass.options[k] = v }
45
+ css_env = Middleman::CoreExtensions::Sprockets::StylesheetEnvironment.new(self)
46
+
47
+ vendor_dir = File.join("vendor", "assets", "stylesheets")
48
+ gems_with_css = ::Middleman.rubygems_latest_specs.select do |spec|
49
+ ::Middleman.spec_has_file?(spec, vendor_dir)
50
+ end.each do |spec|
51
+ css_env.append_path File.join(spec.full_gem_path, vendor_dir)
52
+ end
53
+
54
+ app_dir = File.join("app", "assets", "stylesheets")
55
+ gems_with_css = ::Middleman.rubygems_latest_specs.select do |spec|
56
+ ::Middleman.spec_has_file?(spec, app_dir)
57
+ end.each do |spec|
58
+ css_env.append_path File.join(spec.full_gem_path, app_dir)
59
+ end
60
+
61
+ map("/#{css_dir}") do
62
+ run css_env
63
+ end
64
+ end
65
+ end
66
+ alias :included :registered
67
+ end
68
+
69
+ class MiddlemanEnvironment < ::Sprockets::Environment
70
+ def initialize(app)
71
+ @app = app
72
+ super app.source_dir
73
+
74
+ # Make the app context available to Sprockets
75
+ context_class.send(:define_method, :app) { app }
76
+ context_class.class_eval do
77
+ def method_missing(name)
78
+ if app.respond_to?(name)
79
+ app.send(name)
80
+ else
81
+ super
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ def find_asset(path, options = {})
88
+ expire_index! if @app.development?
89
+ super
90
+ end
91
+ end
92
+
93
+ class JavascriptEnvironment < MiddlemanEnvironment
94
+ def initialize(app)
95
+ super
96
+
97
+ expire_index!
98
+
99
+ unregister_bundle_processor 'application/javascript', :js_compressor
100
+ register_bundle_processor 'application/javascript', :js_compressor do |context, data|
101
+ if context.pathname.to_s =~ /\.min\./
102
+ data
103
+ else
104
+ app.js_compressor.compress(data)
105
+ end
106
+ end if app.js_compressor
107
+
108
+ # configure search paths
109
+ append_path app.js_dir
110
+ end
111
+
112
+ def javascript_exception_response(exception)
113
+ expire_index!
114
+ super(exception)
115
+ end
116
+ end
117
+
118
+ class StylesheetEnvironment < MiddlemanEnvironment
119
+ def initialize(app)
120
+ super
121
+
122
+ expire_index!
123
+
124
+ unregister_bundle_processor 'text/css', :css_compressor
125
+ register_bundle_processor 'text/css', :css_compressor do |context, data|
126
+ if context.pathname.to_s =~ /\.min\./
127
+ data
128
+ else
129
+ app.css_compressor.compress(data)
130
+ end
131
+ end if app.css_compressor
132
+
133
+ # configure search paths
134
+ append_path app.css_dir
135
+ end
136
+
137
+ def css_exception_response(exception)
138
+ expire_index!
139
+ super(exception)
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,59 @@
1
+ module Middleman::Extensions
2
+ module CacheBuster
3
+ class << self
4
+ def registered(app)
5
+ app.send :include, InstanceMethods
6
+
7
+ app.compass_config do |config|
8
+ config.asset_cache_buster do |path, real_path|
9
+ real_path = real_path.path if real_path.is_a? File
10
+ real_path = real_path.gsub(File.join(root, build_dir), source)
11
+ if File.readable?(real_path)
12
+ File.mtime(real_path).strftime("%s")
13
+ else
14
+ $stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ alias :included :registered
20
+ end
21
+
22
+ module InstanceMethods
23
+ def asset_url(path, prefix="")
24
+ http_path = super
25
+
26
+ if http_path.include?("://") || !%w(.css .png .jpg .jpeg .svg .svgz .js .gif).include?(File.extname(http_path))
27
+ http_path
28
+ else
29
+ begin
30
+ prefix = images_dir if prefix == http_images_path
31
+ rescue
32
+ end
33
+
34
+ real_path_static = File.join(prefix, path)
35
+
36
+ if build?
37
+ real_path_dynamic = File.join(build_dir, prefix, path)
38
+ real_path_dynamic = File.expand_path(real_path_dynamic, root)
39
+ http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
40
+ elsif sitemap.exists?(real_path_static)
41
+ page = sitemap.page(real_path_static)
42
+ if !page.template?
43
+ http_path << "?" + File.mtime(result[0]).strftime("%s")
44
+ else
45
+ # It's a template, possible with partials. We can't really know when
46
+ # it's updated, so generate fresh cache buster every time durin
47
+ # developement
48
+ http_path << "?" + Time.now.strftime("%s")
49
+ end
50
+ end
51
+
52
+ http_path
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ register :cache_buster, CacheBuster
59
+ end
@@ -0,0 +1,17 @@
1
+ module Middleman::Extensions
2
+ module MinifyCss
3
+ class << self
4
+ def registered(app)
5
+ app.after_configuration do
6
+ if !css_compressor
7
+ require "middleman-more/extensions/minify_css/cssmin"
8
+ set :css_compressor, ::CSSMin
9
+ end
10
+ end
11
+ end
12
+ alias :included :registered
13
+ end
14
+ end
15
+
16
+ register :minify_css, MinifyCss
17
+ end
@@ -0,0 +1,55 @@
1
+ #--
2
+ # Copyright (c) 2008 Ryan Grove <ryan@wonko.com>
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of this project nor the names of its contributors may be
14
+ # used to endorse or promote products derived from this software without
15
+ # specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #++
28
+
29
+ module CSSMin
30
+ def self.compress(input)
31
+ css = input.is_a?(IO) ? input.read : input.dup.to_s
32
+ css.gsub!(/\/\*[\s\S]*?\*\//, '')
33
+ css.gsub!(/\s+/, ' ')
34
+ css.gsub!(/"\\"\}\\""/, '___BMH___')
35
+ css.gsub!(/(?:^|\})[^\{:]+\s+:+[^\{]*\{/) do |match|
36
+ match.gsub(':', '___PSEUDOCLASSCOLON___')
37
+ end
38
+ css.gsub!(/\s+([!\{\};:>+\(\)\],])/, '\1')
39
+ css.gsub!('___PSEUDOCLASSCOLON___', ':')
40
+ css.gsub!(/([!\{\}:;>+\(\[,])\s+/, '\1')
41
+ css.gsub!(/([^;\}])\}/, '\1;}')
42
+ css.gsub!(/([\s:])([+-]?0)(?:%|em|ex|px|in|cm|mm|pt|pc)/i, '\1\2')
43
+ css.gsub!(/:(?:0 )+0;/, ':0;')
44
+ css.gsub!('background-position:0;', 'background-position:0 0;')
45
+ css.gsub!(/(:|\s)0+\.(\d+)/, '\1.\2')
46
+ css.gsub!(/rgb\s*\(\s*([0-9,\s]+)\s*\)/) do |match|
47
+ '#' << $1.scan(/\d+/).map{|n| n.to_i.to_s(16).rjust(2, '0') }.join
48
+ end
49
+ css.gsub!(/([^"'=\s])\s*#([0-9a-f])\2([0-9a-f])\3([0-9a-f])\4/i, '\1 #\2\3\4')
50
+ css.gsub!(/[^\}]+\{;\}\n/, '')
51
+ css.gsub!('___BMH___', '"\"}\""')
52
+ css.gsub!(/;;+/, ';')
53
+ css.strip
54
+ end
55
+ end