csso-rails 0.0.1 → 0.0.2
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 +48 -25
- data/bin/ruby_csso +2 -2
- data/csso-rails.gemspec +1 -1
- data/lib/csso-rails.rb +1 -1
- data/lib/csso.rb +5 -5
- data/lib/csso/js/compressor.js +76 -20
- data/lib/csso/js/csso.js +70 -0
- data/lib/csso/js/parser.js +3 -3
- data/lib/csso/loader.rb +4 -4
- data/lib/csso/rails.rb +8 -8
- data/lib/csso/version.rb +1 -1
- data/spec/csso/csso_spec.rb +6 -6
- metadata +40 -14
data/README.md
CHANGED
@@ -1,36 +1,59 @@
|
|
1
|
-
csso-rails: Stylesheet Optimizer(CSSO) for Rails Asset pipeline
|
2
|
-
=======
|
1
|
+
# csso-rails: Stylesheet Optimizer (CSSO) for Rails Asset pipeline
|
3
2
|
|
4
|
-
Ruby adapter for
|
3
|
+
Ruby adapter for [github.com/afelix/csso](https://github.com/afelix/csso).
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
(readme and tests/comparison - coming later)
|
10
|
-
Css is usually reduced more that in half in uncompressed and around 15% in gzipped.
|
5
|
+
## About
|
6
|
+
CSSO does structure-optimization for CSS.
|
7
|
+
CSS is usually reduced more than in half in uncompressed and around 15% in gzipped.
|
11
8
|
|
12
|
-
|
13
|
-
|
9
|
+
### A Real-World Example
|
10
|
+
A living rails application CSS – some written in less, some handwritten):
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
| | Original | sass | yui 2.4.7 | csso | % of original
|
13
|
+
|:-------|:------------:|:------:|:-----:|:-----:|:------:
|
14
|
+
|Plain | 129497 | 107006 | 60758 | 60874 | 47%
|
15
|
+
|GZipped | 14046 | 12047 | 10558 | 10472 | 74%
|
19
16
|
|
20
|
-
|
21
|
-
add this gem to your gemfile, and that's it!
|
22
|
-
gem 'csso-rails', :git => ''
|
23
|
-
Upon including it becomes the default compressor,
|
24
|
-
More explicit way - set in config: config.assets.css_compressor = :csso
|
17
|
+
Very close to yui compressor, wining in gzipped (you’re using nginx `mod\_gzip_static`, don’t you?)
|
25
18
|
|
26
|
-
|
27
|
-
ruby_csso non_optimized.css > optimized.css
|
19
|
+
A more hard example – twitter bootstrap.css, already minified:
|
28
20
|
|
21
|
+
| | Original | lessc | yui 2.4.7 | csso | % of original
|
22
|
+
|:-------|:------------:|:-----:|:-----:|:-----:|:------:
|
23
|
+
|Plain | 81443 | 71520 | 68755 | 67679 | 83%
|
24
|
+
|GZipped | 12384 | 11633 | 11652 | 11477 | 92%
|
29
25
|
|
30
|
-
|
31
|
-
-------
|
26
|
+
Please note than benchmark was taken in summer of 2012, since then things may have changed.
|
32
27
|
|
33
|
-
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### In Rails 3.1+
|
31
|
+
add `gem 'csso-rails'` to your gemfile, and that’s it!
|
32
|
+
|
33
|
+
Upon including it becomes the default compressor even if sass is included too.
|
34
|
+
More explicit way – set in config: `config.assets.css_compressor = :csso`.
|
35
|
+
|
36
|
+
|
37
|
+
### In Plain Ruby
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
require 'rubygems'
|
41
|
+
gem 'csso-rails'
|
42
|
+
require 'csso'
|
43
|
+
puts Csso.optimize("a{ color: #FF0000; }") # produces "a{color:red}"
|
44
|
+
```
|
45
|
+
|
46
|
+
In _maniac mode_(`Csso.optimize(css, true)`, default for pipeline) CSS is processed several times until it stops getting lighter (there're cases when original csso does not do all optimizations for no reason).
|
47
|
+
|
48
|
+
### In Command Line
|
49
|
+
|
50
|
+
ruby_csso non_optimized.css > optimized.css
|
51
|
+
|
52
|
+
|
53
|
+
## MIT-License
|
54
|
+
|
55
|
+
> Original CSSO code - Copyright (C) 2011 by Sergey Kryzhanovsky.
|
56
|
+
>
|
34
57
|
> ruby gem - Copyright(C) 2012 Vasily Fedoseyev
|
35
58
|
|
36
59
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -49,4 +72,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
49
72
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
50
73
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
51
74
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
52
|
-
THE SOFTWARE.
|
75
|
+
THE SOFTWARE.
|
data/bin/ruby_csso
CHANGED
data/csso-rails.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
24
|
s.require_paths = ["lib"]
|
25
25
|
|
26
|
-
s.add_dependency "therubyracer", "
|
26
|
+
s.add_dependency "therubyracer", ">= 0.10.2"
|
27
27
|
s.add_dependency "commonjs", "~> 0.2.0"
|
28
28
|
|
29
29
|
s.add_development_dependency "rake"
|
data/lib/csso-rails.rb
CHANGED
data/lib/csso.rb
CHANGED
@@ -25,11 +25,11 @@ module Csso
|
|
25
25
|
Optimizer.new.optimize(css, structural_optimization)
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
|
-
|
28
|
+
|
29
|
+
|
30
30
|
class Optimizer
|
31
31
|
include CallJS
|
32
|
-
|
32
|
+
|
33
33
|
def optimize(css, structural_optimization=true)
|
34
34
|
return nil unless css.is_a?(String)
|
35
35
|
return css if css.size <= 3
|
@@ -38,5 +38,5 @@ module Csso
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
42
|
-
end
|
41
|
+
|
42
|
+
end
|
data/lib/csso/js/compressor.js
CHANGED
@@ -163,11 +163,14 @@ TRBL.prototype.getString = function() {
|
|
163
163
|
|
164
164
|
return r;
|
165
165
|
};
|
166
|
+
|
166
167
|
function CSSOCompressor() {}
|
167
168
|
|
168
169
|
CSSOCompressor.prototype.init = function() {
|
169
170
|
this.props = {};
|
170
171
|
this.shorts = {};
|
172
|
+
this.shorts2 = {};
|
173
|
+
|
171
174
|
this.ccrules = {}; // clean comment rules — special case to resolve ambiguity
|
172
175
|
this.crules = {}; // compress rules
|
173
176
|
this.prules = {}; // prepare rules
|
@@ -189,6 +192,10 @@ CSSOCompressor.prototype.init = function() {
|
|
189
192
|
this.initRules(this.rjrules, this.defRJCfg);
|
190
193
|
this.initRules(this.rrrules, this.defRRCfg);
|
191
194
|
this.initRules(this.frules, this.defFCfg);
|
195
|
+
|
196
|
+
this.shortGroupID = 0;
|
197
|
+
this.lastShortGroupID = 0;
|
198
|
+
this.lastShortSelector = 0;
|
192
199
|
};
|
193
200
|
|
194
201
|
CSSOCompressor.prototype.initRules = function(r, cfg) {
|
@@ -216,6 +223,7 @@ CSSOCompressor.prototype.defCCfg = {
|
|
216
223
|
'cleanWhitespace': 1,
|
217
224
|
'cleanDecldelim': 1,
|
218
225
|
'compressNumber': 1,
|
226
|
+
'cleanUnary': 1,
|
219
227
|
'compressColor': 1,
|
220
228
|
'compressDimension': 1,
|
221
229
|
'compressString': 1,
|
@@ -269,6 +277,7 @@ CSSOCompressor.prototype.order = [
|
|
269
277
|
'cleanComment',
|
270
278
|
'cleanWhitespace',
|
271
279
|
'compressNumber',
|
280
|
+
'cleanUnary',
|
272
281
|
'compressColor',
|
273
282
|
'compressDimension',
|
274
283
|
'compressString',
|
@@ -301,6 +310,9 @@ CSSOCompressor.prototype.profile = {
|
|
301
310
|
'compressNumber': {
|
302
311
|
'number': 1
|
303
312
|
},
|
313
|
+
'cleanUnary': {
|
314
|
+
'unary': 1
|
315
|
+
},
|
304
316
|
'compressColor': {
|
305
317
|
'vhash': 1,
|
306
318
|
'funktion': 1,
|
@@ -411,6 +423,7 @@ CSSOCompressor.prototype.compress = function(tree, ro) {
|
|
411
423
|
|
412
424
|
if (!ro) { // restructure ON
|
413
425
|
xs = this.copyArray(x);
|
426
|
+
x = this.walk(this.rjrules, x, '/0');
|
414
427
|
this.disjoin(x);
|
415
428
|
x = this.walk(this.msrules, x, '/0');
|
416
429
|
x = this.walk(this.csrules, x, '/0');
|
@@ -446,10 +459,12 @@ CSSOCompressor.prototype.injectInfo = function(token) {
|
|
446
459
|
|
447
460
|
CSSOCompressor.prototype.disjoin = function(container) {
|
448
461
|
var t, s, r, sr;
|
462
|
+
|
449
463
|
for (var i = container.length - 1; i > -1; i--) {
|
450
464
|
t = container[i];
|
451
465
|
if (t && Array.isArray(t)) {
|
452
466
|
if (t[1] === 'ruleset') {
|
467
|
+
t[0].shortGroupID = this.shortGroupID++;
|
453
468
|
s = t[2];
|
454
469
|
if (s.length > 3) {
|
455
470
|
sr = s.slice(0, 2);
|
@@ -726,7 +741,7 @@ CSSOCompressor.prototype.cleanDecldelim = function(token) {
|
|
726
741
|
return token;
|
727
742
|
};
|
728
743
|
|
729
|
-
CSSOCompressor.prototype.compressNumber = function(token) {
|
744
|
+
CSSOCompressor.prototype.compressNumber = function(token, rule, container, i) {
|
730
745
|
var x = token[2];
|
731
746
|
|
732
747
|
if (/^0*/.test(x)) x = x.replace(/^0+/, '');
|
@@ -739,6 +754,12 @@ CSSOCompressor.prototype.compressNumber = function(token) {
|
|
739
754
|
return token;
|
740
755
|
};
|
741
756
|
|
757
|
+
CSSOCompressor.prototype.cleanUnary = function(token, rule, container, i) {
|
758
|
+
var next = container[i + 1];
|
759
|
+
if (next && next[1] === 'number' && next[2] === '0') return null;
|
760
|
+
return token;
|
761
|
+
};
|
762
|
+
|
742
763
|
CSSOCompressor.prototype.compressColor = function(token, rule, container, i) {
|
743
764
|
switch(rule) {
|
744
765
|
case 'vhash':
|
@@ -818,9 +839,9 @@ CSSOCompressor.prototype.compressString = function(token, rule, container) {
|
|
818
839
|
if (c === '\\' && s.charAt(i + 1) === '\n') i++;
|
819
840
|
else r += c;
|
820
841
|
}
|
821
|
-
if (container[1] === 'attrib' && /^('|")[a-zA-Z0-9]*('|")$/.test(r)) {
|
822
|
-
r = r.substring(1, r.length - 1);
|
823
|
-
}
|
842
|
+
// if (container[1] === 'attrib' && /^('|")[a-zA-Z0-9]*('|")$/.test(r)) {
|
843
|
+
// r = r.substring(1, r.length - 1);
|
844
|
+
// }
|
824
845
|
if (s.length !== r.length) return [{}, 'string', r];
|
825
846
|
};
|
826
847
|
|
@@ -919,10 +940,12 @@ CSSOCompressor.prototype.markShorthands = function(token, rule, container, j, pa
|
|
919
940
|
freeze = false,
|
920
941
|
freezeID = 'fake';
|
921
942
|
}
|
922
|
-
var x, p, v, imp, s, key,
|
923
|
-
pre = this.pathUp(path) + '/' + (freeze ? '&' + freezeID + '&' : '') + selector + '/'
|
943
|
+
var x, p, v, imp, s, key, sh,
|
944
|
+
pre = this.pathUp(path) + '/' + (freeze ? '&' + freezeID + '&' : '') + selector + '/',
|
945
|
+
createNew, shortsI, shortGroupID = container[0].shortGroupID;
|
924
946
|
|
925
947
|
for (var i = token.length - 1; i > -1; i--) {
|
948
|
+
createNew = true;
|
926
949
|
x = token[i];
|
927
950
|
if (x[1] === 'declaration') {
|
928
951
|
v = x[3];
|
@@ -931,30 +954,48 @@ CSSOCompressor.prototype.markShorthands = function(token, rule, container, j, pa
|
|
931
954
|
x[0].id = path + '/' + i;
|
932
955
|
if (p in TRBL.props) {
|
933
956
|
key = pre + TRBL.extractMain(p);
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
957
|
+
|
958
|
+
var shorts = this.shorts2[key] || [];
|
959
|
+
shortsI = shorts.length === 0 ? 0 : shorts.length - 1;
|
960
|
+
|
961
|
+
if (!this.lastShortSelector || selector === this.lastShortSelector || shortGroupID === this.lastShortGroupID) {
|
962
|
+
if (shorts.length) {
|
963
|
+
sh = shorts[shortsI];
|
964
|
+
if (imp && !sh.imp) sh.invalid = true;
|
965
|
+
createNew = false;
|
966
|
+
}
|
967
|
+
}
|
968
|
+
|
969
|
+
if (createNew) {
|
938
970
|
x[0].replaceByShort = true;
|
939
|
-
x[0].shorthandKey = key;
|
971
|
+
x[0].shorthandKey = { key: key, i: shortsI };
|
972
|
+
sh = new TRBL(p, imp);
|
973
|
+
shorts.push(sh);
|
940
974
|
}
|
941
|
-
|
942
|
-
|
943
|
-
this.shorts[key] = s;
|
975
|
+
|
976
|
+
if (!sh.invalid) {
|
944
977
|
x[0].removeByShort = true;
|
945
|
-
x[0].shorthandKey = key;
|
978
|
+
x[0].shorthandKey = { key: key, i: shortsI };
|
979
|
+
sh.add(p, v[0].s, v.slice(2), imp);
|
946
980
|
}
|
981
|
+
|
982
|
+
this.shorts2[key] = shorts;
|
983
|
+
|
984
|
+
this.lastShortSelector = selector;
|
985
|
+
this.lastShortGroupID = shortGroupID;
|
947
986
|
}
|
948
987
|
}
|
949
988
|
}
|
989
|
+
|
990
|
+
|
950
991
|
return token;
|
951
992
|
};
|
952
993
|
|
953
994
|
CSSOCompressor.prototype.cleanShorthands = function(token) {
|
954
995
|
if (token[0].removeByShort || token[0].replaceByShort) {
|
955
|
-
var s, t;
|
996
|
+
var s, t, sKey = token[0].shorthandKey;
|
956
997
|
|
957
|
-
s = this.
|
998
|
+
s = this.shorts2[sKey.key][sKey.i];
|
958
999
|
|
959
1000
|
if (!s.invalid && s.isOkToMinimize()) {
|
960
1001
|
if (token[0].replaceByShort) {
|
@@ -966,6 +1007,12 @@ CSSOCompressor.prototype.cleanShorthands = function(token) {
|
|
966
1007
|
}
|
967
1008
|
};
|
968
1009
|
|
1010
|
+
CSSOCompressor.prototype.dontRestructure = {
|
1011
|
+
'src': 1, // https://github.com/afelix/csso/issues/50
|
1012
|
+
'clip': 1, // https://github.com/afelix/csso/issues/57
|
1013
|
+
'display': 1 // https://github.com/afelix/csso/issues/71
|
1014
|
+
};
|
1015
|
+
|
969
1016
|
CSSOCompressor.prototype.restructureBlock = function(token, rule, container, j, path) {
|
970
1017
|
if (container[1] === 'ruleset') {
|
971
1018
|
var props = this.props,
|
@@ -984,6 +1031,7 @@ CSSOCompressor.prototype.restructureBlock = function(token, rule, container, j,
|
|
984
1031
|
pseudoID = 'fake',
|
985
1032
|
sg = {};
|
986
1033
|
}
|
1034
|
+
|
987
1035
|
var x, p, v, imp, t,
|
988
1036
|
pre = this.pathUp(path) + '/' + selector + '/',
|
989
1037
|
ppre;
|
@@ -996,7 +1044,7 @@ CSSOCompressor.prototype.restructureBlock = function(token, rule, container, j,
|
|
996
1044
|
p = x[2][0].s;
|
997
1045
|
ppre = this.buildPPre(pre, p, v, x, freeze);
|
998
1046
|
x[0].id = path + '/' + i;
|
999
|
-
if (p
|
1047
|
+
if (!this.dontRestructure[p] && (t = props[ppre])) {
|
1000
1048
|
if ((isPseudo && freezeID === t.freezeID) || // pseudo from equal selectors group
|
1001
1049
|
(!isPseudo && pseudoID === t.pseudoID) || // not pseudo from equal pseudo signature group
|
1002
1050
|
(isPseudo && pseudoID === t.pseudoID && this.hashInHash(sg, t.sg))) { // pseudo from covered selectors group
|
@@ -1105,7 +1153,7 @@ CSSOCompressor.prototype.nlTable = {
|
|
1105
1153
|
|
1106
1154
|
CSSOCompressor.prototype.needless = function(name, props, pre, imp, v, d, freeze) {
|
1107
1155
|
var hack = name.charAt(0);
|
1108
|
-
if (hack === '*' || hack === '_') name = name.substr(1);
|
1156
|
+
if (hack === '*' || hack === '_' || hack === '$') name = name.substr(1);
|
1109
1157
|
else if (hack === '/' && name.charAt(1) === '/') {
|
1110
1158
|
hack = '//';
|
1111
1159
|
name = name.substr(2);
|
@@ -1118,6 +1166,7 @@ CSSOCompressor.prototype.needless = function(name, props, pre, imp, v, d, freeze
|
|
1118
1166
|
|
1119
1167
|
var prop = name.substr(vendor.length),
|
1120
1168
|
x, t, ppre;
|
1169
|
+
|
1121
1170
|
if (prop in this.nlTable) {
|
1122
1171
|
x = this.nlTable[prop];
|
1123
1172
|
for (i = 0; i < x.length; i++) {
|
@@ -1138,9 +1187,11 @@ CSSOCompressor.prototype.rejoinRuleset = function(token, rule, container, i) {
|
|
1138
1187
|
if (!tb.length) return null;
|
1139
1188
|
|
1140
1189
|
if (ps.length && pb.length) {
|
1190
|
+
if (token[1] !== p[1]) return;
|
1141
1191
|
// try to join by selectors
|
1142
1192
|
ph = this.getHash(ps);
|
1143
1193
|
th = this.getHash(ts);
|
1194
|
+
|
1144
1195
|
if (this.equalHash(th, ph)) {
|
1145
1196
|
p[3] = p[3].concat(token[3].splice(2));
|
1146
1197
|
return null;
|
@@ -1203,8 +1254,10 @@ CSSOCompressor.prototype.restructureRuleset = function(token, rule, container, i
|
|
1203
1254
|
if (!tb.length) return null;
|
1204
1255
|
|
1205
1256
|
if (ps.length && pb.length) {
|
1257
|
+
if (token[1] !== p[1]) return;
|
1206
1258
|
// try to join by properties
|
1207
1259
|
r = this.analyze(token, p);
|
1260
|
+
|
1208
1261
|
if (r.eq.length && (r.ne1.length || r.ne2.length)) {
|
1209
1262
|
if (r.ne1.length && !r.ne2.length) { // p in token
|
1210
1263
|
var ns = token[2].slice(2), // TODO: copypaste
|
@@ -1275,9 +1328,12 @@ CSSOCompressor.prototype.cleanSelector = function(token) {
|
|
1275
1328
|
};
|
1276
1329
|
|
1277
1330
|
CSSOCompressor.prototype.analyze = function(r1, r2) {
|
1331
|
+
var r = { eq: [], ne1: [], ne2: [] };
|
1332
|
+
|
1333
|
+
if (r1[1] !== r2[1]) return r;
|
1334
|
+
|
1278
1335
|
var b1 = r1[3], b2 = r2[3],
|
1279
1336
|
d1 = b1.slice(2), d2 = b2.slice(2),
|
1280
|
-
r = { eq: [], ne1: [], ne2: [] },
|
1281
1337
|
h1, h2, i, x;
|
1282
1338
|
|
1283
1339
|
h1 = this.getHash(d1);
|
data/lib/csso/js/csso.js
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
var fs = require('fs'),
|
2
|
+
print = require('util').print,
|
3
|
+
csso = require('./cssoapi.js'),
|
4
|
+
src, x;
|
5
|
+
|
6
|
+
var args = process.argv.slice(2),
|
7
|
+
opts = args.length ? getOpts(args, [
|
8
|
+
'-v', '--version',
|
9
|
+
'-h', '--help',
|
10
|
+
'-dp', '--parser',
|
11
|
+
'-off', '--restructure-off'
|
12
|
+
], [
|
13
|
+
'-r', '--rule',
|
14
|
+
'-i', '--input',
|
15
|
+
'-o', '--output'
|
16
|
+
]) : null,
|
17
|
+
single = opts && opts.single,
|
18
|
+
pairs = opts && opts.pairs,
|
19
|
+
other = opts && opts.other,
|
20
|
+
ro = single && single.contains(['-off', '--restructure-off']),
|
21
|
+
inFile = (pairs && (pairs['-i'] || pairs['--input'])) || (other && other[0]),
|
22
|
+
outFile = (pairs && (pairs['-o'] || pairs['--output'])) || (other && other[1]),
|
23
|
+
rule = pairs && (pairs['-r'] || pairs['--rule']) || 'stylesheet';
|
24
|
+
|
25
|
+
if (single && single.contains(['-v', '--version'])) {
|
26
|
+
printFile('VERSION');
|
27
|
+
} else if (!inFile || !opts || (single && single.contains(['-h', '--help'])) || other.length > 2) {
|
28
|
+
printFile('USAGE');
|
29
|
+
} else {
|
30
|
+
src = fs.readFileSync(inFile).toString().trim();
|
31
|
+
|
32
|
+
if (single.contains(['-dp', '--parser'])) csso.printTree(csso.cleanInfo(csso.parse(src, rule)));
|
33
|
+
else {
|
34
|
+
if (!outFile) print(csso.justDoIt(src, ro));
|
35
|
+
else fs.writeFileSync(outFile, csso.justDoIt(src, ro));
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
// Utils
|
40
|
+
|
41
|
+
function getOpts(argv, o_single, o_pairs) {
|
42
|
+
var opts = { single : [], pairs : {}, other : [] },
|
43
|
+
arg,
|
44
|
+
i = 0;
|
45
|
+
|
46
|
+
for (; i < argv.length;) {
|
47
|
+
arg = argv[i];
|
48
|
+
if (o_single && o_single.indexOf(arg) !== -1 && (!o_pairs || o_pairs.indexOf(arg) === -1)) {
|
49
|
+
opts.single.push(arg);
|
50
|
+
} else if (o_pairs && o_pairs.indexOf(arg) !== -1 && (!o_single || o_single.indexOf(arg) === -1)) {
|
51
|
+
opts.pairs[arg] = argv[++i];
|
52
|
+
} else opts.other.push(arg);
|
53
|
+
i++;
|
54
|
+
}
|
55
|
+
|
56
|
+
opts.single.contains = function(value) {
|
57
|
+
if (typeof value === 'string') {
|
58
|
+
return this.indexOf(value) !== -1;
|
59
|
+
} else {
|
60
|
+
for (var i = 0; i < value.length; i++) if (this.indexOf(value[i]) !== -1) return true;
|
61
|
+
}
|
62
|
+
return false;
|
63
|
+
};
|
64
|
+
|
65
|
+
return opts;
|
66
|
+
}
|
67
|
+
|
68
|
+
function printFile(filename) {
|
69
|
+
print(fs.readFileSync(__dirname.slice(0, __dirname.lastIndexOf('/')) + '/' + filename).toString());
|
70
|
+
}
|
data/lib/csso/js/parser.js
CHANGED
@@ -502,7 +502,7 @@ CSSOParser.prototype.declaration = function() {
|
|
502
502
|
};
|
503
503
|
CSSOParser.prototype.filtern = function() {
|
504
504
|
var _b_;
|
505
|
-
if (_b_ = this.$()._o('.-filter','._filter','.*filter','.-ms-filter','.filter')._()) {
|
505
|
+
if (_b_ = this.$()._o('.-filter','.$filter','._filter','.*filter','.-ms-filter','.filter')._()) {
|
506
506
|
return [this._info(), 'ident', _b_[0]];
|
507
507
|
}
|
508
508
|
};
|
@@ -767,7 +767,7 @@ CSSOParser.prototype.mw = function() {
|
|
767
767
|
CSSOParser.prototype.mnumber = function() {
|
768
768
|
var s = this._src,
|
769
769
|
sl = s.length,
|
770
|
-
f = this._gi() + 1, c, i,
|
770
|
+
f = this._gi() + 1, c, i, v = '',
|
771
771
|
n0 = '', d = '', n1 = '';
|
772
772
|
for (i = f; i < sl; i++) {
|
773
773
|
c = s.charAt(i);
|
@@ -794,7 +794,7 @@ CSSOParser.prototype.mident = function() {
|
|
794
794
|
f = this._gi() + 1, i = f, v = '', c, n;
|
795
795
|
if (s.charAt(i) === '-') v = '-', i++; // special case
|
796
796
|
c = s.charAt(i); n = s.charAt(i + 1);
|
797
|
-
if (/^[
|
797
|
+
if (/^[_$a-zA-Z*]$/.test(c)) v += c; // first char
|
798
798
|
else if (c === '\\') {
|
799
799
|
v += c;
|
800
800
|
if (n) v += n, i++;
|
data/lib/csso/loader.rb
CHANGED
@@ -20,13 +20,13 @@ module Csso
|
|
20
20
|
@js_path = js_path || Pathname(__FILE__).dirname.join('js').to_s
|
21
21
|
@cxt = V8::Context.new
|
22
22
|
@environment = ModifiedEnvironment.new(@cxt, :path => @js_path)
|
23
|
-
|
23
|
+
|
24
24
|
[Util, Path, Fs].each do |native|
|
25
25
|
@environment.native(native.to_s.downcase, native.new)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
[Process, Console].each do|replace|
|
29
|
-
@cxt[replace.to_s.downcase] = replace.new
|
29
|
+
@cxt[replace.to_s.downcase] = replace.new
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -71,4 +71,4 @@ module Csso
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
74
|
-
end
|
74
|
+
end
|
data/lib/csso/rails.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require "action_controller/railtie"
|
2
2
|
|
3
3
|
module Csso
|
4
|
-
|
4
|
+
|
5
5
|
COMPRESSOR_SYM = :csso
|
6
|
-
|
6
|
+
|
7
7
|
class Railtie < ::Rails::Railtie
|
8
8
|
initializer "csso.environment", :after => "sprockets.environment" do
|
9
9
|
CssCompressor.register
|
@@ -15,19 +15,19 @@ module Csso
|
|
15
15
|
app.config.assets.css_compressor = :csso
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
class CssCompressor
|
22
22
|
def compress(css)
|
23
23
|
require 'csso'
|
24
24
|
#TODO: settings?
|
25
25
|
Csso.optimize(css, true)
|
26
|
-
end
|
27
|
-
|
26
|
+
end
|
27
|
+
|
28
28
|
def self.register
|
29
29
|
Sprockets::Compressors.register_css_compressor(COMPRESSOR_SYM, 'Csso::CssCompressor', :default => true)
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
33
|
-
end
|
32
|
+
|
33
|
+
end
|
data/lib/csso/version.rb
CHANGED
data/spec/csso/csso_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Csso do
|
4
|
-
|
4
|
+
|
5
5
|
it "should optimize css" do
|
6
6
|
subject.optimize("a {\ncolor: white; }").should == "a{color:#fff}"
|
7
7
|
end
|
@@ -9,20 +9,20 @@ describe Csso do
|
|
9
9
|
it "should optimize structure" do
|
10
10
|
subject.optimize("a {\ncolor: white; } a{color: red;}").should == "a{color:red}"
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
it "should optimize structure" do
|
14
14
|
pending "original csso is a bit broken at the moment"
|
15
15
|
# FIXME: csso produces "a{color:#fff;color:red}" on this :(
|
16
16
|
subject.optimize("a {\ncolor: white; } a{color: #ff0000;}").should == "a{color:red}"
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it "should optimize structure in maniac mode" do
|
20
20
|
subject.optimize("a {\ncolor: white; } a{color: #ff0000;}", true).should == "a{color:red}"
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it 'should produce no error on empty input' do
|
24
24
|
subject.optimize(nil).should == nil
|
25
25
|
subject.optimize("").should == ""
|
26
26
|
end
|
27
|
-
|
28
|
-
end
|
27
|
+
|
28
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csso-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,27 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: therubyracer
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.10.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.10.2
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: commonjs
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: 0.2.0
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.2.0
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: rake
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: rspec
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
@@ -54,7 +69,12 @@ dependencies:
|
|
54
69
|
version: '2.0'
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.0'
|
58
78
|
description: Invoke the CSSO from Ruby
|
59
79
|
email:
|
60
80
|
- vasilyfedoseyev@gmail.com
|
@@ -74,6 +94,7 @@ files:
|
|
74
94
|
- lib/csso-rails.rb
|
75
95
|
- lib/csso.rb
|
76
96
|
- lib/csso/js/compressor.js
|
97
|
+
- lib/csso/js/csso.js
|
77
98
|
- lib/csso/js/cssoapi.js
|
78
99
|
- lib/csso/js/parser.js
|
79
100
|
- lib/csso/js/translator.js
|
@@ -96,19 +117,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
117
|
- - ! '>='
|
97
118
|
- !ruby/object:Gem::Version
|
98
119
|
version: '0'
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
hash: 2273465511458410944
|
99
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
124
|
none: false
|
101
125
|
requirements:
|
102
126
|
- - ! '>='
|
103
127
|
- !ruby/object:Gem::Version
|
104
128
|
version: '0'
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
hash: 2273465511458410944
|
105
132
|
requirements: []
|
106
133
|
rubyforge_project: csso-rails
|
107
|
-
rubygems_version: 1.8.
|
134
|
+
rubygems_version: 1.8.24
|
108
135
|
signing_key:
|
109
136
|
specification_version: 3
|
110
137
|
summary: CSS Stylesheet optimizer/compressor for Rails
|
111
138
|
test_files:
|
112
139
|
- spec/csso/csso_spec.rb
|
113
140
|
- spec/spec_helper.rb
|
114
|
-
has_rdoc:
|