ruby-clean-css 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +3 -0
- data/EXAMPLE.md +25 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +30 -0
- data/LICENSE +19 -0
- data/README.md +106 -0
- data/lib/javascript/clean-css/.gitignore +4 -0
- data/lib/javascript/clean-css/.jshintignore +3 -0
- data/lib/javascript/clean-css/.jshintrc +14 -0
- data/lib/javascript/clean-css/.travis.yml +11 -0
- data/lib/javascript/clean-css/History.md +556 -0
- data/lib/javascript/clean-css/LICENSE +19 -0
- data/lib/javascript/clean-css/README.md +218 -0
- data/lib/javascript/clean-css/bin/cleancss +157 -0
- data/lib/javascript/clean-css/index.js +1 -0
- data/lib/javascript/clean-css/lib/clean.js +426 -0
- data/lib/javascript/clean-css/lib/colors/hsl-to-hex.js +64 -0
- data/lib/javascript/clean-css/lib/colors/long-to-short-hex.js +12 -0
- data/lib/javascript/clean-css/lib/colors/rgb-to-hex.js +14 -0
- data/lib/javascript/clean-css/lib/colors/shortener.js +174 -0
- data/lib/javascript/clean-css/lib/images/url-rebase.js +32 -0
- data/lib/javascript/clean-css/lib/images/url-rewriter.js +60 -0
- data/lib/javascript/clean-css/lib/imports/inliner.js +319 -0
- data/lib/javascript/clean-css/lib/properties/optimizer.js +276 -0
- data/lib/javascript/clean-css/lib/properties/override-compactor.js +116 -0
- data/lib/javascript/clean-css/lib/properties/processable.js +859 -0
- data/lib/javascript/clean-css/lib/properties/scanner.js +20 -0
- data/lib/javascript/clean-css/lib/properties/shorthand-compactor.js +244 -0
- data/lib/javascript/clean-css/lib/properties/token.js +184 -0
- data/lib/javascript/clean-css/lib/properties/validator.js +140 -0
- data/lib/javascript/clean-css/lib/selectors/empty-removal.js +30 -0
- data/lib/javascript/clean-css/lib/selectors/optimizer.js +341 -0
- data/lib/javascript/clean-css/lib/selectors/tokenizer.js +168 -0
- data/lib/javascript/clean-css/lib/text/comments.js +83 -0
- data/lib/javascript/clean-css/lib/text/escape-store.js +32 -0
- data/lib/javascript/clean-css/lib/text/expressions.js +73 -0
- data/lib/javascript/clean-css/lib/text/free.js +26 -0
- data/lib/javascript/clean-css/lib/text/name-quotes.js +37 -0
- data/lib/javascript/clean-css/lib/text/quote-scanner.js +91 -0
- data/lib/javascript/clean-css/lib/text/splitter.js +35 -0
- data/lib/javascript/clean-css/lib/text/urls.js +41 -0
- data/lib/javascript/clean-css/package.json +50 -0
- data/lib/javascript/clean-css/test/batch-test.js +56 -0
- data/lib/javascript/clean-css/test/bench.js +11 -0
- data/lib/javascript/clean-css/test/binary-test.js +323 -0
- data/lib/javascript/clean-css/test/data-bench/_partial.css +1 -0
- data/lib/javascript/clean-css/test/data-bench/complex.css +4 -0
- data/lib/javascript/clean-css/test/data/129-assets/assets/ui.css +2 -0
- data/lib/javascript/clean-css/test/data/129-assets/components/bootstrap/css/bootstrap.css +3 -0
- data/lib/javascript/clean-css/test/data/129-assets/components/bootstrap/images/glyphs.gif +0 -0
- data/lib/javascript/clean-css/test/data/129-assets/components/jquery-ui/css/style.css +6 -0
- data/lib/javascript/clean-css/test/data/129-assets/components/jquery-ui/images/next.gif +0 -0
- data/lib/javascript/clean-css/test/data/129-assets/components/jquery-ui/images/prev.gif +0 -0
- data/lib/javascript/clean-css/test/data/960-min.css +125 -0
- data/lib/javascript/clean-css/test/data/960.css +602 -0
- data/lib/javascript/clean-css/test/data/big-min.css +2984 -0
- data/lib/javascript/clean-css/test/data/big.css +13794 -0
- data/lib/javascript/clean-css/test/data/blueprint-min.css +245 -0
- data/lib/javascript/clean-css/test/data/blueprint.css +556 -0
- data/lib/javascript/clean-css/test/data/charset-mixed-with-fonts-min.css +3 -0
- data/lib/javascript/clean-css/test/data/charset-mixed-with-fonts.css +14 -0
- data/lib/javascript/clean-css/test/data/font-awesome-ie7-min.css +392 -0
- data/lib/javascript/clean-css/test/data/font-awesome-ie7.css +1203 -0
- data/lib/javascript/clean-css/test/data/font-awesome-min.css +319 -0
- data/lib/javascript/clean-css/test/data/font-awesome.css +540 -0
- data/lib/javascript/clean-css/test/data/imports-min.css +5 -0
- data/lib/javascript/clean-css/test/data/imports.css +4 -0
- data/lib/javascript/clean-css/test/data/issue-117-snippet-min.css +3 -0
- data/lib/javascript/clean-css/test/data/issue-117-snippet.css +19 -0
- data/lib/javascript/clean-css/test/data/issue-159-snippet-min.css +7 -0
- data/lib/javascript/clean-css/test/data/issue-159-snippet.css +7 -0
- data/lib/javascript/clean-css/test/data/issue-192-min.css +1 -0
- data/lib/javascript/clean-css/test/data/issue-192.css +8 -0
- data/lib/javascript/clean-css/test/data/issue-198-min.css +3 -0
- data/lib/javascript/clean-css/test/data/issue-198.css +4 -0
- data/lib/javascript/clean-css/test/data/issue-232-min.css +2 -0
- data/lib/javascript/clean-css/test/data/issue-232.css +17 -0
- data/lib/javascript/clean-css/test/data/issue-241-min.css +2 -0
- data/lib/javascript/clean-css/test/data/issue-241.css +2 -0
- data/lib/javascript/clean-css/test/data/issue-304-min.css +1 -0
- data/lib/javascript/clean-css/test/data/issue-304.css +4 -0
- data/lib/javascript/clean-css/test/data/issue-305-min.css +1 -0
- data/lib/javascript/clean-css/test/data/issue-305.css +3 -0
- data/lib/javascript/clean-css/test/data/issue-308-min.css +1 -0
- data/lib/javascript/clean-css/test/data/issue-308.css +5 -0
- data/lib/javascript/clean-css/test/data/issue-312-min.css +1 -0
- data/lib/javascript/clean-css/test/data/issue-312.css +7 -0
- data/lib/javascript/clean-css/test/data/issue-337-min.css +1 -0
- data/lib/javascript/clean-css/test/data/issue-337.css +4 -0
- data/lib/javascript/clean-css/test/data/line-breaks-in-attributes-min.css +2 -0
- data/lib/javascript/clean-css/test/data/line-breaks-in-attributes.css +8 -0
- data/lib/javascript/clean-css/test/data/partials-absolute/base.css +3 -0
- data/lib/javascript/clean-css/test/data/partials-absolute/base2.css +1 -0
- data/lib/javascript/clean-css/test/data/partials-absolute/extra/sub.css +3 -0
- data/lib/javascript/clean-css/test/data/partials-relative/base.css +3 -0
- data/lib/javascript/clean-css/test/data/partials-relative/extra/included.css +1 -0
- data/lib/javascript/clean-css/test/data/partials/comment.css +2 -0
- data/lib/javascript/clean-css/test/data/partials/extra/down.gif +0 -0
- data/lib/javascript/clean-css/test/data/partials/extra/four.css +3 -0
- data/lib/javascript/clean-css/test/data/partials/extra/three.css +1 -0
- data/lib/javascript/clean-css/test/data/partials/five.css +1 -0
- data/lib/javascript/clean-css/test/data/partials/four.css +1 -0
- data/lib/javascript/clean-css/test/data/partials/one.css +1 -0
- data/lib/javascript/clean-css/test/data/partials/three.css +1 -0
- data/lib/javascript/clean-css/test/data/partials/two.css +5 -0
- data/lib/javascript/clean-css/test/data/reset-min.css +12 -0
- data/lib/javascript/clean-css/test/data/reset.css +64 -0
- data/lib/javascript/clean-css/test/data/sample1-min.css +4 -0
- data/lib/javascript/clean-css/test/data/sample1.css +12 -0
- data/lib/javascript/clean-css/test/data/unsupported/selectors-ie7.css +20 -0
- data/lib/javascript/clean-css/test/data/unsupported/selectors-ie8.css +17 -0
- data/lib/javascript/clean-css/test/module-test.js +185 -0
- data/lib/javascript/clean-css/test/protocol-imports-test.js +409 -0
- data/lib/javascript/clean-css/test/text/splitter-test.js +20 -0
- data/lib/javascript/clean-css/test/unit-test.js +2071 -0
- data/lib/ruby-clean-css.rb +6 -0
- data/lib/ruby-clean-css/compressor.rb +142 -0
- data/lib/ruby-clean-css/exports.rb +258 -0
- data/lib/ruby-clean-css/railtie.rb +27 -0
- data/lib/ruby-clean-css/sprockets.rb +19 -0
- data/lib/ruby-clean-css/version.rb +5 -0
- data/ruby-clean-css.gemspec +30 -0
- data/test/test_compressor.rb +84 -0
- metadata +203 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
var EscapeStore = require('./escape-store');
|
2
|
+
var QuoteScanner = require('./quote-scanner');
|
3
|
+
|
4
|
+
module.exports = function Comments(keepSpecialComments, keepBreaks, lineBreak) {
|
5
|
+
var comments = new EscapeStore('COMMENT');
|
6
|
+
|
7
|
+
return {
|
8
|
+
// Strip special comments (/*! ... */) by replacing them by a special marker
|
9
|
+
// for further restoring. Plain comments are removed. It's done by scanning data using
|
10
|
+
// String#indexOf scanning instead of regexps to speed up the process.
|
11
|
+
escape: function(data) {
|
12
|
+
var tempData = [];
|
13
|
+
var nextStart = 0;
|
14
|
+
var nextEnd = 0;
|
15
|
+
var cursor = 0;
|
16
|
+
var isQuotedAt = (function () {
|
17
|
+
var quoteMap = [];
|
18
|
+
new QuoteScanner(data).each(function (quotedString, _, startsAt) {
|
19
|
+
quoteMap.push([startsAt, startsAt + quotedString.length]);
|
20
|
+
});
|
21
|
+
|
22
|
+
return function (position) {
|
23
|
+
for (var i = 0, l = quoteMap.length; i < l; i++) {
|
24
|
+
if (quoteMap[i][0] < position && quoteMap[i][1] > position)
|
25
|
+
return true;
|
26
|
+
}
|
27
|
+
|
28
|
+
return false;
|
29
|
+
};
|
30
|
+
})();
|
31
|
+
|
32
|
+
for (; nextEnd < data.length;) {
|
33
|
+
nextStart = data.indexOf('/*', cursor);
|
34
|
+
if (nextStart == -1)
|
35
|
+
break;
|
36
|
+
if (isQuotedAt(nextStart)) {
|
37
|
+
tempData.push(data.substring(cursor, nextStart + 2));
|
38
|
+
cursor = nextStart + 2;
|
39
|
+
continue;
|
40
|
+
}
|
41
|
+
|
42
|
+
nextEnd = data.indexOf('*/', nextStart + 2);
|
43
|
+
if (nextEnd == -1)
|
44
|
+
break;
|
45
|
+
|
46
|
+
tempData.push(data.substring(cursor, nextStart));
|
47
|
+
if (data[nextStart + 2] == '!') {
|
48
|
+
// in case of special comments, replace them with a placeholder
|
49
|
+
var comment = data.substring(nextStart, nextEnd + 2);
|
50
|
+
var placeholder = comments.store(comment);
|
51
|
+
tempData.push(placeholder);
|
52
|
+
}
|
53
|
+
cursor = nextEnd + 2;
|
54
|
+
}
|
55
|
+
|
56
|
+
return tempData.length > 0 ?
|
57
|
+
tempData.join('') + data.substring(cursor, data.length) :
|
58
|
+
data;
|
59
|
+
},
|
60
|
+
|
61
|
+
restore: function(data) {
|
62
|
+
var restored = 0;
|
63
|
+
var breakSuffix = keepBreaks ? lineBreak : '';
|
64
|
+
|
65
|
+
return data.replace(new RegExp(comments.placeholderPattern + '(' + lineBreak + '| )?', 'g'), function(match, placeholder) {
|
66
|
+
restored++;
|
67
|
+
|
68
|
+
switch (keepSpecialComments) {
|
69
|
+
case '*':
|
70
|
+
return comments.restore(placeholder) + breakSuffix;
|
71
|
+
case 1:
|
72
|
+
case '1':
|
73
|
+
return restored == 1 ?
|
74
|
+
comments.restore(placeholder) + breakSuffix :
|
75
|
+
'';
|
76
|
+
case 0:
|
77
|
+
case '0':
|
78
|
+
return '';
|
79
|
+
}
|
80
|
+
});
|
81
|
+
}
|
82
|
+
};
|
83
|
+
};
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module.exports = function EscapeStore(placeholderRoot) {
|
2
|
+
placeholderRoot = 'ESCAPED_' + placeholderRoot + '_CLEAN_CSS';
|
3
|
+
|
4
|
+
var placeholderToData = {};
|
5
|
+
var dataToPlaceholder = {};
|
6
|
+
var count = 0;
|
7
|
+
var nextPlaceholder = function() {
|
8
|
+
return '__' + placeholderRoot + (count++) + '__';
|
9
|
+
};
|
10
|
+
var pattern = '(__' + placeholderRoot + '\\d{1,}__)';
|
11
|
+
|
12
|
+
return {
|
13
|
+
placeholderPattern: pattern,
|
14
|
+
|
15
|
+
placeholderRegExp: new RegExp(pattern, 'g'),
|
16
|
+
|
17
|
+
store: function(data) {
|
18
|
+
var placeholder = dataToPlaceholder[data];
|
19
|
+
if (!placeholder) {
|
20
|
+
placeholder = nextPlaceholder();
|
21
|
+
placeholderToData[placeholder] = data;
|
22
|
+
dataToPlaceholder[data] = placeholder;
|
23
|
+
}
|
24
|
+
|
25
|
+
return placeholder;
|
26
|
+
},
|
27
|
+
|
28
|
+
restore: function(placeholder) {
|
29
|
+
return placeholderToData[placeholder];
|
30
|
+
}
|
31
|
+
};
|
32
|
+
};
|
@@ -0,0 +1,73 @@
|
|
1
|
+
var EscapeStore = require('./escape-store');
|
2
|
+
|
3
|
+
module.exports = function Expressions() {
|
4
|
+
var expressions = new EscapeStore('EXPRESSION');
|
5
|
+
|
6
|
+
var findEnd = function(data, start) {
|
7
|
+
var end = start + 'expression'.length;
|
8
|
+
var level = 0;
|
9
|
+
var quoted = false;
|
10
|
+
|
11
|
+
while (true) {
|
12
|
+
var next = data[end++];
|
13
|
+
|
14
|
+
if (quoted) {
|
15
|
+
quoted = next != '\'' && next != '"';
|
16
|
+
} else {
|
17
|
+
quoted = next == '\'' || next == '"';
|
18
|
+
|
19
|
+
if (next == '(')
|
20
|
+
level++;
|
21
|
+
if (next == ')')
|
22
|
+
level--;
|
23
|
+
if (next == '}' && level == 1) {
|
24
|
+
end--;
|
25
|
+
level--;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
if (level === 0 && next == ')')
|
30
|
+
break;
|
31
|
+
if (!next) {
|
32
|
+
end = data.substring(0, end).lastIndexOf('}');
|
33
|
+
break;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
return end;
|
38
|
+
};
|
39
|
+
|
40
|
+
return {
|
41
|
+
// Escapes expressions by replacing them by a special
|
42
|
+
// marker for further restoring. It's done via string scanning
|
43
|
+
// instead of regexps to speed up the process.
|
44
|
+
escape: function(data) {
|
45
|
+
var nextStart = 0;
|
46
|
+
var nextEnd = 0;
|
47
|
+
var cursor = 0;
|
48
|
+
var tempData = [];
|
49
|
+
|
50
|
+
for (; nextEnd < data.length;) {
|
51
|
+
nextStart = data.indexOf('expression(', nextEnd);
|
52
|
+
if (nextStart == -1)
|
53
|
+
break;
|
54
|
+
|
55
|
+
nextEnd = findEnd(data, nextStart);
|
56
|
+
|
57
|
+
var expression = data.substring(nextStart, nextEnd);
|
58
|
+
var placeholder = expressions.store(expression);
|
59
|
+
tempData.push(data.substring(cursor, nextStart));
|
60
|
+
tempData.push(placeholder);
|
61
|
+
cursor = nextEnd;
|
62
|
+
}
|
63
|
+
|
64
|
+
return tempData.length > 0 ?
|
65
|
+
tempData.join('') + data.substring(cursor, data.length) :
|
66
|
+
data;
|
67
|
+
},
|
68
|
+
|
69
|
+
restore: function(data) {
|
70
|
+
return data.replace(expressions.placeholderRegExp, expressions.restore);
|
71
|
+
}
|
72
|
+
};
|
73
|
+
};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
(function() {
|
2
|
+
var EscapeStore = require('./escape-store');
|
3
|
+
var QuoteScanner = require('./quote-scanner');
|
4
|
+
|
5
|
+
var Free = function Free() {
|
6
|
+
this.matches = new EscapeStore('FREE_TEXT');
|
7
|
+
};
|
8
|
+
|
9
|
+
// Strip content tags by replacing them by the a special
|
10
|
+
// marker for further restoring. It's done via string scanning
|
11
|
+
// instead of regexps to speed up the process.
|
12
|
+
Free.prototype.escape = function(data) {
|
13
|
+
var self = this;
|
14
|
+
|
15
|
+
return new QuoteScanner(data).each(function(match, store) {
|
16
|
+
var placeholder = self.matches.store(match);
|
17
|
+
store.push(placeholder);
|
18
|
+
});
|
19
|
+
};
|
20
|
+
|
21
|
+
Free.prototype.restore = function(data) {
|
22
|
+
return data.replace(this.matches.placeholderRegExp, this.matches.restore);
|
23
|
+
};
|
24
|
+
|
25
|
+
module.exports = Free;
|
26
|
+
})();
|
@@ -0,0 +1,37 @@
|
|
1
|
+
(function() {
|
2
|
+
var QuoteScanner = require('./quote-scanner');
|
3
|
+
var PropertyScanner = require('../properties/scanner');
|
4
|
+
|
5
|
+
var NameQuotes = function NameQuotes() {};
|
6
|
+
|
7
|
+
var STRIPPABLE = /^['"][a-zA-Z][a-zA-Z\d\-_]+['"]$/;
|
8
|
+
|
9
|
+
var properties = [
|
10
|
+
'animation',
|
11
|
+
'-moz-animation',
|
12
|
+
'-o-animation',
|
13
|
+
'-webkit-animation',
|
14
|
+
'animation-name',
|
15
|
+
'-moz-animation-name',
|
16
|
+
'-o-animation-name',
|
17
|
+
'-webkit-animation-name',
|
18
|
+
'font',
|
19
|
+
'font-family'
|
20
|
+
];
|
21
|
+
|
22
|
+
NameQuotes.prototype.process = function(data) {
|
23
|
+
var scanner = new PropertyScanner(data);
|
24
|
+
|
25
|
+
return new QuoteScanner(data).each(function(match, store, cursor) {
|
26
|
+
var lastProperty = scanner.nextAt(cursor);
|
27
|
+
if (properties.indexOf(lastProperty) > -1) {
|
28
|
+
if (STRIPPABLE.test(match))
|
29
|
+
match = match.substring(1, match.length - 1);
|
30
|
+
}
|
31
|
+
|
32
|
+
store.push(match);
|
33
|
+
});
|
34
|
+
};
|
35
|
+
|
36
|
+
module.exports = NameQuotes;
|
37
|
+
})();
|
@@ -0,0 +1,91 @@
|
|
1
|
+
(function() {
|
2
|
+
var QuoteScanner = function QuoteScanner(data) {
|
3
|
+
this.data = data;
|
4
|
+
};
|
5
|
+
|
6
|
+
var findQuoteEnd = function(data, matched, cursor, oldCursor) {
|
7
|
+
var commentStartMark = '/*';
|
8
|
+
var commentEndMark = '*/';
|
9
|
+
var escapeMark = '\\';
|
10
|
+
var blockEndMark = '}';
|
11
|
+
var dataPrefix = data.substring(oldCursor, cursor);
|
12
|
+
var commentEndedAt = dataPrefix.lastIndexOf(commentEndMark, cursor);
|
13
|
+
var commentStartedAt = dataPrefix.lastIndexOf(commentStartMark, cursor);
|
14
|
+
var commentStarted = false;
|
15
|
+
|
16
|
+
if (commentEndedAt >= cursor && commentStartedAt > -1)
|
17
|
+
commentStarted = true;
|
18
|
+
if (commentStartedAt < cursor && commentStartedAt > commentEndedAt)
|
19
|
+
commentStarted = true;
|
20
|
+
|
21
|
+
if (commentStarted) {
|
22
|
+
var commentEndsAt = data.indexOf(commentEndMark, cursor);
|
23
|
+
if (commentEndsAt > -1)
|
24
|
+
return commentEndsAt;
|
25
|
+
|
26
|
+
commentEndsAt = data.indexOf(blockEndMark, cursor);
|
27
|
+
return commentEndsAt > -1 ? commentEndsAt - 1 : data.length;
|
28
|
+
}
|
29
|
+
|
30
|
+
while (true) {
|
31
|
+
if (data[cursor] === undefined)
|
32
|
+
break;
|
33
|
+
if (data[cursor] == matched && data[cursor - 1] != escapeMark)
|
34
|
+
break;
|
35
|
+
|
36
|
+
cursor++;
|
37
|
+
}
|
38
|
+
|
39
|
+
return cursor;
|
40
|
+
};
|
41
|
+
|
42
|
+
QuoteScanner.prototype.each = function(callback) {
|
43
|
+
var data = this.data;
|
44
|
+
var tempData = [];
|
45
|
+
var nextStart = 0;
|
46
|
+
var nextEnd = 0;
|
47
|
+
var cursor = 0;
|
48
|
+
var matchedMark = null;
|
49
|
+
var singleMark = '\'';
|
50
|
+
var doubleMark = '"';
|
51
|
+
var dataLength = data.length;
|
52
|
+
|
53
|
+
for (; nextEnd < data.length;) {
|
54
|
+
var nextStartSingle = data.indexOf(singleMark, nextEnd + 1);
|
55
|
+
var nextStartDouble = data.indexOf(doubleMark, nextEnd + 1);
|
56
|
+
|
57
|
+
if (nextStartSingle == -1)
|
58
|
+
nextStartSingle = dataLength;
|
59
|
+
if (nextStartDouble == -1)
|
60
|
+
nextStartDouble = dataLength;
|
61
|
+
|
62
|
+
if (nextStartSingle < nextStartDouble) {
|
63
|
+
nextStart = nextStartSingle;
|
64
|
+
matchedMark = singleMark;
|
65
|
+
} else {
|
66
|
+
nextStart = nextStartDouble;
|
67
|
+
matchedMark = doubleMark;
|
68
|
+
}
|
69
|
+
|
70
|
+
if (nextStart == -1)
|
71
|
+
break;
|
72
|
+
|
73
|
+
nextEnd = findQuoteEnd(data, matchedMark, nextStart + 1, cursor);
|
74
|
+
if (nextEnd == -1)
|
75
|
+
break;
|
76
|
+
|
77
|
+
var text = data.substring(nextStart, nextEnd + 1);
|
78
|
+
tempData.push(data.substring(cursor, nextStart));
|
79
|
+
if (text.length > 0)
|
80
|
+
callback(text, tempData, nextStart);
|
81
|
+
|
82
|
+
cursor = nextEnd + 1;
|
83
|
+
}
|
84
|
+
|
85
|
+
return tempData.length > 0 ?
|
86
|
+
tempData.join('') + data.substring(cursor, data.length) :
|
87
|
+
data;
|
88
|
+
};
|
89
|
+
|
90
|
+
module.exports = QuoteScanner;
|
91
|
+
})();
|
@@ -0,0 +1,35 @@
|
|
1
|
+
var Splitter = function Splitter (separator) {
|
2
|
+
this.separator = separator;
|
3
|
+
};
|
4
|
+
|
5
|
+
Splitter.prototype.split = function (value) {
|
6
|
+
if (value.indexOf(this.separator) === -1)
|
7
|
+
return [value];
|
8
|
+
|
9
|
+
if (value.indexOf('(') === -1)
|
10
|
+
return value.split(this.separator);
|
11
|
+
|
12
|
+
var level = 0;
|
13
|
+
var cursor = 0;
|
14
|
+
var lastStart = 0;
|
15
|
+
var len = value.length;
|
16
|
+
var tokens = [];
|
17
|
+
|
18
|
+
while (cursor++ < len) {
|
19
|
+
if (value[cursor] == '(') {
|
20
|
+
level++;
|
21
|
+
} else if (value[cursor] == ')') {
|
22
|
+
level--;
|
23
|
+
} else if (value[cursor] == this.separator && level === 0) {
|
24
|
+
tokens.push(value.substring(lastStart, cursor));
|
25
|
+
lastStart = cursor + 1;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
if (lastStart < cursor + 1)
|
30
|
+
tokens.push(value.substring(lastStart));
|
31
|
+
|
32
|
+
return tokens;
|
33
|
+
};
|
34
|
+
|
35
|
+
module.exports = Splitter;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
var EscapeStore = require('./escape-store');
|
2
|
+
|
3
|
+
module.exports = function Urls() {
|
4
|
+
var urls = new EscapeStore('URL');
|
5
|
+
|
6
|
+
return {
|
7
|
+
// Strip urls by replacing them by a special
|
8
|
+
// marker for further restoring. It's done via string scanning
|
9
|
+
// instead of regexps to speed up the process.
|
10
|
+
escape: function(data) {
|
11
|
+
var nextStart = 0;
|
12
|
+
var nextEnd = 0;
|
13
|
+
var cursor = 0;
|
14
|
+
var tempData = [];
|
15
|
+
|
16
|
+
for (; nextEnd < data.length;) {
|
17
|
+
nextStart = data.indexOf('url(', nextEnd);
|
18
|
+
if (nextStart == -1)
|
19
|
+
break;
|
20
|
+
|
21
|
+
nextEnd = data.indexOf(')', nextStart);
|
22
|
+
|
23
|
+
var url = data.substring(nextStart, nextEnd + 1);
|
24
|
+
var placeholder = urls.store(url);
|
25
|
+
tempData.push(data.substring(cursor, nextStart));
|
26
|
+
tempData.push(placeholder);
|
27
|
+
cursor = nextEnd + 1;
|
28
|
+
}
|
29
|
+
|
30
|
+
return tempData.length > 0 ?
|
31
|
+
tempData.join('') + data.substring(cursor, data.length) :
|
32
|
+
data;
|
33
|
+
},
|
34
|
+
|
35
|
+
restore: function(data) {
|
36
|
+
return data.replace(urls.placeholderRegExp, function(placeholder) {
|
37
|
+
return urls.restore(placeholder).replace(/\s/g, '');
|
38
|
+
});
|
39
|
+
}
|
40
|
+
};
|
41
|
+
};
|
@@ -0,0 +1,50 @@
|
|
1
|
+
{
|
2
|
+
"name": "clean-css",
|
3
|
+
"version": "2.2.13",
|
4
|
+
"author": "Jakub Pawlowicz <jakub@goalsmashers.com> (http://twitter.com/GoalSmashers)",
|
5
|
+
"description": "A well-tested CSS minifier",
|
6
|
+
"license": "MIT",
|
7
|
+
"keywords": [
|
8
|
+
"css",
|
9
|
+
"minifier"
|
10
|
+
],
|
11
|
+
"homepage": "https://github.com/GoalSmashers/clean-css",
|
12
|
+
"repository": {
|
13
|
+
"type": "git",
|
14
|
+
"url": "https://github.com/GoalSmashers/clean-css.git"
|
15
|
+
},
|
16
|
+
"bugs": {
|
17
|
+
"url": "https://github.com/GoalSmashers/clean-css/issues"
|
18
|
+
},
|
19
|
+
"bin": {
|
20
|
+
"cleancss": "./bin/cleancss"
|
21
|
+
},
|
22
|
+
"main": "index.js",
|
23
|
+
"files": [
|
24
|
+
"bin",
|
25
|
+
"lib",
|
26
|
+
"History.md",
|
27
|
+
"index.js",
|
28
|
+
"LICENSE"
|
29
|
+
],
|
30
|
+
"scripts": {
|
31
|
+
"browserify": "browserify --standalone CleanCSS index.js | uglifyjs --compress --mangle -o cleancss-browser.js",
|
32
|
+
"bench": "node ./test/bench.js",
|
33
|
+
"check": "jshint ./bin/cleancss .",
|
34
|
+
"prepublish": "jshint .",
|
35
|
+
"test": "vows"
|
36
|
+
},
|
37
|
+
"dependencies": {
|
38
|
+
"commander": "2.3.x"
|
39
|
+
},
|
40
|
+
"devDependencies": {
|
41
|
+
"browserify": "5.x",
|
42
|
+
"jshint": "2.5.x",
|
43
|
+
"nock": "0.28.x",
|
44
|
+
"uglify-js": "2.4.x",
|
45
|
+
"vows": "0.7.x"
|
46
|
+
},
|
47
|
+
"engines": {
|
48
|
+
"node": ">=0.8.0"
|
49
|
+
}
|
50
|
+
}
|