|
1 | | -#-- |
2 | | -# Copyright (c) 2008 Ryan Grove <[email protected]> |
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:[email protected]) |
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 | 1 | # Wraps CSSMin compressor to use the same API as the rest of |
114 | 2 | # Jammit's compressors. |
115 | 3 | class Jammit::CssminCompressor |
|
0 commit comments