csso-rails 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|