sqwish 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.md +25 -0
  2. data/lib/sqwish.rb +25 -0
  3. data/sqwish/README.md +53 -0
  4. data/sqwish/src/index.js +127 -0
  5. metadata +81 -0
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # Sqwish-ruby
2
+ #### A CSS compressor
3
+
4
+ This as a Ruby bridge to [Sqwish](https://github.com/ded/sqwish) by Dustin
5
+ Diaz. Just install it:
6
+
7
+ $ gem install sqwish
8
+
9
+ And use it like so:
10
+
11
+ require 'sqwish'
12
+ Sqwish.minify "div { color: red; } div { background: black; }"
13
+ #=> "div{color:red;background:black}"
14
+
15
+ You can also use the `strict: false` flag (it defaults to true):
16
+
17
+ Sqwish.minify "div { color: red; } div { background: black; }", strict: false
18
+ #=> "div{color:red}div{background:black}"
19
+
20
+ ## Authors
21
+
22
+ * **Sqwish** is by Dustin Diaz @ [github.com/ded/sqwish](https://github.com/ded/sqwish).
23
+ * This Ruby gem is by Rico Sta. Cruz @ [github.com/rstacruz/sqwish.rb](http://github.com/rstacruz/sqwish.rb).github.com/rstacruz/sqwish.rb).
24
+
25
+ MIT.
data/lib/sqwish.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'execjs'
2
+
3
+ module Sqwish
4
+ class << self
5
+ def minify(src, options={:strict => true})
6
+ sqwish_js.call "sqwish", src, !! options[:strict]
7
+ end
8
+
9
+ def sqwish_js
10
+ @squish_js ||= ExecJS.compile(sqwish_src)
11
+ end
12
+
13
+ def sqwish_src
14
+ open(sqwish_js_path).read
15
+ end
16
+
17
+ def sqwish_js_path
18
+ File.expand_path '../../sqwish/src/index.js', __FILE__
19
+ end
20
+
21
+ def version
22
+ "0.0.1"
23
+ end
24
+ end
25
+ end
data/sqwish/README.md ADDED
@@ -0,0 +1,53 @@
1
+ Welcome to Sqwish
2
+ ----------
3
+ A [Node](http://nodejs.org) based CSS Compressor. It works like this.
4
+
5
+ require('sqwish').minify('body { color: #ff33cc; }');
6
+ // =>
7
+ body{color:#f3c}
8
+
9
+ CLI
10
+ ---
11
+ Install it.
12
+
13
+ $ npm install sqwish
14
+
15
+ Use it like this:
16
+
17
+ sqwish css/styles.css -o css/prod-styles.min.css
18
+
19
+ Notes
20
+ -------
21
+ Sqwish does not attempt to fix invalid CSS, therefore, at minimum, your CSS should at least follow the basic rules:
22
+
23
+ selectors[,more selectors] {
24
+ property: value;
25
+ another-property: another value;
26
+ }
27
+
28
+ Strict Optimizations
29
+ ----------
30
+ Aside from regular minification, in <code>--strict</code> mode Sqwish will combines duplicate selectors and merge duplicate properties.
31
+
32
+ // before
33
+ div {
34
+ color: orange;
35
+ background: red;
36
+ }
37
+ div {
38
+ color: #ff33cc;
39
+ margin: 0px;
40
+ }
41
+
42
+ // after
43
+ div{color:#f3c;background:red;margin:0}
44
+
45
+ This mode can be enabled as so:
46
+
47
+ sqwish.minify(css, true);
48
+
49
+ on the command line
50
+
51
+ sqwish styles.css --strict
52
+
53
+ Happy Sqwishing!
@@ -0,0 +1,127 @@
1
+ /*!
2
+ * Sqwish - a CSS Compressor
3
+ * Copyright Dustin Diaz 2011
4
+ * https://github.com/ded/sqwish
5
+ * License MIT
6
+ */
7
+
8
+ var fs = require('fs');
9
+
10
+ function uniq(ar) {
11
+ var a = [], i, j;
12
+ label:
13
+ for (i = ar.length - 1; i >= 0; i--) {
14
+ for (j = a.length - 1; j >= 0; j--) {
15
+ if (a[j] == ar[i]) {
16
+ continue label;
17
+ }
18
+ }
19
+ a[a.length] = ar[i];
20
+ }
21
+ return a;
22
+ }
23
+
24
+ function sqwish(css, strict) {
25
+ // allow /*! bla */ style comments to retain copyrights etc.
26
+ var comments = css.match(/\/\*![\s\S]+?\*\//g);
27
+
28
+ css = css.trim() // give it a solid trimming to start
29
+
30
+ // comments
31
+ .replace(/\/\*[\s\S]+?\*\//g, '')
32
+
33
+ // line breaks and carriage returns
34
+ .replace(/[\n\r]/g, '')
35
+
36
+ // space between selectors, declarations, properties and values
37
+ .replace(/\s*([:;,{}])\s*/g, '$1')
38
+
39
+ // replace multiple spaces with single spaces
40
+ .replace(/\s+/g, ' ')
41
+
42
+ // space between last declaration and end of rule
43
+ // also remove trailing semi-colons on last declaration
44
+ .replace(/;}/g, '}')
45
+
46
+ // this is important
47
+ .replace(/\s+(!important)/g, '$1')
48
+
49
+ // convert longhand hex to shorthand hex
50
+ .replace(/#([a-fA-F0-9])\1([a-fA-F0-9])\2([a-fA-F0-9])\3/g, '#$1$2$3')
51
+
52
+ // replace 0px with 0
53
+ .replace(/([\s|:])[0]+px/g, '$10');
54
+
55
+ if (strict) {
56
+ css = strict_css(css);
57
+ }
58
+
59
+ // put back in copyrights
60
+ if (comments) {
61
+ comments = comments ? comments.join('\n') : '';
62
+ css = comments + '\n' + css;
63
+ }
64
+ return css;
65
+ }
66
+
67
+ function strict_css(css) {
68
+ // now some super fun funky shit where we remove duplicate declarations
69
+ // into combined rules
70
+
71
+ // store global dict of all rules
72
+ var ruleList = {},
73
+ rules = css.match(/([^{]+\{[^}]+\})+?/g);
74
+
75
+ // lets find the dups
76
+ rules.forEach(function (rule) {
77
+ // break rule into selector|declaration parts
78
+ var parts = rule.match(/([^{]+)\{([^}]+)/),
79
+ selector = parts[1],
80
+ declarations = parts[2];
81
+
82
+ // start new list if it wasn't created already
83
+ if (!ruleList[selector]) {
84
+ ruleList[selector] = [];
85
+ }
86
+
87
+ declarations = declarations.split(';');
88
+ // filter out duplicate properties
89
+ ruleList[selector] = ruleList[selector].filter(function (decl) {
90
+ var prop = decl.match(/[^:]+/)[0];
91
+ // pre-existing properties are not wanted anymore
92
+ return !declarations.some(function (dec) {
93
+ // must include '^' as to not confuse "color" with "border-color" etc.
94
+ return dec.match(new RegExp('^' + prop + ':'));
95
+ });
96
+ });
97
+
98
+ // latter takes presedence :)
99
+ ruleList[selector] = ruleList[selector].concat(declarations);
100
+ // still dups? just in case
101
+ ruleList[selector] = uniq(ruleList[selector]);
102
+ });
103
+
104
+ // reset css because we're gonna recreate the whole shabang.
105
+ css = '';
106
+ for (var selector in ruleList) {
107
+ var joinedRuleList = ruleList[selector].join(';');
108
+ css += selector + '{' + (joinedRuleList).replace(/;$/, '') + '}';
109
+ }
110
+ return css;
111
+ }
112
+
113
+ module.exports.exec = function (args) {
114
+ var out;
115
+ var read = args[0];
116
+ if (out = args.indexOf('-o') != -1) {
117
+ out = args[out + 1];
118
+ } else {
119
+ out = read.replace(/\.css$/, '.min.css');
120
+ }
121
+ console.log('compressing ' + read + ' to ' + out + '...');
122
+ var data = fs.readFileSync(read, 'utf8');
123
+ fs.writeFileSync(out, sqwish(data, (args.indexOf('--strict') != -1)), 'utf8');
124
+ };
125
+ module.exports.minify = function (css, strict) {
126
+ return sqwish(css, strict);
127
+ };
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sqwish
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Rico Sta. Cruz
13
+ - Dustin Diaz
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-04-26 00:00:00 +08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: execjs
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: Compresses CSS.
35
+ email:
36
+ - rico@sinefunc.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/sqwish.rb
45
+ - sqwish/README.md
46
+ - sqwish/src/index.js
47
+ - README.md
48
+ has_rdoc: true
49
+ homepage: http://github.com/rstacruz/sqwish
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.7
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A node-based CSS compressor
80
+ test_files: []
81
+