xhochy-rainpress 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,50 @@
1
+ == About
2
+
3
+ Rainpress is a compressor for CSS. It's written in ruby, but should not be
4
+ limited to ruby projects.
5
+
6
+ Rainpress does not apply common compression algorithms like gzip, it removes
7
+ unnecessary characters and replaces some attributes with a shorter equivalent
8
+ name.
9
+
10
+ == Simple Usage
11
+
12
+ require 'rubygems'
13
+ require 'rainpress'
14
+ compressed_style_text = Rainpress.compress style_text
15
+
16
+ == License
17
+
18
+ Copyright (c) 2007-2008 Uwe L. Korn
19
+
20
+ Permission is hereby granted, free of charge, to any person obtaining a copy
21
+ of this software and associated documentation files (the "Software"), to deal
22
+ in the Software without restriction, including without limitation the rights
23
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24
+ copies of the Software, and to permit persons to whom the Software is
25
+ furnished to do so, subject to the following conditions:
26
+
27
+ The above copyright notice and this permission notice shall be included in
28
+ all copies or substantial portions of the Software.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36
+ THE SOFTWARE.
37
+
38
+ Remark(not part of the license text): This is a MIT-style license
39
+
40
+ == Links
41
+
42
+ * {Rainpress Website}[http://rainpress.xhochy.com/]
43
+ * {Git repository}[http://github.com/xhochy/rainpress/tree/master]
44
+ * {Bugtracker}[https://bugs.launchpad.net/rainpress/]
45
+ * {Wiki}[http://code.google.com/p/rainpress/w/list]
46
+ * {Translations}[https://translations.launchpad.net/rainpress/]
47
+ * {XhochY Weblog (for Announcements about Rainpress)}[http://xhochy.org/en/]
48
+ * {Mailinglist}[http://groups.google.com/group/xy-oss-projects-discussion]
49
+ * {Freshmeat Record}[http://freshmeat.net/projects/rainpress]
50
+ * {Ohloh listing}[http://www.ohloh.net/projects/12620/]
data/Rakefile ADDED
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env ruby
2
+ #####################################
3
+ ## The main Rakefile for Rainpress ##
4
+ #####################################
5
+ #
6
+ #--
7
+ # Copyright (c) 2007-2008 Uwe L. Korn
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ # of this software and associated documentation files (the "Software"), to deal
11
+ # in the Software without restriction, including without limitation the rights
12
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the Software is
14
+ # furnished to do so, subject to the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included in
17
+ # all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ # THE SOFTWARE.
26
+ #++
27
+ #
28
+ # Author:: Uwe L. Korn <uwelk@xhochy.org>
29
+ # Copyright:: Copyright (c) 2007-2008 Uwe L. Korn
30
+ # License:: MIT-style License (see Rainpress)
31
+
32
+ ## Includes ##
33
+
34
+ # Use the prewritten :clean Task from rake
35
+ require 'rake/clean'
36
+ # Use the gettext-utility functions for pot and mo generation
37
+ require 'gettext/utils'
38
+
39
+ require 'rubygems'
40
+ require 'rake'
41
+ require 'rake/testtask'
42
+ require 'rake/rdoctask'
43
+ require 'spec/rake/spectask'
44
+
45
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
46
+
47
+ ## Config ##
48
+
49
+ doc = {
50
+ # The location of all important Rainpress source files
51
+ 'Files' => FileList['*.rb', File.join('rainpress', '*.rb')],
52
+ # The title of the API Documentation
53
+ 'Title' => 'Rainpress'
54
+ }
55
+
56
+ ## Tasks ##
57
+
58
+ # Run the unit tests via rcov, so that we see which code is covered by
59
+ # the unit tests and which code needs additional tests written for. Our
60
+ # aim is that the tests for Rainpress should cover *all* code, if not
61
+ # it shouldn't be checked in before there are not enough tests.
62
+ #
63
+ # But remember: 100% Code coverage does not mean that the programm is 100%
64
+ # correct!
65
+ desc 'Run unit tests'
66
+ task :test do
67
+ sh 'rcov rainpress_test.rb'
68
+ end
69
+
70
+ desc 'Build pot-file from sourcecode'
71
+ task :build_pot => [File.join('locale', 'rainpress.pot')]
72
+
73
+ desc 'Complie *.po-files to binary mo\'s'
74
+ task :build_mo do
75
+ GetText::create_mofiles(true, 'locale', 'locale')
76
+ end
77
+
78
+ # The API documentation should only be changed if there is a source code file
79
+ # which last modification time is higher than the modification time of the
80
+ # index.html which is always regenerated during the API documentation building
81
+ # process.
82
+ desc 'Generate the sourcecode documentation'
83
+ task :doc => [File.join('doc', 'index.html')]
84
+
85
+ # If we want to build all, this just means we want to build the API
86
+ # documentation and run the unit tests.
87
+ task :all => [:doc, :test]
88
+
89
+ # By default we build the task :all
90
+ task :default => [:all]
91
+
92
+ ## XhochY specific Tasks ##
93
+
94
+ # This tasks is only used for the continous builds on xhochy.com, don't change!
95
+ # The location is fixed and the only place where this script has permission to
96
+ # write to.
97
+ # The output is visible via
98
+ # - http://rainpress.xhochy.com/test/ (The code coverage reports of the unittests)
99
+ # - http://rainpress.xhochy.com/doc/ (The API documentation)
100
+ task :publish_to_rainpress_xhochy_com => [:doc, :test]
101
+ task :publish_to_rainpress_xhochy_com do
102
+ sh 'rm -rf /srv/www/port80/rainpress.xhochy.com/doc/'
103
+ sh 'rm -rf /srv/www/port80/rainpress.xhochy.com/coverage/'
104
+ sh 'cp -r doc/ coverage/ /srv/www/port80/rainpress.xhochy.com'
105
+ end
106
+
107
+ ## clean Task ##
108
+
109
+ # Delete the API Documentation
110
+ CLEAN.include('doc')
111
+ # Delete the code coverage report
112
+ CLEAN.include('coverage')
113
+ # The flowing commands will delete the Debian-Package temporary files
114
+ CLEAN.include('build-stamp')
115
+ CLEAN.include('configure-stamp')
116
+ CLEAN.include(File.join('debian', 'rainpress'))
117
+ CLEAN.include(File.join('debian', 'rainpress-doc'))
118
+ CLEAN.include(File.join('debian', 'files'))
119
+ # Delete all binary translations (*.mo-files, not the *.po-files)
120
+ CLEAN.include(File.join('locale', '*', 'LC_MESSAGES'));
121
+
122
+ ## Deb(ian) Package Tasks ##
123
+
124
+ # Build a source Debian package package that could be either used for building
125
+ # a "binary" Debian package via pbuilder or for uploads in a APT repository.
126
+ desc 'Build debian-source-package'
127
+ task :source_deb => [:build_mo] do
128
+ sh 'debuild -S -I.svn -us -uc'
129
+ end
130
+ task :source_deb => [:clean]
131
+
132
+ # Builds a "binary" Debian package using the fakeroot command, packages created
133
+ # this way only tell us that the generation process has no problems. If you want
134
+ # to check if all build dependecies are remarked in debian/control, you should
135
+ # generate a source Debian package via `rake source_deb` and then use pbuilder
136
+ # to build the "binary" package via `sudo pbuilder *.dsc`. Only this will ensure
137
+ # that the package could be build on standard configurations, since pbuilder
138
+ # builds the package in a clean chroot-environment.
139
+ desc 'Build debian-package using fakeroot'
140
+ task :binary_deb_fakeroot do
141
+ sh 'dpkg-buildpackage -rfakeroot -us -uc'
142
+ end
143
+ task :binary_deb_fakeroot => [:source_deb]
144
+
145
+ ## File Tasks ##
146
+
147
+ # Builds the PO-template out of the ruby source code, at the moment we only have
148
+ # i18n strings in the rainpress.rb, we will ignore other i18n strings in other
149
+ # files. If there are any changes in the PO-template, the new version should be
150
+ # uploaded to https://translations.launchpad.net/rainpress/ so that there's
151
+ # always the up-to-date version, so that the translation keeps up with the
152
+ # development.
153
+ file File.join('locale', 'rainpress.pot') => 'bin/rainpress' do
154
+ rm_f File.join('locale', 'rainpress.pot')
155
+ sh 'rgettext bin/rainpress -o ' + File.join('locale', 'rainpress.pot')
156
+ puts '!!! Remember to upload the updated pot-file to Launchpad/Translations !!!'
157
+ end
158
+
159
+ # Build the API documentation using RDoc, the include diagrams are made with
160
+ # graphviz, so this needs to installed on the developemnt system too.
161
+ file File.join('doc', 'index.html') => doc['Files'] do
162
+ sh "rm -rf doc"
163
+
164
+ cmd = 'rdoc --title ' + doc['Title']
165
+ cmd+= ' --all --diagram --image-format png --inline-source --charset UTF-8 '
166
+ cmd+= '--op doc/ --tab-width 4'
167
+ sh cmd
168
+ end
169
+
170
+ task :release => [:build_mo]
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 1
4
+ :minor: 1
data/bin/rainpress ADDED
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env ruby
2
+ ##############################################
3
+ # This is the Rainpress standalone excutable #
4
+ ##############################################
5
+ #
6
+ #--
7
+ # Copyright (c) 2007-2008 Uwe L. Korn
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ # of this software and associated documentation files (the "Software"), to deal
11
+ # in the Software without restriction, including without limitation the rights
12
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the Software is
14
+ # furnished to do so, subject to the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included in
17
+ # all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ # THE SOFTWARE.
26
+ #++
27
+ #
28
+ # Author:: Uwe L. Korn <uwelk@xhochy.org>
29
+ # Copyright:: Copyright (c) 2007-2008 Uwe L. Korn
30
+ # License:: MIT-style License (see Rainpress)
31
+
32
+ require 'getoptlong'
33
+ require 'gettext'
34
+ # Do not include rainpress/packer via global include, this might include
35
+ # a false file, we want the Packer version which is shipped with this file.
36
+ require File.join(File.dirname(__FILE__), *%w[.. lib rainpress])
37
+
38
+ ## Var Init ##
39
+
40
+ opts = GetoptLong.new(
41
+ ['--help', '-h', GetoptLong::NO_ARGUMENT],
42
+ ['--input', '-i', GetoptLong::REQUIRED_ARGUMENT],
43
+ ['--output', '-o', GetoptLong::REQUIRED_ARGUMENT],
44
+ ['--keep-comments', '-c', GetoptLong::NO_ARGUMENT],
45
+ ['--keep-newlines', '-n', GetoptLong::NO_ARGUMENT],
46
+ ['--keep-spaces', '-s', GetoptLong::NO_ARGUMENT],
47
+ ['--leave-spaces', '-k', GetoptLong::NO_ARGUMENT],
48
+ ['--skip-misc', '-m', GetoptLong::NO_ARGUMENT]
49
+ )
50
+
51
+ $infile = nil
52
+ $outfile = nil
53
+
54
+ GetText::bindtextdomain('rainpress', File.join(File.dirname(__FILE__), *%w[.. locale]))
55
+
56
+ ## Functions ##
57
+
58
+ # Explain to the user how to use Rainpress
59
+ #
60
+ # After displaying this usage information exit the program.
61
+ # The messages in this functions are the only things to translate. The
62
+ # translation files could be found in the locales/ directory, but translation
63
+ # should be done via https://translations.launchpad.net/rainpress/ . The
64
+ # translations done there could be exported and merged into the software. We
65
+ # use Launchpad since it provides a nice interface for the translation process.
66
+ def usage
67
+ puts 'Rainpress -- CSS compressor |'
68
+ puts '----------------------------|'
69
+ puts ''
70
+ puts '--help, -h ' + GetText::_('Display this help')
71
+ puts '--input, -i <file> ' + GetText::_('The CSS-file to be compressed, if not set stdin is used')
72
+ puts '--output, -o <file> ' + GetText::_('The output file, if not set, stdout is used')
73
+ puts '--keep-comments, -c ' + GetText::_('Do not remove comments')
74
+ puts '--keep-newlines, -n ' + GetText::_('Do not remove line breaks')
75
+ puts '--keep-spaces, -s ' + GetText::_('Do not remove multiple spaces')
76
+ puts '--leave-colors, -k ' + GetText::_('Do not change color names')
77
+ puts '--skip-misc, -m ' + GetText::_('Skip all miscellaneous tasks')
78
+ exit
79
+ end
80
+
81
+ ## Main ##
82
+
83
+ # The options that will be passed to the compress method
84
+ $options = {}
85
+
86
+ opts.each do |opt, arg|
87
+ case opt
88
+ when '--help'
89
+ usage()
90
+ when '--input'
91
+ $infile = arg
92
+ when '--output'
93
+ $outfile = arg
94
+ when '--keep-comments'
95
+ $options[:preserveComments] = true
96
+ when '--keep-newlines'
97
+ $options[:preserveNewlines] = true
98
+ when '--keep-spaces'
99
+ $options[:preserveSpaces] = true
100
+ when '--leave-colors'
101
+ $options[:preserveColors] = true
102
+ when '--skip-misc'
103
+ $options[:skipMisc] = true
104
+ end
105
+ end
106
+
107
+ # Check if a input file is set, if not than read from stdin
108
+ if $infile == nil
109
+ $input = STDIN.read
110
+ else
111
+ $input = File.read($infile)
112
+ end
113
+
114
+ # Create a new Rainpress::Packer instance which we'll use for compressing
115
+ packer = Rainpress::Packer.new
116
+ # Compress the inputted text
117
+ $output = packer.compress($input, $options)
118
+
119
+ # Check if a output file is set, if not write to stdout
120
+ if $outfile == nil
121
+ puts $output
122
+ else
123
+ # TODO: Is there no Ruby equivalent to PHP's file_put_contents ?
124
+ File.open($outfile, 'w') do |f|
125
+ f.write $output
126
+ end
127
+ end
128
+
data/lib/rainpress.rb ADDED
@@ -0,0 +1,244 @@
1
+ # == About
2
+ #
3
+ # Rainpress is a compressor for CSS. It's written in ruby, but should not be
4
+ # limited to ruby projects.
5
+ #
6
+ # Rainpress does not apply common compression algorithms like gzip, it removes
7
+ # unnecessary characters and replaces some attributes with a shorter equivalent
8
+ # name.
9
+ #
10
+ # Copyright:: Copyright (c) 2007-2008 Uwe L. Korn
11
+ #
12
+ # == License
13
+ #
14
+ # Copyright (c) 2007-2008 Uwe L. Korn
15
+ #
16
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
17
+ # of this software and associated documentation files (the "Software"), to deal
18
+ # in the Software without restriction, including without limitation the rights
19
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
+ # copies of the Software, and to permit persons to whom the Software is
21
+ # furnished to do so, subject to the following conditions:
22
+ #
23
+ # The above copyright notice and this permission notice shall be included in
24
+ # all copies or substantial portions of the Software.
25
+ #
26
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
+ # THE SOFTWARE.
33
+ #
34
+ # Remark(not part of the license text): This is a MIT-style license
35
+ #
36
+ # == Links
37
+ #
38
+ # * {Rainpress Website}[http://rainpress.xhochy.com/]
39
+ # * {SVN repository}[http://code.google.com/p/rainpress/source]
40
+ # * {Bugtracker}[https://bugs.launchpad.net/rainpress/]
41
+ # * {Wiki}[http://code.google.com/p/rainpress/w/list]
42
+ # * {Translations}[https://translations.launchpad.net/rainpress/]
43
+ # * {XhochY Weblog (for Announcements about Rainpress)}[http://xhochy.org/en/]
44
+ # * {Mailinglist}[http://groups.google.com/group/xy-oss-projects-discussion]
45
+ # * {Continous Integration Builds and Tests}[http://cruisecontrol-rb.xhochy.com/builds/rainpress]
46
+ # * {Freshmeat Record}[http://freshmeat.net/projects/rainpress]
47
+ # * {Ohloh listing}[http://www.ohloh.net/projects/12620/]
48
+ module Rainpress
49
+
50
+ # == Information
51
+ #
52
+ # This is the main class of Rainpress, create an instance of it to compress
53
+ # your CSS-styles.
54
+ #
55
+ # Author:: Uwe L. Korn <uwelk@xhochy.org>
56
+ #
57
+ # == Simple Usage
58
+ #
59
+ # packer = Rainpress::Packer.new
60
+ # compressed_style = packer.compress(style)
61
+ class Packer
62
+
63
+ # Use always this functions if you want to compress your CSS-style
64
+ #
65
+ # <b>Options:</b>
66
+ #
67
+ # * <tt>:preserveComments</tt> - if set to true, comments will not be
68
+ # removed
69
+ # * <tt>:preserveNewline</tt> - if set to true, newlines will not be removed
70
+ # * <tt>:preserveSpaces</tt> - if set to true, spaces will not be removed
71
+ # * <tt>:preserveColors</tt> - if set to true, colors will not be modified
72
+ # * <tt>:skipMisc</tt> - if set to true, miscellaneous compression parts
73
+ # will be skipped
74
+ def compress(style, options = {})
75
+ # remove comments
76
+ style = remove_comments(style) unless options[:preserveComments]
77
+
78
+ # remove newlines
79
+ style = remove_newlines(style) unless options[:preserveNewlines]
80
+
81
+ # remove unneeded spaces
82
+ style = remove_spaces(style) unless options[:preserveSpaces]
83
+
84
+ # replace colours with shorter names
85
+ style = shorten_colors(style) unless options[:preserveColors]
86
+
87
+ # make all other things
88
+ style = do_misc(style) unless options[:skipMisc]
89
+
90
+ style
91
+ end
92
+
93
+ # Remove all comments out of the CSS-Document
94
+ #
95
+ # Only /* text */ comments are supported.
96
+ # Attention: If you are doing css hacks for IE using the comment tricks,
97
+ # they will be removed using this function. Please consider for IE css style
98
+ # corrections the usage of conditionals comments in your (X)HTML document.
99
+ def remove_comments(script)
100
+ input = script
101
+ script = ''
102
+
103
+ while input.length > 0 do
104
+ pos = input.index("/*");
105
+
106
+ # No more comments
107
+ if pos == nil
108
+ script += input
109
+ input = '';
110
+ else # Comment beginning at pos
111
+ script += input[0..(pos-1)] if pos > 0 # only append text if there is some
112
+ input = input[(pos+2)..-1]
113
+ # Comment ending at pos
114
+ pos = input.index("*/")
115
+ input = input[(pos+2)..-1]
116
+ end
117
+ end
118
+
119
+ # return
120
+ script
121
+ end
122
+
123
+ # Remove all newline characters
124
+ #
125
+ # We take care of Windows(\r\n), Unix(\n) and Mac(\r) newlines.
126
+ def remove_newlines(script)
127
+ script.gsub(/\n|\r/,'')
128
+ end
129
+
130
+ # Remove unneeded spaces
131
+ #
132
+ # 1. Turn mutiple spaces into a single
133
+ # 2. Remove spaces around ;:{},
134
+ # 3. Remove tabs
135
+ def remove_spaces(script)
136
+ script = script.gsub(/(\s(\s)+)/, ' ')
137
+ script = script.gsub(/\s*;\s*/,';')
138
+ script = script.gsub(/\s*:\s*/,':')
139
+ script = script.gsub(/\s*\{\s*/,'{')
140
+ script = script.gsub(/\s*\}\s*/,'}')
141
+ script = script.gsub(/\s*,\s*/,',')
142
+ script.gsub("\t",'');
143
+ end
144
+
145
+ # Replace color values with their shorter equivalent
146
+ #
147
+ # 1. Turn rgb(,,)-colors into #-values
148
+ # 2. Shorten #AABBCC down to #ABC
149
+ # 3. Replace names with their shorter hex-equivalent
150
+ # * white -> #fff
151
+ # * black -> #000
152
+ # 4. Replace #-values with their shorter name
153
+ # * #f00 -> red
154
+ def shorten_colors(style)
155
+ # rgb(50,101,152) to #326598
156
+ style = style.gsub(/rgb\s*\(\s*([0-9,\s]+)\s*\)/) do |match|
157
+ out = '#'
158
+ $1.split(',').each do |num|
159
+ if num.to_i < 16
160
+ out += '0'
161
+ end
162
+ out += num.to_i.to_s(16) # convert to hex
163
+ end
164
+ out
165
+ end
166
+ # Convert #AABBCC to #ABC, keep if preceed by a '='
167
+ style = style.gsub(/([^\"'=\s])(\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/) do |match|
168
+ out = match
169
+ if ($3.downcase == $4.downcase) and ($5.downcase == $6.downcase) and ($7.downcase == $8.downcase)
170
+ out = $1 + '#' + $3.downcase + $5.downcase + $7.downcase
171
+ end
172
+ out
173
+ end
174
+
175
+ # At the moment we assume that colours only appear before ';' or '}' and
176
+ # after a ':', if there could be an occurence of a color before or after
177
+ # an other character, submit either a bug report or, better, a patch that
178
+ # enables Rainpress to take care of this.
179
+
180
+ # shorten several names to numbers
181
+ ## shorten white -> #fff
182
+ style = style.gsub(/:[\s]*white[\s]*;/, ':#fff;')
183
+ style = style.gsub(/:[\s]*white[\s]*\}/, ':#fff}')
184
+ ## shorten black -> #000
185
+ style = style.gsub(/:[\s]*black[\s]*;/, ':#000;')
186
+ style = style.gsub(/:[\s]*black[\s]*\}/, ':#000}')
187
+ # shotern several numbers to names
188
+ ## shorten #f00 or #ff0000 -> red
189
+ style = style.gsub(/:[\s]*#([fF]00|[fF]{2}0000);/, ':red;')
190
+ style = style.gsub(/:[\s]*#([fF]00|[fF]{2}0000)\}/, ':red}')
191
+
192
+ style
193
+ end
194
+
195
+ # Do miscellaneous compression methods on the style.
196
+ def do_misc(script)
197
+ # Replace 0(pt,px,em,%) with 0 but only when preceded by : or a white-space
198
+ script = script.gsub(/([\s:]+)(0)(px|em|%|in|cm|mm|pc|pt|ex)/) do |match|
199
+ match.gsub(/(px|em|%|in|cm|mm|pc|pt|ex)/,'')
200
+ end
201
+ # Replace :0 0 0 0(;|}) with :0(;|})
202
+ script = script.gsub(':0 0 0 0;', ':0;')
203
+ script = script.gsub(':0 0 0 0}', ':0}')
204
+ # Replace :0 0 0(;|}) with :0(;|})
205
+ script = script.gsub(':0 0 0;', ':0;')
206
+ script = script.gsub(':0 0 0}', ':0}')
207
+ # Replace :0 0(;|}) with :0(;|})
208
+ script = script.gsub(':0 0}', ':0}')
209
+ script = script.gsub(':0 0;', ':0;')
210
+ # Replace background-position:0; with background-position:0 0;
211
+ script = script.gsub('background-position:0;', 'background-position:0 0;');
212
+ # Replace 0.6 to .6, but only when preceded by : or a white-space
213
+ script = script.gsub(/[:\s]0+\.(\d+)/) do |match|
214
+ match.sub('0', '') # only first '0' !!
215
+ end
216
+ # Replace multiple ';' with a single ';'
217
+ script = script.gsub(/[;]+/, ';')
218
+ # Replace ;} with }
219
+ script = script.gsub(';}', '}')
220
+
221
+ # Do not include again:
222
+ # -> reported as bug #282496 in Launchpad
223
+ # # Replace background-color: with background:
224
+ # # script = script.gsub('background-color:', 'background:')
225
+
226
+ # Replace font-weight:normal; with 400
227
+ script = script.gsub(/font-weight[\s]*:[\s]*normal[\s]*;/,'font-weight:400;')
228
+ script = script.gsub(/font-weight[\s]*:[\s]*normal[\s]*\}/,'font-weight:400}')
229
+ script = script.gsub(/font[\s]*:[\s]*normal[\s;\}]*/) do |match|
230
+ match.sub('normal', '400')
231
+ end
232
+ # Replace font-weight:bold; with 700
233
+ script = script.gsub(/font-weight[\s]*:[\s]*bold[\s]*;/,'font-weight:700;')
234
+ script = script.gsub(/font-weight[\s]*:[\s]*bold[\s]*\}/,'font-weight:700}')
235
+ script = script.gsub(/font[\s]*:[\s]*bold[\s;\}]*/) do |match|
236
+ match.sub('bold', '700')
237
+ end
238
+
239
+ script
240
+ end
241
+
242
+ end
243
+
244
+ end
@@ -0,0 +1,238 @@
1
+ ##############################
2
+ # Test for Rainpress::Packer #
3
+ ##############################
4
+ #
5
+ #--
6
+ # Copyright (c) 2007-2008 Uwe L. Korn
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #++
26
+ #
27
+ # Author:: Uwe L. Korn <uwelk@xhochy.org>
28
+ # Copyright:: Copyright (c) 2007-2008 Uwe L. Korn
29
+ # License:: MIT-style License (see Rainpress)require 'test/unit'
30
+
31
+ require 'test/unit'
32
+ require File.join(File.dirname(__FILE__), 'rainpress.rb')
33
+
34
+ module Rainpress
35
+ # This class keeps all Tests for the class Rainpress::Packer
36
+ #
37
+ # Author:: Uwe L. Korn <uwelk@xhochy.org>
38
+ class TestPacker < Test::Unit::TestCase
39
+
40
+ # Create an instace of Rainpress::Packer for use in the tests
41
+ def setup
42
+ @packer = Rainpress::Packer.new
43
+ end
44
+
45
+ # Test Rainpress::Packer.remove_comments
46
+ def test_remove_comments
47
+ options = {
48
+ :preserveComments => false,
49
+ :preserveNewlines => true,
50
+ :preserveSpaces => true,
51
+ :preserveColors => true,
52
+ :skipMisc => true
53
+ }
54
+
55
+ # plain comment -> ''
56
+ input = '/* sss */';
57
+ assert_equal('', @packer.compress(input, options))
58
+
59
+ # no comment -> no change
60
+ input = 'sss';
61
+ assert_equal('sss', @packer.compress(input, options))
62
+
63
+ # comment floating in text
64
+ input = 's/*ss*/ss';
65
+ assert_equal('sss', @packer.compress(input, options))
66
+
67
+ # empty string
68
+ input = ''
69
+ assert_equal('', @packer.compress(input, options))
70
+ end
71
+
72
+ # Test Rainpress::Packer.remove_newlines
73
+ def test_remove_newlines
74
+ options = {
75
+ :preserveComments => true,
76
+ :preserveNewlines => false,
77
+ :preserveSpaces => true,
78
+ :preserveColors => true,
79
+ :skipMisc => true
80
+ }
81
+
82
+ # plain unix-newline
83
+ input = "\n"
84
+ assert_equal('', @packer.compress(input, options))
85
+
86
+ # plain windows newline
87
+ input = "\r\n"
88
+ assert_equal('', @packer.compress(input, options))
89
+
90
+ # no newline
91
+ input = "rn"
92
+ assert_equal('rn', @packer.compress(input, options))
93
+
94
+ # newlines floatin in text
95
+ input = "sss\n||\r\nsss"
96
+ assert_equal('sss||sss', @packer.compress(input, options))
97
+
98
+ # empty string
99
+ input = ''
100
+ assert_equal('', @packer.compress(input, options))
101
+ end
102
+
103
+ # Test Rainpress::Packer.remove_spaces
104
+ def test_remove_spaces
105
+ options = {
106
+ :preserveComments => true,
107
+ :preserveNewlines => true,
108
+ :preserveSpaces => false,
109
+ :preserveColors => true,
110
+ :skipMisc => true
111
+ }
112
+
113
+ # (a) Turn mutiple Spaces into a single, but not less
114
+ input = ' ' # 2 spaces
115
+ assert_equal(' ', @packer.compress(input, options))
116
+ input = ' ' # 3 spaces
117
+ assert_equal(' ', @packer.compress(input, options))
118
+
119
+ # (b) remove spaces around ;:{},
120
+ input = ' ; '
121
+ assert_equal(';', @packer.compress(input, options))
122
+ input = ' : '
123
+ assert_equal(':', @packer.compress(input, options))
124
+ input = ' { '
125
+ assert_equal('{', @packer.compress(input, options))
126
+ input = ' } '
127
+ assert_equal('}', @packer.compress(input, options))
128
+ input = ' , '
129
+ assert_equal(',', @packer.compress(input, options))
130
+ # (c) remove tabs
131
+ input = "\t"
132
+ assert_equal('', @packer.compress(input, options))
133
+ end
134
+
135
+ # Test Rainpress::Packer.shorten_colors
136
+ def test_shorten_colors
137
+ options = {
138
+ :preserveComments => true,
139
+ :preserveNewlines => true,
140
+ :preserveSpaces => true,
141
+ :preserveColors => false,
142
+ :skipMisc => true
143
+ }
144
+ # rgb(50,101,152) to #326598
145
+ input = 'color:rgb(12,101,152)'
146
+ assert_equal('color:#0c6598', @packer.compress(input, options))
147
+
148
+ # #AABBCC to #ABC
149
+ input = 'color:#AAbBCC'
150
+ assert_equal('color:#abc', @packer.compress(input, options))
151
+ # Keep chroma(color="#FFFFFF"); ... due to IE
152
+ input = 'chroma(color="#FFFFFF");'
153
+ assert_equal('chroma(color="#FFFFFF");', @packer.compress(input, options))
154
+
155
+ # shorten several names to numbers
156
+ input = 'color:white;'
157
+ assert_equal('color:#fff;', @packer.compress(input, options))
158
+ input = 'color: white}'
159
+ assert_equal('color:#fff}', @packer.compress(input, options))
160
+
161
+ # shotern several numbers to names
162
+ input = 'color:#ff0000;'
163
+ assert_equal('color:red;', @packer.compress(input, options))
164
+ input = 'color:#F00;'
165
+ assert_equal('color:red;', @packer.compress(input, options))
166
+ end
167
+
168
+ # Test Rainpress::Packer.do_misc
169
+ def test_do_misc
170
+ options = {
171
+ :preserveComments => true,
172
+ :preserveNewlines => true,
173
+ :preserveSpaces => true,
174
+ :preserveColors => true,
175
+ :skipMisc => false
176
+ }
177
+ # Replace 0(pt,px,em,%) with 0
178
+ input = ' 0px'
179
+ assert_equal(' 0', @packer.compress(input, options))
180
+ input = ' 0em'
181
+ assert_equal(' 0', @packer.compress(input, options))
182
+ input = ' 0pt'
183
+ assert_equal(' 0', @packer.compress(input, options))
184
+ input = ' 0%'
185
+ assert_equal(' 0', @packer.compress(input, options))
186
+ input = ' 0in'
187
+ assert_equal(' 0', @packer.compress(input, options))
188
+ input = ' 0cm '
189
+ assert_equal(' 0 ', @packer.compress(input, options))
190
+ input = ':0mm'
191
+ assert_equal(':0', @packer.compress(input, options))
192
+ input = ' 0pc'
193
+ assert_equal(' 0', @packer.compress(input, options))
194
+ input = ' 0ex'
195
+ assert_equal(' 0', @packer.compress(input, options))
196
+ input = ' 10ex'
197
+ assert_equal(' 10ex', @packer.compress(input, options))
198
+
199
+ # Replace 0 0 0 0; with 0.
200
+ input = ':0 0;'
201
+ assert_equal(':0;', @packer.compress(input, options))
202
+ input = ':0 0 0;'
203
+ assert_equal(':0;', @packer.compress(input, options))
204
+ input = ':0 0 0 0;'
205
+ assert_equal(':0;', @packer.compress(input, options))
206
+ input = ':0 0 0 0}'
207
+ assert_equal(':0}', @packer.compress(input, options))
208
+ # Keep 'background-position:0 0;' !!
209
+ input = 'background-position:0 0;'
210
+ assert_equal('background-position:0 0;', @packer.compress(input, options))
211
+
212
+ # Replace 0.6 to .6, but only when preceded by : or a white-space
213
+ input = ' 0.6'
214
+ assert_equal(' .6', @packer.compress(input, options))
215
+ input = ':0.06'
216
+ assert_equal(':.06', @packer.compress(input, options))
217
+ input = '10.6'
218
+ assert_equal('10.6', @packer.compress(input, options))
219
+
220
+ # Replace ;;;; with ;
221
+ input = 'ss;;;ss'
222
+ assert_equal('ss;ss', @packer.compress(input, options))
223
+
224
+ # Replace ;} with }
225
+ input = 'ss;sss;}ss'
226
+ assert_equal('ss;sss}ss', @packer.compress(input, options))
227
+
228
+ # Replace font-weight:normal; with 400, bold with 700
229
+ input = 'font-weight: normal;'
230
+ assert_equal('font-weight:400;', @packer.compress(input, options))
231
+ input = 'font: normal;'
232
+ assert_equal('font: 400;', @packer.compress(input, options))
233
+ input = 'font: bold 1px;'
234
+ assert_equal('font: 700 1px;', @packer.compress(input, options))
235
+ end
236
+
237
+ end
238
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xhochy-rainpress
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Uwe L. Korn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-05 00:00:00 -07:00
13
+ default_executable: rainpress
14
+ dependencies: []
15
+
16
+ description: Rainpress does not apply common compression algorithms like gzip, it removes unnecessary characters and replaces some attributes with a shorter equivalent name
17
+ email: uwelk@xhochy.org
18
+ executables:
19
+ - rainpress
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - README.rdoc
26
+ - Rakefile
27
+ - VERSION.yml
28
+ - bin/rainpress
29
+ - lib/rainpress.rb
30
+ - lib/rainpress_test.rb
31
+ has_rdoc: false
32
+ homepage: http://rainpress.xhochy.com/
33
+ post_install_message:
34
+ rdoc_options:
35
+ - --charset=UTF-8
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project:
53
+ rubygems_version: 1.2.0
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Rainpress is a compressor for CSS. It's written in ruby, but should not be limited to ruby projects.
57
+ test_files: []
58
+