merged cont.
[opensuse:yast-rest-service.git] / webyast / lib / cssmin.rb
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 # = CSSMin
30 #
31 # Minifies CSS using a fast, safe routine adapted from Julien Lecomte's YUI
32 # Compressor, which was in turn adapted from Isaac Schlueter's cssmin PHP
33 # script.
34 #
35 # Author::    Ryan Grove (mailto:ryan@wonko.com)
36 # Version::   1.0.2 (2008-08-23)
37 # Copyright:: Copyright (c) 2008 Ryan Grove. All rights reserved.
38 # License::   New BSD License (http://opensource.org/licenses/bsd-license.php)
39 # Website::   http://github.com/rgrove/cssmin/
40 #
41 # == Example
42 #
43 #   require 'rubygems'
44 #   require 'cssmin'
45 #
46 #   File.open('example.css', 'r') {|file| puts CSSMin.minify(file) }
47 #
48 module CSSMin
49
50   # Reads CSS from +input+ (which can be a String or an IO object) and
51   # returns a String containing minified CSS.
52   def self.minify(input)
53     css = input.is_a?(IO) ? input.read : input.dup.to_s
54
55     # Remove comments.
56     css.gsub!(/\/\*[\s\S]*?\*\//, '')
57
58     # Compress all runs of whitespace to a single space to make things easier
59     # to work with.
60     css.gsub!(/\s+/, ' ')
61
62     # Replace box model hacks with placeholders.
63     css.gsub!(/"\\"\}\\""/, '___BMH___')
64
65     # Remove unnecessary spaces, but be careful not to turn "p :link {...}"
66     # into "p:link{...}".
67     css.gsub!(/(?:^|\})[^\{:]+\s+:+[^\{]*\{/) do |match|
68       match.gsub(':', '___PSEUDOCLASSCOLON___')
69     end
70     css.gsub!(/\s+([!\{\};:>+\(\)\],])/, '\1')
71     css.gsub!('___PSEUDOCLASSCOLON___', ':')
72     css.gsub!(/([!\{\}:;>+\(\[,])\s+/, '\1')
73
74     # Add missing semicolons.
75     css.gsub!(/([^;\}])\}/, '\1;}')
76
77     # Replace 0(%, em, ex, px, in, cm, mm, pt, pc) with just 0.
78     css.gsub!(/([\s:])([+-]?0)(?:%|em|ex|px|in|cm|mm|pt|pc)/i, '\1\2')
79
80     # Replace 0 0 0 0; with 0.
81     css.gsub!(/:(?:0 )+0;/, ':0;')
82
83     # Replace background-position:0; with background-position:0 0;
84     css.gsub!('background-position:0;', 'background-position:0 0;')
85
86     # Replace 0.6 with .6, but only when preceded by : or a space.
87     css.gsub!(/(:|\s)0+\.(\d+)/, '\1.\2')
88
89     # Convert rgb color values to hex values.
90     css.gsub!(/rgb\s*\(\s*([0-9,\s]+)\s*\)/) do |match|
91       '#' << $1.scan(/\d+/).map{|n| n.to_i.to_s(16).rjust(2, '0') }.join
92     end
93
94     # Compress color hex values, making sure not to touch values used in IE
95     # filters, since they would break.
96     css.gsub!(/([^"'=\s])(\s?)\s*#([0-9a-f])\3([0-9a-f])\4([0-9a-f])\5/i, '\1\2#\3\4\5')
97
98     # Remove empty rules.
99     css.gsub!(/[^\}]+\{;\}\n/, '')
100
101     # Re-insert box model hacks.
102     css.gsub!('___BMH___', '"\"}\""')
103
104     # Prevent redundant semicolons.
105     css.gsub!(/;;+/, ';')
106
107     css.strip
108   end
109
110 end
111
112
113