sqwish 0.0.1
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.
- data/README.md +25 -0
- data/lib/sqwish.rb +25 -0
- data/sqwish/README.md +53 -0
- data/sqwish/src/index.js +127 -0
- 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!
|
data/sqwish/src/index.js
ADDED
@@ -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
|
+
|